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