blob: 5347d0eec868ab22fbfb169bc2ed99ba87927392 [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 {
cristy3ed852e2009-09-05 21:47:34 +0000392 XFree(windows->class_hints);
393 windows->class_hints=(XClassHint *) NULL;
394 }
395 if (windows->manager_hints != (XWMHints *) NULL)
396 {
397 XFree(windows->manager_hints);
398 windows->manager_hints=(XWMHints *) NULL;
399 }
400 if (windows->map_info != (XStandardColormap *) NULL)
401 {
402 XFree(windows->map_info);
403 windows->map_info=(XStandardColormap *) NULL;
404 }
405 if (windows->icon_map != (XStandardColormap *) NULL)
406 {
407 XFree(windows->icon_map);
408 windows->icon_map=(XStandardColormap *) NULL;
409 }
410 if (windows->visual_info != (XVisualInfo *) NULL)
411 {
412 XFree(windows->visual_info);
413 windows->visual_info=(XVisualInfo *) NULL;
414 }
415 if (windows->icon_visual != (XVisualInfo *) NULL)
416 {
417 XFree(windows->icon_visual);
418 windows->icon_visual=(XVisualInfo *) NULL;
419 }
420 (void) XSetWindows((XWindows *) NULL);
421}
422
423/*
424%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
425% %
426% %
427% %
428% X A n n o t a t e I m a g e %
429% %
430% %
431% %
432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433%
434% XAnnotateImage() annotates the image with text.
435%
436% The format of the XAnnotateImage method is:
437%
438% MagickBooleanType XAnnotateImage(Display *display,
439% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
440%
441% A description of each parameter follows:
442%
443% o display: Specifies a connection to an X server; returned from
444% XOpenDisplay.
445%
446% o pixel: Specifies a pointer to a XPixelInfo structure.
447%
448% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
449%
450% o image: the image.
451%
452*/
cristybcbda3f2011-09-03 13:01:22 +0000453MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000454 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
455{
cristyc57f6942010-11-12 01:47:39 +0000456 CacheView
457 *annotate_view;
458
cristy3ed852e2009-09-05 21:47:34 +0000459 GC
460 annotate_context;
461
462 ExceptionInfo
463 *exception;
464
465 Image
466 *annotate_image;
467
468 int
469 x,
470 y;
471
472 MagickBooleanType
473 matte;
474
475 Pixmap
476 annotate_pixmap;
477
478 unsigned int
479 depth,
480 height,
481 width;
482
483 Window
484 root_window;
485
486 XGCValues
487 context_values;
488
489 XImage
490 *annotate_ximage;
491
492 /*
493 Initialize annotated image.
494 */
495 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
496 assert(display != (Display *) NULL);
497 assert(pixel != (XPixelInfo *) NULL);
498 assert(annotate_info != (XAnnotateInfo *) NULL);
499 assert(image != (Image *) NULL);
500 /*
501 Initialize annotated pixmap.
502 */
503 root_window=XRootWindow(display,XDefaultScreen(display));
504 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
505 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
506 annotate_info->height,depth);
507 if (annotate_pixmap == (Pixmap) NULL)
508 return(MagickFalse);
509 /*
510 Initialize graphics info.
511 */
512 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000513 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000514 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000515 annotate_context=XCreateGC(display,root_window,(unsigned long)
516 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000517 if (annotate_context == (GC) NULL)
518 return(MagickFalse);
519 /*
520 Draw text to pixmap.
521 */
522 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
523 (int) annotate_info->font_info->ascent,annotate_info->text,
524 (int) strlen(annotate_info->text));
525 (void) XFreeGC(display,annotate_context);
526 /*
527 Initialize annotated X image.
528 */
529 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
530 annotate_info->height,AllPlanes,ZPixmap);
531 if (annotate_ximage == (XImage *) NULL)
532 return(MagickFalse);
533 (void) XFreePixmap(display,annotate_pixmap);
534 /*
535 Initialize annotated image.
536 */
537 annotate_image=AcquireImage((ImageInfo *) NULL);
538 if (annotate_image == (Image *) NULL)
539 return(MagickFalse);
540 annotate_image->columns=annotate_info->width;
541 annotate_image->rows=annotate_info->height;
542 /*
543 Transfer annotated X image to image.
544 */
545 width=(unsigned int) image->columns;
546 height=(unsigned int) image->rows;
547 x=0;
548 y=0;
549 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +0000550 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
551 &annotate_image->background_color,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +0000552 if (annotate_info->stencil == ForegroundStencil)
553 annotate_image->matte=MagickTrue;
554 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +0000555 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000556 for (y=0; y < (int) annotate_image->rows; y++)
557 {
cristyc57f6942010-11-12 01:47:39 +0000558 register int
cristy3ed852e2009-09-05 21:47:34 +0000559 x;
560
cristy4c08aed2011-07-01 19:47:50 +0000561 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000562 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000563
cristyc57f6942010-11-12 01:47:39 +0000564 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
565 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000566 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000567 break;
cristyc57f6942010-11-12 01:47:39 +0000568 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000569 {
cristy4c08aed2011-07-01 19:47:50 +0000570 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000571 if (XGetPixel(annotate_ximage,x,y) == 0)
572 {
573 /*
574 Set this pixel to the background color.
575 */
cristy4c08aed2011-07-01 19:47:50 +0000576 SetPixelRed(annotate_image,ScaleShortToQuantum(
577 pixel->box_color.red),q);
578 SetPixelGreen(annotate_image,ScaleShortToQuantum(
579 pixel->box_color.green),q);
580 SetPixelBlue(annotate_image,ScaleShortToQuantum(
581 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000582 if ((annotate_info->stencil == ForegroundStencil) ||
583 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000584 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000585 }
586 else
587 {
588 /*
589 Set this pixel to the pen color.
590 */
cristy4c08aed2011-07-01 19:47:50 +0000591 SetPixelRed(annotate_image,ScaleShortToQuantum(
592 pixel->pen_color.red),q);
593 SetPixelGreen(annotate_image,ScaleShortToQuantum(
594 pixel->pen_color.green),q);
595 SetPixelBlue(annotate_image,ScaleShortToQuantum(
596 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000597 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000598 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000599 }
cristyed231572011-07-14 02:18:59 +0000600 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000601 }
cristyc57f6942010-11-12 01:47:39 +0000602 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000603 break;
604 }
cristyc57f6942010-11-12 01:47:39 +0000605 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000606 XDestroyImage(annotate_ximage);
607 /*
608 Determine annotate geometry.
609 */
610 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
611 if ((width != (unsigned int) annotate_image->columns) ||
612 (height != (unsigned int) annotate_image->rows))
613 {
614 char
615 image_geometry[MaxTextExtent];
616
617 /*
618 Scale image.
619 */
cristyb51dff52011-05-19 16:55:47 +0000620 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000621 width,height);
622 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
623 }
624 if (annotate_info->degrees != 0.0)
625 {
626 Image
627 *rotate_image;
628
629 int
630 rotations;
631
632 MagickRealType
633 normalized_degrees;
634
635 /*
636 Rotate image.
637 */
638 rotate_image=
639 RotateImage(annotate_image,annotate_info->degrees,&image->exception);
640 if (rotate_image == (Image *) NULL)
641 return(MagickFalse);
642 annotate_image=DestroyImage(annotate_image);
643 annotate_image=rotate_image;
644 /*
645 Annotation is relative to the degree of rotation.
646 */
647 normalized_degrees=annotate_info->degrees;
648 while (normalized_degrees < -45.0)
649 normalized_degrees+=360.0;
650 for (rotations=0; normalized_degrees > 45.0; rotations++)
651 normalized_degrees-=90.0;
652 switch (rotations % 4)
653 {
654 default:
655 case 0:
656 break;
657 case 1:
658 {
659 /*
660 Rotate 90 degrees.
661 */
662 x-=(int) annotate_image->columns/2;
663 y+=(int) annotate_image->columns/2;
664 break;
665 }
666 case 2:
667 {
668 /*
669 Rotate 180 degrees.
670 */
671 x=x-(int) annotate_image->columns;
672 break;
673 }
674 case 3:
675 {
676 /*
677 Rotate 270 degrees.
678 */
679 x=x-(int) annotate_image->columns/2;
680 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
681 break;
682 }
683 }
684 }
685 /*
686 Composite text onto the image.
687 */
688 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
689 matte=image->matte;
690 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristyc57f6942010-11-12 01:47:39 +0000691 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +0000692 image->matte=matte;
693 annotate_image=DestroyImage(annotate_image);
694 return(MagickTrue);
695}
696
697/*
698%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
699% %
700% %
701% %
702% X B e s t F o n t %
703% %
704% %
705% %
706%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707%
708% XBestFont() returns the "best" font. "Best" is defined as a font specified
709% in the X resource database or a font such that the text width displayed
710% with the font does not exceed the specified maximum width.
711%
712% The format of the XBestFont method is:
713%
714% XFontStruct *XBestFont(Display *display,
715% const XResourceInfo *resource_info,const MagickBooleanType text_font)
716%
717% A description of each parameter follows:
718%
719% o font: XBestFont returns a pointer to a XFontStruct structure.
720%
721% o display: Specifies a connection to an X server; returned from
722% XOpenDisplay.
723%
724% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
725%
726% o text_font: True is font should be mono-spaced (typewriter style).
727%
cristy3ed852e2009-09-05 21:47:34 +0000728*/
729
730static char **FontToList(char *font)
731{
732 char
733 **fontlist;
734
735 register char
736 *p,
737 *q;
738
739 register int
740 i;
741
742 unsigned int
743 fonts;
744
745 if (font == (char *) NULL)
746 return((char **) NULL);
747 /*
748 Convert string to an ASCII list.
749 */
750 fonts=1U;
751 for (p=font; *p != '\0'; p++)
752 if ((*p == ':') || (*p == ';') || (*p == ','))
753 fonts++;
754 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
755 if (fontlist == (char **) NULL)
756 {
757 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
758 font);
759 return((char **) NULL);
760 }
761 p=font;
762 for (i=0; i < (int) fonts; i++)
763 {
764 for (q=p; *q != '\0'; q++)
765 if ((*q == ':') || (*q == ';') || (*q == ','))
766 break;
767 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
768 sizeof(*fontlist[i]));
769 if (fontlist[i] == (char *) NULL)
770 {
771 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
772 font);
773 return((char **) NULL);
774 }
775 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
776 p=q+1;
777 }
778 fontlist[i]=(char *) NULL;
779 return(fontlist);
780}
781
cristybcbda3f2011-09-03 13:01:22 +0000782MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000783 const XResourceInfo *resource_info,const MagickBooleanType text_font)
784{
785 static const char
786 *Fonts[]=
787 {
788 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
789 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
790 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
791 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
792 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
793 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
794 "variable",
795 "fixed",
796 (char *) NULL
797 },
798 *TextFonts[]=
799 {
800 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
801 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
802 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
803 "fixed",
804 (char *) NULL
805 };
806
807 char
808 *font_name;
809
810 register const char
811 **p;
812
813 XFontStruct
814 *font_info;
815
816 font_info=(XFontStruct *) NULL;
817 font_name=resource_info->font;
818 if (text_font != MagickFalse)
819 font_name=resource_info->text_font;
820 if ((font_name != (char *) NULL) && (*font_name != '\0'))
821 {
822 char
823 **fontlist;
824
825 register int
826 i;
827
828 /*
829 Load preferred font specified in the X resource database.
830 */
831 fontlist=FontToList(font_name);
832 if (fontlist != (char **) NULL)
833 {
834 for (i=0; fontlist[i] != (char *) NULL; i++)
835 {
836 if (font_info == (XFontStruct *) NULL)
837 font_info=XLoadQueryFont(display,fontlist[i]);
838 fontlist[i]=DestroyString(fontlist[i]);
839 }
840 fontlist=(char **) RelinquishMagickMemory(fontlist);
841 }
842 if (font_info == (XFontStruct *) NULL)
843 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
844 }
845 /*
846 Load fonts from list of fonts until one is found.
847 */
848 p=Fonts;
849 if (text_font != MagickFalse)
850 p=TextFonts;
851 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
852 p++;
853 while (*p != (char *) NULL)
854 {
855 if (font_info != (XFontStruct *) NULL)
856 break;
857 font_info=XLoadQueryFont(display,(char *) *p);
858 p++;
859 }
860 return(font_info);
861}
862
863/*
864%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865% %
866% %
867% %
868% X B e s t I c o n S i z e %
869% %
870% %
871% %
872%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
873%
874% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
875% size that maintains the aspect ratio of the image. If the window manager
876% has preferred icon sizes, one of the preferred sizes is used.
877%
878% The format of the XBestIconSize method is:
879%
880% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
881%
882% A description of each parameter follows:
883%
884% o display: Specifies a connection to an X server; returned from
885% XOpenDisplay.
886%
887% o image: the image.
888%
889*/
cristybcbda3f2011-09-03 13:01:22 +0000890MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000891 Image *image)
892{
893 int
894 i,
895 number_sizes;
896
897 MagickRealType
898 scale_factor;
899
900 unsigned int
901 height,
902 icon_height,
903 icon_width,
904 width;
905
906 Window
907 root_window;
908
909 XIconSize
910 *icon_size,
911 *size_list;
912
913 /*
914 Determine if the window manager has specified preferred icon sizes.
915 */
916 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
917 assert(display != (Display *) NULL);
918 assert(window != (XWindowInfo *) NULL);
919 assert(image != (Image *) NULL);
920 window->width=MaxIconSize;
921 window->height=MaxIconSize;
922 icon_size=(XIconSize *) NULL;
923 number_sizes=0;
924 root_window=XRootWindow(display,window->screen);
925 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
926 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
927 icon_size=size_list;
928 if (icon_size == (XIconSize *) NULL)
929 {
930 /*
931 Window manager does not restrict icon size.
932 */
933 icon_size=XAllocIconSize();
934 if (icon_size == (XIconSize *) NULL)
935 {
936 ThrowXWindowFatalException(ResourceLimitError,
937 "MemoryAllocationFailed",image->filename);
938 return;
939 }
940 icon_size->min_width=1;
941 icon_size->max_width=MaxIconSize;
942 icon_size->min_height=1;
943 icon_size->max_height=MaxIconSize;
944 icon_size->width_inc=1;
945 icon_size->height_inc=1;
946 }
947 /*
948 Determine aspect ratio of image.
949 */
950 width=(unsigned int) image->columns;
951 height=(unsigned int) image->rows;
952 i=0;
953 if (window->crop_geometry)
954 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
955 /*
956 Look for an icon size that maintains the aspect ratio of image.
957 */
958 scale_factor=(MagickRealType) icon_size->max_width/width;
959 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
960 scale_factor=(MagickRealType) icon_size->max_height/height;
961 icon_width=(unsigned int) icon_size->min_width;
962 while ((int) icon_width < icon_size->max_width)
963 {
964 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
965 break;
966 icon_width+=icon_size->width_inc;
967 }
968 icon_height=(unsigned int) icon_size->min_height;
969 while ((int) icon_height < icon_size->max_height)
970 {
971 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
972 break;
973 icon_height+=icon_size->height_inc;
974 }
975 (void) XFree((void *) icon_size);
976 window->width=icon_width;
977 window->height=icon_height;
978}
979
980/*
981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
982% %
983% %
984% %
985% X B e s t P i x e l %
986% %
987% %
988% %
989%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
990%
991% XBestPixel() returns a pixel from an array of pixels that is closest to the
992% requested color. If the color array is NULL, the colors are obtained from
993% the X server.
994%
995% The format of the XBestPixel method is:
996%
997% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
998% unsigned int number_colors,XColor *color)
999%
1000% A description of each parameter follows:
1001%
1002% o pixel: XBestPixel returns the pixel value closest to the requested
1003% color.
1004%
1005% o display: Specifies a connection to an X server; returned from
1006% XOpenDisplay.
1007%
1008% o colormap: Specifies the ID of the X server colormap.
1009%
1010% o colors: Specifies an array of XColor structures.
1011%
1012% o number_colors: Specifies the number of XColor structures in the
1013% color definition array.
1014%
1015% o color: Specifies the desired RGB value to find in the colors array.
1016%
1017*/
cristybcbda3f2011-09-03 13:01:22 +00001018MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001019 XColor *colors,unsigned int number_colors,XColor *color)
1020{
1021 MagickBooleanType
1022 query_server;
1023
cristy4c08aed2011-07-01 19:47:50 +00001024 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001025 pixel;
1026
1027 MagickRealType
1028 min_distance;
1029
1030 register MagickRealType
1031 distance;
1032
1033 register int
1034 i,
1035 j;
1036
1037 Status
1038 status;
1039
1040 /*
1041 Find closest representation for the requested RGB color.
1042 */
1043 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1044 assert(display != (Display *) NULL);
1045 assert(color != (XColor *) NULL);
1046 status=XAllocColor(display,colormap,color);
1047 if (status != False)
1048 return;
1049 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1050 if (query_server != MagickFalse)
1051 {
1052 /*
1053 Read X server colormap.
1054 */
1055 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1056 if (colors == (XColor *) NULL)
1057 {
1058 ThrowXWindowFatalException(ResourceLimitError,
1059 "MemoryAllocationFailed","...");
1060 return;
1061 }
1062 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001063 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001064 if (number_colors > 256)
1065 number_colors=256;
1066 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1067 }
1068 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1069 QuantumRange+1.0);
1070 j=0;
1071 for (i=0; i < (int) number_colors; i++)
1072 {
1073 pixel.red=colors[i].red-(MagickRealType) color->red;
1074 distance=pixel.red*pixel.red;
1075 if (distance > min_distance)
1076 continue;
1077 pixel.green=colors[i].green-(MagickRealType) color->green;
1078 distance+=pixel.green*pixel.green;
1079 if (distance > min_distance)
1080 continue;
1081 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1082 distance+=pixel.blue*pixel.blue;
1083 if (distance > min_distance)
1084 continue;
1085 min_distance=distance;
1086 color->pixel=colors[i].pixel;
1087 j=i;
1088 }
1089 (void) XAllocColor(display,colormap,&colors[j]);
1090 if (query_server != MagickFalse)
1091 colors=(XColor *) RelinquishMagickMemory(colors);
1092}
1093
1094/*
1095%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1096% %
1097% %
1098% %
1099% X B e s t V i s u a l I n f o %
1100% %
1101% %
1102% %
1103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1104%
1105% XBestVisualInfo() returns visual information for a visual that is the "best"
1106% the server supports. "Best" is defined as:
1107%
1108% 1. Restrict the visual list to those supported by the default screen.
1109%
1110% 2. If a visual type is specified, restrict the visual list to those of
1111% that type.
1112%
1113% 3. If a map type is specified, choose the visual that matches the id
1114% specified by the Standard Colormap.
1115%
1116% 4 From the list of visuals, choose one that can display the most
1117% simultaneous colors. If more than one visual can display the same
1118% number of simultaneous colors, one is chosen based on a rank.
1119%
1120% The format of the XBestVisualInfo method is:
1121%
1122% XVisualInfo *XBestVisualInfo(Display *display,
1123% XStandardColormap *map_info,XResourceInfo *resource_info)
1124%
1125% A description of each parameter follows:
1126%
1127% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1128% structure.
1129%
1130% o display: Specifies a connection to an X server; returned from
1131% XOpenDisplay.
1132%
1133% o map_info: If map_type is specified, this structure is initialized
1134% with info from the Standard Colormap.
1135%
1136% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1137%
1138*/
1139
1140static inline int MagickMax(const int x,const int y)
1141{
1142 if (x > y)
1143 return(x);
1144 return(y);
1145}
1146
cristybb503372010-05-27 20:51:26 +00001147static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001148 const unsigned int y)
1149{
1150 if (x < y)
1151 return(x);
1152 return(y);
1153}
1154
cristybcbda3f2011-09-03 13:01:22 +00001155MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001156 XStandardColormap *map_info,XResourceInfo *resource_info)
1157{
1158#define MaxStandardColormaps 7
1159#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1160 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1161 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1162 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1163
1164 char
1165 *map_type,
1166 *visual_type;
1167
cristyc57f6942010-11-12 01:47:39 +00001168 int
1169 visual_mask;
1170
cristy3ed852e2009-09-05 21:47:34 +00001171 register int
1172 i;
1173
cristy8891f9c2010-06-04 23:32:17 +00001174 size_t
1175 one;
1176
cristy3ed852e2009-09-05 21:47:34 +00001177 static int
1178 number_visuals;
1179
1180 static XVisualInfo
1181 visual_template;
1182
1183 XVisualInfo
1184 *visual_info,
1185 *visual_list;
1186
1187 /*
1188 Restrict visual search by screen number.
1189 */
1190 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1191 assert(display != (Display *) NULL);
1192 assert(map_info != (XStandardColormap *) NULL);
1193 assert(resource_info != (XResourceInfo *) NULL);
1194 map_type=resource_info->map_type;
1195 visual_type=resource_info->visual_type;
1196 visual_mask=VisualScreenMask;
1197 visual_template.screen=XDefaultScreen(display);
1198 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001199 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001200 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001201 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001202 visual_mask|=VisualDepthMask;
1203 if (visual_type != (char *) NULL)
1204 {
1205 /*
1206 Restrict visual search by class or visual id.
1207 */
1208 if (LocaleCompare("staticgray",visual_type) == 0)
1209 {
1210 visual_mask|=VisualClassMask;
1211 visual_template.klass=StaticGray;
1212 }
1213 else
1214 if (LocaleCompare("grayscale",visual_type) == 0)
1215 {
1216 visual_mask|=VisualClassMask;
1217 visual_template.klass=GrayScale;
1218 }
1219 else
1220 if (LocaleCompare("staticcolor",visual_type) == 0)
1221 {
1222 visual_mask|=VisualClassMask;
1223 visual_template.klass=StaticColor;
1224 }
1225 else
1226 if (LocaleCompare("pseudocolor",visual_type) == 0)
1227 {
1228 visual_mask|=VisualClassMask;
1229 visual_template.klass=PseudoColor;
1230 }
1231 else
1232 if (LocaleCompare("truecolor",visual_type) == 0)
1233 {
1234 visual_mask|=VisualClassMask;
1235 visual_template.klass=TrueColor;
1236 }
1237 else
1238 if (LocaleCompare("directcolor",visual_type) == 0)
1239 {
1240 visual_mask|=VisualClassMask;
1241 visual_template.klass=DirectColor;
1242 }
1243 else
1244 if (LocaleCompare("default",visual_type) == 0)
1245 {
1246 visual_mask|=VisualIDMask;
1247 visual_template.visualid=XVisualIDFromVisual(
1248 XDefaultVisual(display,XDefaultScreen(display)));
1249 }
1250 else
1251 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1252 {
1253 visual_mask|=VisualIDMask;
1254 visual_template.visualid=
1255 strtol(visual_type,(char **) NULL,0);
1256 }
1257 else
1258 ThrowXWindowFatalException(XServerError,
1259 "UnrecognizedVisualSpecifier",visual_type);
1260 }
1261 /*
1262 Get all visuals that meet our criteria so far.
1263 */
1264 number_visuals=0;
1265 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1266 &number_visuals);
1267 visual_mask=VisualScreenMask | VisualIDMask;
1268 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1269 {
1270 /*
1271 Failed to get visual; try using the default visual.
1272 */
1273 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1274 visual_type);
1275 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1276 XDefaultScreen(display)));
1277 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1278 &number_visuals);
1279 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1280 return((XVisualInfo *) NULL);
1281 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1282 XVisualClassName(visual_list->klass));
1283 }
1284 resource_info->color_recovery=MagickFalse;
1285 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1286 {
1287 Atom
1288 map_property;
1289
1290 char
1291 map_name[MaxTextExtent];
1292
1293 int
1294 j,
1295 number_maps;
1296
1297 Status
1298 status;
1299
1300 Window
1301 root_window;
1302
1303 XStandardColormap
1304 *map_list;
1305
1306 /*
1307 Choose a visual associated with a standard colormap.
1308 */
1309 root_window=XRootWindow(display,XDefaultScreen(display));
1310 status=False;
1311 if (LocaleCompare(map_type,"list") != 0)
1312 {
1313 /*
1314 User specified Standard Colormap.
1315 */
cristyb51dff52011-05-19 16:55:47 +00001316 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001317 "RGB_%s_MAP",map_type);
1318 LocaleUpper(map_name);
1319 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1320 if (map_property != (Atom) NULL)
1321 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1322 map_property);
1323 }
1324 else
1325 {
1326 static const char
1327 *colormap[MaxStandardColormaps]=
1328 {
1329 "_HP_RGB_SMOOTH_MAP_LIST",
1330 "RGB_BEST_MAP",
1331 "RGB_DEFAULT_MAP",
1332 "RGB_GRAY_MAP",
1333 "RGB_RED_MAP",
1334 "RGB_GREEN_MAP",
1335 "RGB_BLUE_MAP",
1336 };
1337
1338 /*
1339 Choose a standard colormap from a list.
1340 */
1341 for (i=0; i < MaxStandardColormaps; i++)
1342 {
1343 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1344 if (map_property == (Atom) NULL)
1345 continue;
1346 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1347 map_property);
1348 if (status != False)
1349 break;
1350 }
1351 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1352 }
1353 if (status == False)
1354 {
1355 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1356 map_type);
1357 return((XVisualInfo *) NULL);
1358 }
1359 /*
1360 Search all Standard Colormaps and visuals for ids that match.
1361 */
1362 *map_info=map_list[0];
1363#if !defined(PRE_R4_ICCCM)
1364 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1365 for (i=0; i < number_maps; i++)
1366 for (j=0; j < number_visuals; j++)
1367 if (map_list[i].visualid ==
1368 XVisualIDFromVisual(visual_list[j].visual))
1369 {
1370 *map_info=map_list[i];
1371 visual_template.visualid=XVisualIDFromVisual(
1372 visual_list[j].visual);
1373 break;
1374 }
1375 if (map_info->visualid != visual_template.visualid)
1376 {
1377 ThrowXWindowFatalException(XServerError,
1378 "UnableToMatchVisualToStandardColormap",map_type);
1379 return((XVisualInfo *) NULL);
1380 }
1381#endif
1382 if (map_info->colormap == (Colormap) NULL)
1383 {
1384 ThrowXWindowFatalException(XServerError,
1385 "StandardColormapIsNotInitialized",map_type);
1386 return((XVisualInfo *) NULL);
1387 }
1388 (void) XFree((void *) map_list);
1389 }
1390 else
1391 {
1392 static const unsigned int
1393 rank[]=
1394 {
1395 StaticGray,
1396 GrayScale,
1397 StaticColor,
1398 DirectColor,
1399 TrueColor,
1400 PseudoColor
1401 };
1402
1403 XVisualInfo
1404 *p;
1405
1406 /*
1407 Pick one visual that displays the most simultaneous colors.
1408 */
1409 visual_info=visual_list;
1410 p=visual_list;
1411 for (i=1; i < number_visuals; i++)
1412 {
1413 p++;
1414 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1415 visual_info=p;
1416 else
1417 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1418 if (rank[p->klass] > rank[visual_info->klass])
1419 visual_info=p;
1420 }
1421 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1422 }
1423 (void) XFree((void *) visual_list);
1424 /*
1425 Retrieve only one visual by its screen & id number.
1426 */
1427 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1428 &number_visuals);
1429 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1430 return((XVisualInfo *) NULL);
1431 return(visual_info);
1432}
1433
1434/*
1435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436% %
1437% %
1438% %
1439% X C h e c k D e f i n e C u r s o r %
1440% %
1441% %
1442% %
1443%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1444%
1445% XCheckDefineCursor() prevents cursor changes on the root window.
1446%
1447% The format of the XXCheckDefineCursor method is:
1448%
1449% XCheckDefineCursor(display,window,cursor)
1450%
1451% A description of each parameter follows:
1452%
1453% o display: Specifies a connection to an X server; returned from
1454% XOpenDisplay.
1455%
1456% o window: the window.
1457%
1458% o cursor: the cursor.
1459%
1460*/
cristybcbda3f2011-09-03 13:01:22 +00001461MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001462 Cursor cursor)
1463{
1464 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1465 assert(display != (Display *) NULL);
1466 if (window == XRootWindow(display,XDefaultScreen(display)))
1467 return(0);
1468 return(XDefineCursor(display,window,cursor));
1469}
1470
1471/*
1472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1473% %
1474% %
1475% %
1476% X C h e c k R e f r e s h W i n d o w s %
1477% %
1478% %
1479% %
1480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1481%
1482% XCheckRefreshWindows() checks the X server for exposure events for a
1483% particular window and updates the areassociated with the exposure event.
1484%
1485% The format of the XCheckRefreshWindows method is:
1486%
1487% void XCheckRefreshWindows(Display *display,XWindows *windows)
1488%
1489% A description of each parameter follows:
1490%
1491% o display: Specifies a connection to an X server; returned from
1492% XOpenDisplay.
1493%
1494% o windows: Specifies a pointer to a XWindows structure.
1495%
1496*/
cristybcbda3f2011-09-03 13:01:22 +00001497MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001498{
1499 Window
1500 id;
1501
1502 XEvent
1503 event;
1504
1505 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1506 assert(display != (Display *) NULL);
1507 assert(windows != (XWindows *) NULL);
1508 XDelay(display,SuspendTime);
1509 id=windows->command.id;
1510 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1511 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1512 id=windows->image.id;
1513 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1514 XRefreshWindow(display,&windows->image,&event);
1515 XDelay(display,SuspendTime << 1);
1516 id=windows->command.id;
1517 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1518 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1519 id=windows->image.id;
1520 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1521 XRefreshWindow(display,&windows->image,&event);
1522}
1523
1524/*
1525%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1526% %
1527% %
1528% %
1529% X C l i e n t M e s s a g e %
1530% %
1531% %
1532% %
1533%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1534%
1535% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1536% initialized with a particular protocol type and atom.
1537%
1538% The format of the XClientMessage function is:
1539%
1540% XClientMessage(display,window,protocol,reason,timestamp)
1541%
1542% A description of each parameter follows:
1543%
1544% o display: Specifies a pointer to the Display structure; returned from
1545% XOpenDisplay.
1546%
1547% o window: Specifies a pointer to a Window structure.
1548%
1549% o protocol: Specifies an atom value.
1550%
1551% o reason: Specifies an atom value which is the reason to send.
1552%
1553% o timestamp: Specifies a value of type Time.
1554%
1555*/
cristybcbda3f2011-09-03 13:01:22 +00001556MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001557 const Atom protocol,const Atom reason,const Time timestamp)
1558{
1559 XClientMessageEvent
1560 client_event;
1561
1562 assert(display != (Display *) NULL);
1563 client_event.type=ClientMessage;
1564 client_event.window=window;
1565 client_event.message_type=protocol;
1566 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001567 client_event.data.l[0]=(long) reason;
1568 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001569 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1570}
1571
1572/*
1573%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1574% %
1575% %
1576% %
1577+ X C l i e n t W i n d o w %
1578% %
1579% %
1580% %
1581%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1582%
1583% XClientWindow() finds a window, at or below the specified window, which has
1584% a WM_STATE property. If such a window is found, it is returned, otherwise
1585% the argument window is returned.
1586%
1587% The format of the XClientWindow function is:
1588%
1589% client_window=XClientWindow(display,target_window)
1590%
1591% A description of each parameter follows:
1592%
1593% o client_window: XClientWindow returns a window, at or below the specified
1594% window, which has a WM_STATE property otherwise the argument
1595% target_window is returned.
1596%
1597% o display: Specifies a pointer to the Display structure; returned from
1598% XOpenDisplay.
1599%
1600% o target_window: Specifies the window to find a WM_STATE property.
1601%
cristy3ed852e2009-09-05 21:47:34 +00001602*/
1603static Window XClientWindow(Display *display,Window target_window)
1604{
1605 Atom
1606 state,
1607 type;
1608
1609 int
1610 format;
1611
1612 Status
1613 status;
1614
1615 unsigned char
1616 *data;
1617
cristyf2faecf2010-05-28 19:19:36 +00001618 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001619 after,
1620 number_items;
1621
1622 Window
1623 client_window;
1624
1625 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1626 assert(display != (Display *) NULL);
1627 state=XInternAtom(display,"WM_STATE",MagickTrue);
1628 if (state == (Atom) NULL)
1629 return(target_window);
1630 type=(Atom) NULL;
1631 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1632 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1633 if ((status == Success) && (type != (Atom) NULL))
1634 return(target_window);
1635 client_window=XWindowByProperty(display,target_window,state);
1636 if (client_window == (Window) NULL)
1637 return(target_window);
1638 return(client_window);
1639}
1640
1641/*
1642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1643% %
1644% %
1645% %
cristyf34a1452009-10-24 22:29:27 +00001646+ X C o m p o n e n t T e r m i n u s %
1647% %
1648% %
1649% %
1650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1651%
1652% XComponentTerminus() destroys the module component.
1653%
1654% The format of the XComponentTerminus method is:
1655%
1656% XComponentTerminus(void)
1657%
1658*/
cristy5ff4eaf2011-09-03 01:38:02 +00001659MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001660{
1661 DestroyXResources();
1662}
1663
1664/*
1665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1666% %
1667% %
1668% %
cristy3ed852e2009-09-05 21:47:34 +00001669% X C o n f i g u r e I m a g e C o l o r m a p %
1670% %
1671% %
1672% %
1673%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1674%
1675% XConfigureImageColormap() creates a new X colormap.
1676%
1677% The format of the XConfigureImageColormap method is:
1678%
1679% void XConfigureImageColormap(Display *display,
1680% XResourceInfo *resource_info,XWindows *windows,Image *image)
1681%
1682% A description of each parameter follows:
1683%
1684% o display: Specifies a connection to an X server; returned from
1685% XOpenDisplay.
1686%
1687% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1688%
1689% o windows: Specifies a pointer to a XWindows structure.
1690%
1691% o image: the image.
1692%
1693*/
cristybcbda3f2011-09-03 13:01:22 +00001694MagickPrivate void XConfigureImageColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001695 XResourceInfo *resource_info,XWindows *windows,Image *image)
1696{
1697 Colormap
1698 colormap;
1699
1700 /*
1701 Make standard colormap.
1702 */
1703 XSetCursorState(display,windows,MagickTrue);
1704 XCheckRefreshWindows(display,windows);
1705 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1706 windows->map_info,windows->pixel_info);
1707 colormap=windows->map_info->colormap;
1708 (void) XSetWindowColormap(display,windows->image.id,colormap);
1709 (void) XSetWindowColormap(display,windows->command.id,colormap);
1710 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1711 if (windows->magnify.mapped != MagickFalse)
1712 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1713 if (windows->pan.mapped != MagickFalse)
1714 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1715 XSetCursorState(display,windows,MagickFalse);
1716 XClientMessage(display,windows->image.id,windows->im_protocols,
1717 windows->im_update_colormap,CurrentTime);
1718}
1719
1720/*
1721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1722% %
1723% %
1724% %
1725% X C o n s t r a i n W i n d o w P o s i t i o n %
1726% %
1727% %
1728% %
1729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1730%
1731% XConstrainWindowPosition() assures a window is positioned within the X
1732% server boundaries.
1733%
1734% The format of the XConstrainWindowPosition method is:
1735%
1736% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1737%
1738% A description of each parameter follows:
1739%
1740% o display: Specifies a pointer to the Display structure; returned from
1741% XOpenDisplay.
1742%
1743% o window_info: Specifies a pointer to a XWindowInfo structure.
1744%
1745*/
cristybcbda3f2011-09-03 13:01:22 +00001746MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001747 XWindowInfo *window_info)
1748{
1749 int
1750 limit;
1751
1752 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1753 assert(display != (Display *) NULL);
1754 assert(window_info != (XWindowInfo *) NULL);
1755 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1756 if (window_info->x < 0)
1757 window_info->x=0;
1758 else
1759 if (window_info->x > (int) limit)
1760 window_info->x=(int) limit;
1761 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1762 if (window_info->y < 0)
1763 window_info->y=0;
1764 else
1765 if (window_info->y > limit)
1766 window_info->y=limit;
1767}
1768
1769/*
1770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1771% %
1772% %
1773% %
1774% X D e l a y %
1775% %
1776% %
1777% %
1778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1779%
1780% XDelay() suspends program execution for the number of milliseconds
1781% specified.
1782%
1783% The format of the Delay method is:
1784%
cristybb503372010-05-27 20:51:26 +00001785% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001786%
1787% A description of each parameter follows:
1788%
1789% o display: Specifies a pointer to the Display structure; returned from
1790% XOpenDisplay.
1791%
1792% o milliseconds: Specifies the number of milliseconds to delay before
1793% returning.
1794%
1795*/
cristybcbda3f2011-09-03 13:01:22 +00001796MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001797{
1798 assert(display != (Display *) NULL);
1799 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001800 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001801}
1802
1803/*
1804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1805% %
1806% %
1807% %
1808% X D e s t r o y R e s o u r c e I n f o %
1809% %
1810% %
1811% %
1812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1813%
1814% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1815% structure.
1816%
1817% The format of the XDestroyResourceInfo method is:
1818%
1819% void XDestroyResourceInfo(XResourceInfo *resource_info)
1820%
1821% A description of each parameter follows:
1822%
1823% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1824%
1825*/
1826MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1827{
1828 if (resource_info->image_geometry != (char *) NULL)
1829 resource_info->image_geometry=(char *)
1830 RelinquishMagickMemory(resource_info->image_geometry);
1831 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1832 resource_info->quantize_info=DestroyQuantizeInfo(
1833 resource_info->quantize_info);
1834 if (resource_info->client_name != (char *) NULL)
1835 resource_info->client_name=(char *)
1836 RelinquishMagickMemory(resource_info->client_name);
1837 if (resource_info->name != (char *) NULL)
1838 resource_info->name=DestroyString(resource_info->name);
1839 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1840}
1841
1842/*
1843%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1844% %
1845% %
1846% %
1847% X D e s t r o y W i n d o w C o l o r s %
1848% %
1849% %
1850% %
1851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1852%
1853% XDestroyWindowColors() frees X11 color resources previously saved on a
1854% window by XRetainWindowColors or programs like xsetroot.
1855%
1856% The format of the XDestroyWindowColors method is:
1857%
1858% void XDestroyWindowColors(Display *display,Window window)
1859%
1860% A description of each parameter follows:
1861%
1862% o display: Specifies a connection to an X server; returned from
1863% XOpenDisplay.
1864%
1865% o window: Specifies a pointer to a Window structure.
1866%
1867*/
cristybcbda3f2011-09-03 13:01:22 +00001868MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001869{
1870 Atom
1871 property,
1872 type;
1873
1874 int
1875 format;
1876
1877 Status
1878 status;
1879
1880 unsigned char
1881 *data;
1882
cristyf2faecf2010-05-28 19:19:36 +00001883 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001884 after,
1885 length;
1886
1887 /*
1888 If there are previous resources on the root window, destroy them.
1889 */
1890 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1891 assert(display != (Display *) NULL);
1892 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1893 if (property == (Atom) NULL)
1894 {
1895 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1896 "_XSETROOT_ID");
1897 return;
1898 }
1899 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1900 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1901 if (status != Success)
1902 return;
1903 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1904 {
1905 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1906 (void) XDeleteProperty(display,window,property);
1907 }
1908 if (type != None)
1909 (void) XFree((void *) data);
1910}
1911
1912/*
1913%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1914% %
1915% %
1916% %
1917% X D i s p l a y I m a g e I n f o %
1918% %
1919% %
1920% %
1921%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1922%
1923% XDisplayImageInfo() displays information about an X image.
1924%
1925% The format of the XDisplayImageInfo method is:
1926%
1927% void XDisplayImageInfo(Display *display,
1928% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1929% Image *image)
1930%
1931% A description of each parameter follows:
1932%
1933% o display: Specifies a connection to an X server; returned from
1934% XOpenDisplay.
1935%
1936% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1937%
1938% o windows: Specifies a pointer to a XWindows structure.
1939%
1940% o undo_image: the undo image.
1941%
1942% o image: the image.
1943%
1944*/
cristybcbda3f2011-09-03 13:01:22 +00001945MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001946 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1947 Image *image)
1948{
1949 char
1950 filename[MaxTextExtent],
1951 *text,
1952 **textlist;
1953
1954 FILE
1955 *file;
1956
1957 int
1958 unique_file;
1959
cristybb503372010-05-27 20:51:26 +00001960 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001961 i;
1962
cristybb503372010-05-27 20:51:26 +00001963 size_t
cristy3ed852e2009-09-05 21:47:34 +00001964 number_pixels;
1965
cristy9d314ff2011-03-09 01:30:28 +00001966 ssize_t
1967 bytes;
1968
1969 unsigned int
1970 levels;
1971
cristy3ed852e2009-09-05 21:47:34 +00001972 /*
1973 Write info about the X server to a file.
1974 */
1975 assert(display != (Display *) NULL);
1976 assert(resource_info != (XResourceInfo *) NULL);
1977 assert(windows != (XWindows *) NULL);
1978 assert(image != (Image *) NULL);
1979 if (image->debug)
1980 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1981 file=(FILE *) NULL;
1982 unique_file=AcquireUniqueFileResource(filename);
1983 if (unique_file != -1)
1984 file=fdopen(unique_file,"w");
1985 if ((unique_file == -1) || (file == (FILE *) NULL))
1986 {
1987 XNoticeWidget(display,windows,"Unable to display image info",filename);
1988 return;
1989 }
1990 if (resource_info->gamma_correct != MagickFalse)
1991 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00001992 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00001993 resource_info->display_gamma);
1994 /*
1995 Write info about the X image to a file.
1996 */
cristyb51dff52011-05-19 16:55:47 +00001997 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00001998 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00001999 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002000 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002001 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002002 windows->visual_info->colormap_size);
2003 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002004 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002005 else
cristyb51dff52011-05-19 16:55:47 +00002006 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002007 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2008 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002009 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002010 (void) FormatLocaleFile(file," crop geometry: %s\n",
2011 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002012 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002013 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002014 else
cristyb51dff52011-05-19 16:55:47 +00002015 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002016 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002017 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002018 else
cristyb51dff52011-05-19 16:55:47 +00002019 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002020 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002021 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002022 else
cristyb51dff52011-05-19 16:55:47 +00002023 (void) FormatLocaleFile(file," shared memory: False\n");
2024 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002025 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002026 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002027 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002028 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002029 /*
2030 Write info about the undo cache to a file.
2031 */
2032 bytes=0;
2033 for (levels=0; undo_image != (Image *) NULL; levels++)
2034 {
2035 number_pixels=undo_image->list->columns*undo_image->list->rows;
2036 bytes+=number_pixels*sizeof(PixelPacket);
2037 undo_image=GetPreviousImageInList(undo_image);
2038 }
cristyb51dff52011-05-19 16:55:47 +00002039 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002040 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2041 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002042 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002043 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002044 /*
2045 Write info about the image to a file.
2046 */
cristya4037272011-08-28 15:11:39 +00002047 (void) IdentifyImage(image,file,MagickTrue,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002048 (void) fclose(file);
2049 text=FileToString(filename,~0,&image->exception);
2050 (void) RelinquishUniqueFileResource(filename);
2051 if (text == (char *) NULL)
2052 {
2053 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2054 "UnableToDisplayImageInfo");
2055 return;
2056 }
2057 textlist=StringToList(text);
2058 if (textlist != (char **) NULL)
2059 {
2060 char
2061 title[MaxTextExtent];
2062
2063 /*
2064 Display information about the image in the Text View widget.
2065 */
2066 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002067 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002068 image->filename);
2069 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2070 (char const **) textlist);
2071 for (i=0; textlist[i] != (char *) NULL; i++)
2072 textlist[i]=DestroyString(textlist[i]);
2073 textlist=(char **) RelinquishMagickMemory(textlist);
2074 }
2075 text=DestroyString(text);
2076}
2077
2078/*
2079%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2080% %
2081% %
2082% %
2083+ X D i t h e r I m a g e %
2084% %
2085% %
2086% %
2087%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2088%
2089% XDitherImage() dithers the reference image as required by the HP Color
2090% Recovery algorithm. The color values are quantized to 3 bits of red and
2091% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2092% standard colormap.
2093%
2094% The format of the XDitherImage method is:
2095%
2096% void XDitherImage(Image *image,XImage *ximage)
2097%
2098% A description of each parameter follows:
2099%
2100% o image: the image.
2101%
2102% o ximage: Specifies a pointer to a XImage structure; returned from
2103% XCreateImage.
2104%
cristy3ed852e2009-09-05 21:47:34 +00002105*/
2106static void XDitherImage(Image *image,XImage *ximage)
2107{
2108 static const short int
2109 dither_red[2][16]=
2110 {
2111 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2112 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2113 },
2114 dither_green[2][16]=
2115 {
2116 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2117 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2118 },
2119 dither_blue[2][16]=
2120 {
2121 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2122 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2123 };
2124
cristyc57f6942010-11-12 01:47:39 +00002125 CacheView
2126 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002127
2128 int
cristyc57f6942010-11-12 01:47:39 +00002129 value,
cristy3ed852e2009-09-05 21:47:34 +00002130 y;
2131
cristyc57f6942010-11-12 01:47:39 +00002132 PixelPacket
2133 color;
cristy3ed852e2009-09-05 21:47:34 +00002134
2135 register char
2136 *q;
2137
cristy4c08aed2011-07-01 19:47:50 +00002138 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002139 *p;
2140
2141 register int
2142 i,
2143 j,
2144 x;
2145
2146 unsigned int
2147 scanline_pad;
2148
cristybb503372010-05-27 20:51:26 +00002149 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002150 pixel;
2151
2152 unsigned char
2153 *blue_map[2][16],
2154 *green_map[2][16],
2155 *red_map[2][16];
2156
2157 /*
2158 Allocate and initialize dither maps.
2159 */
2160 for (i=0; i < 2; i++)
2161 for (j=0; j < 16; j++)
2162 {
2163 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2164 sizeof(*red_map));
2165 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2166 sizeof(*green_map));
2167 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2168 sizeof(*blue_map));
2169 if ((red_map[i][j] == (unsigned char *) NULL) ||
2170 (green_map[i][j] == (unsigned char *) NULL) ||
2171 (blue_map[i][j] == (unsigned char *) NULL))
2172 {
2173 ThrowXWindowFatalException(ResourceLimitError,
2174 "MemoryAllocationFailed",image->filename);
2175 return;
2176 }
2177 }
2178 /*
2179 Initialize dither tables.
2180 */
2181 for (i=0; i < 2; i++)
2182 for (j=0; j < 16; j++)
2183 for (x=0; x < 256; x++)
2184 {
2185 value=x-16;
2186 if (x < 48)
2187 value=x/2+8;
2188 value+=dither_red[i][j];
2189 red_map[i][j][x]=(unsigned char)
2190 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2191 value=x-16;
2192 if (x < 48)
2193 value=x/2+8;
2194 value+=dither_green[i][j];
2195 green_map[i][j][x]=(unsigned char)
2196 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2197 value=x-32;
2198 if (x < 112)
2199 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002200 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002201 blue_map[i][j][x]=(unsigned char)
2202 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2203 }
2204 /*
2205 Dither image.
2206 */
2207 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002208 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002209 i=0;
2210 j=0;
2211 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002212 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002213 for (y=0; y < (int) image->rows; y++)
2214 {
cristyc57f6942010-11-12 01:47:39 +00002215 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2216 &image->exception);
cristy4c08aed2011-07-01 19:47:50 +00002217 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002218 break;
2219 for (x=0; x < (int) image->columns; x++)
2220 {
cristyce70c172010-01-07 17:15:30 +00002221 color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002222 ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002223 color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002224 ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002225 color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002226 ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002227 pixel=(size_t) (((size_t) color.red & 0xe0) |
2228 (((size_t) color.green & 0xe0) >> 3) |
2229 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002230 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002231 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002232 j++;
2233 if (j == 16)
2234 j=0;
2235 }
2236 q+=scanline_pad;
2237 i++;
2238 if (i == 2)
2239 i=0;
2240 }
cristyc57f6942010-11-12 01:47:39 +00002241 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002242 /*
2243 Free allocated memory.
2244 */
2245 for (i=0; i < 2; i++)
2246 for (j=0; j < 16; j++)
2247 {
2248 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2249 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2250 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2251 }
2252}
2253
2254/*
2255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2256% %
2257% %
2258% %
2259% X D r a w I m a g e %
2260% %
2261% %
2262% %
2263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2264%
2265% XDrawImage() draws a line on the image.
2266%
2267% The format of the XDrawImage method is:
2268%
2269% MagickBooleanType XDrawImage(display,pixel,draw_info,image)
2270%
2271% A description of each parameter follows:
2272%
2273% o display: Specifies a connection to an X server; returned from
2274% XOpenDisplay.
2275%
2276% o pixel: Specifies a pointer to a XPixelInfo structure.
2277%
2278% o draw_info: Specifies a pointer to a XDrawInfo structure.
2279%
2280% o image: the image.
2281%
2282*/
cristybcbda3f2011-09-03 13:01:22 +00002283MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002284 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
2285{
cristyc57f6942010-11-12 01:47:39 +00002286 CacheView
2287 *draw_view;
2288
cristy3ed852e2009-09-05 21:47:34 +00002289 ExceptionInfo
2290 *exception;
2291
2292 GC
2293 draw_context;
2294
2295 Image
2296 *draw_image;
2297
2298 int
2299 x,
2300 y;
2301
2302 MagickBooleanType
2303 matte;
2304
2305 Pixmap
2306 draw_pixmap;
2307
2308 unsigned int
2309 depth,
2310 height,
2311 width;
2312
2313 Window
2314 root_window;
2315
2316 XGCValues
2317 context_values;
2318
2319 XImage
2320 *draw_ximage;
2321
2322 /*
2323 Initialize drawd image.
2324 */
2325 assert(display != (Display *) NULL);
2326 assert(pixel != (XPixelInfo *) NULL);
2327 assert(draw_info != (XDrawInfo *) NULL);
2328 assert(image != (Image *) NULL);
2329 if (image->debug != MagickFalse)
2330 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2331 /*
2332 Initialize drawd pixmap.
2333 */
2334 root_window=XRootWindow(display,XDefaultScreen(display));
2335 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2336 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2337 draw_info->height,depth);
2338 if (draw_pixmap == (Pixmap) NULL)
2339 return(MagickFalse);
2340 /*
2341 Initialize graphics info.
2342 */
cristybb503372010-05-27 20:51:26 +00002343 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002344 context_values.foreground=0;
2345 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002346 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002347 (GCBackground | GCForeground | GCLineWidth),&context_values);
2348 if (draw_context == (GC) NULL)
2349 return(MagickFalse);
2350 /*
2351 Clear pixmap.
2352 */
2353 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2354 draw_info->height);
2355 /*
2356 Draw line to pixmap.
2357 */
2358 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002359 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002360 if (draw_info->stipple != (Pixmap) NULL)
2361 {
2362 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2363 (void) XSetStipple(display,draw_context,draw_info->stipple);
2364 }
cristy3ed852e2009-09-05 21:47:34 +00002365 switch (draw_info->element)
2366 {
2367 case PointElement:
2368 default:
2369 {
2370 (void) XDrawLines(display,draw_pixmap,draw_context,
2371 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2372 CoordModeOrigin);
2373 break;
2374 }
2375 case LineElement:
2376 {
2377 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2378 draw_info->line_info.y1,draw_info->line_info.x2,
2379 draw_info->line_info.y2);
2380 break;
2381 }
2382 case RectangleElement:
2383 {
2384 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2385 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2386 (unsigned int) draw_info->rectangle_info.width,
2387 (unsigned int) draw_info->rectangle_info.height);
2388 break;
2389 }
2390 case FillRectangleElement:
2391 {
2392 (void) XFillRectangle(display,draw_pixmap,draw_context,
2393 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2394 (unsigned int) draw_info->rectangle_info.width,
2395 (unsigned int) draw_info->rectangle_info.height);
2396 break;
2397 }
2398 case CircleElement:
2399 case EllipseElement:
2400 {
2401 (void) XDrawArc(display,draw_pixmap,draw_context,
2402 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2403 (unsigned int) draw_info->rectangle_info.width,
2404 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2405 break;
2406 }
2407 case FillCircleElement:
2408 case FillEllipseElement:
2409 {
2410 (void) XFillArc(display,draw_pixmap,draw_context,
2411 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2412 (unsigned int) draw_info->rectangle_info.width,
2413 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2414 break;
2415 }
2416 case PolygonElement:
2417 {
2418 XPoint
2419 *coordinate_info;
2420
2421 coordinate_info=draw_info->coordinate_info;
2422 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2423 (int) draw_info->number_coordinates,CoordModeOrigin);
2424 (void) XDrawLine(display,draw_pixmap,draw_context,
2425 coordinate_info[draw_info->number_coordinates-1].x,
2426 coordinate_info[draw_info->number_coordinates-1].y,
2427 coordinate_info[0].x,coordinate_info[0].y);
2428 break;
2429 }
2430 case FillPolygonElement:
2431 {
2432 (void) XFillPolygon(display,draw_pixmap,draw_context,
2433 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2434 CoordModeOrigin);
2435 break;
2436 }
2437 }
2438 (void) XFreeGC(display,draw_context);
2439 /*
2440 Initialize X image.
2441 */
2442 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2443 draw_info->height,AllPlanes,ZPixmap);
2444 if (draw_ximage == (XImage *) NULL)
2445 return(MagickFalse);
2446 (void) XFreePixmap(display,draw_pixmap);
2447 /*
2448 Initialize draw image.
2449 */
2450 draw_image=AcquireImage((ImageInfo *) NULL);
2451 if (draw_image == (Image *) NULL)
2452 return(MagickFalse);
2453 draw_image->columns=draw_info->width;
2454 draw_image->rows=draw_info->height;
2455 /*
2456 Transfer drawn X image to image.
2457 */
2458 width=(unsigned int) image->columns;
2459 height=(unsigned int) image->rows;
2460 x=0;
2461 y=0;
2462 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +00002463 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
2464 &draw_image->background_color,&image->exception);
cristy574cc262011-08-05 01:23:58 +00002465 if (SetImageStorageClass(draw_image,DirectClass,&image->exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002466 return(MagickFalse);
2467 draw_image->matte=MagickTrue;
2468 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +00002469 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002470 for (y=0; y < (int) draw_image->rows; y++)
2471 {
cristyc57f6942010-11-12 01:47:39 +00002472 register int
cristy3ed852e2009-09-05 21:47:34 +00002473 x;
2474
cristy4c08aed2011-07-01 19:47:50 +00002475 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002476 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002477
cristyc57f6942010-11-12 01:47:39 +00002478 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2479 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002480 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002481 break;
cristyc57f6942010-11-12 01:47:39 +00002482 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002483 {
2484 if (XGetPixel(draw_ximage,x,y) == 0)
2485 {
2486 /*
2487 Set this pixel to the background color.
2488 */
cristy4c08aed2011-07-01 19:47:50 +00002489 SetPixelPacket(draw_image,&draw_image->background_color,q);
2490 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2491 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002492 }
2493 else
2494 {
2495 /*
2496 Set this pixel to the pen color.
2497 */
cristy4c08aed2011-07-01 19:47:50 +00002498 SetPixelRed(draw_image,ScaleShortToQuantum(
2499 pixel->pen_color.red),q);
2500 SetPixelGreen(draw_image,ScaleShortToQuantum(
2501 pixel->pen_color.green),q);
2502 SetPixelBlue(draw_image,ScaleShortToQuantum(
2503 pixel->pen_color.blue),q);
2504 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2505 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002506 }
cristyed231572011-07-14 02:18:59 +00002507 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002508 }
cristyc57f6942010-11-12 01:47:39 +00002509 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002510 break;
2511 }
cristyc57f6942010-11-12 01:47:39 +00002512 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002513 XDestroyImage(draw_ximage);
2514 /*
2515 Determine draw geometry.
2516 */
2517 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2518 if ((width != (unsigned int) draw_image->columns) ||
2519 (height != (unsigned int) draw_image->rows))
2520 {
2521 char
2522 image_geometry[MaxTextExtent];
2523
2524 /*
2525 Scale image.
2526 */
cristyb51dff52011-05-19 16:55:47 +00002527 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002528 width,height);
2529 (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
2530 }
2531 if (draw_info->degrees != 0.0)
2532 {
2533 Image
2534 *rotate_image;
2535
2536 int
2537 rotations;
2538
2539 MagickRealType
2540 normalized_degrees;
2541
2542 /*
2543 Rotate image.
2544 */
2545 rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
2546 if (rotate_image == (Image *) NULL)
2547 return(MagickFalse);
2548 draw_image=DestroyImage(draw_image);
2549 draw_image=rotate_image;
2550 /*
2551 Annotation is relative to the degree of rotation.
2552 */
2553 normalized_degrees=draw_info->degrees;
2554 while (normalized_degrees < -45.0)
2555 normalized_degrees+=360.0;
2556 for (rotations=0; normalized_degrees > 45.0; rotations++)
2557 normalized_degrees-=90.0;
2558 switch (rotations % 4)
2559 {
2560 default:
2561 case 0:
2562 break;
2563 case 1:
2564 {
2565 /*
2566 Rotate 90 degrees.
2567 */
2568 x=x-(int) draw_image->columns/2;
2569 y=y+(int) draw_image->columns/2;
2570 break;
2571 }
2572 case 2:
2573 {
2574 /*
2575 Rotate 180 degrees.
2576 */
2577 x=x-(int) draw_image->columns;
2578 break;
2579 }
2580 case 3:
2581 {
2582 /*
2583 Rotate 270 degrees.
2584 */
2585 x=x-(int) draw_image->columns/2;
2586 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2587 break;
2588 }
2589 }
2590 }
2591 /*
2592 Composite text onto the image.
2593 */
cristyc57f6942010-11-12 01:47:39 +00002594 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002595 for (y=0; y < (int) draw_image->rows; y++)
2596 {
cristyc57f6942010-11-12 01:47:39 +00002597 register int
cristy3ed852e2009-09-05 21:47:34 +00002598 x;
2599
cristy4c08aed2011-07-01 19:47:50 +00002600 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002601 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002602
cristyc57f6942010-11-12 01:47:39 +00002603 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2604 exception);
cristyacd2ed22011-08-30 01:44:23 +00002605 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002606 break;
cristyc57f6942010-11-12 01:47:39 +00002607 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002608 {
cristy4c08aed2011-07-01 19:47:50 +00002609 if (GetPixelAlpha(image,q) != TransparentAlpha)
2610 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002611 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002612 }
cristyc57f6942010-11-12 01:47:39 +00002613 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002614 break;
2615 }
cristyc57f6942010-11-12 01:47:39 +00002616 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002617 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2618 if (draw_info->stencil == TransparentStencil)
cristyc57f6942010-11-12 01:47:39 +00002619 (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,(ssize_t) x,
2620 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002621 else
2622 {
2623 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002624 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
2625 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002626 image->matte=matte;
2627 }
2628 draw_image=DestroyImage(draw_image);
2629 return(MagickTrue);
2630}
2631
2632/*
2633%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2634% %
2635% %
2636% %
2637% X E r r o r %
2638% %
2639% %
2640% %
2641%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2642%
2643% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2644% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002645% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2646% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002647%
2648% The format of the XError function is:
2649%
cristybcbda3f2011-09-03 13:01:22 +00002650% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002651%
2652% A description of each parameter follows:
2653%
2654% o display: Specifies a pointer to the Display structure; returned from
2655% XOpenDisplay.
2656%
2657% o error: Specifies the error event.
2658%
2659*/
2660
2661#if defined(__cplusplus) || defined(c_plusplus)
2662extern "C" {
2663#endif
2664
2665MagickExport int XError(Display *display,XErrorEvent *error)
2666{
2667 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2668 assert(display != (Display *) NULL);
2669 assert(error != (XErrorEvent *) NULL);
2670 xerror_alert=MagickTrue;
2671 switch (error->request_code)
2672 {
2673 case X_GetGeometry:
2674 {
2675 if ((int) error->error_code == BadDrawable)
2676 return(MagickFalse);
2677 break;
2678 }
2679 case X_GetWindowAttributes:
2680 case X_QueryTree:
2681 {
2682 if ((int) error->error_code == BadWindow)
2683 return(MagickFalse);
2684 break;
2685 }
2686 case X_QueryColors:
2687 {
2688 if ((int) error->error_code == BadValue)
2689 return(MagickFalse);
2690 break;
2691 }
2692 }
2693 return(MagickTrue);
2694}
2695
2696#if defined(__cplusplus) || defined(c_plusplus)
2697}
2698#endif
2699
2700/*
2701%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2702% %
2703% %
2704% %
2705% X F r e e R e s o u r c e s %
2706% %
2707% %
2708% %
2709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2710%
2711% XFreeResources() frees X11 resources.
2712%
2713% The format of the XFreeResources method is:
2714%
2715% void XFreeResources(Display *display,XVisualInfo *visual_info,
2716% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2717% XResourceInfo *resource_info,XWindowInfo *window_info)
2718% resource_info,window_info)
2719%
2720% A description of each parameter follows:
2721%
2722% o display: Specifies a connection to an X server; returned from
2723% XOpenDisplay.
2724%
2725% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2726% returned from XGetVisualInfo.
2727%
2728% o map_info: If map_type is specified, this structure is initialized
2729% with info from the Standard Colormap.
2730%
2731% o pixel: Specifies a pointer to a XPixelInfo structure.
2732%
2733% o font_info: Specifies a pointer to a XFontStruct structure.
2734%
2735% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2736%
2737% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2738%
2739*/
cristybcbda3f2011-09-03 13:01:22 +00002740MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002741 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2742 XResourceInfo *resource_info,XWindowInfo *window_info)
2743{
2744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2745 assert(display != (Display *) NULL);
2746 assert(resource_info != (XResourceInfo *) NULL);
2747 if (window_info != (XWindowInfo *) NULL)
2748 {
2749 /*
2750 Free X image.
2751 */
2752 if (window_info->ximage != (XImage *) NULL)
2753 XDestroyImage(window_info->ximage);
2754 if (window_info->id != (Window) NULL)
2755 {
2756 /*
2757 Free destroy window and free cursors.
2758 */
2759 if (window_info->id != XRootWindow(display,visual_info->screen))
2760 (void) XDestroyWindow(display,window_info->id);
2761 if (window_info->annotate_context != (GC) NULL)
2762 (void) XFreeGC(display,window_info->annotate_context);
2763 if (window_info->highlight_context != (GC) NULL)
2764 (void) XFreeGC(display,window_info->highlight_context);
2765 if (window_info->widget_context != (GC) NULL)
2766 (void) XFreeGC(display,window_info->widget_context);
2767 if (window_info->cursor != (Cursor) NULL)
2768 (void) XFreeCursor(display,window_info->cursor);
2769 window_info->cursor=(Cursor) NULL;
2770 if (window_info->busy_cursor != (Cursor) NULL)
2771 (void) XFreeCursor(display,window_info->busy_cursor);
2772 window_info->busy_cursor=(Cursor) NULL;
2773 }
2774 }
2775 /*
2776 Free font.
2777 */
2778 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002779 {
2780 (void) XFreeFont(display,font_info);
2781 font_info=(XFontStruct *) NULL;
2782 }
cristy3ed852e2009-09-05 21:47:34 +00002783 if (map_info != (XStandardColormap *) NULL)
2784 {
2785 /*
2786 Free X Standard Colormap.
2787 */
2788 if (resource_info->map_type == (char *) NULL)
2789 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2790 (void) XFree((void *) map_info);
2791 }
2792 /*
2793 Free X visual info.
2794 */
2795 if (visual_info != (XVisualInfo *) NULL)
2796 (void) XFree((void *) visual_info);
2797 if (resource_info->close_server != MagickFalse)
2798 (void) XCloseDisplay(display);
2799}
2800
2801/*
2802%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2803% %
2804% %
2805% %
2806% X F r e e S t a n d a r d C o l o r m a p %
2807% %
2808% %
2809% %
2810%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2811%
2812% XFreeStandardColormap() frees an X11 colormap.
2813%
2814% The format of the XFreeStandardColormap method is:
2815%
2816% void XFreeStandardColormap(Display *display,
2817% const XVisualInfo *visual_info,XStandardColormap *map_info,
2818% XPixelInfo *pixel)
2819%
2820% A description of each parameter follows:
2821%
2822% o display: Specifies a connection to an X server; returned from
2823% XOpenDisplay.
2824%
2825% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2826% returned from XGetVisualInfo.
2827%
2828% o map_info: If map_type is specified, this structure is initialized
2829% with info from the Standard Colormap.
2830%
2831% o pixel: Specifies a pointer to a XPixelInfo structure.
2832%
2833*/
cristybcbda3f2011-09-03 13:01:22 +00002834MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002835 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2836{
2837 /*
2838 Free colormap.
2839 */
2840 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2841 assert(display != (Display *) NULL);
2842 assert(visual_info != (XVisualInfo *) NULL);
2843 assert(map_info != (XStandardColormap *) NULL);
2844 (void) XFlush(display);
2845 if (map_info->colormap != (Colormap) NULL)
2846 {
2847 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2848 (void) XFreeColormap(display,map_info->colormap);
2849 else
2850 if (pixel != (XPixelInfo *) NULL)
2851 if ((visual_info->klass != TrueColor) &&
2852 (visual_info->klass != DirectColor))
2853 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2854 (int) pixel->colors,0);
2855 }
2856 map_info->colormap=(Colormap) NULL;
2857 if (pixel != (XPixelInfo *) NULL)
2858 {
cristyf2faecf2010-05-28 19:19:36 +00002859 if (pixel->pixels != (unsigned long *) NULL)
2860 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2861 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002862 }
2863}
2864
2865/*
2866%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2867% %
2868% %
2869% %
2870% X G e t A n n o t a t e I n f o %
2871% %
2872% %
2873% %
2874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2875%
2876% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2877%
2878% The format of the XGetAnnotateInfo method is:
2879%
2880% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2881%
2882% A description of each parameter follows:
2883%
2884% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2885%
2886*/
cristybcbda3f2011-09-03 13:01:22 +00002887MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002888{
2889 /*
2890 Initialize annotate structure.
2891 */
2892 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2893 assert(annotate_info != (XAnnotateInfo *) NULL);
2894 annotate_info->x=0;
2895 annotate_info->y=0;
2896 annotate_info->width=0;
2897 annotate_info->height=0;
2898 annotate_info->stencil=ForegroundStencil;
2899 annotate_info->degrees=0.0;
2900 annotate_info->font_info=(XFontStruct *) NULL;
2901 annotate_info->text=(char *) NULL;
2902 *annotate_info->geometry='\0';
2903 annotate_info->previous=(XAnnotateInfo *) NULL;
2904 annotate_info->next=(XAnnotateInfo *) NULL;
2905 (void) XSupportsLocale();
2906 (void) XSetLocaleModifiers("");
2907}
2908
2909/*
2910%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2911% %
2912% %
2913% %
2914% X G e t M a p I n f o %
2915% %
2916% %
2917% %
2918%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2919%
2920% XGetMapInfo() initializes the XStandardColormap structure.
2921%
2922% The format of the XStandardColormap method is:
2923%
2924% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2925% XStandardColormap *map_info)
2926%
2927% A description of each parameter follows:
2928%
2929% o colormap: Specifies the ID of the X server colormap.
2930%
2931% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2932% returned from XGetVisualInfo.
2933%
2934% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2935%
2936*/
cristybcbda3f2011-09-03 13:01:22 +00002937MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002938 const Colormap colormap,XStandardColormap *map_info)
2939{
2940 /*
2941 Initialize map info.
2942 */
2943 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2944 assert(visual_info != (XVisualInfo *) NULL);
2945 assert(map_info != (XStandardColormap *) NULL);
2946 map_info->colormap=colormap;
2947 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002948 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002949 if (map_info->red_max != 0)
2950 while ((map_info->red_max & 0x01) == 0)
2951 {
2952 map_info->red_max>>=1;
2953 map_info->red_mult<<=1;
2954 }
2955 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002956 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002957 if (map_info->green_max != 0)
2958 while ((map_info->green_max & 0x01) == 0)
2959 {
2960 map_info->green_max>>=1;
2961 map_info->green_mult<<=1;
2962 }
2963 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002964 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002965 if (map_info->blue_max != 0)
2966 while ((map_info->blue_max & 0x01) == 0)
2967 {
2968 map_info->blue_max>>=1;
2969 map_info->blue_mult<<=1;
2970 }
2971 map_info->base_pixel=0;
2972}
2973
2974/*
2975%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2976% %
2977% %
2978% %
2979% X G e t P i x e l I n f o %
2980% %
2981% %
2982% %
2983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2984%
cristy4c08aed2011-07-01 19:47:50 +00002985% XGetPixelInfo() initializes the PixelPacket structure.
cristy3ed852e2009-09-05 21:47:34 +00002986%
cristy4c08aed2011-07-01 19:47:50 +00002987% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00002988%
cristy4c08aed2011-07-01 19:47:50 +00002989% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002990% const XStandardColormap *map_info,const XResourceInfo *resource_info,
2991% Image *image,XPixelInfo *pixel)
2992% pixel)
2993%
2994% A description of each parameter follows:
2995%
2996% o display: Specifies a connection to an X server; returned from
2997% XOpenDisplay.
2998%
2999% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3000% returned from XGetVisualInfo.
3001%
3002% o map_info: If map_type is specified, this structure is initialized
3003% with info from the Standard Colormap.
3004%
3005% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3006%
3007% o image: the image.
3008%
3009% o pixel: Specifies a pointer to a XPixelInfo structure.
3010%
3011*/
cristybcbda3f2011-09-03 13:01:22 +00003012MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003013 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3014 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3015{
3016 static const char
3017 *PenColors[MaxNumberPens]=
3018 {
3019 "#000000000000", /* black */
3020 "#00000000ffff", /* blue */
3021 "#0000ffffffff", /* cyan */
3022 "#0000ffff0000", /* green */
3023 "#bdbdbdbdbdbd", /* gray */
3024 "#ffff00000000", /* red */
3025 "#ffff0000ffff", /* magenta */
3026 "#ffffffff0000", /* yellow */
3027 "#ffffffffffff", /* white */
3028 "#bdbdbdbdbdbd", /* gray */
3029 "#bdbdbdbdbdbd" /* gray */
3030 };
3031
3032 Colormap
3033 colormap;
3034
cristybb503372010-05-27 20:51:26 +00003035 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003036 i;
3037
3038 Status
3039 status;
3040
3041 unsigned int
3042 packets;
3043
3044 /*
3045 Initialize pixel info.
3046 */
3047 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3048 assert(display != (Display *) NULL);
3049 assert(visual_info != (XVisualInfo *) NULL);
3050 assert(map_info != (XStandardColormap *) NULL);
3051 assert(resource_info != (XResourceInfo *) NULL);
3052 assert(pixel != (XPixelInfo *) NULL);
3053 pixel->colors=0;
3054 if (image != (Image *) NULL)
3055 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003056 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003057 packets=(unsigned int)
3058 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003059 if (pixel->pixels != (unsigned long *) NULL)
3060 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3061 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003062 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003063 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003064 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3065 image->filename);
3066 /*
3067 Set foreground color.
3068 */
3069 colormap=map_info->colormap;
3070 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3071 &pixel->foreground_color);
3072 status=XParseColor(display,colormap,resource_info->foreground_color,
3073 &pixel->foreground_color);
3074 if (status == False)
3075 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3076 resource_info->foreground_color);
3077 pixel->foreground_color.pixel=
3078 XStandardPixel(map_info,&pixel->foreground_color);
3079 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3080 /*
3081 Set background color.
3082 */
3083 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3084 status=XParseColor(display,colormap,resource_info->background_color,
3085 &pixel->background_color);
3086 if (status == False)
3087 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3088 resource_info->background_color);
3089 pixel->background_color.pixel=
3090 XStandardPixel(map_info,&pixel->background_color);
3091 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3092 /*
3093 Set border color.
3094 */
3095 (void) XParseColor(display,colormap,(char *) BorderColor,
3096 &pixel->border_color);
3097 status=XParseColor(display,colormap,resource_info->border_color,
3098 &pixel->border_color);
3099 if (status == False)
3100 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3101 resource_info->border_color);
3102 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3103 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3104 /*
3105 Set matte color.
3106 */
3107 pixel->matte_color=pixel->background_color;
3108 if (resource_info->matte_color != (char *) NULL)
3109 {
3110 /*
3111 Matte color is specified as a X resource or command line argument.
3112 */
3113 status=XParseColor(display,colormap,resource_info->matte_color,
3114 &pixel->matte_color);
3115 if (status == False)
3116 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3117 resource_info->matte_color);
3118 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3119 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3120 }
3121 /*
3122 Set highlight color.
3123 */
3124 pixel->highlight_color.red=(unsigned short) ((
3125 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3126 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3127 pixel->highlight_color.green=(unsigned short) ((
3128 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3129 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3130 pixel->highlight_color.blue=(unsigned short) ((
3131 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3132 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3133 pixel->highlight_color.pixel=
3134 XStandardPixel(map_info,&pixel->highlight_color);
3135 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3136 /*
3137 Set shadow color.
3138 */
3139 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3140 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3141 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3142 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3143 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3144 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3145 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3146 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3147 /*
3148 Set depth color.
3149 */
3150 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3151 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3152 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3153 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3154 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3155 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3156 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3157 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3158 /*
3159 Set trough color.
3160 */
3161 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3162 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3163 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3164 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3165 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3166 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3167 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3168 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3169 /*
3170 Set pen color.
3171 */
3172 for (i=0; i < MaxNumberPens; i++)
3173 {
3174 (void) XParseColor(display,colormap,(char *) PenColors[i],
3175 &pixel->pen_colors[i]);
3176 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3177 &pixel->pen_colors[i]);
3178 if (status == False)
3179 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3180 resource_info->pen_colors[i]);
3181 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3182 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3183 }
3184 pixel->box_color=pixel->background_color;
3185 pixel->pen_color=pixel->foreground_color;
3186 pixel->box_index=0;
3187 pixel->pen_index=1;
3188 if (image != (Image *) NULL)
3189 {
3190 if ((resource_info->gamma_correct != MagickFalse) &&
3191 (image->gamma != 0.0))
3192 {
3193 GeometryInfo
3194 geometry_info;
3195
3196 MagickStatusType
3197 flags;
3198
3199 /*
3200 Initialize map relative to display and image gamma.
3201 */
3202 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3203 red_gamma=geometry_info.rho;
3204 green_gamma=geometry_info.sigma;
3205 if ((flags & SigmaValue) == 0)
3206 green_gamma=red_gamma;
3207 blue_gamma=geometry_info.xi;
3208 if ((flags & XiValue) == 0)
3209 blue_gamma=red_gamma;
3210 red_gamma*=image->gamma;
3211 green_gamma*=image->gamma;
3212 blue_gamma*=image->gamma;
3213 }
3214 if (image->storage_class == PseudoClass)
3215 {
3216 /*
3217 Initialize pixel array for images of type PseudoClass.
3218 */
cristybb503372010-05-27 20:51:26 +00003219 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003220 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003221 for (i=0; i < MaxNumberPens; i++)
3222 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3223 pixel->colors+=MaxNumberPens;
3224 }
3225 }
3226}
3227
3228/*
3229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3230% %
3231% %
3232% %
3233% X G e t R e s o u r c e C l a s s %
3234% %
3235% %
3236% %
3237%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3238%
3239% XGetResourceClass() queries the X server for the specified resource name or
3240% class. If the resource name or class is not defined in the database, the
3241% supplied default value is returned.
3242%
3243% The format of the XGetResourceClass method is:
3244%
3245% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3246% const char *keyword,char *resource_default)
3247%
3248% A description of each parameter follows:
3249%
3250% o database: Specifies a resource database; returned from
3251% XrmGetStringDatabase.
3252%
3253% o client_name: Specifies the application name used to retrieve resource
3254% info from the X server database.
3255%
3256% o keyword: Specifies the keyword of the value being retrieved.
3257%
3258% o resource_default: Specifies the default value to return if the query
3259% fails to find the specified keyword/class.
3260%
3261*/
3262MagickExport char *XGetResourceClass(XrmDatabase database,
3263 const char *client_name,const char *keyword,char *resource_default)
3264{
3265 char
3266 resource_class[MaxTextExtent],
3267 resource_name[MaxTextExtent];
3268
3269 static char
3270 *resource_type;
3271
3272 Status
3273 status;
3274
3275 XrmValue
3276 resource_value;
3277
3278 if (database == (XrmDatabase) NULL)
3279 return(resource_default);
3280 *resource_name='\0';
3281 *resource_class='\0';
3282 if (keyword != (char *) NULL)
3283 {
3284 int
3285 c,
3286 k;
3287
3288 /*
3289 Initialize resource keyword and class.
3290 */
cristyb51dff52011-05-19 16:55:47 +00003291 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003292 client_name,keyword);
3293 c=(int) (*client_name);
3294 if ((c >= XK_a) && (c <= XK_z))
3295 c-=(XK_a-XK_A);
3296 else
3297 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3298 c-=(XK_agrave-XK_Agrave);
3299 else
3300 if ((c >= XK_oslash) && (c <= XK_thorn))
3301 c-=(XK_oslash-XK_Ooblique);
3302 k=(int) (*keyword);
3303 if ((k >= XK_a) && (k <= XK_z))
3304 k-=(XK_a-XK_A);
3305 else
3306 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3307 k-=(XK_agrave-XK_Agrave);
3308 else
3309 if ((k >= XK_oslash) && (k <= XK_thorn))
3310 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003311 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003312 client_name+1,k,keyword+1);
3313 }
3314 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3315 &resource_value);
3316 if (status == False)
3317 return(resource_default);
3318 return(resource_value.addr);
3319}
3320
3321/*
3322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3323% %
3324% %
3325% %
3326% X G e t R e s o u r c e D a t a b a s e %
3327% %
3328% %
3329% %
3330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3331%
3332% XGetResourceDatabase() creates a new resource database and initializes it.
3333%
3334% The format of the XGetResourceDatabase method is:
3335%
3336% XrmDatabase XGetResourceDatabase(Display *display,
3337% const char *client_name)
3338%
3339% A description of each parameter follows:
3340%
3341% o database: XGetResourceDatabase() returns the database after it is
3342% initialized.
3343%
3344% o display: Specifies a connection to an X server; returned from
3345% XOpenDisplay.
3346%
3347% o client_name: Specifies the application name used to retrieve resource
3348% info from the X server database.
3349%
3350*/
3351MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3352 const char *client_name)
3353{
3354 char
3355 filename[MaxTextExtent];
3356
3357 int
3358 c;
3359
3360 register const char
3361 *p;
3362
3363 XrmDatabase
3364 resource_database,
3365 server_database;
3366
3367 if (display == (Display *) NULL)
3368 return((XrmDatabase) NULL);
3369 assert(client_name != (char *) NULL);
3370 /*
3371 Initialize resource database.
3372 */
3373 XrmInitialize();
3374 (void) XGetDefault(display,(char *) client_name,"dummy");
3375 resource_database=XrmGetDatabase(display);
3376 /*
3377 Combine application database.
3378 */
3379 if (client_name != (char *) NULL)
3380 {
3381 /*
3382 Get basename of client.
3383 */
3384 p=client_name+(strlen(client_name)-1);
3385 while ((p > client_name) && (*p != '/'))
3386 p--;
3387 if (*p == '/')
3388 client_name=p+1;
3389 }
3390 c=(int) (*client_name);
3391 if ((c >= XK_a) && (c <= XK_z))
3392 c-=(XK_a-XK_A);
3393 else
3394 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3395 c-=(XK_agrave-XK_Agrave);
3396 else
3397 if ((c >= XK_oslash) && (c <= XK_thorn))
3398 c-=(XK_oslash-XK_Ooblique);
3399#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003400 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003401 X11_APPLICATION_PATH,c,client_name+1);
3402 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3403#endif
3404 if (XResourceManagerString(display) != (char *) NULL)
3405 {
3406 /*
3407 Combine server database.
3408 */
3409 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3410 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3411 }
3412 /*
3413 Merge user preferences database.
3414 */
3415#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003416 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003417 X11_PREFERENCES_PATH,client_name);
3418 ExpandFilename(filename);
3419 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3420#endif
3421 return(resource_database);
3422}
3423
3424/*
3425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3426% %
3427% %
3428% %
3429% X G e t R e s o u r c e I n f o %
3430% %
3431% %
3432% %
3433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3434%
3435% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3436%
3437% The format of the XGetResourceInfo method is:
3438%
3439% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3440% const char *client_name,XResourceInfo *resource_info)
3441%
3442% A description of each parameter follows:
3443%
3444% o image_info: the image info.
3445%
3446% o database: Specifies a resource database; returned from
3447% XrmGetStringDatabase.
3448%
3449% o client_name: Specifies the application name used to retrieve
3450% resource info from the X server database.
3451%
3452% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3453%
3454*/
3455MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3456 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3457{
3458 char
cristy00976d82011-02-20 20:31:28 +00003459 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003460 *resource_value;
3461
3462 /*
3463 Initialize resource info fields.
3464 */
3465 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3466 assert(resource_info != (XResourceInfo *) NULL);
3467 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3468 resource_info->resource_database=database;
3469 resource_info->image_info=(ImageInfo *) image_info;
3470 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3471 XMagickProgressMonitor,(void *) NULL);
3472 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3473 resource_info->close_server=MagickTrue;
3474 resource_info->client_name=AcquireString(client_name);
3475 resource_value=XGetResourceClass(database,client_name,"backdrop",
3476 (char *) "False");
3477 resource_info->backdrop=IsMagickTrue(resource_value);
3478 resource_info->background_color=XGetResourceInstance(database,client_name,
3479 "background",(char *) "#d6d6d6d6d6d6");
3480 resource_info->border_color=XGetResourceInstance(database,client_name,
3481 "borderColor",BorderColor);
3482 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3483 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003484 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3485 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003486 resource_value=XGetResourceClass(database,client_name,"colormap",
3487 (char *) "shared");
3488 resource_info->colormap=UndefinedColormap;
3489 if (LocaleCompare("private",resource_value) == 0)
3490 resource_info->colormap=PrivateColormap;
3491 if (LocaleCompare("shared",resource_value) == 0)
3492 resource_info->colormap=SharedColormap;
3493 if (resource_info->colormap == UndefinedColormap)
3494 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3495 resource_value);
3496 resource_value=XGetResourceClass(database,client_name,
3497 "colorRecovery",(char *) "False");
3498 resource_info->color_recovery=IsMagickTrue(resource_value);
3499 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3500 (char *) "False");
3501 resource_info->confirm_exit=IsMagickTrue(resource_value);
3502 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3503 (char *) "False");
3504 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003505 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003506 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003507 resource_info->display_gamma=XGetResourceClass(database,client_name,
3508 "displayGamma",(char *) "2.2");
3509 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3510 (char *) "True");
3511 resource_info->display_warnings=IsMagickTrue(resource_value);
3512 resource_info->font=XGetResourceClass(database,client_name,"font",
3513 (char *) NULL);
3514 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3515 resource_info->font);
3516 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3517 (char *) "fixed");
3518 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3519 (char *) "variable");
3520 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3521 (char *) "5x8");
3522 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3523 (char *) "6x10");
3524 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3525 (char *) "7x13bold");
3526 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3527 (char *) "8x13bold");
3528 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3529 (char *) "9x15bold");
3530 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3531 (char *) "10x20");
3532 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3533 (char *) "12x24");
3534 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3535 (char *) "fixed");
3536 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3537 (char *) "fixed");
3538 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3539 "foreground",ForegroundColor);
3540 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3541 (char *) "True");
3542 resource_info->gamma_correct=IsMagickTrue(resource_value);
3543 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3544 client_name,"geometry",(char *) NULL));
3545 resource_value=XGetResourceClass(database,client_name,"gravity",
3546 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003547 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003548 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003549 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3550 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003551 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3552 "iconGeometry",(char *) NULL);
3553 resource_value=XGetResourceClass(database,client_name,"iconic",
3554 (char *) "False");
3555 resource_info->iconic=IsMagickTrue(resource_value);
3556 resource_value=XGetResourceClass(database,client_name,"immutable",
3557 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3558 (char *) "False");
3559 resource_info->immutable=IsMagickTrue(resource_value);
3560 resource_value=XGetResourceClass(database,client_name,"magnify",
3561 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003562 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003563 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3564 (char *) NULL);
3565 resource_info->matte_color=XGetResourceInstance(database,client_name,
3566 "mattecolor",(char *) NULL);
3567 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3568 "name",(char *) NULL));
3569 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3570 (char *) "black");
3571 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3572 (char *) "blue");
3573 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3574 (char *) "cyan");
3575 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3576 (char *) "green");
3577 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3578 (char *) "gray");
3579 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3580 (char *) "red");
3581 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3582 (char *) "magenta");
3583 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3584 (char *) "yellow");
3585 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3586 (char *) "white");
3587 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3588 (char *) "gray");
3589 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3590 (char *) "gray");
3591 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003592 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003593 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003594 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003595 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3596 "font",(char *) "fixed");
3597 resource_info->text_font=XGetResourceClass(database,client_name,
3598 "textFontList",resource_info->text_font);
3599 resource_info->title=XGetResourceClass(database,client_name,"title",
3600 (char *) NULL);
3601 resource_value=XGetResourceClass(database,client_name,"undoCache",
3602 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003603 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003604 resource_value=XGetResourceClass(database,client_name,"update",
3605 (char *) "False");
3606 resource_info->update=IsMagickTrue(resource_value);
3607 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3608 (char *) "True");
3609 resource_info->use_pixmap=IsMagickTrue(resource_value);
3610 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3611 (char *) "True");
3612 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3613 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3614 (char *) NULL);
3615 resource_info->window_group=XGetResourceClass(database,client_name,
3616 "windowGroup",(char *) NULL);
3617 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3618 (char *) NULL);
3619 resource_info->write_filename=XGetResourceClass(database,client_name,
3620 "writeFilename",(char *) NULL);
3621}
3622
3623/*
3624%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3625% %
3626% %
3627% %
3628% X G e t R e s o u r c e I n s t a n c e %
3629% %
3630% %
3631% %
3632%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3633%
3634% XGetResourceInstance() queries the X server for the specified resource name.
3635% If the resource name is not defined in the database, the supplied default
3636% value is returned.
3637%
3638% The format of the XGetResourceInstance method is:
3639%
3640% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3641% const char *keyword,const char *resource_default)
3642%
3643% A description of each parameter follows:
3644%
3645% o database: Specifies a resource database; returned from
3646% XrmGetStringDatabase.
3647%
3648% o client_name: Specifies the application name used to retrieve
3649% resource info from the X server database.
3650%
3651% o keyword: Specifies the keyword of the value being retrieved.
3652%
3653% o resource_default: Specifies the default value to return if the query
3654% fails to find the specified keyword/class.
3655%
3656*/
3657MagickExport char *XGetResourceInstance(XrmDatabase database,
3658 const char *client_name,const char *keyword,const char *resource_default)
3659{
3660 char
3661 *resource_type,
3662 resource_name[MaxTextExtent];
3663
3664 Status
3665 status;
3666
3667 XrmValue
3668 resource_value;
3669
3670 if (database == (XrmDatabase) NULL)
3671 return((char *) resource_default);
3672 *resource_name='\0';
3673 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003674 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003675 keyword);
3676 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3677 &resource_value);
3678 if (status == False)
3679 return((char *) resource_default);
3680 return(resource_value.addr);
3681}
3682
3683/*
3684%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3685% %
3686% %
3687% %
3688% X G e t S c r e e n D e n s i t y %
3689% %
3690% %
3691% %
3692%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3693%
3694% XGetScreenDensity() returns the density of the X server screen in
3695% dots-per-inch.
3696%
3697% The format of the XGetScreenDensity method is:
3698%
3699% char *XGetScreenDensity(Display *display)
3700%
3701% A description of each parameter follows:
3702%
3703% o density: XGetScreenDensity() returns the density of the X screen in
3704% dots-per-inch.
3705%
3706% o display: Specifies a connection to an X server; returned from
3707% XOpenDisplay.
3708%
3709*/
3710MagickExport char *XGetScreenDensity(Display *display)
3711{
3712 char
3713 density[MaxTextExtent];
3714
3715 double
3716 x_density,
3717 y_density;
3718
3719 /*
3720 Set density as determined by screen size.
3721 */
3722 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3723 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3724 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3725 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003726 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003727 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003728 return(GetPageGeometry(density));
3729}
3730
3731/*
3732%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3733% %
3734% %
3735% %
3736+ X G e t S u b w i n d o w %
3737% %
3738% %
3739% %
3740%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3741%
3742% XGetSubwindow() returns the subwindow of a window chosen the user with the
3743% pointer and a button press.
3744%
3745% The format of the XGetSubwindow method is:
3746%
3747% Window XGetSubwindow(Display *display,Window window,int x,int y)
3748%
3749% A description of each parameter follows:
3750%
3751% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3752% otherwise the subwindow is returned.
3753%
3754% o display: Specifies a connection to an X server; returned from
3755% XOpenDisplay.
3756%
3757% o window: Specifies a pointer to a Window.
3758%
3759% o x: the x coordinate of the pointer relative to the origin of the
3760% window.
3761%
3762% o y: the y coordinate of the pointer relative to the origin of the
3763% window.
3764%
cristy3ed852e2009-09-05 21:47:34 +00003765*/
3766static Window XGetSubwindow(Display *display,Window window,int x,int y)
3767{
3768 int
3769 x_offset,
3770 y_offset;
3771
3772 Status
3773 status;
3774
3775 Window
3776 source_window,
3777 target_window;
3778
3779 assert(display != (Display *) NULL);
3780 source_window=XRootWindow(display,XDefaultScreen(display));
3781 if (window == (Window) NULL)
3782 return(source_window);
3783 target_window=window;
3784 for ( ; ; )
3785 {
3786 status=XTranslateCoordinates(display,source_window,window,x,y,
3787 &x_offset,&y_offset,&target_window);
3788 if (status != True)
3789 break;
3790 if (target_window == (Window) NULL)
3791 break;
3792 source_window=window;
3793 window=target_window;
3794 x=x_offset;
3795 y=y_offset;
3796 }
3797 if (target_window == (Window) NULL)
3798 target_window=window;
3799 return(target_window);
3800}
3801
3802/*
3803%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3804% %
3805% %
3806% %
3807% X G e t W i n d o w C o l o r %
3808% %
3809% %
3810% %
3811%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3812%
3813% XGetWindowColor() returns the color of a pixel interactively chosen from the
3814% X server.
3815%
3816% The format of the XGetWindowColor method is:
3817%
3818% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3819% char *name)
3820%
3821% A description of each parameter follows:
3822%
3823% o display: Specifies a connection to an X server; returned from
3824% XOpenDisplay.
3825%
3826% o windows: Specifies a pointer to a XWindows structure.
3827%
3828% o name: the name of the color if found in the X Color Database is
3829% returned in this character string.
3830%
3831*/
cristybcbda3f2011-09-03 13:01:22 +00003832MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003833 XWindows *windows,char *name)
3834{
3835 int
3836 x,
3837 y;
3838
3839 PixelPacket
3840 pixel;
3841
3842 RectangleInfo
3843 crop_info;
3844
3845 Status
3846 status;
3847
3848 Window
3849 child,
3850 client_window,
3851 root_window,
3852 target_window;
3853
3854 XColor
3855 color;
3856
3857 XImage
3858 *ximage;
3859
3860 XWindowAttributes
3861 window_attributes;
3862
3863 /*
3864 Choose a pixel from the X server.
3865 */
3866 assert(display != (Display *) NULL);
3867 assert(name != (char *) NULL);
3868 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3869 *name='\0';
3870 target_window=XSelectWindow(display,&crop_info);
3871 if (target_window == (Window) NULL)
3872 return(MagickFalse);
3873 root_window=XRootWindow(display,XDefaultScreen(display));
3874 client_window=target_window;
3875 if (target_window != root_window)
3876 {
3877 unsigned int
3878 d;
3879
3880 /*
3881 Get client window.
3882 */
3883 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3884 if (status != False)
3885 {
3886 client_window=XClientWindow(display,target_window);
3887 target_window=client_window;
3888 }
3889 }
3890 /*
3891 Verify window is viewable.
3892 */
3893 status=XGetWindowAttributes(display,target_window,&window_attributes);
3894 if ((status == False) || (window_attributes.map_state != IsViewable))
3895 return(MagickFalse);
3896 /*
3897 Get window X image.
3898 */
3899 (void) XTranslateCoordinates(display,root_window,target_window,
3900 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3901 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3902 if (ximage == (XImage *) NULL)
3903 return(MagickFalse);
3904 color.pixel=XGetPixel(ximage,0,0);
3905 XDestroyImage(ximage);
3906 /*
3907 Match color against the color database.
3908 */
3909 (void) XQueryColor(display,window_attributes.colormap,&color);
3910 pixel.red=ScaleShortToQuantum(color.red);
3911 pixel.green=ScaleShortToQuantum(color.green);
3912 pixel.blue=ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003913 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003914 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3915 &windows->image.image->exception);
3916 return(MagickTrue);
3917}
3918
3919/*
3920%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3921% %
3922% %
3923% %
3924+ X G e t W i n d o w I m a g e %
3925% %
3926% %
3927% %
3928%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3929%
3930% XGetWindowImage() reads an image from the target X window and returns it.
3931% XGetWindowImage() optionally descends the window hierarchy and overlays the
3932% target image with each child image in an optimized fashion. Any child
3933% window that have the same visual, colormap, and are contained by its parent
3934% are exempted.
3935%
3936% The format of the XGetWindowImage method is:
3937%
3938% Image *XGetWindowImage(Display *display,const Window window,
3939% const unsigned int borders,const unsigned int level)
3940%
3941% A description of each parameter follows:
3942%
3943% o display: Specifies a connection to an X server; returned from
3944% XOpenDisplay.
3945%
3946% o window: Specifies the window to obtain the image from.
3947%
3948% o borders: Specifies whether borders pixels are to be saved with
3949% the image.
3950%
3951% o level: Specifies an unsigned integer representing the level of
3952% decent in the window hierarchy. This value must be zero or one on
3953% the initial call to XGetWindowImage. A value of zero returns after
3954% one call. A value of one causes the function to descend the window
3955% hierarchy and overlay the target image with each subwindow image.
3956%
cristy3ed852e2009-09-05 21:47:34 +00003957*/
3958static Image *XGetWindowImage(Display *display,const Window window,
3959 const unsigned int borders,const unsigned int level)
3960{
3961 typedef struct _ColormapInfo
3962 {
3963 Colormap
3964 colormap;
3965
3966 XColor
3967 *colors;
3968
3969 struct _ColormapInfo
3970 *next;
3971 } ColormapInfo;
3972
3973 typedef struct _WindowInfo
3974 {
3975 Window
3976 window,
3977 parent;
3978
3979 Visual
3980 *visual;
3981
3982 Colormap
3983 colormap;
3984
3985 XSegment
3986 bounds;
3987
3988 RectangleInfo
3989 crop_info;
3990 } WindowInfo;
3991
cristy3ed852e2009-09-05 21:47:34 +00003992 int
3993 display_height,
3994 display_width,
3995 id,
3996 x_offset,
3997 y_offset;
3998
cristy4c08aed2011-07-01 19:47:50 +00003999 Quantum
4000 index;
4001
cristy3ed852e2009-09-05 21:47:34 +00004002 RectangleInfo
4003 crop_info;
4004
cristy3ed852e2009-09-05 21:47:34 +00004005 register int
4006 i;
4007
4008 static ColormapInfo
4009 *colormap_info = (ColormapInfo *) NULL;
4010
4011 static int
4012 max_windows = 0,
4013 number_windows = 0;
4014
4015 static WindowInfo
4016 *window_info;
4017
4018 Status
4019 status;
4020
4021 Window
4022 child,
4023 root_window;
4024
4025 XWindowAttributes
4026 window_attributes;
4027
4028 /*
4029 Verify window is viewable.
4030 */
4031 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4032 assert(display != (Display *) NULL);
4033 status=XGetWindowAttributes(display,window,&window_attributes);
4034 if ((status == False) || (window_attributes.map_state != IsViewable))
4035 return((Image *) NULL);
4036 /*
4037 Cropping rectangle is relative to root window.
4038 */
4039 root_window=XRootWindow(display,XDefaultScreen(display));
4040 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4041 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004042 crop_info.x=(ssize_t) x_offset;
4043 crop_info.y=(ssize_t) y_offset;
4044 crop_info.width=(size_t) window_attributes.width;
4045 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004046 if (borders != MagickFalse)
4047 {
4048 /*
4049 Include border in image.
4050 */
cristybb503372010-05-27 20:51:26 +00004051 crop_info.x-=(ssize_t) window_attributes.border_width;
4052 crop_info.y-=(ssize_t) window_attributes.border_width;
4053 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4054 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004055 }
4056 /*
4057 Crop to root window.
4058 */
4059 if (crop_info.x < 0)
4060 {
4061 crop_info.width+=crop_info.x;
4062 crop_info.x=0;
4063 }
4064 if (crop_info.y < 0)
4065 {
4066 crop_info.height+=crop_info.y;
4067 crop_info.y=0;
4068 }
4069 display_width=XDisplayWidth(display,XDefaultScreen(display));
4070 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004071 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004072 display_height=XDisplayHeight(display,XDefaultScreen(display));
4073 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004074 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004075 /*
4076 Initialize window info attributes.
4077 */
4078 if (number_windows >= max_windows)
4079 {
4080 /*
4081 Allocate or resize window info buffer.
4082 */
4083 max_windows+=1024;
4084 if (window_info == (WindowInfo *) NULL)
4085 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4086 sizeof(*window_info));
4087 else
4088 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4089 max_windows,sizeof(*window_info));
4090 }
4091 if (window_info == (WindowInfo *) NULL)
4092 {
4093 ThrowXWindowFatalException(ResourceLimitError,
4094 "MemoryAllocationFailed","...");
4095 return((Image *) NULL);
4096 }
4097 id=number_windows++;
4098 window_info[id].window=window;
4099 window_info[id].visual=window_attributes.visual;
4100 window_info[id].colormap=window_attributes.colormap;
4101 window_info[id].bounds.x1=(short) crop_info.x;
4102 window_info[id].bounds.y1=(short) crop_info.y;
4103 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4104 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4105 crop_info.x-=x_offset;
4106 crop_info.y-=y_offset;
4107 window_info[id].crop_info=crop_info;
4108 if (level != 0)
4109 {
4110 unsigned int
4111 number_children;
4112
4113 Window
4114 *children;
4115
4116 /*
4117 Descend the window hierarchy.
4118 */
4119 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4120 &children,&number_children);
4121 for (i=0; i < id; i++)
4122 if ((window_info[i].window == window_info[id].parent) &&
4123 (window_info[i].visual == window_info[id].visual) &&
4124 (window_info[i].colormap == window_info[id].colormap))
4125 {
4126 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4127 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4128 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4129 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4130 {
4131 /*
4132 Eliminate windows not circumscribed by their parent.
4133 */
4134 number_windows--;
4135 break;
4136 }
4137 }
4138 if ((status == True) && (number_children != 0))
4139 {
4140 for (i=0; i < (int) number_children; i++)
4141 (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4142 (void) XFree((void *) children);
4143 }
4144 }
4145 if (level <= 1)
4146 {
cristyc57f6942010-11-12 01:47:39 +00004147 CacheView
4148 *composite_view;
4149
cristy3ed852e2009-09-05 21:47:34 +00004150 ColormapInfo
4151 *next;
4152
4153 ExceptionInfo
4154 *exception;
4155
4156 Image
4157 *composite_image,
4158 *image;
4159
4160 int
4161 y;
4162
4163 MagickBooleanType
4164 import;
4165
4166 register int
4167 j,
4168 x;
4169
cristy4c08aed2011-07-01 19:47:50 +00004170 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004171 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004172
cristybb503372010-05-27 20:51:26 +00004173 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004174 pixel;
4175
4176 unsigned int
4177 number_colors;
4178
4179 XColor
4180 *colors;
4181
4182 XImage
4183 *ximage;
4184
4185 /*
4186 Get X image for each window in the list.
4187 */
4188 image=NewImageList();
4189 for (id=0; id < number_windows; id++)
4190 {
4191 /*
4192 Does target window intersect top level window?
4193 */
4194 import=
4195 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4196 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4197 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4198 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4199 MagickTrue : MagickFalse;
4200 /*
4201 Is target window contained by another window with the same colormap?
4202 */
4203 for (j=0; j < id; j++)
4204 if ((window_info[id].visual == window_info[j].visual) &&
4205 (window_info[id].colormap == window_info[j].colormap))
4206 {
4207 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4208 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4209 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4210 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4211 import=MagickFalse;
4212 }
4213 else
4214 if ((window_info[id].visual != window_info[j].visual) ||
4215 (window_info[id].colormap != window_info[j].colormap))
4216 {
4217 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4218 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4219 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4220 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4221 import=MagickTrue;
4222 }
4223 if (import == MagickFalse)
4224 continue;
4225 /*
4226 Get X image.
4227 */
4228 ximage=XGetImage(display,window_info[id].window,(int)
4229 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4230 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4231 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4232 if (ximage == (XImage *) NULL)
4233 continue;
4234 /*
4235 Initialize window colormap.
4236 */
4237 number_colors=0;
4238 colors=(XColor *) NULL;
4239 if (window_info[id].colormap != (Colormap) NULL)
4240 {
4241 ColormapInfo
4242 *p;
4243
4244 /*
4245 Search colormap list for window colormap.
4246 */
4247 number_colors=(unsigned int) window_info[id].visual->map_entries;
4248 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4249 if (p->colormap == window_info[id].colormap)
4250 break;
4251 if (p == (ColormapInfo *) NULL)
4252 {
4253 /*
4254 Get the window colormap.
4255 */
4256 colors=(XColor *) AcquireQuantumMemory(number_colors,
4257 sizeof(*colors));
4258 if (colors == (XColor *) NULL)
4259 {
4260 XDestroyImage(ximage);
4261 return((Image *) NULL);
4262 }
4263 if ((window_info[id].visual->klass != DirectColor) &&
4264 (window_info[id].visual->klass != TrueColor))
4265 for (i=0; i < (int) number_colors; i++)
4266 {
cristybb503372010-05-27 20:51:26 +00004267 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004268 colors[i].pad='\0';
4269 }
4270 else
4271 {
cristybb503372010-05-27 20:51:26 +00004272 size_t
cristy3ed852e2009-09-05 21:47:34 +00004273 blue,
4274 blue_bit,
4275 green,
4276 green_bit,
4277 red,
4278 red_bit;
4279
4280 /*
4281 DirectColor or TrueColor visual.
4282 */
4283 red=0;
4284 green=0;
4285 blue=0;
4286 red_bit=window_info[id].visual->red_mask &
4287 (~(window_info[id].visual->red_mask)+1);
4288 green_bit=window_info[id].visual->green_mask &
4289 (~(window_info[id].visual->green_mask)+1);
4290 blue_bit=window_info[id].visual->blue_mask &
4291 (~(window_info[id].visual->blue_mask)+1);
4292 for (i=0; i < (int) number_colors; i++)
4293 {
cristy8891f9c2010-06-04 23:32:17 +00004294 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004295 colors[i].pad='\0';
4296 red+=red_bit;
4297 if (red > window_info[id].visual->red_mask)
4298 red=0;
4299 green+=green_bit;
4300 if (green > window_info[id].visual->green_mask)
4301 green=0;
4302 blue+=blue_bit;
4303 if (blue > window_info[id].visual->blue_mask)
4304 blue=0;
4305 }
4306 }
4307 (void) XQueryColors(display,window_info[id].colormap,colors,
4308 (int) number_colors);
4309 /*
4310 Append colormap to colormap list.
4311 */
cristy73bd4a52010-10-05 11:24:23 +00004312 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004313 if (p == (ColormapInfo *) NULL)
4314 return((Image *) NULL);
4315 p->colormap=window_info[id].colormap;
4316 p->colors=colors;
4317 p->next=colormap_info;
4318 colormap_info=p;
4319 }
4320 colors=p->colors;
4321 }
4322 /*
4323 Allocate image structure.
4324 */
4325 composite_image=AcquireImage((ImageInfo *) NULL);
4326 if (composite_image == (Image *) NULL)
4327 {
4328 XDestroyImage(ximage);
4329 return((Image *) NULL);
4330 }
4331 /*
4332 Convert X image to MIFF format.
4333 */
4334 if ((window_info[id].visual->klass != TrueColor) &&
4335 (window_info[id].visual->klass != DirectColor))
4336 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004337 composite_image->columns=(size_t) ximage->width;
4338 composite_image->rows=(size_t) ximage->height;
cristy3ed852e2009-09-05 21:47:34 +00004339 exception=(&composite_image->exception);
cristyc57f6942010-11-12 01:47:39 +00004340 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004341 switch (composite_image->storage_class)
4342 {
4343 case DirectClass:
4344 default:
4345 {
cristybb503372010-05-27 20:51:26 +00004346 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004347 color,
4348 index;
4349
cristybb503372010-05-27 20:51:26 +00004350 size_t
cristy3ed852e2009-09-05 21:47:34 +00004351 blue_mask,
4352 blue_shift,
4353 green_mask,
4354 green_shift,
4355 red_mask,
4356 red_shift;
4357
4358 /*
4359 Determine shift and mask for red, green, and blue.
4360 */
4361 red_mask=window_info[id].visual->red_mask;
4362 red_shift=0;
4363 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4364 {
4365 red_mask>>=1;
4366 red_shift++;
4367 }
4368 green_mask=window_info[id].visual->green_mask;
4369 green_shift=0;
4370 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4371 {
4372 green_mask>>=1;
4373 green_shift++;
4374 }
4375 blue_mask=window_info[id].visual->blue_mask;
4376 blue_shift=0;
4377 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4378 {
4379 blue_mask>>=1;
4380 blue_shift++;
4381 }
4382 /*
4383 Convert X image to DirectClass packets.
4384 */
4385 if ((number_colors != 0) &&
4386 (window_info[id].visual->klass == DirectColor))
4387 for (y=0; y < (int) composite_image->rows; y++)
4388 {
cristyc57f6942010-11-12 01:47:39 +00004389 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004390 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004391 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004392 break;
4393 for (x=0; x < (int) composite_image->columns; x++)
4394 {
4395 pixel=XGetPixel(ximage,x,y);
4396 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004397 SetPixelRed(composite_image,
4398 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004399 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004400 SetPixelGreen(composite_image,
4401 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004402 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004403 SetPixelBlue(composite_image,
4404 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004405 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004406 }
cristyc57f6942010-11-12 01:47:39 +00004407 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004408 break;
4409 }
4410 else
4411 for (y=0; y < (int) composite_image->rows; y++)
4412 {
cristyc57f6942010-11-12 01:47:39 +00004413 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004414 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004415 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004416 break;
4417 for (x=0; x < (int) composite_image->columns; x++)
4418 {
4419 pixel=XGetPixel(ximage,x,y);
4420 color=(pixel >> red_shift) & red_mask;
4421 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004422 SetPixelRed(composite_image,
4423 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004424 color=(pixel >> green_shift) & green_mask;
4425 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004426 SetPixelGreen(composite_image,
4427 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004428 color=(pixel >> blue_shift) & blue_mask;
4429 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004430 SetPixelBlue(composite_image,
4431 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004432 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004433 }
cristyc57f6942010-11-12 01:47:39 +00004434 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004435 break;
4436 }
4437 break;
4438 }
4439 case PseudoClass:
4440 {
4441 /*
4442 Create colormap.
4443 */
cristy018f07f2011-09-04 21:15:19 +00004444 if (AcquireImageColormap(composite_image,number_colors,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004445 {
4446 XDestroyImage(ximage);
4447 composite_image=DestroyImage(composite_image);
4448 return((Image *) NULL);
4449 }
4450 for (i=0; i < (int) composite_image->colors; i++)
4451 {
4452 composite_image->colormap[colors[i].pixel].red=
4453 ScaleShortToQuantum(colors[i].red);
4454 composite_image->colormap[colors[i].pixel].green=
4455 ScaleShortToQuantum(colors[i].green);
4456 composite_image->colormap[colors[i].pixel].blue=
4457 ScaleShortToQuantum(colors[i].blue);
4458 }
4459 /*
4460 Convert X image to PseudoClass packets.
4461 */
4462 for (y=0; y < (int) composite_image->rows; y++)
4463 {
cristyc57f6942010-11-12 01:47:39 +00004464 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4465 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004466 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004467 break;
cristy3ed852e2009-09-05 21:47:34 +00004468 for (x=0; x < (int) composite_image->columns; x++)
4469 {
cristy4c08aed2011-07-01 19:47:50 +00004470 index=(Quantum) XGetPixel(ximage,x,y);
4471 SetPixelIndex(composite_image,index,q);
4472 SetPixelPacket(composite_image,
4473 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004474 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004475 }
cristyc57f6942010-11-12 01:47:39 +00004476 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004477 break;
4478 }
4479 break;
4480 }
4481 }
cristyc57f6942010-11-12 01:47:39 +00004482 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004483 XDestroyImage(ximage);
4484 if (image == (Image *) NULL)
4485 {
4486 image=composite_image;
4487 continue;
4488 }
4489 /*
4490 Composite any children in back-to-front order.
4491 */
4492 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4493 &x_offset,&y_offset,&child);
4494 x_offset-=(int) crop_info.x;
4495 if (x_offset < 0)
4496 x_offset=0;
4497 y_offset-=(int) crop_info.y;
4498 if (y_offset < 0)
4499 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004500 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
4501 x_offset,(ssize_t) y_offset);
cristy3ed852e2009-09-05 21:47:34 +00004502 }
4503 /*
4504 Relinquish resources.
4505 */
4506 while (colormap_info != (ColormapInfo *) NULL)
4507 {
4508 next=colormap_info->next;
4509 colormap_info->colors=(XColor *)
4510 RelinquishMagickMemory(colormap_info->colors);
4511 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4512 colormap_info=next;
4513 }
4514 /*
4515 Relinquish resources and restore initial state.
4516 */
4517 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4518 max_windows=0;
4519 number_windows=0;
4520 colormap_info=(ColormapInfo *) NULL;
4521 return(image);
4522 }
4523 return((Image *) NULL);
4524}
4525
4526/*
4527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4528% %
4529% %
4530% %
4531% X G e t W i n d o w I n f o %
4532% %
4533% %
4534% %
4535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4536%
4537% XGetWindowInfo() initializes the XWindowInfo structure.
4538%
4539% The format of the XGetWindowInfo method is:
4540%
4541% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4542% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4543% XResourceInfo *resource_info,XWindowInfo *window)
4544% resource_info,window)
4545%
4546% A description of each parameter follows:
4547%
4548% o display: Specifies a connection to an X server; returned from
4549% XOpenDisplay.
4550%
4551% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4552% returned from XGetVisualInfo.
4553%
4554% o map_info: If map_type is specified, this structure is initialized
4555% with info from the Standard Colormap.
4556%
4557% o pixel: Specifies a pointer to a XPixelInfo structure.
4558%
4559% o font_info: Specifies a pointer to a XFontStruct structure.
4560%
4561% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4562%
4563*/
cristybcbda3f2011-09-03 13:01:22 +00004564MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004565 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4566 XResourceInfo *resource_info,XWindowInfo *window)
4567{
4568 /*
4569 Initialize window info.
4570 */
4571 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4572 assert(display != (Display *) NULL);
4573 assert(visual_info != (XVisualInfo *) NULL);
4574 assert(map_info != (XStandardColormap *) NULL);
4575 assert(pixel != (XPixelInfo *) NULL);
4576 assert(resource_info != (XResourceInfo *) NULL);
4577 assert(window != (XWindowInfo *) NULL);
4578 if (window->id != (Window) NULL)
4579 {
4580 if (window->cursor != (Cursor) NULL)
4581 (void) XFreeCursor(display,window->cursor);
4582 if (window->busy_cursor != (Cursor) NULL)
4583 (void) XFreeCursor(display,window->busy_cursor);
4584 if (window->highlight_stipple != (Pixmap) NULL)
4585 (void) XFreePixmap(display,window->highlight_stipple);
4586 if (window->shadow_stipple != (Pixmap) NULL)
4587 (void) XFreePixmap(display,window->shadow_stipple);
4588 if (window->name == (char *) NULL)
4589 window->name=AcquireString("");
4590 if (window->icon_name == (char *) NULL)
4591 window->icon_name=AcquireString("");
4592 }
4593 else
4594 {
4595 /*
4596 Initialize these attributes just once.
4597 */
4598 window->id=(Window) NULL;
4599 if (window->name == (char *) NULL)
4600 window->name=AcquireString("");
4601 if (window->icon_name == (char *) NULL)
4602 window->icon_name=AcquireString("");
4603 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4604 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4605 window->ximage=(XImage *) NULL;
4606 window->matte_image=(XImage *) NULL;
4607 window->pixmap=(Pixmap) NULL;
4608 window->matte_pixmap=(Pixmap) NULL;
4609 window->mapped=MagickFalse;
4610 window->stasis=MagickFalse;
4611 window->shared_memory=MagickTrue;
4612 window->segment_info=(void *) NULL;
4613#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4614 {
4615 XShmSegmentInfo
4616 *segment_info;
4617
4618 if (window->segment_info == (void *) NULL)
4619 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4620 segment_info=(XShmSegmentInfo *) window->segment_info;
4621 segment_info[0].shmid=(-1);
4622 segment_info[0].shmaddr=(char *) NULL;
4623 segment_info[1].shmid=(-1);
4624 segment_info[1].shmaddr=(char *) NULL;
4625 }
4626#endif
4627 }
4628 /*
4629 Initialize these attributes every time function is called.
4630 */
4631 window->screen=visual_info->screen;
4632 window->root=XRootWindow(display,visual_info->screen);
4633 window->visual=visual_info->visual;
4634 window->storage_class=(unsigned int) visual_info->klass;
4635 window->depth=(unsigned int) visual_info->depth;
4636 window->visual_info=visual_info;
4637 window->map_info=map_info;
4638 window->pixel_info=pixel;
4639 window->font_info=font_info;
4640 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4641 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4642 window->geometry=(char *) NULL;
4643 window->icon_geometry=(char *) NULL;
4644 if (resource_info->icon_geometry != (char *) NULL)
4645 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4646 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004647 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004648 window->width=1;
4649 window->height=1;
4650 window->min_width=1;
4651 window->min_height=1;
4652 window->width_inc=1;
4653 window->height_inc=1;
4654 window->border_width=resource_info->border_width;
4655 window->annotate_context=pixel->annotate_context;
4656 window->highlight_context=pixel->highlight_context;
4657 window->widget_context=pixel->widget_context;
4658 window->shadow_stipple=(Pixmap) NULL;
4659 window->highlight_stipple=(Pixmap) NULL;
4660 window->use_pixmap=MagickTrue;
4661 window->immutable=MagickFalse;
4662 window->shape=MagickFalse;
4663 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004664 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004665 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4666 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4667 window->attributes.background_pixel=pixel->background_color.pixel;
4668 window->attributes.background_pixmap=(Pixmap) NULL;
4669 window->attributes.bit_gravity=ForgetGravity;
4670 window->attributes.backing_store=WhenMapped;
4671 window->attributes.save_under=MagickTrue;
4672 window->attributes.border_pixel=pixel->border_color.pixel;
4673 window->attributes.colormap=map_info->colormap;
4674 window->attributes.cursor=window->cursor;
4675 window->attributes.do_not_propagate_mask=NoEventMask;
4676 window->attributes.event_mask=NoEventMask;
4677 window->attributes.override_redirect=MagickFalse;
4678 window->attributes.win_gravity=NorthWestGravity;
4679 window->orphan=MagickFalse;
4680}
4681
4682/*
4683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4684% %
4685% %
4686% %
4687% X H i g h l i g h t E l l i p s e %
4688% %
4689% %
4690% %
4691%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4692%
4693% XHighlightEllipse() puts a border on the X server around a region defined by
4694% highlight_info.
4695%
4696% The format of the XHighlightEllipse method is:
4697%
4698% void XHighlightEllipse(Display *display,Window window,
4699% GC annotate_context,const RectangleInfo *highlight_info)
4700%
4701% A description of each parameter follows:
4702%
4703% o display: Specifies a connection to an X server; returned from
4704% XOpenDisplay.
4705%
4706% o window: Specifies a pointer to a Window structure.
4707%
4708% o annotate_context: Specifies a pointer to a GC structure.
4709%
4710% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4711% contains the extents of any highlighting rectangle.
4712%
4713*/
cristybcbda3f2011-09-03 13:01:22 +00004714MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004715 GC annotate_context,const RectangleInfo *highlight_info)
4716{
4717 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4718 assert(display != (Display *) NULL);
4719 assert(window != (Window) NULL);
4720 assert(annotate_context != (GC) NULL);
4721 assert(highlight_info != (RectangleInfo *) NULL);
4722 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4723 return;
4724 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4725 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4726 (unsigned int) highlight_info->height-1,0,360*64);
4727 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4728 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4729 (unsigned int) highlight_info->height-3,0,360*64);
4730}
4731
4732/*
4733%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4734% %
4735% %
4736% %
4737% X H i g h l i g h t L i n e %
4738% %
4739% %
4740% %
4741%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4742%
4743% XHighlightLine() puts a border on the X server around a region defined by
4744% highlight_info.
4745%
4746% The format of the XHighlightLine method is:
4747%
4748% void XHighlightLine(Display *display,Window window,GC annotate_context,
4749% const XSegment *highlight_info)
4750%
4751% A description of each parameter follows:
4752%
4753% o display: Specifies a connection to an X server; returned from
4754% XOpenDisplay.
4755%
4756% o window: Specifies a pointer to a Window structure.
4757%
4758% o annotate_context: Specifies a pointer to a GC structure.
4759%
4760% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4761% contains the extents of any highlighting rectangle.
4762%
4763*/
cristybcbda3f2011-09-03 13:01:22 +00004764MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004765 GC annotate_context,const XSegment *highlight_info)
4766{
4767 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4768 assert(display != (Display *) NULL);
4769 assert(window != (Window) NULL);
4770 assert(annotate_context != (GC) NULL);
4771 assert(highlight_info != (XSegment *) NULL);
4772 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4773 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4774}
4775
4776/*
4777%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4778% %
4779% %
4780% %
4781% X H i g h l i g h t R e c t a n g l e %
4782% %
4783% %
4784% %
4785%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4786%
4787% XHighlightRectangle() puts a border on the X server around a region defined
4788% by highlight_info.
4789%
4790% The format of the XHighlightRectangle method is:
4791%
4792% void XHighlightRectangle(Display *display,Window window,
4793% GC annotate_context,const RectangleInfo *highlight_info)
4794%
4795% A description of each parameter follows:
4796%
4797% o display: Specifies a connection to an X server; returned from
4798% XOpenDisplay.
4799%
4800% o window: Specifies a pointer to a Window structure.
4801%
4802% o annotate_context: Specifies a pointer to a GC structure.
4803%
4804% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4805% contains the extents of any highlighting rectangle.
4806%
4807*/
cristybcbda3f2011-09-03 13:01:22 +00004808MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004809 GC annotate_context,const RectangleInfo *highlight_info)
4810{
4811 assert(display != (Display *) NULL);
4812 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4813 assert(window != (Window) NULL);
4814 assert(annotate_context != (GC) NULL);
4815 assert(highlight_info != (RectangleInfo *) NULL);
4816 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4817 return;
4818 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4819 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4820 (unsigned int) highlight_info->height-1);
4821 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4822 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4823 (unsigned int) highlight_info->height-3);
4824}
4825
4826/*
4827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4828% %
4829% %
4830% %
4831% X I m p o r t I m a g e %
4832% %
4833% %
4834% %
4835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4836%
4837% XImportImage() reads an image from an X window.
4838%
4839% The format of the XImportImage method is:
4840%
4841% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4842%
4843% A description of each parameter follows:
4844%
4845% o image_info: the image info.
4846%
4847% o ximage_info: Specifies a pointer to an XImportInfo structure.
4848%
4849*/
4850MagickExport Image *XImportImage(const ImageInfo *image_info,
4851 XImportInfo *ximage_info)
4852{
4853 Colormap
4854 *colormaps;
4855
4856 Display
4857 *display;
4858
4859 Image
4860 *image;
4861
4862 int
4863 number_colormaps,
4864 number_windows,
4865 x;
4866
4867 RectangleInfo
4868 crop_info;
4869
4870 Status
4871 status;
4872
4873 Window
4874 *children,
4875 client,
4876 prior_target,
4877 root,
4878 target;
4879
4880 XTextProperty
4881 window_name;
4882
4883 /*
4884 Open X server connection.
4885 */
4886 assert(image_info != (const ImageInfo *) NULL);
4887 assert(image_info->signature == MagickSignature);
4888 if (image_info->debug != MagickFalse)
4889 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4890 image_info->filename);
4891 assert(ximage_info != (XImportInfo *) NULL);
4892 display=XOpenDisplay(image_info->server_name);
4893 if (display == (Display *) NULL)
4894 {
4895 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4896 XDisplayName(image_info->server_name));
4897 return((Image *) NULL);
4898 }
4899 /*
4900 Set our forgiving exception handler.
4901 */
4902 (void) XSetErrorHandler(XError);
4903 /*
4904 Select target window.
4905 */
4906 crop_info.x=0;
4907 crop_info.y=0;
4908 crop_info.width=0;
4909 crop_info.height=0;
4910 root=XRootWindow(display,XDefaultScreen(display));
4911 target=(Window) NULL;
4912 if ((image_info->filename != (char *) NULL) &&
4913 (*image_info->filename != '\0'))
4914 {
4915 if (LocaleCompare(image_info->filename,"root") == 0)
4916 target=root;
4917 else
4918 {
4919 /*
4920 Select window by ID or name.
4921 */
4922 if (isdigit((unsigned char) *image_info->filename) != 0)
4923 target=XWindowByID(display,root,(Window)
4924 strtol(image_info->filename,(char **) NULL,0));
4925 if (target == (Window) NULL)
4926 target=XWindowByName(display,root,image_info->filename);
4927 if (target == (Window) NULL)
4928 ThrowXWindowFatalException(XServerError,
4929 "NoWindowWithSpecifiedIDExists",image_info->filename);
4930 }
4931 }
4932 /*
4933 If target window is not defined, interactively select one.
4934 */
4935 prior_target=target;
4936 if (target == (Window) NULL)
4937 target=XSelectWindow(display,&crop_info);
4938 if (target == (Window) NULL)
4939 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4940 image_info->filename);
4941 client=target; /* obsolete */
4942 if (target != root)
4943 {
4944 unsigned int
4945 d;
4946
4947 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4948 if (status != False)
4949 {
4950 for ( ; ; )
4951 {
4952 Window
4953 parent;
4954
4955 /*
4956 Find window manager frame.
4957 */
4958 status=XQueryTree(display,target,&root,&parent,&children,&d);
4959 if ((status != False) && (children != (Window *) NULL))
4960 (void) XFree((char *) children);
4961 if ((status == False) || (parent == (Window) NULL) ||
4962 (parent == root))
4963 break;
4964 target=parent;
4965 }
4966 /*
4967 Get client window.
4968 */
4969 client=XClientWindow(display,target);
4970 if (ximage_info->frame == MagickFalse)
4971 target=client;
4972 if ((ximage_info->frame == MagickFalse) &&
4973 (prior_target != MagickFalse))
4974 target=prior_target;
4975 XDelay(display,SuspendTime << 4);
4976 }
4977 }
4978 if (ximage_info->screen)
4979 {
4980 int
4981 y;
4982
4983 Window
4984 child;
4985
4986 XWindowAttributes
4987 window_attributes;
4988
4989 /*
4990 Obtain window image directly from screen.
4991 */
4992 status=XGetWindowAttributes(display,target,&window_attributes);
4993 if (status == False)
4994 {
4995 ThrowXWindowFatalException(XServerError,
4996 "UnableToReadXWindowAttributes",image_info->filename);
4997 (void) XCloseDisplay(display);
4998 return((Image *) NULL);
4999 }
5000 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005001 crop_info.x=(ssize_t) x;
5002 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005003 crop_info.width=(size_t) window_attributes.width;
5004 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005005 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005006 {
5007 /*
5008 Include border in image.
5009 */
5010 crop_info.x-=window_attributes.border_width;
5011 crop_info.y-=window_attributes.border_width;
5012 crop_info.width+=window_attributes.border_width << 1;
5013 crop_info.height+=window_attributes.border_width << 1;
5014 }
5015 target=root;
5016 }
5017 /*
5018 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5019 */
5020 number_windows=0;
5021 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5022 if ((status == True) && (number_windows > 0))
5023 {
5024 ximage_info->descend=MagickTrue;
5025 (void) XFree ((char *) children);
5026 }
5027 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5028 if (number_colormaps > 0)
5029 {
5030 if (number_colormaps > 1)
5031 ximage_info->descend=MagickTrue;
5032 (void) XFree((char *) colormaps);
5033 }
5034 /*
5035 Alert the user not to alter the screen.
5036 */
5037 if (ximage_info->silent == MagickFalse)
5038 (void) XBell(display,0);
5039 /*
5040 Get image by window id.
5041 */
5042 (void) XGrabServer(display);
5043 image=XGetWindowImage(display,target,ximage_info->borders,
5044 ximage_info->descend ? 1U : 0U);
5045 (void) XUngrabServer(display);
5046 if (image == (Image *) NULL)
5047 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5048 image_info->filename)
5049 else
5050 {
5051 (void) CopyMagickString(image->filename,image_info->filename,
5052 MaxTextExtent);
5053 if ((crop_info.width != 0) && (crop_info.height != 0))
5054 {
5055 Image
5056 *clone_image,
5057 *crop_image;
5058
5059 /*
5060 Crop image as defined by the cropping rectangle.
5061 */
5062 clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5063 if (clone_image != (Image *) NULL)
5064 {
5065 crop_image=CropImage(clone_image,&crop_info,&image->exception);
5066 if (crop_image != (Image *) NULL)
5067 {
5068 image=DestroyImage(image);
5069 image=crop_image;
5070 }
5071 }
5072 }
5073 status=XGetWMName(display,target,&window_name);
5074 if (status == True)
5075 {
5076 if ((image_info->filename != (char *) NULL) &&
5077 (*image_info->filename == '\0'))
5078 (void) CopyMagickString(image->filename,(char *) window_name.value,
5079 (size_t) window_name.nitems+1);
5080 (void) XFree((void *) window_name.value);
5081 }
5082 }
5083 if (ximage_info->silent == MagickFalse)
5084 {
5085 /*
5086 Alert the user we're done.
5087 */
5088 (void) XBell(display,0);
5089 (void) XBell(display,0);
5090 }
5091 (void) XCloseDisplay(display);
5092 return(image);
5093}
5094
5095/*
5096%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5097% %
5098% %
5099% %
5100% X I n i t i a l i z e W i n d o w s %
5101% %
5102% %
5103% %
5104%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5105%
5106% XInitializeWindows() initializes the XWindows structure.
5107%
5108% The format of the XInitializeWindows method is:
5109%
5110% XWindows *XInitializeWindows(Display *display,
5111% XResourceInfo *resource_info)
5112%
5113% A description of each parameter follows:
5114%
5115% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5116%
5117% o display: Specifies a connection to an X server; returned from
5118% XOpenDisplay.
5119%
5120% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5121%
5122*/
cristybcbda3f2011-09-03 13:01:22 +00005123MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005124 XResourceInfo *resource_info)
5125{
5126 Window
5127 root_window;
5128
5129 XWindows
5130 *windows;
5131
5132 /*
5133 Allocate windows structure.
5134 */
cristy73bd4a52010-10-05 11:24:23 +00005135 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005136 if (windows == (XWindows *) NULL)
5137 {
5138 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5139 "...");
5140 return((XWindows *) NULL);
5141 }
5142 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5143 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5144 sizeof(*windows->pixel_info));
5145 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5146 sizeof(*windows->icon_pixel));
5147 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5148 sizeof(*windows->icon_resources));
5149 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5150 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5151 (windows->icon_resources == (XResourceInfo *) NULL))
5152 {
5153 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5154 "...");
5155 return((XWindows *) NULL);
5156 }
5157 /*
5158 Initialize windows structure.
5159 */
5160 windows->display=display;
5161 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5162 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5163 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5164 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5165 windows->im_remote_command=
5166 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5167 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5168 windows->im_update_colormap=
5169 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5170 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5171 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5172 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5173 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5174 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005175#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005176 (void) XSynchronize(display,IsWindows95());
5177#endif
5178 if (IsEventLogging())
5179 {
5180 (void) XSynchronize(display,MagickTrue);
5181 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005182 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005183 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5184 (void) LogMagickEvent(X11Event,GetMagickModule(),
5185 " Window Manager: 0x%lx",windows->wm_protocols);
5186 (void) LogMagickEvent(X11Event,GetMagickModule(),
5187 " delete window: 0x%lx",windows->wm_delete_window);
5188 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5189 windows->wm_take_focus);
5190 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5191 windows->im_protocols);
5192 (void) LogMagickEvent(X11Event,GetMagickModule(),
5193 " remote command: 0x%lx",windows->im_remote_command);
5194 (void) LogMagickEvent(X11Event,GetMagickModule(),
5195 " update widget: 0x%lx",windows->im_update_widget);
5196 (void) LogMagickEvent(X11Event,GetMagickModule(),
5197 " update colormap: 0x%lx",windows->im_update_colormap);
5198 (void) LogMagickEvent(X11Event,GetMagickModule(),
5199 " former image: 0x%lx",windows->im_former_image);
5200 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5201 windows->im_next_image);
5202 (void) LogMagickEvent(X11Event,GetMagickModule(),
5203 " retain colors: 0x%lx",windows->im_retain_colors);
5204 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5205 windows->im_exit);
5206 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5207 windows->dnd_protocols);
5208 }
5209 /*
5210 Allocate standard colormap.
5211 */
5212 windows->map_info=XAllocStandardColormap();
5213 windows->icon_map=XAllocStandardColormap();
5214 if ((windows->map_info == (XStandardColormap *) NULL) ||
5215 (windows->icon_map == (XStandardColormap *) NULL))
5216 ThrowXWindowFatalException(ResourceLimitFatalError,
5217 "MemoryAllocationFailed","...");
5218 windows->map_info->colormap=(Colormap) NULL;
5219 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005220 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005221 windows->pixel_info->annotate_context=(GC) NULL;
5222 windows->pixel_info->highlight_context=(GC) NULL;
5223 windows->pixel_info->widget_context=(GC) NULL;
5224 windows->font_info=(XFontStruct *) NULL;
5225 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005226 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005227 /*
5228 Allocate visual.
5229 */
5230 *windows->icon_resources=(*resource_info);
5231 windows->icon_resources->visual_type=(char *) "default";
5232 windows->icon_resources->colormap=SharedColormap;
5233 windows->visual_info=
5234 XBestVisualInfo(display,windows->map_info,resource_info);
5235 windows->icon_visual=
5236 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5237 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5238 (windows->icon_visual == (XVisualInfo *) NULL))
5239 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5240 resource_info->visual_type);
5241 if (IsEventLogging())
5242 {
5243 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5244 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5245 windows->visual_info->visualid);
5246 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5247 XVisualClassName(windows->visual_info->klass));
5248 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5249 windows->visual_info->depth);
5250 (void) LogMagickEvent(X11Event,GetMagickModule(),
5251 " size of colormap: %d entries",windows->visual_info->colormap_size);
5252 (void) LogMagickEvent(X11Event,GetMagickModule(),
5253 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5254 windows->visual_info->red_mask,windows->visual_info->green_mask,
5255 windows->visual_info->blue_mask);
5256 (void) LogMagickEvent(X11Event,GetMagickModule(),
5257 " significant bits in color: %d bits",
5258 windows->visual_info->bits_per_rgb);
5259 }
5260 /*
5261 Allocate class and manager hints.
5262 */
5263 windows->class_hints=XAllocClassHint();
5264 windows->manager_hints=XAllocWMHints();
5265 if ((windows->class_hints == (XClassHint *) NULL) ||
5266 (windows->manager_hints == (XWMHints *) NULL))
5267 ThrowXWindowFatalException(ResourceLimitFatalError,
5268 "MemoryAllocationFailed","...");
5269 /*
5270 Determine group leader if we have one.
5271 */
5272 root_window=XRootWindow(display,windows->visual_info->screen);
5273 windows->group_leader.id=(Window) NULL;
5274 if (resource_info->window_group != (char *) NULL)
5275 {
5276 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5277 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5278 strtol((char *) resource_info->window_group,(char **) NULL,0));
5279 if (windows->group_leader.id == (Window) NULL)
5280 windows->group_leader.id=
5281 XWindowByName(display,root_window,resource_info->window_group);
5282 }
5283 return(windows);
5284}
5285
5286/*
5287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5288% %
5289% %
5290% %
5291% X M a k e C u r s o r %
5292% %
5293% %
5294% %
5295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5296%
5297% XMakeCursor() creates a crosshairs X11 cursor.
5298%
5299% The format of the XMakeCursor method is:
5300%
5301% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5302% char *background_color,char *foreground_color)
5303%
5304% A description of each parameter follows:
5305%
5306% o display: Specifies a connection to an X server; returned from
5307% XOpenDisplay.
5308%
5309% o window: Specifies the ID of the window for which the cursor is
5310% assigned.
5311%
5312% o colormap: Specifies the ID of the colormap from which the background
5313% and foreground color will be retrieved.
5314%
5315% o background_color: Specifies the color to use for the cursor background.
5316%
5317% o foreground_color: Specifies the color to use for the cursor foreground.
5318%
5319*/
cristybcbda3f2011-09-03 13:01:22 +00005320MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005321 Colormap colormap,char *background_color,char *foreground_color)
5322{
5323#define scope_height 17
5324#define scope_x_hot 8
5325#define scope_y_hot 8
5326#define scope_width 17
5327
5328 static const unsigned char
5329 scope_bits[] =
5330 {
5331 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5332 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5333 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5334 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5335 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5336 },
5337 scope_mask_bits[] =
5338 {
5339 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5340 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5341 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5342 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5343 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5344 };
5345
5346 Cursor
5347 cursor;
5348
5349 Pixmap
5350 mask,
5351 source;
5352
5353 XColor
5354 background,
5355 foreground;
5356
5357 assert(display != (Display *) NULL);
5358 assert(window != (Window) NULL);
5359 assert(colormap != (Colormap) NULL);
5360 assert(background_color != (char *) NULL);
5361 assert(foreground_color != (char *) NULL);
5362 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5363 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5364 scope_height);
5365 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5366 scope_width,scope_height);
5367 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5368 {
5369 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5370 return((Cursor) NULL);
5371 }
5372 (void) XParseColor(display,colormap,background_color,&background);
5373 (void) XParseColor(display,colormap,foreground_color,&foreground);
5374 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5375 scope_x_hot,scope_y_hot);
5376 (void) XFreePixmap(display,source);
5377 (void) XFreePixmap(display,mask);
5378 return(cursor);
5379}
5380
5381/*
5382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5383% %
5384% %
5385% %
5386% X M a k e I m a g e %
5387% %
5388% %
5389% %
5390%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5391%
5392% XMakeImage() creates an X11 image. If the image size differs from the X11
5393% image size, the image is first resized.
5394%
5395% The format of the XMakeImage method is:
5396%
5397% MagickBooleanType XMakeImage(Display *display,
5398% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005399% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005400%
5401% A description of each parameter follows:
5402%
5403% o display: Specifies a connection to an X server; returned from
5404% XOpenDisplay.
5405%
5406% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5407%
5408% o window: Specifies a pointer to a XWindowInfo structure.
5409%
5410% o image: the image.
5411%
5412% o width: Specifies the width in pixels of the rectangular area to
5413% display.
5414%
5415% o height: Specifies the height in pixels of the rectangular area to
5416% display.
5417%
cristy051718b2011-08-28 22:49:25 +00005418% o exception: return any errors or warnings in this structure.
5419%
cristy3ed852e2009-09-05 21:47:34 +00005420*/
cristybcbda3f2011-09-03 13:01:22 +00005421MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005422 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005423 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005424{
5425#define CheckOverflowException(length,width,height) \
5426 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5427
5428 int
5429 depth,
5430 format;
5431
5432 size_t
5433 length;
5434
5435 XImage
5436 *matte_image,
5437 *ximage;
5438
5439 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5440 assert(display != (Display *) NULL);
5441 assert(resource_info != (XResourceInfo *) NULL);
5442 assert(window != (XWindowInfo *) NULL);
5443 assert(width != 0);
5444 assert(height != 0);
5445 if ((window->width == 0) || (window->height == 0))
5446 return(MagickFalse);
5447 /*
5448 Apply user transforms to the image.
5449 */
5450 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5451 (void) XFlush(display);
5452 depth=(int) window->depth;
5453 if (window->destroy)
5454 window->image=DestroyImage(window->image);
5455 window->image=image;
5456 window->destroy=MagickFalse;
5457 if (window->image != (Image *) NULL)
5458 {
5459 if (window->crop_geometry != (char *) NULL)
5460 {
5461 Image
5462 *crop_image;
5463
5464 RectangleInfo
5465 crop_info;
5466
5467 /*
5468 Crop image.
5469 */
5470 window->image->page.x=0;
5471 window->image->page.y=0;
5472 (void) ParsePageGeometry(window->image,window->crop_geometry,
5473 &crop_info,&image->exception);
5474 crop_image=CropImage(window->image,&crop_info,&image->exception);
5475 if (crop_image != (Image *) NULL)
5476 {
5477 if (window->image != image)
5478 window->image=DestroyImage(window->image);
5479 window->image=crop_image;
5480 window->destroy=MagickTrue;
5481 }
5482 }
5483 if ((width != (unsigned int) window->image->columns) ||
5484 (height != (unsigned int) window->image->rows))
5485 {
5486 Image
5487 *resize_image;
5488
5489 /*
5490 Resize image.
5491 */
5492 resize_image=NewImageList();
5493 if (window->pixel_info->colors != 0)
5494 resize_image=SampleImage(window->image,width,height,
5495 &image->exception);
5496 else
5497 resize_image=ThumbnailImage(window->image,width,height,
5498 &image->exception);
5499 if (resize_image != (Image *) NULL)
5500 {
5501 if (window->image != image)
5502 window->image=DestroyImage(window->image);
5503 window->image=resize_image;
5504 window->destroy=MagickTrue;
5505 }
5506 }
5507 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005508 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005509 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005510 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005511 }
5512 /*
5513 Create X image.
5514 */
5515 ximage=(XImage *) NULL;
5516 format=(depth == 1) ? XYBitmap : ZPixmap;
5517#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5518 if (window->shared_memory != MagickFalse)
5519 {
5520 XShmSegmentInfo
5521 *segment_info;
5522
5523 segment_info=(XShmSegmentInfo *) window->segment_info;
5524 segment_info[1].shmid=(-1);
5525 segment_info[1].shmaddr=(char *) NULL;
5526 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5527 (char *) NULL,&segment_info[1],width,height);
5528 if (ximage == (XImage *) NULL)
5529 window->shared_memory=MagickFalse;
5530 length=(size_t) ximage->bytes_per_line*ximage->height;
5531 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5532 window->shared_memory=MagickFalse;
5533 if (window->shared_memory != MagickFalse)
5534 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5535 if (window->shared_memory != MagickFalse)
5536 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5537 if (segment_info[1].shmid < 0)
5538 window->shared_memory=MagickFalse;
5539 if (window->shared_memory != MagickFalse)
5540 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5541 else
5542 {
5543 if (ximage != (XImage *) NULL)
5544 XDestroyImage(ximage);
5545 ximage=(XImage *) NULL;
5546 if (segment_info[1].shmaddr)
5547 {
5548 (void) shmdt(segment_info[1].shmaddr);
5549 segment_info[1].shmaddr=(char *) NULL;
5550 }
5551 if (segment_info[1].shmid >= 0)
5552 {
5553 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5554 segment_info[1].shmid=(-1);
5555 }
5556 }
5557 }
5558#endif
5559 /*
5560 Allocate X image pixel data.
5561 */
5562#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5563 if (window->shared_memory)
5564 {
5565 Status
5566 status;
5567
5568 XShmSegmentInfo
5569 *segment_info;
5570
5571 (void) XSync(display,MagickFalse);
5572 xerror_alert=MagickFalse;
5573 segment_info=(XShmSegmentInfo *) window->segment_info;
5574 ximage->data=segment_info[1].shmaddr;
5575 segment_info[1].readOnly=MagickFalse;
5576 status=XShmAttach(display,&segment_info[1]);
5577 if (status != False)
5578 (void) XSync(display,MagickFalse);
5579 if ((status == False) || (xerror_alert != MagickFalse))
5580 {
5581 window->shared_memory=MagickFalse;
5582 if (status != False)
5583 XShmDetach(display,&segment_info[1]);
5584 if (ximage != (XImage *) NULL)
5585 {
5586 ximage->data=NULL;
5587 XDestroyImage(ximage);
5588 ximage=(XImage *) NULL;
5589 }
5590 if (segment_info[1].shmid >= 0)
5591 {
5592 if (segment_info[1].shmaddr != NULL)
5593 (void) shmdt(segment_info[1].shmaddr);
5594 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5595 segment_info[1].shmid=(-1);
5596 segment_info[1].shmaddr=(char *) NULL;
5597 }
5598 }
5599 }
5600#endif
5601 if (window->shared_memory == MagickFalse)
5602 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5603 (char *) NULL,width,height,XBitmapPad(display),0);
5604 if (ximage == (XImage *) NULL)
5605 {
5606 /*
5607 Unable to create X image.
5608 */
5609 (void) XCheckDefineCursor(display,window->id,window->cursor);
5610 return(MagickFalse);
5611 }
5612 length=(size_t) ximage->bytes_per_line*ximage->height;
5613 if (IsEventLogging())
5614 {
5615 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5616 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5617 ximage->width,ximage->height);
5618 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5619 ximage->format);
5620 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5621 ximage->byte_order);
5622 (void) LogMagickEvent(X11Event,GetMagickModule(),
5623 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5624 ximage->bitmap_bit_order,ximage->bitmap_pad);
5625 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5626 ximage->depth);
5627 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5628 ximage->bytes_per_line);
5629 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5630 ximage->bits_per_pixel);
5631 (void) LogMagickEvent(X11Event,GetMagickModule(),
5632 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5633 ximage->green_mask,ximage->blue_mask);
5634 }
5635 if (window->shared_memory == MagickFalse)
5636 {
5637 if (ximage->format != XYBitmap)
5638 ximage->data=(char *) AcquireQuantumMemory((size_t)
5639 ximage->bytes_per_line,(size_t) ximage->height);
5640 else
5641 ximage->data=(char *) AcquireQuantumMemory((size_t)
5642 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5643 }
5644 if (ximage->data == (char *) NULL)
5645 {
5646 /*
5647 Unable to allocate pixel data.
5648 */
5649 XDestroyImage(ximage);
5650 ximage=(XImage *) NULL;
5651 (void) XCheckDefineCursor(display,window->id,window->cursor);
5652 return(MagickFalse);
5653 }
5654 if (window->ximage != (XImage *) NULL)
5655 {
5656 /*
5657 Destroy previous X image.
5658 */
5659 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5660#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5661 if (window->segment_info != (XShmSegmentInfo *) NULL)
5662 {
5663 XShmSegmentInfo
5664 *segment_info;
5665
5666 segment_info=(XShmSegmentInfo *) window->segment_info;
5667 if (segment_info[0].shmid >= 0)
5668 {
5669 (void) XSync(display,MagickFalse);
5670 (void) XShmDetach(display,&segment_info[0]);
5671 (void) XSync(display,MagickFalse);
5672 if (segment_info[0].shmaddr != (char *) NULL)
5673 (void) shmdt(segment_info[0].shmaddr);
5674 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5675 segment_info[0].shmid=(-1);
5676 segment_info[0].shmaddr=(char *) NULL;
5677 window->ximage->data=(char *) NULL;
5678 }
5679 }
5680#endif
5681 if (window->ximage->data != (char *) NULL)
5682 free(window->ximage->data);
5683 window->ximage->data=(char *) NULL;
5684 XDestroyImage(window->ximage);
5685 window->ximage=(XImage *) NULL;
5686 }
5687#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5688 if (window->segment_info != (XShmSegmentInfo *) NULL)
5689 {
5690 XShmSegmentInfo
5691 *segment_info;
5692
5693 segment_info=(XShmSegmentInfo *) window->segment_info;
5694 segment_info[0]=segment_info[1];
5695 }
5696#endif
5697 window->ximage=ximage;
5698 matte_image=(XImage *) NULL;
5699 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5700 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005701 ((int) width <= XDisplayWidth(display,window->screen)) &&
5702 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005703 {
5704 /*
5705 Create matte image.
5706 */
5707 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5708 (char *) NULL,width,height,XBitmapPad(display),0);
5709 if (IsEventLogging())
5710 {
5711 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5712 (void) LogMagickEvent(X11Event,GetMagickModule(),
5713 " width, height: %dx%d",matte_image->width,matte_image->height);
5714 }
5715 if (matte_image != (XImage *) NULL)
5716 {
5717 /*
5718 Allocate matte image pixel data.
5719 */
5720 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5721 matte_image->bytes_per_line*matte_image->depth,
5722 (size_t) matte_image->height);
5723 if (matte_image->data == (char *) NULL)
5724 {
5725 XDestroyImage(matte_image);
5726 matte_image=(XImage *) NULL;
5727 }
5728 }
5729 }
5730 if (window->matte_image != (XImage *) NULL)
5731 {
5732 /*
5733 Free matte image.
5734 */
5735 if (window->matte_image->data != (char *) NULL)
5736 free(window->matte_image->data);
5737 window->matte_image->data=(char *) NULL;
5738 XDestroyImage(window->matte_image);
5739 window->matte_image=(XImage *) NULL;
5740 }
5741 window->matte_image=matte_image;
5742 if (window->matte_pixmap != (Pixmap) NULL)
5743 {
5744 (void) XFreePixmap(display,window->matte_pixmap);
5745 window->matte_pixmap=(Pixmap) NULL;
5746#if defined(MAGICKCORE_HAVE_SHAPE)
5747 if (window->shape != MagickFalse)
5748 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5749#endif
5750 }
5751 window->stasis=MagickFalse;
5752 /*
5753 Convert pixels to X image data.
5754 */
5755 if (window->image != (Image *) NULL)
5756 {
5757 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5758 (ximage->bitmap_bit_order == LSBFirst)))
5759 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5760 matte_image);
5761 else
5762 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5763 matte_image);
5764 }
5765 if (window->matte_image != (XImage *) NULL)
5766 {
5767 /*
5768 Create matte pixmap.
5769 */
5770 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5771 if (window->matte_pixmap != (Pixmap) NULL)
5772 {
5773 GC
5774 graphics_context;
5775
5776 XGCValues
5777 context_values;
5778
5779 /*
5780 Copy matte image to matte pixmap.
5781 */
cristy4c08aed2011-07-01 19:47:50 +00005782 context_values.background=0;
5783 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005784 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005785 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005786 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5787 window->matte_image,0,0,0,0,width,height);
5788 (void) XFreeGC(display,graphics_context);
5789#if defined(MAGICKCORE_HAVE_SHAPE)
5790 if (window->shape != MagickFalse)
5791 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5792 window->matte_pixmap,ShapeSet);
5793#endif
5794 }
5795 }
5796 (void) XMakePixmap(display,resource_info,window);
5797 /*
5798 Restore cursor.
5799 */
5800 (void) XCheckDefineCursor(display,window->id,window->cursor);
5801 return(MagickTrue);
5802}
5803
5804/*
5805%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5806% %
5807% %
5808% %
5809+ X M a k e I m a g e L S B F i r s t %
5810% %
5811% %
5812% %
5813%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5814%
5815% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5816% pixels are copied in least-significant bit and byte first order. The
5817% server's scanline pad is respected. Rather than using one or two general
5818% cases, many special cases are found here to help speed up the image
5819% conversion.
5820%
5821% The format of the XMakeImageLSBFirst method is:
5822%
5823% void XMakeImageLSBFirst(Display *display,XWindows *windows)
5824%
5825% A description of each parameter follows:
5826%
5827% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5828%
5829% o window: Specifies a pointer to a XWindowInfo structure.
5830%
5831% o image: the image.
5832%
5833% o ximage: Specifies a pointer to a XImage structure; returned from
5834% XCreateImage.
5835%
5836% o matte_image: Specifies a pointer to a XImage structure; returned from
5837% XCreateImage.
5838%
5839*/
5840static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5841 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5842{
cristyc57f6942010-11-12 01:47:39 +00005843 CacheView
5844 *canvas_view;
5845
cristy3ed852e2009-09-05 21:47:34 +00005846 Image
5847 *canvas;
5848
5849 int
5850 y;
5851
cristy4c08aed2011-07-01 19:47:50 +00005852 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005853 *p;
5854
5855 register int
5856 x;
5857
5858 register unsigned char
5859 *q;
5860
5861 unsigned char
5862 bit,
5863 byte;
5864
5865 unsigned int
5866 scanline_pad;
5867
cristyf2faecf2010-05-28 19:19:36 +00005868 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005869 pixel,
5870 *pixels;
5871
5872 XStandardColormap
5873 *map_info;
5874
5875 assert(resource_info != (XResourceInfo *) NULL);
5876 assert(window != (XWindowInfo *) NULL);
5877 assert(image != (Image *) NULL);
5878 if (image->debug != MagickFalse)
5879 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5880 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005881 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005882 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005883 {
5884 char
5885 size[MaxTextExtent];
5886
5887 Image
5888 *pattern;
5889
5890 ImageInfo
5891 *image_info;
5892
5893 image_info=AcquireImageInfo();
5894 (void) CopyMagickString(image_info->filename,
5895 resource_info->image_info->texture != (char *) NULL ?
5896 resource_info->image_info->texture : "pattern:checkerboard",
5897 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005898 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005899 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005900 image_info->size=ConstantString(size);
5901 pattern=ReadImage(image_info,&image->exception);
5902 image_info=DestroyImageInfo(image_info);
5903 if (pattern != (Image *) NULL)
5904 {
5905 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5906 if (canvas != (Image *) NULL)
5907 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5908 pattern=DestroyImage(pattern);
5909 }
5910 }
5911 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5912 ximage->bits_per_pixel) >> 3));
5913 map_info=window->map_info;
5914 pixels=window->pixel_info->pixels;
5915 q=(unsigned char *) ximage->data;
5916 x=0;
cristyc57f6942010-11-12 01:47:39 +00005917 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005918 if (ximage->format == XYBitmap)
5919 {
5920 register unsigned short
5921 polarity;
5922
5923 unsigned char
5924 background,
5925 foreground;
5926
5927 /*
5928 Convert canvas to big-endian bitmap.
5929 */
5930 background=(unsigned char)
5931 (XPixelIntensity(&window->pixel_info->foreground_color) <
5932 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5933 foreground=(unsigned char)
5934 (XPixelIntensity(&window->pixel_info->background_color) <
5935 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00005936 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005937 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5938 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00005939 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
5940 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005941 for (y=0; y < (int) canvas->rows; y++)
5942 {
cristyc57f6942010-11-12 01:47:39 +00005943 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5944 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005945 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005946 break;
cristy3ed852e2009-09-05 21:47:34 +00005947 bit=0;
5948 byte=0;
5949 for (x=0; x < (int) canvas->columns; x++)
5950 {
5951 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005952 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005953 byte|=foreground;
5954 else
5955 byte|=background;
5956 bit++;
5957 if (bit == 8)
5958 {
5959 *q++=byte;
5960 bit=0;
5961 byte=0;
5962 }
cristyed231572011-07-14 02:18:59 +00005963 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005964 }
5965 if (bit != 0)
5966 *q=byte >> (8-bit);
5967 q+=scanline_pad;
5968 }
5969 }
5970 else
5971 if (window->pixel_info->colors != 0)
5972 switch (ximage->bits_per_pixel)
5973 {
5974 case 2:
5975 {
5976 register unsigned int
5977 nibble;
5978
5979 /*
5980 Convert to 2 bit color-mapped X canvas.
5981 */
5982 for (y=0; y < (int) canvas->rows; y++)
5983 {
cristyc57f6942010-11-12 01:47:39 +00005984 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5985 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005986 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005987 break;
cristy3ed852e2009-09-05 21:47:34 +00005988 nibble=0;
5989 for (x=0; x < (int) canvas->columns; x++)
5990 {
cristy4c08aed2011-07-01 19:47:50 +00005991 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00005992 switch (nibble)
5993 {
5994 case 0:
5995 {
5996 *q=(unsigned char) pixel;
5997 nibble++;
5998 break;
5999 }
6000 case 1:
6001 {
6002 *q|=(unsigned char) (pixel << 2);
6003 nibble++;
6004 break;
6005 }
6006 case 2:
6007 {
6008 *q|=(unsigned char) (pixel << 4);
6009 nibble++;
6010 break;
6011 }
6012 case 3:
6013 {
6014 *q|=(unsigned char) (pixel << 6);
6015 q++;
6016 nibble=0;
6017 break;
6018 }
6019 }
cristyed231572011-07-14 02:18:59 +00006020 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006021 }
6022 q+=scanline_pad;
6023 }
6024 break;
6025 }
6026 case 4:
6027 {
6028 register unsigned int
6029 nibble;
6030
6031 /*
6032 Convert to 4 bit color-mapped X canvas.
6033 */
6034 for (y=0; y < (int) canvas->rows; y++)
6035 {
cristyc57f6942010-11-12 01:47:39 +00006036 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6037 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006038 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006039 break;
cristy3ed852e2009-09-05 21:47:34 +00006040 nibble=0;
6041 for (x=0; x < (int) canvas->columns; x++)
6042 {
cristy4c08aed2011-07-01 19:47:50 +00006043 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006044 switch (nibble)
6045 {
6046 case 0:
6047 {
6048 *q=(unsigned char) pixel;
6049 nibble++;
6050 break;
6051 }
6052 case 1:
6053 {
6054 *q|=(unsigned char) (pixel << 4);
6055 q++;
6056 nibble=0;
6057 break;
6058 }
6059 }
cristyed231572011-07-14 02:18:59 +00006060 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006061 }
6062 q+=scanline_pad;
6063 }
6064 break;
6065 }
6066 case 6:
6067 case 8:
6068 {
6069 /*
6070 Convert to 8 bit color-mapped X canvas.
6071 */
6072 if (resource_info->color_recovery &&
6073 resource_info->quantize_info->dither)
6074 {
6075 XDitherImage(canvas,ximage);
6076 break;
6077 }
6078 for (y=0; y < (int) canvas->rows; y++)
6079 {
cristyc57f6942010-11-12 01:47:39 +00006080 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6081 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006082 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006083 break;
cristy3ed852e2009-09-05 21:47:34 +00006084 for (x=0; x < (int) canvas->columns; x++)
6085 {
cristy4c08aed2011-07-01 19:47:50 +00006086 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006087 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006088 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006089 }
6090 q+=scanline_pad;
6091 }
6092 break;
6093 }
6094 default:
6095 {
6096 register int
6097 k;
6098
6099 register unsigned int
6100 bytes_per_pixel;
6101
6102 unsigned char
cristybb503372010-05-27 20:51:26 +00006103 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006104
6105 /*
6106 Convert to multi-byte color-mapped X canvas.
6107 */
6108 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6109 for (y=0; y < (int) canvas->rows; y++)
6110 {
cristyc57f6942010-11-12 01:47:39 +00006111 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6112 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006113 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006114 break;
cristy3ed852e2009-09-05 21:47:34 +00006115 for (x=0; x < (int) canvas->columns; x++)
6116 {
cristy4c08aed2011-07-01 19:47:50 +00006117 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006118 for (k=0; k < (int) bytes_per_pixel; k++)
6119 {
6120 channel[k]=(unsigned char) pixel;
6121 pixel>>=8;
6122 }
6123 for (k=0; k < (int) bytes_per_pixel; k++)
6124 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006125 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006126 }
6127 q+=scanline_pad;
6128 }
6129 break;
6130 }
6131 }
6132 else
6133 switch (ximage->bits_per_pixel)
6134 {
6135 case 2:
6136 {
6137 register unsigned int
6138 nibble;
6139
6140 /*
6141 Convert to contiguous 2 bit continuous-tone X canvas.
6142 */
6143 for (y=0; y < (int) canvas->rows; y++)
6144 {
6145 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006146 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6147 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006148 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006149 break;
6150 for (x=0; x < (int) canvas->columns; x++)
6151 {
cristy4c08aed2011-07-01 19:47:50 +00006152 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006153 pixel&=0xf;
6154 switch (nibble)
6155 {
6156 case 0:
6157 {
6158 *q=(unsigned char) pixel;
6159 nibble++;
6160 break;
6161 }
6162 case 1:
6163 {
6164 *q|=(unsigned char) (pixel << 2);
6165 nibble++;
6166 break;
6167 }
6168 case 2:
6169 {
6170 *q|=(unsigned char) (pixel << 4);
6171 nibble++;
6172 break;
6173 }
6174 case 3:
6175 {
6176 *q|=(unsigned char) (pixel << 6);
6177 q++;
6178 nibble=0;
6179 break;
6180 }
6181 }
cristyed231572011-07-14 02:18:59 +00006182 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006183 }
6184 q+=scanline_pad;
6185 }
6186 break;
6187 }
6188 case 4:
6189 {
6190 register unsigned int
6191 nibble;
6192
6193 /*
6194 Convert to contiguous 4 bit continuous-tone X canvas.
6195 */
6196 for (y=0; y < (int) canvas->rows; y++)
6197 {
cristyc57f6942010-11-12 01:47:39 +00006198 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6199 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006200 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006201 break;
6202 nibble=0;
6203 for (x=0; x < (int) canvas->columns; x++)
6204 {
cristy4c08aed2011-07-01 19:47:50 +00006205 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006206 pixel&=0xf;
6207 switch (nibble)
6208 {
6209 case 0:
6210 {
6211 *q=(unsigned char) pixel;
6212 nibble++;
6213 break;
6214 }
6215 case 1:
6216 {
6217 *q|=(unsigned char) (pixel << 4);
6218 q++;
6219 nibble=0;
6220 break;
6221 }
6222 }
cristyed231572011-07-14 02:18:59 +00006223 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006224 }
6225 q+=scanline_pad;
6226 }
6227 break;
6228 }
6229 case 6:
6230 case 8:
6231 {
6232 /*
6233 Convert to contiguous 8 bit continuous-tone X canvas.
6234 */
6235 if (resource_info->color_recovery &&
6236 resource_info->quantize_info->dither)
6237 {
6238 XDitherImage(canvas,ximage);
6239 break;
6240 }
6241 for (y=0; y < (int) canvas->rows; y++)
6242 {
cristyc57f6942010-11-12 01:47:39 +00006243 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6244 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006245 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006246 break;
6247 for (x=0; x < (int) canvas->columns; x++)
6248 {
cristy4c08aed2011-07-01 19:47:50 +00006249 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006250 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006251 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006252 }
6253 q+=scanline_pad;
6254 }
6255 break;
6256 }
6257 default:
6258 {
6259 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6260 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6261 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6262 (map_info->blue_mult == 1))
6263 {
6264 /*
6265 Convert to 32 bit continuous-tone X canvas.
6266 */
6267 for (y=0; y < (int) canvas->rows; y++)
6268 {
cristyc57f6942010-11-12 01:47:39 +00006269 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6270 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006271 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006272 break;
6273 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6274 (blue_gamma != 1.0))
6275 {
6276 /*
6277 Gamma correct canvas.
6278 */
6279 for (x=(int) canvas->columns-1; x >= 0; x--)
6280 {
cristyccf844f2010-02-03 23:28:16 +00006281 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006282 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006283 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006284 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006285 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006286 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006287 *q++=0;
cristyed231572011-07-14 02:18:59 +00006288 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006289 }
6290 continue;
6291 }
6292 for (x=(int) canvas->columns-1; x >= 0; x--)
6293 {
cristy4c08aed2011-07-01 19:47:50 +00006294 *q++=ScaleQuantumToChar((Quantum)
6295 GetPixelBlue(canvas,p));
6296 *q++=ScaleQuantumToChar((Quantum)
6297 GetPixelGreen(canvas,p));
6298 *q++=ScaleQuantumToChar((Quantum)
6299 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006300 *q++=0;
cristyed231572011-07-14 02:18:59 +00006301 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006302 }
6303 }
6304 }
6305 else
6306 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6307 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6308 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6309 (map_info->blue_mult == 65536L))
6310 {
6311 /*
6312 Convert to 32 bit continuous-tone X canvas.
6313 */
6314 for (y=0; y < (int) canvas->rows; y++)
6315 {
cristyc57f6942010-11-12 01:47:39 +00006316 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6317 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006318 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006319 break;
6320 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6321 (blue_gamma != 1.0))
6322 {
6323 /*
6324 Gamma correct canvas.
6325 */
6326 for (x=(int) canvas->columns-1; x >= 0; x--)
6327 {
cristyccf844f2010-02-03 23:28:16 +00006328 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006329 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006330 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006331 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006332 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006333 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006334 *q++=0;
cristyed231572011-07-14 02:18:59 +00006335 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006336 }
6337 continue;
6338 }
6339 for (x=(int) canvas->columns-1; x >= 0; x--)
6340 {
cristyccf844f2010-02-03 23:28:16 +00006341 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006342 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006343 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006344 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006345 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006346 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006347 *q++=0;
cristyed231572011-07-14 02:18:59 +00006348 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006349 }
6350 }
6351 }
6352 else
6353 {
6354 register int
6355 k;
6356
6357 register unsigned int
6358 bytes_per_pixel;
6359
6360 unsigned char
cristybb503372010-05-27 20:51:26 +00006361 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006362
6363 /*
6364 Convert to multi-byte continuous-tone X canvas.
6365 */
6366 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6367 for (y=0; y < (int) canvas->rows; y++)
6368 {
cristyc57f6942010-11-12 01:47:39 +00006369 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6370 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006371 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006372 break;
cristyc57f6942010-11-12 01:47:39 +00006373 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006374 {
cristy4c08aed2011-07-01 19:47:50 +00006375 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006376 for (k=0; k < (int) bytes_per_pixel; k++)
6377 {
6378 channel[k]=(unsigned char) pixel;
6379 pixel>>=8;
6380 }
6381 for (k=0; k < (int) bytes_per_pixel; k++)
6382 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006383 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006384 }
6385 q+=scanline_pad;
6386 }
6387 }
6388 break;
6389 }
6390 }
6391 if (matte_image != (XImage *) NULL)
6392 {
6393 /*
6394 Initialize matte canvas.
6395 */
6396 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6397 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6398 q=(unsigned char *) matte_image->data;
6399 for (y=0; y < (int) canvas->rows; y++)
6400 {
cristyc57f6942010-11-12 01:47:39 +00006401 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6402 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006403 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006404 break;
6405 bit=0;
6406 byte=0;
6407 for (x=(int) canvas->columns-1; x >= 0; x--)
6408 {
6409 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006410 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006411 byte|=0x80;
6412 bit++;
6413 if (bit == 8)
6414 {
6415 *q++=byte;
6416 bit=0;
6417 byte=0;
6418 }
cristyed231572011-07-14 02:18:59 +00006419 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006420 }
6421 if (bit != 0)
6422 *q=byte >> (8-bit);
6423 q+=scanline_pad;
6424 }
6425 }
cristyc57f6942010-11-12 01:47:39 +00006426 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006427 if (canvas != image)
6428 canvas=DestroyImage(canvas);
6429}
6430
6431/*
6432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6433% %
6434% %
6435% %
6436+ X M a k e I m a g e M S B F i r s t %
6437% %
6438% %
6439% %
6440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6441%
6442% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6443% image pixels are copied in most-significant bit and byte first order. The
6444% server's scanline pad is also respected. Rather than using one or two
6445% general cases, many special cases are found here to help speed up the image
6446% conversion.
6447%
6448% The format of the XMakeImageMSBFirst method is:
6449%
6450% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6451%
6452% A description of each parameter follows:
6453%
6454% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6455%
6456% o window: Specifies a pointer to a XWindowInfo structure.
6457%
6458% o image: the image.
6459%
6460% o ximage: Specifies a pointer to a XImage structure; returned from
6461% XCreateImage.
6462%
6463% o matte_image: Specifies a pointer to a XImage structure; returned from
6464% XCreateImage.
6465%
cristy3ed852e2009-09-05 21:47:34 +00006466*/
6467static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6468 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6469{
cristyc57f6942010-11-12 01:47:39 +00006470 CacheView
6471 *canvas_view;
6472
cristy3ed852e2009-09-05 21:47:34 +00006473 Image
6474 *canvas;
6475
6476 int
6477 y;
6478
6479 register int
6480 x;
6481
cristy4c08aed2011-07-01 19:47:50 +00006482 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006483 *p;
6484
6485 register unsigned char
6486 *q;
6487
6488 unsigned char
6489 bit,
6490 byte;
6491
6492 unsigned int
6493 scanline_pad;
6494
cristyf2faecf2010-05-28 19:19:36 +00006495 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006496 pixel,
6497 *pixels;
6498
6499 XStandardColormap
6500 *map_info;
6501
6502 assert(resource_info != (XResourceInfo *) NULL);
6503 assert(window != (XWindowInfo *) NULL);
6504 assert(image != (Image *) NULL);
6505 if (image->debug != MagickFalse)
6506 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6507 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006508 if ((window->immutable != MagickFalse) &&
6509 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006510 {
6511 char
6512 size[MaxTextExtent];
6513
6514 Image
6515 *pattern;
6516
6517 ImageInfo
6518 *image_info;
6519
6520 image_info=AcquireImageInfo();
6521 (void) CopyMagickString(image_info->filename,
6522 resource_info->image_info->texture != (char *) NULL ?
6523 resource_info->image_info->texture : "pattern:checkerboard",
6524 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006525 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006526 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006527 image_info->size=ConstantString(size);
6528 pattern=ReadImage(image_info,&image->exception);
6529 image_info=DestroyImageInfo(image_info);
6530 if (pattern != (Image *) NULL)
6531 {
6532 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6533 if (canvas != (Image *) NULL)
6534 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6535 pattern=DestroyImage(pattern);
6536 }
6537 }
cristy4c08aed2011-07-01 19:47:50 +00006538 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6539 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006540 map_info=window->map_info;
6541 pixels=window->pixel_info->pixels;
6542 q=(unsigned char *) ximage->data;
6543 x=0;
cristyc57f6942010-11-12 01:47:39 +00006544 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006545 if (ximage->format == XYBitmap)
6546 {
6547 register unsigned short
6548 polarity;
6549
6550 unsigned char
6551 background,
6552 foreground;
6553
6554 /*
6555 Convert canvas to big-endian bitmap.
6556 */
6557 background=(unsigned char)
6558 (XPixelIntensity(&window->pixel_info->foreground_color) <
6559 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6560 foreground=(unsigned char)
6561 (XPixelIntensity(&window->pixel_info->background_color) <
6562 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00006563 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006564 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6565 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00006566 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
6567 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006568 for (y=0; y < (int) canvas->rows; y++)
6569 {
cristyc57f6942010-11-12 01:47:39 +00006570 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6571 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006572 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006573 break;
cristy3ed852e2009-09-05 21:47:34 +00006574 bit=0;
6575 byte=0;
6576 for (x=(int) canvas->columns-1; x >= 0; x--)
6577 {
6578 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006579 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006580 byte|=foreground;
6581 else
6582 byte|=background;
6583 bit++;
6584 if (bit == 8)
6585 {
6586 *q++=byte;
6587 bit=0;
6588 byte=0;
6589 }
cristyed231572011-07-14 02:18:59 +00006590 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006591 }
6592 if (bit != 0)
6593 *q=byte << (8-bit);
6594 q+=scanline_pad;
6595 }
6596 }
6597 else
6598 if (window->pixel_info->colors != 0)
6599 switch (ximage->bits_per_pixel)
6600 {
6601 case 2:
6602 {
6603 register unsigned int
6604 nibble;
6605
6606 /*
6607 Convert to 2 bit color-mapped X canvas.
6608 */
6609 for (y=0; y < (int) canvas->rows; y++)
6610 {
cristyc57f6942010-11-12 01:47:39 +00006611 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6612 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006613 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006614 break;
cristy3ed852e2009-09-05 21:47:34 +00006615 nibble=0;
6616 for (x=0; x < (int) canvas->columns; x++)
6617 {
cristy4c08aed2011-07-01 19:47:50 +00006618 pixel=pixels[(ssize_t)
6619 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006620 switch (nibble)
6621 {
6622 case 0:
6623 {
6624 *q=(unsigned char) (pixel << 6);
6625 nibble++;
6626 break;
6627 }
6628 case 1:
6629 {
6630 *q|=(unsigned char) (pixel << 4);
6631 nibble++;
6632 break;
6633 }
6634 case 2:
6635 {
6636 *q|=(unsigned char) (pixel << 2);
6637 nibble++;
6638 break;
6639 }
6640 case 3:
6641 {
6642 *q|=(unsigned char) pixel;
6643 q++;
6644 nibble=0;
6645 break;
6646 }
6647 }
cristyed231572011-07-14 02:18:59 +00006648 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006649 }
6650 q+=scanline_pad;
6651 }
6652 break;
6653 }
6654 case 4:
6655 {
6656 register unsigned int
6657 nibble;
6658
6659 /*
6660 Convert to 4 bit color-mapped X canvas.
6661 */
6662 for (y=0; y < (int) canvas->rows; y++)
6663 {
cristyc57f6942010-11-12 01:47:39 +00006664 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6665 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006666 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006667 break;
cristy3ed852e2009-09-05 21:47:34 +00006668 nibble=0;
6669 for (x=0; x < (int) canvas->columns; x++)
6670 {
cristy4c08aed2011-07-01 19:47:50 +00006671 pixel=pixels[(ssize_t)
6672 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006673 switch (nibble)
6674 {
6675 case 0:
6676 {
6677 *q=(unsigned char) (pixel << 4);
6678 nibble++;
6679 break;
6680 }
6681 case 1:
6682 {
6683 *q|=(unsigned char) pixel;
6684 q++;
6685 nibble=0;
6686 break;
6687 }
6688 }
cristyed231572011-07-14 02:18:59 +00006689 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006690 }
6691 q+=scanline_pad;
6692 }
6693 break;
6694 }
6695 case 6:
6696 case 8:
6697 {
6698 /*
6699 Convert to 8 bit color-mapped X canvas.
6700 */
6701 if (resource_info->color_recovery &&
6702 resource_info->quantize_info->dither)
6703 {
6704 XDitherImage(canvas,ximage);
6705 break;
6706 }
6707 for (y=0; y < (int) canvas->rows; y++)
6708 {
cristyc57f6942010-11-12 01:47:39 +00006709 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6710 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006711 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006712 break;
cristy3ed852e2009-09-05 21:47:34 +00006713 for (x=0; x < (int) canvas->columns; x++)
6714 {
cristy4c08aed2011-07-01 19:47:50 +00006715 pixel=pixels[(ssize_t)
6716 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006717 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006718 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006719 }
6720 q+=scanline_pad;
6721 }
6722 break;
6723 }
6724 default:
6725 {
6726 register int
6727 k;
6728
6729 register unsigned int
6730 bytes_per_pixel;
6731
6732 unsigned char
cristybb503372010-05-27 20:51:26 +00006733 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006734
6735 /*
6736 Convert to 8 bit color-mapped X canvas.
6737 */
6738 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6739 for (y=0; y < (int) canvas->rows; y++)
6740 {
cristyc57f6942010-11-12 01:47:39 +00006741 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6742 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006743 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006744 break;
cristy3ed852e2009-09-05 21:47:34 +00006745 for (x=0; x < (int) canvas->columns; x++)
6746 {
cristy4c08aed2011-07-01 19:47:50 +00006747 pixel=pixels[(ssize_t)
6748 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006749 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6750 {
6751 channel[k]=(unsigned char) pixel;
6752 pixel>>=8;
6753 }
6754 for (k=0; k < (int) bytes_per_pixel; k++)
6755 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006756 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006757 }
6758 q+=scanline_pad;
6759 }
6760 break;
6761 }
6762 }
6763 else
6764 switch (ximage->bits_per_pixel)
6765 {
6766 case 2:
6767 {
6768 register unsigned int
6769 nibble;
6770
6771 /*
6772 Convert to 4 bit continuous-tone X canvas.
6773 */
6774 for (y=0; y < (int) canvas->rows; y++)
6775 {
cristyc57f6942010-11-12 01:47:39 +00006776 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6777 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006778 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006779 break;
6780 nibble=0;
6781 for (x=(int) canvas->columns-1; x >= 0; x--)
6782 {
cristy4c08aed2011-07-01 19:47:50 +00006783 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006784 pixel&=0xf;
6785 switch (nibble)
6786 {
6787 case 0:
6788 {
6789 *q=(unsigned char) (pixel << 6);
6790 nibble++;
6791 break;
6792 }
6793 case 1:
6794 {
6795 *q|=(unsigned char) (pixel << 4);
6796 nibble++;
6797 break;
6798 }
6799 case 2:
6800 {
6801 *q|=(unsigned char) (pixel << 2);
6802 nibble++;
6803 break;
6804 }
6805 case 3:
6806 {
6807 *q|=(unsigned char) pixel;
6808 q++;
6809 nibble=0;
6810 break;
6811 }
6812 }
cristyed231572011-07-14 02:18:59 +00006813 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006814 }
6815 q+=scanline_pad;
6816 }
6817 break;
6818 }
6819 case 4:
6820 {
6821 register unsigned int
6822 nibble;
6823
6824 /*
6825 Convert to 4 bit continuous-tone X canvas.
6826 */
6827 for (y=0; y < (int) canvas->rows; y++)
6828 {
cristyc57f6942010-11-12 01:47:39 +00006829 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6830 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006831 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006832 break;
6833 nibble=0;
6834 for (x=(int) canvas->columns-1; x >= 0; x--)
6835 {
cristy4c08aed2011-07-01 19:47:50 +00006836 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006837 pixel&=0xf;
6838 switch (nibble)
6839 {
6840 case 0:
6841 {
6842 *q=(unsigned char) (pixel << 4);
6843 nibble++;
6844 break;
6845 }
6846 case 1:
6847 {
6848 *q|=(unsigned char) pixel;
6849 q++;
6850 nibble=0;
6851 break;
6852 }
6853 }
cristyed231572011-07-14 02:18:59 +00006854 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006855 }
6856 q+=scanline_pad;
6857 }
6858 break;
6859 }
6860 case 6:
6861 case 8:
6862 {
6863 /*
6864 Convert to 8 bit continuous-tone X canvas.
6865 */
6866 if (resource_info->color_recovery &&
6867 resource_info->quantize_info->dither)
6868 {
6869 XDitherImage(canvas,ximage);
6870 break;
6871 }
6872 for (y=0; y < (int) canvas->rows; y++)
6873 {
cristyc57f6942010-11-12 01:47:39 +00006874 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6875 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006876 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006877 break;
6878 for (x=(int) canvas->columns-1; x >= 0; x--)
6879 {
cristy4c08aed2011-07-01 19:47:50 +00006880 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006881 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006882 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006883 }
6884 q+=scanline_pad;
6885 }
6886 break;
6887 }
6888 default:
6889 {
6890 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6891 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6892 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6893 (map_info->blue_mult == 1))
6894 {
6895 /*
6896 Convert to 32 bit continuous-tone X canvas.
6897 */
6898 for (y=0; y < (int) canvas->rows; y++)
6899 {
cristyc57f6942010-11-12 01:47:39 +00006900 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6901 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006902 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006903 break;
6904 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6905 (blue_gamma != 1.0))
6906 {
6907 /*
6908 Gamma correct canvas.
6909 */
6910 for (x=(int) canvas->columns-1; x >= 0; x--)
6911 {
6912 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006913 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006914 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006915 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006916 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006917 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006918 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006919 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006920 }
6921 continue;
6922 }
6923 for (x=(int) canvas->columns-1; x >= 0; x--)
6924 {
6925 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006926 *q++=ScaleQuantumToChar((Quantum)
6927 GetPixelRed(canvas,p));
6928 *q++=ScaleQuantumToChar((Quantum)
6929 GetPixelGreen(canvas,p));
6930 *q++=ScaleQuantumToChar((Quantum)
6931 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006932 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006933 }
6934 }
6935 }
6936 else
6937 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6938 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6939 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6940 (map_info->blue_mult == 65536L))
6941 {
6942 /*
6943 Convert to 32 bit continuous-tone X canvas.
6944 */
6945 for (y=0; y < (int) canvas->rows; y++)
6946 {
cristyc57f6942010-11-12 01:47:39 +00006947 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6948 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006949 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006950 break;
6951 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6952 (blue_gamma != 1.0))
6953 {
6954 /*
6955 Gamma correct canvas.
6956 */
6957 for (x=(int) canvas->columns-1; x >= 0; x--)
6958 {
6959 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006960 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006961 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006962 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006963 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006964 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006965 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006966 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006967 }
6968 continue;
6969 }
6970 for (x=(int) canvas->columns-1; x >= 0; x--)
6971 {
6972 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006973 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006974 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006975 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006976 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006977 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006978 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006979 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006980 }
6981 }
6982 }
6983 else
6984 {
6985 register int
6986 k;
6987
6988 register unsigned int
6989 bytes_per_pixel;
6990
6991 unsigned char
cristybb503372010-05-27 20:51:26 +00006992 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006993
6994 /*
6995 Convert to multi-byte continuous-tone X canvas.
6996 */
6997 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6998 for (y=0; y < (int) canvas->rows; y++)
6999 {
cristyc57f6942010-11-12 01:47:39 +00007000 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
7001 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007002 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007003 break;
7004 for (x=(int) canvas->columns-1; x >= 0; x--)
7005 {
cristy4c08aed2011-07-01 19:47:50 +00007006 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007007 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7008 {
7009 channel[k]=(unsigned char) pixel;
7010 pixel>>=8;
7011 }
7012 for (k=0; k < (int) bytes_per_pixel; k++)
7013 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007014 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007015 }
7016 q+=scanline_pad;
7017 }
7018 }
7019 break;
7020 }
7021 }
7022 if (matte_image != (XImage *) NULL)
7023 {
7024 /*
7025 Initialize matte canvas.
7026 */
7027 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7028 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7029 q=(unsigned char *) matte_image->data;
7030 for (y=0; y < (int) canvas->rows; y++)
7031 {
cristyc57f6942010-11-12 01:47:39 +00007032 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7033 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007034 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007035 break;
7036 bit=0;
7037 byte=0;
7038 for (x=(int) canvas->columns-1; x >= 0; x--)
7039 {
7040 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007041 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007042 byte|=0x01;
7043 bit++;
7044 if (bit == 8)
7045 {
7046 *q++=byte;
7047 bit=0;
7048 byte=0;
7049 }
cristyed231572011-07-14 02:18:59 +00007050 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007051 }
7052 if (bit != 0)
7053 *q=byte << (8-bit);
7054 q+=scanline_pad;
7055 }
7056 }
cristyc57f6942010-11-12 01:47:39 +00007057 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007058 if (canvas != image)
7059 canvas=DestroyImage(canvas);
7060}
7061
7062/*
7063%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7064% %
7065% %
7066% %
7067% X M a k e M a g n i f y I m a g e %
7068% %
7069% %
7070% %
7071%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7072%
7073% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7074%
7075% The format of the XMakeMagnifyImage method is:
7076%
7077% void XMakeMagnifyImage(display,windows)
7078%
7079% A description of each parameter follows:
7080%
7081% o display: Specifies a connection to an X server; returned from
7082% XOpenDisplay.
7083%
7084% o windows: Specifies a pointer to a XWindows structure.
7085%
7086*/
cristybcbda3f2011-09-03 13:01:22 +00007087MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00007088{
7089 char
7090 tuple[MaxTextExtent];
7091
7092 int
7093 y;
7094
cristy4c08aed2011-07-01 19:47:50 +00007095 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007096 pixel;
7097
7098 register int
7099 x;
7100
cristybb503372010-05-27 20:51:26 +00007101 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007102 i;
7103
7104 register unsigned char
7105 *p,
7106 *q;
7107
cristy9d314ff2011-03-09 01:30:28 +00007108 ssize_t
7109 n;
7110
cristy3ed852e2009-09-05 21:47:34 +00007111 static unsigned int
7112 previous_magnify = 0;
7113
7114 static XWindowInfo
7115 magnify_window;
7116
7117 unsigned int
7118 height,
7119 j,
7120 k,
7121 l,
7122 magnify,
7123 scanline_pad,
7124 width;
7125
7126 XImage
7127 *ximage;
7128
7129 /*
7130 Check boundary conditions.
7131 */
7132 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7133 assert(display != (Display *) NULL);
7134 assert(windows != (XWindows *) NULL);
7135 magnify=1;
cristybb503372010-05-27 20:51:26 +00007136 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007137 magnify<<=1;
7138 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7139 magnify<<=1;
7140 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7141 magnify<<=1;
7142 while (magnify > windows->magnify.width)
7143 magnify>>=1;
7144 while (magnify > windows->magnify.height)
7145 magnify>>=1;
7146 if (magnify != previous_magnify)
7147 {
7148 Status
7149 status;
7150
7151 XTextProperty
7152 window_name;
7153
7154 /*
7155 New magnify factor: update magnify window name.
7156 */
7157 i=0;
7158 while ((1 << i) <= (int) magnify)
7159 i++;
cristyb51dff52011-05-19 16:55:47 +00007160 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007161 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007162 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7163 if (status != False)
7164 {
7165 XSetWMName(display,windows->magnify.id,&window_name);
7166 XSetWMIconName(display,windows->magnify.id,&window_name);
7167 (void) XFree((void *) window_name.value);
7168 }
7169 }
7170 previous_magnify=magnify;
7171 ximage=windows->image.ximage;
7172 width=(unsigned int) windows->magnify.ximage->width;
7173 height=(unsigned int) windows->magnify.ximage->height;
7174 if ((windows->magnify.x < 0) ||
7175 (windows->magnify.x >= windows->image.ximage->width))
7176 windows->magnify.x=windows->image.ximage->width >> 1;
7177 x=windows->magnify.x-((width/magnify) >> 1);
7178 if (x < 0)
7179 x=0;
7180 else
7181 if (x > (int) (ximage->width-(width/magnify)))
7182 x=ximage->width-width/magnify;
7183 if ((windows->magnify.y < 0) ||
7184 (windows->magnify.y >= windows->image.ximage->height))
7185 windows->magnify.y=windows->image.ximage->height >> 1;
7186 y=windows->magnify.y-((height/magnify) >> 1);
7187 if (y < 0)
7188 y=0;
7189 else
7190 if (y > (int) (ximage->height-(height/magnify)))
7191 y=ximage->height-height/magnify;
7192 q=(unsigned char *) windows->magnify.ximage->data;
7193 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7194 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7195 if (ximage->bits_per_pixel < 8)
7196 {
7197 register unsigned char
7198 background,
7199 byte,
7200 foreground,
7201 p_bit,
7202 q_bit;
7203
7204 register unsigned int
7205 plane;
7206
7207 XPixelInfo
7208 *pixel_info;
7209
7210 pixel_info=windows->magnify.pixel_info;
7211 switch (ximage->bitmap_bit_order)
7212 {
7213 case LSBFirst:
7214 {
7215 /*
7216 Magnify little-endian bitmap.
7217 */
7218 background=0x00;
7219 foreground=0x80;
7220 if (ximage->format == XYBitmap)
7221 {
7222 background=(unsigned char)
7223 (XPixelIntensity(&pixel_info->foreground_color) <
7224 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7225 foreground=(unsigned char)
7226 (XPixelIntensity(&pixel_info->background_color) <
7227 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7228 if (windows->magnify.depth > 1)
7229 Swap(background,foreground);
7230 }
cristybb503372010-05-27 20:51:26 +00007231 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007232 {
7233 /*
7234 Propogate pixel magnify rows.
7235 */
7236 for (j=0; j < magnify; j++)
7237 {
7238 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7239 ((x*ximage->bits_per_pixel) >> 3);
7240 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7241 q_bit=0;
7242 byte=0;
7243 for (k=0; k < width; k+=magnify)
7244 {
7245 /*
7246 Propogate pixel magnify columns.
7247 */
7248 for (l=0; l < magnify; l++)
7249 {
7250 /*
7251 Propogate each bit plane.
7252 */
7253 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7254 {
7255 byte>>=1;
7256 if (*p & (0x01 << (p_bit+plane)))
7257 byte|=foreground;
7258 else
7259 byte|=background;
7260 q_bit++;
7261 if (q_bit == 8)
7262 {
7263 *q++=byte;
7264 q_bit=0;
7265 byte=0;
7266 }
7267 }
7268 }
7269 p_bit+=ximage->bits_per_pixel;
7270 if (p_bit == 8)
7271 {
7272 p++;
7273 p_bit=0;
7274 }
7275 if (q_bit != 0)
7276 *q=byte >> (8-q_bit);
7277 q+=scanline_pad;
7278 }
7279 }
7280 y++;
7281 }
7282 break;
7283 }
7284 case MSBFirst:
7285 default:
7286 {
7287 /*
7288 Magnify big-endian bitmap.
7289 */
7290 background=0x00;
7291 foreground=0x01;
7292 if (ximage->format == XYBitmap)
7293 {
7294 background=(unsigned char)
7295 (XPixelIntensity(&pixel_info->foreground_color) <
7296 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7297 foreground=(unsigned char)
7298 (XPixelIntensity(&pixel_info->background_color) <
7299 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7300 if (windows->magnify.depth > 1)
7301 Swap(background,foreground);
7302 }
cristybb503372010-05-27 20:51:26 +00007303 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007304 {
7305 /*
7306 Propogate pixel magnify rows.
7307 */
7308 for (j=0; j < magnify; j++)
7309 {
7310 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7311 ((x*ximage->bits_per_pixel) >> 3);
7312 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7313 q_bit=0;
7314 byte=0;
7315 for (k=0; k < width; k+=magnify)
7316 {
7317 /*
7318 Propogate pixel magnify columns.
7319 */
7320 for (l=0; l < magnify; l++)
7321 {
7322 /*
7323 Propogate each bit plane.
7324 */
7325 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7326 {
7327 byte<<=1;
7328 if (*p & (0x80 >> (p_bit+plane)))
7329 byte|=foreground;
7330 else
7331 byte|=background;
7332 q_bit++;
7333 if (q_bit == 8)
7334 {
7335 *q++=byte;
7336 q_bit=0;
7337 byte=0;
7338 }
7339 }
7340 }
7341 p_bit+=ximage->bits_per_pixel;
7342 if (p_bit == 8)
7343 {
7344 p++;
7345 p_bit=0;
7346 }
7347 if (q_bit != 0)
7348 *q=byte << (8-q_bit);
7349 q+=scanline_pad;
7350 }
7351 }
7352 y++;
7353 }
7354 break;
7355 }
7356 }
7357 }
7358 else
7359 switch (ximage->bits_per_pixel)
7360 {
7361 case 6:
7362 case 8:
7363 {
7364 /*
7365 Magnify 8 bit X image.
7366 */
cristybb503372010-05-27 20:51:26 +00007367 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007368 {
7369 /*
7370 Propogate pixel magnify rows.
7371 */
7372 for (j=0; j < magnify; j++)
7373 {
7374 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7375 ((x*ximage->bits_per_pixel) >> 3);
7376 for (k=0; k < width; k+=magnify)
7377 {
7378 /*
7379 Propogate pixel magnify columns.
7380 */
7381 for (l=0; l < magnify; l++)
7382 *q++=(*p);
7383 p++;
7384 }
7385 q+=scanline_pad;
7386 }
7387 y++;
7388 }
7389 break;
7390 }
7391 default:
7392 {
7393 register unsigned int
7394 bytes_per_pixel,
7395 m;
7396
7397 /*
7398 Magnify multi-byte X image.
7399 */
7400 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007401 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007402 {
7403 /*
7404 Propogate pixel magnify rows.
7405 */
7406 for (j=0; j < magnify; j++)
7407 {
7408 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7409 ((x*ximage->bits_per_pixel) >> 3);
7410 for (k=0; k < width; k+=magnify)
7411 {
7412 /*
7413 Propogate pixel magnify columns.
7414 */
7415 for (l=0; l < magnify; l++)
7416 for (m=0; m < bytes_per_pixel; m++)
7417 *q++=(*(p+m));
7418 p+=bytes_per_pixel;
7419 }
7420 q+=scanline_pad;
7421 }
7422 y++;
7423 }
7424 break;
7425 }
7426 }
7427 /*
7428 Copy X image to magnify pixmap.
7429 */
7430 x=windows->magnify.x-((width/magnify) >> 1);
7431 if (x < 0)
7432 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7433 else
7434 if (x > (int) (ximage->width-(width/magnify)))
7435 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7436 else
7437 x=0;
7438 y=windows->magnify.y-((height/magnify) >> 1);
7439 if (y < 0)
7440 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7441 else
7442 if (y > (int) (ximage->height-(height/magnify)))
7443 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7444 else
7445 y=0;
7446 if ((x != 0) || (y != 0))
7447 (void) XFillRectangle(display,windows->magnify.pixmap,
7448 windows->magnify.annotate_context,0,0,width,height);
7449 (void) XPutImage(display,windows->magnify.pixmap,
7450 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7451 height-y);
7452 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7453 (magnify <= (height >> 1))))
7454 {
7455 RectangleInfo
7456 highlight_info;
7457
7458 /*
7459 Highlight center pixel.
7460 */
cristybb503372010-05-27 20:51:26 +00007461 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7462 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007463 highlight_info.width=magnify;
7464 highlight_info.height=magnify;
7465 (void) XDrawRectangle(display,windows->magnify.pixmap,
7466 windows->magnify.highlight_context,(int) highlight_info.x,
7467 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7468 (unsigned int) highlight_info.height-1);
7469 if (magnify > 2)
7470 (void) XDrawRectangle(display,windows->magnify.pixmap,
7471 windows->magnify.annotate_context,(int) highlight_info.x+1,
7472 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7473 (unsigned int) highlight_info.height-3);
7474 }
7475 /*
7476 Show center pixel color.
7477 */
cristyc57f6942010-11-12 01:47:39 +00007478 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7479 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7480 &windows->image.image->exception);
cristyb51dff52011-05-19 16:55:47 +00007481 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007482 windows->magnify.x,windows->magnify.y);
7483 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007484 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007485 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007486 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007487 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007488 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007489 if (pixel.colorspace == CMYKColorspace)
7490 {
7491 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007492 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007493 }
7494 if (pixel.matte != MagickFalse)
7495 {
7496 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007497 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007498 }
7499 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7500 height=(unsigned int) windows->magnify.font_info->ascent+
7501 windows->magnify.font_info->descent;
7502 x=windows->magnify.font_info->max_bounds.width >> 1;
7503 y=windows->magnify.font_info->ascent+(height >> 2);
7504 (void) XDrawImageString(display,windows->magnify.pixmap,
7505 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7506 GetColorTuple(&pixel,MagickTrue,tuple);
7507 y+=height;
7508 (void) XDrawImageString(display,windows->magnify.pixmap,
7509 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7510 (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7511 &windows->image.image->exception);
7512 y+=height;
7513 (void) XDrawImageString(display,windows->magnify.pixmap,
7514 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7515 /*
7516 Refresh magnify window.
7517 */
7518 magnify_window=windows->magnify;
7519 magnify_window.x=0;
7520 magnify_window.y=0;
7521 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7522}
7523
7524/*
7525%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7526% %
7527% %
7528% %
7529% X M a k e P i x m a p %
7530% %
7531% %
7532% %
7533%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7534%
7535% XMakePixmap() creates an X11 pixmap.
7536%
7537% The format of the XMakePixmap method is:
7538%
7539% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7540% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7541% XPixelInfo *pixel)
7542%
7543% A description of each parameter follows:
7544%
7545% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7546%
7547% o display: Specifies a connection to an X server; returned from
7548% XOpenDisplay.
7549%
7550% o window: Specifies a pointer to a XWindowInfo structure.
7551%
cristy3ed852e2009-09-05 21:47:34 +00007552*/
7553static MagickBooleanType XMakePixmap(Display *display,
7554 const XResourceInfo *resource_info,XWindowInfo *window)
7555{
7556 unsigned int
7557 height,
7558 width;
7559
7560 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7561 assert(display != (Display *) NULL);
7562 assert(resource_info != (XResourceInfo *) NULL);
7563 assert(window != (XWindowInfo *) NULL);
7564 if (window->pixmap != (Pixmap) NULL)
7565 {
7566 /*
7567 Destroy previous X pixmap.
7568 */
7569 (void) XFreePixmap(display,window->pixmap);
7570 window->pixmap=(Pixmap) NULL;
7571 }
7572 if (window->use_pixmap == MagickFalse)
7573 return(MagickFalse);
7574 if (window->ximage == (XImage *) NULL)
7575 return(MagickFalse);
7576 /*
7577 Display busy cursor.
7578 */
7579 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7580 (void) XFlush(display);
7581 /*
7582 Create pixmap.
7583 */
7584 width=(unsigned int) window->ximage->width;
7585 height=(unsigned int) window->ximage->height;
7586 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7587 if (window->pixmap == (Pixmap) NULL)
7588 {
7589 /*
7590 Unable to allocate pixmap.
7591 */
7592 (void) XCheckDefineCursor(display,window->id,window->cursor);
7593 return(MagickFalse);
7594 }
7595 /*
7596 Copy X image to pixmap.
7597 */
7598#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7599 if (window->shared_memory)
7600 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7601 window->ximage,0,0,0,0,width,height,MagickTrue);
7602#endif
7603 if (window->shared_memory == MagickFalse)
7604 (void) XPutImage(display,window->pixmap,window->annotate_context,
7605 window->ximage,0,0,0,0,width,height);
7606 if (IsEventLogging())
7607 {
7608 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7609 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7610 width,height);
7611 }
7612 /*
7613 Restore cursor.
7614 */
7615 (void) XCheckDefineCursor(display,window->id,window->cursor);
7616 return(MagickTrue);
7617}
7618
7619/*
7620%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7621% %
7622% %
7623% %
7624% X M a k e S t a n d a r d C o l o r m a p %
7625% %
7626% %
7627% %
7628%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7629%
7630% XMakeStandardColormap() creates an X11 Standard Colormap.
7631%
7632% The format of the XMakeStandardColormap method is:
7633%
7634% XMakeStandardColormap(display,visual_info,resource_info,image,
7635% map_info,pixel)
7636%
7637% A description of each parameter follows:
7638%
7639% o display: Specifies a connection to an X server; returned from
7640% XOpenDisplay.
7641%
7642% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7643% returned from XGetVisualInfo.
7644%
7645% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7646%
7647% o image: the image.
7648%
7649% o map_info: If a Standard Colormap type is specified, this structure is
7650% initialized with info from the Standard Colormap.
7651%
7652% o pixel: Specifies a pointer to a XPixelInfo structure.
7653%
cristy3ed852e2009-09-05 21:47:34 +00007654*/
7655
7656#if defined(__cplusplus) || defined(c_plusplus)
7657extern "C" {
7658#endif
7659
7660static inline MagickRealType DiversityPixelIntensity(
7661 const DiversityPacket *pixel)
7662{
7663 MagickRealType
7664 intensity;
7665
7666 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7667 return(intensity);
7668}
7669
7670static int IntensityCompare(const void *x,const void *y)
7671{
7672 DiversityPacket
7673 *color_1,
7674 *color_2;
7675
7676 int
7677 diversity;
7678
7679 color_1=(DiversityPacket *) x;
7680 color_2=(DiversityPacket *) y;
7681 diversity=(int) (DiversityPixelIntensity(color_2)-
7682 DiversityPixelIntensity(color_1));
7683 return(diversity);
7684}
7685
7686static int PopularityCompare(const void *x,const void *y)
7687{
7688 DiversityPacket
7689 *color_1,
7690 *color_2;
7691
7692 color_1=(DiversityPacket *) x;
7693 color_2=(DiversityPacket *) y;
7694 return((int) color_2->count-(int) color_1->count);
7695}
7696
7697#if defined(__cplusplus) || defined(c_plusplus)
7698}
7699#endif
7700
cristybb503372010-05-27 20:51:26 +00007701static inline Quantum ScaleXToQuantum(const size_t x,
7702 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007703{
7704 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7705}
7706
cristybcbda3f2011-09-03 13:01:22 +00007707MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007708 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7709 XStandardColormap *map_info,XPixelInfo *pixel)
7710{
7711 Colormap
7712 colormap;
7713
7714 ExceptionInfo
7715 *exception;
7716
cristybb503372010-05-27 20:51:26 +00007717 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007718 i;
7719
7720 Status
7721 status;
7722
cristybb503372010-05-27 20:51:26 +00007723 size_t
cristy3ed852e2009-09-05 21:47:34 +00007724 number_colors,
7725 retain_colors;
7726
7727 unsigned short
7728 gray_value;
7729
7730 XColor
7731 color,
7732 *colors,
7733 *p;
7734
7735 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7736 assert(display != (Display *) NULL);
7737 assert(visual_info != (XVisualInfo *) NULL);
7738 assert(map_info != (XStandardColormap *) NULL);
7739 assert(resource_info != (XResourceInfo *) NULL);
7740 assert(pixel != (XPixelInfo *) NULL);
7741 exception=(&image->exception);
7742 if (resource_info->map_type != (char *) NULL)
7743 {
7744 /*
7745 Standard Colormap is already defined (i.e. xstdcmap).
7746 */
cristy4c08aed2011-07-01 19:47:50 +00007747 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007748 pixel);
7749 number_colors=(unsigned int) (map_info->base_pixel+
7750 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7751 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7752 if ((image->matte == MagickFalse) &&
7753 (resource_info->color_recovery == MagickFalse) &&
7754 resource_info->quantize_info->dither &&
7755 (number_colors < MaxColormapSize))
7756 {
7757 Image
7758 *affinity_image;
7759
cristy4c08aed2011-07-01 19:47:50 +00007760 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007761 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007762
7763 /*
7764 Improve image appearance with error diffusion.
7765 */
7766 affinity_image=AcquireImage((ImageInfo *) NULL);
7767 if (affinity_image == (Image *) NULL)
7768 ThrowXWindowFatalException(ResourceLimitFatalError,
7769 "UnableToDitherImage",image->filename);
7770 affinity_image->columns=number_colors;
7771 affinity_image->rows=1;
7772 /*
7773 Initialize colormap image.
7774 */
7775 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7776 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007777 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007778 {
cristybb503372010-05-27 20:51:26 +00007779 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007780 {
cristy4c08aed2011-07-01 19:47:50 +00007781 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007782 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007783 SetPixelRed(affinity_image,
7784 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7785 map_info->red_max),q);
7786 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007787 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007788 SetPixelGreen(affinity_image,
7789 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7790 (map_info->green_max+1)),map_info->green_max),q);
7791 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007792 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007793 SetPixelBlue(affinity_image,
7794 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7795 map_info->blue_max),q);
7796 SetPixelAlpha(affinity_image,
7797 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007798 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007799 }
7800 (void) SyncAuthenticPixels(affinity_image,exception);
7801 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007802 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007803 }
cristy4c08aed2011-07-01 19:47:50 +00007804 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007805 pixel);
cristy574cc262011-08-05 01:23:58 +00007806 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007807 affinity_image=DestroyImage(affinity_image);
7808 }
7809 if (IsEventLogging())
7810 {
7811 (void) LogMagickEvent(X11Event,GetMagickModule(),
7812 "Standard Colormap:");
7813 (void) LogMagickEvent(X11Event,GetMagickModule(),
7814 " colormap id: 0x%lx",map_info->colormap);
7815 (void) LogMagickEvent(X11Event,GetMagickModule(),
7816 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7817 map_info->green_max,map_info->blue_max);
7818 (void) LogMagickEvent(X11Event,GetMagickModule(),
7819 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7820 map_info->green_mult,map_info->blue_mult);
7821 }
7822 return;
7823 }
7824 if ((visual_info->klass != DirectColor) &&
7825 (visual_info->klass != TrueColor))
7826 if ((image->storage_class == DirectClass) ||
7827 ((int) image->colors > visual_info->colormap_size))
7828 {
7829 QuantizeInfo
7830 quantize_info;
7831
7832 /*
7833 Image has more colors than the visual supports.
7834 */
7835 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007836 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007837 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007838 }
7839 /*
7840 Free previous and create new colormap.
7841 */
7842 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7843 colormap=XDefaultColormap(display,visual_info->screen);
7844 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7845 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7846 visual_info->visual,visual_info->klass == DirectColor ?
7847 AllocAll : AllocNone);
7848 if (colormap == (Colormap) NULL)
7849 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7850 image->filename);
7851 /*
7852 Initialize the map and pixel info structures.
7853 */
7854 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007855 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007856 /*
7857 Allocating colors in server colormap is based on visual class.
7858 */
7859 switch (visual_info->klass)
7860 {
7861 case StaticGray:
7862 case StaticColor:
7863 {
7864 /*
7865 Define Standard Colormap for StaticGray or StaticColor visual.
7866 */
7867 number_colors=image->colors;
7868 colors=(XColor *) AcquireQuantumMemory((size_t)
7869 visual_info->colormap_size,sizeof(*colors));
7870 if (colors == (XColor *) NULL)
7871 ThrowXWindowFatalException(ResourceLimitFatalError,
7872 "UnableToCreateColormap",image->filename);
7873 p=colors;
7874 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007875 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007876 {
7877 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7878 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7879 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7880 if (visual_info->klass != StaticColor)
7881 {
7882 gray_value=(unsigned short) XPixelIntensity(&color);
7883 color.red=gray_value;
7884 color.green=gray_value;
7885 color.blue=gray_value;
7886 }
7887 status=XAllocColor(display,colormap,&color);
7888 if (status == False)
7889 {
7890 colormap=XCopyColormapAndFree(display,colormap);
7891 (void) XAllocColor(display,colormap,&color);
7892 }
7893 pixel->pixels[i]=color.pixel;
7894 *p++=color;
7895 }
7896 break;
7897 }
7898 case GrayScale:
7899 case PseudoColor:
7900 {
7901 unsigned int
7902 colormap_type;
7903
7904 /*
7905 Define Standard Colormap for GrayScale or PseudoColor visual.
7906 */
7907 number_colors=image->colors;
7908 colors=(XColor *) AcquireQuantumMemory((size_t)
7909 visual_info->colormap_size,sizeof(*colors));
7910 if (colors == (XColor *) NULL)
7911 ThrowXWindowFatalException(ResourceLimitFatalError,
7912 "UnableToCreateColormap",image->filename);
7913 /*
7914 Preallocate our GUI colors.
7915 */
7916 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7917 (void) XAllocColor(display,colormap,&pixel->background_color);
7918 (void) XAllocColor(display,colormap,&pixel->border_color);
7919 (void) XAllocColor(display,colormap,&pixel->matte_color);
7920 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7921 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7922 (void) XAllocColor(display,colormap,&pixel->depth_color);
7923 (void) XAllocColor(display,colormap,&pixel->trough_color);
7924 for (i=0; i < MaxNumberPens; i++)
7925 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7926 /*
7927 Determine if image colors will "fit" into X server colormap.
7928 */
7929 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007930 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007931 NULL,0,pixel->pixels,(unsigned int) image->colors);
7932 if (status != False)
7933 colormap_type=PrivateColormap;
7934 if (colormap_type == SharedColormap)
7935 {
cristyc57f6942010-11-12 01:47:39 +00007936 CacheView
7937 *image_view;
7938
cristy3ed852e2009-09-05 21:47:34 +00007939 DiversityPacket
7940 *diversity;
7941
7942 int
7943 y;
7944
7945 register int
7946 x;
7947
7948 unsigned short
7949 index;
7950
7951 XColor
7952 *server_colors;
7953
7954 /*
7955 Define Standard colormap for shared GrayScale or PseudoColor visual.
7956 */
7957 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7958 sizeof(*diversity));
7959 if (diversity == (DiversityPacket *) NULL)
7960 ThrowXWindowFatalException(ResourceLimitFatalError,
7961 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007962 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007963 {
7964 diversity[i].red=image->colormap[i].red;
7965 diversity[i].green=image->colormap[i].green;
7966 diversity[i].blue=image->colormap[i].blue;
7967 diversity[i].index=(unsigned short) i;
7968 diversity[i].count=0;
7969 }
cristyc57f6942010-11-12 01:47:39 +00007970 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00007971 for (y=0; y < (int) image->rows; y++)
7972 {
cristyc57f6942010-11-12 01:47:39 +00007973 register int
cristy3ed852e2009-09-05 21:47:34 +00007974 x;
7975
cristy4c08aed2011-07-01 19:47:50 +00007976 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007977 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007978
cristyc57f6942010-11-12 01:47:39 +00007979 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7980 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007981 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007982 break;
cristyc57f6942010-11-12 01:47:39 +00007983 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00007984 {
7985 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00007986 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00007987 }
cristy3ed852e2009-09-05 21:47:34 +00007988 }
cristyc57f6942010-11-12 01:47:39 +00007989 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00007990 /*
7991 Sort colors by decreasing intensity.
7992 */
7993 qsort((void *) diversity,image->colors,sizeof(*diversity),
7994 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00007995 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00007996 {
7997 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00007998 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00007999 }
8000 diversity[image->colors-1].count<<=4;
8001 qsort((void *) diversity,image->colors,sizeof(*diversity),
8002 PopularityCompare);
8003 /*
8004 Allocate colors.
8005 */
8006 p=colors;
8007 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008008 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008009 {
8010 index=diversity[i].index;
8011 color.red=
8012 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8013 color.green=
8014 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8015 color.blue=
8016 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8017 if (visual_info->klass != PseudoColor)
8018 {
8019 gray_value=(unsigned short) XPixelIntensity(&color);
8020 color.red=gray_value;
8021 color.green=gray_value;
8022 color.blue=gray_value;
8023 }
8024 status=XAllocColor(display,colormap,&color);
8025 if (status == False)
8026 break;
8027 pixel->pixels[index]=color.pixel;
8028 *p++=color;
8029 }
8030 /*
8031 Read X server colormap.
8032 */
8033 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8034 visual_info->colormap_size,sizeof(*server_colors));
8035 if (server_colors == (XColor *) NULL)
8036 ThrowXWindowFatalException(ResourceLimitFatalError,
8037 "UnableToCreateColormap",image->filename);
8038 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008039 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008040 (void) XQueryColors(display,colormap,server_colors,
8041 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8042 /*
8043 Select remaining colors from X server colormap.
8044 */
cristybb503372010-05-27 20:51:26 +00008045 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008046 {
8047 index=diversity[i].index;
8048 color.red=
8049 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8050 color.green=
8051 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8052 color.blue=
8053 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8054 if (visual_info->klass != PseudoColor)
8055 {
8056 gray_value=(unsigned short) XPixelIntensity(&color);
8057 color.red=gray_value;
8058 color.green=gray_value;
8059 color.blue=gray_value;
8060 }
8061 XBestPixel(display,colormap,server_colors,(unsigned int)
8062 visual_info->colormap_size,&color);
8063 pixel->pixels[index]=color.pixel;
8064 *p++=color;
8065 }
8066 if ((int) image->colors < visual_info->colormap_size)
8067 {
8068 /*
8069 Fill up colors array-- more choices for pen colors.
8070 */
8071 retain_colors=MagickMin((unsigned int)
8072 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008073 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008074 *p++=server_colors[i];
8075 number_colors+=retain_colors;
8076 }
8077 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8078 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8079 break;
8080 }
8081 /*
8082 Define Standard colormap for private GrayScale or PseudoColor visual.
8083 */
8084 if (status == False)
8085 {
8086 /*
8087 Not enough colormap entries in the colormap-- Create a new colormap.
8088 */
8089 colormap=XCreateColormap(display,
8090 XRootWindow(display,visual_info->screen),visual_info->visual,
8091 AllocNone);
8092 if (colormap == (Colormap) NULL)
8093 ThrowXWindowFatalException(ResourceLimitFatalError,
8094 "UnableToCreateColormap",image->filename);
8095 map_info->colormap=colormap;
8096 if ((int) image->colors < visual_info->colormap_size)
8097 {
8098 /*
8099 Retain colors from the default colormap to help lessens the
8100 effects of colormap flashing.
8101 */
8102 retain_colors=MagickMin((unsigned int)
8103 (visual_info->colormap_size-image->colors),256);
8104 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008105 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008106 {
cristyc57f6942010-11-12 01:47:39 +00008107 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008108 p++;
8109 }
8110 (void) XQueryColors(display,
8111 XDefaultColormap(display,visual_info->screen),
8112 colors+image->colors,(int) retain_colors);
8113 /*
8114 Transfer colors from default to private colormap.
8115 */
8116 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008117 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008118 retain_colors);
8119 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008120 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008121 {
8122 p->pixel=pixel->pixels[i];
8123 p++;
8124 }
8125 (void) XStoreColors(display,colormap,colors+image->colors,
8126 (int) retain_colors);
8127 number_colors+=retain_colors;
8128 }
8129 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008130 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008131 image->colors);
8132 }
8133 /*
8134 Store the image colormap.
8135 */
8136 p=colors;
8137 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008138 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008139 {
8140 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8141 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8142 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8143 if (visual_info->klass != PseudoColor)
8144 {
8145 gray_value=(unsigned short) XPixelIntensity(&color);
8146 color.red=gray_value;
8147 color.green=gray_value;
8148 color.blue=gray_value;
8149 }
8150 color.pixel=pixel->pixels[i];
8151 *p++=color;
8152 }
8153 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8154 break;
8155 }
8156 case TrueColor:
8157 case DirectColor:
8158 default:
8159 {
8160 MagickBooleanType
8161 linear_colormap;
8162
8163 /*
8164 Define Standard Colormap for TrueColor or DirectColor visual.
8165 */
8166 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8167 (map_info->green_max*map_info->green_mult)+
8168 (map_info->blue_max*map_info->blue_mult)+1);
8169 linear_colormap=(number_colors > 4096) ||
8170 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8171 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8172 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8173 MagickTrue : MagickFalse;
8174 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008175 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008176 /*
8177 Allocate color array.
8178 */
8179 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8180 if (colors == (XColor *) NULL)
8181 ThrowXWindowFatalException(ResourceLimitFatalError,
8182 "UnableToCreateColormap",image->filename);
8183 /*
8184 Initialize linear color ramp.
8185 */
8186 p=colors;
8187 color.flags=(char) (DoRed | DoGreen | DoBlue);
8188 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008189 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008190 {
8191 color.blue=(unsigned short) 0;
8192 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008193 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008194 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8195 color.green=color.blue;
8196 color.red=color.blue;
8197 color.pixel=XStandardPixel(map_info,&color);
8198 *p++=color;
8199 }
8200 else
cristybb503372010-05-27 20:51:26 +00008201 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008202 {
8203 color.red=(unsigned short) 0;
8204 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008205 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008206 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8207 color.green=(unsigned int) 0;
8208 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008209 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008210 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8211 map_info->green_max));
8212 color.blue=(unsigned short) 0;
8213 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008214 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008215 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8216 color.pixel=XStandardPixel(map_info,&color);
8217 *p++=color;
8218 }
8219 if ((visual_info->klass == DirectColor) &&
8220 (colormap != XDefaultColormap(display,visual_info->screen)))
8221 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8222 else
cristybb503372010-05-27 20:51:26 +00008223 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008224 (void) XAllocColor(display,colormap,&colors[i]);
8225 break;
8226 }
8227 }
8228 if ((visual_info->klass != DirectColor) &&
8229 (visual_info->klass != TrueColor))
8230 {
8231 /*
8232 Set foreground, background, border, etc. pixels.
8233 */
8234 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8235 &pixel->foreground_color);
8236 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8237 &pixel->background_color);
8238 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8239 {
8240 /*
8241 Foreground and background colors must differ.
8242 */
8243 pixel->background_color.red=(~pixel->foreground_color.red);
8244 pixel->background_color.green=
8245 (~pixel->foreground_color.green);
8246 pixel->background_color.blue=
8247 (~pixel->foreground_color.blue);
8248 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8249 &pixel->background_color);
8250 }
8251 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8252 &pixel->border_color);
8253 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8254 &pixel->matte_color);
8255 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8256 &pixel->highlight_color);
8257 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8258 &pixel->shadow_color);
8259 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8260 &pixel->depth_color);
8261 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8262 &pixel->trough_color);
8263 for (i=0; i < MaxNumberPens; i++)
8264 {
8265 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8266 &pixel->pen_colors[i]);
8267 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8268 }
cristyc57f6942010-11-12 01:47:39 +00008269 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008270 }
8271 colors=(XColor *) RelinquishMagickMemory(colors);
8272 if (IsEventLogging())
8273 {
8274 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8275 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8276 map_info->colormap);
8277 (void) LogMagickEvent(X11Event,GetMagickModule(),
8278 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8279 map_info->green_max,map_info->blue_max);
8280 (void) LogMagickEvent(X11Event,GetMagickModule(),
8281 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8282 map_info->green_mult,map_info->blue_mult);
8283 }
8284}
8285
8286/*
8287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8288% %
8289% %
8290% %
8291% X M a k e W i n d o w %
8292% %
8293% %
8294% %
8295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8296%
8297% XMakeWindow() creates an X11 window.
8298%
8299% The format of the XMakeWindow method is:
8300%
8301% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8302% XClassHint *class_hint,XWMHints *manager_hints,
8303% XWindowInfo *window_info)
8304%
8305% A description of each parameter follows:
8306%
8307% o display: Specifies a connection to an X server; returned from
8308% XOpenDisplay.
8309%
8310% o parent: Specifies the parent window_info.
8311%
8312% o argv: Specifies the application's argument list.
8313%
8314% o argc: Specifies the number of arguments.
8315%
8316% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8317%
8318% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8319%
8320% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8321%
8322*/
cristybcbda3f2011-09-03 13:01:22 +00008323MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008324 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8325 XWindowInfo *window_info)
8326{
8327#define MinWindowSize 64
8328
8329 Atom
8330 atom_list[2];
8331
8332 int
8333 gravity;
8334
8335 static XTextProperty
8336 icon_name,
8337 window_name;
8338
8339 Status
8340 status;
8341
8342 XSizeHints
8343 *size_hints;
8344
8345 /*
8346 Set window info hints.
8347 */
8348 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8349 assert(display != (Display *) NULL);
8350 assert(window_info != (XWindowInfo *) NULL);
8351 size_hints=XAllocSizeHints();
8352 if (size_hints == (XSizeHints *) NULL)
8353 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008354 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008355 size_hints->x=window_info->x;
8356 size_hints->y=window_info->y;
8357 size_hints->width=(int) window_info->width;
8358 size_hints->height=(int) window_info->height;
8359 if (window_info->immutable != MagickFalse)
8360 {
8361 /*
8362 Window size cannot be changed.
8363 */
8364 size_hints->min_width=size_hints->width;
8365 size_hints->min_height=size_hints->height;
8366 size_hints->max_width=size_hints->width;
8367 size_hints->max_height=size_hints->height;
8368 size_hints->flags|=PMinSize;
8369 size_hints->flags|=PMaxSize;
8370 }
8371 else
8372 {
8373 /*
8374 Window size can be changed.
8375 */
8376 size_hints->min_width=(int) window_info->min_width;
8377 size_hints->min_height=(int) window_info->min_height;
8378 size_hints->flags|=PResizeInc;
8379 size_hints->width_inc=(int) window_info->width_inc;
8380 size_hints->height_inc=(int) window_info->height_inc;
8381#if !defined(PRE_R4_ICCCM)
8382 size_hints->flags|=PBaseSize;
8383 size_hints->base_width=size_hints->width_inc;
8384 size_hints->base_height=size_hints->height_inc;
8385#endif
8386 }
8387 gravity=NorthWestGravity;
8388 if (window_info->geometry != (char *) NULL)
8389 {
8390 char
8391 default_geometry[MaxTextExtent],
8392 geometry[MaxTextExtent];
8393
8394 int
8395 flags;
8396
8397 register char
8398 *p;
8399
8400 /*
8401 User specified geometry.
8402 */
cristyb51dff52011-05-19 16:55:47 +00008403 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008404 size_hints->width,size_hints->height);
8405 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8406 p=geometry;
8407 while (strlen(p) != 0)
8408 {
8409 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8410 p++;
8411 else
8412 (void) CopyMagickString(p,p+1,MaxTextExtent);
8413 }
8414 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8415 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8416 &size_hints->width,&size_hints->height,&gravity);
8417 if ((flags & WidthValue) && (flags & HeightValue))
8418 size_hints->flags|=USSize;
8419 if ((flags & XValue) && (flags & YValue))
8420 {
8421 size_hints->flags|=USPosition;
8422 window_info->x=size_hints->x;
8423 window_info->y=size_hints->y;
8424 }
8425 }
8426#if !defined(PRE_R4_ICCCM)
8427 size_hints->win_gravity=gravity;
8428 size_hints->flags|=PWinGravity;
8429#endif
8430 if (window_info->id == (Window) NULL)
8431 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8432 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8433 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008434 window_info->visual,(unsigned long) window_info->mask,
8435 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008436 else
8437 {
8438 MagickStatusType
8439 mask;
8440
8441 XEvent
8442 sans_event;
8443
8444 XWindowChanges
8445 window_changes;
8446
8447 /*
8448 Window already exists; change relevant attributes.
8449 */
cristyc57f6942010-11-12 01:47:39 +00008450 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8451 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008452 mask=ConfigureNotify;
8453 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8454 window_changes.x=window_info->x;
8455 window_changes.y=window_info->y;
8456 window_changes.width=(int) window_info->width;
8457 window_changes.height=(int) window_info->height;
8458 mask=(MagickStatusType) (CWWidth | CWHeight);
8459 if (window_info->flags & USPosition)
8460 mask|=CWX | CWY;
8461 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8462 mask,&window_changes);
8463 }
8464 if (window_info->id == (Window) NULL)
8465 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8466 window_info->name);
8467 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8468 if (status == False)
8469 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8470 window_info->name);
8471 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8472 if (status == False)
8473 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8474 window_info->icon_name);
8475 if (window_info->icon_geometry != (char *) NULL)
8476 {
8477 int
8478 flags,
8479 height,
8480 width;
8481
8482 /*
8483 User specified icon geometry.
8484 */
8485 size_hints->flags|=USPosition;
8486 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8487 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8488 &manager_hints->icon_y,&width,&height,&gravity);
8489 if ((flags & XValue) && (flags & YValue))
8490 manager_hints->flags|=IconPositionHint;
8491 }
8492 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8493 size_hints,manager_hints,class_hint);
8494 if (window_name.value != (void *) NULL)
8495 {
8496 (void) XFree((void *) window_name.value);
8497 window_name.value=(unsigned char *) NULL;
8498 window_name.nitems=0;
8499 }
8500 if (icon_name.value != (void *) NULL)
8501 {
8502 (void) XFree((void *) icon_name.value);
8503 icon_name.value=(unsigned char *) NULL;
8504 icon_name.nitems=0;
8505 }
8506 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8507 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8508 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8509 (void) XFree((void *) size_hints);
8510 if (window_info->shape != MagickFalse)
8511 {
8512#if defined(MAGICKCORE_HAVE_SHAPE)
8513 int
8514 error_base,
8515 event_base;
8516
8517 /*
8518 Can we apply a non-rectangular shaping mask?
8519 */
8520 error_base=0;
8521 event_base=0;
8522 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8523 window_info->shape=MagickFalse;
8524#else
8525 window_info->shape=MagickFalse;
8526#endif
8527 }
8528 if (window_info->shared_memory)
8529 {
8530#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8531 /*
8532 Can we use shared memory with this window?
8533 */
8534 if (XShmQueryExtension(display) == 0)
8535 window_info->shared_memory=MagickFalse;
8536#else
8537 window_info->shared_memory=MagickFalse;
8538#endif
8539 }
8540 window_info->image=NewImageList();
8541 window_info->destroy=MagickFalse;
8542}
8543
8544/*
8545%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8546% %
8547% %
8548% %
8549% X M a g i c k P r o g r e s s M o n i t o r %
8550% %
8551% %
8552% %
8553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8554%
8555% XMagickProgressMonitor() displays the progress a task is making in
8556% completing a task.
8557%
8558% The format of the XMagickProgressMonitor method is:
8559%
8560% void XMagickProgressMonitor(const char *task,
8561% const MagickOffsetType quantum,const MagickSizeType span,
8562% void *client_data)
8563%
8564% A description of each parameter follows:
8565%
8566% o task: Identifies the task in progress.
8567%
8568% o quantum: Specifies the quantum position within the span which represents
8569% how much progress has been made in completing a task.
8570%
8571% o span: Specifies the span relative to completing a task.
8572%
8573% o client_data: Pointer to any client data.
8574%
8575*/
8576
8577static const char *GetLocaleMonitorMessage(const char *text)
8578{
8579 char
8580 message[MaxTextExtent],
8581 tag[MaxTextExtent];
8582
8583 const char
8584 *locale_message;
8585
8586 register char
8587 *p;
8588
8589 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8590 p=strrchr(tag,'/');
8591 if (p != (char *) NULL)
8592 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008593 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008594 locale_message=GetLocaleMessage(message);
8595 if (locale_message == message)
8596 return(text);
8597 return(locale_message);
8598}
8599
cristybcbda3f2011-09-03 13:01:22 +00008600MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008601 const MagickOffsetType quantum,const MagickSizeType span,
8602 void *magick_unused(client_data))
8603{
8604 XWindows
8605 *windows;
8606
8607 windows=XSetWindows((XWindows *) ~0);
8608 if (windows == (XWindows *) NULL)
8609 return(MagickTrue);
8610 if (windows->info.mapped != MagickFalse)
8611 XProgressMonitorWidget(windows->display,windows,
8612 GetLocaleMonitorMessage(tag),quantum,span);
8613 return(MagickTrue);
8614}
8615
8616/*
8617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8618% %
8619% %
8620% %
8621% X Q u e r y C o l o r D a t a b a s e %
8622% %
8623% %
8624% %
8625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8626%
8627% XQueryColorDatabase() looks up a RGB values for a color given in the target
8628% string.
8629%
8630% The format of the XQueryColorDatabase method is:
8631%
8632% MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8633%
8634% A description of each parameter follows:
8635%
8636% o target: Specifies the color to lookup in the X color database.
8637%
8638% o color: A pointer to an PixelPacket structure. The RGB value of the target
8639% color is returned as this value.
8640%
8641*/
cristybcbda3f2011-09-03 13:01:22 +00008642MagickPrivate MagickBooleanType XQueryColorDatabase(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008643 XColor *color)
8644{
8645 Colormap
8646 colormap;
8647
8648 static Display
8649 *display = (Display *) NULL;
8650
8651 Status
8652 status;
8653
8654 XColor
8655 xcolor;
8656
8657 /*
8658 Initialize color return value.
8659 */
8660 assert(color != (XColor *) NULL);
8661 color->red=0;
8662 color->green=0;
8663 color->blue=0;
8664 color->flags=(char) (DoRed | DoGreen | DoBlue);
8665 if ((target == (char *) NULL) || (*target == '\0'))
8666 target="#ffffffffffff";
8667 /*
8668 Let the X server define the color for us.
8669 */
8670 if (display == (Display *) NULL)
8671 display=XOpenDisplay((char *) NULL);
8672 if (display == (Display *) NULL)
8673 {
8674 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8675 return(MagickFalse);
8676 }
8677 colormap=XDefaultColormap(display,XDefaultScreen(display));
8678 status=XParseColor(display,colormap,(char *) target,&xcolor);
8679 if (status == False)
8680 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8681 else
8682 {
8683 color->red=xcolor.red;
8684 color->green=xcolor.green;
8685 color->blue=xcolor.blue;
8686 color->flags=xcolor.flags;
8687 }
8688 return(status != False ? MagickTrue : MagickFalse);
8689}
8690
8691/*
8692%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8693% %
8694% %
8695% %
8696% X Q u e r y P o s i t i o n %
8697% %
8698% %
8699% %
8700%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8701%
8702% XQueryPosition() gets the pointer coordinates relative to a window.
8703%
8704% The format of the XQueryPosition method is:
8705%
8706% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8707%
8708% A description of each parameter follows:
8709%
8710% o display: Specifies a connection to an X server; returned from
8711% XOpenDisplay.
8712%
8713% o window: Specifies a pointer to a Window.
8714%
8715% o x: Return the x coordinate of the pointer relative to the origin of the
8716% window.
8717%
8718% o y: Return the y coordinate of the pointer relative to the origin of the
8719% window.
8720%
8721*/
cristybcbda3f2011-09-03 13:01:22 +00008722MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008723{
8724 int
8725 x_root,
8726 y_root;
8727
8728 unsigned int
8729 mask;
8730
8731 Window
8732 root_window;
8733
8734 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8735 assert(display != (Display *) NULL);
8736 assert(window != (Window) NULL);
8737 assert(x != (int *) NULL);
8738 assert(y != (int *) NULL);
8739 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8740 x,y,&mask);
8741}
8742
8743/*
8744%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8745% %
8746% %
8747% %
8748% X R e f r e s h W i n d o w %
8749% %
8750% %
8751% %
8752%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8753%
8754% XRefreshWindow() refreshes an image in a X window.
8755%
8756% The format of the XRefreshWindow method is:
8757%
8758% void XRefreshWindow(Display *display,const XWindowInfo *window,
8759% const XEvent *event)
8760%
8761% A description of each parameter follows:
8762%
8763% o display: Specifies a connection to an X server; returned from
8764% XOpenDisplay.
8765%
8766% o window: Specifies a pointer to a XWindowInfo structure.
8767%
8768% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8769% the entire image is refreshed.
8770%
8771*/
cristybcbda3f2011-09-03 13:01:22 +00008772MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008773 const XEvent *event)
8774{
8775 int
8776 x,
8777 y;
8778
8779 unsigned int
8780 height,
8781 width;
8782
8783 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8784 assert(display != (Display *) NULL);
8785 assert(window != (XWindowInfo *) NULL);
8786 if (window->ximage == (XImage *) NULL)
8787 return;
8788 if (event != (XEvent *) NULL)
8789 {
8790 /*
8791 Determine geometry from expose event.
8792 */
8793 x=event->xexpose.x;
8794 y=event->xexpose.y;
8795 width=(unsigned int) event->xexpose.width;
8796 height=(unsigned int) event->xexpose.height;
8797 }
8798 else
8799 {
8800 XEvent
8801 sans_event;
8802
8803 /*
8804 Refresh entire window; discard outstanding expose events.
8805 */
8806 x=0;
8807 y=0;
8808 width=window->width;
8809 height=window->height;
8810 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008811 if (window->matte_pixmap != (Pixmap) NULL)
8812 {
8813#if defined(MAGICKCORE_HAVE_SHAPE)
8814 if (window->shape != MagickFalse)
8815 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8816 window->matte_pixmap,ShapeSet);
8817#endif
8818 }
cristy3ed852e2009-09-05 21:47:34 +00008819 }
8820 /*
8821 Check boundary conditions.
8822 */
8823 if ((window->ximage->width-(x+window->x)) < (int) width)
8824 width=(unsigned int) (window->ximage->width-(x+window->x));
8825 if ((window->ximage->height-(y+window->y)) < (int) height)
8826 height=(unsigned int) (window->ximage->height-(y+window->y));
8827 /*
8828 Refresh image.
8829 */
8830 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008831 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008832 if (window->pixmap != (Pixmap) NULL)
8833 {
8834 if (window->depth > 1)
8835 (void) XCopyArea(display,window->pixmap,window->id,
8836 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8837 else
8838 (void) XCopyPlane(display,window->pixmap,window->id,
8839 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8840 1L);
8841 }
8842 else
8843 {
8844#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8845 if (window->shared_memory)
8846 (void) XShmPutImage(display,window->id,window->annotate_context,
8847 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8848#endif
8849 if (window->shared_memory == MagickFalse)
8850 (void) XPutImage(display,window->id,window->annotate_context,
8851 window->ximage,x+window->x,y+window->y,x,y,width,height);
8852 }
8853 if (window->matte_pixmap != (Pixmap) NULL)
8854 (void) XSetClipMask(display,window->annotate_context,None);
8855 (void) XFlush(display);
8856}
8857
8858/*
8859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8860% %
8861% %
8862% %
8863% X R e m o t e C o m m a n d %
8864% %
8865% %
8866% %
8867%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8868%
8869% XRemoteCommand() forces a remote display(1) to display the specified
8870% image filename.
8871%
8872% The format of the XRemoteCommand method is:
8873%
8874% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8875% const char *filename)
8876%
8877% A description of each parameter follows:
8878%
8879% o display: Specifies a connection to an X server; returned from
8880% XOpenDisplay.
8881%
8882% o window: Specifies the name or id of an X window.
8883%
8884% o filename: the name of the image filename to display.
8885%
8886*/
8887MagickExport MagickBooleanType XRemoteCommand(Display *display,
8888 const char *window,const char *filename)
8889{
8890 Atom
8891 remote_atom;
8892
8893 Window
8894 remote_window,
8895 root_window;
8896
8897 assert(filename != (char *) NULL);
8898 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8899 if (display == (Display *) NULL)
8900 display=XOpenDisplay((char *) NULL);
8901 if (display == (Display *) NULL)
8902 {
8903 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8904 return(MagickFalse);
8905 }
8906 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8907 remote_window=(Window) NULL;
8908 root_window=XRootWindow(display,XDefaultScreen(display));
8909 if (window != (char *) NULL)
8910 {
8911 /*
8912 Search window hierarchy and identify any clients by name or ID.
8913 */
8914 if (isdigit((unsigned char) *window) != 0)
8915 remote_window=XWindowByID(display,root_window,(Window)
8916 strtol((char *) window,(char **) NULL,0));
8917 if (remote_window == (Window) NULL)
8918 remote_window=XWindowByName(display,root_window,window);
8919 }
8920 if (remote_window == (Window) NULL)
8921 remote_window=XWindowByProperty(display,root_window,remote_atom);
8922 if (remote_window == (Window) NULL)
8923 {
8924 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8925 filename);
8926 return(MagickFalse);
8927 }
8928 /*
8929 Send remote command.
8930 */
8931 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8932 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8933 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8934 (void) XSync(display,MagickFalse);
8935 return(MagickTrue);
8936}
8937
8938/*
8939%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8940% %
8941% %
8942% %
8943% X R e t a i n W i n d o w C o l o r s %
8944% %
8945% %
8946% %
8947%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8948%
8949% XRetainWindowColors() sets X11 color resources on a window. This preserves
8950% the colors associated with an image displayed on the window.
8951%
8952% The format of the XRetainWindowColors method is:
8953%
8954% void XRetainWindowColors(Display *display,const Window window)
8955%
8956% A description of each parameter follows:
8957%
8958% o display: Specifies a connection to an X server; returned from
8959% XOpenDisplay.
8960%
8961% o window: Specifies a pointer to a XWindowInfo structure.
8962%
8963*/
8964MagickExport void XRetainWindowColors(Display *display,const Window window)
8965{
8966 Atom
8967 property;
8968
8969 Pixmap
8970 pixmap;
8971
8972 /*
8973 Put property on the window.
8974 */
8975 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8976 assert(display != (Display *) NULL);
8977 assert(window != (Window) NULL);
8978 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8979 if (property == (Atom) NULL)
8980 {
8981 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8982 "_XSETROOT_ID");
8983 return;
8984 }
8985 pixmap=XCreatePixmap(display,window,1,1,1);
8986 if (pixmap == (Pixmap) NULL)
8987 {
8988 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8989 return;
8990 }
8991 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8992 (unsigned char *) &pixmap,1);
8993 (void) XSetCloseDownMode(display,RetainPermanent);
8994}
8995
8996/*
8997%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8998% %
8999% %
9000% %
9001% X S e l e c t W i n d o w %
9002% %
9003% %
9004% %
9005%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9006%
9007% XSelectWindow() allows a user to select a window using the mouse. If the
9008% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9009% is returned in the crop_info structure.
9010%
9011% The format of the XSelectWindow function is:
9012%
9013% target_window=XSelectWindow(display,crop_info)
9014%
9015% A description of each parameter follows:
9016%
9017% o window: XSelectWindow returns the window id.
9018%
9019% o display: Specifies a pointer to the Display structure; returned from
9020% XOpenDisplay.
9021%
9022% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9023% contains the extents of any cropping rectangle.
9024%
cristy3ed852e2009-09-05 21:47:34 +00009025*/
9026static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9027{
9028#define MinimumCropArea (unsigned int) 9
9029
9030 Cursor
9031 target_cursor;
9032
9033 GC
9034 annotate_context;
9035
9036 int
9037 presses,
9038 x_offset,
9039 y_offset;
9040
9041 Status
9042 status;
9043
9044 Window
9045 root_window,
9046 target_window;
9047
9048 XEvent
9049 event;
9050
9051 XGCValues
9052 context_values;
9053
9054 /*
9055 Initialize graphic context.
9056 */
9057 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9058 assert(display != (Display *) NULL);
9059 assert(crop_info != (RectangleInfo *) NULL);
9060 root_window=XRootWindow(display,XDefaultScreen(display));
9061 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9062 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9063 context_values.function=GXinvert;
9064 context_values.plane_mask=
9065 context_values.background ^ context_values.foreground;
9066 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009067 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009068 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9069 if (annotate_context == (GC) NULL)
9070 return(MagickFalse);
9071 /*
9072 Grab the pointer using target cursor.
9073 */
9074 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9075 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9076 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9077 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9078 GrabModeAsync,root_window,target_cursor,CurrentTime);
9079 if (status != GrabSuccess)
9080 {
9081 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9082 return((Window) NULL);
9083 }
9084 /*
9085 Select a window.
9086 */
9087 crop_info->width=0;
9088 crop_info->height=0;
9089 presses=0;
9090 target_window=(Window) NULL;
9091 x_offset=0;
9092 y_offset=0;
9093 do
9094 {
9095 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9096 (void) XDrawRectangle(display,root_window,annotate_context,
9097 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9098 (unsigned int) crop_info->height-1);
9099 /*
9100 Allow another event.
9101 */
9102 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9103 (void) XWindowEvent(display,root_window,ButtonPressMask |
9104 ButtonReleaseMask | ButtonMotionMask,&event);
9105 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9106 (void) XDrawRectangle(display,root_window,annotate_context,
9107 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9108 (unsigned int) crop_info->height-1);
9109 switch (event.type)
9110 {
9111 case ButtonPress:
9112 {
9113 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9114 event.xbutton.x,event.xbutton.y);
9115 if (target_window == (Window) NULL)
9116 target_window=root_window;
9117 x_offset=event.xbutton.x_root;
9118 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009119 crop_info->x=(ssize_t) x_offset;
9120 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009121 crop_info->width=0;
9122 crop_info->height=0;
9123 presses++;
9124 break;
9125 }
9126 case ButtonRelease:
9127 {
9128 presses--;
9129 break;
9130 }
9131 case MotionNotify:
9132 {
9133 /*
9134 Discard pending button motion events.
9135 */
9136 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009137 crop_info->x=(ssize_t) event.xmotion.x;
9138 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009139 /*
9140 Check boundary conditions.
9141 */
9142 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009143 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009144 else
9145 {
cristyecd0ab52010-05-30 14:59:20 +00009146 crop_info->width=(size_t) (crop_info->x-x_offset);
9147 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009148 }
9149 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009150 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009151 else
9152 {
cristyecd0ab52010-05-30 14:59:20 +00009153 crop_info->height=(size_t) (crop_info->y-y_offset);
9154 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009155 }
9156 }
9157 default:
9158 break;
9159 }
9160 } while ((target_window == (Window) NULL) || (presses > 0));
9161 (void) XUngrabPointer(display,CurrentTime);
9162 (void) XFreeCursor(display,target_cursor);
9163 (void) XFreeGC(display,annotate_context);
9164 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9165 {
9166 crop_info->width=0;
9167 crop_info->height=0;
9168 }
9169 if ((crop_info->width != 0) && (crop_info->height != 0))
9170 target_window=root_window;
9171 return(target_window);
9172}
9173
9174/*
9175%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9176% %
9177% %
9178% %
9179% X S e t C u r s o r S t a t e %
9180% %
9181% %
9182% %
9183%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9184%
9185% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9186% reset to their default.
9187%
9188% The format of the XXSetCursorState method is:
9189%
9190% XSetCursorState(display,windows,const MagickStatusType state)
9191%
9192% A description of each parameter follows:
9193%
9194% o display: Specifies a connection to an X server; returned from
9195% XOpenDisplay.
9196%
9197% o windows: Specifies a pointer to a XWindows structure.
9198%
9199% o state: An unsigned integer greater than 0 sets the cursor state
9200% to busy, otherwise the cursor are reset to their default.
9201%
9202*/
cristybcbda3f2011-09-03 13:01:22 +00009203MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009204 const MagickStatusType state)
9205{
9206 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9207 assert(display != (Display *) NULL);
9208 assert(windows != (XWindows *) NULL);
9209 if (state)
9210 {
9211 (void) XCheckDefineCursor(display,windows->image.id,
9212 windows->image.busy_cursor);
9213 (void) XCheckDefineCursor(display,windows->pan.id,
9214 windows->pan.busy_cursor);
9215 (void) XCheckDefineCursor(display,windows->magnify.id,
9216 windows->magnify.busy_cursor);
9217 (void) XCheckDefineCursor(display,windows->command.id,
9218 windows->command.busy_cursor);
9219 }
9220 else
9221 {
9222 (void) XCheckDefineCursor(display,windows->image.id,
9223 windows->image.cursor);
9224 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9225 (void) XCheckDefineCursor(display,windows->magnify.id,
9226 windows->magnify.cursor);
9227 (void) XCheckDefineCursor(display,windows->command.id,
9228 windows->command.cursor);
9229 (void) XCheckDefineCursor(display,windows->command.id,
9230 windows->widget.cursor);
9231 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9232 }
9233 windows->info.mapped=MagickFalse;
9234}
9235
9236/*
9237%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9238% %
9239% %
9240% %
9241% X S e t W i n d o w s %
9242% %
9243% %
9244% %
9245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9246%
9247% XSetWindows() sets the X windows structure if the windows info is specified.
9248% Otherwise the current windows structure is returned.
9249%
9250% The format of the XSetWindows method is:
9251%
9252% XWindows *XSetWindows(XWindows *windows_info)
9253%
9254% A description of each parameter follows:
9255%
9256% o windows_info: Initialize the Windows structure with this information.
9257%
9258*/
cristybcbda3f2011-09-03 13:01:22 +00009259MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009260{
9261 static XWindows
9262 *windows = (XWindows *) NULL;
9263
9264 if (windows_info != (XWindows *) ~0)
9265 {
9266 windows=(XWindows *) RelinquishMagickMemory(windows);
9267 windows=windows_info;
9268 }
9269 return(windows);
9270}
9271/*
9272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9273% %
9274% %
9275% %
9276% X U s e r P r e f e r e n c e s %
9277% %
9278% %
9279% %
9280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9281%
9282% XUserPreferences() saves the preferences in a configuration file in the
9283% users' home directory.
9284%
9285% The format of the XUserPreferences method is:
9286%
9287% void XUserPreferences(XResourceInfo *resource_info)
9288%
9289% A description of each parameter follows:
9290%
9291% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9292%
9293*/
cristybcbda3f2011-09-03 13:01:22 +00009294MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009295{
9296#if defined(X11_PREFERENCES_PATH)
9297 char
9298 cache[MaxTextExtent],
9299 filename[MaxTextExtent],
9300 specifier[MaxTextExtent];
9301
9302 const char
cristy104cea82009-10-25 02:26:51 +00009303 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009304 *value;
9305
9306 XrmDatabase
9307 preferences_database;
9308
9309 /*
9310 Save user preferences to the client configuration file.
9311 */
9312 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009313 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009314 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009315 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009316 value=resource_info->backdrop ? "True" : "False";
9317 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009318 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009319 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9320 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009321 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009322 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009323 value=resource_info->confirm_exit ? "True" : "False";
9324 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009325 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009326 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009327 value=resource_info->confirm_edit ? "True" : "False";
9328 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009329 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009330 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009331 value=resource_info->display_warnings ? "True" : "False";
9332 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009333 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009334 value=resource_info->quantize_info->dither ? "True" : "False";
9335 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009336 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009337 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009338 value=resource_info->gamma_correct ? "True" : "False";
9339 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009340 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9341 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009342 resource_info->undo_cache);
9343 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009344 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009345 value=resource_info->use_pixmap ? "True" : "False";
9346 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009347 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009348 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009349 ExpandFilename(filename);
9350 XrmPutFileDatabase(preferences_database,filename);
9351#endif
9352}
9353
9354/*
9355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9356% %
9357% %
9358% %
9359% X V i s u a l C l a s s N a m e %
9360% %
9361% %
9362% %
9363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9364%
9365% XVisualClassName() returns the visual class name as a character string.
9366%
9367% The format of the XVisualClassName method is:
9368%
9369% char *XVisualClassName(const int visual_class)
9370%
9371% A description of each parameter follows:
9372%
9373% o visual_type: XVisualClassName returns the visual class as a character
9374% string.
9375%
9376% o class: Specifies the visual class.
9377%
cristy3ed852e2009-09-05 21:47:34 +00009378*/
9379static const char *XVisualClassName(const int visual_class)
9380{
9381 switch (visual_class)
9382 {
9383 case StaticGray: return("StaticGray");
9384 case GrayScale: return("GrayScale");
9385 case StaticColor: return("StaticColor");
9386 case PseudoColor: return("PseudoColor");
9387 case TrueColor: return("TrueColor");
9388 case DirectColor: return("DirectColor");
9389 }
9390 return("unknown visual class");
9391}
9392
9393/*
9394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9395% %
9396% %
9397% %
9398% X W a r n i n g %
9399% %
9400% %
9401% %
9402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9403%
9404% XWarning() displays a warning reason in a Notice widget.
9405%
9406% The format of the XWarning method is:
9407%
9408% void XWarning(const unsigned int warning,const char *reason,
9409% const char *description)
9410%
9411% A description of each parameter follows:
9412%
9413% o warning: Specifies the numeric warning category.
9414%
9415% o reason: Specifies the reason to display before terminating the
9416% program.
9417%
9418% o description: Specifies any description to the reason.
9419%
9420*/
cristybcbda3f2011-09-03 13:01:22 +00009421MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009422 const char *reason,const char *description)
9423{
9424 char
9425 text[MaxTextExtent];
9426
9427 XWindows
9428 *windows;
9429
9430 if (reason == (char *) NULL)
9431 return;
9432 (void) CopyMagickString(text,reason,MaxTextExtent);
9433 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9434 windows=XSetWindows((XWindows *) ~0);
9435 XNoticeWidget(windows->display,windows,text,(char *) description);
9436}
9437
9438/*
9439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9440% %
9441% %
9442% %
9443% X W i n d o w B y I D %
9444% %
9445% %
9446% %
9447%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9448%
9449% XWindowByID() locates a child window with a given ID. If not window with
9450% the given name is found, 0 is returned. Only the window specified and its
9451% subwindows are searched.
9452%
9453% The format of the XWindowByID function is:
9454%
9455% child=XWindowByID(display,window,id)
9456%
9457% A description of each parameter follows:
9458%
9459% o child: XWindowByID returns the window with the specified
9460% id. If no windows are found, XWindowByID returns 0.
9461%
9462% o display: Specifies a pointer to the Display structure; returned from
9463% XOpenDisplay.
9464%
9465% o id: Specifies the id of the window to locate.
9466%
9467*/
cristybcbda3f2011-09-03 13:01:22 +00009468MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009469 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009470{
9471 RectangleInfo
9472 rectangle_info;
9473
9474 register int
9475 i;
9476
9477 Status
9478 status;
9479
9480 unsigned int
9481 number_children;
9482
9483 Window
9484 child,
9485 *children,
9486 window;
9487
9488 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9489 assert(display != (Display *) NULL);
9490 assert(root_window != (Window) NULL);
9491 if (id == 0)
9492 return(XSelectWindow(display,&rectangle_info));
9493 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009494 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009495 status=XQueryTree(display,root_window,&child,&child,&children,
9496 &number_children);
9497 if (status == False)
9498 return((Window) NULL);
9499 window=(Window) NULL;
9500 for (i=0; i < (int) number_children; i++)
9501 {
9502 /*
9503 Search each child and their children.
9504 */
9505 window=XWindowByID(display,children[i],id);
9506 if (window != (Window) NULL)
9507 break;
9508 }
9509 if (children != (Window *) NULL)
9510 (void) XFree((void *) children);
9511 return(window);
9512}
9513
9514/*
9515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9516% %
9517% %
9518% %
9519% X W i n d o w B y N a m e %
9520% %
9521% %
9522% %
9523%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9524%
9525% XWindowByName() locates a window with a given name on a display. If no
9526% window with the given name is found, 0 is returned. If more than one window
9527% has the given name, the first one is returned. Only root and its children
9528% are searched.
9529%
9530% The format of the XWindowByName function is:
9531%
9532% window=XWindowByName(display,root_window,name)
9533%
9534% A description of each parameter follows:
9535%
9536% o window: XWindowByName returns the window id.
9537%
9538% o display: Specifies a pointer to the Display structure; returned from
9539% XOpenDisplay.
9540%
9541% o root_window: Specifies the id of the root window.
9542%
9543% o name: Specifies the name of the window to locate.
9544%
9545*/
cristybcbda3f2011-09-03 13:01:22 +00009546MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009547 const char *name)
9548{
9549 register int
9550 i;
9551
9552 Status
9553 status;
9554
9555 unsigned int
9556 number_children;
9557
9558 Window
9559 *children,
9560 child,
9561 window;
9562
9563 XTextProperty
9564 window_name;
9565
9566 assert(display != (Display *) NULL);
9567 assert(root_window != (Window) NULL);
9568 assert(name != (char *) NULL);
9569 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9570 if (XGetWMName(display,root_window,&window_name) != 0)
9571 if (LocaleCompare((char *) window_name.value,name) == 0)
9572 return(root_window);
9573 status=XQueryTree(display,root_window,&child,&child,&children,
9574 &number_children);
9575 if (status == False)
9576 return((Window) NULL);
9577 window=(Window) NULL;
9578 for (i=0; i < (int) number_children; i++)
9579 {
9580 /*
9581 Search each child and their children.
9582 */
9583 window=XWindowByName(display,children[i],name);
9584 if (window != (Window) NULL)
9585 break;
9586 }
9587 if (children != (Window *) NULL)
9588 (void) XFree((void *) children);
9589 return(window);
9590}
9591
9592/*
9593%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9594% %
9595% %
9596% %
9597% X W i n d o w B y P r o p e r y %
9598% %
9599% %
9600% %
9601%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9602%
9603% XWindowByProperty() locates a child window with a given property. If not
9604% window with the given name is found, 0 is returned. If more than one window
9605% has the given property, the first one is returned. Only the window
9606% specified and its subwindows are searched.
9607%
9608% The format of the XWindowByProperty function is:
9609%
9610% child=XWindowByProperty(display,window,property)
9611%
9612% A description of each parameter follows:
9613%
9614% o child: XWindowByProperty returns the window id with the specified
9615% property. If no windows are found, XWindowByProperty returns 0.
9616%
9617% o display: Specifies a pointer to the Display structure; returned from
9618% XOpenDisplay.
9619%
9620% o property: Specifies the property of the window to locate.
9621%
9622*/
cristybcbda3f2011-09-03 13:01:22 +00009623MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009624 const Atom property)
9625{
9626 Atom
9627 type;
9628
9629 int
9630 format;
9631
9632 Status
9633 status;
9634
9635 unsigned char
9636 *data;
9637
9638 unsigned int
9639 i,
9640 number_children;
9641
cristyf2faecf2010-05-28 19:19:36 +00009642 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009643 after,
9644 number_items;
9645
9646 Window
9647 child,
9648 *children,
9649 parent,
9650 root;
9651
9652 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9653 assert(display != (Display *) NULL);
9654 assert(window != (Window) NULL);
9655 assert(property != (Atom) NULL);
9656 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9657 if (status == False)
9658 return((Window) NULL);
9659 type=(Atom) NULL;
9660 child=(Window) NULL;
9661 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9662 {
9663 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9664 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9665 if (data != NULL)
9666 (void) XFree((void *) data);
9667 if ((status == Success) && (type != (Atom) NULL))
9668 child=children[i];
9669 }
9670 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9671 child=XWindowByProperty(display,children[i],property);
9672 if (children != (Window *) NULL)
9673 (void) XFree((void *) children);
9674 return(child);
9675}
9676#else
9677
9678/*
9679%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9680% %
9681% %
9682% %
9683% X I m p o r t I m a g e %
9684% %
9685% %
9686% %
9687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9688%
9689% XImportImage() reads an image from an X window.
9690%
9691% The format of the XImportImage method is:
9692%
9693% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9694%
9695% A description of each parameter follows:
9696%
9697% o image_info: the image info..
9698%
9699% o ximage_info: Specifies a pointer to an XImportInfo structure.
9700%
9701*/
cristybcbda3f2011-09-03 13:01:22 +00009702MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00009703 XImportInfo *ximage_info)
9704{
9705 assert(image_info != (const ImageInfo *) NULL);
9706 assert(image_info->signature == MagickSignature);
9707 if (image_info->debug != MagickFalse)
9708 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9709 image_info->filename);
9710 assert(ximage_info != (XImportInfo *) NULL);
9711 return((Image *) NULL);
9712}
9713#endif
9714
9715/*
9716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9717% %
9718% %
9719% %
cristy576974e2009-10-25 20:45:31 +00009720+ X C o m p o n e n t G e n e s i s %
9721% %
9722% %
9723% %
9724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9725%
9726% XComponentGenesis() instantiates the X component.
9727%
9728% The format of the XComponentGenesis method is:
9729%
9730% MagickBooleanType XComponentGenesis(void)
9731%
9732*/
cristy5ff4eaf2011-09-03 01:38:02 +00009733MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009734{
9735 return(MagickTrue);
9736}
9737
9738/*
9739%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9740% %
9741% %
9742% %
cristy3ed852e2009-09-05 21:47:34 +00009743% X G e t I m p o r t I n f o %
9744% %
9745% %
9746% %
9747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9748%
9749% XGetImportInfo() initializes the XImportInfo structure.
9750%
9751% The format of the XGetImportInfo method is:
9752%
9753% void XGetImportInfo(XImportInfo *ximage_info)
9754%
9755% A description of each parameter follows:
9756%
9757% o ximage_info: Specifies a pointer to an ImageInfo structure.
9758%
9759*/
9760MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9761{
9762 assert(ximage_info != (XImportInfo *) NULL);
9763 ximage_info->frame=MagickFalse;
9764 ximage_info->borders=MagickFalse;
9765 ximage_info->screen=MagickFalse;
9766 ximage_info->descend=MagickTrue;
9767 ximage_info->silent=MagickFalse;
9768}