blob: edb4f61f6abe19806c7648d67f2b82f07e1ce472 [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% %
cristy45ef08f2012-12-07 13:13:34 +000020% Copyright 1999-2013 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
cristya19f1d72012-08-07 18:24:38 +0000209static double
cristy3ed852e2009-09-05 21:47:34 +0000210 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
cristyb0a657e2012-08-29 00:45:37 +0000482 PixelTrait
483 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +0000484
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)
cristy8a46d822012-08-28 23:32:39 +0000563 annotate_image->alpha_trait=BlendPixelTrait;
cristy6f5395d2012-12-14 18:30:30 +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
cristya19f1d72012-08-07 18:24:38 +0000642 double
cristy3ed852e2009-09-05 21:47:34 +0000643 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);
cristyb0a657e2012-08-29 00:45:37 +0000698 alpha_trait=image->alpha_trait;
cristyfeb3e962012-03-29 17:25:55 +0000699 (void) CompositeImage(image,annotate_image,
cristyb0a657e2012-08-29 00:45:37 +0000700 annotate_image->alpha_trait == BlendPixelTrait ? OverCompositeOp :
701 CopyCompositeOp,MagickTrue,(ssize_t) x,(ssize_t) y,exception);
702 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +0000703 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
cristya19f1d72012-08-07 18:24:38 +0000907 double
cristy3ed852e2009-09-05 21:47:34 +0000908 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 */
cristya19f1d72012-08-07 18:24:38 +0000968 scale_factor=(double) icon_size->max_width/width;
969 if (scale_factor > ((double) icon_size->max_height/height))
970 scale_factor=(double) icon_size->max_height/height;
cristy3ed852e2009-09-05 21:47:34 +0000971 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
cristya19f1d72012-08-07 18:24:38 +00001037 double
cristy3ed852e2009-09-05 21:47:34 +00001038 min_distance;
1039
cristya19f1d72012-08-07 18:24:38 +00001040 register double
cristy3ed852e2009-09-05 21:47:34 +00001041 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 }
cristya19f1d72012-08-07 18:24:38 +00001078 min_distance=3.0*((double) QuantumRange+1.0)*((double)
cristy3ed852e2009-09-05 21:47:34 +00001079 QuantumRange+1.0);
1080 j=0;
1081 for (i=0; i < (int) number_colors; i++)
1082 {
cristya19f1d72012-08-07 18:24:38 +00001083 pixel.red=colors[i].red-(double) color->red;
cristy3ed852e2009-09-05 21:47:34 +00001084 distance=pixel.red*pixel.red;
1085 if (distance > min_distance)
1086 continue;
cristya19f1d72012-08-07 18:24:38 +00001087 pixel.green=colors[i].green-(double) color->green;
cristy3ed852e2009-09-05 21:47:34 +00001088 distance+=pixel.green*pixel.green;
1089 if (distance > min_distance)
1090 continue;
cristya19f1d72012-08-07 18:24:38 +00001091 pixel.blue=colors[i].blue-(double) color->blue;
cristy3ed852e2009-09-05 21:47:34 +00001092 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;
cristy46ff2672012-12-14 15:32:26 +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 {
cristyada285b2012-07-07 19:00:46 +00002239 color.red=(double) ClampToQuantum((double) (red_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002240 (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002241 color.green=(double) ClampToQuantum((double) (green_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002242 (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002243 color.blue=(double) ClampToQuantum((double) (blue_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002244 (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
cristyb0a657e2012-08-29 00:45:37 +00002321 PixelTrait
2322 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002323
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);
cristy8a46d822012-08-28 23:32:39 +00002486 draw_image->alpha_trait=BlendPixelTrait;
cristy6f5395d2012-12-14 18:30:30 +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
cristya19f1d72012-08-07 18:24:38 +00002558 double
cristy3ed852e2009-09-05 21:47:34 +00002559 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 */
cristy6f5395d2012-12-14 18:30:30 +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 {
cristyb0a657e2012-08-29 00:45:37 +00002642 alpha_trait=image->alpha_trait;
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);
cristyb0a657e2012-08-29 00:45:37 +00002645 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002646 }
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
cristybcdf5672012-05-24 22:58:54 +00003054 extern const char
3055 BorderColor[],
3056 ForegroundColor[];
3057
cristybb503372010-05-27 20:51:26 +00003058 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003059 i;
3060
3061 Status
3062 status;
3063
3064 unsigned int
3065 packets;
3066
3067 /*
3068 Initialize pixel info.
3069 */
3070 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3071 assert(display != (Display *) NULL);
3072 assert(visual_info != (XVisualInfo *) NULL);
3073 assert(map_info != (XStandardColormap *) NULL);
3074 assert(resource_info != (XResourceInfo *) NULL);
3075 assert(pixel != (XPixelInfo *) NULL);
3076 pixel->colors=0;
3077 if (image != (Image *) NULL)
3078 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003079 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003080 packets=(unsigned int)
3081 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003082 if (pixel->pixels != (unsigned long *) NULL)
3083 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3084 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003085 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003086 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003087 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3088 image->filename);
3089 /*
3090 Set foreground color.
3091 */
3092 colormap=map_info->colormap;
3093 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3094 &pixel->foreground_color);
3095 status=XParseColor(display,colormap,resource_info->foreground_color,
3096 &pixel->foreground_color);
3097 if (status == False)
3098 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3099 resource_info->foreground_color);
3100 pixel->foreground_color.pixel=
3101 XStandardPixel(map_info,&pixel->foreground_color);
3102 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3103 /*
3104 Set background color.
3105 */
3106 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3107 status=XParseColor(display,colormap,resource_info->background_color,
3108 &pixel->background_color);
3109 if (status == False)
3110 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3111 resource_info->background_color);
3112 pixel->background_color.pixel=
3113 XStandardPixel(map_info,&pixel->background_color);
3114 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3115 /*
3116 Set border color.
3117 */
3118 (void) XParseColor(display,colormap,(char *) BorderColor,
3119 &pixel->border_color);
3120 status=XParseColor(display,colormap,resource_info->border_color,
3121 &pixel->border_color);
3122 if (status == False)
3123 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3124 resource_info->border_color);
3125 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3126 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3127 /*
3128 Set matte color.
3129 */
3130 pixel->matte_color=pixel->background_color;
3131 if (resource_info->matte_color != (char *) NULL)
3132 {
3133 /*
3134 Matte color is specified as a X resource or command line argument.
3135 */
3136 status=XParseColor(display,colormap,resource_info->matte_color,
3137 &pixel->matte_color);
3138 if (status == False)
3139 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3140 resource_info->matte_color);
3141 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3142 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3143 }
3144 /*
3145 Set highlight color.
3146 */
3147 pixel->highlight_color.red=(unsigned short) ((
3148 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3149 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3150 pixel->highlight_color.green=(unsigned short) ((
3151 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3152 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3153 pixel->highlight_color.blue=(unsigned short) ((
3154 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3155 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3156 pixel->highlight_color.pixel=
3157 XStandardPixel(map_info,&pixel->highlight_color);
3158 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3159 /*
3160 Set shadow color.
3161 */
cristya19f1d72012-08-07 18:24:38 +00003162 pixel->shadow_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003163 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003164 pixel->shadow_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003165 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003166 pixel->shadow_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003167 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3168 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3169 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3170 /*
3171 Set depth color.
3172 */
cristya19f1d72012-08-07 18:24:38 +00003173 pixel->depth_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003174 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003175 pixel->depth_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003176 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003177 pixel->depth_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003178 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3179 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3180 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3181 /*
3182 Set trough color.
3183 */
cristya19f1d72012-08-07 18:24:38 +00003184 pixel->trough_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003185 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003186 pixel->trough_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003187 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003188 pixel->trough_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003189 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3190 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3191 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3192 /*
3193 Set pen color.
3194 */
3195 for (i=0; i < MaxNumberPens; i++)
3196 {
3197 (void) XParseColor(display,colormap,(char *) PenColors[i],
3198 &pixel->pen_colors[i]);
3199 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3200 &pixel->pen_colors[i]);
3201 if (status == False)
3202 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3203 resource_info->pen_colors[i]);
3204 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3205 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3206 }
3207 pixel->box_color=pixel->background_color;
3208 pixel->pen_color=pixel->foreground_color;
3209 pixel->box_index=0;
3210 pixel->pen_index=1;
3211 if (image != (Image *) NULL)
3212 {
3213 if ((resource_info->gamma_correct != MagickFalse) &&
3214 (image->gamma != 0.0))
3215 {
3216 GeometryInfo
3217 geometry_info;
3218
3219 MagickStatusType
3220 flags;
3221
3222 /*
3223 Initialize map relative to display and image gamma.
3224 */
3225 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3226 red_gamma=geometry_info.rho;
3227 green_gamma=geometry_info.sigma;
3228 if ((flags & SigmaValue) == 0)
3229 green_gamma=red_gamma;
3230 blue_gamma=geometry_info.xi;
3231 if ((flags & XiValue) == 0)
3232 blue_gamma=red_gamma;
3233 red_gamma*=image->gamma;
3234 green_gamma*=image->gamma;
3235 blue_gamma*=image->gamma;
3236 }
3237 if (image->storage_class == PseudoClass)
3238 {
3239 /*
3240 Initialize pixel array for images of type PseudoClass.
3241 */
cristybb503372010-05-27 20:51:26 +00003242 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003243 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003244 for (i=0; i < MaxNumberPens; i++)
3245 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3246 pixel->colors+=MaxNumberPens;
3247 }
3248 }
3249}
3250
3251/*
3252%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3253% %
3254% %
3255% %
3256% X G e t R e s o u r c e C l a s s %
3257% %
3258% %
3259% %
3260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3261%
3262% XGetResourceClass() queries the X server for the specified resource name or
3263% class. If the resource name or class is not defined in the database, the
3264% supplied default value is returned.
3265%
3266% The format of the XGetResourceClass method is:
3267%
3268% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3269% const char *keyword,char *resource_default)
3270%
3271% A description of each parameter follows:
3272%
3273% o database: Specifies a resource database; returned from
3274% XrmGetStringDatabase.
3275%
3276% o client_name: Specifies the application name used to retrieve resource
3277% info from the X server database.
3278%
3279% o keyword: Specifies the keyword of the value being retrieved.
3280%
3281% o resource_default: Specifies the default value to return if the query
3282% fails to find the specified keyword/class.
3283%
3284*/
3285MagickExport char *XGetResourceClass(XrmDatabase database,
3286 const char *client_name,const char *keyword,char *resource_default)
3287{
3288 char
3289 resource_class[MaxTextExtent],
3290 resource_name[MaxTextExtent];
3291
3292 static char
3293 *resource_type;
3294
3295 Status
3296 status;
3297
3298 XrmValue
3299 resource_value;
3300
3301 if (database == (XrmDatabase) NULL)
3302 return(resource_default);
3303 *resource_name='\0';
3304 *resource_class='\0';
3305 if (keyword != (char *) NULL)
3306 {
3307 int
3308 c,
3309 k;
3310
3311 /*
3312 Initialize resource keyword and class.
3313 */
cristyb51dff52011-05-19 16:55:47 +00003314 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003315 client_name,keyword);
3316 c=(int) (*client_name);
3317 if ((c >= XK_a) && (c <= XK_z))
3318 c-=(XK_a-XK_A);
3319 else
3320 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3321 c-=(XK_agrave-XK_Agrave);
3322 else
3323 if ((c >= XK_oslash) && (c <= XK_thorn))
3324 c-=(XK_oslash-XK_Ooblique);
3325 k=(int) (*keyword);
3326 if ((k >= XK_a) && (k <= XK_z))
3327 k-=(XK_a-XK_A);
3328 else
3329 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3330 k-=(XK_agrave-XK_Agrave);
3331 else
3332 if ((k >= XK_oslash) && (k <= XK_thorn))
3333 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003334 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003335 client_name+1,k,keyword+1);
3336 }
3337 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3338 &resource_value);
3339 if (status == False)
3340 return(resource_default);
3341 return(resource_value.addr);
3342}
3343
3344/*
3345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3346% %
3347% %
3348% %
3349% X G e t R e s o u r c e D a t a b a s e %
3350% %
3351% %
3352% %
3353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3354%
3355% XGetResourceDatabase() creates a new resource database and initializes it.
3356%
3357% The format of the XGetResourceDatabase method is:
3358%
3359% XrmDatabase XGetResourceDatabase(Display *display,
3360% const char *client_name)
3361%
3362% A description of each parameter follows:
3363%
3364% o database: XGetResourceDatabase() returns the database after it is
3365% initialized.
3366%
3367% o display: Specifies a connection to an X server; returned from
3368% XOpenDisplay.
3369%
3370% o client_name: Specifies the application name used to retrieve resource
3371% info from the X server database.
3372%
3373*/
3374MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3375 const char *client_name)
3376{
3377 char
3378 filename[MaxTextExtent];
3379
3380 int
3381 c;
3382
3383 register const char
3384 *p;
3385
3386 XrmDatabase
3387 resource_database,
3388 server_database;
3389
3390 if (display == (Display *) NULL)
3391 return((XrmDatabase) NULL);
3392 assert(client_name != (char *) NULL);
3393 /*
3394 Initialize resource database.
3395 */
3396 XrmInitialize();
3397 (void) XGetDefault(display,(char *) client_name,"dummy");
3398 resource_database=XrmGetDatabase(display);
3399 /*
3400 Combine application database.
3401 */
3402 if (client_name != (char *) NULL)
3403 {
3404 /*
3405 Get basename of client.
3406 */
3407 p=client_name+(strlen(client_name)-1);
3408 while ((p > client_name) && (*p != '/'))
3409 p--;
3410 if (*p == '/')
3411 client_name=p+1;
3412 }
3413 c=(int) (*client_name);
3414 if ((c >= XK_a) && (c <= XK_z))
3415 c-=(XK_a-XK_A);
3416 else
3417 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3418 c-=(XK_agrave-XK_Agrave);
3419 else
3420 if ((c >= XK_oslash) && (c <= XK_thorn))
3421 c-=(XK_oslash-XK_Ooblique);
3422#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003423 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003424 X11_APPLICATION_PATH,c,client_name+1);
3425 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3426#endif
3427 if (XResourceManagerString(display) != (char *) NULL)
3428 {
3429 /*
3430 Combine server database.
3431 */
3432 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3433 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3434 }
3435 /*
3436 Merge user preferences database.
3437 */
3438#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003439 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003440 X11_PREFERENCES_PATH,client_name);
3441 ExpandFilename(filename);
3442 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3443#endif
3444 return(resource_database);
3445}
3446
3447/*
3448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3449% %
3450% %
3451% %
3452% X G e t R e s o u r c e I n f o %
3453% %
3454% %
3455% %
3456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3457%
3458% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3459%
3460% The format of the XGetResourceInfo method is:
3461%
3462% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3463% const char *client_name,XResourceInfo *resource_info)
3464%
3465% A description of each parameter follows:
3466%
3467% o image_info: the image info.
3468%
3469% o database: Specifies a resource database; returned from
3470% XrmGetStringDatabase.
3471%
3472% o client_name: Specifies the application name used to retrieve
3473% resource info from the X server database.
3474%
3475% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3476%
3477*/
3478MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3479 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3480{
3481 char
cristy00976d82011-02-20 20:31:28 +00003482 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003483 *resource_value;
3484
cristybcdf5672012-05-24 22:58:54 +00003485 extern const char
3486 BorderColor[],
3487 ForegroundColor[];
3488
cristy3ed852e2009-09-05 21:47:34 +00003489 /*
3490 Initialize resource info fields.
3491 */
3492 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3493 assert(resource_info != (XResourceInfo *) NULL);
3494 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3495 resource_info->resource_database=database;
3496 resource_info->image_info=(ImageInfo *) image_info;
3497 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3498 XMagickProgressMonitor,(void *) NULL);
3499 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3500 resource_info->close_server=MagickTrue;
3501 resource_info->client_name=AcquireString(client_name);
3502 resource_value=XGetResourceClass(database,client_name,"backdrop",
3503 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003504 resource_info->backdrop=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003505 resource_info->background_color=XGetResourceInstance(database,client_name,
3506 "background",(char *) "#d6d6d6d6d6d6");
3507 resource_info->border_color=XGetResourceInstance(database,client_name,
3508 "borderColor",BorderColor);
3509 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3510 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003511 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3512 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003513 resource_value=XGetResourceClass(database,client_name,"colormap",
3514 (char *) "shared");
3515 resource_info->colormap=UndefinedColormap;
3516 if (LocaleCompare("private",resource_value) == 0)
3517 resource_info->colormap=PrivateColormap;
3518 if (LocaleCompare("shared",resource_value) == 0)
3519 resource_info->colormap=SharedColormap;
3520 if (resource_info->colormap == UndefinedColormap)
3521 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3522 resource_value);
3523 resource_value=XGetResourceClass(database,client_name,
3524 "colorRecovery",(char *) "False");
anthony6f201312012-03-30 04:08:15 +00003525 resource_info->color_recovery=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003526 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3527 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003528 resource_info->confirm_exit=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003529 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3530 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003531 resource_info->confirm_edit=IsStringTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003532 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003533 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003534 resource_info->display_gamma=XGetResourceClass(database,client_name,
3535 "displayGamma",(char *) "2.2");
3536 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3537 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003538 resource_info->display_warnings=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003539 resource_info->font=XGetResourceClass(database,client_name,"font",
3540 (char *) NULL);
3541 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3542 resource_info->font);
3543 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3544 (char *) "fixed");
3545 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3546 (char *) "variable");
3547 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3548 (char *) "5x8");
3549 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3550 (char *) "6x10");
3551 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3552 (char *) "7x13bold");
3553 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3554 (char *) "8x13bold");
3555 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3556 (char *) "9x15bold");
3557 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3558 (char *) "10x20");
3559 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3560 (char *) "12x24");
3561 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3562 (char *) "fixed");
3563 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3564 (char *) "fixed");
3565 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3566 "foreground",ForegroundColor);
3567 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
cristy8bc259b2012-06-21 23:53:15 +00003568 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003569 resource_info->gamma_correct=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003570 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3571 client_name,"geometry",(char *) NULL));
3572 resource_value=XGetResourceClass(database,client_name,"gravity",
3573 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003574 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003575 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003576 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3577 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003578 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3579 "iconGeometry",(char *) NULL);
3580 resource_value=XGetResourceClass(database,client_name,"iconic",
3581 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003582 resource_info->iconic=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003583 resource_value=XGetResourceClass(database,client_name,"immutable",
3584 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3585 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003586 resource_info->immutable=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003587 resource_value=XGetResourceClass(database,client_name,"magnify",
3588 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003589 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003590 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3591 (char *) NULL);
3592 resource_info->matte_color=XGetResourceInstance(database,client_name,
3593 "mattecolor",(char *) NULL);
3594 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3595 "name",(char *) NULL));
3596 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3597 (char *) "black");
3598 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3599 (char *) "blue");
3600 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3601 (char *) "cyan");
3602 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3603 (char *) "green");
3604 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3605 (char *) "gray");
3606 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3607 (char *) "red");
3608 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3609 (char *) "magenta");
3610 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3611 (char *) "yellow");
3612 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3613 (char *) "white");
3614 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3615 (char *) "gray");
3616 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3617 (char *) "gray");
3618 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003619 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003620 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003621 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003622 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3623 "font",(char *) "fixed");
3624 resource_info->text_font=XGetResourceClass(database,client_name,
3625 "textFontList",resource_info->text_font);
3626 resource_info->title=XGetResourceClass(database,client_name,"title",
3627 (char *) NULL);
3628 resource_value=XGetResourceClass(database,client_name,"undoCache",
cristy92befbd2012-09-16 14:08:12 +00003629 (char *) "256");
cristye27293e2009-12-18 02:53:20 +00003630 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003631 resource_value=XGetResourceClass(database,client_name,"update",
3632 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003633 resource_info->update=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003634 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3635 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003636 resource_info->use_pixmap=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003637 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3638 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003639 resource_info->use_shared_memory=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003640 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3641 (char *) NULL);
3642 resource_info->window_group=XGetResourceClass(database,client_name,
3643 "windowGroup",(char *) NULL);
3644 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3645 (char *) NULL);
3646 resource_info->write_filename=XGetResourceClass(database,client_name,
3647 "writeFilename",(char *) NULL);
3648}
3649
3650/*
3651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3652% %
3653% %
3654% %
3655% X G e t R e s o u r c e I n s t a n c e %
3656% %
3657% %
3658% %
3659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3660%
3661% XGetResourceInstance() queries the X server for the specified resource name.
3662% If the resource name is not defined in the database, the supplied default
3663% value is returned.
3664%
3665% The format of the XGetResourceInstance method is:
3666%
3667% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3668% const char *keyword,const char *resource_default)
3669%
3670% A description of each parameter follows:
3671%
3672% o database: Specifies a resource database; returned from
3673% XrmGetStringDatabase.
3674%
3675% o client_name: Specifies the application name used to retrieve
3676% resource info from the X server database.
3677%
3678% o keyword: Specifies the keyword of the value being retrieved.
3679%
3680% o resource_default: Specifies the default value to return if the query
3681% fails to find the specified keyword/class.
3682%
3683*/
3684MagickExport char *XGetResourceInstance(XrmDatabase database,
3685 const char *client_name,const char *keyword,const char *resource_default)
3686{
3687 char
3688 *resource_type,
3689 resource_name[MaxTextExtent];
3690
3691 Status
3692 status;
3693
3694 XrmValue
3695 resource_value;
3696
3697 if (database == (XrmDatabase) NULL)
3698 return((char *) resource_default);
3699 *resource_name='\0';
3700 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003701 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003702 keyword);
3703 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3704 &resource_value);
3705 if (status == False)
3706 return((char *) resource_default);
3707 return(resource_value.addr);
3708}
3709
3710/*
3711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3712% %
3713% %
3714% %
3715% X G e t S c r e e n D e n s i t y %
3716% %
3717% %
3718% %
3719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3720%
3721% XGetScreenDensity() returns the density of the X server screen in
3722% dots-per-inch.
3723%
3724% The format of the XGetScreenDensity method is:
3725%
3726% char *XGetScreenDensity(Display *display)
3727%
3728% A description of each parameter follows:
3729%
3730% o density: XGetScreenDensity() returns the density of the X screen in
3731% dots-per-inch.
3732%
3733% o display: Specifies a connection to an X server; returned from
3734% XOpenDisplay.
3735%
3736*/
3737MagickExport char *XGetScreenDensity(Display *display)
3738{
3739 char
3740 density[MaxTextExtent];
3741
3742 double
3743 x_density,
3744 y_density;
3745
3746 /*
3747 Set density as determined by screen size.
3748 */
3749 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3750 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3751 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3752 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003753 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003754 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003755 return(GetPageGeometry(density));
3756}
3757
3758/*
3759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3760% %
3761% %
3762% %
3763+ X G e t S u b w i n d o w %
3764% %
3765% %
3766% %
3767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3768%
3769% XGetSubwindow() returns the subwindow of a window chosen the user with the
3770% pointer and a button press.
3771%
3772% The format of the XGetSubwindow method is:
3773%
3774% Window XGetSubwindow(Display *display,Window window,int x,int y)
3775%
3776% A description of each parameter follows:
3777%
3778% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3779% otherwise the subwindow is returned.
3780%
3781% o display: Specifies a connection to an X server; returned from
3782% XOpenDisplay.
3783%
3784% o window: Specifies a pointer to a Window.
3785%
3786% o x: the x coordinate of the pointer relative to the origin of the
3787% window.
3788%
3789% o y: the y coordinate of the pointer relative to the origin of the
3790% window.
3791%
cristy3ed852e2009-09-05 21:47:34 +00003792*/
3793static Window XGetSubwindow(Display *display,Window window,int x,int y)
3794{
3795 int
3796 x_offset,
3797 y_offset;
3798
3799 Status
3800 status;
3801
3802 Window
3803 source_window,
3804 target_window;
3805
3806 assert(display != (Display *) NULL);
3807 source_window=XRootWindow(display,XDefaultScreen(display));
3808 if (window == (Window) NULL)
3809 return(source_window);
3810 target_window=window;
3811 for ( ; ; )
3812 {
3813 status=XTranslateCoordinates(display,source_window,window,x,y,
3814 &x_offset,&y_offset,&target_window);
3815 if (status != True)
3816 break;
3817 if (target_window == (Window) NULL)
3818 break;
3819 source_window=window;
3820 window=target_window;
3821 x=x_offset;
3822 y=y_offset;
3823 }
3824 if (target_window == (Window) NULL)
3825 target_window=window;
3826 return(target_window);
3827}
3828
3829/*
3830%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3831% %
3832% %
3833% %
3834% X G e t W i n d o w C o l o r %
3835% %
3836% %
3837% %
3838%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3839%
3840% XGetWindowColor() returns the color of a pixel interactively chosen from the
3841% X server.
3842%
3843% The format of the XGetWindowColor method is:
3844%
3845% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003846% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003847%
3848% A description of each parameter follows:
3849%
3850% o display: Specifies a connection to an X server; returned from
3851% XOpenDisplay.
3852%
3853% o windows: Specifies a pointer to a XWindows structure.
3854%
3855% o name: the name of the color if found in the X Color Database is
3856% returned in this character string.
3857%
cristy6710d842011-10-20 23:23:00 +00003858% o exception: return any errors or warnings in this structure.
3859%
cristy3ed852e2009-09-05 21:47:34 +00003860*/
cristybcbda3f2011-09-03 13:01:22 +00003861MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003862 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003863{
3864 int
3865 x,
3866 y;
3867
cristy101ab702011-10-13 13:06:32 +00003868 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003869 pixel;
3870
3871 RectangleInfo
3872 crop_info;
3873
3874 Status
3875 status;
3876
3877 Window
3878 child,
3879 client_window,
3880 root_window,
3881 target_window;
3882
3883 XColor
3884 color;
3885
3886 XImage
3887 *ximage;
3888
3889 XWindowAttributes
3890 window_attributes;
3891
3892 /*
3893 Choose a pixel from the X server.
3894 */
3895 assert(display != (Display *) NULL);
3896 assert(name != (char *) NULL);
3897 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3898 *name='\0';
3899 target_window=XSelectWindow(display,&crop_info);
3900 if (target_window == (Window) NULL)
3901 return(MagickFalse);
3902 root_window=XRootWindow(display,XDefaultScreen(display));
3903 client_window=target_window;
3904 if (target_window != root_window)
3905 {
3906 unsigned int
3907 d;
3908
3909 /*
3910 Get client window.
3911 */
3912 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3913 if (status != False)
3914 {
3915 client_window=XClientWindow(display,target_window);
3916 target_window=client_window;
3917 }
3918 }
3919 /*
3920 Verify window is viewable.
3921 */
3922 status=XGetWindowAttributes(display,target_window,&window_attributes);
3923 if ((status == False) || (window_attributes.map_state != IsViewable))
3924 return(MagickFalse);
3925 /*
3926 Get window X image.
3927 */
3928 (void) XTranslateCoordinates(display,root_window,target_window,
3929 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3930 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3931 if (ximage == (XImage *) NULL)
3932 return(MagickFalse);
3933 color.pixel=XGetPixel(ximage,0,0);
3934 XDestroyImage(ximage);
3935 /*
3936 Match color against the color database.
3937 */
3938 (void) XQueryColor(display,window_attributes.colormap,&color);
cristye42f6582012-02-11 17:59:50 +00003939 pixel.red=(double) ScaleShortToQuantum(color.red);
3940 pixel.green=(double) ScaleShortToQuantum(color.green);
3941 pixel.blue=(double) ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003942 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003943 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003944 exception);
cristy3ed852e2009-09-05 21:47:34 +00003945 return(MagickTrue);
3946}
3947
3948/*
3949%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3950% %
3951% %
3952% %
3953+ X G e t W i n d o w I m a g e %
3954% %
3955% %
3956% %
3957%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3958%
3959% XGetWindowImage() reads an image from the target X window and returns it.
3960% XGetWindowImage() optionally descends the window hierarchy and overlays the
3961% target image with each child image in an optimized fashion. Any child
3962% window that have the same visual, colormap, and are contained by its parent
3963% are exempted.
3964%
3965% The format of the XGetWindowImage method is:
3966%
3967% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003968% const unsigned int borders,const unsigned int level,
3969% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003970%
3971% A description of each parameter follows:
3972%
3973% o display: Specifies a connection to an X server; returned from
3974% XOpenDisplay.
3975%
3976% o window: Specifies the window to obtain the image from.
3977%
3978% o borders: Specifies whether borders pixels are to be saved with
3979% the image.
3980%
3981% o level: Specifies an unsigned integer representing the level of
3982% decent in the window hierarchy. This value must be zero or one on
3983% the initial call to XGetWindowImage. A value of zero returns after
3984% one call. A value of one causes the function to descend the window
3985% hierarchy and overlay the target image with each subwindow image.
3986%
cristy6710d842011-10-20 23:23:00 +00003987% o exception: return any errors or warnings in this structure.
3988%
cristy3ed852e2009-09-05 21:47:34 +00003989*/
3990static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003991 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003992{
3993 typedef struct _ColormapInfo
3994 {
3995 Colormap
3996 colormap;
3997
3998 XColor
3999 *colors;
4000
4001 struct _ColormapInfo
4002 *next;
4003 } ColormapInfo;
4004
4005 typedef struct _WindowInfo
4006 {
4007 Window
4008 window,
4009 parent;
4010
4011 Visual
4012 *visual;
4013
4014 Colormap
4015 colormap;
4016
4017 XSegment
4018 bounds;
4019
4020 RectangleInfo
4021 crop_info;
4022 } WindowInfo;
4023
cristy3ed852e2009-09-05 21:47:34 +00004024 int
4025 display_height,
4026 display_width,
4027 id,
4028 x_offset,
4029 y_offset;
4030
cristy4c08aed2011-07-01 19:47:50 +00004031 Quantum
4032 index;
4033
cristy3ed852e2009-09-05 21:47:34 +00004034 RectangleInfo
4035 crop_info;
4036
cristy3ed852e2009-09-05 21:47:34 +00004037 register int
4038 i;
4039
4040 static ColormapInfo
4041 *colormap_info = (ColormapInfo *) NULL;
4042
4043 static int
4044 max_windows = 0,
4045 number_windows = 0;
4046
4047 static WindowInfo
4048 *window_info;
4049
4050 Status
4051 status;
4052
4053 Window
4054 child,
4055 root_window;
4056
4057 XWindowAttributes
4058 window_attributes;
4059
4060 /*
4061 Verify window is viewable.
4062 */
4063 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4064 assert(display != (Display *) NULL);
4065 status=XGetWindowAttributes(display,window,&window_attributes);
4066 if ((status == False) || (window_attributes.map_state != IsViewable))
4067 return((Image *) NULL);
4068 /*
4069 Cropping rectangle is relative to root window.
4070 */
4071 root_window=XRootWindow(display,XDefaultScreen(display));
4072 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4073 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004074 crop_info.x=(ssize_t) x_offset;
4075 crop_info.y=(ssize_t) y_offset;
4076 crop_info.width=(size_t) window_attributes.width;
4077 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004078 if (borders != MagickFalse)
4079 {
4080 /*
4081 Include border in image.
4082 */
cristybb503372010-05-27 20:51:26 +00004083 crop_info.x-=(ssize_t) window_attributes.border_width;
4084 crop_info.y-=(ssize_t) window_attributes.border_width;
4085 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4086 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004087 }
4088 /*
4089 Crop to root window.
4090 */
4091 if (crop_info.x < 0)
4092 {
4093 crop_info.width+=crop_info.x;
4094 crop_info.x=0;
4095 }
4096 if (crop_info.y < 0)
4097 {
4098 crop_info.height+=crop_info.y;
4099 crop_info.y=0;
4100 }
4101 display_width=XDisplayWidth(display,XDefaultScreen(display));
4102 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004103 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004104 display_height=XDisplayHeight(display,XDefaultScreen(display));
4105 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004106 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004107 /*
4108 Initialize window info attributes.
4109 */
4110 if (number_windows >= max_windows)
4111 {
4112 /*
4113 Allocate or resize window info buffer.
4114 */
4115 max_windows+=1024;
4116 if (window_info == (WindowInfo *) NULL)
4117 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4118 sizeof(*window_info));
4119 else
4120 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4121 max_windows,sizeof(*window_info));
4122 }
4123 if (window_info == (WindowInfo *) NULL)
4124 {
4125 ThrowXWindowFatalException(ResourceLimitError,
4126 "MemoryAllocationFailed","...");
4127 return((Image *) NULL);
4128 }
4129 id=number_windows++;
4130 window_info[id].window=window;
4131 window_info[id].visual=window_attributes.visual;
4132 window_info[id].colormap=window_attributes.colormap;
4133 window_info[id].bounds.x1=(short) crop_info.x;
4134 window_info[id].bounds.y1=(short) crop_info.y;
4135 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4136 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4137 crop_info.x-=x_offset;
4138 crop_info.y-=y_offset;
4139 window_info[id].crop_info=crop_info;
4140 if (level != 0)
4141 {
4142 unsigned int
4143 number_children;
4144
4145 Window
4146 *children;
4147
4148 /*
4149 Descend the window hierarchy.
4150 */
4151 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4152 &children,&number_children);
4153 for (i=0; i < id; i++)
4154 if ((window_info[i].window == window_info[id].parent) &&
4155 (window_info[i].visual == window_info[id].visual) &&
4156 (window_info[i].colormap == window_info[id].colormap))
4157 {
cristy64057b02013-01-11 00:09:58 +00004158 if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
4159 (window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
4160 (window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
4161 (window_info[id].bounds.y2 > window_info[i].bounds.y2))
cristy3ed852e2009-09-05 21:47:34 +00004162 {
4163 /*
4164 Eliminate windows not circumscribed by their parent.
4165 */
4166 number_windows--;
4167 break;
4168 }
4169 }
4170 if ((status == True) && (number_children != 0))
4171 {
4172 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004173 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4174 exception);
cristy3ed852e2009-09-05 21:47:34 +00004175 (void) XFree((void *) children);
4176 }
4177 }
4178 if (level <= 1)
4179 {
cristyc57f6942010-11-12 01:47:39 +00004180 CacheView
4181 *composite_view;
4182
cristy3ed852e2009-09-05 21:47:34 +00004183 ColormapInfo
4184 *next;
4185
cristy3ed852e2009-09-05 21:47:34 +00004186 Image
4187 *composite_image,
4188 *image;
4189
4190 int
4191 y;
4192
4193 MagickBooleanType
4194 import;
4195
4196 register int
4197 j,
4198 x;
4199
cristy4c08aed2011-07-01 19:47:50 +00004200 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004201 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004202
cristybb503372010-05-27 20:51:26 +00004203 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004204 pixel;
4205
4206 unsigned int
4207 number_colors;
4208
4209 XColor
4210 *colors;
4211
4212 XImage
4213 *ximage;
4214
4215 /*
4216 Get X image for each window in the list.
4217 */
4218 image=NewImageList();
4219 for (id=0; id < number_windows; id++)
4220 {
4221 /*
4222 Does target window intersect top level window?
4223 */
4224 import=
4225 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4226 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4227 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4228 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4229 MagickTrue : MagickFalse;
4230 /*
4231 Is target window contained by another window with the same colormap?
4232 */
4233 for (j=0; j < id; j++)
4234 if ((window_info[id].visual == window_info[j].visual) &&
4235 (window_info[id].colormap == window_info[j].colormap))
4236 {
cristy64057b02013-01-11 00:09:58 +00004237 if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
4238 (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
4239 (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
4240 (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
cristy3ed852e2009-09-05 21:47:34 +00004241 import=MagickFalse;
4242 }
cristy3ed852e2009-09-05 21:47:34 +00004243 if (import == MagickFalse)
4244 continue;
4245 /*
4246 Get X image.
4247 */
4248 ximage=XGetImage(display,window_info[id].window,(int)
4249 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4250 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4251 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4252 if (ximage == (XImage *) NULL)
4253 continue;
4254 /*
4255 Initialize window colormap.
4256 */
4257 number_colors=0;
4258 colors=(XColor *) NULL;
4259 if (window_info[id].colormap != (Colormap) NULL)
4260 {
4261 ColormapInfo
4262 *p;
4263
4264 /*
4265 Search colormap list for window colormap.
4266 */
4267 number_colors=(unsigned int) window_info[id].visual->map_entries;
4268 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4269 if (p->colormap == window_info[id].colormap)
4270 break;
4271 if (p == (ColormapInfo *) NULL)
4272 {
4273 /*
4274 Get the window colormap.
4275 */
4276 colors=(XColor *) AcquireQuantumMemory(number_colors,
4277 sizeof(*colors));
4278 if (colors == (XColor *) NULL)
4279 {
4280 XDestroyImage(ximage);
4281 return((Image *) NULL);
4282 }
4283 if ((window_info[id].visual->klass != DirectColor) &&
4284 (window_info[id].visual->klass != TrueColor))
4285 for (i=0; i < (int) number_colors; i++)
4286 {
cristybb503372010-05-27 20:51:26 +00004287 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004288 colors[i].pad='\0';
4289 }
4290 else
4291 {
cristybb503372010-05-27 20:51:26 +00004292 size_t
cristy3ed852e2009-09-05 21:47:34 +00004293 blue,
4294 blue_bit,
4295 green,
4296 green_bit,
4297 red,
4298 red_bit;
4299
4300 /*
4301 DirectColor or TrueColor visual.
4302 */
4303 red=0;
4304 green=0;
4305 blue=0;
4306 red_bit=window_info[id].visual->red_mask &
4307 (~(window_info[id].visual->red_mask)+1);
4308 green_bit=window_info[id].visual->green_mask &
4309 (~(window_info[id].visual->green_mask)+1);
4310 blue_bit=window_info[id].visual->blue_mask &
4311 (~(window_info[id].visual->blue_mask)+1);
4312 for (i=0; i < (int) number_colors; i++)
4313 {
cristy8891f9c2010-06-04 23:32:17 +00004314 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004315 colors[i].pad='\0';
4316 red+=red_bit;
4317 if (red > window_info[id].visual->red_mask)
4318 red=0;
4319 green+=green_bit;
4320 if (green > window_info[id].visual->green_mask)
4321 green=0;
4322 blue+=blue_bit;
4323 if (blue > window_info[id].visual->blue_mask)
4324 blue=0;
4325 }
4326 }
4327 (void) XQueryColors(display,window_info[id].colormap,colors,
4328 (int) number_colors);
4329 /*
4330 Append colormap to colormap list.
4331 */
cristy73bd4a52010-10-05 11:24:23 +00004332 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004333 if (p == (ColormapInfo *) NULL)
4334 return((Image *) NULL);
4335 p->colormap=window_info[id].colormap;
4336 p->colors=colors;
4337 p->next=colormap_info;
4338 colormap_info=p;
4339 }
4340 colors=p->colors;
4341 }
4342 /*
4343 Allocate image structure.
4344 */
cristy6710d842011-10-20 23:23:00 +00004345 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004346 if (composite_image == (Image *) NULL)
4347 {
4348 XDestroyImage(ximage);
4349 return((Image *) NULL);
4350 }
4351 /*
4352 Convert X image to MIFF format.
4353 */
4354 if ((window_info[id].visual->klass != TrueColor) &&
4355 (window_info[id].visual->klass != DirectColor))
4356 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004357 composite_image->columns=(size_t) ximage->width;
4358 composite_image->rows=(size_t) ximage->height;
cristy46ff2672012-12-14 15:32:26 +00004359 composite_view=AcquireAuthenticCacheView(composite_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00004360 switch (composite_image->storage_class)
4361 {
4362 case DirectClass:
4363 default:
4364 {
cristybb503372010-05-27 20:51:26 +00004365 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004366 color,
4367 index;
4368
cristybb503372010-05-27 20:51:26 +00004369 size_t
cristy3ed852e2009-09-05 21:47:34 +00004370 blue_mask,
4371 blue_shift,
4372 green_mask,
4373 green_shift,
4374 red_mask,
4375 red_shift;
4376
4377 /*
4378 Determine shift and mask for red, green, and blue.
4379 */
4380 red_mask=window_info[id].visual->red_mask;
4381 red_shift=0;
4382 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4383 {
4384 red_mask>>=1;
4385 red_shift++;
4386 }
4387 green_mask=window_info[id].visual->green_mask;
4388 green_shift=0;
4389 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4390 {
4391 green_mask>>=1;
4392 green_shift++;
4393 }
4394 blue_mask=window_info[id].visual->blue_mask;
4395 blue_shift=0;
4396 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4397 {
4398 blue_mask>>=1;
4399 blue_shift++;
4400 }
4401 /*
4402 Convert X image to DirectClass packets.
4403 */
4404 if ((number_colors != 0) &&
4405 (window_info[id].visual->klass == DirectColor))
4406 for (y=0; y < (int) composite_image->rows; y++)
4407 {
cristyc57f6942010-11-12 01:47:39 +00004408 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004409 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004410 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004411 break;
4412 for (x=0; x < (int) composite_image->columns; x++)
4413 {
4414 pixel=XGetPixel(ximage,x,y);
4415 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004416 SetPixelRed(composite_image,
4417 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004418 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004419 SetPixelGreen(composite_image,
4420 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004421 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004422 SetPixelBlue(composite_image,
4423 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004424 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004425 }
cristy0b1a7972011-10-22 22:17:02 +00004426 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4427 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004428 break;
4429 }
4430 else
4431 for (y=0; y < (int) composite_image->rows; y++)
4432 {
cristyc57f6942010-11-12 01:47:39 +00004433 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004434 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004435 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004436 break;
4437 for (x=0; x < (int) composite_image->columns; x++)
4438 {
4439 pixel=XGetPixel(ximage,x,y);
4440 color=(pixel >> red_shift) & red_mask;
4441 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004442 SetPixelRed(composite_image,
4443 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004444 color=(pixel >> green_shift) & green_mask;
4445 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004446 SetPixelGreen(composite_image,
4447 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004448 color=(pixel >> blue_shift) & blue_mask;
4449 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004450 SetPixelBlue(composite_image,
4451 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004452 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004453 }
cristy0b1a7972011-10-22 22:17:02 +00004454 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4455 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004456 break;
4457 }
4458 break;
4459 }
4460 case PseudoClass:
4461 {
4462 /*
4463 Create colormap.
4464 */
cristy0b1a7972011-10-22 22:17:02 +00004465 status=AcquireImageColormap(composite_image,number_colors,
4466 exception);
4467 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004468 {
4469 XDestroyImage(ximage);
4470 composite_image=DestroyImage(composite_image);
4471 return((Image *) NULL);
4472 }
4473 for (i=0; i < (int) composite_image->colors; i++)
4474 {
cristye42f6582012-02-11 17:59:50 +00004475 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004476 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004477 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004478 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004479 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004480 ScaleShortToQuantum(colors[i].blue);
4481 }
4482 /*
4483 Convert X image to PseudoClass packets.
4484 */
4485 for (y=0; y < (int) composite_image->rows; y++)
4486 {
cristyc57f6942010-11-12 01:47:39 +00004487 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4488 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004489 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004490 break;
cristy3ed852e2009-09-05 21:47:34 +00004491 for (x=0; x < (int) composite_image->columns; x++)
4492 {
cristy4c08aed2011-07-01 19:47:50 +00004493 index=(Quantum) XGetPixel(ximage,x,y);
4494 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004495 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004496 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004497 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004498 }
cristy0b1a7972011-10-22 22:17:02 +00004499 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4500 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004501 break;
4502 }
4503 break;
4504 }
4505 }
cristyc57f6942010-11-12 01:47:39 +00004506 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004507 XDestroyImage(ximage);
4508 if (image == (Image *) NULL)
4509 {
4510 image=composite_image;
4511 continue;
4512 }
4513 /*
4514 Composite any children in back-to-front order.
4515 */
4516 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4517 &x_offset,&y_offset,&child);
4518 x_offset-=(int) crop_info.x;
4519 if (x_offset < 0)
4520 x_offset=0;
4521 y_offset-=(int) crop_info.y;
4522 if (y_offset < 0)
4523 y_offset=0;
cristy39172402012-03-30 13:04:39 +00004524 (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00004525 (ssize_t) x_offset,(ssize_t) y_offset,exception);
cristy5f257b22012-03-07 00:27:29 +00004526 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004527 }
4528 /*
4529 Relinquish resources.
4530 */
4531 while (colormap_info != (ColormapInfo *) NULL)
4532 {
4533 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004534 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4535 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004536 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4537 colormap_info=next;
4538 }
4539 /*
4540 Relinquish resources and restore initial state.
4541 */
4542 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4543 max_windows=0;
4544 number_windows=0;
4545 colormap_info=(ColormapInfo *) NULL;
4546 return(image);
4547 }
4548 return((Image *) NULL);
4549}
4550
4551/*
4552%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4553% %
4554% %
4555% %
4556% X G e t W i n d o w I n f o %
4557% %
4558% %
4559% %
4560%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4561%
4562% XGetWindowInfo() initializes the XWindowInfo structure.
4563%
4564% The format of the XGetWindowInfo method is:
4565%
4566% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4567% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4568% XResourceInfo *resource_info,XWindowInfo *window)
4569% resource_info,window)
4570%
4571% A description of each parameter follows:
4572%
4573% o display: Specifies a connection to an X server; returned from
4574% XOpenDisplay.
4575%
4576% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4577% returned from XGetVisualInfo.
4578%
4579% o map_info: If map_type is specified, this structure is initialized
4580% with info from the Standard Colormap.
4581%
4582% o pixel: Specifies a pointer to a XPixelInfo structure.
4583%
4584% o font_info: Specifies a pointer to a XFontStruct structure.
4585%
4586% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4587%
4588*/
cristybcbda3f2011-09-03 13:01:22 +00004589MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004590 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4591 XResourceInfo *resource_info,XWindowInfo *window)
4592{
4593 /*
4594 Initialize window info.
4595 */
4596 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4597 assert(display != (Display *) NULL);
4598 assert(visual_info != (XVisualInfo *) NULL);
4599 assert(map_info != (XStandardColormap *) NULL);
4600 assert(pixel != (XPixelInfo *) NULL);
4601 assert(resource_info != (XResourceInfo *) NULL);
4602 assert(window != (XWindowInfo *) NULL);
4603 if (window->id != (Window) NULL)
4604 {
4605 if (window->cursor != (Cursor) NULL)
4606 (void) XFreeCursor(display,window->cursor);
4607 if (window->busy_cursor != (Cursor) NULL)
4608 (void) XFreeCursor(display,window->busy_cursor);
4609 if (window->highlight_stipple != (Pixmap) NULL)
4610 (void) XFreePixmap(display,window->highlight_stipple);
4611 if (window->shadow_stipple != (Pixmap) NULL)
4612 (void) XFreePixmap(display,window->shadow_stipple);
4613 if (window->name == (char *) NULL)
4614 window->name=AcquireString("");
4615 if (window->icon_name == (char *) NULL)
4616 window->icon_name=AcquireString("");
4617 }
4618 else
4619 {
4620 /*
4621 Initialize these attributes just once.
4622 */
4623 window->id=(Window) NULL;
4624 if (window->name == (char *) NULL)
4625 window->name=AcquireString("");
4626 if (window->icon_name == (char *) NULL)
4627 window->icon_name=AcquireString("");
4628 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4629 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4630 window->ximage=(XImage *) NULL;
4631 window->matte_image=(XImage *) NULL;
4632 window->pixmap=(Pixmap) NULL;
4633 window->matte_pixmap=(Pixmap) NULL;
4634 window->mapped=MagickFalse;
4635 window->stasis=MagickFalse;
4636 window->shared_memory=MagickTrue;
4637 window->segment_info=(void *) NULL;
4638#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4639 {
4640 XShmSegmentInfo
4641 *segment_info;
4642
4643 if (window->segment_info == (void *) NULL)
4644 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4645 segment_info=(XShmSegmentInfo *) window->segment_info;
4646 segment_info[0].shmid=(-1);
4647 segment_info[0].shmaddr=(char *) NULL;
4648 segment_info[1].shmid=(-1);
4649 segment_info[1].shmaddr=(char *) NULL;
4650 }
4651#endif
4652 }
4653 /*
4654 Initialize these attributes every time function is called.
4655 */
4656 window->screen=visual_info->screen;
4657 window->root=XRootWindow(display,visual_info->screen);
4658 window->visual=visual_info->visual;
4659 window->storage_class=(unsigned int) visual_info->klass;
4660 window->depth=(unsigned int) visual_info->depth;
4661 window->visual_info=visual_info;
4662 window->map_info=map_info;
4663 window->pixel_info=pixel;
4664 window->font_info=font_info;
4665 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4666 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4667 window->geometry=(char *) NULL;
4668 window->icon_geometry=(char *) NULL;
4669 if (resource_info->icon_geometry != (char *) NULL)
4670 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4671 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004672 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004673 window->width=1;
4674 window->height=1;
4675 window->min_width=1;
4676 window->min_height=1;
4677 window->width_inc=1;
4678 window->height_inc=1;
4679 window->border_width=resource_info->border_width;
4680 window->annotate_context=pixel->annotate_context;
4681 window->highlight_context=pixel->highlight_context;
4682 window->widget_context=pixel->widget_context;
4683 window->shadow_stipple=(Pixmap) NULL;
4684 window->highlight_stipple=(Pixmap) NULL;
4685 window->use_pixmap=MagickTrue;
4686 window->immutable=MagickFalse;
4687 window->shape=MagickFalse;
4688 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004689 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004690 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4691 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4692 window->attributes.background_pixel=pixel->background_color.pixel;
4693 window->attributes.background_pixmap=(Pixmap) NULL;
4694 window->attributes.bit_gravity=ForgetGravity;
4695 window->attributes.backing_store=WhenMapped;
4696 window->attributes.save_under=MagickTrue;
4697 window->attributes.border_pixel=pixel->border_color.pixel;
4698 window->attributes.colormap=map_info->colormap;
4699 window->attributes.cursor=window->cursor;
4700 window->attributes.do_not_propagate_mask=NoEventMask;
4701 window->attributes.event_mask=NoEventMask;
4702 window->attributes.override_redirect=MagickFalse;
4703 window->attributes.win_gravity=NorthWestGravity;
4704 window->orphan=MagickFalse;
4705}
4706
4707/*
4708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4709% %
4710% %
4711% %
4712% X H i g h l i g h t E l l i p s e %
4713% %
4714% %
4715% %
4716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4717%
4718% XHighlightEllipse() puts a border on the X server around a region defined by
4719% highlight_info.
4720%
4721% The format of the XHighlightEllipse method is:
4722%
4723% void XHighlightEllipse(Display *display,Window window,
4724% GC annotate_context,const RectangleInfo *highlight_info)
4725%
4726% A description of each parameter follows:
4727%
4728% o display: Specifies a connection to an X server; returned from
4729% XOpenDisplay.
4730%
4731% o window: Specifies a pointer to a Window structure.
4732%
4733% o annotate_context: Specifies a pointer to a GC structure.
4734%
4735% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4736% contains the extents of any highlighting rectangle.
4737%
4738*/
cristybcbda3f2011-09-03 13:01:22 +00004739MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004740 GC annotate_context,const RectangleInfo *highlight_info)
4741{
4742 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4743 assert(display != (Display *) NULL);
4744 assert(window != (Window) NULL);
4745 assert(annotate_context != (GC) NULL);
4746 assert(highlight_info != (RectangleInfo *) NULL);
4747 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4748 return;
4749 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4750 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4751 (unsigned int) highlight_info->height-1,0,360*64);
4752 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4753 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4754 (unsigned int) highlight_info->height-3,0,360*64);
4755}
4756
4757/*
4758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4759% %
4760% %
4761% %
4762% X H i g h l i g h t L i n e %
4763% %
4764% %
4765% %
4766%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4767%
4768% XHighlightLine() puts a border on the X server around a region defined by
4769% highlight_info.
4770%
4771% The format of the XHighlightLine method is:
4772%
4773% void XHighlightLine(Display *display,Window window,GC annotate_context,
4774% const XSegment *highlight_info)
4775%
4776% A description of each parameter follows:
4777%
4778% o display: Specifies a connection to an X server; returned from
4779% XOpenDisplay.
4780%
4781% o window: Specifies a pointer to a Window structure.
4782%
4783% o annotate_context: Specifies a pointer to a GC structure.
4784%
4785% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4786% contains the extents of any highlighting rectangle.
4787%
4788*/
cristybcbda3f2011-09-03 13:01:22 +00004789MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004790 GC annotate_context,const XSegment *highlight_info)
4791{
4792 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4793 assert(display != (Display *) NULL);
4794 assert(window != (Window) NULL);
4795 assert(annotate_context != (GC) NULL);
4796 assert(highlight_info != (XSegment *) NULL);
4797 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4798 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4799}
4800
4801/*
4802%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4803% %
4804% %
4805% %
4806% X H i g h l i g h t R e c t a n g l e %
4807% %
4808% %
4809% %
4810%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4811%
4812% XHighlightRectangle() puts a border on the X server around a region defined
4813% by highlight_info.
4814%
4815% The format of the XHighlightRectangle method is:
4816%
4817% void XHighlightRectangle(Display *display,Window window,
4818% GC annotate_context,const RectangleInfo *highlight_info)
4819%
4820% A description of each parameter follows:
4821%
4822% o display: Specifies a connection to an X server; returned from
4823% XOpenDisplay.
4824%
4825% o window: Specifies a pointer to a Window structure.
4826%
4827% o annotate_context: Specifies a pointer to a GC structure.
4828%
4829% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4830% contains the extents of any highlighting rectangle.
4831%
4832*/
cristybcbda3f2011-09-03 13:01:22 +00004833MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004834 GC annotate_context,const RectangleInfo *highlight_info)
4835{
4836 assert(display != (Display *) NULL);
4837 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4838 assert(window != (Window) NULL);
4839 assert(annotate_context != (GC) NULL);
4840 assert(highlight_info != (RectangleInfo *) NULL);
4841 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4842 return;
4843 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4844 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4845 (unsigned int) highlight_info->height-1);
4846 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4847 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4848 (unsigned int) highlight_info->height-3);
4849}
4850
4851/*
4852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4853% %
4854% %
4855% %
4856% X I m p o r t I m a g e %
4857% %
4858% %
4859% %
4860%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4861%
4862% XImportImage() reads an image from an X window.
4863%
4864% The format of the XImportImage method is:
4865%
cristy6710d842011-10-20 23:23:00 +00004866% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4867% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004868%
4869% A description of each parameter follows:
4870%
4871% o image_info: the image info.
4872%
4873% o ximage_info: Specifies a pointer to an XImportInfo structure.
4874%
cristy6710d842011-10-20 23:23:00 +00004875% o exception: return any errors or warnings in this structure.
4876%
cristy3ed852e2009-09-05 21:47:34 +00004877*/
4878MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004879 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004880{
4881 Colormap
4882 *colormaps;
4883
4884 Display
4885 *display;
4886
4887 Image
4888 *image;
4889
4890 int
4891 number_colormaps,
4892 number_windows,
4893 x;
4894
4895 RectangleInfo
4896 crop_info;
4897
4898 Status
4899 status;
4900
4901 Window
4902 *children,
4903 client,
4904 prior_target,
4905 root,
4906 target;
4907
4908 XTextProperty
4909 window_name;
4910
4911 /*
4912 Open X server connection.
4913 */
4914 assert(image_info != (const ImageInfo *) NULL);
4915 assert(image_info->signature == MagickSignature);
4916 if (image_info->debug != MagickFalse)
4917 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4918 image_info->filename);
4919 assert(ximage_info != (XImportInfo *) NULL);
4920 display=XOpenDisplay(image_info->server_name);
4921 if (display == (Display *) NULL)
4922 {
4923 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4924 XDisplayName(image_info->server_name));
4925 return((Image *) NULL);
4926 }
4927 /*
4928 Set our forgiving exception handler.
4929 */
4930 (void) XSetErrorHandler(XError);
4931 /*
4932 Select target window.
4933 */
4934 crop_info.x=0;
4935 crop_info.y=0;
4936 crop_info.width=0;
4937 crop_info.height=0;
4938 root=XRootWindow(display,XDefaultScreen(display));
4939 target=(Window) NULL;
4940 if ((image_info->filename != (char *) NULL) &&
4941 (*image_info->filename != '\0'))
4942 {
4943 if (LocaleCompare(image_info->filename,"root") == 0)
4944 target=root;
4945 else
4946 {
4947 /*
4948 Select window by ID or name.
4949 */
4950 if (isdigit((unsigned char) *image_info->filename) != 0)
4951 target=XWindowByID(display,root,(Window)
4952 strtol(image_info->filename,(char **) NULL,0));
4953 if (target == (Window) NULL)
4954 target=XWindowByName(display,root,image_info->filename);
4955 if (target == (Window) NULL)
4956 ThrowXWindowFatalException(XServerError,
4957 "NoWindowWithSpecifiedIDExists",image_info->filename);
4958 }
4959 }
4960 /*
4961 If target window is not defined, interactively select one.
4962 */
4963 prior_target=target;
4964 if (target == (Window) NULL)
4965 target=XSelectWindow(display,&crop_info);
4966 if (target == (Window) NULL)
4967 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4968 image_info->filename);
4969 client=target; /* obsolete */
4970 if (target != root)
4971 {
4972 unsigned int
4973 d;
4974
4975 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4976 if (status != False)
4977 {
4978 for ( ; ; )
4979 {
4980 Window
4981 parent;
4982
4983 /*
4984 Find window manager frame.
4985 */
4986 status=XQueryTree(display,target,&root,&parent,&children,&d);
4987 if ((status != False) && (children != (Window *) NULL))
4988 (void) XFree((char *) children);
4989 if ((status == False) || (parent == (Window) NULL) ||
4990 (parent == root))
4991 break;
4992 target=parent;
4993 }
4994 /*
4995 Get client window.
4996 */
4997 client=XClientWindow(display,target);
4998 if (ximage_info->frame == MagickFalse)
4999 target=client;
5000 if ((ximage_info->frame == MagickFalse) &&
5001 (prior_target != MagickFalse))
5002 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00005003 }
5004 }
5005 if (ximage_info->screen)
5006 {
5007 int
5008 y;
5009
5010 Window
5011 child;
5012
5013 XWindowAttributes
5014 window_attributes;
5015
5016 /*
5017 Obtain window image directly from screen.
5018 */
5019 status=XGetWindowAttributes(display,target,&window_attributes);
5020 if (status == False)
5021 {
5022 ThrowXWindowFatalException(XServerError,
5023 "UnableToReadXWindowAttributes",image_info->filename);
5024 (void) XCloseDisplay(display);
5025 return((Image *) NULL);
5026 }
5027 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005028 crop_info.x=(ssize_t) x;
5029 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005030 crop_info.width=(size_t) window_attributes.width;
5031 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005032 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005033 {
5034 /*
5035 Include border in image.
5036 */
5037 crop_info.x-=window_attributes.border_width;
5038 crop_info.y-=window_attributes.border_width;
5039 crop_info.width+=window_attributes.border_width << 1;
5040 crop_info.height+=window_attributes.border_width << 1;
5041 }
5042 target=root;
5043 }
5044 /*
5045 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5046 */
5047 number_windows=0;
5048 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5049 if ((status == True) && (number_windows > 0))
5050 {
5051 ximage_info->descend=MagickTrue;
5052 (void) XFree ((char *) children);
5053 }
5054 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5055 if (number_colormaps > 0)
5056 {
5057 if (number_colormaps > 1)
5058 ximage_info->descend=MagickTrue;
5059 (void) XFree((char *) colormaps);
5060 }
5061 /*
5062 Alert the user not to alter the screen.
5063 */
5064 if (ximage_info->silent == MagickFalse)
5065 (void) XBell(display,0);
5066 /*
5067 Get image by window id.
5068 */
5069 (void) XGrabServer(display);
5070 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005071 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005072 (void) XUngrabServer(display);
5073 if (image == (Image *) NULL)
5074 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5075 image_info->filename)
5076 else
5077 {
5078 (void) CopyMagickString(image->filename,image_info->filename,
5079 MaxTextExtent);
5080 if ((crop_info.width != 0) && (crop_info.height != 0))
5081 {
5082 Image
5083 *clone_image,
5084 *crop_image;
5085
5086 /*
5087 Crop image as defined by the cropping rectangle.
5088 */
cristy6710d842011-10-20 23:23:00 +00005089 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005090 if (clone_image != (Image *) NULL)
5091 {
cristy6710d842011-10-20 23:23:00 +00005092 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005093 if (crop_image != (Image *) NULL)
5094 {
5095 image=DestroyImage(image);
5096 image=crop_image;
5097 }
5098 }
5099 }
5100 status=XGetWMName(display,target,&window_name);
5101 if (status == True)
5102 {
5103 if ((image_info->filename != (char *) NULL) &&
5104 (*image_info->filename == '\0'))
5105 (void) CopyMagickString(image->filename,(char *) window_name.value,
5106 (size_t) window_name.nitems+1);
5107 (void) XFree((void *) window_name.value);
5108 }
5109 }
5110 if (ximage_info->silent == MagickFalse)
5111 {
5112 /*
5113 Alert the user we're done.
5114 */
5115 (void) XBell(display,0);
5116 (void) XBell(display,0);
5117 }
5118 (void) XCloseDisplay(display);
5119 return(image);
5120}
5121
5122/*
5123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5124% %
5125% %
5126% %
5127% X I n i t i a l i z e W i n d o w s %
5128% %
5129% %
5130% %
5131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5132%
5133% XInitializeWindows() initializes the XWindows structure.
5134%
5135% The format of the XInitializeWindows method is:
5136%
5137% XWindows *XInitializeWindows(Display *display,
5138% XResourceInfo *resource_info)
5139%
5140% A description of each parameter follows:
5141%
5142% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5143%
5144% o display: Specifies a connection to an X server; returned from
5145% XOpenDisplay.
5146%
5147% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5148%
5149*/
cristybcbda3f2011-09-03 13:01:22 +00005150MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005151 XResourceInfo *resource_info)
5152{
5153 Window
5154 root_window;
5155
5156 XWindows
5157 *windows;
5158
5159 /*
5160 Allocate windows structure.
5161 */
cristy73bd4a52010-10-05 11:24:23 +00005162 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005163 if (windows == (XWindows *) NULL)
5164 {
5165 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5166 "...");
5167 return((XWindows *) NULL);
5168 }
5169 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5170 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5171 sizeof(*windows->pixel_info));
5172 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5173 sizeof(*windows->icon_pixel));
5174 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5175 sizeof(*windows->icon_resources));
5176 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5177 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5178 (windows->icon_resources == (XResourceInfo *) NULL))
5179 {
5180 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5181 "...");
5182 return((XWindows *) NULL);
5183 }
5184 /*
5185 Initialize windows structure.
5186 */
5187 windows->display=display;
5188 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5189 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5190 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5191 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5192 windows->im_remote_command=
5193 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5194 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5195 windows->im_update_colormap=
5196 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5197 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5198 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5199 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5200 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5201 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005202#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005203 (void) XSynchronize(display,IsWindows95());
5204#endif
5205 if (IsEventLogging())
5206 {
5207 (void) XSynchronize(display,MagickTrue);
5208 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005209 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005210 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5211 (void) LogMagickEvent(X11Event,GetMagickModule(),
5212 " Window Manager: 0x%lx",windows->wm_protocols);
5213 (void) LogMagickEvent(X11Event,GetMagickModule(),
5214 " delete window: 0x%lx",windows->wm_delete_window);
5215 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5216 windows->wm_take_focus);
5217 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5218 windows->im_protocols);
5219 (void) LogMagickEvent(X11Event,GetMagickModule(),
5220 " remote command: 0x%lx",windows->im_remote_command);
5221 (void) LogMagickEvent(X11Event,GetMagickModule(),
5222 " update widget: 0x%lx",windows->im_update_widget);
5223 (void) LogMagickEvent(X11Event,GetMagickModule(),
5224 " update colormap: 0x%lx",windows->im_update_colormap);
5225 (void) LogMagickEvent(X11Event,GetMagickModule(),
5226 " former image: 0x%lx",windows->im_former_image);
5227 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5228 windows->im_next_image);
5229 (void) LogMagickEvent(X11Event,GetMagickModule(),
5230 " retain colors: 0x%lx",windows->im_retain_colors);
5231 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5232 windows->im_exit);
5233 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5234 windows->dnd_protocols);
5235 }
5236 /*
5237 Allocate standard colormap.
5238 */
5239 windows->map_info=XAllocStandardColormap();
5240 windows->icon_map=XAllocStandardColormap();
5241 if ((windows->map_info == (XStandardColormap *) NULL) ||
5242 (windows->icon_map == (XStandardColormap *) NULL))
5243 ThrowXWindowFatalException(ResourceLimitFatalError,
5244 "MemoryAllocationFailed","...");
5245 windows->map_info->colormap=(Colormap) NULL;
5246 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005247 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005248 windows->pixel_info->annotate_context=(GC) NULL;
5249 windows->pixel_info->highlight_context=(GC) NULL;
5250 windows->pixel_info->widget_context=(GC) NULL;
5251 windows->font_info=(XFontStruct *) NULL;
5252 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005253 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005254 /*
5255 Allocate visual.
5256 */
5257 *windows->icon_resources=(*resource_info);
5258 windows->icon_resources->visual_type=(char *) "default";
5259 windows->icon_resources->colormap=SharedColormap;
5260 windows->visual_info=
5261 XBestVisualInfo(display,windows->map_info,resource_info);
5262 windows->icon_visual=
5263 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5264 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5265 (windows->icon_visual == (XVisualInfo *) NULL))
5266 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5267 resource_info->visual_type);
5268 if (IsEventLogging())
5269 {
5270 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5271 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5272 windows->visual_info->visualid);
5273 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5274 XVisualClassName(windows->visual_info->klass));
5275 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5276 windows->visual_info->depth);
5277 (void) LogMagickEvent(X11Event,GetMagickModule(),
5278 " size of colormap: %d entries",windows->visual_info->colormap_size);
5279 (void) LogMagickEvent(X11Event,GetMagickModule(),
5280 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5281 windows->visual_info->red_mask,windows->visual_info->green_mask,
5282 windows->visual_info->blue_mask);
5283 (void) LogMagickEvent(X11Event,GetMagickModule(),
5284 " significant bits in color: %d bits",
5285 windows->visual_info->bits_per_rgb);
5286 }
5287 /*
5288 Allocate class and manager hints.
5289 */
5290 windows->class_hints=XAllocClassHint();
5291 windows->manager_hints=XAllocWMHints();
5292 if ((windows->class_hints == (XClassHint *) NULL) ||
5293 (windows->manager_hints == (XWMHints *) NULL))
5294 ThrowXWindowFatalException(ResourceLimitFatalError,
5295 "MemoryAllocationFailed","...");
5296 /*
5297 Determine group leader if we have one.
5298 */
5299 root_window=XRootWindow(display,windows->visual_info->screen);
5300 windows->group_leader.id=(Window) NULL;
5301 if (resource_info->window_group != (char *) NULL)
5302 {
5303 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5304 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5305 strtol((char *) resource_info->window_group,(char **) NULL,0));
5306 if (windows->group_leader.id == (Window) NULL)
5307 windows->group_leader.id=
5308 XWindowByName(display,root_window,resource_info->window_group);
5309 }
5310 return(windows);
5311}
5312
5313/*
5314%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5315% %
5316% %
5317% %
5318% X M a k e C u r s o r %
5319% %
5320% %
5321% %
5322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5323%
5324% XMakeCursor() creates a crosshairs X11 cursor.
5325%
5326% The format of the XMakeCursor method is:
5327%
5328% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5329% char *background_color,char *foreground_color)
5330%
5331% A description of each parameter follows:
5332%
5333% o display: Specifies a connection to an X server; returned from
5334% XOpenDisplay.
5335%
5336% o window: Specifies the ID of the window for which the cursor is
5337% assigned.
5338%
5339% o colormap: Specifies the ID of the colormap from which the background
5340% and foreground color will be retrieved.
5341%
5342% o background_color: Specifies the color to use for the cursor background.
5343%
5344% o foreground_color: Specifies the color to use for the cursor foreground.
5345%
5346*/
cristybcbda3f2011-09-03 13:01:22 +00005347MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005348 Colormap colormap,char *background_color,char *foreground_color)
5349{
5350#define scope_height 17
5351#define scope_x_hot 8
5352#define scope_y_hot 8
5353#define scope_width 17
5354
5355 static const unsigned char
5356 scope_bits[] =
5357 {
5358 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5359 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5360 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5361 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5362 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5363 },
5364 scope_mask_bits[] =
5365 {
5366 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5367 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5368 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5369 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5370 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5371 };
5372
5373 Cursor
5374 cursor;
5375
5376 Pixmap
5377 mask,
5378 source;
5379
5380 XColor
5381 background,
5382 foreground;
5383
5384 assert(display != (Display *) NULL);
5385 assert(window != (Window) NULL);
5386 assert(colormap != (Colormap) NULL);
5387 assert(background_color != (char *) NULL);
5388 assert(foreground_color != (char *) NULL);
5389 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5390 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5391 scope_height);
5392 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5393 scope_width,scope_height);
5394 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5395 {
5396 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5397 return((Cursor) NULL);
5398 }
5399 (void) XParseColor(display,colormap,background_color,&background);
5400 (void) XParseColor(display,colormap,foreground_color,&foreground);
5401 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5402 scope_x_hot,scope_y_hot);
5403 (void) XFreePixmap(display,source);
5404 (void) XFreePixmap(display,mask);
5405 return(cursor);
5406}
5407
5408/*
5409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5410% %
5411% %
5412% %
5413% X M a k e I m a g e %
5414% %
5415% %
5416% %
5417%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5418%
5419% XMakeImage() creates an X11 image. If the image size differs from the X11
5420% image size, the image is first resized.
5421%
5422% The format of the XMakeImage method is:
5423%
5424% MagickBooleanType XMakeImage(Display *display,
5425% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005426% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005427%
5428% A description of each parameter follows:
5429%
5430% o display: Specifies a connection to an X server; returned from
5431% XOpenDisplay.
5432%
5433% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5434%
5435% o window: Specifies a pointer to a XWindowInfo structure.
5436%
5437% o image: the image.
5438%
5439% o width: Specifies the width in pixels of the rectangular area to
5440% display.
5441%
5442% o height: Specifies the height in pixels of the rectangular area to
5443% display.
5444%
cristy051718b2011-08-28 22:49:25 +00005445% o exception: return any errors or warnings in this structure.
5446%
cristy3ed852e2009-09-05 21:47:34 +00005447*/
cristybcbda3f2011-09-03 13:01:22 +00005448MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005449 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005450 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005451{
5452#define CheckOverflowException(length,width,height) \
5453 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5454
5455 int
5456 depth,
5457 format;
5458
5459 size_t
5460 length;
5461
5462 XImage
5463 *matte_image,
5464 *ximage;
5465
5466 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5467 assert(display != (Display *) NULL);
5468 assert(resource_info != (XResourceInfo *) NULL);
5469 assert(window != (XWindowInfo *) NULL);
5470 assert(width != 0);
5471 assert(height != 0);
5472 if ((window->width == 0) || (window->height == 0))
5473 return(MagickFalse);
5474 /*
5475 Apply user transforms to the image.
5476 */
5477 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5478 (void) XFlush(display);
5479 depth=(int) window->depth;
5480 if (window->destroy)
5481 window->image=DestroyImage(window->image);
5482 window->image=image;
5483 window->destroy=MagickFalse;
5484 if (window->image != (Image *) NULL)
5485 {
5486 if (window->crop_geometry != (char *) NULL)
5487 {
5488 Image
5489 *crop_image;
5490
5491 RectangleInfo
5492 crop_info;
5493
5494 /*
5495 Crop image.
5496 */
5497 window->image->page.x=0;
5498 window->image->page.y=0;
5499 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005500 &crop_info,exception);
5501 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005502 if (crop_image != (Image *) NULL)
5503 {
5504 if (window->image != image)
5505 window->image=DestroyImage(window->image);
5506 window->image=crop_image;
5507 window->destroy=MagickTrue;
5508 }
5509 }
5510 if ((width != (unsigned int) window->image->columns) ||
5511 (height != (unsigned int) window->image->rows))
5512 {
5513 Image
5514 *resize_image;
5515
5516 /*
5517 Resize image.
5518 */
5519 resize_image=NewImageList();
5520 if (window->pixel_info->colors != 0)
cristy6710d842011-10-20 23:23:00 +00005521 resize_image=SampleImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005522 else
cristy6710d842011-10-20 23:23:00 +00005523 resize_image=ThumbnailImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005524 if (resize_image != (Image *) NULL)
5525 {
5526 if (window->image != image)
5527 window->image=DestroyImage(window->image);
5528 window->image=resize_image;
5529 window->destroy=MagickTrue;
5530 }
5531 }
5532 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005533 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005534 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005535 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005536 }
5537 /*
5538 Create X image.
5539 */
5540 ximage=(XImage *) NULL;
5541 format=(depth == 1) ? XYBitmap : ZPixmap;
5542#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5543 if (window->shared_memory != MagickFalse)
5544 {
5545 XShmSegmentInfo
5546 *segment_info;
5547
5548 segment_info=(XShmSegmentInfo *) window->segment_info;
5549 segment_info[1].shmid=(-1);
5550 segment_info[1].shmaddr=(char *) NULL;
5551 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5552 (char *) NULL,&segment_info[1],width,height);
5553 if (ximage == (XImage *) NULL)
5554 window->shared_memory=MagickFalse;
5555 length=(size_t) ximage->bytes_per_line*ximage->height;
5556 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5557 window->shared_memory=MagickFalse;
5558 if (window->shared_memory != MagickFalse)
5559 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5560 if (window->shared_memory != MagickFalse)
5561 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5562 if (segment_info[1].shmid < 0)
5563 window->shared_memory=MagickFalse;
5564 if (window->shared_memory != MagickFalse)
5565 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5566 else
5567 {
5568 if (ximage != (XImage *) NULL)
5569 XDestroyImage(ximage);
5570 ximage=(XImage *) NULL;
5571 if (segment_info[1].shmaddr)
5572 {
5573 (void) shmdt(segment_info[1].shmaddr);
5574 segment_info[1].shmaddr=(char *) NULL;
5575 }
5576 if (segment_info[1].shmid >= 0)
5577 {
5578 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5579 segment_info[1].shmid=(-1);
5580 }
5581 }
5582 }
5583#endif
5584 /*
5585 Allocate X image pixel data.
5586 */
5587#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5588 if (window->shared_memory)
5589 {
5590 Status
5591 status;
5592
5593 XShmSegmentInfo
5594 *segment_info;
5595
5596 (void) XSync(display,MagickFalse);
5597 xerror_alert=MagickFalse;
5598 segment_info=(XShmSegmentInfo *) window->segment_info;
5599 ximage->data=segment_info[1].shmaddr;
5600 segment_info[1].readOnly=MagickFalse;
5601 status=XShmAttach(display,&segment_info[1]);
5602 if (status != False)
5603 (void) XSync(display,MagickFalse);
5604 if ((status == False) || (xerror_alert != MagickFalse))
5605 {
5606 window->shared_memory=MagickFalse;
5607 if (status != False)
5608 XShmDetach(display,&segment_info[1]);
5609 if (ximage != (XImage *) NULL)
5610 {
5611 ximage->data=NULL;
5612 XDestroyImage(ximage);
5613 ximage=(XImage *) NULL;
5614 }
5615 if (segment_info[1].shmid >= 0)
5616 {
5617 if (segment_info[1].shmaddr != NULL)
5618 (void) shmdt(segment_info[1].shmaddr);
5619 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5620 segment_info[1].shmid=(-1);
5621 segment_info[1].shmaddr=(char *) NULL;
5622 }
5623 }
5624 }
5625#endif
5626 if (window->shared_memory == MagickFalse)
5627 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5628 (char *) NULL,width,height,XBitmapPad(display),0);
5629 if (ximage == (XImage *) NULL)
5630 {
5631 /*
5632 Unable to create X image.
5633 */
5634 (void) XCheckDefineCursor(display,window->id,window->cursor);
5635 return(MagickFalse);
5636 }
5637 length=(size_t) ximage->bytes_per_line*ximage->height;
5638 if (IsEventLogging())
5639 {
5640 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5641 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5642 ximage->width,ximage->height);
5643 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5644 ximage->format);
5645 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5646 ximage->byte_order);
5647 (void) LogMagickEvent(X11Event,GetMagickModule(),
5648 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5649 ximage->bitmap_bit_order,ximage->bitmap_pad);
5650 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5651 ximage->depth);
5652 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5653 ximage->bytes_per_line);
5654 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5655 ximage->bits_per_pixel);
5656 (void) LogMagickEvent(X11Event,GetMagickModule(),
5657 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5658 ximage->green_mask,ximage->blue_mask);
5659 }
5660 if (window->shared_memory == MagickFalse)
5661 {
5662 if (ximage->format != XYBitmap)
5663 ximage->data=(char *) AcquireQuantumMemory((size_t)
5664 ximage->bytes_per_line,(size_t) ximage->height);
5665 else
5666 ximage->data=(char *) AcquireQuantumMemory((size_t)
5667 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5668 }
5669 if (ximage->data == (char *) NULL)
5670 {
5671 /*
5672 Unable to allocate pixel data.
5673 */
5674 XDestroyImage(ximage);
5675 ximage=(XImage *) NULL;
5676 (void) XCheckDefineCursor(display,window->id,window->cursor);
5677 return(MagickFalse);
5678 }
5679 if (window->ximage != (XImage *) NULL)
5680 {
5681 /*
5682 Destroy previous X image.
5683 */
5684 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5685#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5686 if (window->segment_info != (XShmSegmentInfo *) NULL)
5687 {
5688 XShmSegmentInfo
5689 *segment_info;
5690
5691 segment_info=(XShmSegmentInfo *) window->segment_info;
5692 if (segment_info[0].shmid >= 0)
5693 {
5694 (void) XSync(display,MagickFalse);
5695 (void) XShmDetach(display,&segment_info[0]);
5696 (void) XSync(display,MagickFalse);
5697 if (segment_info[0].shmaddr != (char *) NULL)
5698 (void) shmdt(segment_info[0].shmaddr);
5699 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5700 segment_info[0].shmid=(-1);
5701 segment_info[0].shmaddr=(char *) NULL;
5702 window->ximage->data=(char *) NULL;
5703 }
5704 }
5705#endif
5706 if (window->ximage->data != (char *) NULL)
5707 free(window->ximage->data);
5708 window->ximage->data=(char *) NULL;
5709 XDestroyImage(window->ximage);
5710 window->ximage=(XImage *) NULL;
5711 }
5712#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5713 if (window->segment_info != (XShmSegmentInfo *) NULL)
5714 {
5715 XShmSegmentInfo
5716 *segment_info;
5717
5718 segment_info=(XShmSegmentInfo *) window->segment_info;
5719 segment_info[0]=segment_info[1];
5720 }
5721#endif
5722 window->ximage=ximage;
5723 matte_image=(XImage *) NULL;
5724 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
cristy8a46d822012-08-28 23:32:39 +00005725 if ((window->image->alpha_trait == BlendPixelTrait) &&
cristyc57f6942010-11-12 01:47:39 +00005726 ((int) width <= XDisplayWidth(display,window->screen)) &&
5727 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005728 {
5729 /*
5730 Create matte image.
5731 */
5732 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5733 (char *) NULL,width,height,XBitmapPad(display),0);
5734 if (IsEventLogging())
5735 {
5736 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5737 (void) LogMagickEvent(X11Event,GetMagickModule(),
5738 " width, height: %dx%d",matte_image->width,matte_image->height);
5739 }
5740 if (matte_image != (XImage *) NULL)
5741 {
5742 /*
5743 Allocate matte image pixel data.
5744 */
5745 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5746 matte_image->bytes_per_line*matte_image->depth,
5747 (size_t) matte_image->height);
5748 if (matte_image->data == (char *) NULL)
5749 {
5750 XDestroyImage(matte_image);
5751 matte_image=(XImage *) NULL;
5752 }
5753 }
5754 }
5755 if (window->matte_image != (XImage *) NULL)
5756 {
5757 /*
5758 Free matte image.
5759 */
5760 if (window->matte_image->data != (char *) NULL)
5761 free(window->matte_image->data);
5762 window->matte_image->data=(char *) NULL;
5763 XDestroyImage(window->matte_image);
5764 window->matte_image=(XImage *) NULL;
5765 }
5766 window->matte_image=matte_image;
5767 if (window->matte_pixmap != (Pixmap) NULL)
5768 {
5769 (void) XFreePixmap(display,window->matte_pixmap);
5770 window->matte_pixmap=(Pixmap) NULL;
5771#if defined(MAGICKCORE_HAVE_SHAPE)
5772 if (window->shape != MagickFalse)
5773 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5774#endif
5775 }
5776 window->stasis=MagickFalse;
5777 /*
5778 Convert pixels to X image data.
5779 */
5780 if (window->image != (Image *) NULL)
5781 {
5782 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5783 (ximage->bitmap_bit_order == LSBFirst)))
5784 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005785 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005786 else
5787 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005788 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005789 }
5790 if (window->matte_image != (XImage *) NULL)
5791 {
5792 /*
5793 Create matte pixmap.
5794 */
5795 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5796 if (window->matte_pixmap != (Pixmap) NULL)
5797 {
5798 GC
5799 graphics_context;
5800
5801 XGCValues
5802 context_values;
5803
5804 /*
5805 Copy matte image to matte pixmap.
5806 */
cristy4c08aed2011-07-01 19:47:50 +00005807 context_values.background=0;
5808 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005809 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005810 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005811 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5812 window->matte_image,0,0,0,0,width,height);
5813 (void) XFreeGC(display,graphics_context);
5814#if defined(MAGICKCORE_HAVE_SHAPE)
5815 if (window->shape != MagickFalse)
5816 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5817 window->matte_pixmap,ShapeSet);
5818#endif
5819 }
5820 }
5821 (void) XMakePixmap(display,resource_info,window);
5822 /*
5823 Restore cursor.
5824 */
5825 (void) XCheckDefineCursor(display,window->id,window->cursor);
5826 return(MagickTrue);
5827}
5828
5829/*
5830%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5831% %
5832% %
5833% %
5834+ X M a k e I m a g e L S B F i r s t %
5835% %
5836% %
5837% %
5838%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5839%
5840% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5841% pixels are copied in least-significant bit and byte first order. The
5842% server's scanline pad is respected. Rather than using one or two general
5843% cases, many special cases are found here to help speed up the image
5844% conversion.
5845%
5846% The format of the XMakeImageLSBFirst method is:
5847%
cristye941a752011-10-15 01:52:48 +00005848% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5849% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005850%
5851% A description of each parameter follows:
5852%
5853% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5854%
5855% o window: Specifies a pointer to a XWindowInfo structure.
5856%
5857% o image: the image.
5858%
5859% o ximage: Specifies a pointer to a XImage structure; returned from
5860% XCreateImage.
5861%
5862% o matte_image: Specifies a pointer to a XImage structure; returned from
5863% XCreateImage.
5864%
cristye941a752011-10-15 01:52:48 +00005865% o exception: return any errors or warnings in this structure.
5866%
cristy3ed852e2009-09-05 21:47:34 +00005867*/
5868static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005869 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5870 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005871{
cristyc57f6942010-11-12 01:47:39 +00005872 CacheView
5873 *canvas_view;
5874
cristy3ed852e2009-09-05 21:47:34 +00005875 Image
5876 *canvas;
5877
5878 int
5879 y;
5880
cristy4c08aed2011-07-01 19:47:50 +00005881 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005882 *p;
5883
5884 register int
5885 x;
5886
5887 register unsigned char
5888 *q;
5889
5890 unsigned char
5891 bit,
5892 byte;
5893
5894 unsigned int
5895 scanline_pad;
5896
cristyf2faecf2010-05-28 19:19:36 +00005897 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005898 pixel,
5899 *pixels;
5900
5901 XStandardColormap
5902 *map_info;
5903
5904 assert(resource_info != (XResourceInfo *) NULL);
5905 assert(window != (XWindowInfo *) NULL);
5906 assert(image != (Image *) NULL);
5907 if (image->debug != MagickFalse)
5908 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5909 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005910 if ((window->immutable == MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00005911 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00005912 {
5913 char
5914 size[MaxTextExtent];
5915
5916 Image
5917 *pattern;
5918
5919 ImageInfo
5920 *image_info;
5921
5922 image_info=AcquireImageInfo();
5923 (void) CopyMagickString(image_info->filename,
5924 resource_info->image_info->texture != (char *) NULL ?
5925 resource_info->image_info->texture : "pattern:checkerboard",
5926 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005927 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005928 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005929 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005930 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005931 image_info=DestroyImageInfo(image_info);
5932 if (pattern != (Image *) NULL)
5933 {
cristy6710d842011-10-20 23:23:00 +00005934 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005935 if (canvas != (Image *) NULL)
cristy39172402012-03-30 13:04:39 +00005936 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00005937 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00005938 pattern=DestroyImage(pattern);
5939 }
5940 }
5941 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5942 ximage->bits_per_pixel) >> 3));
5943 map_info=window->map_info;
5944 pixels=window->pixel_info->pixels;
5945 q=(unsigned char *) ximage->data;
5946 x=0;
cristy46ff2672012-12-14 15:32:26 +00005947 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00005948 if (ximage->format == XYBitmap)
5949 {
5950 register unsigned short
5951 polarity;
5952
5953 unsigned char
5954 background,
5955 foreground;
5956
5957 /*
5958 Convert canvas to big-endian bitmap.
5959 */
5960 background=(unsigned char)
5961 (XPixelIntensity(&window->pixel_info->foreground_color) <
5962 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5963 foreground=(unsigned char)
5964 (XPixelIntensity(&window->pixel_info->background_color) <
5965 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005966 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00005967 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00005968 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005969 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5970 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005971 for (y=0; y < (int) canvas->rows; y++)
5972 {
cristyc57f6942010-11-12 01:47:39 +00005973 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005974 exception);
cristy4c08aed2011-07-01 19:47:50 +00005975 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005976 break;
cristy3ed852e2009-09-05 21:47:34 +00005977 bit=0;
5978 byte=0;
5979 for (x=0; x < (int) canvas->columns; x++)
5980 {
5981 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005982 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005983 byte|=foreground;
5984 else
5985 byte|=background;
5986 bit++;
5987 if (bit == 8)
5988 {
5989 *q++=byte;
5990 bit=0;
5991 byte=0;
5992 }
cristyed231572011-07-14 02:18:59 +00005993 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005994 }
5995 if (bit != 0)
5996 *q=byte >> (8-bit);
5997 q+=scanline_pad;
5998 }
5999 }
6000 else
6001 if (window->pixel_info->colors != 0)
6002 switch (ximage->bits_per_pixel)
6003 {
6004 case 2:
6005 {
6006 register unsigned int
6007 nibble;
6008
6009 /*
6010 Convert to 2 bit color-mapped X canvas.
6011 */
6012 for (y=0; y < (int) canvas->rows; y++)
6013 {
cristyc57f6942010-11-12 01:47:39 +00006014 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006015 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006016 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006017 break;
cristy3ed852e2009-09-05 21:47:34 +00006018 nibble=0;
6019 for (x=0; x < (int) canvas->columns; x++)
6020 {
cristy4c08aed2011-07-01 19:47:50 +00006021 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006022 switch (nibble)
6023 {
6024 case 0:
6025 {
6026 *q=(unsigned char) pixel;
6027 nibble++;
6028 break;
6029 }
6030 case 1:
6031 {
6032 *q|=(unsigned char) (pixel << 2);
6033 nibble++;
6034 break;
6035 }
6036 case 2:
6037 {
6038 *q|=(unsigned char) (pixel << 4);
6039 nibble++;
6040 break;
6041 }
6042 case 3:
6043 {
6044 *q|=(unsigned char) (pixel << 6);
6045 q++;
6046 nibble=0;
6047 break;
6048 }
6049 }
cristyed231572011-07-14 02:18:59 +00006050 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006051 }
6052 q+=scanline_pad;
6053 }
6054 break;
6055 }
6056 case 4:
6057 {
6058 register unsigned int
6059 nibble;
6060
6061 /*
6062 Convert to 4 bit color-mapped X canvas.
6063 */
6064 for (y=0; y < (int) canvas->rows; y++)
6065 {
cristyc57f6942010-11-12 01:47:39 +00006066 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006067 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006068 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006069 break;
cristy3ed852e2009-09-05 21:47:34 +00006070 nibble=0;
6071 for (x=0; x < (int) canvas->columns; x++)
6072 {
cristy4c08aed2011-07-01 19:47:50 +00006073 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006074 switch (nibble)
6075 {
6076 case 0:
6077 {
6078 *q=(unsigned char) pixel;
6079 nibble++;
6080 break;
6081 }
6082 case 1:
6083 {
6084 *q|=(unsigned char) (pixel << 4);
6085 q++;
6086 nibble=0;
6087 break;
6088 }
6089 }
cristyed231572011-07-14 02:18:59 +00006090 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006091 }
6092 q+=scanline_pad;
6093 }
6094 break;
6095 }
6096 case 6:
6097 case 8:
6098 {
6099 /*
6100 Convert to 8 bit color-mapped X canvas.
6101 */
6102 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006103 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006104 {
cristy6710d842011-10-20 23:23:00 +00006105 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006106 break;
6107 }
6108 for (y=0; y < (int) canvas->rows; y++)
6109 {
cristyc57f6942010-11-12 01:47:39 +00006110 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006111 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006112 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006113 break;
cristy3ed852e2009-09-05 21:47:34 +00006114 for (x=0; x < (int) canvas->columns; x++)
6115 {
cristy4c08aed2011-07-01 19:47:50 +00006116 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006117 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006118 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006119 }
6120 q+=scanline_pad;
6121 }
6122 break;
6123 }
6124 default:
6125 {
6126 register int
6127 k;
6128
6129 register unsigned int
6130 bytes_per_pixel;
6131
6132 unsigned char
cristybb503372010-05-27 20:51:26 +00006133 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006134
6135 /*
6136 Convert to multi-byte color-mapped X canvas.
6137 */
6138 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6139 for (y=0; y < (int) canvas->rows; y++)
6140 {
cristyc57f6942010-11-12 01:47:39 +00006141 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006142 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006143 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006144 break;
cristy3ed852e2009-09-05 21:47:34 +00006145 for (x=0; x < (int) canvas->columns; x++)
6146 {
cristy4c08aed2011-07-01 19:47:50 +00006147 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006148 for (k=0; k < (int) bytes_per_pixel; k++)
6149 {
6150 channel[k]=(unsigned char) pixel;
6151 pixel>>=8;
6152 }
6153 for (k=0; k < (int) bytes_per_pixel; k++)
6154 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006155 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006156 }
6157 q+=scanline_pad;
6158 }
6159 break;
6160 }
6161 }
6162 else
6163 switch (ximage->bits_per_pixel)
6164 {
6165 case 2:
6166 {
6167 register unsigned int
6168 nibble;
6169
6170 /*
6171 Convert to contiguous 2 bit continuous-tone X canvas.
6172 */
6173 for (y=0; y < (int) canvas->rows; y++)
6174 {
6175 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006176 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006177 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006178 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006179 break;
6180 for (x=0; x < (int) canvas->columns; x++)
6181 {
cristy4c08aed2011-07-01 19:47:50 +00006182 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006183 pixel&=0xf;
6184 switch (nibble)
6185 {
6186 case 0:
6187 {
6188 *q=(unsigned char) pixel;
6189 nibble++;
6190 break;
6191 }
6192 case 1:
6193 {
6194 *q|=(unsigned char) (pixel << 2);
6195 nibble++;
6196 break;
6197 }
6198 case 2:
6199 {
6200 *q|=(unsigned char) (pixel << 4);
6201 nibble++;
6202 break;
6203 }
6204 case 3:
6205 {
6206 *q|=(unsigned char) (pixel << 6);
6207 q++;
6208 nibble=0;
6209 break;
6210 }
6211 }
cristyed231572011-07-14 02:18:59 +00006212 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006213 }
6214 q+=scanline_pad;
6215 }
6216 break;
6217 }
6218 case 4:
6219 {
6220 register unsigned int
6221 nibble;
6222
6223 /*
6224 Convert to contiguous 4 bit continuous-tone X canvas.
6225 */
6226 for (y=0; y < (int) canvas->rows; y++)
6227 {
cristyc57f6942010-11-12 01:47:39 +00006228 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006229 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006230 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006231 break;
6232 nibble=0;
6233 for (x=0; x < (int) canvas->columns; x++)
6234 {
cristy4c08aed2011-07-01 19:47:50 +00006235 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006236 pixel&=0xf;
6237 switch (nibble)
6238 {
6239 case 0:
6240 {
6241 *q=(unsigned char) pixel;
6242 nibble++;
6243 break;
6244 }
6245 case 1:
6246 {
6247 *q|=(unsigned char) (pixel << 4);
6248 q++;
6249 nibble=0;
6250 break;
6251 }
6252 }
cristyed231572011-07-14 02:18:59 +00006253 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006254 }
6255 q+=scanline_pad;
6256 }
6257 break;
6258 }
6259 case 6:
6260 case 8:
6261 {
6262 /*
6263 Convert to contiguous 8 bit continuous-tone X canvas.
6264 */
6265 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006266 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006267 {
cristy6710d842011-10-20 23:23:00 +00006268 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006269 break;
6270 }
6271 for (y=0; y < (int) canvas->rows; y++)
6272 {
cristyc57f6942010-11-12 01:47:39 +00006273 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006274 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006275 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006276 break;
6277 for (x=0; x < (int) canvas->columns; x++)
6278 {
cristy4c08aed2011-07-01 19:47:50 +00006279 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006280 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006281 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006282 }
6283 q+=scanline_pad;
6284 }
6285 break;
6286 }
6287 default:
6288 {
6289 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6290 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6291 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6292 (map_info->blue_mult == 1))
6293 {
6294 /*
6295 Convert to 32 bit continuous-tone X canvas.
6296 */
6297 for (y=0; y < (int) canvas->rows; y++)
6298 {
cristyc57f6942010-11-12 01:47:39 +00006299 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006300 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006301 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006302 break;
6303 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6304 (blue_gamma != 1.0))
6305 {
6306 /*
6307 Gamma correct canvas.
6308 */
6309 for (x=(int) canvas->columns-1; x >= 0; x--)
6310 {
cristyccf844f2010-02-03 23:28:16 +00006311 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006312 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006313 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006314 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006315 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006316 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006317 *q++=0;
cristyed231572011-07-14 02:18:59 +00006318 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006319 }
6320 continue;
6321 }
6322 for (x=(int) canvas->columns-1; x >= 0; x--)
6323 {
cristy8bc259b2012-06-21 23:53:15 +00006324 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6325 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6326 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006327 *q++=0;
cristyed231572011-07-14 02:18:59 +00006328 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006329 }
6330 }
6331 }
6332 else
6333 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6334 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6335 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6336 (map_info->blue_mult == 65536L))
6337 {
6338 /*
6339 Convert to 32 bit continuous-tone X canvas.
6340 */
6341 for (y=0; y < (int) canvas->rows; y++)
6342 {
cristyc57f6942010-11-12 01:47:39 +00006343 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006344 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006345 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006346 break;
6347 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6348 (blue_gamma != 1.0))
6349 {
6350 /*
6351 Gamma correct canvas.
6352 */
6353 for (x=(int) canvas->columns-1; x >= 0; x--)
6354 {
cristyccf844f2010-02-03 23:28:16 +00006355 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006356 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006357 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006358 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006359 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006360 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006361 *q++=0;
cristyed231572011-07-14 02:18:59 +00006362 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006363 }
6364 continue;
6365 }
6366 for (x=(int) canvas->columns-1; x >= 0; x--)
6367 {
cristy8bc259b2012-06-21 23:53:15 +00006368 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6369 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6370 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006371 *q++=0;
cristyed231572011-07-14 02:18:59 +00006372 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006373 }
6374 }
6375 }
6376 else
6377 {
6378 register int
6379 k;
6380
6381 register unsigned int
6382 bytes_per_pixel;
6383
6384 unsigned char
cristybb503372010-05-27 20:51:26 +00006385 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006386
6387 /*
6388 Convert to multi-byte continuous-tone X canvas.
6389 */
cristyca0aa652013-03-16 13:56:03 +00006390 (void) ResetMagickMemory(channel,0,sizeof(channel));
cristy3ed852e2009-09-05 21:47:34 +00006391 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6392 for (y=0; y < (int) canvas->rows; y++)
6393 {
cristyc57f6942010-11-12 01:47:39 +00006394 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006395 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006396 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006397 break;
cristyc57f6942010-11-12 01:47:39 +00006398 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006399 {
cristy4c08aed2011-07-01 19:47:50 +00006400 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006401 for (k=0; k < (int) bytes_per_pixel; k++)
6402 {
6403 channel[k]=(unsigned char) pixel;
6404 pixel>>=8;
6405 }
6406 for (k=0; k < (int) bytes_per_pixel; k++)
6407 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006408 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006409 }
6410 q+=scanline_pad;
6411 }
6412 }
6413 break;
6414 }
6415 }
6416 if (matte_image != (XImage *) NULL)
6417 {
6418 /*
6419 Initialize matte canvas.
6420 */
6421 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6422 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6423 q=(unsigned char *) matte_image->data;
6424 for (y=0; y < (int) canvas->rows; y++)
6425 {
cristyc57f6942010-11-12 01:47:39 +00006426 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006427 exception);
cristy4c08aed2011-07-01 19:47:50 +00006428 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006429 break;
6430 bit=0;
6431 byte=0;
6432 for (x=(int) canvas->columns-1; x >= 0; x--)
6433 {
6434 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006435 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006436 byte|=0x80;
6437 bit++;
6438 if (bit == 8)
6439 {
6440 *q++=byte;
6441 bit=0;
6442 byte=0;
6443 }
cristyed231572011-07-14 02:18:59 +00006444 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006445 }
6446 if (bit != 0)
6447 *q=byte >> (8-bit);
6448 q+=scanline_pad;
6449 }
6450 }
cristyc57f6942010-11-12 01:47:39 +00006451 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006452 if (canvas != image)
6453 canvas=DestroyImage(canvas);
6454}
6455
6456/*
6457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6458% %
6459% %
6460% %
6461+ X M a k e I m a g e M S B F i r s t %
6462% %
6463% %
6464% %
6465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6466%
6467% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6468% image pixels are copied in most-significant bit and byte first order. The
6469% server's scanline pad is also respected. Rather than using one or two
6470% general cases, many special cases are found here to help speed up the image
6471% conversion.
6472%
6473% The format of the XMakeImageMSBFirst method is:
6474%
cristye941a752011-10-15 01:52:48 +00006475% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6476% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006477%
6478% A description of each parameter follows:
6479%
6480% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6481%
6482% o window: Specifies a pointer to a XWindowInfo structure.
6483%
6484% o image: the image.
6485%
6486% o ximage: Specifies a pointer to a XImage structure; returned from
6487% XCreateImage.
6488%
6489% o matte_image: Specifies a pointer to a XImage structure; returned from
6490% XCreateImage.
6491%
cristye941a752011-10-15 01:52:48 +00006492% o exception: return any errors or warnings in this structure.
6493%
cristy3ed852e2009-09-05 21:47:34 +00006494*/
6495static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006496 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6497 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006498{
cristyc57f6942010-11-12 01:47:39 +00006499 CacheView
6500 *canvas_view;
6501
cristy3ed852e2009-09-05 21:47:34 +00006502 Image
6503 *canvas;
6504
6505 int
6506 y;
6507
6508 register int
6509 x;
6510
cristy4c08aed2011-07-01 19:47:50 +00006511 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006512 *p;
6513
6514 register unsigned char
6515 *q;
6516
6517 unsigned char
6518 bit,
6519 byte;
6520
6521 unsigned int
6522 scanline_pad;
6523
cristyf2faecf2010-05-28 19:19:36 +00006524 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006525 pixel,
6526 *pixels;
6527
6528 XStandardColormap
6529 *map_info;
6530
6531 assert(resource_info != (XResourceInfo *) NULL);
6532 assert(window != (XWindowInfo *) NULL);
6533 assert(image != (Image *) NULL);
6534 if (image->debug != MagickFalse)
6535 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6536 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006537 if ((window->immutable != MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00006538 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00006539 {
6540 char
6541 size[MaxTextExtent];
6542
6543 Image
6544 *pattern;
6545
6546 ImageInfo
6547 *image_info;
6548
6549 image_info=AcquireImageInfo();
6550 (void) CopyMagickString(image_info->filename,
6551 resource_info->image_info->texture != (char *) NULL ?
6552 resource_info->image_info->texture : "pattern:checkerboard",
6553 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006554 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006555 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006556 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006557 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006558 image_info=DestroyImageInfo(image_info);
6559 if (pattern != (Image *) NULL)
6560 {
cristy6710d842011-10-20 23:23:00 +00006561 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006562 if (canvas != (Image *) NULL)
cristyfeb3e962012-03-29 17:25:55 +00006563 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6564 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00006565 pattern=DestroyImage(pattern);
6566 }
6567 }
cristy4c08aed2011-07-01 19:47:50 +00006568 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6569 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006570 map_info=window->map_info;
6571 pixels=window->pixel_info->pixels;
6572 q=(unsigned char *) ximage->data;
6573 x=0;
cristy46ff2672012-12-14 15:32:26 +00006574 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00006575 if (ximage->format == XYBitmap)
6576 {
6577 register unsigned short
6578 polarity;
6579
6580 unsigned char
6581 background,
6582 foreground;
6583
6584 /*
6585 Convert canvas to big-endian bitmap.
6586 */
6587 background=(unsigned char)
6588 (XPixelIntensity(&window->pixel_info->foreground_color) <
6589 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6590 foreground=(unsigned char)
6591 (XPixelIntensity(&window->pixel_info->background_color) <
6592 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006593 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00006594 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00006595 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006596 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6597 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006598 for (y=0; y < (int) canvas->rows; y++)
6599 {
cristyc57f6942010-11-12 01:47:39 +00006600 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006601 exception);
cristy4c08aed2011-07-01 19:47:50 +00006602 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006603 break;
cristy3ed852e2009-09-05 21:47:34 +00006604 bit=0;
6605 byte=0;
6606 for (x=(int) canvas->columns-1; x >= 0; x--)
6607 {
6608 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006609 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006610 byte|=foreground;
6611 else
6612 byte|=background;
6613 bit++;
6614 if (bit == 8)
6615 {
6616 *q++=byte;
6617 bit=0;
6618 byte=0;
6619 }
cristyed231572011-07-14 02:18:59 +00006620 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006621 }
6622 if (bit != 0)
6623 *q=byte << (8-bit);
6624 q+=scanline_pad;
6625 }
6626 }
6627 else
6628 if (window->pixel_info->colors != 0)
6629 switch (ximage->bits_per_pixel)
6630 {
6631 case 2:
6632 {
6633 register unsigned int
6634 nibble;
6635
6636 /*
6637 Convert to 2 bit color-mapped X canvas.
6638 */
6639 for (y=0; y < (int) canvas->rows; y++)
6640 {
cristyc57f6942010-11-12 01:47:39 +00006641 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006642 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006643 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006644 break;
cristy3ed852e2009-09-05 21:47:34 +00006645 nibble=0;
6646 for (x=0; x < (int) canvas->columns; x++)
6647 {
cristy4c08aed2011-07-01 19:47:50 +00006648 pixel=pixels[(ssize_t)
6649 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006650 switch (nibble)
6651 {
6652 case 0:
6653 {
6654 *q=(unsigned char) (pixel << 6);
6655 nibble++;
6656 break;
6657 }
6658 case 1:
6659 {
6660 *q|=(unsigned char) (pixel << 4);
6661 nibble++;
6662 break;
6663 }
6664 case 2:
6665 {
6666 *q|=(unsigned char) (pixel << 2);
6667 nibble++;
6668 break;
6669 }
6670 case 3:
6671 {
6672 *q|=(unsigned char) pixel;
6673 q++;
6674 nibble=0;
6675 break;
6676 }
6677 }
cristyed231572011-07-14 02:18:59 +00006678 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006679 }
6680 q+=scanline_pad;
6681 }
6682 break;
6683 }
6684 case 4:
6685 {
6686 register unsigned int
6687 nibble;
6688
6689 /*
6690 Convert to 4 bit color-mapped X canvas.
6691 */
6692 for (y=0; y < (int) canvas->rows; y++)
6693 {
cristyc57f6942010-11-12 01:47:39 +00006694 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006695 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006696 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006697 break;
cristy3ed852e2009-09-05 21:47:34 +00006698 nibble=0;
6699 for (x=0; x < (int) canvas->columns; x++)
6700 {
cristy4c08aed2011-07-01 19:47:50 +00006701 pixel=pixels[(ssize_t)
6702 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006703 switch (nibble)
6704 {
6705 case 0:
6706 {
6707 *q=(unsigned char) (pixel << 4);
6708 nibble++;
6709 break;
6710 }
6711 case 1:
6712 {
6713 *q|=(unsigned char) pixel;
6714 q++;
6715 nibble=0;
6716 break;
6717 }
6718 }
cristyed231572011-07-14 02:18:59 +00006719 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006720 }
6721 q+=scanline_pad;
6722 }
6723 break;
6724 }
6725 case 6:
6726 case 8:
6727 {
6728 /*
6729 Convert to 8 bit color-mapped X canvas.
6730 */
6731 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006732 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006733 {
cristy6710d842011-10-20 23:23:00 +00006734 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006735 break;
6736 }
6737 for (y=0; y < (int) canvas->rows; y++)
6738 {
cristyc57f6942010-11-12 01:47:39 +00006739 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006740 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006741 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006742 break;
cristy3ed852e2009-09-05 21:47:34 +00006743 for (x=0; x < (int) canvas->columns; x++)
6744 {
cristy6710d842011-10-20 23:23:00 +00006745 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006746 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006747 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006748 }
6749 q+=scanline_pad;
6750 }
6751 break;
6752 }
6753 default:
6754 {
6755 register int
6756 k;
6757
6758 register unsigned int
6759 bytes_per_pixel;
6760
6761 unsigned char
cristybb503372010-05-27 20:51:26 +00006762 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006763
6764 /*
6765 Convert to 8 bit color-mapped X canvas.
6766 */
6767 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6768 for (y=0; y < (int) canvas->rows; y++)
6769 {
cristyc57f6942010-11-12 01:47:39 +00006770 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006771 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006772 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006773 break;
cristy3ed852e2009-09-05 21:47:34 +00006774 for (x=0; x < (int) canvas->columns; x++)
6775 {
cristy4c08aed2011-07-01 19:47:50 +00006776 pixel=pixels[(ssize_t)
6777 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006778 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6779 {
6780 channel[k]=(unsigned char) pixel;
6781 pixel>>=8;
6782 }
6783 for (k=0; k < (int) bytes_per_pixel; k++)
6784 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006785 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006786 }
6787 q+=scanline_pad;
6788 }
6789 break;
6790 }
6791 }
6792 else
6793 switch (ximage->bits_per_pixel)
6794 {
6795 case 2:
6796 {
6797 register unsigned int
6798 nibble;
6799
6800 /*
6801 Convert to 4 bit continuous-tone X canvas.
6802 */
6803 for (y=0; y < (int) canvas->rows; y++)
6804 {
cristyc57f6942010-11-12 01:47:39 +00006805 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006806 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006807 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006808 break;
6809 nibble=0;
6810 for (x=(int) canvas->columns-1; x >= 0; x--)
6811 {
cristy4c08aed2011-07-01 19:47:50 +00006812 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006813 pixel&=0xf;
6814 switch (nibble)
6815 {
6816 case 0:
6817 {
6818 *q=(unsigned char) (pixel << 6);
6819 nibble++;
6820 break;
6821 }
6822 case 1:
6823 {
6824 *q|=(unsigned char) (pixel << 4);
6825 nibble++;
6826 break;
6827 }
6828 case 2:
6829 {
6830 *q|=(unsigned char) (pixel << 2);
6831 nibble++;
6832 break;
6833 }
6834 case 3:
6835 {
6836 *q|=(unsigned char) pixel;
6837 q++;
6838 nibble=0;
6839 break;
6840 }
6841 }
cristyed231572011-07-14 02:18:59 +00006842 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006843 }
6844 q+=scanline_pad;
6845 }
6846 break;
6847 }
6848 case 4:
6849 {
6850 register unsigned int
6851 nibble;
6852
6853 /*
6854 Convert to 4 bit continuous-tone X canvas.
6855 */
6856 for (y=0; y < (int) canvas->rows; y++)
6857 {
cristyc57f6942010-11-12 01:47:39 +00006858 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006859 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006860 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006861 break;
6862 nibble=0;
6863 for (x=(int) canvas->columns-1; x >= 0; x--)
6864 {
cristy4c08aed2011-07-01 19:47:50 +00006865 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006866 pixel&=0xf;
6867 switch (nibble)
6868 {
6869 case 0:
6870 {
6871 *q=(unsigned char) (pixel << 4);
6872 nibble++;
6873 break;
6874 }
6875 case 1:
6876 {
6877 *q|=(unsigned char) pixel;
6878 q++;
6879 nibble=0;
6880 break;
6881 }
6882 }
cristyed231572011-07-14 02:18:59 +00006883 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006884 }
6885 q+=scanline_pad;
6886 }
6887 break;
6888 }
6889 case 6:
6890 case 8:
6891 {
6892 /*
6893 Convert to 8 bit continuous-tone X canvas.
6894 */
6895 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006896 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006897 {
cristy6710d842011-10-20 23:23:00 +00006898 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006899 break;
6900 }
6901 for (y=0; y < (int) canvas->rows; y++)
6902 {
cristyc57f6942010-11-12 01:47:39 +00006903 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006904 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006905 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006906 break;
6907 for (x=(int) canvas->columns-1; x >= 0; x--)
6908 {
cristy4c08aed2011-07-01 19:47:50 +00006909 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006910 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006911 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006912 }
6913 q+=scanline_pad;
6914 }
6915 break;
6916 }
6917 default:
6918 {
6919 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6920 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6921 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6922 (map_info->blue_mult == 1))
6923 {
6924 /*
6925 Convert to 32 bit continuous-tone X canvas.
6926 */
6927 for (y=0; y < (int) canvas->rows; y++)
6928 {
cristyc57f6942010-11-12 01:47:39 +00006929 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006930 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006931 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006932 break;
6933 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6934 (blue_gamma != 1.0))
6935 {
6936 /*
6937 Gamma correct canvas.
6938 */
6939 for (x=(int) canvas->columns-1; x >= 0; x--)
6940 {
6941 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006942 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006943 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006944 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006945 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006946 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006947 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006948 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006949 }
6950 continue;
6951 }
6952 for (x=(int) canvas->columns-1; x >= 0; x--)
6953 {
6954 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006955 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6956 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6957 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006958 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006959 }
6960 }
6961 }
6962 else
6963 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6964 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6965 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6966 (map_info->blue_mult == 65536L))
6967 {
6968 /*
6969 Convert to 32 bit continuous-tone X canvas.
6970 */
6971 for (y=0; y < (int) canvas->rows; y++)
6972 {
cristyc57f6942010-11-12 01:47:39 +00006973 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006974 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006975 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006976 break;
6977 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6978 (blue_gamma != 1.0))
6979 {
6980 /*
6981 Gamma correct canvas.
6982 */
6983 for (x=(int) canvas->columns-1; x >= 0; x--)
6984 {
6985 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006986 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006987 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006988 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006989 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006990 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006991 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006992 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006993 }
6994 continue;
6995 }
6996 for (x=(int) canvas->columns-1; x >= 0; x--)
6997 {
6998 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006999 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
7000 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
7001 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00007002 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007003 }
7004 }
7005 }
7006 else
7007 {
7008 register int
7009 k;
7010
7011 register unsigned int
7012 bytes_per_pixel;
7013
7014 unsigned char
cristybb503372010-05-27 20:51:26 +00007015 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007016
7017 /*
7018 Convert to multi-byte continuous-tone X canvas.
7019 */
7020 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7021 for (y=0; y < (int) canvas->rows; y++)
7022 {
cristyc57f6942010-11-12 01:47:39 +00007023 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007024 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007025 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007026 break;
7027 for (x=(int) canvas->columns-1; x >= 0; x--)
7028 {
cristy4c08aed2011-07-01 19:47:50 +00007029 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007030 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7031 {
7032 channel[k]=(unsigned char) pixel;
7033 pixel>>=8;
7034 }
7035 for (k=0; k < (int) bytes_per_pixel; k++)
7036 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007037 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007038 }
7039 q+=scanline_pad;
7040 }
7041 }
7042 break;
7043 }
7044 }
7045 if (matte_image != (XImage *) NULL)
7046 {
7047 /*
7048 Initialize matte canvas.
7049 */
7050 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7051 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7052 q=(unsigned char *) matte_image->data;
7053 for (y=0; y < (int) canvas->rows; y++)
7054 {
cristyc57f6942010-11-12 01:47:39 +00007055 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007056 exception);
cristy4c08aed2011-07-01 19:47:50 +00007057 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007058 break;
7059 bit=0;
7060 byte=0;
7061 for (x=(int) canvas->columns-1; x >= 0; x--)
7062 {
7063 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007064 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007065 byte|=0x01;
7066 bit++;
7067 if (bit == 8)
7068 {
7069 *q++=byte;
7070 bit=0;
7071 byte=0;
7072 }
cristyed231572011-07-14 02:18:59 +00007073 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007074 }
7075 if (bit != 0)
7076 *q=byte << (8-bit);
7077 q+=scanline_pad;
7078 }
7079 }
cristyc57f6942010-11-12 01:47:39 +00007080 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007081 if (canvas != image)
7082 canvas=DestroyImage(canvas);
7083}
7084
7085/*
7086%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7087% %
7088% %
7089% %
7090% X M a k e M a g n i f y I m a g e %
7091% %
7092% %
7093% %
7094%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7095%
7096% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7097%
7098% The format of the XMakeMagnifyImage method is:
7099%
cristy6710d842011-10-20 23:23:00 +00007100% void XMakeMagnifyImage(Display *display,XWindows *windows,
7101% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007102%
7103% A description of each parameter follows:
7104%
7105% o display: Specifies a connection to an X server; returned from
7106% XOpenDisplay.
7107%
7108% o windows: Specifies a pointer to a XWindows structure.
7109%
cristy6710d842011-10-20 23:23:00 +00007110% o exception: return any errors or warnings in this structure.
7111%
cristy3ed852e2009-09-05 21:47:34 +00007112*/
cristy6710d842011-10-20 23:23:00 +00007113MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7114 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007115{
7116 char
7117 tuple[MaxTextExtent];
7118
7119 int
7120 y;
7121
cristy4c08aed2011-07-01 19:47:50 +00007122 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007123 pixel;
7124
7125 register int
7126 x;
7127
cristybb503372010-05-27 20:51:26 +00007128 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007129 i;
7130
7131 register unsigned char
7132 *p,
7133 *q;
7134
cristy9d314ff2011-03-09 01:30:28 +00007135 ssize_t
7136 n;
7137
cristy3ed852e2009-09-05 21:47:34 +00007138 static unsigned int
7139 previous_magnify = 0;
7140
7141 static XWindowInfo
7142 magnify_window;
7143
7144 unsigned int
7145 height,
7146 j,
7147 k,
7148 l,
7149 magnify,
7150 scanline_pad,
7151 width;
7152
7153 XImage
7154 *ximage;
7155
7156 /*
7157 Check boundary conditions.
7158 */
7159 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7160 assert(display != (Display *) NULL);
7161 assert(windows != (XWindows *) NULL);
7162 magnify=1;
cristybb503372010-05-27 20:51:26 +00007163 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007164 magnify<<=1;
7165 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7166 magnify<<=1;
7167 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7168 magnify<<=1;
7169 while (magnify > windows->magnify.width)
7170 magnify>>=1;
7171 while (magnify > windows->magnify.height)
7172 magnify>>=1;
7173 if (magnify != previous_magnify)
7174 {
7175 Status
7176 status;
7177
7178 XTextProperty
7179 window_name;
7180
7181 /*
7182 New magnify factor: update magnify window name.
7183 */
7184 i=0;
7185 while ((1 << i) <= (int) magnify)
7186 i++;
cristyb51dff52011-05-19 16:55:47 +00007187 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007188 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007189 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7190 if (status != False)
7191 {
7192 XSetWMName(display,windows->magnify.id,&window_name);
7193 XSetWMIconName(display,windows->magnify.id,&window_name);
7194 (void) XFree((void *) window_name.value);
7195 }
7196 }
7197 previous_magnify=magnify;
7198 ximage=windows->image.ximage;
7199 width=(unsigned int) windows->magnify.ximage->width;
7200 height=(unsigned int) windows->magnify.ximage->height;
7201 if ((windows->magnify.x < 0) ||
7202 (windows->magnify.x >= windows->image.ximage->width))
7203 windows->magnify.x=windows->image.ximage->width >> 1;
7204 x=windows->magnify.x-((width/magnify) >> 1);
7205 if (x < 0)
7206 x=0;
7207 else
7208 if (x > (int) (ximage->width-(width/magnify)))
7209 x=ximage->width-width/magnify;
7210 if ((windows->magnify.y < 0) ||
7211 (windows->magnify.y >= windows->image.ximage->height))
7212 windows->magnify.y=windows->image.ximage->height >> 1;
7213 y=windows->magnify.y-((height/magnify) >> 1);
7214 if (y < 0)
7215 y=0;
7216 else
7217 if (y > (int) (ximage->height-(height/magnify)))
7218 y=ximage->height-height/magnify;
7219 q=(unsigned char *) windows->magnify.ximage->data;
7220 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7221 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7222 if (ximage->bits_per_pixel < 8)
7223 {
7224 register unsigned char
7225 background,
7226 byte,
7227 foreground,
7228 p_bit,
7229 q_bit;
7230
7231 register unsigned int
7232 plane;
7233
7234 XPixelInfo
7235 *pixel_info;
7236
7237 pixel_info=windows->magnify.pixel_info;
7238 switch (ximage->bitmap_bit_order)
7239 {
7240 case LSBFirst:
7241 {
7242 /*
7243 Magnify little-endian bitmap.
7244 */
7245 background=0x00;
7246 foreground=0x80;
7247 if (ximage->format == XYBitmap)
7248 {
7249 background=(unsigned char)
7250 (XPixelIntensity(&pixel_info->foreground_color) <
7251 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7252 foreground=(unsigned char)
7253 (XPixelIntensity(&pixel_info->background_color) <
7254 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7255 if (windows->magnify.depth > 1)
7256 Swap(background,foreground);
7257 }
cristybb503372010-05-27 20:51:26 +00007258 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007259 {
7260 /*
7261 Propogate pixel magnify rows.
7262 */
7263 for (j=0; j < magnify; j++)
7264 {
7265 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7266 ((x*ximage->bits_per_pixel) >> 3);
7267 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7268 q_bit=0;
7269 byte=0;
7270 for (k=0; k < width; k+=magnify)
7271 {
7272 /*
7273 Propogate pixel magnify columns.
7274 */
7275 for (l=0; l < magnify; l++)
7276 {
7277 /*
7278 Propogate each bit plane.
7279 */
7280 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7281 {
7282 byte>>=1;
7283 if (*p & (0x01 << (p_bit+plane)))
7284 byte|=foreground;
7285 else
7286 byte|=background;
7287 q_bit++;
7288 if (q_bit == 8)
7289 {
7290 *q++=byte;
7291 q_bit=0;
7292 byte=0;
7293 }
7294 }
7295 }
7296 p_bit+=ximage->bits_per_pixel;
7297 if (p_bit == 8)
7298 {
7299 p++;
7300 p_bit=0;
7301 }
7302 if (q_bit != 0)
7303 *q=byte >> (8-q_bit);
7304 q+=scanline_pad;
7305 }
7306 }
7307 y++;
7308 }
7309 break;
7310 }
7311 case MSBFirst:
7312 default:
7313 {
7314 /*
7315 Magnify big-endian bitmap.
7316 */
7317 background=0x00;
7318 foreground=0x01;
7319 if (ximage->format == XYBitmap)
7320 {
7321 background=(unsigned char)
7322 (XPixelIntensity(&pixel_info->foreground_color) <
7323 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7324 foreground=(unsigned char)
7325 (XPixelIntensity(&pixel_info->background_color) <
7326 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7327 if (windows->magnify.depth > 1)
7328 Swap(background,foreground);
7329 }
cristybb503372010-05-27 20:51:26 +00007330 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007331 {
7332 /*
7333 Propogate pixel magnify rows.
7334 */
7335 for (j=0; j < magnify; j++)
7336 {
7337 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7338 ((x*ximage->bits_per_pixel) >> 3);
7339 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7340 q_bit=0;
7341 byte=0;
7342 for (k=0; k < width; k+=magnify)
7343 {
7344 /*
7345 Propogate pixel magnify columns.
7346 */
7347 for (l=0; l < magnify; l++)
7348 {
7349 /*
7350 Propogate each bit plane.
7351 */
7352 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7353 {
7354 byte<<=1;
7355 if (*p & (0x80 >> (p_bit+plane)))
7356 byte|=foreground;
7357 else
7358 byte|=background;
7359 q_bit++;
7360 if (q_bit == 8)
7361 {
7362 *q++=byte;
7363 q_bit=0;
7364 byte=0;
7365 }
7366 }
7367 }
7368 p_bit+=ximage->bits_per_pixel;
7369 if (p_bit == 8)
7370 {
7371 p++;
7372 p_bit=0;
7373 }
7374 if (q_bit != 0)
7375 *q=byte << (8-q_bit);
7376 q+=scanline_pad;
7377 }
7378 }
7379 y++;
7380 }
7381 break;
7382 }
7383 }
7384 }
7385 else
7386 switch (ximage->bits_per_pixel)
7387 {
7388 case 6:
7389 case 8:
7390 {
7391 /*
7392 Magnify 8 bit X image.
7393 */
cristybb503372010-05-27 20:51:26 +00007394 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007395 {
7396 /*
7397 Propogate pixel magnify rows.
7398 */
7399 for (j=0; j < magnify; j++)
7400 {
7401 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7402 ((x*ximage->bits_per_pixel) >> 3);
7403 for (k=0; k < width; k+=magnify)
7404 {
7405 /*
7406 Propogate pixel magnify columns.
7407 */
7408 for (l=0; l < magnify; l++)
7409 *q++=(*p);
7410 p++;
7411 }
7412 q+=scanline_pad;
7413 }
7414 y++;
7415 }
7416 break;
7417 }
7418 default:
7419 {
7420 register unsigned int
7421 bytes_per_pixel,
7422 m;
7423
7424 /*
7425 Magnify multi-byte X image.
7426 */
7427 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007428 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007429 {
7430 /*
7431 Propogate pixel magnify rows.
7432 */
7433 for (j=0; j < magnify; j++)
7434 {
7435 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7436 ((x*ximage->bits_per_pixel) >> 3);
7437 for (k=0; k < width; k+=magnify)
7438 {
7439 /*
7440 Propogate pixel magnify columns.
7441 */
7442 for (l=0; l < magnify; l++)
7443 for (m=0; m < bytes_per_pixel; m++)
7444 *q++=(*(p+m));
7445 p+=bytes_per_pixel;
7446 }
7447 q+=scanline_pad;
7448 }
7449 y++;
7450 }
7451 break;
7452 }
7453 }
7454 /*
7455 Copy X image to magnify pixmap.
7456 */
7457 x=windows->magnify.x-((width/magnify) >> 1);
7458 if (x < 0)
7459 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7460 else
7461 if (x > (int) (ximage->width-(width/magnify)))
7462 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7463 else
7464 x=0;
7465 y=windows->magnify.y-((height/magnify) >> 1);
7466 if (y < 0)
7467 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7468 else
7469 if (y > (int) (ximage->height-(height/magnify)))
7470 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7471 else
7472 y=0;
7473 if ((x != 0) || (y != 0))
7474 (void) XFillRectangle(display,windows->magnify.pixmap,
7475 windows->magnify.annotate_context,0,0,width,height);
7476 (void) XPutImage(display,windows->magnify.pixmap,
7477 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7478 height-y);
7479 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7480 (magnify <= (height >> 1))))
7481 {
7482 RectangleInfo
7483 highlight_info;
7484
7485 /*
7486 Highlight center pixel.
7487 */
cristybb503372010-05-27 20:51:26 +00007488 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7489 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007490 highlight_info.width=magnify;
7491 highlight_info.height=magnify;
7492 (void) XDrawRectangle(display,windows->magnify.pixmap,
7493 windows->magnify.highlight_context,(int) highlight_info.x,
7494 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7495 (unsigned int) highlight_info.height-1);
7496 if (magnify > 2)
7497 (void) XDrawRectangle(display,windows->magnify.pixmap,
7498 windows->magnify.annotate_context,(int) highlight_info.x+1,
7499 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7500 (unsigned int) highlight_info.height-3);
7501 }
7502 /*
7503 Show center pixel color.
7504 */
cristy3aa93752011-12-18 15:54:24 +00007505 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007506 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007507 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007508 windows->magnify.x,windows->magnify.y);
7509 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007510 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007511 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007512 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007513 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007514 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007515 if (pixel.colorspace == CMYKColorspace)
7516 {
7517 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007518 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007519 }
cristy8a46d822012-08-28 23:32:39 +00007520 if (pixel.alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00007521 {
7522 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007523 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007524 }
7525 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7526 height=(unsigned int) windows->magnify.font_info->ascent+
7527 windows->magnify.font_info->descent;
7528 x=windows->magnify.font_info->max_bounds.width >> 1;
7529 y=windows->magnify.font_info->ascent+(height >> 2);
7530 (void) XDrawImageString(display,windows->magnify.pixmap,
7531 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7532 GetColorTuple(&pixel,MagickTrue,tuple);
7533 y+=height;
7534 (void) XDrawImageString(display,windows->magnify.pixmap,
7535 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007536 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007537 exception);
cristy3ed852e2009-09-05 21:47:34 +00007538 y+=height;
7539 (void) XDrawImageString(display,windows->magnify.pixmap,
7540 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7541 /*
7542 Refresh magnify window.
7543 */
7544 magnify_window=windows->magnify;
7545 magnify_window.x=0;
7546 magnify_window.y=0;
7547 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7548}
7549
7550/*
7551%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7552% %
7553% %
7554% %
7555% X M a k e P i x m a p %
7556% %
7557% %
7558% %
7559%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7560%
7561% XMakePixmap() creates an X11 pixmap.
7562%
7563% The format of the XMakePixmap method is:
7564%
7565% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7566% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7567% XPixelInfo *pixel)
7568%
7569% A description of each parameter follows:
7570%
7571% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7572%
7573% o display: Specifies a connection to an X server; returned from
7574% XOpenDisplay.
7575%
7576% o window: Specifies a pointer to a XWindowInfo structure.
7577%
cristy3ed852e2009-09-05 21:47:34 +00007578*/
7579static MagickBooleanType XMakePixmap(Display *display,
7580 const XResourceInfo *resource_info,XWindowInfo *window)
7581{
7582 unsigned int
7583 height,
7584 width;
7585
7586 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7587 assert(display != (Display *) NULL);
7588 assert(resource_info != (XResourceInfo *) NULL);
7589 assert(window != (XWindowInfo *) NULL);
7590 if (window->pixmap != (Pixmap) NULL)
7591 {
7592 /*
7593 Destroy previous X pixmap.
7594 */
7595 (void) XFreePixmap(display,window->pixmap);
7596 window->pixmap=(Pixmap) NULL;
7597 }
7598 if (window->use_pixmap == MagickFalse)
7599 return(MagickFalse);
7600 if (window->ximage == (XImage *) NULL)
7601 return(MagickFalse);
7602 /*
7603 Display busy cursor.
7604 */
7605 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7606 (void) XFlush(display);
7607 /*
7608 Create pixmap.
7609 */
7610 width=(unsigned int) window->ximage->width;
7611 height=(unsigned int) window->ximage->height;
7612 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7613 if (window->pixmap == (Pixmap) NULL)
7614 {
7615 /*
7616 Unable to allocate pixmap.
7617 */
7618 (void) XCheckDefineCursor(display,window->id,window->cursor);
7619 return(MagickFalse);
7620 }
7621 /*
7622 Copy X image to pixmap.
7623 */
7624#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7625 if (window->shared_memory)
7626 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7627 window->ximage,0,0,0,0,width,height,MagickTrue);
7628#endif
7629 if (window->shared_memory == MagickFalse)
7630 (void) XPutImage(display,window->pixmap,window->annotate_context,
7631 window->ximage,0,0,0,0,width,height);
7632 if (IsEventLogging())
7633 {
7634 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7635 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7636 width,height);
7637 }
7638 /*
7639 Restore cursor.
7640 */
7641 (void) XCheckDefineCursor(display,window->id,window->cursor);
7642 return(MagickTrue);
7643}
7644
7645/*
7646%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7647% %
7648% %
7649% %
7650% X M a k e S t a n d a r d C o l o r m a p %
7651% %
7652% %
7653% %
7654%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7655%
7656% XMakeStandardColormap() creates an X11 Standard Colormap.
7657%
7658% The format of the XMakeStandardColormap method is:
7659%
cristy6710d842011-10-20 23:23:00 +00007660% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7661% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7662% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007663%
7664% A description of each parameter follows:
7665%
7666% o display: Specifies a connection to an X server; returned from
7667% XOpenDisplay.
7668%
7669% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7670% returned from XGetVisualInfo.
7671%
7672% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7673%
7674% o image: the image.
7675%
7676% o map_info: If a Standard Colormap type is specified, this structure is
7677% initialized with info from the Standard Colormap.
7678%
7679% o pixel: Specifies a pointer to a XPixelInfo structure.
7680%
cristy6710d842011-10-20 23:23:00 +00007681% o exception: return any errors or warnings in this structure.
7682%
cristy3ed852e2009-09-05 21:47:34 +00007683*/
7684
7685#if defined(__cplusplus) || defined(c_plusplus)
7686extern "C" {
7687#endif
7688
cristya19f1d72012-08-07 18:24:38 +00007689static inline double DiversityPixelIntensity(
cristy3ed852e2009-09-05 21:47:34 +00007690 const DiversityPacket *pixel)
7691{
cristya19f1d72012-08-07 18:24:38 +00007692 double
cristy3ed852e2009-09-05 21:47:34 +00007693 intensity;
7694
cristya86a5cb2012-10-14 13:40:33 +00007695 intensity=0.298839f*pixel->red+0.586811f*pixel->green+0.114350f*pixel->blue;
cristy3ed852e2009-09-05 21:47:34 +00007696 return(intensity);
7697}
7698
7699static int IntensityCompare(const void *x,const void *y)
7700{
7701 DiversityPacket
7702 *color_1,
7703 *color_2;
7704
7705 int
7706 diversity;
7707
7708 color_1=(DiversityPacket *) x;
7709 color_2=(DiversityPacket *) y;
7710 diversity=(int) (DiversityPixelIntensity(color_2)-
7711 DiversityPixelIntensity(color_1));
7712 return(diversity);
7713}
7714
7715static int PopularityCompare(const void *x,const void *y)
7716{
7717 DiversityPacket
7718 *color_1,
7719 *color_2;
7720
7721 color_1=(DiversityPacket *) x;
7722 color_2=(DiversityPacket *) y;
7723 return((int) color_2->count-(int) color_1->count);
7724}
7725
7726#if defined(__cplusplus) || defined(c_plusplus)
7727}
7728#endif
7729
cristybb503372010-05-27 20:51:26 +00007730static inline Quantum ScaleXToQuantum(const size_t x,
7731 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007732{
cristya19f1d72012-08-07 18:24:38 +00007733 return((Quantum) (((double) QuantumRange*x)/scale+0.5));
cristy3ed852e2009-09-05 21:47:34 +00007734}
7735
cristybcbda3f2011-09-03 13:01:22 +00007736MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007737 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007738 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007739{
7740 Colormap
7741 colormap;
7742
cristybb503372010-05-27 20:51:26 +00007743 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007744 i;
7745
7746 Status
7747 status;
7748
cristybb503372010-05-27 20:51:26 +00007749 size_t
cristy3ed852e2009-09-05 21:47:34 +00007750 number_colors,
7751 retain_colors;
7752
7753 unsigned short
7754 gray_value;
7755
7756 XColor
7757 color,
7758 *colors,
7759 *p;
7760
7761 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7762 assert(display != (Display *) NULL);
7763 assert(visual_info != (XVisualInfo *) NULL);
7764 assert(map_info != (XStandardColormap *) NULL);
7765 assert(resource_info != (XResourceInfo *) NULL);
7766 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007767 if (resource_info->map_type != (char *) NULL)
7768 {
7769 /*
7770 Standard Colormap is already defined (i.e. xstdcmap).
7771 */
cristy4c08aed2011-07-01 19:47:50 +00007772 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007773 pixel);
7774 number_colors=(unsigned int) (map_info->base_pixel+
7775 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7776 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
cristy8a46d822012-08-28 23:32:39 +00007777 if ((image->alpha_trait != BlendPixelTrait) &&
cristy3ed852e2009-09-05 21:47:34 +00007778 (resource_info->color_recovery == MagickFalse) &&
cristycbda6112012-05-27 20:57:16 +00007779 (resource_info->quantize_info->dither_method != NoDitherMethod) &&
cristy3ed852e2009-09-05 21:47:34 +00007780 (number_colors < MaxColormapSize))
7781 {
7782 Image
7783 *affinity_image;
7784
cristy4c08aed2011-07-01 19:47:50 +00007785 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007786 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007787
7788 /*
7789 Improve image appearance with error diffusion.
7790 */
cristy6710d842011-10-20 23:23:00 +00007791 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007792 if (affinity_image == (Image *) NULL)
7793 ThrowXWindowFatalException(ResourceLimitFatalError,
7794 "UnableToDitherImage",image->filename);
7795 affinity_image->columns=number_colors;
7796 affinity_image->rows=1;
7797 /*
7798 Initialize colormap image.
7799 */
7800 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7801 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007802 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007803 {
cristybb503372010-05-27 20:51:26 +00007804 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007805 {
cristy4c08aed2011-07-01 19:47:50 +00007806 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007807 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007808 SetPixelRed(affinity_image,
7809 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7810 map_info->red_max),q);
7811 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007812 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007813 SetPixelGreen(affinity_image,
7814 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7815 (map_info->green_max+1)),map_info->green_max),q);
7816 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007817 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007818 SetPixelBlue(affinity_image,
7819 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7820 map_info->blue_max),q);
7821 SetPixelAlpha(affinity_image,
7822 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007823 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007824 }
7825 (void) SyncAuthenticPixels(affinity_image,exception);
7826 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007827 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007828 }
cristy4c08aed2011-07-01 19:47:50 +00007829 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007830 pixel);
cristy574cc262011-08-05 01:23:58 +00007831 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007832 affinity_image=DestroyImage(affinity_image);
7833 }
7834 if (IsEventLogging())
7835 {
7836 (void) LogMagickEvent(X11Event,GetMagickModule(),
7837 "Standard Colormap:");
7838 (void) LogMagickEvent(X11Event,GetMagickModule(),
7839 " colormap id: 0x%lx",map_info->colormap);
7840 (void) LogMagickEvent(X11Event,GetMagickModule(),
7841 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7842 map_info->green_max,map_info->blue_max);
7843 (void) LogMagickEvent(X11Event,GetMagickModule(),
7844 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7845 map_info->green_mult,map_info->blue_mult);
7846 }
7847 return;
7848 }
7849 if ((visual_info->klass != DirectColor) &&
7850 (visual_info->klass != TrueColor))
7851 if ((image->storage_class == DirectClass) ||
7852 ((int) image->colors > visual_info->colormap_size))
7853 {
7854 QuantizeInfo
7855 quantize_info;
7856
7857 /*
7858 Image has more colors than the visual supports.
7859 */
7860 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007861 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007862 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007863 }
7864 /*
7865 Free previous and create new colormap.
7866 */
7867 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7868 colormap=XDefaultColormap(display,visual_info->screen);
7869 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7870 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7871 visual_info->visual,visual_info->klass == DirectColor ?
7872 AllocAll : AllocNone);
7873 if (colormap == (Colormap) NULL)
7874 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7875 image->filename);
7876 /*
7877 Initialize the map and pixel info structures.
7878 */
7879 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007880 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007881 /*
7882 Allocating colors in server colormap is based on visual class.
7883 */
7884 switch (visual_info->klass)
7885 {
7886 case StaticGray:
7887 case StaticColor:
7888 {
7889 /*
7890 Define Standard Colormap for StaticGray or StaticColor visual.
7891 */
7892 number_colors=image->colors;
7893 colors=(XColor *) AcquireQuantumMemory((size_t)
7894 visual_info->colormap_size,sizeof(*colors));
7895 if (colors == (XColor *) NULL)
7896 ThrowXWindowFatalException(ResourceLimitFatalError,
7897 "UnableToCreateColormap",image->filename);
7898 p=colors;
7899 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007900 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007901 {
7902 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7903 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7904 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7905 if (visual_info->klass != StaticColor)
7906 {
7907 gray_value=(unsigned short) XPixelIntensity(&color);
7908 color.red=gray_value;
7909 color.green=gray_value;
7910 color.blue=gray_value;
7911 }
7912 status=XAllocColor(display,colormap,&color);
7913 if (status == False)
7914 {
7915 colormap=XCopyColormapAndFree(display,colormap);
7916 (void) XAllocColor(display,colormap,&color);
7917 }
7918 pixel->pixels[i]=color.pixel;
7919 *p++=color;
7920 }
7921 break;
7922 }
7923 case GrayScale:
7924 case PseudoColor:
7925 {
7926 unsigned int
7927 colormap_type;
7928
7929 /*
7930 Define Standard Colormap for GrayScale or PseudoColor visual.
7931 */
7932 number_colors=image->colors;
7933 colors=(XColor *) AcquireQuantumMemory((size_t)
7934 visual_info->colormap_size,sizeof(*colors));
7935 if (colors == (XColor *) NULL)
7936 ThrowXWindowFatalException(ResourceLimitFatalError,
7937 "UnableToCreateColormap",image->filename);
7938 /*
7939 Preallocate our GUI colors.
7940 */
7941 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7942 (void) XAllocColor(display,colormap,&pixel->background_color);
7943 (void) XAllocColor(display,colormap,&pixel->border_color);
7944 (void) XAllocColor(display,colormap,&pixel->matte_color);
7945 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7946 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7947 (void) XAllocColor(display,colormap,&pixel->depth_color);
7948 (void) XAllocColor(display,colormap,&pixel->trough_color);
7949 for (i=0; i < MaxNumberPens; i++)
7950 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7951 /*
7952 Determine if image colors will "fit" into X server colormap.
7953 */
7954 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007955 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007956 NULL,0,pixel->pixels,(unsigned int) image->colors);
7957 if (status != False)
7958 colormap_type=PrivateColormap;
7959 if (colormap_type == SharedColormap)
7960 {
cristyc57f6942010-11-12 01:47:39 +00007961 CacheView
7962 *image_view;
7963
cristy3ed852e2009-09-05 21:47:34 +00007964 DiversityPacket
7965 *diversity;
7966
7967 int
7968 y;
7969
7970 register int
7971 x;
7972
7973 unsigned short
7974 index;
7975
7976 XColor
7977 *server_colors;
7978
7979 /*
7980 Define Standard colormap for shared GrayScale or PseudoColor visual.
7981 */
7982 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7983 sizeof(*diversity));
7984 if (diversity == (DiversityPacket *) NULL)
7985 ThrowXWindowFatalException(ResourceLimitFatalError,
7986 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007987 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007988 {
cristye42f6582012-02-11 17:59:50 +00007989 diversity[i].red=ClampToQuantum(image->colormap[i].red);
7990 diversity[i].green=ClampToQuantum(image->colormap[i].green);
7991 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00007992 diversity[i].index=(unsigned short) i;
7993 diversity[i].count=0;
7994 }
cristy46ff2672012-12-14 15:32:26 +00007995 image_view=AcquireAuthenticCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007996 for (y=0; y < (int) image->rows; y++)
7997 {
cristyc57f6942010-11-12 01:47:39 +00007998 register int
cristy3ed852e2009-09-05 21:47:34 +00007999 x;
8000
cristy4c08aed2011-07-01 19:47:50 +00008001 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00008002 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00008003
cristyc57f6942010-11-12 01:47:39 +00008004 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8005 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008006 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008007 break;
cristyc57f6942010-11-12 01:47:39 +00008008 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008009 {
8010 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008011 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008012 }
cristy3ed852e2009-09-05 21:47:34 +00008013 }
cristyc57f6942010-11-12 01:47:39 +00008014 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008015 /*
8016 Sort colors by decreasing intensity.
8017 */
8018 qsort((void *) diversity,image->colors,sizeof(*diversity),
8019 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008020 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008021 {
8022 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008023 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008024 }
8025 diversity[image->colors-1].count<<=4;
8026 qsort((void *) diversity,image->colors,sizeof(*diversity),
8027 PopularityCompare);
8028 /*
8029 Allocate colors.
8030 */
8031 p=colors;
8032 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008033 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008034 {
8035 index=diversity[i].index;
8036 color.red=
8037 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8038 color.green=
8039 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8040 color.blue=
8041 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8042 if (visual_info->klass != PseudoColor)
8043 {
8044 gray_value=(unsigned short) XPixelIntensity(&color);
8045 color.red=gray_value;
8046 color.green=gray_value;
8047 color.blue=gray_value;
8048 }
8049 status=XAllocColor(display,colormap,&color);
8050 if (status == False)
8051 break;
8052 pixel->pixels[index]=color.pixel;
8053 *p++=color;
8054 }
8055 /*
8056 Read X server colormap.
8057 */
8058 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8059 visual_info->colormap_size,sizeof(*server_colors));
8060 if (server_colors == (XColor *) NULL)
8061 ThrowXWindowFatalException(ResourceLimitFatalError,
8062 "UnableToCreateColormap",image->filename);
8063 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008064 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008065 (void) XQueryColors(display,colormap,server_colors,
8066 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8067 /*
8068 Select remaining colors from X server colormap.
8069 */
cristybb503372010-05-27 20:51:26 +00008070 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008071 {
8072 index=diversity[i].index;
8073 color.red=
8074 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8075 color.green=
8076 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8077 color.blue=
8078 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8079 if (visual_info->klass != PseudoColor)
8080 {
8081 gray_value=(unsigned short) XPixelIntensity(&color);
8082 color.red=gray_value;
8083 color.green=gray_value;
8084 color.blue=gray_value;
8085 }
8086 XBestPixel(display,colormap,server_colors,(unsigned int)
8087 visual_info->colormap_size,&color);
8088 pixel->pixels[index]=color.pixel;
8089 *p++=color;
8090 }
8091 if ((int) image->colors < visual_info->colormap_size)
8092 {
8093 /*
8094 Fill up colors array-- more choices for pen colors.
8095 */
8096 retain_colors=MagickMin((unsigned int)
8097 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008098 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008099 *p++=server_colors[i];
8100 number_colors+=retain_colors;
8101 }
8102 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8103 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8104 break;
8105 }
8106 /*
8107 Define Standard colormap for private GrayScale or PseudoColor visual.
8108 */
8109 if (status == False)
8110 {
8111 /*
8112 Not enough colormap entries in the colormap-- Create a new colormap.
8113 */
8114 colormap=XCreateColormap(display,
8115 XRootWindow(display,visual_info->screen),visual_info->visual,
8116 AllocNone);
8117 if (colormap == (Colormap) NULL)
8118 ThrowXWindowFatalException(ResourceLimitFatalError,
8119 "UnableToCreateColormap",image->filename);
8120 map_info->colormap=colormap;
8121 if ((int) image->colors < visual_info->colormap_size)
8122 {
8123 /*
8124 Retain colors from the default colormap to help lessens the
8125 effects of colormap flashing.
8126 */
8127 retain_colors=MagickMin((unsigned int)
8128 (visual_info->colormap_size-image->colors),256);
8129 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008130 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008131 {
cristyc57f6942010-11-12 01:47:39 +00008132 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008133 p++;
8134 }
8135 (void) XQueryColors(display,
8136 XDefaultColormap(display,visual_info->screen),
8137 colors+image->colors,(int) retain_colors);
8138 /*
8139 Transfer colors from default to private colormap.
8140 */
8141 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008142 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008143 retain_colors);
8144 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008145 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008146 {
8147 p->pixel=pixel->pixels[i];
8148 p++;
8149 }
8150 (void) XStoreColors(display,colormap,colors+image->colors,
8151 (int) retain_colors);
8152 number_colors+=retain_colors;
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 image->colors);
8157 }
8158 /*
8159 Store the image colormap.
8160 */
8161 p=colors;
8162 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008163 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008164 {
8165 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8166 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8167 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8168 if (visual_info->klass != PseudoColor)
8169 {
8170 gray_value=(unsigned short) XPixelIntensity(&color);
8171 color.red=gray_value;
8172 color.green=gray_value;
8173 color.blue=gray_value;
8174 }
8175 color.pixel=pixel->pixels[i];
8176 *p++=color;
8177 }
8178 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8179 break;
8180 }
8181 case TrueColor:
8182 case DirectColor:
8183 default:
8184 {
8185 MagickBooleanType
8186 linear_colormap;
8187
8188 /*
8189 Define Standard Colormap for TrueColor or DirectColor visual.
8190 */
8191 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8192 (map_info->green_max*map_info->green_mult)+
8193 (map_info->blue_max*map_info->blue_mult)+1);
8194 linear_colormap=(number_colors > 4096) ||
8195 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8196 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8197 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8198 MagickTrue : MagickFalse;
8199 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008200 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008201 /*
8202 Allocate color array.
8203 */
8204 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8205 if (colors == (XColor *) NULL)
8206 ThrowXWindowFatalException(ResourceLimitFatalError,
8207 "UnableToCreateColormap",image->filename);
8208 /*
8209 Initialize linear color ramp.
8210 */
8211 p=colors;
8212 color.flags=(char) (DoRed | DoGreen | DoBlue);
8213 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008214 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008215 {
8216 color.blue=(unsigned short) 0;
8217 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008218 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008219 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8220 color.green=color.blue;
8221 color.red=color.blue;
8222 color.pixel=XStandardPixel(map_info,&color);
8223 *p++=color;
8224 }
8225 else
cristybb503372010-05-27 20:51:26 +00008226 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008227 {
8228 color.red=(unsigned short) 0;
8229 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008230 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008231 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8232 color.green=(unsigned int) 0;
8233 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008234 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008235 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8236 map_info->green_max));
8237 color.blue=(unsigned short) 0;
8238 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008239 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008240 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8241 color.pixel=XStandardPixel(map_info,&color);
8242 *p++=color;
8243 }
8244 if ((visual_info->klass == DirectColor) &&
8245 (colormap != XDefaultColormap(display,visual_info->screen)))
8246 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8247 else
cristybb503372010-05-27 20:51:26 +00008248 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008249 (void) XAllocColor(display,colormap,&colors[i]);
8250 break;
8251 }
8252 }
8253 if ((visual_info->klass != DirectColor) &&
8254 (visual_info->klass != TrueColor))
8255 {
8256 /*
8257 Set foreground, background, border, etc. pixels.
8258 */
8259 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8260 &pixel->foreground_color);
8261 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8262 &pixel->background_color);
8263 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8264 {
8265 /*
8266 Foreground and background colors must differ.
8267 */
8268 pixel->background_color.red=(~pixel->foreground_color.red);
8269 pixel->background_color.green=
8270 (~pixel->foreground_color.green);
8271 pixel->background_color.blue=
8272 (~pixel->foreground_color.blue);
8273 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8274 &pixel->background_color);
8275 }
8276 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8277 &pixel->border_color);
8278 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8279 &pixel->matte_color);
8280 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8281 &pixel->highlight_color);
8282 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8283 &pixel->shadow_color);
8284 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8285 &pixel->depth_color);
8286 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8287 &pixel->trough_color);
8288 for (i=0; i < MaxNumberPens; i++)
8289 {
8290 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8291 &pixel->pen_colors[i]);
8292 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8293 }
cristyc57f6942010-11-12 01:47:39 +00008294 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008295 }
8296 colors=(XColor *) RelinquishMagickMemory(colors);
8297 if (IsEventLogging())
8298 {
8299 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8300 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8301 map_info->colormap);
8302 (void) LogMagickEvent(X11Event,GetMagickModule(),
8303 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8304 map_info->green_max,map_info->blue_max);
8305 (void) LogMagickEvent(X11Event,GetMagickModule(),
8306 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8307 map_info->green_mult,map_info->blue_mult);
8308 }
8309}
8310
8311/*
8312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8313% %
8314% %
8315% %
8316% X M a k e W i n d o w %
8317% %
8318% %
8319% %
8320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8321%
8322% XMakeWindow() creates an X11 window.
8323%
8324% The format of the XMakeWindow method is:
8325%
8326% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8327% XClassHint *class_hint,XWMHints *manager_hints,
8328% XWindowInfo *window_info)
8329%
8330% A description of each parameter follows:
8331%
8332% o display: Specifies a connection to an X server; returned from
8333% XOpenDisplay.
8334%
8335% o parent: Specifies the parent window_info.
8336%
8337% o argv: Specifies the application's argument list.
8338%
8339% o argc: Specifies the number of arguments.
8340%
8341% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8342%
8343% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8344%
8345% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8346%
8347*/
cristybcbda3f2011-09-03 13:01:22 +00008348MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008349 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8350 XWindowInfo *window_info)
8351{
8352#define MinWindowSize 64
8353
8354 Atom
8355 atom_list[2];
8356
8357 int
8358 gravity;
8359
8360 static XTextProperty
8361 icon_name,
8362 window_name;
8363
8364 Status
8365 status;
8366
8367 XSizeHints
8368 *size_hints;
8369
8370 /*
8371 Set window info hints.
8372 */
8373 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8374 assert(display != (Display *) NULL);
8375 assert(window_info != (XWindowInfo *) NULL);
8376 size_hints=XAllocSizeHints();
8377 if (size_hints == (XSizeHints *) NULL)
8378 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008379 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008380 size_hints->x=window_info->x;
8381 size_hints->y=window_info->y;
8382 size_hints->width=(int) window_info->width;
8383 size_hints->height=(int) window_info->height;
8384 if (window_info->immutable != MagickFalse)
8385 {
8386 /*
8387 Window size cannot be changed.
8388 */
8389 size_hints->min_width=size_hints->width;
8390 size_hints->min_height=size_hints->height;
8391 size_hints->max_width=size_hints->width;
8392 size_hints->max_height=size_hints->height;
8393 size_hints->flags|=PMinSize;
8394 size_hints->flags|=PMaxSize;
8395 }
8396 else
8397 {
8398 /*
8399 Window size can be changed.
8400 */
8401 size_hints->min_width=(int) window_info->min_width;
8402 size_hints->min_height=(int) window_info->min_height;
8403 size_hints->flags|=PResizeInc;
8404 size_hints->width_inc=(int) window_info->width_inc;
8405 size_hints->height_inc=(int) window_info->height_inc;
8406#if !defined(PRE_R4_ICCCM)
8407 size_hints->flags|=PBaseSize;
8408 size_hints->base_width=size_hints->width_inc;
8409 size_hints->base_height=size_hints->height_inc;
8410#endif
8411 }
8412 gravity=NorthWestGravity;
8413 if (window_info->geometry != (char *) NULL)
8414 {
8415 char
8416 default_geometry[MaxTextExtent],
8417 geometry[MaxTextExtent];
8418
8419 int
8420 flags;
8421
8422 register char
8423 *p;
8424
8425 /*
8426 User specified geometry.
8427 */
cristyb51dff52011-05-19 16:55:47 +00008428 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008429 size_hints->width,size_hints->height);
8430 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8431 p=geometry;
8432 while (strlen(p) != 0)
8433 {
8434 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8435 p++;
8436 else
8437 (void) CopyMagickString(p,p+1,MaxTextExtent);
8438 }
8439 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8440 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8441 &size_hints->width,&size_hints->height,&gravity);
8442 if ((flags & WidthValue) && (flags & HeightValue))
8443 size_hints->flags|=USSize;
8444 if ((flags & XValue) && (flags & YValue))
8445 {
8446 size_hints->flags|=USPosition;
8447 window_info->x=size_hints->x;
8448 window_info->y=size_hints->y;
8449 }
8450 }
8451#if !defined(PRE_R4_ICCCM)
8452 size_hints->win_gravity=gravity;
8453 size_hints->flags|=PWinGravity;
8454#endif
8455 if (window_info->id == (Window) NULL)
8456 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8457 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8458 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008459 window_info->visual,(unsigned long) window_info->mask,
8460 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008461 else
8462 {
8463 MagickStatusType
8464 mask;
8465
8466 XEvent
8467 sans_event;
8468
8469 XWindowChanges
8470 window_changes;
8471
8472 /*
8473 Window already exists; change relevant attributes.
8474 */
cristyc57f6942010-11-12 01:47:39 +00008475 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8476 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008477 mask=ConfigureNotify;
8478 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8479 window_changes.x=window_info->x;
8480 window_changes.y=window_info->y;
8481 window_changes.width=(int) window_info->width;
8482 window_changes.height=(int) window_info->height;
8483 mask=(MagickStatusType) (CWWidth | CWHeight);
8484 if (window_info->flags & USPosition)
8485 mask|=CWX | CWY;
8486 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8487 mask,&window_changes);
8488 }
8489 if (window_info->id == (Window) NULL)
8490 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8491 window_info->name);
8492 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8493 if (status == False)
8494 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8495 window_info->name);
8496 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8497 if (status == False)
8498 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8499 window_info->icon_name);
8500 if (window_info->icon_geometry != (char *) NULL)
8501 {
8502 int
8503 flags,
8504 height,
8505 width;
8506
8507 /*
8508 User specified icon geometry.
8509 */
8510 size_hints->flags|=USPosition;
8511 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8512 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8513 &manager_hints->icon_y,&width,&height,&gravity);
8514 if ((flags & XValue) && (flags & YValue))
8515 manager_hints->flags|=IconPositionHint;
8516 }
8517 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8518 size_hints,manager_hints,class_hint);
8519 if (window_name.value != (void *) NULL)
8520 {
8521 (void) XFree((void *) window_name.value);
8522 window_name.value=(unsigned char *) NULL;
8523 window_name.nitems=0;
8524 }
8525 if (icon_name.value != (void *) NULL)
8526 {
8527 (void) XFree((void *) icon_name.value);
8528 icon_name.value=(unsigned char *) NULL;
8529 icon_name.nitems=0;
8530 }
8531 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8532 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8533 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8534 (void) XFree((void *) size_hints);
8535 if (window_info->shape != MagickFalse)
8536 {
8537#if defined(MAGICKCORE_HAVE_SHAPE)
8538 int
8539 error_base,
8540 event_base;
8541
8542 /*
8543 Can we apply a non-rectangular shaping mask?
8544 */
8545 error_base=0;
8546 event_base=0;
8547 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8548 window_info->shape=MagickFalse;
8549#else
8550 window_info->shape=MagickFalse;
8551#endif
8552 }
8553 if (window_info->shared_memory)
8554 {
8555#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8556 /*
8557 Can we use shared memory with this window?
8558 */
8559 if (XShmQueryExtension(display) == 0)
8560 window_info->shared_memory=MagickFalse;
8561#else
8562 window_info->shared_memory=MagickFalse;
8563#endif
8564 }
8565 window_info->image=NewImageList();
8566 window_info->destroy=MagickFalse;
8567}
8568
8569/*
8570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8571% %
8572% %
8573% %
8574% X M a g i c k P r o g r e s s M o n i t o r %
8575% %
8576% %
8577% %
8578%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8579%
8580% XMagickProgressMonitor() displays the progress a task is making in
8581% completing a task.
8582%
8583% The format of the XMagickProgressMonitor method is:
8584%
8585% void XMagickProgressMonitor(const char *task,
8586% const MagickOffsetType quantum,const MagickSizeType span,
8587% void *client_data)
8588%
8589% A description of each parameter follows:
8590%
8591% o task: Identifies the task in progress.
8592%
8593% o quantum: Specifies the quantum position within the span which represents
8594% how much progress has been made in completing a task.
8595%
8596% o span: Specifies the span relative to completing a task.
8597%
8598% o client_data: Pointer to any client data.
8599%
8600*/
8601
8602static const char *GetLocaleMonitorMessage(const char *text)
8603{
8604 char
8605 message[MaxTextExtent],
8606 tag[MaxTextExtent];
8607
8608 const char
8609 *locale_message;
8610
8611 register char
8612 *p;
8613
8614 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8615 p=strrchr(tag,'/');
8616 if (p != (char *) NULL)
8617 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008618 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008619 locale_message=GetLocaleMessage(message);
8620 if (locale_message == message)
8621 return(text);
8622 return(locale_message);
8623}
8624
cristybcbda3f2011-09-03 13:01:22 +00008625MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008626 const MagickOffsetType quantum,const MagickSizeType span,
8627 void *magick_unused(client_data))
8628{
8629 XWindows
8630 *windows;
8631
8632 windows=XSetWindows((XWindows *) ~0);
8633 if (windows == (XWindows *) NULL)
8634 return(MagickTrue);
8635 if (windows->info.mapped != MagickFalse)
8636 XProgressMonitorWidget(windows->display,windows,
8637 GetLocaleMonitorMessage(tag),quantum,span);
8638 return(MagickTrue);
8639}
8640
8641/*
8642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8643% %
8644% %
8645% %
8646% X Q u e r y C o l o r D a t a b a s e %
8647% %
8648% %
8649% %
8650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8651%
cristy9950d572011-10-01 18:22:35 +00008652% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008653% string.
8654%
8655% The format of the XQueryColorDatabase method is:
8656%
cristy9950d572011-10-01 18:22:35 +00008657% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008658%
8659% A description of each parameter follows:
8660%
8661% o target: Specifies the color to lookup in the X color database.
8662%
cristy101ab702011-10-13 13:06:32 +00008663% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008664% color is returned as this value.
8665%
8666*/
cristy9950d572011-10-01 18:22:35 +00008667MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008668 XColor *color)
8669{
8670 Colormap
8671 colormap;
8672
8673 static Display
8674 *display = (Display *) NULL;
8675
8676 Status
8677 status;
8678
8679 XColor
8680 xcolor;
8681
8682 /*
8683 Initialize color return value.
8684 */
8685 assert(color != (XColor *) NULL);
8686 color->red=0;
8687 color->green=0;
8688 color->blue=0;
8689 color->flags=(char) (DoRed | DoGreen | DoBlue);
8690 if ((target == (char *) NULL) || (*target == '\0'))
8691 target="#ffffffffffff";
8692 /*
8693 Let the X server define the color for us.
8694 */
8695 if (display == (Display *) NULL)
8696 display=XOpenDisplay((char *) NULL);
8697 if (display == (Display *) NULL)
8698 {
8699 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8700 return(MagickFalse);
8701 }
8702 colormap=XDefaultColormap(display,XDefaultScreen(display));
8703 status=XParseColor(display,colormap,(char *) target,&xcolor);
8704 if (status == False)
8705 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8706 else
8707 {
8708 color->red=xcolor.red;
8709 color->green=xcolor.green;
8710 color->blue=xcolor.blue;
8711 color->flags=xcolor.flags;
8712 }
8713 return(status != False ? MagickTrue : MagickFalse);
8714}
8715
8716/*
8717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8718% %
8719% %
8720% %
8721% X Q u e r y P o s i t i o n %
8722% %
8723% %
8724% %
8725%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8726%
8727% XQueryPosition() gets the pointer coordinates relative to a window.
8728%
8729% The format of the XQueryPosition method is:
8730%
8731% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8732%
8733% A description of each parameter follows:
8734%
8735% o display: Specifies a connection to an X server; returned from
8736% XOpenDisplay.
8737%
8738% o window: Specifies a pointer to a Window.
8739%
8740% o x: Return the x coordinate of the pointer relative to the origin of the
8741% window.
8742%
8743% o y: Return the y coordinate of the pointer relative to the origin of the
8744% window.
8745%
8746*/
cristybcbda3f2011-09-03 13:01:22 +00008747MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008748{
8749 int
8750 x_root,
8751 y_root;
8752
8753 unsigned int
8754 mask;
8755
8756 Window
8757 root_window;
8758
8759 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8760 assert(display != (Display *) NULL);
8761 assert(window != (Window) NULL);
8762 assert(x != (int *) NULL);
8763 assert(y != (int *) NULL);
8764 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8765 x,y,&mask);
8766}
8767
8768/*
8769%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8770% %
8771% %
8772% %
8773% X R e f r e s h W i n d o w %
8774% %
8775% %
8776% %
8777%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8778%
8779% XRefreshWindow() refreshes an image in a X window.
8780%
8781% The format of the XRefreshWindow method is:
8782%
8783% void XRefreshWindow(Display *display,const XWindowInfo *window,
8784% const XEvent *event)
8785%
8786% A description of each parameter follows:
8787%
8788% o display: Specifies a connection to an X server; returned from
8789% XOpenDisplay.
8790%
8791% o window: Specifies a pointer to a XWindowInfo structure.
8792%
8793% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8794% the entire image is refreshed.
8795%
8796*/
cristybcbda3f2011-09-03 13:01:22 +00008797MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008798 const XEvent *event)
8799{
8800 int
8801 x,
8802 y;
8803
8804 unsigned int
8805 height,
8806 width;
8807
8808 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8809 assert(display != (Display *) NULL);
8810 assert(window != (XWindowInfo *) NULL);
8811 if (window->ximage == (XImage *) NULL)
8812 return;
8813 if (event != (XEvent *) NULL)
8814 {
8815 /*
8816 Determine geometry from expose event.
8817 */
8818 x=event->xexpose.x;
8819 y=event->xexpose.y;
8820 width=(unsigned int) event->xexpose.width;
8821 height=(unsigned int) event->xexpose.height;
8822 }
8823 else
8824 {
8825 XEvent
8826 sans_event;
8827
8828 /*
8829 Refresh entire window; discard outstanding expose events.
8830 */
8831 x=0;
8832 y=0;
8833 width=window->width;
8834 height=window->height;
8835 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008836 if (window->matte_pixmap != (Pixmap) NULL)
8837 {
8838#if defined(MAGICKCORE_HAVE_SHAPE)
8839 if (window->shape != MagickFalse)
8840 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8841 window->matte_pixmap,ShapeSet);
8842#endif
8843 }
cristy3ed852e2009-09-05 21:47:34 +00008844 }
8845 /*
8846 Check boundary conditions.
8847 */
8848 if ((window->ximage->width-(x+window->x)) < (int) width)
8849 width=(unsigned int) (window->ximage->width-(x+window->x));
8850 if ((window->ximage->height-(y+window->y)) < (int) height)
8851 height=(unsigned int) (window->ximage->height-(y+window->y));
8852 /*
8853 Refresh image.
8854 */
8855 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008856 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008857 if (window->pixmap != (Pixmap) NULL)
8858 {
8859 if (window->depth > 1)
8860 (void) XCopyArea(display,window->pixmap,window->id,
8861 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8862 else
8863 (void) XCopyPlane(display,window->pixmap,window->id,
8864 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8865 1L);
8866 }
8867 else
8868 {
8869#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8870 if (window->shared_memory)
8871 (void) XShmPutImage(display,window->id,window->annotate_context,
8872 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8873#endif
8874 if (window->shared_memory == MagickFalse)
8875 (void) XPutImage(display,window->id,window->annotate_context,
8876 window->ximage,x+window->x,y+window->y,x,y,width,height);
8877 }
8878 if (window->matte_pixmap != (Pixmap) NULL)
8879 (void) XSetClipMask(display,window->annotate_context,None);
8880 (void) XFlush(display);
8881}
8882
8883/*
8884%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8885% %
8886% %
8887% %
8888% X R e m o t e C o m m a n d %
8889% %
8890% %
8891% %
8892%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8893%
8894% XRemoteCommand() forces a remote display(1) to display the specified
8895% image filename.
8896%
8897% The format of the XRemoteCommand method is:
8898%
8899% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8900% const char *filename)
8901%
8902% A description of each parameter follows:
8903%
8904% o display: Specifies a connection to an X server; returned from
8905% XOpenDisplay.
8906%
8907% o window: Specifies the name or id of an X window.
8908%
8909% o filename: the name of the image filename to display.
8910%
8911*/
8912MagickExport MagickBooleanType XRemoteCommand(Display *display,
8913 const char *window,const char *filename)
8914{
8915 Atom
8916 remote_atom;
8917
8918 Window
8919 remote_window,
8920 root_window;
8921
8922 assert(filename != (char *) NULL);
8923 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8924 if (display == (Display *) NULL)
8925 display=XOpenDisplay((char *) NULL);
8926 if (display == (Display *) NULL)
8927 {
8928 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8929 return(MagickFalse);
8930 }
8931 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8932 remote_window=(Window) NULL;
8933 root_window=XRootWindow(display,XDefaultScreen(display));
8934 if (window != (char *) NULL)
8935 {
8936 /*
8937 Search window hierarchy and identify any clients by name or ID.
8938 */
8939 if (isdigit((unsigned char) *window) != 0)
8940 remote_window=XWindowByID(display,root_window,(Window)
8941 strtol((char *) window,(char **) NULL,0));
8942 if (remote_window == (Window) NULL)
8943 remote_window=XWindowByName(display,root_window,window);
8944 }
8945 if (remote_window == (Window) NULL)
8946 remote_window=XWindowByProperty(display,root_window,remote_atom);
8947 if (remote_window == (Window) NULL)
8948 {
8949 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8950 filename);
8951 return(MagickFalse);
8952 }
8953 /*
8954 Send remote command.
8955 */
8956 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8957 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8958 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8959 (void) XSync(display,MagickFalse);
8960 return(MagickTrue);
8961}
8962
8963/*
8964%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8965% %
8966% %
8967% %
8968% X R e t a i n W i n d o w C o l o r s %
8969% %
8970% %
8971% %
8972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8973%
8974% XRetainWindowColors() sets X11 color resources on a window. This preserves
8975% the colors associated with an image displayed on the window.
8976%
8977% The format of the XRetainWindowColors method is:
8978%
8979% void XRetainWindowColors(Display *display,const Window window)
8980%
8981% A description of each parameter follows:
8982%
8983% o display: Specifies a connection to an X server; returned from
8984% XOpenDisplay.
8985%
8986% o window: Specifies a pointer to a XWindowInfo structure.
8987%
8988*/
8989MagickExport void XRetainWindowColors(Display *display,const Window window)
8990{
8991 Atom
8992 property;
8993
8994 Pixmap
8995 pixmap;
8996
8997 /*
8998 Put property on the window.
8999 */
9000 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9001 assert(display != (Display *) NULL);
9002 assert(window != (Window) NULL);
9003 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9004 if (property == (Atom) NULL)
9005 {
9006 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9007 "_XSETROOT_ID");
9008 return;
9009 }
9010 pixmap=XCreatePixmap(display,window,1,1,1);
9011 if (pixmap == (Pixmap) NULL)
9012 {
9013 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9014 return;
9015 }
9016 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9017 (unsigned char *) &pixmap,1);
9018 (void) XSetCloseDownMode(display,RetainPermanent);
9019}
9020
9021/*
9022%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9023% %
9024% %
9025% %
9026% X S e l e c t W i n d o w %
9027% %
9028% %
9029% %
9030%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9031%
9032% XSelectWindow() allows a user to select a window using the mouse. If the
9033% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9034% is returned in the crop_info structure.
9035%
9036% The format of the XSelectWindow function is:
9037%
9038% target_window=XSelectWindow(display,crop_info)
9039%
9040% A description of each parameter follows:
9041%
9042% o window: XSelectWindow returns the window id.
9043%
9044% o display: Specifies a pointer to the Display structure; returned from
9045% XOpenDisplay.
9046%
9047% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9048% contains the extents of any cropping rectangle.
9049%
cristy3ed852e2009-09-05 21:47:34 +00009050*/
9051static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9052{
9053#define MinimumCropArea (unsigned int) 9
9054
9055 Cursor
9056 target_cursor;
9057
9058 GC
9059 annotate_context;
9060
9061 int
9062 presses,
9063 x_offset,
9064 y_offset;
9065
9066 Status
9067 status;
9068
9069 Window
9070 root_window,
9071 target_window;
9072
9073 XEvent
9074 event;
9075
9076 XGCValues
9077 context_values;
9078
9079 /*
9080 Initialize graphic context.
9081 */
9082 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9083 assert(display != (Display *) NULL);
9084 assert(crop_info != (RectangleInfo *) NULL);
9085 root_window=XRootWindow(display,XDefaultScreen(display));
9086 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9087 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9088 context_values.function=GXinvert;
9089 context_values.plane_mask=
9090 context_values.background ^ context_values.foreground;
9091 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009092 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009093 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9094 if (annotate_context == (GC) NULL)
9095 return(MagickFalse);
9096 /*
9097 Grab the pointer using target cursor.
9098 */
9099 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9100 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9101 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9102 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9103 GrabModeAsync,root_window,target_cursor,CurrentTime);
9104 if (status != GrabSuccess)
9105 {
9106 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9107 return((Window) NULL);
9108 }
9109 /*
9110 Select a window.
9111 */
9112 crop_info->width=0;
9113 crop_info->height=0;
9114 presses=0;
9115 target_window=(Window) NULL;
9116 x_offset=0;
9117 y_offset=0;
9118 do
9119 {
9120 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9121 (void) XDrawRectangle(display,root_window,annotate_context,
9122 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9123 (unsigned int) crop_info->height-1);
9124 /*
9125 Allow another event.
9126 */
9127 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9128 (void) XWindowEvent(display,root_window,ButtonPressMask |
9129 ButtonReleaseMask | ButtonMotionMask,&event);
9130 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9131 (void) XDrawRectangle(display,root_window,annotate_context,
9132 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9133 (unsigned int) crop_info->height-1);
9134 switch (event.type)
9135 {
9136 case ButtonPress:
9137 {
9138 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9139 event.xbutton.x,event.xbutton.y);
9140 if (target_window == (Window) NULL)
9141 target_window=root_window;
9142 x_offset=event.xbutton.x_root;
9143 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009144 crop_info->x=(ssize_t) x_offset;
9145 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009146 crop_info->width=0;
9147 crop_info->height=0;
9148 presses++;
9149 break;
9150 }
9151 case ButtonRelease:
9152 {
9153 presses--;
9154 break;
9155 }
9156 case MotionNotify:
9157 {
9158 /*
9159 Discard pending button motion events.
9160 */
9161 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009162 crop_info->x=(ssize_t) event.xmotion.x;
9163 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009164 /*
9165 Check boundary conditions.
9166 */
9167 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009168 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009169 else
9170 {
cristyecd0ab52010-05-30 14:59:20 +00009171 crop_info->width=(size_t) (crop_info->x-x_offset);
9172 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009173 }
9174 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009175 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009176 else
9177 {
cristyecd0ab52010-05-30 14:59:20 +00009178 crop_info->height=(size_t) (crop_info->y-y_offset);
9179 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009180 }
9181 }
9182 default:
9183 break;
9184 }
9185 } while ((target_window == (Window) NULL) || (presses > 0));
9186 (void) XUngrabPointer(display,CurrentTime);
9187 (void) XFreeCursor(display,target_cursor);
9188 (void) XFreeGC(display,annotate_context);
9189 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9190 {
9191 crop_info->width=0;
9192 crop_info->height=0;
9193 }
9194 if ((crop_info->width != 0) && (crop_info->height != 0))
9195 target_window=root_window;
9196 return(target_window);
9197}
9198
9199/*
9200%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9201% %
9202% %
9203% %
9204% X S e t C u r s o r S t a t e %
9205% %
9206% %
9207% %
9208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9209%
9210% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9211% reset to their default.
9212%
9213% The format of the XXSetCursorState method is:
9214%
9215% XSetCursorState(display,windows,const MagickStatusType state)
9216%
9217% A description of each parameter follows:
9218%
9219% o display: Specifies a connection to an X server; returned from
9220% XOpenDisplay.
9221%
9222% o windows: Specifies a pointer to a XWindows structure.
9223%
9224% o state: An unsigned integer greater than 0 sets the cursor state
9225% to busy, otherwise the cursor are reset to their default.
9226%
9227*/
cristybcbda3f2011-09-03 13:01:22 +00009228MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009229 const MagickStatusType state)
9230{
9231 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9232 assert(display != (Display *) NULL);
9233 assert(windows != (XWindows *) NULL);
9234 if (state)
9235 {
9236 (void) XCheckDefineCursor(display,windows->image.id,
9237 windows->image.busy_cursor);
9238 (void) XCheckDefineCursor(display,windows->pan.id,
9239 windows->pan.busy_cursor);
9240 (void) XCheckDefineCursor(display,windows->magnify.id,
9241 windows->magnify.busy_cursor);
9242 (void) XCheckDefineCursor(display,windows->command.id,
9243 windows->command.busy_cursor);
9244 }
9245 else
9246 {
9247 (void) XCheckDefineCursor(display,windows->image.id,
9248 windows->image.cursor);
9249 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9250 (void) XCheckDefineCursor(display,windows->magnify.id,
9251 windows->magnify.cursor);
9252 (void) XCheckDefineCursor(display,windows->command.id,
9253 windows->command.cursor);
9254 (void) XCheckDefineCursor(display,windows->command.id,
9255 windows->widget.cursor);
9256 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9257 }
9258 windows->info.mapped=MagickFalse;
9259}
9260
9261/*
9262%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9263% %
9264% %
9265% %
9266% X S e t W i n d o w s %
9267% %
9268% %
9269% %
9270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9271%
9272% XSetWindows() sets the X windows structure if the windows info is specified.
9273% Otherwise the current windows structure is returned.
9274%
9275% The format of the XSetWindows method is:
9276%
9277% XWindows *XSetWindows(XWindows *windows_info)
9278%
9279% A description of each parameter follows:
9280%
9281% o windows_info: Initialize the Windows structure with this information.
9282%
9283*/
cristybcbda3f2011-09-03 13:01:22 +00009284MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009285{
9286 static XWindows
9287 *windows = (XWindows *) NULL;
9288
9289 if (windows_info != (XWindows *) ~0)
9290 {
9291 windows=(XWindows *) RelinquishMagickMemory(windows);
9292 windows=windows_info;
9293 }
9294 return(windows);
9295}
9296/*
9297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9298% %
9299% %
9300% %
9301% X U s e r P r e f e r e n c e s %
9302% %
9303% %
9304% %
9305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9306%
9307% XUserPreferences() saves the preferences in a configuration file in the
9308% users' home directory.
9309%
9310% The format of the XUserPreferences method is:
9311%
9312% void XUserPreferences(XResourceInfo *resource_info)
9313%
9314% A description of each parameter follows:
9315%
9316% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9317%
9318*/
cristybcbda3f2011-09-03 13:01:22 +00009319MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009320{
9321#if defined(X11_PREFERENCES_PATH)
9322 char
9323 cache[MaxTextExtent],
9324 filename[MaxTextExtent],
9325 specifier[MaxTextExtent];
9326
9327 const char
cristy104cea82009-10-25 02:26:51 +00009328 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009329 *value;
9330
9331 XrmDatabase
9332 preferences_database;
9333
9334 /*
9335 Save user preferences to the client configuration file.
9336 */
9337 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009338 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009339 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009340 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009341 value=resource_info->backdrop ? "True" : "False";
9342 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009343 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009344 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9345 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009346 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009347 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009348 value=resource_info->confirm_exit ? "True" : "False";
9349 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009350 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009351 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009352 value=resource_info->confirm_edit ? "True" : "False";
9353 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009354 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009355 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009356 value=resource_info->display_warnings ? "True" : "False";
9357 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009358 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristycbda6112012-05-27 20:57:16 +00009359 value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9360 "True" : "False";
cristy3ed852e2009-09-05 21:47:34 +00009361 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009362 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009363 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009364 value=resource_info->gamma_correct ? "True" : "False";
9365 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009366 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9367 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009368 resource_info->undo_cache);
9369 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009370 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009371 value=resource_info->use_pixmap ? "True" : "False";
9372 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009373 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009374 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009375 ExpandFilename(filename);
9376 XrmPutFileDatabase(preferences_database,filename);
9377#endif
9378}
9379
9380/*
9381%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9382% %
9383% %
9384% %
9385% X V i s u a l C l a s s N a m e %
9386% %
9387% %
9388% %
9389%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9390%
9391% XVisualClassName() returns the visual class name as a character string.
9392%
9393% The format of the XVisualClassName method is:
9394%
9395% char *XVisualClassName(const int visual_class)
9396%
9397% A description of each parameter follows:
9398%
9399% o visual_type: XVisualClassName returns the visual class as a character
9400% string.
9401%
9402% o class: Specifies the visual class.
9403%
cristy3ed852e2009-09-05 21:47:34 +00009404*/
9405static const char *XVisualClassName(const int visual_class)
9406{
9407 switch (visual_class)
9408 {
9409 case StaticGray: return("StaticGray");
9410 case GrayScale: return("GrayScale");
9411 case StaticColor: return("StaticColor");
9412 case PseudoColor: return("PseudoColor");
9413 case TrueColor: return("TrueColor");
9414 case DirectColor: return("DirectColor");
9415 }
9416 return("unknown visual class");
9417}
9418
9419/*
9420%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9421% %
9422% %
9423% %
9424% X W a r n i n g %
9425% %
9426% %
9427% %
9428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9429%
9430% XWarning() displays a warning reason in a Notice widget.
9431%
9432% The format of the XWarning method is:
9433%
9434% void XWarning(const unsigned int warning,const char *reason,
9435% const char *description)
9436%
9437% A description of each parameter follows:
9438%
9439% o warning: Specifies the numeric warning category.
9440%
9441% o reason: Specifies the reason to display before terminating the
9442% program.
9443%
9444% o description: Specifies any description to the reason.
9445%
9446*/
cristybcbda3f2011-09-03 13:01:22 +00009447MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009448 const char *reason,const char *description)
9449{
9450 char
9451 text[MaxTextExtent];
9452
9453 XWindows
9454 *windows;
9455
9456 if (reason == (char *) NULL)
9457 return;
9458 (void) CopyMagickString(text,reason,MaxTextExtent);
9459 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9460 windows=XSetWindows((XWindows *) ~0);
9461 XNoticeWidget(windows->display,windows,text,(char *) description);
9462}
9463
9464/*
9465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9466% %
9467% %
9468% %
9469% X W i n d o w B y I D %
9470% %
9471% %
9472% %
9473%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9474%
9475% XWindowByID() locates a child window with a given ID. If not window with
9476% the given name is found, 0 is returned. Only the window specified and its
9477% subwindows are searched.
9478%
9479% The format of the XWindowByID function is:
9480%
9481% child=XWindowByID(display,window,id)
9482%
9483% A description of each parameter follows:
9484%
9485% o child: XWindowByID returns the window with the specified
9486% id. If no windows are found, XWindowByID returns 0.
9487%
9488% o display: Specifies a pointer to the Display structure; returned from
9489% XOpenDisplay.
9490%
9491% o id: Specifies the id of the window to locate.
9492%
9493*/
cristybcbda3f2011-09-03 13:01:22 +00009494MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009495 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009496{
9497 RectangleInfo
9498 rectangle_info;
9499
9500 register int
9501 i;
9502
9503 Status
9504 status;
9505
9506 unsigned int
9507 number_children;
9508
9509 Window
9510 child,
9511 *children,
9512 window;
9513
9514 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9515 assert(display != (Display *) NULL);
9516 assert(root_window != (Window) NULL);
9517 if (id == 0)
9518 return(XSelectWindow(display,&rectangle_info));
9519 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009520 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009521 status=XQueryTree(display,root_window,&child,&child,&children,
9522 &number_children);
9523 if (status == False)
9524 return((Window) NULL);
9525 window=(Window) NULL;
9526 for (i=0; i < (int) number_children; i++)
9527 {
9528 /*
9529 Search each child and their children.
9530 */
9531 window=XWindowByID(display,children[i],id);
9532 if (window != (Window) NULL)
9533 break;
9534 }
9535 if (children != (Window *) NULL)
9536 (void) XFree((void *) children);
9537 return(window);
9538}
9539
9540/*
9541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9542% %
9543% %
9544% %
9545% X W i n d o w B y N a m e %
9546% %
9547% %
9548% %
9549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9550%
9551% XWindowByName() locates a window with a given name on a display. If no
9552% window with the given name is found, 0 is returned. If more than one window
9553% has the given name, the first one is returned. Only root and its children
9554% are searched.
9555%
9556% The format of the XWindowByName function is:
9557%
9558% window=XWindowByName(display,root_window,name)
9559%
9560% A description of each parameter follows:
9561%
9562% o window: XWindowByName returns the window id.
9563%
9564% o display: Specifies a pointer to the Display structure; returned from
9565% XOpenDisplay.
9566%
9567% o root_window: Specifies the id of the root window.
9568%
9569% o name: Specifies the name of the window to locate.
9570%
9571*/
cristybcbda3f2011-09-03 13:01:22 +00009572MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009573 const char *name)
9574{
9575 register int
9576 i;
9577
9578 Status
9579 status;
9580
9581 unsigned int
9582 number_children;
9583
9584 Window
9585 *children,
9586 child,
9587 window;
9588
9589 XTextProperty
9590 window_name;
9591
9592 assert(display != (Display *) NULL);
9593 assert(root_window != (Window) NULL);
9594 assert(name != (char *) NULL);
9595 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9596 if (XGetWMName(display,root_window,&window_name) != 0)
9597 if (LocaleCompare((char *) window_name.value,name) == 0)
9598 return(root_window);
9599 status=XQueryTree(display,root_window,&child,&child,&children,
9600 &number_children);
9601 if (status == False)
9602 return((Window) NULL);
9603 window=(Window) NULL;
9604 for (i=0; i < (int) number_children; i++)
9605 {
9606 /*
9607 Search each child and their children.
9608 */
9609 window=XWindowByName(display,children[i],name);
9610 if (window != (Window) NULL)
9611 break;
9612 }
9613 if (children != (Window *) NULL)
9614 (void) XFree((void *) children);
9615 return(window);
9616}
9617
9618/*
9619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9620% %
9621% %
9622% %
9623% X W i n d o w B y P r o p e r y %
9624% %
9625% %
9626% %
9627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9628%
9629% XWindowByProperty() locates a child window with a given property. If not
9630% window with the given name is found, 0 is returned. If more than one window
9631% has the given property, the first one is returned. Only the window
9632% specified and its subwindows are searched.
9633%
9634% The format of the XWindowByProperty function is:
9635%
9636% child=XWindowByProperty(display,window,property)
9637%
9638% A description of each parameter follows:
9639%
9640% o child: XWindowByProperty returns the window id with the specified
9641% property. If no windows are found, XWindowByProperty returns 0.
9642%
9643% o display: Specifies a pointer to the Display structure; returned from
9644% XOpenDisplay.
9645%
9646% o property: Specifies the property of the window to locate.
9647%
9648*/
cristybcbda3f2011-09-03 13:01:22 +00009649MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009650 const Atom property)
9651{
9652 Atom
9653 type;
9654
9655 int
9656 format;
9657
9658 Status
9659 status;
9660
9661 unsigned char
9662 *data;
9663
9664 unsigned int
9665 i,
9666 number_children;
9667
cristyf2faecf2010-05-28 19:19:36 +00009668 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009669 after,
9670 number_items;
9671
9672 Window
9673 child,
9674 *children,
9675 parent,
9676 root;
9677
9678 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9679 assert(display != (Display *) NULL);
9680 assert(window != (Window) NULL);
9681 assert(property != (Atom) NULL);
9682 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9683 if (status == False)
9684 return((Window) NULL);
9685 type=(Atom) NULL;
9686 child=(Window) NULL;
9687 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9688 {
9689 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9690 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9691 if (data != NULL)
9692 (void) XFree((void *) data);
9693 if ((status == Success) && (type != (Atom) NULL))
9694 child=children[i];
9695 }
9696 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9697 child=XWindowByProperty(display,children[i],property);
9698 if (children != (Window *) NULL)
9699 (void) XFree((void *) children);
9700 return(child);
9701}
9702#else
9703
9704/*
9705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9706% %
9707% %
9708% %
9709% X I m p o r t I m a g e %
9710% %
9711% %
9712% %
9713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9714%
9715% XImportImage() reads an image from an X window.
9716%
9717% The format of the XImportImage method is:
9718%
cristya0dc96a2011-12-19 23:58:54 +00009719% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9720% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009721%
9722% A description of each parameter follows:
9723%
9724% o image_info: the image info..
9725%
9726% o ximage_info: Specifies a pointer to an XImportInfo structure.
9727%
cristya0dc96a2011-12-19 23:58:54 +00009728% o exception: return any errors or warnings in this structure.
9729%
cristy3ed852e2009-09-05 21:47:34 +00009730*/
cristy4bc52022012-12-13 14:15:41 +00009731MagickExport Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009732 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009733{
9734 assert(image_info != (const ImageInfo *) NULL);
9735 assert(image_info->signature == MagickSignature);
9736 if (image_info->debug != MagickFalse)
9737 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9738 image_info->filename);
9739 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009740 assert(exception != (ExceptionInfo *) NULL);
9741 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009742 return((Image *) NULL);
9743}
9744#endif
9745
9746/*
9747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9748% %
9749% %
9750% %
cristy576974e2009-10-25 20:45:31 +00009751+ X C o m p o n e n t G e n e s i s %
9752% %
9753% %
9754% %
9755%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9756%
9757% XComponentGenesis() instantiates the X component.
9758%
9759% The format of the XComponentGenesis method is:
9760%
9761% MagickBooleanType XComponentGenesis(void)
9762%
9763*/
cristy5ff4eaf2011-09-03 01:38:02 +00009764MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009765{
9766 return(MagickTrue);
9767}
9768
9769/*
9770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9771% %
9772% %
9773% %
cristy3ed852e2009-09-05 21:47:34 +00009774% X G e t I m p o r t I n f o %
9775% %
9776% %
9777% %
9778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9779%
9780% XGetImportInfo() initializes the XImportInfo structure.
9781%
9782% The format of the XGetImportInfo method is:
9783%
9784% void XGetImportInfo(XImportInfo *ximage_info)
9785%
9786% A description of each parameter follows:
9787%
9788% o ximage_info: Specifies a pointer to an ImageInfo structure.
9789%
9790*/
9791MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9792{
9793 assert(ximage_info != (XImportInfo *) NULL);
9794 ximage_info->frame=MagickFalse;
9795 ximage_info->borders=MagickFalse;
9796 ximage_info->screen=MagickFalse;
9797 ximage_info->descend=MagickTrue;
9798 ximage_info->silent=MagickFalse;
9799}