blob: a4cb182b767b4879b669ddfe7af20bdb1d23ff58 [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% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 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"
cristy030436f2012-01-06 21:56:17 +000052#include "MagickCore/constitute.h"
cristy4c08aed2011-07-01 19:47:50 +000053#include "MagickCore/display.h"
cristyc53413d2011-11-17 13:04:26 +000054#include "MagickCore/distort.h"
cristy4c08aed2011-07-01 19:47:50 +000055#include "MagickCore/exception.h"
56#include "MagickCore/exception-private.h"
57#include "MagickCore/geometry.h"
58#include "MagickCore/identify.h"
59#include "MagickCore/image.h"
60#include "MagickCore/image-private.h"
61#include "MagickCore/list.h"
62#include "MagickCore/locale_.h"
63#include "MagickCore/log.h"
64#include "MagickCore/magick.h"
65#include "MagickCore/memory_.h"
66#include "MagickCore/monitor.h"
cristy2c5fc272012-02-22 01:27:46 +000067#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000068#include "MagickCore/option.h"
69#include "MagickCore/pixel-accessor.h"
70#include "MagickCore/PreRvIcccm.h"
71#include "MagickCore/quantize.h"
72#include "MagickCore/quantum.h"
73#include "MagickCore/quantum-private.h"
74#include "MagickCore/resource_.h"
75#include "MagickCore/resize.h"
cristy4c08aed2011-07-01 19:47:50 +000076#include "MagickCore/statistic.h"
77#include "MagickCore/string_.h"
78#include "MagickCore/string-private.h"
79#include "MagickCore/transform.h"
cristy63a81872012-03-22 15:52:52 +000080#include "MagickCore/token.h"
cristy4c08aed2011-07-01 19:47:50 +000081#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000082#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000083#include "MagickCore/widget.h"
cristybcbda3f2011-09-03 13:01:22 +000084#include "MagickCore/widget-private.h"
cristy4c08aed2011-07-01 19:47:50 +000085#include "MagickCore/xwindow.h"
86#include "MagickCore/xwindow-private.h"
87#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000088#if defined(__BEOS__)
89#include <OS.h>
90#endif
91#if defined(MAGICKCORE_X11_DELEGATE)
92#include <X11/Xproto.h>
93#include <X11/Xlocale.h>
94#if defined(MAGICK_HAVE_POLL)
95# include <sys/poll.h>
96#endif
97#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
98#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
99# include <machine/param.h>
100#endif
101#include <sys/ipc.h>
102#include <sys/shm.h>
103#include <X11/extensions/XShm.h>
104#endif
105#if defined(MAGICKCORE_HAVE_SHAPE)
106#include <X11/extensions/shape.h>
107#endif
108
109/*
110 X defines.
111*/
cristyce70c172010-01-07 17:15:30 +0000112#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000113 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
114 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000115#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000116 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
117 map->red_mult)+ \
118 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
119 map->green_mult)+ \
120 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
121 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000122#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
123 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
124 map->red_mult)+ \
125 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
126 map->green_mult)+ \
127 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
128 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000129#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000130 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
131 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000132#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000133 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
134 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000135#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000136 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
137 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
138 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000139
140#define AccentuateModulate ScaleCharToQuantum(80)
141#define HighlightModulate ScaleCharToQuantum(125)
142#define ShadowModulate ScaleCharToQuantum(135)
143#define DepthModulate ScaleCharToQuantum(185)
144#define TroughModulate ScaleCharToQuantum(110)
145
146#define XLIB_ILLEGAL_ACCESS 1
147#undef ForgetGravity
148#undef NorthWestGravity
149#undef NorthGravity
150#undef NorthEastGravity
151#undef WestGravity
152#undef CenterGravity
153#undef EastGravity
154#undef SouthWestGravity
155#undef SouthGravity
156#undef SouthEastGravity
157#undef StaticGravity
158
159#undef index
160#if defined(hpux9)
161#define XFD_SET int
162#else
163#define XFD_SET fd_set
164#endif
165
166/*
167 Enumeration declarations.
168*/
169typedef enum
170{
171#undef DoRed
172 DoRed = 0x0001,
173#undef DoGreen
174 DoGreen = 0x0002,
175#undef DoBlue
176 DoBlue = 0x0004,
177 DoMatte = 0x0008
178} XColorFlags;
179
180/*
181 Typedef declarations.
182*/
183typedef struct _DiversityPacket
184{
185 Quantum
186 red,
187 green,
188 blue;
189
190 unsigned short
191 index;
192
cristybb503372010-05-27 20:51:26 +0000193 size_t
cristy3ed852e2009-09-05 21:47:34 +0000194 count;
195} DiversityPacket;
196
197/*
198 Constant declaractions.
199*/
200static MagickBooleanType
201 xerror_alert = MagickFalse;
202
203/*
204 Method prototypes.
205*/
206static const char
207 *XVisualClassName(const int);
208
209static MagickRealType
210 blue_gamma = 1.0,
211 green_gamma = 1.0,
212 red_gamma = 1.0;
213
214static MagickBooleanType
215 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
216
217static void
218 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000219 XImage *,XImage *,ExceptionInfo *),
cristy3ed852e2009-09-05 21:47:34 +0000220 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000221 XImage *,XImage *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +0000222
223static Window
224 XSelectWindow(Display *,RectangleInfo *);
225
226/*
227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228% %
229% %
230% %
231% D e s t r o y X R e s o u r c e s %
232% %
233% %
234% %
235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236%
237% DestroyXResources() destroys any X resources.
238%
239% The format of the DestroyXResources method is:
240%
241% void DestroyXResources()
242%
243% A description of each parameter follows:
244%
245*/
246MagickExport void DestroyXResources(void)
247{
248 register int
249 i;
250
251 unsigned int
252 number_windows;
253
254 XWindowInfo
255 *magick_windows[MaxXWindows];
256
257 XWindows
258 *windows;
259
260 DestroyXWidget();
261 windows=XSetWindows((XWindows *) ~0);
262 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
263 return;
264 number_windows=0;
265 magick_windows[number_windows++]=(&windows->context);
266 magick_windows[number_windows++]=(&windows->group_leader);
267 magick_windows[number_windows++]=(&windows->backdrop);
268 magick_windows[number_windows++]=(&windows->icon);
269 magick_windows[number_windows++]=(&windows->image);
270 magick_windows[number_windows++]=(&windows->info);
271 magick_windows[number_windows++]=(&windows->magnify);
272 magick_windows[number_windows++]=(&windows->pan);
273 magick_windows[number_windows++]=(&windows->command);
274 magick_windows[number_windows++]=(&windows->widget);
275 magick_windows[number_windows++]=(&windows->popup);
276 magick_windows[number_windows++]=(&windows->context);
277 for (i=0; i < (int) number_windows; i++)
278 {
279 if (magick_windows[i]->mapped != MagickFalse)
280 {
281 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
282 magick_windows[i]->screen);
283 magick_windows[i]->mapped=MagickFalse;
284 }
285 if (magick_windows[i]->name != (char *) NULL)
286 magick_windows[i]->name=(char *)
287 RelinquishMagickMemory(magick_windows[i]->name);
288 if (magick_windows[i]->icon_name != (char *) NULL)
289 magick_windows[i]->icon_name=(char *)
290 RelinquishMagickMemory(magick_windows[i]->icon_name);
291 if (magick_windows[i]->cursor != (Cursor) NULL)
292 {
293 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
294 magick_windows[i]->cursor=(Cursor) NULL;
295 }
296 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
297 {
298 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
299 magick_windows[i]->busy_cursor=(Cursor) NULL;
300 }
301 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
302 {
303 (void) XFreePixmap(windows->display,
304 magick_windows[i]->highlight_stipple);
305 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
306 }
307 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
308 {
309 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
310 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
311 }
312 if (magick_windows[i]->ximage != (XImage *) NULL)
313 {
314 XDestroyImage(magick_windows[i]->ximage);
315 magick_windows[i]->ximage=(XImage *) NULL;
316 }
317 if (magick_windows[i]->pixmap != (Pixmap) NULL)
318 {
319 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
320 magick_windows[i]->pixmap=(Pixmap) NULL;
321 }
322 if (magick_windows[i]->id != (Window) NULL)
323 {
324 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
325 magick_windows[i]->id=(Window) NULL;
326 }
327 if (magick_windows[i]->destroy != MagickFalse)
328 {
329 if (magick_windows[i]->image != (Image *) NULL)
330 {
331 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
332 magick_windows[i]->image=NewImageList();
333 }
334 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
335 {
336 (void) XFreePixmap(windows->display,
337 magick_windows[i]->matte_pixmap);
338 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
339 }
340 }
341 if (magick_windows[i]->segment_info != (void *) NULL)
342 {
343#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
344 XShmSegmentInfo
345 *segment_info;
346
347 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
348 if (segment_info != (XShmSegmentInfo *) NULL)
349 if (segment_info[0].shmid >= 0)
350 {
351 if (segment_info[0].shmaddr != NULL)
352 (void) shmdt(segment_info[0].shmaddr);
353 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
354 segment_info[0].shmaddr=NULL;
355 segment_info[0].shmid=(-1);
356 }
357#endif
358 magick_windows[i]->segment_info=(void *)
359 RelinquishMagickMemory(magick_windows[i]->segment_info);
360 }
361 }
362 windows->icon_resources=(XResourceInfo *)
363 RelinquishMagickMemory(windows->icon_resources);
364 if (windows->icon_pixel != (XPixelInfo *) NULL)
365 {
cristyf2faecf2010-05-28 19:19:36 +0000366 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
367 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000368 RelinquishMagickMemory(windows->icon_pixel->pixels);
369 if (windows->icon_pixel->annotate_context != (GC) NULL)
370 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
371 windows->icon_pixel=(XPixelInfo *)
372 RelinquishMagickMemory(windows->icon_pixel);
373 }
374 if (windows->pixel_info != (XPixelInfo *) NULL)
375 {
cristyf2faecf2010-05-28 19:19:36 +0000376 if (windows->pixel_info->pixels != (unsigned long *) NULL)
377 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000378 RelinquishMagickMemory(windows->pixel_info->pixels);
379 if (windows->pixel_info->annotate_context != (GC) NULL)
380 XFreeGC(windows->display,windows->pixel_info->annotate_context);
381 if (windows->pixel_info->widget_context != (GC) NULL)
382 XFreeGC(windows->display,windows->pixel_info->widget_context);
383 if (windows->pixel_info->highlight_context != (GC) NULL)
384 XFreeGC(windows->display,windows->pixel_info->highlight_context);
385 windows->pixel_info=(XPixelInfo *)
386 RelinquishMagickMemory(windows->pixel_info);
387 }
388 if (windows->font_info != (XFontStruct *) NULL)
389 {
390 XFreeFont(windows->display,windows->font_info);
391 windows->font_info=(XFontStruct *) NULL;
392 }
393 if (windows->class_hints != (XClassHint *) NULL)
394 {
cristyc9cc4a72011-09-18 02:12:41 +0000395 if (windows->class_hints->res_name != (char *) NULL)
396 windows->class_hints->res_name=DestroyString(
397 windows->class_hints->res_name);
398 if (windows->class_hints->res_class != (char *) NULL)
399 windows->class_hints->res_class=DestroyString(
400 windows->class_hints->res_class);
cristy3ed852e2009-09-05 21:47:34 +0000401 XFree(windows->class_hints);
402 windows->class_hints=(XClassHint *) NULL;
403 }
404 if (windows->manager_hints != (XWMHints *) NULL)
405 {
406 XFree(windows->manager_hints);
407 windows->manager_hints=(XWMHints *) NULL;
408 }
409 if (windows->map_info != (XStandardColormap *) NULL)
410 {
411 XFree(windows->map_info);
412 windows->map_info=(XStandardColormap *) NULL;
413 }
414 if (windows->icon_map != (XStandardColormap *) NULL)
415 {
416 XFree(windows->icon_map);
417 windows->icon_map=(XStandardColormap *) NULL;
418 }
419 if (windows->visual_info != (XVisualInfo *) NULL)
420 {
421 XFree(windows->visual_info);
422 windows->visual_info=(XVisualInfo *) NULL;
423 }
424 if (windows->icon_visual != (XVisualInfo *) NULL)
425 {
426 XFree(windows->icon_visual);
427 windows->icon_visual=(XVisualInfo *) NULL;
428 }
429 (void) XSetWindows((XWindows *) NULL);
430}
431
432/*
433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434% %
435% %
436% %
437% X A n n o t a t e I m a g e %
438% %
439% %
440% %
441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
442%
443% XAnnotateImage() annotates the image with text.
444%
445% The format of the XAnnotateImage method is:
446%
447% MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000448% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
449% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000450%
451% A description of each parameter follows:
452%
453% o display: Specifies a connection to an X server; returned from
454% XOpenDisplay.
455%
456% o pixel: Specifies a pointer to a XPixelInfo structure.
457%
458% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
459%
460% o image: the image.
461%
cristy7c3af952011-10-20 16:04:16 +0000462% o exception: return any errors or warnings in this structure.
463%
cristy3ed852e2009-09-05 21:47:34 +0000464*/
cristybcbda3f2011-09-03 13:01:22 +0000465MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000466 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
467 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000468{
cristyc57f6942010-11-12 01:47:39 +0000469 CacheView
470 *annotate_view;
471
cristy3ed852e2009-09-05 21:47:34 +0000472 GC
473 annotate_context;
474
cristy3ed852e2009-09-05 21:47:34 +0000475 Image
476 *annotate_image;
477
478 int
479 x,
480 y;
481
482 MagickBooleanType
483 matte;
484
485 Pixmap
486 annotate_pixmap;
487
488 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 */
cristy6710d842011-10-20 23:23:00 +0000547 annotate_image=AcquireImage((ImageInfo *) NULL,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);
cristyf05d4942012-03-17 16:26:09 +0000560 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
561 (ssize_t) y,&annotate_image->background_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000562 if (annotate_info->stencil == ForegroundStencil)
563 annotate_image->matte=MagickTrue;
cristydb070952012-04-20 14:33:00 +0000564 annotate_view=AcquireAuthenticCacheView(annotate_image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000565 for (y=0; y < (int) annotate_image->rows; y++)
566 {
cristyc57f6942010-11-12 01:47:39 +0000567 register int
cristy3ed852e2009-09-05 21:47:34 +0000568 x;
569
cristy4c08aed2011-07-01 19:47:50 +0000570 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000571 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000572
cristyc57f6942010-11-12 01:47:39 +0000573 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
574 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000575 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000576 break;
cristyc57f6942010-11-12 01:47:39 +0000577 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000578 {
cristy4c08aed2011-07-01 19:47:50 +0000579 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000580 if (XGetPixel(annotate_ximage,x,y) == 0)
581 {
582 /*
583 Set this pixel to the background color.
584 */
cristy4c08aed2011-07-01 19:47:50 +0000585 SetPixelRed(annotate_image,ScaleShortToQuantum(
586 pixel->box_color.red),q);
587 SetPixelGreen(annotate_image,ScaleShortToQuantum(
588 pixel->box_color.green),q);
589 SetPixelBlue(annotate_image,ScaleShortToQuantum(
590 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000591 if ((annotate_info->stencil == ForegroundStencil) ||
592 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000593 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000594 }
595 else
596 {
597 /*
598 Set this pixel to the pen color.
599 */
cristy4c08aed2011-07-01 19:47:50 +0000600 SetPixelRed(annotate_image,ScaleShortToQuantum(
601 pixel->pen_color.red),q);
602 SetPixelGreen(annotate_image,ScaleShortToQuantum(
603 pixel->pen_color.green),q);
604 SetPixelBlue(annotate_image,ScaleShortToQuantum(
605 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000606 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000607 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000608 }
cristyed231572011-07-14 02:18:59 +0000609 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000610 }
cristyc57f6942010-11-12 01:47:39 +0000611 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000612 break;
613 }
cristyc57f6942010-11-12 01:47:39 +0000614 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000615 XDestroyImage(annotate_ximage);
616 /*
617 Determine annotate geometry.
618 */
619 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
620 if ((width != (unsigned int) annotate_image->columns) ||
621 (height != (unsigned int) annotate_image->rows))
622 {
623 char
624 image_geometry[MaxTextExtent];
625
626 /*
627 Scale image.
628 */
cristyb51dff52011-05-19 16:55:47 +0000629 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000630 width,height);
cristye941a752011-10-15 01:52:48 +0000631 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
632 exception);
cristy3ed852e2009-09-05 21:47:34 +0000633 }
634 if (annotate_info->degrees != 0.0)
635 {
636 Image
637 *rotate_image;
638
639 int
640 rotations;
641
642 MagickRealType
643 normalized_degrees;
644
645 /*
646 Rotate image.
647 */
cristy6710d842011-10-20 23:23:00 +0000648 rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +0000649 if (rotate_image == (Image *) NULL)
650 return(MagickFalse);
651 annotate_image=DestroyImage(annotate_image);
652 annotate_image=rotate_image;
653 /*
654 Annotation is relative to the degree of rotation.
655 */
656 normalized_degrees=annotate_info->degrees;
657 while (normalized_degrees < -45.0)
658 normalized_degrees+=360.0;
659 for (rotations=0; normalized_degrees > 45.0; rotations++)
660 normalized_degrees-=90.0;
661 switch (rotations % 4)
662 {
663 default:
664 case 0:
665 break;
666 case 1:
667 {
668 /*
669 Rotate 90 degrees.
670 */
671 x-=(int) annotate_image->columns/2;
672 y+=(int) annotate_image->columns/2;
673 break;
674 }
675 case 2:
676 {
677 /*
678 Rotate 180 degrees.
679 */
680 x=x-(int) annotate_image->columns;
681 break;
682 }
683 case 3:
684 {
685 /*
686 Rotate 270 degrees.
687 */
688 x=x-(int) annotate_image->columns/2;
689 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
690 break;
691 }
692 }
693 }
694 /*
695 Composite text onto the image.
696 */
697 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
698 matte=image->matte;
cristyfeb3e962012-03-29 17:25:55 +0000699 (void) CompositeImage(image,annotate_image,
700 annotate_image->matte != MagickFalse ? OverCompositeOp : CopyCompositeOp,
cristy39172402012-03-30 13:04:39 +0000701 MagickTrue,(ssize_t) x,(ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +0000702 image->matte=matte;
703 annotate_image=DestroyImage(annotate_image);
704 return(MagickTrue);
705}
706
707/*
708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
709% %
710% %
711% %
712% X B e s t F o n t %
713% %
714% %
715% %
716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
717%
718% XBestFont() returns the "best" font. "Best" is defined as a font specified
719% in the X resource database or a font such that the text width displayed
720% with the font does not exceed the specified maximum width.
721%
722% The format of the XBestFont method is:
723%
724% XFontStruct *XBestFont(Display *display,
725% const XResourceInfo *resource_info,const MagickBooleanType text_font)
726%
727% A description of each parameter follows:
728%
729% o font: XBestFont returns a pointer to a XFontStruct structure.
730%
731% o display: Specifies a connection to an X server; returned from
732% XOpenDisplay.
733%
734% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
735%
736% o text_font: True is font should be mono-spaced (typewriter style).
737%
cristy3ed852e2009-09-05 21:47:34 +0000738*/
739
740static char **FontToList(char *font)
741{
742 char
743 **fontlist;
744
745 register char
746 *p,
747 *q;
748
749 register int
750 i;
751
752 unsigned int
753 fonts;
754
755 if (font == (char *) NULL)
756 return((char **) NULL);
757 /*
758 Convert string to an ASCII list.
759 */
760 fonts=1U;
761 for (p=font; *p != '\0'; p++)
762 if ((*p == ':') || (*p == ';') || (*p == ','))
763 fonts++;
764 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
765 if (fontlist == (char **) NULL)
766 {
767 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
768 font);
769 return((char **) NULL);
770 }
771 p=font;
772 for (i=0; i < (int) fonts; i++)
773 {
774 for (q=p; *q != '\0'; q++)
775 if ((*q == ':') || (*q == ';') || (*q == ','))
776 break;
777 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
778 sizeof(*fontlist[i]));
779 if (fontlist[i] == (char *) NULL)
780 {
781 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
782 font);
783 return((char **) NULL);
784 }
785 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
786 p=q+1;
787 }
788 fontlist[i]=(char *) NULL;
789 return(fontlist);
790}
791
cristybcbda3f2011-09-03 13:01:22 +0000792MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000793 const XResourceInfo *resource_info,const MagickBooleanType text_font)
794{
795 static const char
796 *Fonts[]=
797 {
798 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
799 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
800 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
801 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
802 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
803 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
804 "variable",
805 "fixed",
806 (char *) NULL
807 },
808 *TextFonts[]=
809 {
810 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
811 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
812 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
813 "fixed",
814 (char *) NULL
815 };
816
817 char
818 *font_name;
819
820 register const char
821 **p;
822
823 XFontStruct
824 *font_info;
825
826 font_info=(XFontStruct *) NULL;
827 font_name=resource_info->font;
828 if (text_font != MagickFalse)
829 font_name=resource_info->text_font;
830 if ((font_name != (char *) NULL) && (*font_name != '\0'))
831 {
832 char
833 **fontlist;
834
835 register int
836 i;
837
838 /*
839 Load preferred font specified in the X resource database.
840 */
841 fontlist=FontToList(font_name);
842 if (fontlist != (char **) NULL)
843 {
844 for (i=0; fontlist[i] != (char *) NULL; i++)
845 {
846 if (font_info == (XFontStruct *) NULL)
847 font_info=XLoadQueryFont(display,fontlist[i]);
848 fontlist[i]=DestroyString(fontlist[i]);
849 }
850 fontlist=(char **) RelinquishMagickMemory(fontlist);
851 }
852 if (font_info == (XFontStruct *) NULL)
853 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
854 }
855 /*
856 Load fonts from list of fonts until one is found.
857 */
858 p=Fonts;
859 if (text_font != MagickFalse)
860 p=TextFonts;
861 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
862 p++;
863 while (*p != (char *) NULL)
864 {
865 if (font_info != (XFontStruct *) NULL)
866 break;
867 font_info=XLoadQueryFont(display,(char *) *p);
868 p++;
869 }
870 return(font_info);
871}
872
873/*
874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875% %
876% %
877% %
878% X B e s t I c o n S i z e %
879% %
880% %
881% %
882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883%
884% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
885% size that maintains the aspect ratio of the image. If the window manager
886% has preferred icon sizes, one of the preferred sizes is used.
887%
888% The format of the XBestIconSize method is:
889%
890% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
891%
892% A description of each parameter follows:
893%
894% o display: Specifies a connection to an X server; returned from
895% XOpenDisplay.
896%
897% o image: the image.
898%
899*/
cristybcbda3f2011-09-03 13:01:22 +0000900MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000901 Image *image)
902{
903 int
904 i,
905 number_sizes;
906
907 MagickRealType
908 scale_factor;
909
910 unsigned int
911 height,
912 icon_height,
913 icon_width,
914 width;
915
916 Window
917 root_window;
918
919 XIconSize
920 *icon_size,
921 *size_list;
922
923 /*
924 Determine if the window manager has specified preferred icon sizes.
925 */
926 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
927 assert(display != (Display *) NULL);
928 assert(window != (XWindowInfo *) NULL);
929 assert(image != (Image *) NULL);
930 window->width=MaxIconSize;
931 window->height=MaxIconSize;
932 icon_size=(XIconSize *) NULL;
933 number_sizes=0;
934 root_window=XRootWindow(display,window->screen);
935 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
936 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
937 icon_size=size_list;
938 if (icon_size == (XIconSize *) NULL)
939 {
940 /*
941 Window manager does not restrict icon size.
942 */
943 icon_size=XAllocIconSize();
944 if (icon_size == (XIconSize *) NULL)
945 {
946 ThrowXWindowFatalException(ResourceLimitError,
947 "MemoryAllocationFailed",image->filename);
948 return;
949 }
950 icon_size->min_width=1;
951 icon_size->max_width=MaxIconSize;
952 icon_size->min_height=1;
953 icon_size->max_height=MaxIconSize;
954 icon_size->width_inc=1;
955 icon_size->height_inc=1;
956 }
957 /*
958 Determine aspect ratio of image.
959 */
960 width=(unsigned int) image->columns;
961 height=(unsigned int) image->rows;
962 i=0;
963 if (window->crop_geometry)
964 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
965 /*
966 Look for an icon size that maintains the aspect ratio of image.
967 */
968 scale_factor=(MagickRealType) icon_size->max_width/width;
969 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
970 scale_factor=(MagickRealType) icon_size->max_height/height;
971 icon_width=(unsigned int) icon_size->min_width;
972 while ((int) icon_width < icon_size->max_width)
973 {
974 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
975 break;
976 icon_width+=icon_size->width_inc;
977 }
978 icon_height=(unsigned int) icon_size->min_height;
979 while ((int) icon_height < icon_size->max_height)
980 {
981 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
982 break;
983 icon_height+=icon_size->height_inc;
984 }
985 (void) XFree((void *) icon_size);
986 window->width=icon_width;
987 window->height=icon_height;
988}
989
990/*
991%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992% %
993% %
994% %
995% X B e s t P i x e l %
996% %
997% %
998% %
999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000%
1001% XBestPixel() returns a pixel from an array of pixels that is closest to the
1002% requested color. If the color array is NULL, the colors are obtained from
1003% the X server.
1004%
1005% The format of the XBestPixel method is:
1006%
1007% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1008% unsigned int number_colors,XColor *color)
1009%
1010% A description of each parameter follows:
1011%
1012% o pixel: XBestPixel returns the pixel value closest to the requested
1013% color.
1014%
1015% o display: Specifies a connection to an X server; returned from
1016% XOpenDisplay.
1017%
1018% o colormap: Specifies the ID of the X server colormap.
1019%
1020% o colors: Specifies an array of XColor structures.
1021%
1022% o number_colors: Specifies the number of XColor structures in the
1023% color definition array.
1024%
1025% o color: Specifies the desired RGB value to find in the colors array.
1026%
1027*/
cristybcbda3f2011-09-03 13:01:22 +00001028MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001029 XColor *colors,unsigned int number_colors,XColor *color)
1030{
1031 MagickBooleanType
1032 query_server;
1033
cristy4c08aed2011-07-01 19:47:50 +00001034 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001035 pixel;
1036
1037 MagickRealType
1038 min_distance;
1039
1040 register MagickRealType
1041 distance;
1042
1043 register int
1044 i,
1045 j;
1046
1047 Status
1048 status;
1049
1050 /*
1051 Find closest representation for the requested RGB color.
1052 */
1053 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1054 assert(display != (Display *) NULL);
1055 assert(color != (XColor *) NULL);
1056 status=XAllocColor(display,colormap,color);
1057 if (status != False)
1058 return;
1059 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1060 if (query_server != MagickFalse)
1061 {
1062 /*
1063 Read X server colormap.
1064 */
1065 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1066 if (colors == (XColor *) NULL)
1067 {
1068 ThrowXWindowFatalException(ResourceLimitError,
1069 "MemoryAllocationFailed","...");
1070 return;
1071 }
1072 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001073 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001074 if (number_colors > 256)
1075 number_colors=256;
1076 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1077 }
1078 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1079 QuantumRange+1.0);
1080 j=0;
1081 for (i=0; i < (int) number_colors; i++)
1082 {
1083 pixel.red=colors[i].red-(MagickRealType) color->red;
1084 distance=pixel.red*pixel.red;
1085 if (distance > min_distance)
1086 continue;
1087 pixel.green=colors[i].green-(MagickRealType) color->green;
1088 distance+=pixel.green*pixel.green;
1089 if (distance > min_distance)
1090 continue;
1091 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1092 distance+=pixel.blue*pixel.blue;
1093 if (distance > min_distance)
1094 continue;
1095 min_distance=distance;
1096 color->pixel=colors[i].pixel;
1097 j=i;
1098 }
1099 (void) XAllocColor(display,colormap,&colors[j]);
1100 if (query_server != MagickFalse)
1101 colors=(XColor *) RelinquishMagickMemory(colors);
1102}
1103
1104/*
1105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1106% %
1107% %
1108% %
1109% X B e s t V i s u a l I n f o %
1110% %
1111% %
1112% %
1113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114%
1115% XBestVisualInfo() returns visual information for a visual that is the "best"
1116% the server supports. "Best" is defined as:
1117%
1118% 1. Restrict the visual list to those supported by the default screen.
1119%
1120% 2. If a visual type is specified, restrict the visual list to those of
1121% that type.
1122%
1123% 3. If a map type is specified, choose the visual that matches the id
1124% specified by the Standard Colormap.
1125%
1126% 4 From the list of visuals, choose one that can display the most
1127% simultaneous colors. If more than one visual can display the same
1128% number of simultaneous colors, one is chosen based on a rank.
1129%
1130% The format of the XBestVisualInfo method is:
1131%
1132% XVisualInfo *XBestVisualInfo(Display *display,
1133% XStandardColormap *map_info,XResourceInfo *resource_info)
1134%
1135% A description of each parameter follows:
1136%
1137% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1138% structure.
1139%
1140% o display: Specifies a connection to an X server; returned from
1141% XOpenDisplay.
1142%
1143% o map_info: If map_type is specified, this structure is initialized
1144% with info from the Standard Colormap.
1145%
1146% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1147%
1148*/
1149
1150static inline int MagickMax(const int x,const int y)
1151{
1152 if (x > y)
1153 return(x);
1154 return(y);
1155}
1156
cristybb503372010-05-27 20:51:26 +00001157static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001158 const unsigned int y)
1159{
1160 if (x < y)
1161 return(x);
1162 return(y);
1163}
1164
cristybcbda3f2011-09-03 13:01:22 +00001165MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001166 XStandardColormap *map_info,XResourceInfo *resource_info)
1167{
1168#define MaxStandardColormaps 7
1169#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1170 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1171 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1172 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1173
1174 char
1175 *map_type,
1176 *visual_type;
1177
cristyc57f6942010-11-12 01:47:39 +00001178 int
1179 visual_mask;
1180
cristy3ed852e2009-09-05 21:47:34 +00001181 register int
1182 i;
1183
cristy8891f9c2010-06-04 23:32:17 +00001184 size_t
1185 one;
1186
cristy3ed852e2009-09-05 21:47:34 +00001187 static int
1188 number_visuals;
1189
1190 static XVisualInfo
1191 visual_template;
1192
1193 XVisualInfo
1194 *visual_info,
1195 *visual_list;
1196
1197 /*
1198 Restrict visual search by screen number.
1199 */
1200 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1201 assert(display != (Display *) NULL);
1202 assert(map_info != (XStandardColormap *) NULL);
1203 assert(resource_info != (XResourceInfo *) NULL);
1204 map_type=resource_info->map_type;
1205 visual_type=resource_info->visual_type;
1206 visual_mask=VisualScreenMask;
1207 visual_template.screen=XDefaultScreen(display);
1208 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001209 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001210 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001211 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001212 visual_mask|=VisualDepthMask;
1213 if (visual_type != (char *) NULL)
1214 {
1215 /*
1216 Restrict visual search by class or visual id.
1217 */
1218 if (LocaleCompare("staticgray",visual_type) == 0)
1219 {
1220 visual_mask|=VisualClassMask;
1221 visual_template.klass=StaticGray;
1222 }
1223 else
1224 if (LocaleCompare("grayscale",visual_type) == 0)
1225 {
1226 visual_mask|=VisualClassMask;
1227 visual_template.klass=GrayScale;
1228 }
1229 else
1230 if (LocaleCompare("staticcolor",visual_type) == 0)
1231 {
1232 visual_mask|=VisualClassMask;
1233 visual_template.klass=StaticColor;
1234 }
1235 else
1236 if (LocaleCompare("pseudocolor",visual_type) == 0)
1237 {
1238 visual_mask|=VisualClassMask;
1239 visual_template.klass=PseudoColor;
1240 }
1241 else
1242 if (LocaleCompare("truecolor",visual_type) == 0)
1243 {
1244 visual_mask|=VisualClassMask;
1245 visual_template.klass=TrueColor;
1246 }
1247 else
1248 if (LocaleCompare("directcolor",visual_type) == 0)
1249 {
1250 visual_mask|=VisualClassMask;
1251 visual_template.klass=DirectColor;
1252 }
1253 else
1254 if (LocaleCompare("default",visual_type) == 0)
1255 {
1256 visual_mask|=VisualIDMask;
1257 visual_template.visualid=XVisualIDFromVisual(
1258 XDefaultVisual(display,XDefaultScreen(display)));
1259 }
1260 else
1261 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1262 {
1263 visual_mask|=VisualIDMask;
1264 visual_template.visualid=
1265 strtol(visual_type,(char **) NULL,0);
1266 }
1267 else
1268 ThrowXWindowFatalException(XServerError,
1269 "UnrecognizedVisualSpecifier",visual_type);
1270 }
1271 /*
1272 Get all visuals that meet our criteria so far.
1273 */
1274 number_visuals=0;
1275 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1276 &number_visuals);
1277 visual_mask=VisualScreenMask | VisualIDMask;
1278 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1279 {
1280 /*
1281 Failed to get visual; try using the default visual.
1282 */
1283 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1284 visual_type);
1285 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1286 XDefaultScreen(display)));
1287 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1288 &number_visuals);
1289 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1290 return((XVisualInfo *) NULL);
1291 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1292 XVisualClassName(visual_list->klass));
1293 }
1294 resource_info->color_recovery=MagickFalse;
1295 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1296 {
1297 Atom
1298 map_property;
1299
1300 char
1301 map_name[MaxTextExtent];
1302
1303 int
1304 j,
1305 number_maps;
1306
1307 Status
1308 status;
1309
1310 Window
1311 root_window;
1312
1313 XStandardColormap
1314 *map_list;
1315
1316 /*
1317 Choose a visual associated with a standard colormap.
1318 */
1319 root_window=XRootWindow(display,XDefaultScreen(display));
1320 status=False;
1321 if (LocaleCompare(map_type,"list") != 0)
1322 {
1323 /*
1324 User specified Standard Colormap.
1325 */
cristyb51dff52011-05-19 16:55:47 +00001326 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001327 "RGB_%s_MAP",map_type);
1328 LocaleUpper(map_name);
1329 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1330 if (map_property != (Atom) NULL)
1331 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1332 map_property);
1333 }
1334 else
1335 {
1336 static const char
1337 *colormap[MaxStandardColormaps]=
1338 {
1339 "_HP_RGB_SMOOTH_MAP_LIST",
1340 "RGB_BEST_MAP",
1341 "RGB_DEFAULT_MAP",
1342 "RGB_GRAY_MAP",
1343 "RGB_RED_MAP",
1344 "RGB_GREEN_MAP",
1345 "RGB_BLUE_MAP",
1346 };
1347
1348 /*
1349 Choose a standard colormap from a list.
1350 */
1351 for (i=0; i < MaxStandardColormaps; i++)
1352 {
1353 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1354 if (map_property == (Atom) NULL)
1355 continue;
1356 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1357 map_property);
1358 if (status != False)
1359 break;
1360 }
1361 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1362 }
1363 if (status == False)
1364 {
1365 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1366 map_type);
1367 return((XVisualInfo *) NULL);
1368 }
1369 /*
1370 Search all Standard Colormaps and visuals for ids that match.
1371 */
1372 *map_info=map_list[0];
1373#if !defined(PRE_R4_ICCCM)
1374 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1375 for (i=0; i < number_maps; i++)
1376 for (j=0; j < number_visuals; j++)
1377 if (map_list[i].visualid ==
1378 XVisualIDFromVisual(visual_list[j].visual))
1379 {
1380 *map_info=map_list[i];
1381 visual_template.visualid=XVisualIDFromVisual(
1382 visual_list[j].visual);
1383 break;
1384 }
1385 if (map_info->visualid != visual_template.visualid)
1386 {
1387 ThrowXWindowFatalException(XServerError,
1388 "UnableToMatchVisualToStandardColormap",map_type);
1389 return((XVisualInfo *) NULL);
1390 }
1391#endif
1392 if (map_info->colormap == (Colormap) NULL)
1393 {
1394 ThrowXWindowFatalException(XServerError,
1395 "StandardColormapIsNotInitialized",map_type);
1396 return((XVisualInfo *) NULL);
1397 }
1398 (void) XFree((void *) map_list);
1399 }
1400 else
1401 {
1402 static const unsigned int
1403 rank[]=
1404 {
1405 StaticGray,
1406 GrayScale,
1407 StaticColor,
1408 DirectColor,
1409 TrueColor,
1410 PseudoColor
1411 };
1412
1413 XVisualInfo
1414 *p;
1415
1416 /*
1417 Pick one visual that displays the most simultaneous colors.
1418 */
1419 visual_info=visual_list;
1420 p=visual_list;
1421 for (i=1; i < number_visuals; i++)
1422 {
1423 p++;
1424 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1425 visual_info=p;
1426 else
1427 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1428 if (rank[p->klass] > rank[visual_info->klass])
1429 visual_info=p;
1430 }
1431 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1432 }
1433 (void) XFree((void *) visual_list);
1434 /*
1435 Retrieve only one visual by its screen & id number.
1436 */
1437 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1438 &number_visuals);
1439 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1440 return((XVisualInfo *) NULL);
1441 return(visual_info);
1442}
1443
1444/*
1445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1446% %
1447% %
1448% %
1449% X C h e c k D e f i n e C u r s o r %
1450% %
1451% %
1452% %
1453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1454%
1455% XCheckDefineCursor() prevents cursor changes on the root window.
1456%
1457% The format of the XXCheckDefineCursor method is:
1458%
1459% XCheckDefineCursor(display,window,cursor)
1460%
1461% A description of each parameter follows:
1462%
1463% o display: Specifies a connection to an X server; returned from
1464% XOpenDisplay.
1465%
1466% o window: the window.
1467%
1468% o cursor: the cursor.
1469%
1470*/
cristybcbda3f2011-09-03 13:01:22 +00001471MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001472 Cursor cursor)
1473{
1474 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1475 assert(display != (Display *) NULL);
1476 if (window == XRootWindow(display,XDefaultScreen(display)))
1477 return(0);
1478 return(XDefineCursor(display,window,cursor));
1479}
1480
1481/*
1482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1483% %
1484% %
1485% %
1486% X C h e c k R e f r e s h W i n d o w s %
1487% %
1488% %
1489% %
1490%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1491%
1492% XCheckRefreshWindows() checks the X server for exposure events for a
1493% particular window and updates the areassociated with the exposure event.
1494%
1495% The format of the XCheckRefreshWindows method is:
1496%
1497% void XCheckRefreshWindows(Display *display,XWindows *windows)
1498%
1499% A description of each parameter follows:
1500%
1501% o display: Specifies a connection to an X server; returned from
1502% XOpenDisplay.
1503%
1504% o windows: Specifies a pointer to a XWindows structure.
1505%
1506*/
cristybcbda3f2011-09-03 13:01:22 +00001507MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001508{
1509 Window
1510 id;
1511
1512 XEvent
1513 event;
1514
1515 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1516 assert(display != (Display *) NULL);
1517 assert(windows != (XWindows *) NULL);
1518 XDelay(display,SuspendTime);
1519 id=windows->command.id;
1520 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1521 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1522 id=windows->image.id;
1523 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1524 XRefreshWindow(display,&windows->image,&event);
1525 XDelay(display,SuspendTime << 1);
1526 id=windows->command.id;
1527 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1528 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1529 id=windows->image.id;
1530 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1531 XRefreshWindow(display,&windows->image,&event);
1532}
1533
1534/*
1535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1536% %
1537% %
1538% %
1539% X C l i e n t M e s s a g e %
1540% %
1541% %
1542% %
1543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1544%
1545% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1546% initialized with a particular protocol type and atom.
1547%
1548% The format of the XClientMessage function is:
1549%
1550% XClientMessage(display,window,protocol,reason,timestamp)
1551%
1552% A description of each parameter follows:
1553%
1554% o display: Specifies a pointer to the Display structure; returned from
1555% XOpenDisplay.
1556%
1557% o window: Specifies a pointer to a Window structure.
1558%
1559% o protocol: Specifies an atom value.
1560%
1561% o reason: Specifies an atom value which is the reason to send.
1562%
1563% o timestamp: Specifies a value of type Time.
1564%
1565*/
cristybcbda3f2011-09-03 13:01:22 +00001566MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001567 const Atom protocol,const Atom reason,const Time timestamp)
1568{
1569 XClientMessageEvent
1570 client_event;
1571
1572 assert(display != (Display *) NULL);
1573 client_event.type=ClientMessage;
1574 client_event.window=window;
1575 client_event.message_type=protocol;
1576 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001577 client_event.data.l[0]=(long) reason;
1578 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001579 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1580}
1581
1582/*
1583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1584% %
1585% %
1586% %
1587+ X C l i e n t W i n d o w %
1588% %
1589% %
1590% %
1591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1592%
1593% XClientWindow() finds a window, at or below the specified window, which has
1594% a WM_STATE property. If such a window is found, it is returned, otherwise
1595% the argument window is returned.
1596%
1597% The format of the XClientWindow function is:
1598%
1599% client_window=XClientWindow(display,target_window)
1600%
1601% A description of each parameter follows:
1602%
1603% o client_window: XClientWindow returns a window, at or below the specified
1604% window, which has a WM_STATE property otherwise the argument
1605% target_window is returned.
1606%
1607% o display: Specifies a pointer to the Display structure; returned from
1608% XOpenDisplay.
1609%
1610% o target_window: Specifies the window to find a WM_STATE property.
1611%
cristy3ed852e2009-09-05 21:47:34 +00001612*/
1613static Window XClientWindow(Display *display,Window target_window)
1614{
1615 Atom
1616 state,
1617 type;
1618
1619 int
1620 format;
1621
1622 Status
1623 status;
1624
1625 unsigned char
1626 *data;
1627
cristyf2faecf2010-05-28 19:19:36 +00001628 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001629 after,
1630 number_items;
1631
1632 Window
1633 client_window;
1634
1635 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1636 assert(display != (Display *) NULL);
1637 state=XInternAtom(display,"WM_STATE",MagickTrue);
1638 if (state == (Atom) NULL)
1639 return(target_window);
1640 type=(Atom) NULL;
1641 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1642 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1643 if ((status == Success) && (type != (Atom) NULL))
1644 return(target_window);
1645 client_window=XWindowByProperty(display,target_window,state);
1646 if (client_window == (Window) NULL)
1647 return(target_window);
1648 return(client_window);
1649}
1650
1651/*
1652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1653% %
1654% %
1655% %
cristyf34a1452009-10-24 22:29:27 +00001656+ X C o m p o n e n t T e r m i n u s %
1657% %
1658% %
1659% %
1660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1661%
1662% XComponentTerminus() destroys the module component.
1663%
1664% The format of the XComponentTerminus method is:
1665%
1666% XComponentTerminus(void)
1667%
1668*/
cristy5ff4eaf2011-09-03 01:38:02 +00001669MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001670{
1671 DestroyXResources();
1672}
1673
1674/*
1675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1676% %
1677% %
1678% %
cristy3ed852e2009-09-05 21:47:34 +00001679% X C o n f i g u r e I m a g e C o l o r m a p %
1680% %
1681% %
1682% %
1683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1684%
1685% XConfigureImageColormap() creates a new X colormap.
1686%
1687% The format of the XConfigureImageColormap method is:
1688%
1689% void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001690% XResourceInfo *resource_info,XWindows *windows,Image *image,
1691% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001692%
1693% A description of each parameter follows:
1694%
1695% o display: Specifies a connection to an X server; returned from
1696% XOpenDisplay.
1697%
1698% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1699%
1700% o windows: Specifies a pointer to a XWindows structure.
1701%
1702% o image: the image.
1703%
cristy6710d842011-10-20 23:23:00 +00001704% o exception: return any errors or warnings in this structure.
1705%
cristy3ed852e2009-09-05 21:47:34 +00001706*/
cristybcbda3f2011-09-03 13:01:22 +00001707MagickPrivate void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001708 XResourceInfo *resource_info,XWindows *windows,Image *image,
1709 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001710{
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,
cristy6710d842011-10-20 23:23:00 +00001720 windows->map_info,windows->pixel_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00001721 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,
cristy6710d842011-10-20 23:23:00 +00001943% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001944%
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%
cristy6710d842011-10-20 23:23:00 +00001958% o exception: return any errors or warnings in this structure.
1959%
cristy3ed852e2009-09-05 21:47:34 +00001960*/
cristybcbda3f2011-09-03 13:01:22 +00001961MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001962 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001963 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001964{
1965 char
1966 filename[MaxTextExtent],
1967 *text,
1968 **textlist;
1969
1970 FILE
1971 *file;
1972
1973 int
1974 unique_file;
1975
cristybb503372010-05-27 20:51:26 +00001976 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001977 i;
1978
cristybb503372010-05-27 20:51:26 +00001979 size_t
cristy3ed852e2009-09-05 21:47:34 +00001980 number_pixels;
1981
cristy9d314ff2011-03-09 01:30:28 +00001982 ssize_t
1983 bytes;
1984
1985 unsigned int
1986 levels;
1987
cristy3ed852e2009-09-05 21:47:34 +00001988 /*
1989 Write info about the X server to a file.
1990 */
1991 assert(display != (Display *) NULL);
1992 assert(resource_info != (XResourceInfo *) NULL);
1993 assert(windows != (XWindows *) NULL);
1994 assert(image != (Image *) NULL);
1995 if (image->debug)
1996 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1997 file=(FILE *) NULL;
1998 unique_file=AcquireUniqueFileResource(filename);
1999 if (unique_file != -1)
2000 file=fdopen(unique_file,"w");
2001 if ((unique_file == -1) || (file == (FILE *) NULL))
2002 {
2003 XNoticeWidget(display,windows,"Unable to display image info",filename);
2004 return;
2005 }
2006 if (resource_info->gamma_correct != MagickFalse)
2007 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002008 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002009 resource_info->display_gamma);
2010 /*
2011 Write info about the X image to a file.
2012 */
cristyb51dff52011-05-19 16:55:47 +00002013 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002014 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002015 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002016 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002017 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002018 windows->visual_info->colormap_size);
2019 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002020 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002021 else
cristyb51dff52011-05-19 16:55:47 +00002022 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002023 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2024 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002025 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002026 (void) FormatLocaleFile(file," crop geometry: %s\n",
2027 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002028 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002029 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002030 else
cristyb51dff52011-05-19 16:55:47 +00002031 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002032 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002033 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002034 else
cristyb51dff52011-05-19 16:55:47 +00002035 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002036 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002037 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002038 else
cristyb51dff52011-05-19 16:55:47 +00002039 (void) FormatLocaleFile(file," shared memory: False\n");
2040 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002041 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002042 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002043 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002044 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002045 /*
2046 Write info about the undo cache to a file.
2047 */
2048 bytes=0;
2049 for (levels=0; undo_image != (Image *) NULL; levels++)
2050 {
2051 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002052 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002053 undo_image=GetPreviousImageInList(undo_image);
2054 }
cristyb51dff52011-05-19 16:55:47 +00002055 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002056 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2057 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002058 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002059 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002060 /*
2061 Write info about the image to a file.
2062 */
cristy6710d842011-10-20 23:23:00 +00002063 (void) IdentifyImage(image,file,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00002064 (void) fclose(file);
cristy6710d842011-10-20 23:23:00 +00002065 text=FileToString(filename,~0,exception);
cristy3ed852e2009-09-05 21:47:34 +00002066 (void) RelinquishUniqueFileResource(filename);
2067 if (text == (char *) NULL)
2068 {
2069 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2070 "UnableToDisplayImageInfo");
2071 return;
2072 }
2073 textlist=StringToList(text);
2074 if (textlist != (char **) NULL)
2075 {
2076 char
2077 title[MaxTextExtent];
2078
2079 /*
2080 Display information about the image in the Text View widget.
2081 */
2082 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002083 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002084 image->filename);
2085 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2086 (char const **) textlist);
2087 for (i=0; textlist[i] != (char *) NULL; i++)
2088 textlist[i]=DestroyString(textlist[i]);
2089 textlist=(char **) RelinquishMagickMemory(textlist);
2090 }
2091 text=DestroyString(text);
2092}
2093
2094/*
2095%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2096% %
2097% %
2098% %
2099+ X D i t h e r I m a g e %
2100% %
2101% %
2102% %
2103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2104%
2105% XDitherImage() dithers the reference image as required by the HP Color
2106% Recovery algorithm. The color values are quantized to 3 bits of red and
2107% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2108% standard colormap.
2109%
2110% The format of the XDitherImage method is:
2111%
cristy6710d842011-10-20 23:23:00 +00002112% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002113%
2114% A description of each parameter follows:
2115%
2116% o image: the image.
2117%
2118% o ximage: Specifies a pointer to a XImage structure; returned from
2119% XCreateImage.
2120%
cristy6710d842011-10-20 23:23:00 +00002121% o exception: return any errors or warnings in this structure.
2122%
cristy3ed852e2009-09-05 21:47:34 +00002123*/
cristy6710d842011-10-20 23:23:00 +00002124static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002125{
2126 static const short int
2127 dither_red[2][16]=
2128 {
2129 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2130 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2131 },
2132 dither_green[2][16]=
2133 {
2134 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2135 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2136 },
2137 dither_blue[2][16]=
2138 {
2139 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2140 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2141 };
2142
cristyc57f6942010-11-12 01:47:39 +00002143 CacheView
2144 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002145
2146 int
cristyc57f6942010-11-12 01:47:39 +00002147 value,
cristy3ed852e2009-09-05 21:47:34 +00002148 y;
2149
cristy101ab702011-10-13 13:06:32 +00002150 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002151 color;
cristy3ed852e2009-09-05 21:47:34 +00002152
2153 register char
2154 *q;
2155
cristy4c08aed2011-07-01 19:47:50 +00002156 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002157 *p;
2158
2159 register int
2160 i,
2161 j,
2162 x;
2163
2164 unsigned int
2165 scanline_pad;
2166
cristybb503372010-05-27 20:51:26 +00002167 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002168 pixel;
2169
2170 unsigned char
2171 *blue_map[2][16],
2172 *green_map[2][16],
2173 *red_map[2][16];
2174
2175 /*
2176 Allocate and initialize dither maps.
2177 */
2178 for (i=0; i < 2; i++)
2179 for (j=0; j < 16; j++)
2180 {
2181 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2182 sizeof(*red_map));
2183 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2184 sizeof(*green_map));
2185 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2186 sizeof(*blue_map));
2187 if ((red_map[i][j] == (unsigned char *) NULL) ||
2188 (green_map[i][j] == (unsigned char *) NULL) ||
2189 (blue_map[i][j] == (unsigned char *) NULL))
2190 {
2191 ThrowXWindowFatalException(ResourceLimitError,
2192 "MemoryAllocationFailed",image->filename);
2193 return;
2194 }
2195 }
2196 /*
2197 Initialize dither tables.
2198 */
2199 for (i=0; i < 2; i++)
2200 for (j=0; j < 16; j++)
2201 for (x=0; x < 256; x++)
2202 {
2203 value=x-16;
2204 if (x < 48)
2205 value=x/2+8;
2206 value+=dither_red[i][j];
2207 red_map[i][j][x]=(unsigned char)
2208 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2209 value=x-16;
2210 if (x < 48)
2211 value=x/2+8;
2212 value+=dither_green[i][j];
2213 green_map[i][j][x]=(unsigned char)
2214 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2215 value=x-32;
2216 if (x < 112)
2217 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002218 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002219 blue_map[i][j][x]=(unsigned char)
2220 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2221 }
2222 /*
2223 Dither image.
2224 */
2225 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002226 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002227 i=0;
2228 j=0;
2229 q=ximage->data;
cristydb070952012-04-20 14:33:00 +00002230 image_view=AcquireVirtualCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002231 for (y=0; y < (int) image->rows; y++)
2232 {
cristyc57f6942010-11-12 01:47:39 +00002233 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
cristy6710d842011-10-20 23:23:00 +00002234 exception);
cristy4c08aed2011-07-01 19:47:50 +00002235 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002236 break;
2237 for (x=0; x < (int) image->columns; x++)
2238 {
cristye42f6582012-02-11 17:59:50 +00002239 color.red=(double) ClampToQuantum((MagickRealType) (red_map[i][j][
2240 (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
2241 color.green=(double) ClampToQuantum((MagickRealType) (green_map[i][j][
2242 (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
2243 color.blue=(double) ClampToQuantum((MagickRealType) (blue_map[i][j][
2244 (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002245 pixel=(size_t) (((size_t) color.red & 0xe0) |
2246 (((size_t) color.green & 0xe0) >> 3) |
2247 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002248 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002249 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002250 j++;
2251 if (j == 16)
2252 j=0;
2253 }
2254 q+=scanline_pad;
2255 i++;
2256 if (i == 2)
2257 i=0;
2258 }
cristyc57f6942010-11-12 01:47:39 +00002259 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002260 /*
2261 Free allocated memory.
2262 */
2263 for (i=0; i < 2; i++)
2264 for (j=0; j < 16; j++)
2265 {
2266 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2267 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2268 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2269 }
2270}
2271
2272/*
2273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2274% %
2275% %
2276% %
2277% X D r a w I m a g e %
2278% %
2279% %
2280% %
2281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2282%
2283% XDrawImage() draws a line on the image.
2284%
2285% The format of the XDrawImage method is:
2286%
cristy6710d842011-10-20 23:23:00 +00002287% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2288% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002289%
2290% A description of each parameter follows:
2291%
2292% o display: Specifies a connection to an X server; returned from
2293% XOpenDisplay.
2294%
2295% o pixel: Specifies a pointer to a XPixelInfo structure.
2296%
2297% o draw_info: Specifies a pointer to a XDrawInfo structure.
2298%
2299% o image: the image.
2300%
cristy6710d842011-10-20 23:23:00 +00002301% o exception: return any errors or warnings in this structure.
2302%
cristy3ed852e2009-09-05 21:47:34 +00002303*/
cristybcbda3f2011-09-03 13:01:22 +00002304MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy6710d842011-10-20 23:23:00 +00002305 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2306 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002307{
cristyc57f6942010-11-12 01:47:39 +00002308 CacheView
2309 *draw_view;
2310
cristy3ed852e2009-09-05 21:47:34 +00002311 GC
2312 draw_context;
2313
2314 Image
2315 *draw_image;
2316
2317 int
2318 x,
2319 y;
2320
2321 MagickBooleanType
2322 matte;
2323
2324 Pixmap
2325 draw_pixmap;
2326
2327 unsigned int
2328 depth,
2329 height,
2330 width;
2331
2332 Window
2333 root_window;
2334
2335 XGCValues
2336 context_values;
2337
2338 XImage
2339 *draw_ximage;
2340
2341 /*
2342 Initialize drawd image.
2343 */
2344 assert(display != (Display *) NULL);
2345 assert(pixel != (XPixelInfo *) NULL);
2346 assert(draw_info != (XDrawInfo *) NULL);
2347 assert(image != (Image *) NULL);
2348 if (image->debug != MagickFalse)
2349 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2350 /*
2351 Initialize drawd pixmap.
2352 */
2353 root_window=XRootWindow(display,XDefaultScreen(display));
2354 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2355 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2356 draw_info->height,depth);
2357 if (draw_pixmap == (Pixmap) NULL)
2358 return(MagickFalse);
2359 /*
2360 Initialize graphics info.
2361 */
cristybb503372010-05-27 20:51:26 +00002362 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002363 context_values.foreground=0;
2364 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002365 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002366 (GCBackground | GCForeground | GCLineWidth),&context_values);
2367 if (draw_context == (GC) NULL)
2368 return(MagickFalse);
2369 /*
2370 Clear pixmap.
2371 */
2372 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2373 draw_info->height);
2374 /*
2375 Draw line to pixmap.
2376 */
2377 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002378 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002379 if (draw_info->stipple != (Pixmap) NULL)
2380 {
2381 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2382 (void) XSetStipple(display,draw_context,draw_info->stipple);
2383 }
cristy3ed852e2009-09-05 21:47:34 +00002384 switch (draw_info->element)
2385 {
2386 case PointElement:
2387 default:
2388 {
2389 (void) XDrawLines(display,draw_pixmap,draw_context,
2390 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2391 CoordModeOrigin);
2392 break;
2393 }
2394 case LineElement:
2395 {
2396 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2397 draw_info->line_info.y1,draw_info->line_info.x2,
2398 draw_info->line_info.y2);
2399 break;
2400 }
2401 case RectangleElement:
2402 {
2403 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2404 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2405 (unsigned int) draw_info->rectangle_info.width,
2406 (unsigned int) draw_info->rectangle_info.height);
2407 break;
2408 }
2409 case FillRectangleElement:
2410 {
2411 (void) XFillRectangle(display,draw_pixmap,draw_context,
2412 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2413 (unsigned int) draw_info->rectangle_info.width,
2414 (unsigned int) draw_info->rectangle_info.height);
2415 break;
2416 }
2417 case CircleElement:
2418 case EllipseElement:
2419 {
2420 (void) XDrawArc(display,draw_pixmap,draw_context,
2421 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2422 (unsigned int) draw_info->rectangle_info.width,
2423 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2424 break;
2425 }
2426 case FillCircleElement:
2427 case FillEllipseElement:
2428 {
2429 (void) XFillArc(display,draw_pixmap,draw_context,
2430 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2431 (unsigned int) draw_info->rectangle_info.width,
2432 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2433 break;
2434 }
2435 case PolygonElement:
2436 {
2437 XPoint
2438 *coordinate_info;
2439
2440 coordinate_info=draw_info->coordinate_info;
2441 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2442 (int) draw_info->number_coordinates,CoordModeOrigin);
2443 (void) XDrawLine(display,draw_pixmap,draw_context,
2444 coordinate_info[draw_info->number_coordinates-1].x,
2445 coordinate_info[draw_info->number_coordinates-1].y,
2446 coordinate_info[0].x,coordinate_info[0].y);
2447 break;
2448 }
2449 case FillPolygonElement:
2450 {
2451 (void) XFillPolygon(display,draw_pixmap,draw_context,
2452 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2453 CoordModeOrigin);
2454 break;
2455 }
2456 }
2457 (void) XFreeGC(display,draw_context);
2458 /*
2459 Initialize X image.
2460 */
2461 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2462 draw_info->height,AllPlanes,ZPixmap);
2463 if (draw_ximage == (XImage *) NULL)
2464 return(MagickFalse);
2465 (void) XFreePixmap(display,draw_pixmap);
2466 /*
2467 Initialize draw image.
2468 */
cristy6710d842011-10-20 23:23:00 +00002469 draw_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002470 if (draw_image == (Image *) NULL)
2471 return(MagickFalse);
2472 draw_image->columns=draw_info->width;
2473 draw_image->rows=draw_info->height;
2474 /*
2475 Transfer drawn X image to image.
2476 */
2477 width=(unsigned int) image->columns;
2478 height=(unsigned int) image->rows;
2479 x=0;
2480 y=0;
2481 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +00002482 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
2483 (ssize_t) y,&draw_image->background_color,exception);
cristy6710d842011-10-20 23:23:00 +00002484 if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002485 return(MagickFalse);
2486 draw_image->matte=MagickTrue;
cristydb070952012-04-20 14:33:00 +00002487 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002488 for (y=0; y < (int) draw_image->rows; y++)
2489 {
cristyc57f6942010-11-12 01:47:39 +00002490 register int
cristy3ed852e2009-09-05 21:47:34 +00002491 x;
2492
cristy4c08aed2011-07-01 19:47:50 +00002493 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002494 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002495
cristyc57f6942010-11-12 01:47:39 +00002496 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2497 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002498 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002499 break;
cristyc57f6942010-11-12 01:47:39 +00002500 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002501 {
2502 if (XGetPixel(draw_ximage,x,y) == 0)
2503 {
2504 /*
2505 Set this pixel to the background color.
2506 */
cristy803640d2011-11-17 02:11:32 +00002507 SetPixelInfoPixel(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002508 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002509 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002510 }
2511 else
2512 {
2513 /*
2514 Set this pixel to the pen color.
2515 */
cristy4c08aed2011-07-01 19:47:50 +00002516 SetPixelRed(draw_image,ScaleShortToQuantum(
2517 pixel->pen_color.red),q);
2518 SetPixelGreen(draw_image,ScaleShortToQuantum(
2519 pixel->pen_color.green),q);
2520 SetPixelBlue(draw_image,ScaleShortToQuantum(
2521 pixel->pen_color.blue),q);
2522 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2523 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002524 }
cristyed231572011-07-14 02:18:59 +00002525 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002526 }
cristyc57f6942010-11-12 01:47:39 +00002527 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002528 break;
2529 }
cristyc57f6942010-11-12 01:47:39 +00002530 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002531 XDestroyImage(draw_ximage);
2532 /*
2533 Determine draw geometry.
2534 */
2535 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2536 if ((width != (unsigned int) draw_image->columns) ||
2537 (height != (unsigned int) draw_image->rows))
2538 {
2539 char
2540 image_geometry[MaxTextExtent];
2541
2542 /*
2543 Scale image.
2544 */
cristyb51dff52011-05-19 16:55:47 +00002545 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002546 width,height);
cristye941a752011-10-15 01:52:48 +00002547 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2548 exception);
cristy3ed852e2009-09-05 21:47:34 +00002549 }
2550 if (draw_info->degrees != 0.0)
2551 {
2552 Image
2553 *rotate_image;
2554
2555 int
2556 rotations;
2557
2558 MagickRealType
2559 normalized_degrees;
2560
2561 /*
2562 Rotate image.
2563 */
cristy6710d842011-10-20 23:23:00 +00002564 rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +00002565 if (rotate_image == (Image *) NULL)
2566 return(MagickFalse);
2567 draw_image=DestroyImage(draw_image);
2568 draw_image=rotate_image;
2569 /*
2570 Annotation is relative to the degree of rotation.
2571 */
2572 normalized_degrees=draw_info->degrees;
2573 while (normalized_degrees < -45.0)
2574 normalized_degrees+=360.0;
2575 for (rotations=0; normalized_degrees > 45.0; rotations++)
2576 normalized_degrees-=90.0;
2577 switch (rotations % 4)
2578 {
2579 default:
2580 case 0:
2581 break;
2582 case 1:
2583 {
2584 /*
2585 Rotate 90 degrees.
2586 */
2587 x=x-(int) draw_image->columns/2;
2588 y=y+(int) draw_image->columns/2;
2589 break;
2590 }
2591 case 2:
2592 {
2593 /*
2594 Rotate 180 degrees.
2595 */
2596 x=x-(int) draw_image->columns;
2597 break;
2598 }
2599 case 3:
2600 {
2601 /*
2602 Rotate 270 degrees.
2603 */
2604 x=x-(int) draw_image->columns/2;
2605 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2606 break;
2607 }
2608 }
2609 }
2610 /*
2611 Composite text onto the image.
2612 */
cristydb070952012-04-20 14:33:00 +00002613 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002614 for (y=0; y < (int) draw_image->rows; y++)
2615 {
cristyc57f6942010-11-12 01:47:39 +00002616 register int
cristy3ed852e2009-09-05 21:47:34 +00002617 x;
2618
cristy4c08aed2011-07-01 19:47:50 +00002619 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002620 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002621
cristyc57f6942010-11-12 01:47:39 +00002622 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2623 exception);
cristyacd2ed22011-08-30 01:44:23 +00002624 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002625 break;
cristyc57f6942010-11-12 01:47:39 +00002626 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002627 {
cristy4c08aed2011-07-01 19:47:50 +00002628 if (GetPixelAlpha(image,q) != TransparentAlpha)
2629 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002630 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002631 }
cristyc57f6942010-11-12 01:47:39 +00002632 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002633 break;
2634 }
cristyc57f6942010-11-12 01:47:39 +00002635 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002636 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2637 if (draw_info->stencil == TransparentStencil)
cristy39172402012-03-30 13:04:39 +00002638 (void) CompositeImage(image,draw_image,CopyAlphaCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002639 (ssize_t) x,(ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002640 else
2641 {
2642 matte=image->matte;
cristy39172402012-03-30 13:04:39 +00002643 (void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002644 (ssize_t) x,(ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002645 image->matte=matte;
2646 }
2647 draw_image=DestroyImage(draw_image);
2648 return(MagickTrue);
2649}
2650
2651/*
2652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2653% %
2654% %
2655% %
2656% X E r r o r %
2657% %
2658% %
2659% %
2660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2661%
2662% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2663% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002664% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2665% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002666%
2667% The format of the XError function is:
2668%
cristybcbda3f2011-09-03 13:01:22 +00002669% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002670%
2671% A description of each parameter follows:
2672%
2673% o display: Specifies a pointer to the Display structure; returned from
2674% XOpenDisplay.
2675%
2676% o error: Specifies the error event.
2677%
2678*/
2679
2680#if defined(__cplusplus) || defined(c_plusplus)
2681extern "C" {
2682#endif
2683
2684MagickExport int XError(Display *display,XErrorEvent *error)
2685{
2686 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2687 assert(display != (Display *) NULL);
2688 assert(error != (XErrorEvent *) NULL);
2689 xerror_alert=MagickTrue;
2690 switch (error->request_code)
2691 {
2692 case X_GetGeometry:
2693 {
2694 if ((int) error->error_code == BadDrawable)
2695 return(MagickFalse);
2696 break;
2697 }
2698 case X_GetWindowAttributes:
2699 case X_QueryTree:
2700 {
2701 if ((int) error->error_code == BadWindow)
2702 return(MagickFalse);
2703 break;
2704 }
2705 case X_QueryColors:
2706 {
2707 if ((int) error->error_code == BadValue)
2708 return(MagickFalse);
2709 break;
2710 }
2711 }
2712 return(MagickTrue);
2713}
2714
2715#if defined(__cplusplus) || defined(c_plusplus)
2716}
2717#endif
2718
2719/*
2720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2721% %
2722% %
2723% %
2724% X F r e e R e s o u r c e s %
2725% %
2726% %
2727% %
2728%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2729%
2730% XFreeResources() frees X11 resources.
2731%
2732% The format of the XFreeResources method is:
2733%
2734% void XFreeResources(Display *display,XVisualInfo *visual_info,
2735% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2736% XResourceInfo *resource_info,XWindowInfo *window_info)
2737% resource_info,window_info)
2738%
2739% A description of each parameter follows:
2740%
2741% o display: Specifies a connection to an X server; returned from
2742% XOpenDisplay.
2743%
2744% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2745% returned from XGetVisualInfo.
2746%
2747% o map_info: If map_type is specified, this structure is initialized
2748% with info from the Standard Colormap.
2749%
2750% o pixel: Specifies a pointer to a XPixelInfo structure.
2751%
2752% o font_info: Specifies a pointer to a XFontStruct structure.
2753%
2754% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2755%
2756% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2757%
2758*/
cristybcbda3f2011-09-03 13:01:22 +00002759MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002760 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2761 XResourceInfo *resource_info,XWindowInfo *window_info)
2762{
2763 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2764 assert(display != (Display *) NULL);
2765 assert(resource_info != (XResourceInfo *) NULL);
2766 if (window_info != (XWindowInfo *) NULL)
2767 {
2768 /*
2769 Free X image.
2770 */
2771 if (window_info->ximage != (XImage *) NULL)
2772 XDestroyImage(window_info->ximage);
2773 if (window_info->id != (Window) NULL)
2774 {
2775 /*
2776 Free destroy window and free cursors.
2777 */
2778 if (window_info->id != XRootWindow(display,visual_info->screen))
2779 (void) XDestroyWindow(display,window_info->id);
2780 if (window_info->annotate_context != (GC) NULL)
2781 (void) XFreeGC(display,window_info->annotate_context);
2782 if (window_info->highlight_context != (GC) NULL)
2783 (void) XFreeGC(display,window_info->highlight_context);
2784 if (window_info->widget_context != (GC) NULL)
2785 (void) XFreeGC(display,window_info->widget_context);
2786 if (window_info->cursor != (Cursor) NULL)
2787 (void) XFreeCursor(display,window_info->cursor);
2788 window_info->cursor=(Cursor) NULL;
2789 if (window_info->busy_cursor != (Cursor) NULL)
2790 (void) XFreeCursor(display,window_info->busy_cursor);
2791 window_info->busy_cursor=(Cursor) NULL;
2792 }
2793 }
2794 /*
2795 Free font.
2796 */
2797 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002798 {
2799 (void) XFreeFont(display,font_info);
2800 font_info=(XFontStruct *) NULL;
2801 }
cristy3ed852e2009-09-05 21:47:34 +00002802 if (map_info != (XStandardColormap *) NULL)
2803 {
2804 /*
2805 Free X Standard Colormap.
2806 */
2807 if (resource_info->map_type == (char *) NULL)
2808 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2809 (void) XFree((void *) map_info);
2810 }
2811 /*
2812 Free X visual info.
2813 */
2814 if (visual_info != (XVisualInfo *) NULL)
2815 (void) XFree((void *) visual_info);
2816 if (resource_info->close_server != MagickFalse)
2817 (void) XCloseDisplay(display);
2818}
2819
2820/*
2821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2822% %
2823% %
2824% %
2825% X F r e e S t a n d a r d C o l o r m a p %
2826% %
2827% %
2828% %
2829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2830%
2831% XFreeStandardColormap() frees an X11 colormap.
2832%
2833% The format of the XFreeStandardColormap method is:
2834%
2835% void XFreeStandardColormap(Display *display,
2836% const XVisualInfo *visual_info,XStandardColormap *map_info,
2837% XPixelInfo *pixel)
2838%
2839% A description of each parameter follows:
2840%
2841% o display: Specifies a connection to an X server; returned from
2842% XOpenDisplay.
2843%
2844% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2845% returned from XGetVisualInfo.
2846%
2847% o map_info: If map_type is specified, this structure is initialized
2848% with info from the Standard Colormap.
2849%
2850% o pixel: Specifies a pointer to a XPixelInfo structure.
2851%
2852*/
cristybcbda3f2011-09-03 13:01:22 +00002853MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002854 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2855{
2856 /*
2857 Free colormap.
2858 */
2859 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2860 assert(display != (Display *) NULL);
2861 assert(visual_info != (XVisualInfo *) NULL);
2862 assert(map_info != (XStandardColormap *) NULL);
2863 (void) XFlush(display);
2864 if (map_info->colormap != (Colormap) NULL)
2865 {
2866 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2867 (void) XFreeColormap(display,map_info->colormap);
2868 else
2869 if (pixel != (XPixelInfo *) NULL)
2870 if ((visual_info->klass != TrueColor) &&
2871 (visual_info->klass != DirectColor))
2872 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2873 (int) pixel->colors,0);
2874 }
2875 map_info->colormap=(Colormap) NULL;
2876 if (pixel != (XPixelInfo *) NULL)
2877 {
cristyf2faecf2010-05-28 19:19:36 +00002878 if (pixel->pixels != (unsigned long *) NULL)
2879 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2880 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002881 }
2882}
2883
2884/*
2885%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2886% %
2887% %
2888% %
2889% X G e t A n n o t a t e I n f o %
2890% %
2891% %
2892% %
2893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2894%
2895% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2896%
2897% The format of the XGetAnnotateInfo method is:
2898%
2899% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2900%
2901% A description of each parameter follows:
2902%
2903% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2904%
2905*/
cristybcbda3f2011-09-03 13:01:22 +00002906MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002907{
2908 /*
2909 Initialize annotate structure.
2910 */
2911 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2912 assert(annotate_info != (XAnnotateInfo *) NULL);
2913 annotate_info->x=0;
2914 annotate_info->y=0;
2915 annotate_info->width=0;
2916 annotate_info->height=0;
2917 annotate_info->stencil=ForegroundStencil;
2918 annotate_info->degrees=0.0;
2919 annotate_info->font_info=(XFontStruct *) NULL;
2920 annotate_info->text=(char *) NULL;
2921 *annotate_info->geometry='\0';
2922 annotate_info->previous=(XAnnotateInfo *) NULL;
2923 annotate_info->next=(XAnnotateInfo *) NULL;
2924 (void) XSupportsLocale();
2925 (void) XSetLocaleModifiers("");
2926}
2927
2928/*
2929%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2930% %
2931% %
2932% %
2933% X G e t M a p I n f o %
2934% %
2935% %
2936% %
2937%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2938%
2939% XGetMapInfo() initializes the XStandardColormap structure.
2940%
2941% The format of the XStandardColormap method is:
2942%
2943% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2944% XStandardColormap *map_info)
2945%
2946% A description of each parameter follows:
2947%
2948% o colormap: Specifies the ID of the X server colormap.
2949%
2950% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2951% returned from XGetVisualInfo.
2952%
2953% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2954%
2955*/
cristybcbda3f2011-09-03 13:01:22 +00002956MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002957 const Colormap colormap,XStandardColormap *map_info)
2958{
2959 /*
2960 Initialize map info.
2961 */
2962 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2963 assert(visual_info != (XVisualInfo *) NULL);
2964 assert(map_info != (XStandardColormap *) NULL);
2965 map_info->colormap=colormap;
2966 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002967 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002968 if (map_info->red_max != 0)
2969 while ((map_info->red_max & 0x01) == 0)
2970 {
2971 map_info->red_max>>=1;
2972 map_info->red_mult<<=1;
2973 }
2974 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002975 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002976 if (map_info->green_max != 0)
2977 while ((map_info->green_max & 0x01) == 0)
2978 {
2979 map_info->green_max>>=1;
2980 map_info->green_mult<<=1;
2981 }
2982 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002983 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002984 if (map_info->blue_max != 0)
2985 while ((map_info->blue_max & 0x01) == 0)
2986 {
2987 map_info->blue_max>>=1;
2988 map_info->blue_mult<<=1;
2989 }
2990 map_info->base_pixel=0;
2991}
2992
2993/*
2994%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2995% %
2996% %
2997% %
2998% X G e t P i x e l I n f o %
2999% %
3000% %
3001% %
3002%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3003%
cristy101ab702011-10-13 13:06:32 +00003004% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00003005%
cristy4c08aed2011-07-01 19:47:50 +00003006% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00003007%
cristy4c08aed2011-07-01 19:47:50 +00003008% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00003009% const XStandardColormap *map_info,const XResourceInfo *resource_info,
3010% Image *image,XPixelInfo *pixel)
3011% pixel)
3012%
3013% A description of each parameter follows:
3014%
3015% o display: Specifies a connection to an X server; returned from
3016% XOpenDisplay.
3017%
3018% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3019% returned from XGetVisualInfo.
3020%
3021% o map_info: If map_type is specified, this structure is initialized
3022% with info from the Standard Colormap.
3023%
3024% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3025%
3026% o image: the image.
3027%
3028% o pixel: Specifies a pointer to a XPixelInfo structure.
3029%
3030*/
cristybcbda3f2011-09-03 13:01:22 +00003031MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003032 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3033 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3034{
3035 static const char
3036 *PenColors[MaxNumberPens]=
3037 {
3038 "#000000000000", /* black */
3039 "#00000000ffff", /* blue */
3040 "#0000ffffffff", /* cyan */
3041 "#0000ffff0000", /* green */
3042 "#bdbdbdbdbdbd", /* gray */
3043 "#ffff00000000", /* red */
3044 "#ffff0000ffff", /* magenta */
3045 "#ffffffff0000", /* yellow */
3046 "#ffffffffffff", /* white */
3047 "#bdbdbdbdbdbd", /* gray */
3048 "#bdbdbdbdbdbd" /* gray */
3049 };
3050
3051 Colormap
3052 colormap;
3053
cristybb503372010-05-27 20:51:26 +00003054 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003055 i;
3056
3057 Status
3058 status;
3059
3060 unsigned int
3061 packets;
3062
3063 /*
3064 Initialize pixel info.
3065 */
3066 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3067 assert(display != (Display *) NULL);
3068 assert(visual_info != (XVisualInfo *) NULL);
3069 assert(map_info != (XStandardColormap *) NULL);
3070 assert(resource_info != (XResourceInfo *) NULL);
3071 assert(pixel != (XPixelInfo *) NULL);
3072 pixel->colors=0;
3073 if (image != (Image *) NULL)
3074 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003075 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003076 packets=(unsigned int)
3077 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003078 if (pixel->pixels != (unsigned long *) NULL)
3079 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3080 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003081 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003082 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003083 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3084 image->filename);
3085 /*
3086 Set foreground color.
3087 */
3088 colormap=map_info->colormap;
3089 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3090 &pixel->foreground_color);
3091 status=XParseColor(display,colormap,resource_info->foreground_color,
3092 &pixel->foreground_color);
3093 if (status == False)
3094 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3095 resource_info->foreground_color);
3096 pixel->foreground_color.pixel=
3097 XStandardPixel(map_info,&pixel->foreground_color);
3098 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3099 /*
3100 Set background color.
3101 */
3102 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3103 status=XParseColor(display,colormap,resource_info->background_color,
3104 &pixel->background_color);
3105 if (status == False)
3106 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3107 resource_info->background_color);
3108 pixel->background_color.pixel=
3109 XStandardPixel(map_info,&pixel->background_color);
3110 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3111 /*
3112 Set border color.
3113 */
3114 (void) XParseColor(display,colormap,(char *) BorderColor,
3115 &pixel->border_color);
3116 status=XParseColor(display,colormap,resource_info->border_color,
3117 &pixel->border_color);
3118 if (status == False)
3119 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3120 resource_info->border_color);
3121 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3122 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3123 /*
3124 Set matte color.
3125 */
3126 pixel->matte_color=pixel->background_color;
3127 if (resource_info->matte_color != (char *) NULL)
3128 {
3129 /*
3130 Matte color is specified as a X resource or command line argument.
3131 */
3132 status=XParseColor(display,colormap,resource_info->matte_color,
3133 &pixel->matte_color);
3134 if (status == False)
3135 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3136 resource_info->matte_color);
3137 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3138 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3139 }
3140 /*
3141 Set highlight color.
3142 */
3143 pixel->highlight_color.red=(unsigned short) ((
3144 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3145 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3146 pixel->highlight_color.green=(unsigned short) ((
3147 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3148 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3149 pixel->highlight_color.blue=(unsigned short) ((
3150 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3151 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3152 pixel->highlight_color.pixel=
3153 XStandardPixel(map_info,&pixel->highlight_color);
3154 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3155 /*
3156 Set shadow color.
3157 */
3158 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3159 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3160 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3161 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3162 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3163 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3164 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3165 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3166 /*
3167 Set depth color.
3168 */
3169 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3170 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3171 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3172 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3173 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3174 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3175 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3176 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3177 /*
3178 Set trough color.
3179 */
3180 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3181 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3182 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3183 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3184 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3185 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3186 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3187 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3188 /*
3189 Set pen color.
3190 */
3191 for (i=0; i < MaxNumberPens; i++)
3192 {
3193 (void) XParseColor(display,colormap,(char *) PenColors[i],
3194 &pixel->pen_colors[i]);
3195 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3196 &pixel->pen_colors[i]);
3197 if (status == False)
3198 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3199 resource_info->pen_colors[i]);
3200 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3201 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3202 }
3203 pixel->box_color=pixel->background_color;
3204 pixel->pen_color=pixel->foreground_color;
3205 pixel->box_index=0;
3206 pixel->pen_index=1;
3207 if (image != (Image *) NULL)
3208 {
3209 if ((resource_info->gamma_correct != MagickFalse) &&
3210 (image->gamma != 0.0))
3211 {
3212 GeometryInfo
3213 geometry_info;
3214
3215 MagickStatusType
3216 flags;
3217
3218 /*
3219 Initialize map relative to display and image gamma.
3220 */
3221 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3222 red_gamma=geometry_info.rho;
3223 green_gamma=geometry_info.sigma;
3224 if ((flags & SigmaValue) == 0)
3225 green_gamma=red_gamma;
3226 blue_gamma=geometry_info.xi;
3227 if ((flags & XiValue) == 0)
3228 blue_gamma=red_gamma;
3229 red_gamma*=image->gamma;
3230 green_gamma*=image->gamma;
3231 blue_gamma*=image->gamma;
3232 }
3233 if (image->storage_class == PseudoClass)
3234 {
3235 /*
3236 Initialize pixel array for images of type PseudoClass.
3237 */
cristybb503372010-05-27 20:51:26 +00003238 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003239 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003240 for (i=0; i < MaxNumberPens; i++)
3241 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3242 pixel->colors+=MaxNumberPens;
3243 }
3244 }
3245}
3246
3247/*
3248%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3249% %
3250% %
3251% %
3252% X G e t R e s o u r c e C l a s s %
3253% %
3254% %
3255% %
3256%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3257%
3258% XGetResourceClass() queries the X server for the specified resource name or
3259% class. If the resource name or class is not defined in the database, the
3260% supplied default value is returned.
3261%
3262% The format of the XGetResourceClass method is:
3263%
3264% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3265% const char *keyword,char *resource_default)
3266%
3267% A description of each parameter follows:
3268%
3269% o database: Specifies a resource database; returned from
3270% XrmGetStringDatabase.
3271%
3272% o client_name: Specifies the application name used to retrieve resource
3273% info from the X server database.
3274%
3275% o keyword: Specifies the keyword of the value being retrieved.
3276%
3277% o resource_default: Specifies the default value to return if the query
3278% fails to find the specified keyword/class.
3279%
3280*/
3281MagickExport char *XGetResourceClass(XrmDatabase database,
3282 const char *client_name,const char *keyword,char *resource_default)
3283{
3284 char
3285 resource_class[MaxTextExtent],
3286 resource_name[MaxTextExtent];
3287
3288 static char
3289 *resource_type;
3290
3291 Status
3292 status;
3293
3294 XrmValue
3295 resource_value;
3296
3297 if (database == (XrmDatabase) NULL)
3298 return(resource_default);
3299 *resource_name='\0';
3300 *resource_class='\0';
3301 if (keyword != (char *) NULL)
3302 {
3303 int
3304 c,
3305 k;
3306
3307 /*
3308 Initialize resource keyword and class.
3309 */
cristyb51dff52011-05-19 16:55:47 +00003310 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003311 client_name,keyword);
3312 c=(int) (*client_name);
3313 if ((c >= XK_a) && (c <= XK_z))
3314 c-=(XK_a-XK_A);
3315 else
3316 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3317 c-=(XK_agrave-XK_Agrave);
3318 else
3319 if ((c >= XK_oslash) && (c <= XK_thorn))
3320 c-=(XK_oslash-XK_Ooblique);
3321 k=(int) (*keyword);
3322 if ((k >= XK_a) && (k <= XK_z))
3323 k-=(XK_a-XK_A);
3324 else
3325 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3326 k-=(XK_agrave-XK_Agrave);
3327 else
3328 if ((k >= XK_oslash) && (k <= XK_thorn))
3329 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003330 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003331 client_name+1,k,keyword+1);
3332 }
3333 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3334 &resource_value);
3335 if (status == False)
3336 return(resource_default);
3337 return(resource_value.addr);
3338}
3339
3340/*
3341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3342% %
3343% %
3344% %
3345% X G e t R e s o u r c e D a t a b a s e %
3346% %
3347% %
3348% %
3349%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3350%
3351% XGetResourceDatabase() creates a new resource database and initializes it.
3352%
3353% The format of the XGetResourceDatabase method is:
3354%
3355% XrmDatabase XGetResourceDatabase(Display *display,
3356% const char *client_name)
3357%
3358% A description of each parameter follows:
3359%
3360% o database: XGetResourceDatabase() returns the database after it is
3361% initialized.
3362%
3363% o display: Specifies a connection to an X server; returned from
3364% XOpenDisplay.
3365%
3366% o client_name: Specifies the application name used to retrieve resource
3367% info from the X server database.
3368%
3369*/
3370MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3371 const char *client_name)
3372{
3373 char
3374 filename[MaxTextExtent];
3375
3376 int
3377 c;
3378
3379 register const char
3380 *p;
3381
3382 XrmDatabase
3383 resource_database,
3384 server_database;
3385
3386 if (display == (Display *) NULL)
3387 return((XrmDatabase) NULL);
3388 assert(client_name != (char *) NULL);
3389 /*
3390 Initialize resource database.
3391 */
3392 XrmInitialize();
3393 (void) XGetDefault(display,(char *) client_name,"dummy");
3394 resource_database=XrmGetDatabase(display);
3395 /*
3396 Combine application database.
3397 */
3398 if (client_name != (char *) NULL)
3399 {
3400 /*
3401 Get basename of client.
3402 */
3403 p=client_name+(strlen(client_name)-1);
3404 while ((p > client_name) && (*p != '/'))
3405 p--;
3406 if (*p == '/')
3407 client_name=p+1;
3408 }
3409 c=(int) (*client_name);
3410 if ((c >= XK_a) && (c <= XK_z))
3411 c-=(XK_a-XK_A);
3412 else
3413 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3414 c-=(XK_agrave-XK_Agrave);
3415 else
3416 if ((c >= XK_oslash) && (c <= XK_thorn))
3417 c-=(XK_oslash-XK_Ooblique);
3418#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003419 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003420 X11_APPLICATION_PATH,c,client_name+1);
3421 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3422#endif
3423 if (XResourceManagerString(display) != (char *) NULL)
3424 {
3425 /*
3426 Combine server database.
3427 */
3428 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3429 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3430 }
3431 /*
3432 Merge user preferences database.
3433 */
3434#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003435 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003436 X11_PREFERENCES_PATH,client_name);
3437 ExpandFilename(filename);
3438 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3439#endif
3440 return(resource_database);
3441}
3442
3443/*
3444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3445% %
3446% %
3447% %
3448% X G e t R e s o u r c e I n f o %
3449% %
3450% %
3451% %
3452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3453%
3454% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3455%
3456% The format of the XGetResourceInfo method is:
3457%
3458% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3459% const char *client_name,XResourceInfo *resource_info)
3460%
3461% A description of each parameter follows:
3462%
3463% o image_info: the image info.
3464%
3465% o database: Specifies a resource database; returned from
3466% XrmGetStringDatabase.
3467%
3468% o client_name: Specifies the application name used to retrieve
3469% resource info from the X server database.
3470%
3471% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3472%
3473*/
3474MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3475 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3476{
3477 char
cristy00976d82011-02-20 20:31:28 +00003478 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003479 *resource_value;
3480
3481 /*
3482 Initialize resource info fields.
3483 */
3484 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3485 assert(resource_info != (XResourceInfo *) NULL);
3486 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3487 resource_info->resource_database=database;
3488 resource_info->image_info=(ImageInfo *) image_info;
3489 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3490 XMagickProgressMonitor,(void *) NULL);
3491 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3492 resource_info->close_server=MagickTrue;
3493 resource_info->client_name=AcquireString(client_name);
3494 resource_value=XGetResourceClass(database,client_name,"backdrop",
3495 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003496 resource_info->backdrop=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003497 resource_info->background_color=XGetResourceInstance(database,client_name,
3498 "background",(char *) "#d6d6d6d6d6d6");
3499 resource_info->border_color=XGetResourceInstance(database,client_name,
3500 "borderColor",BorderColor);
3501 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3502 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003503 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3504 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003505 resource_value=XGetResourceClass(database,client_name,"colormap",
3506 (char *) "shared");
3507 resource_info->colormap=UndefinedColormap;
3508 if (LocaleCompare("private",resource_value) == 0)
3509 resource_info->colormap=PrivateColormap;
3510 if (LocaleCompare("shared",resource_value) == 0)
3511 resource_info->colormap=SharedColormap;
3512 if (resource_info->colormap == UndefinedColormap)
3513 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3514 resource_value);
3515 resource_value=XGetResourceClass(database,client_name,
3516 "colorRecovery",(char *) "False");
anthony6f201312012-03-30 04:08:15 +00003517 resource_info->color_recovery=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003518 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3519 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003520 resource_info->confirm_exit=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003521 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3522 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003523 resource_info->confirm_edit=IsStringTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003524 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003525 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003526 resource_info->display_gamma=XGetResourceClass(database,client_name,
3527 "displayGamma",(char *) "2.2");
3528 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3529 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003530 resource_info->display_warnings=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003531 resource_info->font=XGetResourceClass(database,client_name,"font",
3532 (char *) NULL);
3533 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3534 resource_info->font);
3535 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3536 (char *) "fixed");
3537 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3538 (char *) "variable");
3539 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3540 (char *) "5x8");
3541 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3542 (char *) "6x10");
3543 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3544 (char *) "7x13bold");
3545 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3546 (char *) "8x13bold");
3547 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3548 (char *) "9x15bold");
3549 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3550 (char *) "10x20");
3551 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3552 (char *) "12x24");
3553 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3554 (char *) "fixed");
3555 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3556 (char *) "fixed");
3557 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3558 "foreground",ForegroundColor);
3559 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3560 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003561 resource_info->gamma_correct=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003562 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3563 client_name,"geometry",(char *) NULL));
3564 resource_value=XGetResourceClass(database,client_name,"gravity",
3565 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003566 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003567 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003568 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3569 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003570 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3571 "iconGeometry",(char *) NULL);
3572 resource_value=XGetResourceClass(database,client_name,"iconic",
3573 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003574 resource_info->iconic=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003575 resource_value=XGetResourceClass(database,client_name,"immutable",
3576 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3577 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003578 resource_info->immutable=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003579 resource_value=XGetResourceClass(database,client_name,"magnify",
3580 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003581 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003582 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3583 (char *) NULL);
3584 resource_info->matte_color=XGetResourceInstance(database,client_name,
3585 "mattecolor",(char *) NULL);
3586 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3587 "name",(char *) NULL));
3588 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3589 (char *) "black");
3590 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3591 (char *) "blue");
3592 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3593 (char *) "cyan");
3594 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3595 (char *) "green");
3596 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3597 (char *) "gray");
3598 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3599 (char *) "red");
3600 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3601 (char *) "magenta");
3602 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3603 (char *) "yellow");
3604 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3605 (char *) "white");
3606 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3607 (char *) "gray");
3608 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3609 (char *) "gray");
3610 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003611 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003612 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003613 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003614 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3615 "font",(char *) "fixed");
3616 resource_info->text_font=XGetResourceClass(database,client_name,
3617 "textFontList",resource_info->text_font);
3618 resource_info->title=XGetResourceClass(database,client_name,"title",
3619 (char *) NULL);
3620 resource_value=XGetResourceClass(database,client_name,"undoCache",
3621 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003622 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003623 resource_value=XGetResourceClass(database,client_name,"update",
3624 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003625 resource_info->update=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003626 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3627 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003628 resource_info->use_pixmap=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003629 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3630 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003631 resource_info->use_shared_memory=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003632 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3633 (char *) NULL);
3634 resource_info->window_group=XGetResourceClass(database,client_name,
3635 "windowGroup",(char *) NULL);
3636 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3637 (char *) NULL);
3638 resource_info->write_filename=XGetResourceClass(database,client_name,
3639 "writeFilename",(char *) NULL);
3640}
3641
3642/*
3643%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3644% %
3645% %
3646% %
3647% X G e t R e s o u r c e I n s t a n c e %
3648% %
3649% %
3650% %
3651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3652%
3653% XGetResourceInstance() queries the X server for the specified resource name.
3654% If the resource name is not defined in the database, the supplied default
3655% value is returned.
3656%
3657% The format of the XGetResourceInstance method is:
3658%
3659% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3660% const char *keyword,const char *resource_default)
3661%
3662% A description of each parameter follows:
3663%
3664% o database: Specifies a resource database; returned from
3665% XrmGetStringDatabase.
3666%
3667% o client_name: Specifies the application name used to retrieve
3668% resource info from the X server database.
3669%
3670% o keyword: Specifies the keyword of the value being retrieved.
3671%
3672% o resource_default: Specifies the default value to return if the query
3673% fails to find the specified keyword/class.
3674%
3675*/
3676MagickExport char *XGetResourceInstance(XrmDatabase database,
3677 const char *client_name,const char *keyword,const char *resource_default)
3678{
3679 char
3680 *resource_type,
3681 resource_name[MaxTextExtent];
3682
3683 Status
3684 status;
3685
3686 XrmValue
3687 resource_value;
3688
3689 if (database == (XrmDatabase) NULL)
3690 return((char *) resource_default);
3691 *resource_name='\0';
3692 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003693 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003694 keyword);
3695 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3696 &resource_value);
3697 if (status == False)
3698 return((char *) resource_default);
3699 return(resource_value.addr);
3700}
3701
3702/*
3703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3704% %
3705% %
3706% %
3707% X G e t S c r e e n D e n s i t y %
3708% %
3709% %
3710% %
3711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3712%
3713% XGetScreenDensity() returns the density of the X server screen in
3714% dots-per-inch.
3715%
3716% The format of the XGetScreenDensity method is:
3717%
3718% char *XGetScreenDensity(Display *display)
3719%
3720% A description of each parameter follows:
3721%
3722% o density: XGetScreenDensity() returns the density of the X screen in
3723% dots-per-inch.
3724%
3725% o display: Specifies a connection to an X server; returned from
3726% XOpenDisplay.
3727%
3728*/
3729MagickExport char *XGetScreenDensity(Display *display)
3730{
3731 char
3732 density[MaxTextExtent];
3733
3734 double
3735 x_density,
3736 y_density;
3737
3738 /*
3739 Set density as determined by screen size.
3740 */
3741 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3742 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3743 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3744 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003745 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003746 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003747 return(GetPageGeometry(density));
3748}
3749
3750/*
3751%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3752% %
3753% %
3754% %
3755+ X G e t S u b w i n d o w %
3756% %
3757% %
3758% %
3759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3760%
3761% XGetSubwindow() returns the subwindow of a window chosen the user with the
3762% pointer and a button press.
3763%
3764% The format of the XGetSubwindow method is:
3765%
3766% Window XGetSubwindow(Display *display,Window window,int x,int y)
3767%
3768% A description of each parameter follows:
3769%
3770% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3771% otherwise the subwindow is returned.
3772%
3773% o display: Specifies a connection to an X server; returned from
3774% XOpenDisplay.
3775%
3776% o window: Specifies a pointer to a Window.
3777%
3778% o x: the x coordinate of the pointer relative to the origin of the
3779% window.
3780%
3781% o y: the y coordinate of the pointer relative to the origin of the
3782% window.
3783%
cristy3ed852e2009-09-05 21:47:34 +00003784*/
3785static Window XGetSubwindow(Display *display,Window window,int x,int y)
3786{
3787 int
3788 x_offset,
3789 y_offset;
3790
3791 Status
3792 status;
3793
3794 Window
3795 source_window,
3796 target_window;
3797
3798 assert(display != (Display *) NULL);
3799 source_window=XRootWindow(display,XDefaultScreen(display));
3800 if (window == (Window) NULL)
3801 return(source_window);
3802 target_window=window;
3803 for ( ; ; )
3804 {
3805 status=XTranslateCoordinates(display,source_window,window,x,y,
3806 &x_offset,&y_offset,&target_window);
3807 if (status != True)
3808 break;
3809 if (target_window == (Window) NULL)
3810 break;
3811 source_window=window;
3812 window=target_window;
3813 x=x_offset;
3814 y=y_offset;
3815 }
3816 if (target_window == (Window) NULL)
3817 target_window=window;
3818 return(target_window);
3819}
3820
3821/*
3822%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3823% %
3824% %
3825% %
3826% X G e t W i n d o w C o l o r %
3827% %
3828% %
3829% %
3830%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3831%
3832% XGetWindowColor() returns the color of a pixel interactively chosen from the
3833% X server.
3834%
3835% The format of the XGetWindowColor method is:
3836%
3837% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003838% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003839%
3840% A description of each parameter follows:
3841%
3842% o display: Specifies a connection to an X server; returned from
3843% XOpenDisplay.
3844%
3845% o windows: Specifies a pointer to a XWindows structure.
3846%
3847% o name: the name of the color if found in the X Color Database is
3848% returned in this character string.
3849%
cristy6710d842011-10-20 23:23:00 +00003850% o exception: return any errors or warnings in this structure.
3851%
cristy3ed852e2009-09-05 21:47:34 +00003852*/
cristybcbda3f2011-09-03 13:01:22 +00003853MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003854 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003855{
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);
cristye42f6582012-02-11 17:59:50 +00003931 pixel.red=(double) ScaleShortToQuantum(color.red);
3932 pixel.green=(double) ScaleShortToQuantum(color.green);
3933 pixel.blue=(double) 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,
cristy6710d842011-10-20 23:23:00 +00003936 exception);
cristy3ed852e2009-09-05 21:47:34 +00003937 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,
cristy6710d842011-10-20 23:23:00 +00003960% const unsigned int borders,const unsigned int level,
3961% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003962%
3963% A description of each parameter follows:
3964%
3965% o display: Specifies a connection to an X server; returned from
3966% XOpenDisplay.
3967%
3968% o window: Specifies the window to obtain the image from.
3969%
3970% o borders: Specifies whether borders pixels are to be saved with
3971% the image.
3972%
3973% o level: Specifies an unsigned integer representing the level of
3974% decent in the window hierarchy. This value must be zero or one on
3975% the initial call to XGetWindowImage. A value of zero returns after
3976% one call. A value of one causes the function to descend the window
3977% hierarchy and overlay the target image with each subwindow image.
3978%
cristy6710d842011-10-20 23:23:00 +00003979% o exception: return any errors or warnings in this structure.
3980%
cristy3ed852e2009-09-05 21:47:34 +00003981*/
3982static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003983 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003984{
3985 typedef struct _ColormapInfo
3986 {
3987 Colormap
3988 colormap;
3989
3990 XColor
3991 *colors;
3992
3993 struct _ColormapInfo
3994 *next;
3995 } ColormapInfo;
3996
3997 typedef struct _WindowInfo
3998 {
3999 Window
4000 window,
4001 parent;
4002
4003 Visual
4004 *visual;
4005
4006 Colormap
4007 colormap;
4008
4009 XSegment
4010 bounds;
4011
4012 RectangleInfo
4013 crop_info;
4014 } WindowInfo;
4015
cristy3ed852e2009-09-05 21:47:34 +00004016 int
4017 display_height,
4018 display_width,
4019 id,
4020 x_offset,
4021 y_offset;
4022
cristy4c08aed2011-07-01 19:47:50 +00004023 Quantum
4024 index;
4025
cristy3ed852e2009-09-05 21:47:34 +00004026 RectangleInfo
4027 crop_info;
4028
cristy3ed852e2009-09-05 21:47:34 +00004029 register int
4030 i;
4031
4032 static ColormapInfo
4033 *colormap_info = (ColormapInfo *) NULL;
4034
4035 static int
4036 max_windows = 0,
4037 number_windows = 0;
4038
4039 static WindowInfo
4040 *window_info;
4041
4042 Status
4043 status;
4044
4045 Window
4046 child,
4047 root_window;
4048
4049 XWindowAttributes
4050 window_attributes;
4051
4052 /*
4053 Verify window is viewable.
4054 */
4055 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4056 assert(display != (Display *) NULL);
4057 status=XGetWindowAttributes(display,window,&window_attributes);
4058 if ((status == False) || (window_attributes.map_state != IsViewable))
4059 return((Image *) NULL);
4060 /*
4061 Cropping rectangle is relative to root window.
4062 */
4063 root_window=XRootWindow(display,XDefaultScreen(display));
4064 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4065 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004066 crop_info.x=(ssize_t) x_offset;
4067 crop_info.y=(ssize_t) y_offset;
4068 crop_info.width=(size_t) window_attributes.width;
4069 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004070 if (borders != MagickFalse)
4071 {
4072 /*
4073 Include border in image.
4074 */
cristybb503372010-05-27 20:51:26 +00004075 crop_info.x-=(ssize_t) window_attributes.border_width;
4076 crop_info.y-=(ssize_t) window_attributes.border_width;
4077 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4078 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004079 }
4080 /*
4081 Crop to root window.
4082 */
4083 if (crop_info.x < 0)
4084 {
4085 crop_info.width+=crop_info.x;
4086 crop_info.x=0;
4087 }
4088 if (crop_info.y < 0)
4089 {
4090 crop_info.height+=crop_info.y;
4091 crop_info.y=0;
4092 }
4093 display_width=XDisplayWidth(display,XDefaultScreen(display));
4094 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004095 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004096 display_height=XDisplayHeight(display,XDefaultScreen(display));
4097 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004098 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004099 /*
4100 Initialize window info attributes.
4101 */
4102 if (number_windows >= max_windows)
4103 {
4104 /*
4105 Allocate or resize window info buffer.
4106 */
4107 max_windows+=1024;
4108 if (window_info == (WindowInfo *) NULL)
4109 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4110 sizeof(*window_info));
4111 else
4112 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4113 max_windows,sizeof(*window_info));
4114 }
4115 if (window_info == (WindowInfo *) NULL)
4116 {
4117 ThrowXWindowFatalException(ResourceLimitError,
4118 "MemoryAllocationFailed","...");
4119 return((Image *) NULL);
4120 }
4121 id=number_windows++;
4122 window_info[id].window=window;
4123 window_info[id].visual=window_attributes.visual;
4124 window_info[id].colormap=window_attributes.colormap;
4125 window_info[id].bounds.x1=(short) crop_info.x;
4126 window_info[id].bounds.y1=(short) crop_info.y;
4127 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4128 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4129 crop_info.x-=x_offset;
4130 crop_info.y-=y_offset;
4131 window_info[id].crop_info=crop_info;
4132 if (level != 0)
4133 {
4134 unsigned int
4135 number_children;
4136
4137 Window
4138 *children;
4139
4140 /*
4141 Descend the window hierarchy.
4142 */
4143 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4144 &children,&number_children);
4145 for (i=0; i < id; i++)
4146 if ((window_info[i].window == window_info[id].parent) &&
4147 (window_info[i].visual == window_info[id].visual) &&
4148 (window_info[i].colormap == window_info[id].colormap))
4149 {
4150 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4151 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4152 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4153 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4154 {
4155 /*
4156 Eliminate windows not circumscribed by their parent.
4157 */
4158 number_windows--;
4159 break;
4160 }
4161 }
4162 if ((status == True) && (number_children != 0))
4163 {
4164 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004165 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4166 exception);
cristy3ed852e2009-09-05 21:47:34 +00004167 (void) XFree((void *) children);
4168 }
4169 }
4170 if (level <= 1)
4171 {
cristyc57f6942010-11-12 01:47:39 +00004172 CacheView
4173 *composite_view;
4174
cristy3ed852e2009-09-05 21:47:34 +00004175 ColormapInfo
4176 *next;
4177
cristy3ed852e2009-09-05 21:47:34 +00004178 Image
4179 *composite_image,
4180 *image;
4181
4182 int
4183 y;
4184
4185 MagickBooleanType
4186 import;
4187
4188 register int
4189 j,
4190 x;
4191
cristy4c08aed2011-07-01 19:47:50 +00004192 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004193 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004194
cristybb503372010-05-27 20:51:26 +00004195 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004196 pixel;
4197
4198 unsigned int
4199 number_colors;
4200
4201 XColor
4202 *colors;
4203
4204 XImage
4205 *ximage;
4206
4207 /*
4208 Get X image for each window in the list.
4209 */
4210 image=NewImageList();
4211 for (id=0; id < number_windows; id++)
4212 {
4213 /*
4214 Does target window intersect top level window?
4215 */
4216 import=
4217 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4218 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4219 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4220 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4221 MagickTrue : MagickFalse;
4222 /*
4223 Is target window contained by another window with the same colormap?
4224 */
4225 for (j=0; j < id; j++)
4226 if ((window_info[id].visual == window_info[j].visual) &&
4227 (window_info[id].colormap == window_info[j].colormap))
4228 {
4229 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4230 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4231 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4232 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4233 import=MagickFalse;
4234 }
4235 else
4236 if ((window_info[id].visual != window_info[j].visual) ||
4237 (window_info[id].colormap != window_info[j].colormap))
4238 {
4239 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4240 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4241 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4242 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4243 import=MagickTrue;
4244 }
4245 if (import == MagickFalse)
4246 continue;
4247 /*
4248 Get X image.
4249 */
4250 ximage=XGetImage(display,window_info[id].window,(int)
4251 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4252 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4253 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4254 if (ximage == (XImage *) NULL)
4255 continue;
4256 /*
4257 Initialize window colormap.
4258 */
4259 number_colors=0;
4260 colors=(XColor *) NULL;
4261 if (window_info[id].colormap != (Colormap) NULL)
4262 {
4263 ColormapInfo
4264 *p;
4265
4266 /*
4267 Search colormap list for window colormap.
4268 */
4269 number_colors=(unsigned int) window_info[id].visual->map_entries;
4270 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4271 if (p->colormap == window_info[id].colormap)
4272 break;
4273 if (p == (ColormapInfo *) NULL)
4274 {
4275 /*
4276 Get the window colormap.
4277 */
4278 colors=(XColor *) AcquireQuantumMemory(number_colors,
4279 sizeof(*colors));
4280 if (colors == (XColor *) NULL)
4281 {
4282 XDestroyImage(ximage);
4283 return((Image *) NULL);
4284 }
4285 if ((window_info[id].visual->klass != DirectColor) &&
4286 (window_info[id].visual->klass != TrueColor))
4287 for (i=0; i < (int) number_colors; i++)
4288 {
cristybb503372010-05-27 20:51:26 +00004289 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004290 colors[i].pad='\0';
4291 }
4292 else
4293 {
cristybb503372010-05-27 20:51:26 +00004294 size_t
cristy3ed852e2009-09-05 21:47:34 +00004295 blue,
4296 blue_bit,
4297 green,
4298 green_bit,
4299 red,
4300 red_bit;
4301
4302 /*
4303 DirectColor or TrueColor visual.
4304 */
4305 red=0;
4306 green=0;
4307 blue=0;
4308 red_bit=window_info[id].visual->red_mask &
4309 (~(window_info[id].visual->red_mask)+1);
4310 green_bit=window_info[id].visual->green_mask &
4311 (~(window_info[id].visual->green_mask)+1);
4312 blue_bit=window_info[id].visual->blue_mask &
4313 (~(window_info[id].visual->blue_mask)+1);
4314 for (i=0; i < (int) number_colors; i++)
4315 {
cristy8891f9c2010-06-04 23:32:17 +00004316 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004317 colors[i].pad='\0';
4318 red+=red_bit;
4319 if (red > window_info[id].visual->red_mask)
4320 red=0;
4321 green+=green_bit;
4322 if (green > window_info[id].visual->green_mask)
4323 green=0;
4324 blue+=blue_bit;
4325 if (blue > window_info[id].visual->blue_mask)
4326 blue=0;
4327 }
4328 }
4329 (void) XQueryColors(display,window_info[id].colormap,colors,
4330 (int) number_colors);
4331 /*
4332 Append colormap to colormap list.
4333 */
cristy73bd4a52010-10-05 11:24:23 +00004334 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004335 if (p == (ColormapInfo *) NULL)
4336 return((Image *) NULL);
4337 p->colormap=window_info[id].colormap;
4338 p->colors=colors;
4339 p->next=colormap_info;
4340 colormap_info=p;
4341 }
4342 colors=p->colors;
4343 }
4344 /*
4345 Allocate image structure.
4346 */
cristy6710d842011-10-20 23:23:00 +00004347 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004348 if (composite_image == (Image *) NULL)
4349 {
4350 XDestroyImage(ximage);
4351 return((Image *) NULL);
4352 }
4353 /*
4354 Convert X image to MIFF format.
4355 */
4356 if ((window_info[id].visual->klass != TrueColor) &&
4357 (window_info[id].visual->klass != DirectColor))
4358 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004359 composite_image->columns=(size_t) ximage->width;
4360 composite_image->rows=(size_t) ximage->height;
cristydb070952012-04-20 14:33:00 +00004361 composite_view=AcquireAuthenticCacheView(composite_image,exception);
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 }
cristy0b1a7972011-10-22 22:17:02 +00004428 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4429 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004430 break;
4431 }
4432 else
4433 for (y=0; y < (int) composite_image->rows; y++)
4434 {
cristyc57f6942010-11-12 01:47:39 +00004435 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004436 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004437 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004438 break;
4439 for (x=0; x < (int) composite_image->columns; x++)
4440 {
4441 pixel=XGetPixel(ximage,x,y);
4442 color=(pixel >> red_shift) & red_mask;
4443 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004444 SetPixelRed(composite_image,
4445 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004446 color=(pixel >> green_shift) & green_mask;
4447 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004448 SetPixelGreen(composite_image,
4449 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004450 color=(pixel >> blue_shift) & blue_mask;
4451 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004452 SetPixelBlue(composite_image,
4453 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004454 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004455 }
cristy0b1a7972011-10-22 22:17:02 +00004456 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4457 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004458 break;
4459 }
4460 break;
4461 }
4462 case PseudoClass:
4463 {
4464 /*
4465 Create colormap.
4466 */
cristy0b1a7972011-10-22 22:17:02 +00004467 status=AcquireImageColormap(composite_image,number_colors,
4468 exception);
4469 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004470 {
4471 XDestroyImage(ximage);
4472 composite_image=DestroyImage(composite_image);
4473 return((Image *) NULL);
4474 }
4475 for (i=0; i < (int) composite_image->colors; i++)
4476 {
cristye42f6582012-02-11 17:59:50 +00004477 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004478 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004479 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004480 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004481 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004482 ScaleShortToQuantum(colors[i].blue);
4483 }
4484 /*
4485 Convert X image to PseudoClass packets.
4486 */
4487 for (y=0; y < (int) composite_image->rows; y++)
4488 {
cristyc57f6942010-11-12 01:47:39 +00004489 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4490 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004491 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004492 break;
cristy3ed852e2009-09-05 21:47:34 +00004493 for (x=0; x < (int) composite_image->columns; x++)
4494 {
cristy4c08aed2011-07-01 19:47:50 +00004495 index=(Quantum) XGetPixel(ximage,x,y);
4496 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004497 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004498 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004499 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004500 }
cristy0b1a7972011-10-22 22:17:02 +00004501 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4502 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004503 break;
4504 }
4505 break;
4506 }
4507 }
cristyc57f6942010-11-12 01:47:39 +00004508 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004509 XDestroyImage(ximage);
4510 if (image == (Image *) NULL)
4511 {
4512 image=composite_image;
4513 continue;
4514 }
4515 /*
4516 Composite any children in back-to-front order.
4517 */
4518 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4519 &x_offset,&y_offset,&child);
4520 x_offset-=(int) crop_info.x;
4521 if (x_offset < 0)
4522 x_offset=0;
4523 y_offset-=(int) crop_info.y;
4524 if (y_offset < 0)
4525 y_offset=0;
cristy39172402012-03-30 13:04:39 +00004526 (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00004527 (ssize_t) x_offset,(ssize_t) y_offset,exception);
cristy5f257b22012-03-07 00:27:29 +00004528 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004529 }
4530 /*
4531 Relinquish resources.
4532 */
4533 while (colormap_info != (ColormapInfo *) NULL)
4534 {
4535 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004536 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4537 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004538 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4539 colormap_info=next;
4540 }
4541 /*
4542 Relinquish resources and restore initial state.
4543 */
4544 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4545 max_windows=0;
4546 number_windows=0;
4547 colormap_info=(ColormapInfo *) NULL;
4548 return(image);
4549 }
4550 return((Image *) NULL);
4551}
4552
4553/*
4554%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4555% %
4556% %
4557% %
4558% X G e t W i n d o w I n f o %
4559% %
4560% %
4561% %
4562%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4563%
4564% XGetWindowInfo() initializes the XWindowInfo structure.
4565%
4566% The format of the XGetWindowInfo method is:
4567%
4568% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4569% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4570% XResourceInfo *resource_info,XWindowInfo *window)
4571% resource_info,window)
4572%
4573% A description of each parameter follows:
4574%
4575% o display: Specifies a connection to an X server; returned from
4576% XOpenDisplay.
4577%
4578% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4579% returned from XGetVisualInfo.
4580%
4581% o map_info: If map_type is specified, this structure is initialized
4582% with info from the Standard Colormap.
4583%
4584% o pixel: Specifies a pointer to a XPixelInfo structure.
4585%
4586% o font_info: Specifies a pointer to a XFontStruct structure.
4587%
4588% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4589%
4590*/
cristybcbda3f2011-09-03 13:01:22 +00004591MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004592 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4593 XResourceInfo *resource_info,XWindowInfo *window)
4594{
4595 /*
4596 Initialize window info.
4597 */
4598 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4599 assert(display != (Display *) NULL);
4600 assert(visual_info != (XVisualInfo *) NULL);
4601 assert(map_info != (XStandardColormap *) NULL);
4602 assert(pixel != (XPixelInfo *) NULL);
4603 assert(resource_info != (XResourceInfo *) NULL);
4604 assert(window != (XWindowInfo *) NULL);
4605 if (window->id != (Window) NULL)
4606 {
4607 if (window->cursor != (Cursor) NULL)
4608 (void) XFreeCursor(display,window->cursor);
4609 if (window->busy_cursor != (Cursor) NULL)
4610 (void) XFreeCursor(display,window->busy_cursor);
4611 if (window->highlight_stipple != (Pixmap) NULL)
4612 (void) XFreePixmap(display,window->highlight_stipple);
4613 if (window->shadow_stipple != (Pixmap) NULL)
4614 (void) XFreePixmap(display,window->shadow_stipple);
4615 if (window->name == (char *) NULL)
4616 window->name=AcquireString("");
4617 if (window->icon_name == (char *) NULL)
4618 window->icon_name=AcquireString("");
4619 }
4620 else
4621 {
4622 /*
4623 Initialize these attributes just once.
4624 */
4625 window->id=(Window) NULL;
4626 if (window->name == (char *) NULL)
4627 window->name=AcquireString("");
4628 if (window->icon_name == (char *) NULL)
4629 window->icon_name=AcquireString("");
4630 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4631 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4632 window->ximage=(XImage *) NULL;
4633 window->matte_image=(XImage *) NULL;
4634 window->pixmap=(Pixmap) NULL;
4635 window->matte_pixmap=(Pixmap) NULL;
4636 window->mapped=MagickFalse;
4637 window->stasis=MagickFalse;
4638 window->shared_memory=MagickTrue;
4639 window->segment_info=(void *) NULL;
4640#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4641 {
4642 XShmSegmentInfo
4643 *segment_info;
4644
4645 if (window->segment_info == (void *) NULL)
4646 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4647 segment_info=(XShmSegmentInfo *) window->segment_info;
4648 segment_info[0].shmid=(-1);
4649 segment_info[0].shmaddr=(char *) NULL;
4650 segment_info[1].shmid=(-1);
4651 segment_info[1].shmaddr=(char *) NULL;
4652 }
4653#endif
4654 }
4655 /*
4656 Initialize these attributes every time function is called.
4657 */
4658 window->screen=visual_info->screen;
4659 window->root=XRootWindow(display,visual_info->screen);
4660 window->visual=visual_info->visual;
4661 window->storage_class=(unsigned int) visual_info->klass;
4662 window->depth=(unsigned int) visual_info->depth;
4663 window->visual_info=visual_info;
4664 window->map_info=map_info;
4665 window->pixel_info=pixel;
4666 window->font_info=font_info;
4667 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4668 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4669 window->geometry=(char *) NULL;
4670 window->icon_geometry=(char *) NULL;
4671 if (resource_info->icon_geometry != (char *) NULL)
4672 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4673 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004674 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004675 window->width=1;
4676 window->height=1;
4677 window->min_width=1;
4678 window->min_height=1;
4679 window->width_inc=1;
4680 window->height_inc=1;
4681 window->border_width=resource_info->border_width;
4682 window->annotate_context=pixel->annotate_context;
4683 window->highlight_context=pixel->highlight_context;
4684 window->widget_context=pixel->widget_context;
4685 window->shadow_stipple=(Pixmap) NULL;
4686 window->highlight_stipple=(Pixmap) NULL;
4687 window->use_pixmap=MagickTrue;
4688 window->immutable=MagickFalse;
4689 window->shape=MagickFalse;
4690 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004691 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004692 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4693 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4694 window->attributes.background_pixel=pixel->background_color.pixel;
4695 window->attributes.background_pixmap=(Pixmap) NULL;
4696 window->attributes.bit_gravity=ForgetGravity;
4697 window->attributes.backing_store=WhenMapped;
4698 window->attributes.save_under=MagickTrue;
4699 window->attributes.border_pixel=pixel->border_color.pixel;
4700 window->attributes.colormap=map_info->colormap;
4701 window->attributes.cursor=window->cursor;
4702 window->attributes.do_not_propagate_mask=NoEventMask;
4703 window->attributes.event_mask=NoEventMask;
4704 window->attributes.override_redirect=MagickFalse;
4705 window->attributes.win_gravity=NorthWestGravity;
4706 window->orphan=MagickFalse;
4707}
4708
4709/*
4710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4711% %
4712% %
4713% %
4714% X H i g h l i g h t E l l i p s e %
4715% %
4716% %
4717% %
4718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4719%
4720% XHighlightEllipse() puts a border on the X server around a region defined by
4721% highlight_info.
4722%
4723% The format of the XHighlightEllipse method is:
4724%
4725% void XHighlightEllipse(Display *display,Window window,
4726% GC annotate_context,const RectangleInfo *highlight_info)
4727%
4728% A description of each parameter follows:
4729%
4730% o display: Specifies a connection to an X server; returned from
4731% XOpenDisplay.
4732%
4733% o window: Specifies a pointer to a Window structure.
4734%
4735% o annotate_context: Specifies a pointer to a GC structure.
4736%
4737% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4738% contains the extents of any highlighting rectangle.
4739%
4740*/
cristybcbda3f2011-09-03 13:01:22 +00004741MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004742 GC annotate_context,const RectangleInfo *highlight_info)
4743{
4744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4745 assert(display != (Display *) NULL);
4746 assert(window != (Window) NULL);
4747 assert(annotate_context != (GC) NULL);
4748 assert(highlight_info != (RectangleInfo *) NULL);
4749 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4750 return;
4751 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4752 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4753 (unsigned int) highlight_info->height-1,0,360*64);
4754 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4755 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4756 (unsigned int) highlight_info->height-3,0,360*64);
4757}
4758
4759/*
4760%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4761% %
4762% %
4763% %
4764% X H i g h l i g h t L i n e %
4765% %
4766% %
4767% %
4768%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4769%
4770% XHighlightLine() puts a border on the X server around a region defined by
4771% highlight_info.
4772%
4773% The format of the XHighlightLine method is:
4774%
4775% void XHighlightLine(Display *display,Window window,GC annotate_context,
4776% const XSegment *highlight_info)
4777%
4778% A description of each parameter follows:
4779%
4780% o display: Specifies a connection to an X server; returned from
4781% XOpenDisplay.
4782%
4783% o window: Specifies a pointer to a Window structure.
4784%
4785% o annotate_context: Specifies a pointer to a GC structure.
4786%
4787% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4788% contains the extents of any highlighting rectangle.
4789%
4790*/
cristybcbda3f2011-09-03 13:01:22 +00004791MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004792 GC annotate_context,const XSegment *highlight_info)
4793{
4794 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4795 assert(display != (Display *) NULL);
4796 assert(window != (Window) NULL);
4797 assert(annotate_context != (GC) NULL);
4798 assert(highlight_info != (XSegment *) NULL);
4799 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4800 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4801}
4802
4803/*
4804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4805% %
4806% %
4807% %
4808% X H i g h l i g h t R e c t a n g l e %
4809% %
4810% %
4811% %
4812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4813%
4814% XHighlightRectangle() puts a border on the X server around a region defined
4815% by highlight_info.
4816%
4817% The format of the XHighlightRectangle method is:
4818%
4819% void XHighlightRectangle(Display *display,Window window,
4820% GC annotate_context,const RectangleInfo *highlight_info)
4821%
4822% A description of each parameter follows:
4823%
4824% o display: Specifies a connection to an X server; returned from
4825% XOpenDisplay.
4826%
4827% o window: Specifies a pointer to a Window structure.
4828%
4829% o annotate_context: Specifies a pointer to a GC structure.
4830%
4831% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4832% contains the extents of any highlighting rectangle.
4833%
4834*/
cristybcbda3f2011-09-03 13:01:22 +00004835MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004836 GC annotate_context,const RectangleInfo *highlight_info)
4837{
4838 assert(display != (Display *) NULL);
4839 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4840 assert(window != (Window) NULL);
4841 assert(annotate_context != (GC) NULL);
4842 assert(highlight_info != (RectangleInfo *) NULL);
4843 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4844 return;
4845 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4846 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4847 (unsigned int) highlight_info->height-1);
4848 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4849 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4850 (unsigned int) highlight_info->height-3);
4851}
4852
4853/*
4854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4855% %
4856% %
4857% %
4858% X I m p o r t I m a g e %
4859% %
4860% %
4861% %
4862%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4863%
4864% XImportImage() reads an image from an X window.
4865%
4866% The format of the XImportImage method is:
4867%
cristy6710d842011-10-20 23:23:00 +00004868% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4869% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004870%
4871% A description of each parameter follows:
4872%
4873% o image_info: the image info.
4874%
4875% o ximage_info: Specifies a pointer to an XImportInfo structure.
4876%
cristy6710d842011-10-20 23:23:00 +00004877% o exception: return any errors or warnings in this structure.
4878%
cristy3ed852e2009-09-05 21:47:34 +00004879*/
4880MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004881 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004882{
4883 Colormap
4884 *colormaps;
4885
4886 Display
4887 *display;
4888
4889 Image
4890 *image;
4891
4892 int
4893 number_colormaps,
4894 number_windows,
4895 x;
4896
4897 RectangleInfo
4898 crop_info;
4899
4900 Status
4901 status;
4902
4903 Window
4904 *children,
4905 client,
4906 prior_target,
4907 root,
4908 target;
4909
4910 XTextProperty
4911 window_name;
4912
4913 /*
4914 Open X server connection.
4915 */
4916 assert(image_info != (const ImageInfo *) NULL);
4917 assert(image_info->signature == MagickSignature);
4918 if (image_info->debug != MagickFalse)
4919 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4920 image_info->filename);
4921 assert(ximage_info != (XImportInfo *) NULL);
4922 display=XOpenDisplay(image_info->server_name);
4923 if (display == (Display *) NULL)
4924 {
4925 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4926 XDisplayName(image_info->server_name));
4927 return((Image *) NULL);
4928 }
4929 /*
4930 Set our forgiving exception handler.
4931 */
4932 (void) XSetErrorHandler(XError);
4933 /*
4934 Select target window.
4935 */
4936 crop_info.x=0;
4937 crop_info.y=0;
4938 crop_info.width=0;
4939 crop_info.height=0;
4940 root=XRootWindow(display,XDefaultScreen(display));
4941 target=(Window) NULL;
4942 if ((image_info->filename != (char *) NULL) &&
4943 (*image_info->filename != '\0'))
4944 {
4945 if (LocaleCompare(image_info->filename,"root") == 0)
4946 target=root;
4947 else
4948 {
4949 /*
4950 Select window by ID or name.
4951 */
4952 if (isdigit((unsigned char) *image_info->filename) != 0)
4953 target=XWindowByID(display,root,(Window)
4954 strtol(image_info->filename,(char **) NULL,0));
4955 if (target == (Window) NULL)
4956 target=XWindowByName(display,root,image_info->filename);
4957 if (target == (Window) NULL)
4958 ThrowXWindowFatalException(XServerError,
4959 "NoWindowWithSpecifiedIDExists",image_info->filename);
4960 }
4961 }
4962 /*
4963 If target window is not defined, interactively select one.
4964 */
4965 prior_target=target;
4966 if (target == (Window) NULL)
4967 target=XSelectWindow(display,&crop_info);
4968 if (target == (Window) NULL)
4969 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4970 image_info->filename);
4971 client=target; /* obsolete */
4972 if (target != root)
4973 {
4974 unsigned int
4975 d;
4976
4977 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4978 if (status != False)
4979 {
4980 for ( ; ; )
4981 {
4982 Window
4983 parent;
4984
4985 /*
4986 Find window manager frame.
4987 */
4988 status=XQueryTree(display,target,&root,&parent,&children,&d);
4989 if ((status != False) && (children != (Window *) NULL))
4990 (void) XFree((char *) children);
4991 if ((status == False) || (parent == (Window) NULL) ||
4992 (parent == root))
4993 break;
4994 target=parent;
4995 }
4996 /*
4997 Get client window.
4998 */
4999 client=XClientWindow(display,target);
5000 if (ximage_info->frame == MagickFalse)
5001 target=client;
5002 if ((ximage_info->frame == MagickFalse) &&
5003 (prior_target != MagickFalse))
5004 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00005005 }
5006 }
5007 if (ximage_info->screen)
5008 {
5009 int
5010 y;
5011
5012 Window
5013 child;
5014
5015 XWindowAttributes
5016 window_attributes;
5017
5018 /*
5019 Obtain window image directly from screen.
5020 */
5021 status=XGetWindowAttributes(display,target,&window_attributes);
5022 if (status == False)
5023 {
5024 ThrowXWindowFatalException(XServerError,
5025 "UnableToReadXWindowAttributes",image_info->filename);
5026 (void) XCloseDisplay(display);
5027 return((Image *) NULL);
5028 }
5029 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005030 crop_info.x=(ssize_t) x;
5031 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005032 crop_info.width=(size_t) window_attributes.width;
5033 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005034 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005035 {
5036 /*
5037 Include border in image.
5038 */
5039 crop_info.x-=window_attributes.border_width;
5040 crop_info.y-=window_attributes.border_width;
5041 crop_info.width+=window_attributes.border_width << 1;
5042 crop_info.height+=window_attributes.border_width << 1;
5043 }
5044 target=root;
5045 }
5046 /*
5047 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5048 */
5049 number_windows=0;
5050 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5051 if ((status == True) && (number_windows > 0))
5052 {
5053 ximage_info->descend=MagickTrue;
5054 (void) XFree ((char *) children);
5055 }
5056 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5057 if (number_colormaps > 0)
5058 {
5059 if (number_colormaps > 1)
5060 ximage_info->descend=MagickTrue;
5061 (void) XFree((char *) colormaps);
5062 }
5063 /*
5064 Alert the user not to alter the screen.
5065 */
5066 if (ximage_info->silent == MagickFalse)
5067 (void) XBell(display,0);
5068 /*
5069 Get image by window id.
5070 */
5071 (void) XGrabServer(display);
5072 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005073 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005074 (void) XUngrabServer(display);
5075 if (image == (Image *) NULL)
5076 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5077 image_info->filename)
5078 else
5079 {
5080 (void) CopyMagickString(image->filename,image_info->filename,
5081 MaxTextExtent);
5082 if ((crop_info.width != 0) && (crop_info.height != 0))
5083 {
5084 Image
5085 *clone_image,
5086 *crop_image;
5087
5088 /*
5089 Crop image as defined by the cropping rectangle.
5090 */
cristy6710d842011-10-20 23:23:00 +00005091 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005092 if (clone_image != (Image *) NULL)
5093 {
cristy6710d842011-10-20 23:23:00 +00005094 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005095 if (crop_image != (Image *) NULL)
5096 {
5097 image=DestroyImage(image);
5098 image=crop_image;
5099 }
5100 }
5101 }
5102 status=XGetWMName(display,target,&window_name);
5103 if (status == True)
5104 {
5105 if ((image_info->filename != (char *) NULL) &&
5106 (*image_info->filename == '\0'))
5107 (void) CopyMagickString(image->filename,(char *) window_name.value,
5108 (size_t) window_name.nitems+1);
5109 (void) XFree((void *) window_name.value);
5110 }
5111 }
5112 if (ximage_info->silent == MagickFalse)
5113 {
5114 /*
5115 Alert the user we're done.
5116 */
5117 (void) XBell(display,0);
5118 (void) XBell(display,0);
5119 }
5120 (void) XCloseDisplay(display);
5121 return(image);
5122}
5123
5124/*
5125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5126% %
5127% %
5128% %
5129% X I n i t i a l i z e W i n d o w s %
5130% %
5131% %
5132% %
5133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5134%
5135% XInitializeWindows() initializes the XWindows structure.
5136%
5137% The format of the XInitializeWindows method is:
5138%
5139% XWindows *XInitializeWindows(Display *display,
5140% XResourceInfo *resource_info)
5141%
5142% A description of each parameter follows:
5143%
5144% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5145%
5146% o display: Specifies a connection to an X server; returned from
5147% XOpenDisplay.
5148%
5149% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5150%
5151*/
cristybcbda3f2011-09-03 13:01:22 +00005152MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005153 XResourceInfo *resource_info)
5154{
5155 Window
5156 root_window;
5157
5158 XWindows
5159 *windows;
5160
5161 /*
5162 Allocate windows structure.
5163 */
cristy73bd4a52010-10-05 11:24:23 +00005164 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005165 if (windows == (XWindows *) NULL)
5166 {
5167 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5168 "...");
5169 return((XWindows *) NULL);
5170 }
5171 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5172 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5173 sizeof(*windows->pixel_info));
5174 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5175 sizeof(*windows->icon_pixel));
5176 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5177 sizeof(*windows->icon_resources));
5178 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5179 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5180 (windows->icon_resources == (XResourceInfo *) NULL))
5181 {
5182 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5183 "...");
5184 return((XWindows *) NULL);
5185 }
5186 /*
5187 Initialize windows structure.
5188 */
5189 windows->display=display;
5190 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5191 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5192 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5193 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5194 windows->im_remote_command=
5195 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5196 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5197 windows->im_update_colormap=
5198 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5199 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5200 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5201 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5202 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5203 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005204#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005205 (void) XSynchronize(display,IsWindows95());
5206#endif
5207 if (IsEventLogging())
5208 {
5209 (void) XSynchronize(display,MagickTrue);
5210 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005211 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005212 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5213 (void) LogMagickEvent(X11Event,GetMagickModule(),
5214 " Window Manager: 0x%lx",windows->wm_protocols);
5215 (void) LogMagickEvent(X11Event,GetMagickModule(),
5216 " delete window: 0x%lx",windows->wm_delete_window);
5217 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5218 windows->wm_take_focus);
5219 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5220 windows->im_protocols);
5221 (void) LogMagickEvent(X11Event,GetMagickModule(),
5222 " remote command: 0x%lx",windows->im_remote_command);
5223 (void) LogMagickEvent(X11Event,GetMagickModule(),
5224 " update widget: 0x%lx",windows->im_update_widget);
5225 (void) LogMagickEvent(X11Event,GetMagickModule(),
5226 " update colormap: 0x%lx",windows->im_update_colormap);
5227 (void) LogMagickEvent(X11Event,GetMagickModule(),
5228 " former image: 0x%lx",windows->im_former_image);
5229 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5230 windows->im_next_image);
5231 (void) LogMagickEvent(X11Event,GetMagickModule(),
5232 " retain colors: 0x%lx",windows->im_retain_colors);
5233 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5234 windows->im_exit);
5235 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5236 windows->dnd_protocols);
5237 }
5238 /*
5239 Allocate standard colormap.
5240 */
5241 windows->map_info=XAllocStandardColormap();
5242 windows->icon_map=XAllocStandardColormap();
5243 if ((windows->map_info == (XStandardColormap *) NULL) ||
5244 (windows->icon_map == (XStandardColormap *) NULL))
5245 ThrowXWindowFatalException(ResourceLimitFatalError,
5246 "MemoryAllocationFailed","...");
5247 windows->map_info->colormap=(Colormap) NULL;
5248 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005249 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005250 windows->pixel_info->annotate_context=(GC) NULL;
5251 windows->pixel_info->highlight_context=(GC) NULL;
5252 windows->pixel_info->widget_context=(GC) NULL;
5253 windows->font_info=(XFontStruct *) NULL;
5254 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005255 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005256 /*
5257 Allocate visual.
5258 */
5259 *windows->icon_resources=(*resource_info);
5260 windows->icon_resources->visual_type=(char *) "default";
5261 windows->icon_resources->colormap=SharedColormap;
5262 windows->visual_info=
5263 XBestVisualInfo(display,windows->map_info,resource_info);
5264 windows->icon_visual=
5265 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5266 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5267 (windows->icon_visual == (XVisualInfo *) NULL))
5268 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5269 resource_info->visual_type);
5270 if (IsEventLogging())
5271 {
5272 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5273 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5274 windows->visual_info->visualid);
5275 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5276 XVisualClassName(windows->visual_info->klass));
5277 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5278 windows->visual_info->depth);
5279 (void) LogMagickEvent(X11Event,GetMagickModule(),
5280 " size of colormap: %d entries",windows->visual_info->colormap_size);
5281 (void) LogMagickEvent(X11Event,GetMagickModule(),
5282 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5283 windows->visual_info->red_mask,windows->visual_info->green_mask,
5284 windows->visual_info->blue_mask);
5285 (void) LogMagickEvent(X11Event,GetMagickModule(),
5286 " significant bits in color: %d bits",
5287 windows->visual_info->bits_per_rgb);
5288 }
5289 /*
5290 Allocate class and manager hints.
5291 */
5292 windows->class_hints=XAllocClassHint();
5293 windows->manager_hints=XAllocWMHints();
5294 if ((windows->class_hints == (XClassHint *) NULL) ||
5295 (windows->manager_hints == (XWMHints *) NULL))
5296 ThrowXWindowFatalException(ResourceLimitFatalError,
5297 "MemoryAllocationFailed","...");
5298 /*
5299 Determine group leader if we have one.
5300 */
5301 root_window=XRootWindow(display,windows->visual_info->screen);
5302 windows->group_leader.id=(Window) NULL;
5303 if (resource_info->window_group != (char *) NULL)
5304 {
5305 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5306 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5307 strtol((char *) resource_info->window_group,(char **) NULL,0));
5308 if (windows->group_leader.id == (Window) NULL)
5309 windows->group_leader.id=
5310 XWindowByName(display,root_window,resource_info->window_group);
5311 }
5312 return(windows);
5313}
5314
5315/*
5316%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5317% %
5318% %
5319% %
5320% X M a k e C u r s o r %
5321% %
5322% %
5323% %
5324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5325%
5326% XMakeCursor() creates a crosshairs X11 cursor.
5327%
5328% The format of the XMakeCursor method is:
5329%
5330% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5331% char *background_color,char *foreground_color)
5332%
5333% A description of each parameter follows:
5334%
5335% o display: Specifies a connection to an X server; returned from
5336% XOpenDisplay.
5337%
5338% o window: Specifies the ID of the window for which the cursor is
5339% assigned.
5340%
5341% o colormap: Specifies the ID of the colormap from which the background
5342% and foreground color will be retrieved.
5343%
5344% o background_color: Specifies the color to use for the cursor background.
5345%
5346% o foreground_color: Specifies the color to use for the cursor foreground.
5347%
5348*/
cristybcbda3f2011-09-03 13:01:22 +00005349MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005350 Colormap colormap,char *background_color,char *foreground_color)
5351{
5352#define scope_height 17
5353#define scope_x_hot 8
5354#define scope_y_hot 8
5355#define scope_width 17
5356
5357 static const unsigned char
5358 scope_bits[] =
5359 {
5360 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5361 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5362 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5363 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5364 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5365 },
5366 scope_mask_bits[] =
5367 {
5368 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5369 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5370 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5371 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5372 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5373 };
5374
5375 Cursor
5376 cursor;
5377
5378 Pixmap
5379 mask,
5380 source;
5381
5382 XColor
5383 background,
5384 foreground;
5385
5386 assert(display != (Display *) NULL);
5387 assert(window != (Window) NULL);
5388 assert(colormap != (Colormap) NULL);
5389 assert(background_color != (char *) NULL);
5390 assert(foreground_color != (char *) NULL);
5391 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5392 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5393 scope_height);
5394 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5395 scope_width,scope_height);
5396 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5397 {
5398 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5399 return((Cursor) NULL);
5400 }
5401 (void) XParseColor(display,colormap,background_color,&background);
5402 (void) XParseColor(display,colormap,foreground_color,&foreground);
5403 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5404 scope_x_hot,scope_y_hot);
5405 (void) XFreePixmap(display,source);
5406 (void) XFreePixmap(display,mask);
5407 return(cursor);
5408}
5409
5410/*
5411%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5412% %
5413% %
5414% %
5415% X M a k e I m a g e %
5416% %
5417% %
5418% %
5419%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5420%
5421% XMakeImage() creates an X11 image. If the image size differs from the X11
5422% image size, the image is first resized.
5423%
5424% The format of the XMakeImage method is:
5425%
5426% MagickBooleanType XMakeImage(Display *display,
5427% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005428% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005429%
5430% A description of each parameter follows:
5431%
5432% o display: Specifies a connection to an X server; returned from
5433% XOpenDisplay.
5434%
5435% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5436%
5437% o window: Specifies a pointer to a XWindowInfo structure.
5438%
5439% o image: the image.
5440%
5441% o width: Specifies the width in pixels of the rectangular area to
5442% display.
5443%
5444% o height: Specifies the height in pixels of the rectangular area to
5445% display.
5446%
cristy051718b2011-08-28 22:49:25 +00005447% o exception: return any errors or warnings in this structure.
5448%
cristy3ed852e2009-09-05 21:47:34 +00005449*/
cristybcbda3f2011-09-03 13:01:22 +00005450MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005451 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005452 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005453{
5454#define CheckOverflowException(length,width,height) \
5455 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5456
5457 int
5458 depth,
5459 format;
5460
5461 size_t
5462 length;
5463
5464 XImage
5465 *matte_image,
5466 *ximage;
5467
5468 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5469 assert(display != (Display *) NULL);
5470 assert(resource_info != (XResourceInfo *) NULL);
5471 assert(window != (XWindowInfo *) NULL);
5472 assert(width != 0);
5473 assert(height != 0);
5474 if ((window->width == 0) || (window->height == 0))
5475 return(MagickFalse);
5476 /*
5477 Apply user transforms to the image.
5478 */
5479 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5480 (void) XFlush(display);
5481 depth=(int) window->depth;
5482 if (window->destroy)
5483 window->image=DestroyImage(window->image);
5484 window->image=image;
5485 window->destroy=MagickFalse;
5486 if (window->image != (Image *) NULL)
5487 {
5488 if (window->crop_geometry != (char *) NULL)
5489 {
5490 Image
5491 *crop_image;
5492
5493 RectangleInfo
5494 crop_info;
5495
5496 /*
5497 Crop image.
5498 */
5499 window->image->page.x=0;
5500 window->image->page.y=0;
5501 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005502 &crop_info,exception);
5503 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005504 if (crop_image != (Image *) NULL)
5505 {
5506 if (window->image != image)
5507 window->image=DestroyImage(window->image);
5508 window->image=crop_image;
5509 window->destroy=MagickTrue;
5510 }
5511 }
5512 if ((width != (unsigned int) window->image->columns) ||
5513 (height != (unsigned int) window->image->rows))
5514 {
5515 Image
5516 *resize_image;
5517
5518 /*
5519 Resize image.
5520 */
5521 resize_image=NewImageList();
5522 if (window->pixel_info->colors != 0)
cristy6710d842011-10-20 23:23:00 +00005523 resize_image=SampleImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005524 else
cristy6710d842011-10-20 23:23:00 +00005525 resize_image=ThumbnailImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005526 if (resize_image != (Image *) NULL)
5527 {
5528 if (window->image != image)
5529 window->image=DestroyImage(window->image);
5530 window->image=resize_image;
5531 window->destroy=MagickTrue;
5532 }
5533 }
5534 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005535 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005536 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005537 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005538 }
5539 /*
5540 Create X image.
5541 */
5542 ximage=(XImage *) NULL;
5543 format=(depth == 1) ? XYBitmap : ZPixmap;
5544#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5545 if (window->shared_memory != MagickFalse)
5546 {
5547 XShmSegmentInfo
5548 *segment_info;
5549
5550 segment_info=(XShmSegmentInfo *) window->segment_info;
5551 segment_info[1].shmid=(-1);
5552 segment_info[1].shmaddr=(char *) NULL;
5553 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5554 (char *) NULL,&segment_info[1],width,height);
5555 if (ximage == (XImage *) NULL)
5556 window->shared_memory=MagickFalse;
5557 length=(size_t) ximage->bytes_per_line*ximage->height;
5558 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5559 window->shared_memory=MagickFalse;
5560 if (window->shared_memory != MagickFalse)
5561 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5562 if (window->shared_memory != MagickFalse)
5563 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5564 if (segment_info[1].shmid < 0)
5565 window->shared_memory=MagickFalse;
5566 if (window->shared_memory != MagickFalse)
5567 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5568 else
5569 {
5570 if (ximage != (XImage *) NULL)
5571 XDestroyImage(ximage);
5572 ximage=(XImage *) NULL;
5573 if (segment_info[1].shmaddr)
5574 {
5575 (void) shmdt(segment_info[1].shmaddr);
5576 segment_info[1].shmaddr=(char *) NULL;
5577 }
5578 if (segment_info[1].shmid >= 0)
5579 {
5580 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5581 segment_info[1].shmid=(-1);
5582 }
5583 }
5584 }
5585#endif
5586 /*
5587 Allocate X image pixel data.
5588 */
5589#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5590 if (window->shared_memory)
5591 {
5592 Status
5593 status;
5594
5595 XShmSegmentInfo
5596 *segment_info;
5597
5598 (void) XSync(display,MagickFalse);
5599 xerror_alert=MagickFalse;
5600 segment_info=(XShmSegmentInfo *) window->segment_info;
5601 ximage->data=segment_info[1].shmaddr;
5602 segment_info[1].readOnly=MagickFalse;
5603 status=XShmAttach(display,&segment_info[1]);
5604 if (status != False)
5605 (void) XSync(display,MagickFalse);
5606 if ((status == False) || (xerror_alert != MagickFalse))
5607 {
5608 window->shared_memory=MagickFalse;
5609 if (status != False)
5610 XShmDetach(display,&segment_info[1]);
5611 if (ximage != (XImage *) NULL)
5612 {
5613 ximage->data=NULL;
5614 XDestroyImage(ximage);
5615 ximage=(XImage *) NULL;
5616 }
5617 if (segment_info[1].shmid >= 0)
5618 {
5619 if (segment_info[1].shmaddr != NULL)
5620 (void) shmdt(segment_info[1].shmaddr);
5621 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5622 segment_info[1].shmid=(-1);
5623 segment_info[1].shmaddr=(char *) NULL;
5624 }
5625 }
5626 }
5627#endif
5628 if (window->shared_memory == MagickFalse)
5629 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5630 (char *) NULL,width,height,XBitmapPad(display),0);
5631 if (ximage == (XImage *) NULL)
5632 {
5633 /*
5634 Unable to create X image.
5635 */
5636 (void) XCheckDefineCursor(display,window->id,window->cursor);
5637 return(MagickFalse);
5638 }
5639 length=(size_t) ximage->bytes_per_line*ximage->height;
5640 if (IsEventLogging())
5641 {
5642 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5643 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5644 ximage->width,ximage->height);
5645 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5646 ximage->format);
5647 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5648 ximage->byte_order);
5649 (void) LogMagickEvent(X11Event,GetMagickModule(),
5650 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5651 ximage->bitmap_bit_order,ximage->bitmap_pad);
5652 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5653 ximage->depth);
5654 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5655 ximage->bytes_per_line);
5656 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5657 ximage->bits_per_pixel);
5658 (void) LogMagickEvent(X11Event,GetMagickModule(),
5659 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5660 ximage->green_mask,ximage->blue_mask);
5661 }
5662 if (window->shared_memory == MagickFalse)
5663 {
5664 if (ximage->format != XYBitmap)
5665 ximage->data=(char *) AcquireQuantumMemory((size_t)
5666 ximage->bytes_per_line,(size_t) ximage->height);
5667 else
5668 ximage->data=(char *) AcquireQuantumMemory((size_t)
5669 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5670 }
5671 if (ximage->data == (char *) NULL)
5672 {
5673 /*
5674 Unable to allocate pixel data.
5675 */
5676 XDestroyImage(ximage);
5677 ximage=(XImage *) NULL;
5678 (void) XCheckDefineCursor(display,window->id,window->cursor);
5679 return(MagickFalse);
5680 }
5681 if (window->ximage != (XImage *) NULL)
5682 {
5683 /*
5684 Destroy previous X image.
5685 */
5686 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5687#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5688 if (window->segment_info != (XShmSegmentInfo *) NULL)
5689 {
5690 XShmSegmentInfo
5691 *segment_info;
5692
5693 segment_info=(XShmSegmentInfo *) window->segment_info;
5694 if (segment_info[0].shmid >= 0)
5695 {
5696 (void) XSync(display,MagickFalse);
5697 (void) XShmDetach(display,&segment_info[0]);
5698 (void) XSync(display,MagickFalse);
5699 if (segment_info[0].shmaddr != (char *) NULL)
5700 (void) shmdt(segment_info[0].shmaddr);
5701 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5702 segment_info[0].shmid=(-1);
5703 segment_info[0].shmaddr=(char *) NULL;
5704 window->ximage->data=(char *) NULL;
5705 }
5706 }
5707#endif
5708 if (window->ximage->data != (char *) NULL)
5709 free(window->ximage->data);
5710 window->ximage->data=(char *) NULL;
5711 XDestroyImage(window->ximage);
5712 window->ximage=(XImage *) NULL;
5713 }
5714#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5715 if (window->segment_info != (XShmSegmentInfo *) NULL)
5716 {
5717 XShmSegmentInfo
5718 *segment_info;
5719
5720 segment_info=(XShmSegmentInfo *) window->segment_info;
5721 segment_info[0]=segment_info[1];
5722 }
5723#endif
5724 window->ximage=ximage;
5725 matte_image=(XImage *) NULL;
5726 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5727 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005728 ((int) width <= XDisplayWidth(display,window->screen)) &&
5729 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005730 {
5731 /*
5732 Create matte image.
5733 */
5734 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5735 (char *) NULL,width,height,XBitmapPad(display),0);
5736 if (IsEventLogging())
5737 {
5738 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5739 (void) LogMagickEvent(X11Event,GetMagickModule(),
5740 " width, height: %dx%d",matte_image->width,matte_image->height);
5741 }
5742 if (matte_image != (XImage *) NULL)
5743 {
5744 /*
5745 Allocate matte image pixel data.
5746 */
5747 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5748 matte_image->bytes_per_line*matte_image->depth,
5749 (size_t) matte_image->height);
5750 if (matte_image->data == (char *) NULL)
5751 {
5752 XDestroyImage(matte_image);
5753 matte_image=(XImage *) NULL;
5754 }
5755 }
5756 }
5757 if (window->matte_image != (XImage *) NULL)
5758 {
5759 /*
5760 Free matte image.
5761 */
5762 if (window->matte_image->data != (char *) NULL)
5763 free(window->matte_image->data);
5764 window->matte_image->data=(char *) NULL;
5765 XDestroyImage(window->matte_image);
5766 window->matte_image=(XImage *) NULL;
5767 }
5768 window->matte_image=matte_image;
5769 if (window->matte_pixmap != (Pixmap) NULL)
5770 {
5771 (void) XFreePixmap(display,window->matte_pixmap);
5772 window->matte_pixmap=(Pixmap) NULL;
5773#if defined(MAGICKCORE_HAVE_SHAPE)
5774 if (window->shape != MagickFalse)
5775 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5776#endif
5777 }
5778 window->stasis=MagickFalse;
5779 /*
5780 Convert pixels to X image data.
5781 */
5782 if (window->image != (Image *) NULL)
5783 {
5784 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5785 (ximage->bitmap_bit_order == LSBFirst)))
5786 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005787 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005788 else
5789 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005790 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005791 }
5792 if (window->matte_image != (XImage *) NULL)
5793 {
5794 /*
5795 Create matte pixmap.
5796 */
5797 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5798 if (window->matte_pixmap != (Pixmap) NULL)
5799 {
5800 GC
5801 graphics_context;
5802
5803 XGCValues
5804 context_values;
5805
5806 /*
5807 Copy matte image to matte pixmap.
5808 */
cristy4c08aed2011-07-01 19:47:50 +00005809 context_values.background=0;
5810 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005811 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005812 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005813 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5814 window->matte_image,0,0,0,0,width,height);
5815 (void) XFreeGC(display,graphics_context);
5816#if defined(MAGICKCORE_HAVE_SHAPE)
5817 if (window->shape != MagickFalse)
5818 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5819 window->matte_pixmap,ShapeSet);
5820#endif
5821 }
5822 }
5823 (void) XMakePixmap(display,resource_info,window);
5824 /*
5825 Restore cursor.
5826 */
5827 (void) XCheckDefineCursor(display,window->id,window->cursor);
5828 return(MagickTrue);
5829}
5830
5831/*
5832%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5833% %
5834% %
5835% %
5836+ X M a k e I m a g e L S B F i r s t %
5837% %
5838% %
5839% %
5840%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5841%
5842% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5843% pixels are copied in least-significant bit and byte first order. The
5844% server's scanline pad is respected. Rather than using one or two general
5845% cases, many special cases are found here to help speed up the image
5846% conversion.
5847%
5848% The format of the XMakeImageLSBFirst method is:
5849%
cristye941a752011-10-15 01:52:48 +00005850% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5851% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005852%
5853% A description of each parameter follows:
5854%
5855% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5856%
5857% o window: Specifies a pointer to a XWindowInfo structure.
5858%
5859% o image: the image.
5860%
5861% o ximage: Specifies a pointer to a XImage structure; returned from
5862% XCreateImage.
5863%
5864% o matte_image: Specifies a pointer to a XImage structure; returned from
5865% XCreateImage.
5866%
cristye941a752011-10-15 01:52:48 +00005867% o exception: return any errors or warnings in this structure.
5868%
cristy3ed852e2009-09-05 21:47:34 +00005869*/
5870static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005871 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5872 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005873{
cristyc57f6942010-11-12 01:47:39 +00005874 CacheView
5875 *canvas_view;
5876
cristy3ed852e2009-09-05 21:47:34 +00005877 Image
5878 *canvas;
5879
5880 int
5881 y;
5882
cristy4c08aed2011-07-01 19:47:50 +00005883 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005884 *p;
5885
5886 register int
5887 x;
5888
5889 register unsigned char
5890 *q;
5891
5892 unsigned char
5893 bit,
5894 byte;
5895
5896 unsigned int
5897 scanline_pad;
5898
cristyf2faecf2010-05-28 19:19:36 +00005899 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005900 pixel,
5901 *pixels;
5902
5903 XStandardColormap
5904 *map_info;
5905
5906 assert(resource_info != (XResourceInfo *) NULL);
5907 assert(window != (XWindowInfo *) NULL);
5908 assert(image != (Image *) NULL);
5909 if (image->debug != MagickFalse)
5910 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5911 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005912 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005913 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005914 {
5915 char
5916 size[MaxTextExtent];
5917
5918 Image
5919 *pattern;
5920
5921 ImageInfo
5922 *image_info;
5923
5924 image_info=AcquireImageInfo();
5925 (void) CopyMagickString(image_info->filename,
5926 resource_info->image_info->texture != (char *) NULL ?
5927 resource_info->image_info->texture : "pattern:checkerboard",
5928 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005929 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005930 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005931 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005932 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005933 image_info=DestroyImageInfo(image_info);
5934 if (pattern != (Image *) NULL)
5935 {
cristy6710d842011-10-20 23:23:00 +00005936 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005937 if (canvas != (Image *) NULL)
cristy39172402012-03-30 13:04:39 +00005938 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00005939 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00005940 pattern=DestroyImage(pattern);
5941 }
5942 }
5943 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5944 ximage->bits_per_pixel) >> 3));
5945 map_info=window->map_info;
5946 pixels=window->pixel_info->pixels;
5947 q=(unsigned char *) ximage->data;
5948 x=0;
cristydb070952012-04-20 14:33:00 +00005949 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00005950 if (ximage->format == XYBitmap)
5951 {
5952 register unsigned short
5953 polarity;
5954
5955 unsigned char
5956 background,
5957 foreground;
5958
5959 /*
5960 Convert canvas to big-endian bitmap.
5961 */
5962 background=(unsigned char)
5963 (XPixelIntensity(&window->pixel_info->foreground_color) <
5964 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5965 foreground=(unsigned char)
5966 (XPixelIntensity(&window->pixel_info->background_color) <
5967 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005968 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005969 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5970 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005971 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5972 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005973 for (y=0; y < (int) canvas->rows; y++)
5974 {
cristyc57f6942010-11-12 01:47:39 +00005975 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005976 exception);
cristy4c08aed2011-07-01 19:47:50 +00005977 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005978 break;
cristy3ed852e2009-09-05 21:47:34 +00005979 bit=0;
5980 byte=0;
5981 for (x=0; x < (int) canvas->columns; x++)
5982 {
5983 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005984 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005985 byte|=foreground;
5986 else
5987 byte|=background;
5988 bit++;
5989 if (bit == 8)
5990 {
5991 *q++=byte;
5992 bit=0;
5993 byte=0;
5994 }
cristyed231572011-07-14 02:18:59 +00005995 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005996 }
5997 if (bit != 0)
5998 *q=byte >> (8-bit);
5999 q+=scanline_pad;
6000 }
6001 }
6002 else
6003 if (window->pixel_info->colors != 0)
6004 switch (ximage->bits_per_pixel)
6005 {
6006 case 2:
6007 {
6008 register unsigned int
6009 nibble;
6010
6011 /*
6012 Convert to 2 bit color-mapped X canvas.
6013 */
6014 for (y=0; y < (int) canvas->rows; y++)
6015 {
cristyc57f6942010-11-12 01:47:39 +00006016 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006017 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006018 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006019 break;
cristy3ed852e2009-09-05 21:47:34 +00006020 nibble=0;
6021 for (x=0; x < (int) canvas->columns; x++)
6022 {
cristy4c08aed2011-07-01 19:47:50 +00006023 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006024 switch (nibble)
6025 {
6026 case 0:
6027 {
6028 *q=(unsigned char) pixel;
6029 nibble++;
6030 break;
6031 }
6032 case 1:
6033 {
6034 *q|=(unsigned char) (pixel << 2);
6035 nibble++;
6036 break;
6037 }
6038 case 2:
6039 {
6040 *q|=(unsigned char) (pixel << 4);
6041 nibble++;
6042 break;
6043 }
6044 case 3:
6045 {
6046 *q|=(unsigned char) (pixel << 6);
6047 q++;
6048 nibble=0;
6049 break;
6050 }
6051 }
cristyed231572011-07-14 02:18:59 +00006052 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006053 }
6054 q+=scanline_pad;
6055 }
6056 break;
6057 }
6058 case 4:
6059 {
6060 register unsigned int
6061 nibble;
6062
6063 /*
6064 Convert to 4 bit color-mapped X canvas.
6065 */
6066 for (y=0; y < (int) canvas->rows; y++)
6067 {
cristyc57f6942010-11-12 01:47:39 +00006068 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006069 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006070 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006071 break;
cristy3ed852e2009-09-05 21:47:34 +00006072 nibble=0;
6073 for (x=0; x < (int) canvas->columns; x++)
6074 {
cristy4c08aed2011-07-01 19:47:50 +00006075 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006076 switch (nibble)
6077 {
6078 case 0:
6079 {
6080 *q=(unsigned char) pixel;
6081 nibble++;
6082 break;
6083 }
6084 case 1:
6085 {
6086 *q|=(unsigned char) (pixel << 4);
6087 q++;
6088 nibble=0;
6089 break;
6090 }
6091 }
cristyed231572011-07-14 02:18:59 +00006092 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006093 }
6094 q+=scanline_pad;
6095 }
6096 break;
6097 }
6098 case 6:
6099 case 8:
6100 {
6101 /*
6102 Convert to 8 bit color-mapped X canvas.
6103 */
6104 if (resource_info->color_recovery &&
6105 resource_info->quantize_info->dither)
6106 {
cristy6710d842011-10-20 23:23:00 +00006107 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006108 break;
6109 }
6110 for (y=0; y < (int) canvas->rows; y++)
6111 {
cristyc57f6942010-11-12 01:47:39 +00006112 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006113 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006114 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006115 break;
cristy3ed852e2009-09-05 21:47:34 +00006116 for (x=0; x < (int) canvas->columns; x++)
6117 {
cristy4c08aed2011-07-01 19:47:50 +00006118 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006119 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006120 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006121 }
6122 q+=scanline_pad;
6123 }
6124 break;
6125 }
6126 default:
6127 {
6128 register int
6129 k;
6130
6131 register unsigned int
6132 bytes_per_pixel;
6133
6134 unsigned char
cristybb503372010-05-27 20:51:26 +00006135 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006136
6137 /*
6138 Convert to multi-byte color-mapped X canvas.
6139 */
6140 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6141 for (y=0; y < (int) canvas->rows; y++)
6142 {
cristyc57f6942010-11-12 01:47:39 +00006143 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006144 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006145 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006146 break;
cristy3ed852e2009-09-05 21:47:34 +00006147 for (x=0; x < (int) canvas->columns; x++)
6148 {
cristy4c08aed2011-07-01 19:47:50 +00006149 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006150 for (k=0; k < (int) bytes_per_pixel; k++)
6151 {
6152 channel[k]=(unsigned char) pixel;
6153 pixel>>=8;
6154 }
6155 for (k=0; k < (int) bytes_per_pixel; k++)
6156 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006157 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006158 }
6159 q+=scanline_pad;
6160 }
6161 break;
6162 }
6163 }
6164 else
6165 switch (ximage->bits_per_pixel)
6166 {
6167 case 2:
6168 {
6169 register unsigned int
6170 nibble;
6171
6172 /*
6173 Convert to contiguous 2 bit continuous-tone X canvas.
6174 */
6175 for (y=0; y < (int) canvas->rows; y++)
6176 {
6177 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006178 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006179 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006180 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006181 break;
6182 for (x=0; x < (int) canvas->columns; x++)
6183 {
cristy4c08aed2011-07-01 19:47:50 +00006184 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006185 pixel&=0xf;
6186 switch (nibble)
6187 {
6188 case 0:
6189 {
6190 *q=(unsigned char) pixel;
6191 nibble++;
6192 break;
6193 }
6194 case 1:
6195 {
6196 *q|=(unsigned char) (pixel << 2);
6197 nibble++;
6198 break;
6199 }
6200 case 2:
6201 {
6202 *q|=(unsigned char) (pixel << 4);
6203 nibble++;
6204 break;
6205 }
6206 case 3:
6207 {
6208 *q|=(unsigned char) (pixel << 6);
6209 q++;
6210 nibble=0;
6211 break;
6212 }
6213 }
cristyed231572011-07-14 02:18:59 +00006214 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006215 }
6216 q+=scanline_pad;
6217 }
6218 break;
6219 }
6220 case 4:
6221 {
6222 register unsigned int
6223 nibble;
6224
6225 /*
6226 Convert to contiguous 4 bit continuous-tone X canvas.
6227 */
6228 for (y=0; y < (int) canvas->rows; y++)
6229 {
cristyc57f6942010-11-12 01:47:39 +00006230 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006231 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006232 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006233 break;
6234 nibble=0;
6235 for (x=0; x < (int) canvas->columns; x++)
6236 {
cristy4c08aed2011-07-01 19:47:50 +00006237 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006238 pixel&=0xf;
6239 switch (nibble)
6240 {
6241 case 0:
6242 {
6243 *q=(unsigned char) pixel;
6244 nibble++;
6245 break;
6246 }
6247 case 1:
6248 {
6249 *q|=(unsigned char) (pixel << 4);
6250 q++;
6251 nibble=0;
6252 break;
6253 }
6254 }
cristyed231572011-07-14 02:18:59 +00006255 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006256 }
6257 q+=scanline_pad;
6258 }
6259 break;
6260 }
6261 case 6:
6262 case 8:
6263 {
6264 /*
6265 Convert to contiguous 8 bit continuous-tone X canvas.
6266 */
6267 if (resource_info->color_recovery &&
6268 resource_info->quantize_info->dither)
6269 {
cristy6710d842011-10-20 23:23:00 +00006270 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006271 break;
6272 }
6273 for (y=0; y < (int) canvas->rows; y++)
6274 {
cristyc57f6942010-11-12 01:47:39 +00006275 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006276 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006277 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006278 break;
6279 for (x=0; x < (int) canvas->columns; x++)
6280 {
cristy4c08aed2011-07-01 19:47:50 +00006281 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006282 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006283 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006284 }
6285 q+=scanline_pad;
6286 }
6287 break;
6288 }
6289 default:
6290 {
6291 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6292 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6293 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6294 (map_info->blue_mult == 1))
6295 {
6296 /*
6297 Convert to 32 bit continuous-tone X canvas.
6298 */
6299 for (y=0; y < (int) canvas->rows; y++)
6300 {
cristyc57f6942010-11-12 01:47:39 +00006301 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006302 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006303 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006304 break;
6305 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6306 (blue_gamma != 1.0))
6307 {
6308 /*
6309 Gamma correct canvas.
6310 */
6311 for (x=(int) canvas->columns-1; x >= 0; x--)
6312 {
cristyccf844f2010-02-03 23:28:16 +00006313 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006314 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006315 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006316 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006317 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006318 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006319 *q++=0;
cristyed231572011-07-14 02:18:59 +00006320 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006321 }
6322 continue;
6323 }
6324 for (x=(int) canvas->columns-1; x >= 0; x--)
6325 {
cristy4c08aed2011-07-01 19:47:50 +00006326 *q++=ScaleQuantumToChar((Quantum)
6327 GetPixelBlue(canvas,p));
6328 *q++=ScaleQuantumToChar((Quantum)
6329 GetPixelGreen(canvas,p));
6330 *q++=ScaleQuantumToChar((Quantum)
6331 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006332 *q++=0;
cristyed231572011-07-14 02:18:59 +00006333 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006334 }
6335 }
6336 }
6337 else
6338 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6339 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6340 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6341 (map_info->blue_mult == 65536L))
6342 {
6343 /*
6344 Convert to 32 bit continuous-tone X canvas.
6345 */
6346 for (y=0; y < (int) canvas->rows; y++)
6347 {
cristyc57f6942010-11-12 01:47:39 +00006348 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006349 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006350 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006351 break;
6352 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6353 (blue_gamma != 1.0))
6354 {
6355 /*
6356 Gamma correct canvas.
6357 */
6358 for (x=(int) canvas->columns-1; x >= 0; x--)
6359 {
cristyccf844f2010-02-03 23:28:16 +00006360 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006361 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006362 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006363 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006364 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006365 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006366 *q++=0;
cristyed231572011-07-14 02:18:59 +00006367 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006368 }
6369 continue;
6370 }
6371 for (x=(int) canvas->columns-1; x >= 0; x--)
6372 {
cristyccf844f2010-02-03 23:28:16 +00006373 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006374 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006375 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006376 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006377 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006378 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006379 *q++=0;
cristyed231572011-07-14 02:18:59 +00006380 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006381 }
6382 }
6383 }
6384 else
6385 {
6386 register int
6387 k;
6388
6389 register unsigned int
6390 bytes_per_pixel;
6391
6392 unsigned char
cristybb503372010-05-27 20:51:26 +00006393 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006394
6395 /*
6396 Convert to multi-byte continuous-tone X canvas.
6397 */
6398 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6399 for (y=0; y < (int) canvas->rows; y++)
6400 {
cristyc57f6942010-11-12 01:47:39 +00006401 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006402 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006403 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006404 break;
cristyc57f6942010-11-12 01:47:39 +00006405 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006406 {
cristy4c08aed2011-07-01 19:47:50 +00006407 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006408 for (k=0; k < (int) bytes_per_pixel; k++)
6409 {
6410 channel[k]=(unsigned char) pixel;
6411 pixel>>=8;
6412 }
6413 for (k=0; k < (int) bytes_per_pixel; k++)
6414 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006415 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006416 }
6417 q+=scanline_pad;
6418 }
6419 }
6420 break;
6421 }
6422 }
6423 if (matte_image != (XImage *) NULL)
6424 {
6425 /*
6426 Initialize matte canvas.
6427 */
6428 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6429 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6430 q=(unsigned char *) matte_image->data;
6431 for (y=0; y < (int) canvas->rows; y++)
6432 {
cristyc57f6942010-11-12 01:47:39 +00006433 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006434 exception);
cristy4c08aed2011-07-01 19:47:50 +00006435 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006436 break;
6437 bit=0;
6438 byte=0;
6439 for (x=(int) canvas->columns-1; x >= 0; x--)
6440 {
6441 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006442 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006443 byte|=0x80;
6444 bit++;
6445 if (bit == 8)
6446 {
6447 *q++=byte;
6448 bit=0;
6449 byte=0;
6450 }
cristyed231572011-07-14 02:18:59 +00006451 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006452 }
6453 if (bit != 0)
6454 *q=byte >> (8-bit);
6455 q+=scanline_pad;
6456 }
6457 }
cristyc57f6942010-11-12 01:47:39 +00006458 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006459 if (canvas != image)
6460 canvas=DestroyImage(canvas);
6461}
6462
6463/*
6464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6465% %
6466% %
6467% %
6468+ X M a k e I m a g e M S B F i r s t %
6469% %
6470% %
6471% %
6472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6473%
6474% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6475% image pixels are copied in most-significant bit and byte first order. The
6476% server's scanline pad is also respected. Rather than using one or two
6477% general cases, many special cases are found here to help speed up the image
6478% conversion.
6479%
6480% The format of the XMakeImageMSBFirst method is:
6481%
cristye941a752011-10-15 01:52:48 +00006482% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6483% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006484%
6485% A description of each parameter follows:
6486%
6487% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6488%
6489% o window: Specifies a pointer to a XWindowInfo structure.
6490%
6491% o image: the image.
6492%
6493% o ximage: Specifies a pointer to a XImage structure; returned from
6494% XCreateImage.
6495%
6496% o matte_image: Specifies a pointer to a XImage structure; returned from
6497% XCreateImage.
6498%
cristye941a752011-10-15 01:52:48 +00006499% o exception: return any errors or warnings in this structure.
6500%
cristy3ed852e2009-09-05 21:47:34 +00006501*/
6502static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006503 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6504 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006505{
cristyc57f6942010-11-12 01:47:39 +00006506 CacheView
6507 *canvas_view;
6508
cristy3ed852e2009-09-05 21:47:34 +00006509 Image
6510 *canvas;
6511
6512 int
6513 y;
6514
6515 register int
6516 x;
6517
cristy4c08aed2011-07-01 19:47:50 +00006518 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006519 *p;
6520
6521 register unsigned char
6522 *q;
6523
6524 unsigned char
6525 bit,
6526 byte;
6527
6528 unsigned int
6529 scanline_pad;
6530
cristyf2faecf2010-05-28 19:19:36 +00006531 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006532 pixel,
6533 *pixels;
6534
6535 XStandardColormap
6536 *map_info;
6537
6538 assert(resource_info != (XResourceInfo *) NULL);
6539 assert(window != (XWindowInfo *) NULL);
6540 assert(image != (Image *) NULL);
6541 if (image->debug != MagickFalse)
6542 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6543 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006544 if ((window->immutable != MagickFalse) &&
6545 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006546 {
6547 char
6548 size[MaxTextExtent];
6549
6550 Image
6551 *pattern;
6552
6553 ImageInfo
6554 *image_info;
6555
6556 image_info=AcquireImageInfo();
6557 (void) CopyMagickString(image_info->filename,
6558 resource_info->image_info->texture != (char *) NULL ?
6559 resource_info->image_info->texture : "pattern:checkerboard",
6560 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006561 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006562 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006563 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006564 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006565 image_info=DestroyImageInfo(image_info);
6566 if (pattern != (Image *) NULL)
6567 {
cristy6710d842011-10-20 23:23:00 +00006568 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006569 if (canvas != (Image *) NULL)
cristyfeb3e962012-03-29 17:25:55 +00006570 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6571 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00006572 pattern=DestroyImage(pattern);
6573 }
6574 }
cristy4c08aed2011-07-01 19:47:50 +00006575 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6576 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006577 map_info=window->map_info;
6578 pixels=window->pixel_info->pixels;
6579 q=(unsigned char *) ximage->data;
6580 x=0;
cristydb070952012-04-20 14:33:00 +00006581 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00006582 if (ximage->format == XYBitmap)
6583 {
6584 register unsigned short
6585 polarity;
6586
6587 unsigned char
6588 background,
6589 foreground;
6590
6591 /*
6592 Convert canvas to big-endian bitmap.
6593 */
6594 background=(unsigned char)
6595 (XPixelIntensity(&window->pixel_info->foreground_color) <
6596 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6597 foreground=(unsigned char)
6598 (XPixelIntensity(&window->pixel_info->background_color) <
6599 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006600 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006601 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6602 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006603 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6604 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006605 for (y=0; y < (int) canvas->rows; y++)
6606 {
cristyc57f6942010-11-12 01:47:39 +00006607 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006608 exception);
cristy4c08aed2011-07-01 19:47:50 +00006609 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006610 break;
cristy3ed852e2009-09-05 21:47:34 +00006611 bit=0;
6612 byte=0;
6613 for (x=(int) canvas->columns-1; x >= 0; x--)
6614 {
6615 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006616 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006617 byte|=foreground;
6618 else
6619 byte|=background;
6620 bit++;
6621 if (bit == 8)
6622 {
6623 *q++=byte;
6624 bit=0;
6625 byte=0;
6626 }
cristyed231572011-07-14 02:18:59 +00006627 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006628 }
6629 if (bit != 0)
6630 *q=byte << (8-bit);
6631 q+=scanline_pad;
6632 }
6633 }
6634 else
6635 if (window->pixel_info->colors != 0)
6636 switch (ximage->bits_per_pixel)
6637 {
6638 case 2:
6639 {
6640 register unsigned int
6641 nibble;
6642
6643 /*
6644 Convert to 2 bit color-mapped X canvas.
6645 */
6646 for (y=0; y < (int) canvas->rows; y++)
6647 {
cristyc57f6942010-11-12 01:47:39 +00006648 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006649 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006650 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006651 break;
cristy3ed852e2009-09-05 21:47:34 +00006652 nibble=0;
6653 for (x=0; x < (int) canvas->columns; x++)
6654 {
cristy4c08aed2011-07-01 19:47:50 +00006655 pixel=pixels[(ssize_t)
6656 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006657 switch (nibble)
6658 {
6659 case 0:
6660 {
6661 *q=(unsigned char) (pixel << 6);
6662 nibble++;
6663 break;
6664 }
6665 case 1:
6666 {
6667 *q|=(unsigned char) (pixel << 4);
6668 nibble++;
6669 break;
6670 }
6671 case 2:
6672 {
6673 *q|=(unsigned char) (pixel << 2);
6674 nibble++;
6675 break;
6676 }
6677 case 3:
6678 {
6679 *q|=(unsigned char) pixel;
6680 q++;
6681 nibble=0;
6682 break;
6683 }
6684 }
cristyed231572011-07-14 02:18:59 +00006685 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006686 }
6687 q+=scanline_pad;
6688 }
6689 break;
6690 }
6691 case 4:
6692 {
6693 register unsigned int
6694 nibble;
6695
6696 /*
6697 Convert to 4 bit color-mapped X canvas.
6698 */
6699 for (y=0; y < (int) canvas->rows; y++)
6700 {
cristyc57f6942010-11-12 01:47:39 +00006701 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006702 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006703 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006704 break;
cristy3ed852e2009-09-05 21:47:34 +00006705 nibble=0;
6706 for (x=0; x < (int) canvas->columns; x++)
6707 {
cristy4c08aed2011-07-01 19:47:50 +00006708 pixel=pixels[(ssize_t)
6709 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006710 switch (nibble)
6711 {
6712 case 0:
6713 {
6714 *q=(unsigned char) (pixel << 4);
6715 nibble++;
6716 break;
6717 }
6718 case 1:
6719 {
6720 *q|=(unsigned char) pixel;
6721 q++;
6722 nibble=0;
6723 break;
6724 }
6725 }
cristyed231572011-07-14 02:18:59 +00006726 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006727 }
6728 q+=scanline_pad;
6729 }
6730 break;
6731 }
6732 case 6:
6733 case 8:
6734 {
6735 /*
6736 Convert to 8 bit color-mapped X canvas.
6737 */
6738 if (resource_info->color_recovery &&
6739 resource_info->quantize_info->dither)
6740 {
cristy6710d842011-10-20 23:23:00 +00006741 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006742 break;
6743 }
6744 for (y=0; y < (int) canvas->rows; y++)
6745 {
cristyc57f6942010-11-12 01:47:39 +00006746 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006747 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006748 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006749 break;
cristy3ed852e2009-09-05 21:47:34 +00006750 for (x=0; x < (int) canvas->columns; x++)
6751 {
cristy6710d842011-10-20 23:23:00 +00006752 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006753 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006754 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006755 }
6756 q+=scanline_pad;
6757 }
6758 break;
6759 }
6760 default:
6761 {
6762 register int
6763 k;
6764
6765 register unsigned int
6766 bytes_per_pixel;
6767
6768 unsigned char
cristybb503372010-05-27 20:51:26 +00006769 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006770
6771 /*
6772 Convert to 8 bit color-mapped X canvas.
6773 */
6774 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6775 for (y=0; y < (int) canvas->rows; y++)
6776 {
cristyc57f6942010-11-12 01:47:39 +00006777 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006778 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006779 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006780 break;
cristy3ed852e2009-09-05 21:47:34 +00006781 for (x=0; x < (int) canvas->columns; x++)
6782 {
cristy4c08aed2011-07-01 19:47:50 +00006783 pixel=pixels[(ssize_t)
6784 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006785 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6786 {
6787 channel[k]=(unsigned char) pixel;
6788 pixel>>=8;
6789 }
6790 for (k=0; k < (int) bytes_per_pixel; k++)
6791 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006792 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006793 }
6794 q+=scanline_pad;
6795 }
6796 break;
6797 }
6798 }
6799 else
6800 switch (ximage->bits_per_pixel)
6801 {
6802 case 2:
6803 {
6804 register unsigned int
6805 nibble;
6806
6807 /*
6808 Convert to 4 bit continuous-tone X canvas.
6809 */
6810 for (y=0; y < (int) canvas->rows; y++)
6811 {
cristyc57f6942010-11-12 01:47:39 +00006812 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006813 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006814 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006815 break;
6816 nibble=0;
6817 for (x=(int) canvas->columns-1; x >= 0; x--)
6818 {
cristy4c08aed2011-07-01 19:47:50 +00006819 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006820 pixel&=0xf;
6821 switch (nibble)
6822 {
6823 case 0:
6824 {
6825 *q=(unsigned char) (pixel << 6);
6826 nibble++;
6827 break;
6828 }
6829 case 1:
6830 {
6831 *q|=(unsigned char) (pixel << 4);
6832 nibble++;
6833 break;
6834 }
6835 case 2:
6836 {
6837 *q|=(unsigned char) (pixel << 2);
6838 nibble++;
6839 break;
6840 }
6841 case 3:
6842 {
6843 *q|=(unsigned char) pixel;
6844 q++;
6845 nibble=0;
6846 break;
6847 }
6848 }
cristyed231572011-07-14 02:18:59 +00006849 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006850 }
6851 q+=scanline_pad;
6852 }
6853 break;
6854 }
6855 case 4:
6856 {
6857 register unsigned int
6858 nibble;
6859
6860 /*
6861 Convert to 4 bit continuous-tone X canvas.
6862 */
6863 for (y=0; y < (int) canvas->rows; y++)
6864 {
cristyc57f6942010-11-12 01:47:39 +00006865 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006866 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006867 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006868 break;
6869 nibble=0;
6870 for (x=(int) canvas->columns-1; x >= 0; x--)
6871 {
cristy4c08aed2011-07-01 19:47:50 +00006872 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006873 pixel&=0xf;
6874 switch (nibble)
6875 {
6876 case 0:
6877 {
6878 *q=(unsigned char) (pixel << 4);
6879 nibble++;
6880 break;
6881 }
6882 case 1:
6883 {
6884 *q|=(unsigned char) pixel;
6885 q++;
6886 nibble=0;
6887 break;
6888 }
6889 }
cristyed231572011-07-14 02:18:59 +00006890 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006891 }
6892 q+=scanline_pad;
6893 }
6894 break;
6895 }
6896 case 6:
6897 case 8:
6898 {
6899 /*
6900 Convert to 8 bit continuous-tone X canvas.
6901 */
6902 if (resource_info->color_recovery &&
6903 resource_info->quantize_info->dither)
6904 {
cristy6710d842011-10-20 23:23:00 +00006905 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006906 break;
6907 }
6908 for (y=0; y < (int) canvas->rows; y++)
6909 {
cristyc57f6942010-11-12 01:47:39 +00006910 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006911 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006912 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006913 break;
6914 for (x=(int) canvas->columns-1; x >= 0; x--)
6915 {
cristy4c08aed2011-07-01 19:47:50 +00006916 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006917 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006918 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006919 }
6920 q+=scanline_pad;
6921 }
6922 break;
6923 }
6924 default:
6925 {
6926 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6927 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6928 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6929 (map_info->blue_mult == 1))
6930 {
6931 /*
6932 Convert to 32 bit continuous-tone X canvas.
6933 */
6934 for (y=0; y < (int) canvas->rows; y++)
6935 {
cristyc57f6942010-11-12 01:47:39 +00006936 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006937 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006938 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006939 break;
6940 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6941 (blue_gamma != 1.0))
6942 {
6943 /*
6944 Gamma correct canvas.
6945 */
6946 for (x=(int) canvas->columns-1; x >= 0; x--)
6947 {
6948 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006949 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006950 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006951 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006952 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006953 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006954 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006955 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006956 }
6957 continue;
6958 }
6959 for (x=(int) canvas->columns-1; x >= 0; x--)
6960 {
6961 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006962 *q++=ScaleQuantumToChar((Quantum)
6963 GetPixelRed(canvas,p));
6964 *q++=ScaleQuantumToChar((Quantum)
6965 GetPixelGreen(canvas,p));
6966 *q++=ScaleQuantumToChar((Quantum)
6967 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006968 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006969 }
6970 }
6971 }
6972 else
6973 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6974 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6975 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6976 (map_info->blue_mult == 65536L))
6977 {
6978 /*
6979 Convert to 32 bit continuous-tone X canvas.
6980 */
6981 for (y=0; y < (int) canvas->rows; y++)
6982 {
cristyc57f6942010-11-12 01:47:39 +00006983 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006984 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006985 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006986 break;
6987 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6988 (blue_gamma != 1.0))
6989 {
6990 /*
6991 Gamma correct canvas.
6992 */
6993 for (x=(int) canvas->columns-1; x >= 0; x--)
6994 {
6995 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006996 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006997 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006998 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006999 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00007000 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00007001 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00007002 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007003 }
7004 continue;
7005 }
7006 for (x=(int) canvas->columns-1; x >= 0; x--)
7007 {
7008 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007009 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007010 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007011 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007012 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007013 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007014 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00007015 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007016 }
7017 }
7018 }
7019 else
7020 {
7021 register int
7022 k;
7023
7024 register unsigned int
7025 bytes_per_pixel;
7026
7027 unsigned char
cristybb503372010-05-27 20:51:26 +00007028 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007029
7030 /*
7031 Convert to multi-byte continuous-tone X canvas.
7032 */
7033 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7034 for (y=0; y < (int) canvas->rows; y++)
7035 {
cristyc57f6942010-11-12 01:47:39 +00007036 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007037 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007038 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007039 break;
7040 for (x=(int) canvas->columns-1; x >= 0; x--)
7041 {
cristy4c08aed2011-07-01 19:47:50 +00007042 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007043 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7044 {
7045 channel[k]=(unsigned char) pixel;
7046 pixel>>=8;
7047 }
7048 for (k=0; k < (int) bytes_per_pixel; k++)
7049 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007050 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007051 }
7052 q+=scanline_pad;
7053 }
7054 }
7055 break;
7056 }
7057 }
7058 if (matte_image != (XImage *) NULL)
7059 {
7060 /*
7061 Initialize matte canvas.
7062 */
7063 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7064 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7065 q=(unsigned char *) matte_image->data;
7066 for (y=0; y < (int) canvas->rows; y++)
7067 {
cristyc57f6942010-11-12 01:47:39 +00007068 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007069 exception);
cristy4c08aed2011-07-01 19:47:50 +00007070 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007071 break;
7072 bit=0;
7073 byte=0;
7074 for (x=(int) canvas->columns-1; x >= 0; x--)
7075 {
7076 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007077 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007078 byte|=0x01;
7079 bit++;
7080 if (bit == 8)
7081 {
7082 *q++=byte;
7083 bit=0;
7084 byte=0;
7085 }
cristyed231572011-07-14 02:18:59 +00007086 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007087 }
7088 if (bit != 0)
7089 *q=byte << (8-bit);
7090 q+=scanline_pad;
7091 }
7092 }
cristyc57f6942010-11-12 01:47:39 +00007093 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007094 if (canvas != image)
7095 canvas=DestroyImage(canvas);
7096}
7097
7098/*
7099%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7100% %
7101% %
7102% %
7103% X M a k e M a g n i f y I m a g e %
7104% %
7105% %
7106% %
7107%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7108%
7109% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7110%
7111% The format of the XMakeMagnifyImage method is:
7112%
cristy6710d842011-10-20 23:23:00 +00007113% void XMakeMagnifyImage(Display *display,XWindows *windows,
7114% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007115%
7116% A description of each parameter follows:
7117%
7118% o display: Specifies a connection to an X server; returned from
7119% XOpenDisplay.
7120%
7121% o windows: Specifies a pointer to a XWindows structure.
7122%
cristy6710d842011-10-20 23:23:00 +00007123% o exception: return any errors or warnings in this structure.
7124%
cristy3ed852e2009-09-05 21:47:34 +00007125*/
cristy6710d842011-10-20 23:23:00 +00007126MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7127 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007128{
7129 char
7130 tuple[MaxTextExtent];
7131
7132 int
7133 y;
7134
cristy4c08aed2011-07-01 19:47:50 +00007135 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007136 pixel;
7137
7138 register int
7139 x;
7140
cristybb503372010-05-27 20:51:26 +00007141 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007142 i;
7143
7144 register unsigned char
7145 *p,
7146 *q;
7147
cristy9d314ff2011-03-09 01:30:28 +00007148 ssize_t
7149 n;
7150
cristy3ed852e2009-09-05 21:47:34 +00007151 static unsigned int
7152 previous_magnify = 0;
7153
7154 static XWindowInfo
7155 magnify_window;
7156
7157 unsigned int
7158 height,
7159 j,
7160 k,
7161 l,
7162 magnify,
7163 scanline_pad,
7164 width;
7165
7166 XImage
7167 *ximage;
7168
7169 /*
7170 Check boundary conditions.
7171 */
7172 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7173 assert(display != (Display *) NULL);
7174 assert(windows != (XWindows *) NULL);
7175 magnify=1;
cristybb503372010-05-27 20:51:26 +00007176 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007177 magnify<<=1;
7178 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7179 magnify<<=1;
7180 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7181 magnify<<=1;
7182 while (magnify > windows->magnify.width)
7183 magnify>>=1;
7184 while (magnify > windows->magnify.height)
7185 magnify>>=1;
7186 if (magnify != previous_magnify)
7187 {
7188 Status
7189 status;
7190
7191 XTextProperty
7192 window_name;
7193
7194 /*
7195 New magnify factor: update magnify window name.
7196 */
7197 i=0;
7198 while ((1 << i) <= (int) magnify)
7199 i++;
cristyb51dff52011-05-19 16:55:47 +00007200 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007201 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007202 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7203 if (status != False)
7204 {
7205 XSetWMName(display,windows->magnify.id,&window_name);
7206 XSetWMIconName(display,windows->magnify.id,&window_name);
7207 (void) XFree((void *) window_name.value);
7208 }
7209 }
7210 previous_magnify=magnify;
7211 ximage=windows->image.ximage;
7212 width=(unsigned int) windows->magnify.ximage->width;
7213 height=(unsigned int) windows->magnify.ximage->height;
7214 if ((windows->magnify.x < 0) ||
7215 (windows->magnify.x >= windows->image.ximage->width))
7216 windows->magnify.x=windows->image.ximage->width >> 1;
7217 x=windows->magnify.x-((width/magnify) >> 1);
7218 if (x < 0)
7219 x=0;
7220 else
7221 if (x > (int) (ximage->width-(width/magnify)))
7222 x=ximage->width-width/magnify;
7223 if ((windows->magnify.y < 0) ||
7224 (windows->magnify.y >= windows->image.ximage->height))
7225 windows->magnify.y=windows->image.ximage->height >> 1;
7226 y=windows->magnify.y-((height/magnify) >> 1);
7227 if (y < 0)
7228 y=0;
7229 else
7230 if (y > (int) (ximage->height-(height/magnify)))
7231 y=ximage->height-height/magnify;
7232 q=(unsigned char *) windows->magnify.ximage->data;
7233 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7234 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7235 if (ximage->bits_per_pixel < 8)
7236 {
7237 register unsigned char
7238 background,
7239 byte,
7240 foreground,
7241 p_bit,
7242 q_bit;
7243
7244 register unsigned int
7245 plane;
7246
7247 XPixelInfo
7248 *pixel_info;
7249
7250 pixel_info=windows->magnify.pixel_info;
7251 switch (ximage->bitmap_bit_order)
7252 {
7253 case LSBFirst:
7254 {
7255 /*
7256 Magnify little-endian bitmap.
7257 */
7258 background=0x00;
7259 foreground=0x80;
7260 if (ximage->format == XYBitmap)
7261 {
7262 background=(unsigned char)
7263 (XPixelIntensity(&pixel_info->foreground_color) <
7264 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7265 foreground=(unsigned char)
7266 (XPixelIntensity(&pixel_info->background_color) <
7267 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7268 if (windows->magnify.depth > 1)
7269 Swap(background,foreground);
7270 }
cristybb503372010-05-27 20:51:26 +00007271 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007272 {
7273 /*
7274 Propogate pixel magnify rows.
7275 */
7276 for (j=0; j < magnify; j++)
7277 {
7278 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7279 ((x*ximage->bits_per_pixel) >> 3);
7280 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7281 q_bit=0;
7282 byte=0;
7283 for (k=0; k < width; k+=magnify)
7284 {
7285 /*
7286 Propogate pixel magnify columns.
7287 */
7288 for (l=0; l < magnify; l++)
7289 {
7290 /*
7291 Propogate each bit plane.
7292 */
7293 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7294 {
7295 byte>>=1;
7296 if (*p & (0x01 << (p_bit+plane)))
7297 byte|=foreground;
7298 else
7299 byte|=background;
7300 q_bit++;
7301 if (q_bit == 8)
7302 {
7303 *q++=byte;
7304 q_bit=0;
7305 byte=0;
7306 }
7307 }
7308 }
7309 p_bit+=ximage->bits_per_pixel;
7310 if (p_bit == 8)
7311 {
7312 p++;
7313 p_bit=0;
7314 }
7315 if (q_bit != 0)
7316 *q=byte >> (8-q_bit);
7317 q+=scanline_pad;
7318 }
7319 }
7320 y++;
7321 }
7322 break;
7323 }
7324 case MSBFirst:
7325 default:
7326 {
7327 /*
7328 Magnify big-endian bitmap.
7329 */
7330 background=0x00;
7331 foreground=0x01;
7332 if (ximage->format == XYBitmap)
7333 {
7334 background=(unsigned char)
7335 (XPixelIntensity(&pixel_info->foreground_color) <
7336 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7337 foreground=(unsigned char)
7338 (XPixelIntensity(&pixel_info->background_color) <
7339 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7340 if (windows->magnify.depth > 1)
7341 Swap(background,foreground);
7342 }
cristybb503372010-05-27 20:51:26 +00007343 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007344 {
7345 /*
7346 Propogate pixel magnify rows.
7347 */
7348 for (j=0; j < magnify; j++)
7349 {
7350 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7351 ((x*ximage->bits_per_pixel) >> 3);
7352 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7353 q_bit=0;
7354 byte=0;
7355 for (k=0; k < width; k+=magnify)
7356 {
7357 /*
7358 Propogate pixel magnify columns.
7359 */
7360 for (l=0; l < magnify; l++)
7361 {
7362 /*
7363 Propogate each bit plane.
7364 */
7365 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7366 {
7367 byte<<=1;
7368 if (*p & (0x80 >> (p_bit+plane)))
7369 byte|=foreground;
7370 else
7371 byte|=background;
7372 q_bit++;
7373 if (q_bit == 8)
7374 {
7375 *q++=byte;
7376 q_bit=0;
7377 byte=0;
7378 }
7379 }
7380 }
7381 p_bit+=ximage->bits_per_pixel;
7382 if (p_bit == 8)
7383 {
7384 p++;
7385 p_bit=0;
7386 }
7387 if (q_bit != 0)
7388 *q=byte << (8-q_bit);
7389 q+=scanline_pad;
7390 }
7391 }
7392 y++;
7393 }
7394 break;
7395 }
7396 }
7397 }
7398 else
7399 switch (ximage->bits_per_pixel)
7400 {
7401 case 6:
7402 case 8:
7403 {
7404 /*
7405 Magnify 8 bit X image.
7406 */
cristybb503372010-05-27 20:51:26 +00007407 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007408 {
7409 /*
7410 Propogate pixel magnify rows.
7411 */
7412 for (j=0; j < magnify; j++)
7413 {
7414 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7415 ((x*ximage->bits_per_pixel) >> 3);
7416 for (k=0; k < width; k+=magnify)
7417 {
7418 /*
7419 Propogate pixel magnify columns.
7420 */
7421 for (l=0; l < magnify; l++)
7422 *q++=(*p);
7423 p++;
7424 }
7425 q+=scanline_pad;
7426 }
7427 y++;
7428 }
7429 break;
7430 }
7431 default:
7432 {
7433 register unsigned int
7434 bytes_per_pixel,
7435 m;
7436
7437 /*
7438 Magnify multi-byte X image.
7439 */
7440 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007441 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007442 {
7443 /*
7444 Propogate pixel magnify rows.
7445 */
7446 for (j=0; j < magnify; j++)
7447 {
7448 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7449 ((x*ximage->bits_per_pixel) >> 3);
7450 for (k=0; k < width; k+=magnify)
7451 {
7452 /*
7453 Propogate pixel magnify columns.
7454 */
7455 for (l=0; l < magnify; l++)
7456 for (m=0; m < bytes_per_pixel; m++)
7457 *q++=(*(p+m));
7458 p+=bytes_per_pixel;
7459 }
7460 q+=scanline_pad;
7461 }
7462 y++;
7463 }
7464 break;
7465 }
7466 }
7467 /*
7468 Copy X image to magnify pixmap.
7469 */
7470 x=windows->magnify.x-((width/magnify) >> 1);
7471 if (x < 0)
7472 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7473 else
7474 if (x > (int) (ximage->width-(width/magnify)))
7475 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7476 else
7477 x=0;
7478 y=windows->magnify.y-((height/magnify) >> 1);
7479 if (y < 0)
7480 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7481 else
7482 if (y > (int) (ximage->height-(height/magnify)))
7483 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7484 else
7485 y=0;
7486 if ((x != 0) || (y != 0))
7487 (void) XFillRectangle(display,windows->magnify.pixmap,
7488 windows->magnify.annotate_context,0,0,width,height);
7489 (void) XPutImage(display,windows->magnify.pixmap,
7490 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7491 height-y);
7492 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7493 (magnify <= (height >> 1))))
7494 {
7495 RectangleInfo
7496 highlight_info;
7497
7498 /*
7499 Highlight center pixel.
7500 */
cristybb503372010-05-27 20:51:26 +00007501 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7502 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007503 highlight_info.width=magnify;
7504 highlight_info.height=magnify;
7505 (void) XDrawRectangle(display,windows->magnify.pixmap,
7506 windows->magnify.highlight_context,(int) highlight_info.x,
7507 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7508 (unsigned int) highlight_info.height-1);
7509 if (magnify > 2)
7510 (void) XDrawRectangle(display,windows->magnify.pixmap,
7511 windows->magnify.annotate_context,(int) highlight_info.x+1,
7512 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7513 (unsigned int) highlight_info.height-3);
7514 }
7515 /*
7516 Show center pixel color.
7517 */
cristy3aa93752011-12-18 15:54:24 +00007518 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007519 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007520 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007521 windows->magnify.x,windows->magnify.y);
7522 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007523 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007524 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007525 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007526 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007527 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007528 if (pixel.colorspace == CMYKColorspace)
7529 {
7530 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007531 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007532 }
7533 if (pixel.matte != MagickFalse)
7534 {
7535 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007536 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007537 }
7538 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7539 height=(unsigned int) windows->magnify.font_info->ascent+
7540 windows->magnify.font_info->descent;
7541 x=windows->magnify.font_info->max_bounds.width >> 1;
7542 y=windows->magnify.font_info->ascent+(height >> 2);
7543 (void) XDrawImageString(display,windows->magnify.pixmap,
7544 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7545 GetColorTuple(&pixel,MagickTrue,tuple);
7546 y+=height;
7547 (void) XDrawImageString(display,windows->magnify.pixmap,
7548 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007549 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007550 exception);
cristy3ed852e2009-09-05 21:47:34 +00007551 y+=height;
7552 (void) XDrawImageString(display,windows->magnify.pixmap,
7553 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7554 /*
7555 Refresh magnify window.
7556 */
7557 magnify_window=windows->magnify;
7558 magnify_window.x=0;
7559 magnify_window.y=0;
7560 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7561}
7562
7563/*
7564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7565% %
7566% %
7567% %
7568% X M a k e P i x m a p %
7569% %
7570% %
7571% %
7572%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7573%
7574% XMakePixmap() creates an X11 pixmap.
7575%
7576% The format of the XMakePixmap method is:
7577%
7578% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7579% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7580% XPixelInfo *pixel)
7581%
7582% A description of each parameter follows:
7583%
7584% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7585%
7586% o display: Specifies a connection to an X server; returned from
7587% XOpenDisplay.
7588%
7589% o window: Specifies a pointer to a XWindowInfo structure.
7590%
cristy3ed852e2009-09-05 21:47:34 +00007591*/
7592static MagickBooleanType XMakePixmap(Display *display,
7593 const XResourceInfo *resource_info,XWindowInfo *window)
7594{
7595 unsigned int
7596 height,
7597 width;
7598
7599 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7600 assert(display != (Display *) NULL);
7601 assert(resource_info != (XResourceInfo *) NULL);
7602 assert(window != (XWindowInfo *) NULL);
7603 if (window->pixmap != (Pixmap) NULL)
7604 {
7605 /*
7606 Destroy previous X pixmap.
7607 */
7608 (void) XFreePixmap(display,window->pixmap);
7609 window->pixmap=(Pixmap) NULL;
7610 }
7611 if (window->use_pixmap == MagickFalse)
7612 return(MagickFalse);
7613 if (window->ximage == (XImage *) NULL)
7614 return(MagickFalse);
7615 /*
7616 Display busy cursor.
7617 */
7618 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7619 (void) XFlush(display);
7620 /*
7621 Create pixmap.
7622 */
7623 width=(unsigned int) window->ximage->width;
7624 height=(unsigned int) window->ximage->height;
7625 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7626 if (window->pixmap == (Pixmap) NULL)
7627 {
7628 /*
7629 Unable to allocate pixmap.
7630 */
7631 (void) XCheckDefineCursor(display,window->id,window->cursor);
7632 return(MagickFalse);
7633 }
7634 /*
7635 Copy X image to pixmap.
7636 */
7637#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7638 if (window->shared_memory)
7639 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7640 window->ximage,0,0,0,0,width,height,MagickTrue);
7641#endif
7642 if (window->shared_memory == MagickFalse)
7643 (void) XPutImage(display,window->pixmap,window->annotate_context,
7644 window->ximage,0,0,0,0,width,height);
7645 if (IsEventLogging())
7646 {
7647 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7648 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7649 width,height);
7650 }
7651 /*
7652 Restore cursor.
7653 */
7654 (void) XCheckDefineCursor(display,window->id,window->cursor);
7655 return(MagickTrue);
7656}
7657
7658/*
7659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7660% %
7661% %
7662% %
7663% X M a k e S t a n d a r d C o l o r m a p %
7664% %
7665% %
7666% %
7667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7668%
7669% XMakeStandardColormap() creates an X11 Standard Colormap.
7670%
7671% The format of the XMakeStandardColormap method is:
7672%
cristy6710d842011-10-20 23:23:00 +00007673% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7674% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7675% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007676%
7677% A description of each parameter follows:
7678%
7679% o display: Specifies a connection to an X server; returned from
7680% XOpenDisplay.
7681%
7682% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7683% returned from XGetVisualInfo.
7684%
7685% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7686%
7687% o image: the image.
7688%
7689% o map_info: If a Standard Colormap type is specified, this structure is
7690% initialized with info from the Standard Colormap.
7691%
7692% o pixel: Specifies a pointer to a XPixelInfo structure.
7693%
cristy6710d842011-10-20 23:23:00 +00007694% o exception: return any errors or warnings in this structure.
7695%
cristy3ed852e2009-09-05 21:47:34 +00007696*/
7697
7698#if defined(__cplusplus) || defined(c_plusplus)
7699extern "C" {
7700#endif
7701
7702static inline MagickRealType DiversityPixelIntensity(
7703 const DiversityPacket *pixel)
7704{
7705 MagickRealType
7706 intensity;
7707
7708 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7709 return(intensity);
7710}
7711
7712static int IntensityCompare(const void *x,const void *y)
7713{
7714 DiversityPacket
7715 *color_1,
7716 *color_2;
7717
7718 int
7719 diversity;
7720
7721 color_1=(DiversityPacket *) x;
7722 color_2=(DiversityPacket *) y;
7723 diversity=(int) (DiversityPixelIntensity(color_2)-
7724 DiversityPixelIntensity(color_1));
7725 return(diversity);
7726}
7727
7728static int PopularityCompare(const void *x,const void *y)
7729{
7730 DiversityPacket
7731 *color_1,
7732 *color_2;
7733
7734 color_1=(DiversityPacket *) x;
7735 color_2=(DiversityPacket *) y;
7736 return((int) color_2->count-(int) color_1->count);
7737}
7738
7739#if defined(__cplusplus) || defined(c_plusplus)
7740}
7741#endif
7742
cristybb503372010-05-27 20:51:26 +00007743static inline Quantum ScaleXToQuantum(const size_t x,
7744 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007745{
7746 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7747}
7748
cristybcbda3f2011-09-03 13:01:22 +00007749MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007750 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007751 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007752{
7753 Colormap
7754 colormap;
7755
cristybb503372010-05-27 20:51:26 +00007756 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007757 i;
7758
7759 Status
7760 status;
7761
cristybb503372010-05-27 20:51:26 +00007762 size_t
cristy3ed852e2009-09-05 21:47:34 +00007763 number_colors,
7764 retain_colors;
7765
7766 unsigned short
7767 gray_value;
7768
7769 XColor
7770 color,
7771 *colors,
7772 *p;
7773
7774 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7775 assert(display != (Display *) NULL);
7776 assert(visual_info != (XVisualInfo *) NULL);
7777 assert(map_info != (XStandardColormap *) NULL);
7778 assert(resource_info != (XResourceInfo *) NULL);
7779 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007780 if (resource_info->map_type != (char *) NULL)
7781 {
7782 /*
7783 Standard Colormap is already defined (i.e. xstdcmap).
7784 */
cristy4c08aed2011-07-01 19:47:50 +00007785 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007786 pixel);
7787 number_colors=(unsigned int) (map_info->base_pixel+
7788 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7789 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7790 if ((image->matte == MagickFalse) &&
7791 (resource_info->color_recovery == MagickFalse) &&
7792 resource_info->quantize_info->dither &&
7793 (number_colors < MaxColormapSize))
7794 {
7795 Image
7796 *affinity_image;
7797
cristy4c08aed2011-07-01 19:47:50 +00007798 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007799 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007800
7801 /*
7802 Improve image appearance with error diffusion.
7803 */
cristy6710d842011-10-20 23:23:00 +00007804 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007805 if (affinity_image == (Image *) NULL)
7806 ThrowXWindowFatalException(ResourceLimitFatalError,
7807 "UnableToDitherImage",image->filename);
7808 affinity_image->columns=number_colors;
7809 affinity_image->rows=1;
7810 /*
7811 Initialize colormap image.
7812 */
7813 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7814 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007815 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007816 {
cristybb503372010-05-27 20:51:26 +00007817 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007818 {
cristy4c08aed2011-07-01 19:47:50 +00007819 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007820 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007821 SetPixelRed(affinity_image,
7822 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7823 map_info->red_max),q);
7824 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007825 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007826 SetPixelGreen(affinity_image,
7827 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7828 (map_info->green_max+1)),map_info->green_max),q);
7829 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007830 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007831 SetPixelBlue(affinity_image,
7832 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7833 map_info->blue_max),q);
7834 SetPixelAlpha(affinity_image,
7835 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007836 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007837 }
7838 (void) SyncAuthenticPixels(affinity_image,exception);
7839 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007840 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007841 }
cristy4c08aed2011-07-01 19:47:50 +00007842 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007843 pixel);
cristy574cc262011-08-05 01:23:58 +00007844 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007845 affinity_image=DestroyImage(affinity_image);
7846 }
7847 if (IsEventLogging())
7848 {
7849 (void) LogMagickEvent(X11Event,GetMagickModule(),
7850 "Standard Colormap:");
7851 (void) LogMagickEvent(X11Event,GetMagickModule(),
7852 " colormap id: 0x%lx",map_info->colormap);
7853 (void) LogMagickEvent(X11Event,GetMagickModule(),
7854 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7855 map_info->green_max,map_info->blue_max);
7856 (void) LogMagickEvent(X11Event,GetMagickModule(),
7857 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7858 map_info->green_mult,map_info->blue_mult);
7859 }
7860 return;
7861 }
7862 if ((visual_info->klass != DirectColor) &&
7863 (visual_info->klass != TrueColor))
7864 if ((image->storage_class == DirectClass) ||
7865 ((int) image->colors > visual_info->colormap_size))
7866 {
7867 QuantizeInfo
7868 quantize_info;
7869
7870 /*
7871 Image has more colors than the visual supports.
7872 */
7873 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007874 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007875 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007876 }
7877 /*
7878 Free previous and create new colormap.
7879 */
7880 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7881 colormap=XDefaultColormap(display,visual_info->screen);
7882 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7883 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7884 visual_info->visual,visual_info->klass == DirectColor ?
7885 AllocAll : AllocNone);
7886 if (colormap == (Colormap) NULL)
7887 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7888 image->filename);
7889 /*
7890 Initialize the map and pixel info structures.
7891 */
7892 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007893 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007894 /*
7895 Allocating colors in server colormap is based on visual class.
7896 */
7897 switch (visual_info->klass)
7898 {
7899 case StaticGray:
7900 case StaticColor:
7901 {
7902 /*
7903 Define Standard Colormap for StaticGray or StaticColor visual.
7904 */
7905 number_colors=image->colors;
7906 colors=(XColor *) AcquireQuantumMemory((size_t)
7907 visual_info->colormap_size,sizeof(*colors));
7908 if (colors == (XColor *) NULL)
7909 ThrowXWindowFatalException(ResourceLimitFatalError,
7910 "UnableToCreateColormap",image->filename);
7911 p=colors;
7912 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007913 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007914 {
7915 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7916 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7917 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7918 if (visual_info->klass != StaticColor)
7919 {
7920 gray_value=(unsigned short) XPixelIntensity(&color);
7921 color.red=gray_value;
7922 color.green=gray_value;
7923 color.blue=gray_value;
7924 }
7925 status=XAllocColor(display,colormap,&color);
7926 if (status == False)
7927 {
7928 colormap=XCopyColormapAndFree(display,colormap);
7929 (void) XAllocColor(display,colormap,&color);
7930 }
7931 pixel->pixels[i]=color.pixel;
7932 *p++=color;
7933 }
7934 break;
7935 }
7936 case GrayScale:
7937 case PseudoColor:
7938 {
7939 unsigned int
7940 colormap_type;
7941
7942 /*
7943 Define Standard Colormap for GrayScale or PseudoColor visual.
7944 */
7945 number_colors=image->colors;
7946 colors=(XColor *) AcquireQuantumMemory((size_t)
7947 visual_info->colormap_size,sizeof(*colors));
7948 if (colors == (XColor *) NULL)
7949 ThrowXWindowFatalException(ResourceLimitFatalError,
7950 "UnableToCreateColormap",image->filename);
7951 /*
7952 Preallocate our GUI colors.
7953 */
7954 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7955 (void) XAllocColor(display,colormap,&pixel->background_color);
7956 (void) XAllocColor(display,colormap,&pixel->border_color);
7957 (void) XAllocColor(display,colormap,&pixel->matte_color);
7958 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7959 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7960 (void) XAllocColor(display,colormap,&pixel->depth_color);
7961 (void) XAllocColor(display,colormap,&pixel->trough_color);
7962 for (i=0; i < MaxNumberPens; i++)
7963 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7964 /*
7965 Determine if image colors will "fit" into X server colormap.
7966 */
7967 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007968 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007969 NULL,0,pixel->pixels,(unsigned int) image->colors);
7970 if (status != False)
7971 colormap_type=PrivateColormap;
7972 if (colormap_type == SharedColormap)
7973 {
cristyc57f6942010-11-12 01:47:39 +00007974 CacheView
7975 *image_view;
7976
cristy3ed852e2009-09-05 21:47:34 +00007977 DiversityPacket
7978 *diversity;
7979
7980 int
7981 y;
7982
7983 register int
7984 x;
7985
7986 unsigned short
7987 index;
7988
7989 XColor
7990 *server_colors;
7991
7992 /*
7993 Define Standard colormap for shared GrayScale or PseudoColor visual.
7994 */
7995 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7996 sizeof(*diversity));
7997 if (diversity == (DiversityPacket *) NULL)
7998 ThrowXWindowFatalException(ResourceLimitFatalError,
7999 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00008000 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008001 {
cristye42f6582012-02-11 17:59:50 +00008002 diversity[i].red=ClampToQuantum(image->colormap[i].red);
8003 diversity[i].green=ClampToQuantum(image->colormap[i].green);
8004 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00008005 diversity[i].index=(unsigned short) i;
8006 diversity[i].count=0;
8007 }
cristydb070952012-04-20 14:33:00 +00008008 image_view=AcquireAuthenticCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00008009 for (y=0; y < (int) image->rows; y++)
8010 {
cristyc57f6942010-11-12 01:47:39 +00008011 register int
cristy3ed852e2009-09-05 21:47:34 +00008012 x;
8013
cristy4c08aed2011-07-01 19:47:50 +00008014 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00008015 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00008016
cristyc57f6942010-11-12 01:47:39 +00008017 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8018 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008019 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008020 break;
cristyc57f6942010-11-12 01:47:39 +00008021 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008022 {
8023 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008024 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008025 }
cristy3ed852e2009-09-05 21:47:34 +00008026 }
cristyc57f6942010-11-12 01:47:39 +00008027 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008028 /*
8029 Sort colors by decreasing intensity.
8030 */
8031 qsort((void *) diversity,image->colors,sizeof(*diversity),
8032 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008033 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008034 {
8035 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008036 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008037 }
8038 diversity[image->colors-1].count<<=4;
8039 qsort((void *) diversity,image->colors,sizeof(*diversity),
8040 PopularityCompare);
8041 /*
8042 Allocate colors.
8043 */
8044 p=colors;
8045 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008046 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008047 {
8048 index=diversity[i].index;
8049 color.red=
8050 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8051 color.green=
8052 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8053 color.blue=
8054 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8055 if (visual_info->klass != PseudoColor)
8056 {
8057 gray_value=(unsigned short) XPixelIntensity(&color);
8058 color.red=gray_value;
8059 color.green=gray_value;
8060 color.blue=gray_value;
8061 }
8062 status=XAllocColor(display,colormap,&color);
8063 if (status == False)
8064 break;
8065 pixel->pixels[index]=color.pixel;
8066 *p++=color;
8067 }
8068 /*
8069 Read X server colormap.
8070 */
8071 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8072 visual_info->colormap_size,sizeof(*server_colors));
8073 if (server_colors == (XColor *) NULL)
8074 ThrowXWindowFatalException(ResourceLimitFatalError,
8075 "UnableToCreateColormap",image->filename);
8076 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008077 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008078 (void) XQueryColors(display,colormap,server_colors,
8079 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8080 /*
8081 Select remaining colors from X server colormap.
8082 */
cristybb503372010-05-27 20:51:26 +00008083 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008084 {
8085 index=diversity[i].index;
8086 color.red=
8087 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8088 color.green=
8089 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8090 color.blue=
8091 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8092 if (visual_info->klass != PseudoColor)
8093 {
8094 gray_value=(unsigned short) XPixelIntensity(&color);
8095 color.red=gray_value;
8096 color.green=gray_value;
8097 color.blue=gray_value;
8098 }
8099 XBestPixel(display,colormap,server_colors,(unsigned int)
8100 visual_info->colormap_size,&color);
8101 pixel->pixels[index]=color.pixel;
8102 *p++=color;
8103 }
8104 if ((int) image->colors < visual_info->colormap_size)
8105 {
8106 /*
8107 Fill up colors array-- more choices for pen colors.
8108 */
8109 retain_colors=MagickMin((unsigned int)
8110 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008111 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008112 *p++=server_colors[i];
8113 number_colors+=retain_colors;
8114 }
8115 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8116 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8117 break;
8118 }
8119 /*
8120 Define Standard colormap for private GrayScale or PseudoColor visual.
8121 */
8122 if (status == False)
8123 {
8124 /*
8125 Not enough colormap entries in the colormap-- Create a new colormap.
8126 */
8127 colormap=XCreateColormap(display,
8128 XRootWindow(display,visual_info->screen),visual_info->visual,
8129 AllocNone);
8130 if (colormap == (Colormap) NULL)
8131 ThrowXWindowFatalException(ResourceLimitFatalError,
8132 "UnableToCreateColormap",image->filename);
8133 map_info->colormap=colormap;
8134 if ((int) image->colors < visual_info->colormap_size)
8135 {
8136 /*
8137 Retain colors from the default colormap to help lessens the
8138 effects of colormap flashing.
8139 */
8140 retain_colors=MagickMin((unsigned int)
8141 (visual_info->colormap_size-image->colors),256);
8142 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008143 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008144 {
cristyc57f6942010-11-12 01:47:39 +00008145 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008146 p++;
8147 }
8148 (void) XQueryColors(display,
8149 XDefaultColormap(display,visual_info->screen),
8150 colors+image->colors,(int) retain_colors);
8151 /*
8152 Transfer colors from default to private colormap.
8153 */
8154 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008155 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008156 retain_colors);
8157 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008158 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008159 {
8160 p->pixel=pixel->pixels[i];
8161 p++;
8162 }
8163 (void) XStoreColors(display,colormap,colors+image->colors,
8164 (int) retain_colors);
8165 number_colors+=retain_colors;
8166 }
8167 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008168 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008169 image->colors);
8170 }
8171 /*
8172 Store the image colormap.
8173 */
8174 p=colors;
8175 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008176 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008177 {
8178 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8179 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8180 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8181 if (visual_info->klass != PseudoColor)
8182 {
8183 gray_value=(unsigned short) XPixelIntensity(&color);
8184 color.red=gray_value;
8185 color.green=gray_value;
8186 color.blue=gray_value;
8187 }
8188 color.pixel=pixel->pixels[i];
8189 *p++=color;
8190 }
8191 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8192 break;
8193 }
8194 case TrueColor:
8195 case DirectColor:
8196 default:
8197 {
8198 MagickBooleanType
8199 linear_colormap;
8200
8201 /*
8202 Define Standard Colormap for TrueColor or DirectColor visual.
8203 */
8204 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8205 (map_info->green_max*map_info->green_mult)+
8206 (map_info->blue_max*map_info->blue_mult)+1);
8207 linear_colormap=(number_colors > 4096) ||
8208 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8209 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8210 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8211 MagickTrue : MagickFalse;
8212 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008213 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008214 /*
8215 Allocate color array.
8216 */
8217 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8218 if (colors == (XColor *) NULL)
8219 ThrowXWindowFatalException(ResourceLimitFatalError,
8220 "UnableToCreateColormap",image->filename);
8221 /*
8222 Initialize linear color ramp.
8223 */
8224 p=colors;
8225 color.flags=(char) (DoRed | DoGreen | DoBlue);
8226 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008227 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008228 {
8229 color.blue=(unsigned short) 0;
8230 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008231 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008232 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8233 color.green=color.blue;
8234 color.red=color.blue;
8235 color.pixel=XStandardPixel(map_info,&color);
8236 *p++=color;
8237 }
8238 else
cristybb503372010-05-27 20:51:26 +00008239 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008240 {
8241 color.red=(unsigned short) 0;
8242 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008243 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008244 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8245 color.green=(unsigned int) 0;
8246 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008247 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008248 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8249 map_info->green_max));
8250 color.blue=(unsigned short) 0;
8251 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008252 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008253 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8254 color.pixel=XStandardPixel(map_info,&color);
8255 *p++=color;
8256 }
8257 if ((visual_info->klass == DirectColor) &&
8258 (colormap != XDefaultColormap(display,visual_info->screen)))
8259 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8260 else
cristybb503372010-05-27 20:51:26 +00008261 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008262 (void) XAllocColor(display,colormap,&colors[i]);
8263 break;
8264 }
8265 }
8266 if ((visual_info->klass != DirectColor) &&
8267 (visual_info->klass != TrueColor))
8268 {
8269 /*
8270 Set foreground, background, border, etc. pixels.
8271 */
8272 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8273 &pixel->foreground_color);
8274 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8275 &pixel->background_color);
8276 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8277 {
8278 /*
8279 Foreground and background colors must differ.
8280 */
8281 pixel->background_color.red=(~pixel->foreground_color.red);
8282 pixel->background_color.green=
8283 (~pixel->foreground_color.green);
8284 pixel->background_color.blue=
8285 (~pixel->foreground_color.blue);
8286 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8287 &pixel->background_color);
8288 }
8289 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8290 &pixel->border_color);
8291 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8292 &pixel->matte_color);
8293 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8294 &pixel->highlight_color);
8295 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8296 &pixel->shadow_color);
8297 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8298 &pixel->depth_color);
8299 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8300 &pixel->trough_color);
8301 for (i=0; i < MaxNumberPens; i++)
8302 {
8303 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8304 &pixel->pen_colors[i]);
8305 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8306 }
cristyc57f6942010-11-12 01:47:39 +00008307 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008308 }
8309 colors=(XColor *) RelinquishMagickMemory(colors);
8310 if (IsEventLogging())
8311 {
8312 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8313 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8314 map_info->colormap);
8315 (void) LogMagickEvent(X11Event,GetMagickModule(),
8316 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8317 map_info->green_max,map_info->blue_max);
8318 (void) LogMagickEvent(X11Event,GetMagickModule(),
8319 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8320 map_info->green_mult,map_info->blue_mult);
8321 }
8322}
8323
8324/*
8325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8326% %
8327% %
8328% %
8329% X M a k e W i n d o w %
8330% %
8331% %
8332% %
8333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8334%
8335% XMakeWindow() creates an X11 window.
8336%
8337% The format of the XMakeWindow method is:
8338%
8339% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8340% XClassHint *class_hint,XWMHints *manager_hints,
8341% XWindowInfo *window_info)
8342%
8343% A description of each parameter follows:
8344%
8345% o display: Specifies a connection to an X server; returned from
8346% XOpenDisplay.
8347%
8348% o parent: Specifies the parent window_info.
8349%
8350% o argv: Specifies the application's argument list.
8351%
8352% o argc: Specifies the number of arguments.
8353%
8354% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8355%
8356% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8357%
8358% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8359%
8360*/
cristybcbda3f2011-09-03 13:01:22 +00008361MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008362 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8363 XWindowInfo *window_info)
8364{
8365#define MinWindowSize 64
8366
8367 Atom
8368 atom_list[2];
8369
8370 int
8371 gravity;
8372
8373 static XTextProperty
8374 icon_name,
8375 window_name;
8376
8377 Status
8378 status;
8379
8380 XSizeHints
8381 *size_hints;
8382
8383 /*
8384 Set window info hints.
8385 */
8386 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8387 assert(display != (Display *) NULL);
8388 assert(window_info != (XWindowInfo *) NULL);
8389 size_hints=XAllocSizeHints();
8390 if (size_hints == (XSizeHints *) NULL)
8391 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008392 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008393 size_hints->x=window_info->x;
8394 size_hints->y=window_info->y;
8395 size_hints->width=(int) window_info->width;
8396 size_hints->height=(int) window_info->height;
8397 if (window_info->immutable != MagickFalse)
8398 {
8399 /*
8400 Window size cannot be changed.
8401 */
8402 size_hints->min_width=size_hints->width;
8403 size_hints->min_height=size_hints->height;
8404 size_hints->max_width=size_hints->width;
8405 size_hints->max_height=size_hints->height;
8406 size_hints->flags|=PMinSize;
8407 size_hints->flags|=PMaxSize;
8408 }
8409 else
8410 {
8411 /*
8412 Window size can be changed.
8413 */
8414 size_hints->min_width=(int) window_info->min_width;
8415 size_hints->min_height=(int) window_info->min_height;
8416 size_hints->flags|=PResizeInc;
8417 size_hints->width_inc=(int) window_info->width_inc;
8418 size_hints->height_inc=(int) window_info->height_inc;
8419#if !defined(PRE_R4_ICCCM)
8420 size_hints->flags|=PBaseSize;
8421 size_hints->base_width=size_hints->width_inc;
8422 size_hints->base_height=size_hints->height_inc;
8423#endif
8424 }
8425 gravity=NorthWestGravity;
8426 if (window_info->geometry != (char *) NULL)
8427 {
8428 char
8429 default_geometry[MaxTextExtent],
8430 geometry[MaxTextExtent];
8431
8432 int
8433 flags;
8434
8435 register char
8436 *p;
8437
8438 /*
8439 User specified geometry.
8440 */
cristyb51dff52011-05-19 16:55:47 +00008441 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008442 size_hints->width,size_hints->height);
8443 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8444 p=geometry;
8445 while (strlen(p) != 0)
8446 {
8447 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8448 p++;
8449 else
8450 (void) CopyMagickString(p,p+1,MaxTextExtent);
8451 }
8452 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8453 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8454 &size_hints->width,&size_hints->height,&gravity);
8455 if ((flags & WidthValue) && (flags & HeightValue))
8456 size_hints->flags|=USSize;
8457 if ((flags & XValue) && (flags & YValue))
8458 {
8459 size_hints->flags|=USPosition;
8460 window_info->x=size_hints->x;
8461 window_info->y=size_hints->y;
8462 }
8463 }
8464#if !defined(PRE_R4_ICCCM)
8465 size_hints->win_gravity=gravity;
8466 size_hints->flags|=PWinGravity;
8467#endif
8468 if (window_info->id == (Window) NULL)
8469 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8470 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8471 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008472 window_info->visual,(unsigned long) window_info->mask,
8473 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008474 else
8475 {
8476 MagickStatusType
8477 mask;
8478
8479 XEvent
8480 sans_event;
8481
8482 XWindowChanges
8483 window_changes;
8484
8485 /*
8486 Window already exists; change relevant attributes.
8487 */
cristyc57f6942010-11-12 01:47:39 +00008488 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8489 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008490 mask=ConfigureNotify;
8491 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8492 window_changes.x=window_info->x;
8493 window_changes.y=window_info->y;
8494 window_changes.width=(int) window_info->width;
8495 window_changes.height=(int) window_info->height;
8496 mask=(MagickStatusType) (CWWidth | CWHeight);
8497 if (window_info->flags & USPosition)
8498 mask|=CWX | CWY;
8499 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8500 mask,&window_changes);
8501 }
8502 if (window_info->id == (Window) NULL)
8503 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8504 window_info->name);
8505 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8506 if (status == False)
8507 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8508 window_info->name);
8509 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8510 if (status == False)
8511 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8512 window_info->icon_name);
8513 if (window_info->icon_geometry != (char *) NULL)
8514 {
8515 int
8516 flags,
8517 height,
8518 width;
8519
8520 /*
8521 User specified icon geometry.
8522 */
8523 size_hints->flags|=USPosition;
8524 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8525 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8526 &manager_hints->icon_y,&width,&height,&gravity);
8527 if ((flags & XValue) && (flags & YValue))
8528 manager_hints->flags|=IconPositionHint;
8529 }
8530 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8531 size_hints,manager_hints,class_hint);
8532 if (window_name.value != (void *) NULL)
8533 {
8534 (void) XFree((void *) window_name.value);
8535 window_name.value=(unsigned char *) NULL;
8536 window_name.nitems=0;
8537 }
8538 if (icon_name.value != (void *) NULL)
8539 {
8540 (void) XFree((void *) icon_name.value);
8541 icon_name.value=(unsigned char *) NULL;
8542 icon_name.nitems=0;
8543 }
8544 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8545 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8546 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8547 (void) XFree((void *) size_hints);
8548 if (window_info->shape != MagickFalse)
8549 {
8550#if defined(MAGICKCORE_HAVE_SHAPE)
8551 int
8552 error_base,
8553 event_base;
8554
8555 /*
8556 Can we apply a non-rectangular shaping mask?
8557 */
8558 error_base=0;
8559 event_base=0;
8560 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8561 window_info->shape=MagickFalse;
8562#else
8563 window_info->shape=MagickFalse;
8564#endif
8565 }
8566 if (window_info->shared_memory)
8567 {
8568#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8569 /*
8570 Can we use shared memory with this window?
8571 */
8572 if (XShmQueryExtension(display) == 0)
8573 window_info->shared_memory=MagickFalse;
8574#else
8575 window_info->shared_memory=MagickFalse;
8576#endif
8577 }
8578 window_info->image=NewImageList();
8579 window_info->destroy=MagickFalse;
8580}
8581
8582/*
8583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8584% %
8585% %
8586% %
8587% X M a g i c k P r o g r e s s M o n i t o r %
8588% %
8589% %
8590% %
8591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8592%
8593% XMagickProgressMonitor() displays the progress a task is making in
8594% completing a task.
8595%
8596% The format of the XMagickProgressMonitor method is:
8597%
8598% void XMagickProgressMonitor(const char *task,
8599% const MagickOffsetType quantum,const MagickSizeType span,
8600% void *client_data)
8601%
8602% A description of each parameter follows:
8603%
8604% o task: Identifies the task in progress.
8605%
8606% o quantum: Specifies the quantum position within the span which represents
8607% how much progress has been made in completing a task.
8608%
8609% o span: Specifies the span relative to completing a task.
8610%
8611% o client_data: Pointer to any client data.
8612%
8613*/
8614
8615static const char *GetLocaleMonitorMessage(const char *text)
8616{
8617 char
8618 message[MaxTextExtent],
8619 tag[MaxTextExtent];
8620
8621 const char
8622 *locale_message;
8623
8624 register char
8625 *p;
8626
8627 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8628 p=strrchr(tag,'/');
8629 if (p != (char *) NULL)
8630 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008631 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008632 locale_message=GetLocaleMessage(message);
8633 if (locale_message == message)
8634 return(text);
8635 return(locale_message);
8636}
8637
cristybcbda3f2011-09-03 13:01:22 +00008638MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008639 const MagickOffsetType quantum,const MagickSizeType span,
8640 void *magick_unused(client_data))
8641{
8642 XWindows
8643 *windows;
8644
8645 windows=XSetWindows((XWindows *) ~0);
8646 if (windows == (XWindows *) NULL)
8647 return(MagickTrue);
8648 if (windows->info.mapped != MagickFalse)
8649 XProgressMonitorWidget(windows->display,windows,
8650 GetLocaleMonitorMessage(tag),quantum,span);
8651 return(MagickTrue);
8652}
8653
8654/*
8655%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8656% %
8657% %
8658% %
8659% X Q u e r y C o l o r D a t a b a s e %
8660% %
8661% %
8662% %
8663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8664%
cristy9950d572011-10-01 18:22:35 +00008665% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008666% string.
8667%
8668% The format of the XQueryColorDatabase method is:
8669%
cristy9950d572011-10-01 18:22:35 +00008670% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008671%
8672% A description of each parameter follows:
8673%
8674% o target: Specifies the color to lookup in the X color database.
8675%
cristy101ab702011-10-13 13:06:32 +00008676% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008677% color is returned as this value.
8678%
8679*/
cristy9950d572011-10-01 18:22:35 +00008680MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008681 XColor *color)
8682{
8683 Colormap
8684 colormap;
8685
8686 static Display
8687 *display = (Display *) NULL;
8688
8689 Status
8690 status;
8691
8692 XColor
8693 xcolor;
8694
8695 /*
8696 Initialize color return value.
8697 */
8698 assert(color != (XColor *) NULL);
8699 color->red=0;
8700 color->green=0;
8701 color->blue=0;
8702 color->flags=(char) (DoRed | DoGreen | DoBlue);
8703 if ((target == (char *) NULL) || (*target == '\0'))
8704 target="#ffffffffffff";
8705 /*
8706 Let the X server define the color for us.
8707 */
8708 if (display == (Display *) NULL)
8709 display=XOpenDisplay((char *) NULL);
8710 if (display == (Display *) NULL)
8711 {
8712 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8713 return(MagickFalse);
8714 }
8715 colormap=XDefaultColormap(display,XDefaultScreen(display));
8716 status=XParseColor(display,colormap,(char *) target,&xcolor);
8717 if (status == False)
8718 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8719 else
8720 {
8721 color->red=xcolor.red;
8722 color->green=xcolor.green;
8723 color->blue=xcolor.blue;
8724 color->flags=xcolor.flags;
8725 }
8726 return(status != False ? MagickTrue : MagickFalse);
8727}
8728
8729/*
8730%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8731% %
8732% %
8733% %
8734% X Q u e r y P o s i t i o n %
8735% %
8736% %
8737% %
8738%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8739%
8740% XQueryPosition() gets the pointer coordinates relative to a window.
8741%
8742% The format of the XQueryPosition method is:
8743%
8744% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8745%
8746% A description of each parameter follows:
8747%
8748% o display: Specifies a connection to an X server; returned from
8749% XOpenDisplay.
8750%
8751% o window: Specifies a pointer to a Window.
8752%
8753% o x: Return the x coordinate of the pointer relative to the origin of the
8754% window.
8755%
8756% o y: Return the y coordinate of the pointer relative to the origin of the
8757% window.
8758%
8759*/
cristybcbda3f2011-09-03 13:01:22 +00008760MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008761{
8762 int
8763 x_root,
8764 y_root;
8765
8766 unsigned int
8767 mask;
8768
8769 Window
8770 root_window;
8771
8772 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8773 assert(display != (Display *) NULL);
8774 assert(window != (Window) NULL);
8775 assert(x != (int *) NULL);
8776 assert(y != (int *) NULL);
8777 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8778 x,y,&mask);
8779}
8780
8781/*
8782%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8783% %
8784% %
8785% %
8786% X R e f r e s h W i n d o w %
8787% %
8788% %
8789% %
8790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8791%
8792% XRefreshWindow() refreshes an image in a X window.
8793%
8794% The format of the XRefreshWindow method is:
8795%
8796% void XRefreshWindow(Display *display,const XWindowInfo *window,
8797% const XEvent *event)
8798%
8799% A description of each parameter follows:
8800%
8801% o display: Specifies a connection to an X server; returned from
8802% XOpenDisplay.
8803%
8804% o window: Specifies a pointer to a XWindowInfo structure.
8805%
8806% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8807% the entire image is refreshed.
8808%
8809*/
cristybcbda3f2011-09-03 13:01:22 +00008810MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008811 const XEvent *event)
8812{
8813 int
8814 x,
8815 y;
8816
8817 unsigned int
8818 height,
8819 width;
8820
8821 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8822 assert(display != (Display *) NULL);
8823 assert(window != (XWindowInfo *) NULL);
8824 if (window->ximage == (XImage *) NULL)
8825 return;
8826 if (event != (XEvent *) NULL)
8827 {
8828 /*
8829 Determine geometry from expose event.
8830 */
8831 x=event->xexpose.x;
8832 y=event->xexpose.y;
8833 width=(unsigned int) event->xexpose.width;
8834 height=(unsigned int) event->xexpose.height;
8835 }
8836 else
8837 {
8838 XEvent
8839 sans_event;
8840
8841 /*
8842 Refresh entire window; discard outstanding expose events.
8843 */
8844 x=0;
8845 y=0;
8846 width=window->width;
8847 height=window->height;
8848 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008849 if (window->matte_pixmap != (Pixmap) NULL)
8850 {
8851#if defined(MAGICKCORE_HAVE_SHAPE)
8852 if (window->shape != MagickFalse)
8853 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8854 window->matte_pixmap,ShapeSet);
8855#endif
8856 }
cristy3ed852e2009-09-05 21:47:34 +00008857 }
8858 /*
8859 Check boundary conditions.
8860 */
8861 if ((window->ximage->width-(x+window->x)) < (int) width)
8862 width=(unsigned int) (window->ximage->width-(x+window->x));
8863 if ((window->ximage->height-(y+window->y)) < (int) height)
8864 height=(unsigned int) (window->ximage->height-(y+window->y));
8865 /*
8866 Refresh image.
8867 */
8868 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008869 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008870 if (window->pixmap != (Pixmap) NULL)
8871 {
8872 if (window->depth > 1)
8873 (void) XCopyArea(display,window->pixmap,window->id,
8874 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8875 else
8876 (void) XCopyPlane(display,window->pixmap,window->id,
8877 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8878 1L);
8879 }
8880 else
8881 {
8882#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8883 if (window->shared_memory)
8884 (void) XShmPutImage(display,window->id,window->annotate_context,
8885 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8886#endif
8887 if (window->shared_memory == MagickFalse)
8888 (void) XPutImage(display,window->id,window->annotate_context,
8889 window->ximage,x+window->x,y+window->y,x,y,width,height);
8890 }
8891 if (window->matte_pixmap != (Pixmap) NULL)
8892 (void) XSetClipMask(display,window->annotate_context,None);
8893 (void) XFlush(display);
8894}
8895
8896/*
8897%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8898% %
8899% %
8900% %
8901% X R e m o t e C o m m a n d %
8902% %
8903% %
8904% %
8905%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8906%
8907% XRemoteCommand() forces a remote display(1) to display the specified
8908% image filename.
8909%
8910% The format of the XRemoteCommand method is:
8911%
8912% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8913% const char *filename)
8914%
8915% A description of each parameter follows:
8916%
8917% o display: Specifies a connection to an X server; returned from
8918% XOpenDisplay.
8919%
8920% o window: Specifies the name or id of an X window.
8921%
8922% o filename: the name of the image filename to display.
8923%
8924*/
8925MagickExport MagickBooleanType XRemoteCommand(Display *display,
8926 const char *window,const char *filename)
8927{
8928 Atom
8929 remote_atom;
8930
8931 Window
8932 remote_window,
8933 root_window;
8934
8935 assert(filename != (char *) NULL);
8936 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8937 if (display == (Display *) NULL)
8938 display=XOpenDisplay((char *) NULL);
8939 if (display == (Display *) NULL)
8940 {
8941 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8942 return(MagickFalse);
8943 }
8944 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8945 remote_window=(Window) NULL;
8946 root_window=XRootWindow(display,XDefaultScreen(display));
8947 if (window != (char *) NULL)
8948 {
8949 /*
8950 Search window hierarchy and identify any clients by name or ID.
8951 */
8952 if (isdigit((unsigned char) *window) != 0)
8953 remote_window=XWindowByID(display,root_window,(Window)
8954 strtol((char *) window,(char **) NULL,0));
8955 if (remote_window == (Window) NULL)
8956 remote_window=XWindowByName(display,root_window,window);
8957 }
8958 if (remote_window == (Window) NULL)
8959 remote_window=XWindowByProperty(display,root_window,remote_atom);
8960 if (remote_window == (Window) NULL)
8961 {
8962 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8963 filename);
8964 return(MagickFalse);
8965 }
8966 /*
8967 Send remote command.
8968 */
8969 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8970 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8971 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8972 (void) XSync(display,MagickFalse);
8973 return(MagickTrue);
8974}
8975
8976/*
8977%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8978% %
8979% %
8980% %
8981% X R e t a i n W i n d o w C o l o r s %
8982% %
8983% %
8984% %
8985%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8986%
8987% XRetainWindowColors() sets X11 color resources on a window. This preserves
8988% the colors associated with an image displayed on the window.
8989%
8990% The format of the XRetainWindowColors method is:
8991%
8992% void XRetainWindowColors(Display *display,const Window window)
8993%
8994% A description of each parameter follows:
8995%
8996% o display: Specifies a connection to an X server; returned from
8997% XOpenDisplay.
8998%
8999% o window: Specifies a pointer to a XWindowInfo structure.
9000%
9001*/
9002MagickExport void XRetainWindowColors(Display *display,const Window window)
9003{
9004 Atom
9005 property;
9006
9007 Pixmap
9008 pixmap;
9009
9010 /*
9011 Put property on the window.
9012 */
9013 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9014 assert(display != (Display *) NULL);
9015 assert(window != (Window) NULL);
9016 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9017 if (property == (Atom) NULL)
9018 {
9019 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9020 "_XSETROOT_ID");
9021 return;
9022 }
9023 pixmap=XCreatePixmap(display,window,1,1,1);
9024 if (pixmap == (Pixmap) NULL)
9025 {
9026 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9027 return;
9028 }
9029 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9030 (unsigned char *) &pixmap,1);
9031 (void) XSetCloseDownMode(display,RetainPermanent);
9032}
9033
9034/*
9035%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9036% %
9037% %
9038% %
9039% X S e l e c t W i n d o w %
9040% %
9041% %
9042% %
9043%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9044%
9045% XSelectWindow() allows a user to select a window using the mouse. If the
9046% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9047% is returned in the crop_info structure.
9048%
9049% The format of the XSelectWindow function is:
9050%
9051% target_window=XSelectWindow(display,crop_info)
9052%
9053% A description of each parameter follows:
9054%
9055% o window: XSelectWindow returns the window id.
9056%
9057% o display: Specifies a pointer to the Display structure; returned from
9058% XOpenDisplay.
9059%
9060% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9061% contains the extents of any cropping rectangle.
9062%
cristy3ed852e2009-09-05 21:47:34 +00009063*/
9064static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9065{
9066#define MinimumCropArea (unsigned int) 9
9067
9068 Cursor
9069 target_cursor;
9070
9071 GC
9072 annotate_context;
9073
9074 int
9075 presses,
9076 x_offset,
9077 y_offset;
9078
9079 Status
9080 status;
9081
9082 Window
9083 root_window,
9084 target_window;
9085
9086 XEvent
9087 event;
9088
9089 XGCValues
9090 context_values;
9091
9092 /*
9093 Initialize graphic context.
9094 */
9095 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9096 assert(display != (Display *) NULL);
9097 assert(crop_info != (RectangleInfo *) NULL);
9098 root_window=XRootWindow(display,XDefaultScreen(display));
9099 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9100 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9101 context_values.function=GXinvert;
9102 context_values.plane_mask=
9103 context_values.background ^ context_values.foreground;
9104 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009105 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009106 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9107 if (annotate_context == (GC) NULL)
9108 return(MagickFalse);
9109 /*
9110 Grab the pointer using target cursor.
9111 */
9112 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9113 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9114 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9115 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9116 GrabModeAsync,root_window,target_cursor,CurrentTime);
9117 if (status != GrabSuccess)
9118 {
9119 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9120 return((Window) NULL);
9121 }
9122 /*
9123 Select a window.
9124 */
9125 crop_info->width=0;
9126 crop_info->height=0;
9127 presses=0;
9128 target_window=(Window) NULL;
9129 x_offset=0;
9130 y_offset=0;
9131 do
9132 {
9133 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9134 (void) XDrawRectangle(display,root_window,annotate_context,
9135 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9136 (unsigned int) crop_info->height-1);
9137 /*
9138 Allow another event.
9139 */
9140 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9141 (void) XWindowEvent(display,root_window,ButtonPressMask |
9142 ButtonReleaseMask | ButtonMotionMask,&event);
9143 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9144 (void) XDrawRectangle(display,root_window,annotate_context,
9145 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9146 (unsigned int) crop_info->height-1);
9147 switch (event.type)
9148 {
9149 case ButtonPress:
9150 {
9151 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9152 event.xbutton.x,event.xbutton.y);
9153 if (target_window == (Window) NULL)
9154 target_window=root_window;
9155 x_offset=event.xbutton.x_root;
9156 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009157 crop_info->x=(ssize_t) x_offset;
9158 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009159 crop_info->width=0;
9160 crop_info->height=0;
9161 presses++;
9162 break;
9163 }
9164 case ButtonRelease:
9165 {
9166 presses--;
9167 break;
9168 }
9169 case MotionNotify:
9170 {
9171 /*
9172 Discard pending button motion events.
9173 */
9174 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009175 crop_info->x=(ssize_t) event.xmotion.x;
9176 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009177 /*
9178 Check boundary conditions.
9179 */
9180 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009181 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009182 else
9183 {
cristyecd0ab52010-05-30 14:59:20 +00009184 crop_info->width=(size_t) (crop_info->x-x_offset);
9185 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009186 }
9187 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009188 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009189 else
9190 {
cristyecd0ab52010-05-30 14:59:20 +00009191 crop_info->height=(size_t) (crop_info->y-y_offset);
9192 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009193 }
9194 }
9195 default:
9196 break;
9197 }
9198 } while ((target_window == (Window) NULL) || (presses > 0));
9199 (void) XUngrabPointer(display,CurrentTime);
9200 (void) XFreeCursor(display,target_cursor);
9201 (void) XFreeGC(display,annotate_context);
9202 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9203 {
9204 crop_info->width=0;
9205 crop_info->height=0;
9206 }
9207 if ((crop_info->width != 0) && (crop_info->height != 0))
9208 target_window=root_window;
9209 return(target_window);
9210}
9211
9212/*
9213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9214% %
9215% %
9216% %
9217% X S e t C u r s o r S t a t e %
9218% %
9219% %
9220% %
9221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9222%
9223% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9224% reset to their default.
9225%
9226% The format of the XXSetCursorState method is:
9227%
9228% XSetCursorState(display,windows,const MagickStatusType state)
9229%
9230% A description of each parameter follows:
9231%
9232% o display: Specifies a connection to an X server; returned from
9233% XOpenDisplay.
9234%
9235% o windows: Specifies a pointer to a XWindows structure.
9236%
9237% o state: An unsigned integer greater than 0 sets the cursor state
9238% to busy, otherwise the cursor are reset to their default.
9239%
9240*/
cristybcbda3f2011-09-03 13:01:22 +00009241MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009242 const MagickStatusType state)
9243{
9244 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9245 assert(display != (Display *) NULL);
9246 assert(windows != (XWindows *) NULL);
9247 if (state)
9248 {
9249 (void) XCheckDefineCursor(display,windows->image.id,
9250 windows->image.busy_cursor);
9251 (void) XCheckDefineCursor(display,windows->pan.id,
9252 windows->pan.busy_cursor);
9253 (void) XCheckDefineCursor(display,windows->magnify.id,
9254 windows->magnify.busy_cursor);
9255 (void) XCheckDefineCursor(display,windows->command.id,
9256 windows->command.busy_cursor);
9257 }
9258 else
9259 {
9260 (void) XCheckDefineCursor(display,windows->image.id,
9261 windows->image.cursor);
9262 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9263 (void) XCheckDefineCursor(display,windows->magnify.id,
9264 windows->magnify.cursor);
9265 (void) XCheckDefineCursor(display,windows->command.id,
9266 windows->command.cursor);
9267 (void) XCheckDefineCursor(display,windows->command.id,
9268 windows->widget.cursor);
9269 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9270 }
9271 windows->info.mapped=MagickFalse;
9272}
9273
9274/*
9275%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9276% %
9277% %
9278% %
9279% X S e t W i n d o w s %
9280% %
9281% %
9282% %
9283%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9284%
9285% XSetWindows() sets the X windows structure if the windows info is specified.
9286% Otherwise the current windows structure is returned.
9287%
9288% The format of the XSetWindows method is:
9289%
9290% XWindows *XSetWindows(XWindows *windows_info)
9291%
9292% A description of each parameter follows:
9293%
9294% o windows_info: Initialize the Windows structure with this information.
9295%
9296*/
cristybcbda3f2011-09-03 13:01:22 +00009297MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009298{
9299 static XWindows
9300 *windows = (XWindows *) NULL;
9301
9302 if (windows_info != (XWindows *) ~0)
9303 {
9304 windows=(XWindows *) RelinquishMagickMemory(windows);
9305 windows=windows_info;
9306 }
9307 return(windows);
9308}
9309/*
9310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9311% %
9312% %
9313% %
9314% X U s e r P r e f e r e n c e s %
9315% %
9316% %
9317% %
9318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9319%
9320% XUserPreferences() saves the preferences in a configuration file in the
9321% users' home directory.
9322%
9323% The format of the XUserPreferences method is:
9324%
9325% void XUserPreferences(XResourceInfo *resource_info)
9326%
9327% A description of each parameter follows:
9328%
9329% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9330%
9331*/
cristybcbda3f2011-09-03 13:01:22 +00009332MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009333{
9334#if defined(X11_PREFERENCES_PATH)
9335 char
9336 cache[MaxTextExtent],
9337 filename[MaxTextExtent],
9338 specifier[MaxTextExtent];
9339
9340 const char
cristy104cea82009-10-25 02:26:51 +00009341 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009342 *value;
9343
9344 XrmDatabase
9345 preferences_database;
9346
9347 /*
9348 Save user preferences to the client configuration file.
9349 */
9350 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009351 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009352 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009353 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009354 value=resource_info->backdrop ? "True" : "False";
9355 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009356 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009357 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9358 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009359 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009360 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009361 value=resource_info->confirm_exit ? "True" : "False";
9362 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009363 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009364 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009365 value=resource_info->confirm_edit ? "True" : "False";
9366 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009367 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009368 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009369 value=resource_info->display_warnings ? "True" : "False";
9370 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009371 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009372 value=resource_info->quantize_info->dither ? "True" : "False";
9373 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009374 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009375 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009376 value=resource_info->gamma_correct ? "True" : "False";
9377 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009378 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9379 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009380 resource_info->undo_cache);
9381 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009382 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009383 value=resource_info->use_pixmap ? "True" : "False";
9384 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009385 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009386 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009387 ExpandFilename(filename);
9388 XrmPutFileDatabase(preferences_database,filename);
9389#endif
9390}
9391
9392/*
9393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9394% %
9395% %
9396% %
9397% X V i s u a l C l a s s N a m e %
9398% %
9399% %
9400% %
9401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9402%
9403% XVisualClassName() returns the visual class name as a character string.
9404%
9405% The format of the XVisualClassName method is:
9406%
9407% char *XVisualClassName(const int visual_class)
9408%
9409% A description of each parameter follows:
9410%
9411% o visual_type: XVisualClassName returns the visual class as a character
9412% string.
9413%
9414% o class: Specifies the visual class.
9415%
cristy3ed852e2009-09-05 21:47:34 +00009416*/
9417static const char *XVisualClassName(const int visual_class)
9418{
9419 switch (visual_class)
9420 {
9421 case StaticGray: return("StaticGray");
9422 case GrayScale: return("GrayScale");
9423 case StaticColor: return("StaticColor");
9424 case PseudoColor: return("PseudoColor");
9425 case TrueColor: return("TrueColor");
9426 case DirectColor: return("DirectColor");
9427 }
9428 return("unknown visual class");
9429}
9430
9431/*
9432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9433% %
9434% %
9435% %
9436% X W a r n i n g %
9437% %
9438% %
9439% %
9440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9441%
9442% XWarning() displays a warning reason in a Notice widget.
9443%
9444% The format of the XWarning method is:
9445%
9446% void XWarning(const unsigned int warning,const char *reason,
9447% const char *description)
9448%
9449% A description of each parameter follows:
9450%
9451% o warning: Specifies the numeric warning category.
9452%
9453% o reason: Specifies the reason to display before terminating the
9454% program.
9455%
9456% o description: Specifies any description to the reason.
9457%
9458*/
cristybcbda3f2011-09-03 13:01:22 +00009459MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009460 const char *reason,const char *description)
9461{
9462 char
9463 text[MaxTextExtent];
9464
9465 XWindows
9466 *windows;
9467
9468 if (reason == (char *) NULL)
9469 return;
9470 (void) CopyMagickString(text,reason,MaxTextExtent);
9471 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9472 windows=XSetWindows((XWindows *) ~0);
9473 XNoticeWidget(windows->display,windows,text,(char *) description);
9474}
9475
9476/*
9477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9478% %
9479% %
9480% %
9481% X W i n d o w B y I D %
9482% %
9483% %
9484% %
9485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9486%
9487% XWindowByID() locates a child window with a given ID. If not window with
9488% the given name is found, 0 is returned. Only the window specified and its
9489% subwindows are searched.
9490%
9491% The format of the XWindowByID function is:
9492%
9493% child=XWindowByID(display,window,id)
9494%
9495% A description of each parameter follows:
9496%
9497% o child: XWindowByID returns the window with the specified
9498% id. If no windows are found, XWindowByID returns 0.
9499%
9500% o display: Specifies a pointer to the Display structure; returned from
9501% XOpenDisplay.
9502%
9503% o id: Specifies the id of the window to locate.
9504%
9505*/
cristybcbda3f2011-09-03 13:01:22 +00009506MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009507 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009508{
9509 RectangleInfo
9510 rectangle_info;
9511
9512 register int
9513 i;
9514
9515 Status
9516 status;
9517
9518 unsigned int
9519 number_children;
9520
9521 Window
9522 child,
9523 *children,
9524 window;
9525
9526 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9527 assert(display != (Display *) NULL);
9528 assert(root_window != (Window) NULL);
9529 if (id == 0)
9530 return(XSelectWindow(display,&rectangle_info));
9531 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009532 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009533 status=XQueryTree(display,root_window,&child,&child,&children,
9534 &number_children);
9535 if (status == False)
9536 return((Window) NULL);
9537 window=(Window) NULL;
9538 for (i=0; i < (int) number_children; i++)
9539 {
9540 /*
9541 Search each child and their children.
9542 */
9543 window=XWindowByID(display,children[i],id);
9544 if (window != (Window) NULL)
9545 break;
9546 }
9547 if (children != (Window *) NULL)
9548 (void) XFree((void *) children);
9549 return(window);
9550}
9551
9552/*
9553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9554% %
9555% %
9556% %
9557% X W i n d o w B y N a m e %
9558% %
9559% %
9560% %
9561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9562%
9563% XWindowByName() locates a window with a given name on a display. If no
9564% window with the given name is found, 0 is returned. If more than one window
9565% has the given name, the first one is returned. Only root and its children
9566% are searched.
9567%
9568% The format of the XWindowByName function is:
9569%
9570% window=XWindowByName(display,root_window,name)
9571%
9572% A description of each parameter follows:
9573%
9574% o window: XWindowByName returns the window id.
9575%
9576% o display: Specifies a pointer to the Display structure; returned from
9577% XOpenDisplay.
9578%
9579% o root_window: Specifies the id of the root window.
9580%
9581% o name: Specifies the name of the window to locate.
9582%
9583*/
cristybcbda3f2011-09-03 13:01:22 +00009584MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009585 const char *name)
9586{
9587 register int
9588 i;
9589
9590 Status
9591 status;
9592
9593 unsigned int
9594 number_children;
9595
9596 Window
9597 *children,
9598 child,
9599 window;
9600
9601 XTextProperty
9602 window_name;
9603
9604 assert(display != (Display *) NULL);
9605 assert(root_window != (Window) NULL);
9606 assert(name != (char *) NULL);
9607 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9608 if (XGetWMName(display,root_window,&window_name) != 0)
9609 if (LocaleCompare((char *) window_name.value,name) == 0)
9610 return(root_window);
9611 status=XQueryTree(display,root_window,&child,&child,&children,
9612 &number_children);
9613 if (status == False)
9614 return((Window) NULL);
9615 window=(Window) NULL;
9616 for (i=0; i < (int) number_children; i++)
9617 {
9618 /*
9619 Search each child and their children.
9620 */
9621 window=XWindowByName(display,children[i],name);
9622 if (window != (Window) NULL)
9623 break;
9624 }
9625 if (children != (Window *) NULL)
9626 (void) XFree((void *) children);
9627 return(window);
9628}
9629
9630/*
9631%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9632% %
9633% %
9634% %
9635% X W i n d o w B y P r o p e r y %
9636% %
9637% %
9638% %
9639%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9640%
9641% XWindowByProperty() locates a child window with a given property. If not
9642% window with the given name is found, 0 is returned. If more than one window
9643% has the given property, the first one is returned. Only the window
9644% specified and its subwindows are searched.
9645%
9646% The format of the XWindowByProperty function is:
9647%
9648% child=XWindowByProperty(display,window,property)
9649%
9650% A description of each parameter follows:
9651%
9652% o child: XWindowByProperty returns the window id with the specified
9653% property. If no windows are found, XWindowByProperty returns 0.
9654%
9655% o display: Specifies a pointer to the Display structure; returned from
9656% XOpenDisplay.
9657%
9658% o property: Specifies the property of the window to locate.
9659%
9660*/
cristybcbda3f2011-09-03 13:01:22 +00009661MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009662 const Atom property)
9663{
9664 Atom
9665 type;
9666
9667 int
9668 format;
9669
9670 Status
9671 status;
9672
9673 unsigned char
9674 *data;
9675
9676 unsigned int
9677 i,
9678 number_children;
9679
cristyf2faecf2010-05-28 19:19:36 +00009680 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009681 after,
9682 number_items;
9683
9684 Window
9685 child,
9686 *children,
9687 parent,
9688 root;
9689
9690 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9691 assert(display != (Display *) NULL);
9692 assert(window != (Window) NULL);
9693 assert(property != (Atom) NULL);
9694 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9695 if (status == False)
9696 return((Window) NULL);
9697 type=(Atom) NULL;
9698 child=(Window) NULL;
9699 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9700 {
9701 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9702 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9703 if (data != NULL)
9704 (void) XFree((void *) data);
9705 if ((status == Success) && (type != (Atom) NULL))
9706 child=children[i];
9707 }
9708 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9709 child=XWindowByProperty(display,children[i],property);
9710 if (children != (Window *) NULL)
9711 (void) XFree((void *) children);
9712 return(child);
9713}
9714#else
9715
9716/*
9717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9718% %
9719% %
9720% %
9721% X I m p o r t I m a g e %
9722% %
9723% %
9724% %
9725%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9726%
9727% XImportImage() reads an image from an X window.
9728%
9729% The format of the XImportImage method is:
9730%
cristya0dc96a2011-12-19 23:58:54 +00009731% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9732% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009733%
9734% A description of each parameter follows:
9735%
9736% o image_info: the image info..
9737%
9738% o ximage_info: Specifies a pointer to an XImportInfo structure.
9739%
cristya0dc96a2011-12-19 23:58:54 +00009740% o exception: return any errors or warnings in this structure.
9741%
cristy3ed852e2009-09-05 21:47:34 +00009742*/
cristybcbda3f2011-09-03 13:01:22 +00009743MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009744 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009745{
9746 assert(image_info != (const ImageInfo *) NULL);
9747 assert(image_info->signature == MagickSignature);
9748 if (image_info->debug != MagickFalse)
9749 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9750 image_info->filename);
9751 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009752 assert(exception != (ExceptionInfo *) NULL);
9753 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009754 return((Image *) NULL);
9755}
9756#endif
9757
9758/*
9759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9760% %
9761% %
9762% %
cristy576974e2009-10-25 20:45:31 +00009763+ X C o m p o n e n t G e n e s i s %
9764% %
9765% %
9766% %
9767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9768%
9769% XComponentGenesis() instantiates the X component.
9770%
9771% The format of the XComponentGenesis method is:
9772%
9773% MagickBooleanType XComponentGenesis(void)
9774%
9775*/
cristy5ff4eaf2011-09-03 01:38:02 +00009776MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009777{
9778 return(MagickTrue);
9779}
9780
9781/*
9782%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9783% %
9784% %
9785% %
cristy3ed852e2009-09-05 21:47:34 +00009786% X G e t I m p o r t I n f o %
9787% %
9788% %
9789% %
9790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9791%
9792% XGetImportInfo() initializes the XImportInfo structure.
9793%
9794% The format of the XGetImportInfo method is:
9795%
9796% void XGetImportInfo(XImportInfo *ximage_info)
9797%
9798% A description of each parameter follows:
9799%
9800% o ximage_info: Specifies a pointer to an ImageInfo structure.
9801%
9802*/
9803MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9804{
9805 assert(ximage_info != (XImportInfo *) NULL);
9806 ximage_info->frame=MagickFalse;
9807 ximage_info->borders=MagickFalse;
9808 ximage_info->screen=MagickFalse;
9809 ximage_info->descend=MagickTrue;
9810 ximage_info->silent=MagickFalse;
9811}