blob: 8274f1e1a7be376f31320b2a05b1cb7b539c1011 [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 %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 1992 %
18% %
19% %
cristyb56bb242014-11-25 17:12:48 +000020% Copyright 1999-2015 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,
cristy17f11b02014-12-20 19:37:04 +0000700 annotate_image->alpha_trait != UndefinedPixelTrait ? OverCompositeOp :
cristyb0a657e2012-08-29 00:45:37 +0000701 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 {
cristyc38fbf52013-11-03 13:55:54 +0000767 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",font);
cristy3ed852e2009-09-05 21:47:34 +0000768 return((char **) NULL);
769 }
770 p=font;
771 for (i=0; i < (int) fonts; i++)
772 {
773 for (q=p; *q != '\0'; q++)
774 if ((*q == ':') || (*q == ';') || (*q == ','))
775 break;
776 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
777 sizeof(*fontlist[i]));
778 if (fontlist[i] == (char *) NULL)
779 {
cristyc38fbf52013-11-03 13:55:54 +0000780 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",font);
cristy3ed852e2009-09-05 21:47:34 +0000781 return((char **) NULL);
782 }
783 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
784 p=q+1;
785 }
786 fontlist[i]=(char *) NULL;
787 return(fontlist);
788}
789
cristybcbda3f2011-09-03 13:01:22 +0000790MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000791 const XResourceInfo *resource_info,const MagickBooleanType text_font)
792{
793 static const char
794 *Fonts[]=
795 {
796 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
797 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
798 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
799 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
800 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
801 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
802 "variable",
803 "fixed",
804 (char *) NULL
805 },
806 *TextFonts[]=
807 {
808 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
809 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
810 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
811 "fixed",
812 (char *) NULL
813 };
814
815 char
816 *font_name;
817
818 register const char
819 **p;
820
821 XFontStruct
822 *font_info;
823
824 font_info=(XFontStruct *) NULL;
825 font_name=resource_info->font;
826 if (text_font != MagickFalse)
827 font_name=resource_info->text_font;
828 if ((font_name != (char *) NULL) && (*font_name != '\0'))
829 {
830 char
831 **fontlist;
832
833 register int
834 i;
835
836 /*
837 Load preferred font specified in the X resource database.
838 */
839 fontlist=FontToList(font_name);
840 if (fontlist != (char **) NULL)
841 {
842 for (i=0; fontlist[i] != (char *) NULL; i++)
843 {
844 if (font_info == (XFontStruct *) NULL)
845 font_info=XLoadQueryFont(display,fontlist[i]);
846 fontlist[i]=DestroyString(fontlist[i]);
847 }
848 fontlist=(char **) RelinquishMagickMemory(fontlist);
849 }
850 if (font_info == (XFontStruct *) NULL)
cristyc38fbf52013-11-03 13:55:54 +0000851 ThrowXWindowException(XServerError,"UnableToLoadFont",font_name);
cristy3ed852e2009-09-05 21:47:34 +0000852 }
853 /*
854 Load fonts from list of fonts until one is found.
855 */
856 p=Fonts;
857 if (text_font != MagickFalse)
858 p=TextFonts;
859 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
860 p++;
861 while (*p != (char *) NULL)
862 {
863 if (font_info != (XFontStruct *) NULL)
864 break;
865 font_info=XLoadQueryFont(display,(char *) *p);
866 p++;
867 }
868 return(font_info);
869}
870
871/*
872%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
873% %
874% %
875% %
876% X B e s t I c o n S i z e %
877% %
878% %
879% %
880%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881%
882% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
883% size that maintains the aspect ratio of the image. If the window manager
884% has preferred icon sizes, one of the preferred sizes is used.
885%
886% The format of the XBestIconSize method is:
887%
888% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
889%
890% A description of each parameter follows:
891%
892% o display: Specifies a connection to an X server; returned from
893% XOpenDisplay.
894%
895% o image: the image.
896%
897*/
cristybcbda3f2011-09-03 13:01:22 +0000898MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000899 Image *image)
900{
901 int
902 i,
903 number_sizes;
904
cristya19f1d72012-08-07 18:24:38 +0000905 double
cristy3ed852e2009-09-05 21:47:34 +0000906 scale_factor;
907
908 unsigned int
909 height,
910 icon_height,
911 icon_width,
912 width;
913
914 Window
915 root_window;
916
917 XIconSize
918 *icon_size,
919 *size_list;
920
921 /*
922 Determine if the window manager has specified preferred icon sizes.
923 */
924 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
925 assert(display != (Display *) NULL);
926 assert(window != (XWindowInfo *) NULL);
927 assert(image != (Image *) NULL);
928 window->width=MaxIconSize;
929 window->height=MaxIconSize;
930 icon_size=(XIconSize *) NULL;
931 number_sizes=0;
932 root_window=XRootWindow(display,window->screen);
933 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
934 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
935 icon_size=size_list;
936 if (icon_size == (XIconSize *) NULL)
937 {
938 /*
939 Window manager does not restrict icon size.
940 */
941 icon_size=XAllocIconSize();
942 if (icon_size == (XIconSize *) NULL)
943 {
cristyc38fbf52013-11-03 13:55:54 +0000944 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
945 image->filename);
cristy3ed852e2009-09-05 21:47:34 +0000946 return;
947 }
948 icon_size->min_width=1;
949 icon_size->max_width=MaxIconSize;
950 icon_size->min_height=1;
951 icon_size->max_height=MaxIconSize;
952 icon_size->width_inc=1;
953 icon_size->height_inc=1;
954 }
955 /*
956 Determine aspect ratio of image.
957 */
958 width=(unsigned int) image->columns;
959 height=(unsigned int) image->rows;
960 i=0;
961 if (window->crop_geometry)
962 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
963 /*
964 Look for an icon size that maintains the aspect ratio of image.
965 */
cristya19f1d72012-08-07 18:24:38 +0000966 scale_factor=(double) icon_size->max_width/width;
967 if (scale_factor > ((double) icon_size->max_height/height))
968 scale_factor=(double) icon_size->max_height/height;
cristy3ed852e2009-09-05 21:47:34 +0000969 icon_width=(unsigned int) icon_size->min_width;
970 while ((int) icon_width < icon_size->max_width)
971 {
972 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
973 break;
974 icon_width+=icon_size->width_inc;
975 }
976 icon_height=(unsigned int) icon_size->min_height;
977 while ((int) icon_height < icon_size->max_height)
978 {
979 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
980 break;
981 icon_height+=icon_size->height_inc;
982 }
983 (void) XFree((void *) icon_size);
984 window->width=icon_width;
985 window->height=icon_height;
986}
987
988/*
989%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
990% %
991% %
992% %
993% X B e s t P i x e l %
994% %
995% %
996% %
997%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
998%
999% XBestPixel() returns a pixel from an array of pixels that is closest to the
1000% requested color. If the color array is NULL, the colors are obtained from
1001% the X server.
1002%
1003% The format of the XBestPixel method is:
1004%
1005% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1006% unsigned int number_colors,XColor *color)
1007%
1008% A description of each parameter follows:
1009%
1010% o pixel: XBestPixel returns the pixel value closest to the requested
1011% color.
1012%
1013% o display: Specifies a connection to an X server; returned from
1014% XOpenDisplay.
1015%
1016% o colormap: Specifies the ID of the X server colormap.
1017%
1018% o colors: Specifies an array of XColor structures.
1019%
1020% o number_colors: Specifies the number of XColor structures in the
1021% color definition array.
1022%
1023% o color: Specifies the desired RGB value to find in the colors array.
1024%
1025*/
cristybcbda3f2011-09-03 13:01:22 +00001026MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001027 XColor *colors,unsigned int number_colors,XColor *color)
1028{
1029 MagickBooleanType
1030 query_server;
1031
cristy4c08aed2011-07-01 19:47:50 +00001032 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001033 pixel;
1034
cristya19f1d72012-08-07 18:24:38 +00001035 double
cristy3ed852e2009-09-05 21:47:34 +00001036 min_distance;
1037
cristya19f1d72012-08-07 18:24:38 +00001038 register double
cristy3ed852e2009-09-05 21:47:34 +00001039 distance;
1040
1041 register int
1042 i,
1043 j;
1044
1045 Status
1046 status;
1047
1048 /*
1049 Find closest representation for the requested RGB color.
1050 */
1051 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1052 assert(display != (Display *) NULL);
1053 assert(color != (XColor *) NULL);
1054 status=XAllocColor(display,colormap,color);
1055 if (status != False)
1056 return;
1057 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1058 if (query_server != MagickFalse)
1059 {
1060 /*
1061 Read X server colormap.
1062 */
1063 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1064 if (colors == (XColor *) NULL)
1065 {
cristyc38fbf52013-11-03 13:55:54 +00001066 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
1067 "...");
cristy3ed852e2009-09-05 21:47:34 +00001068 return;
1069 }
1070 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001071 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001072 if (number_colors > 256)
1073 number_colors=256;
1074 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1075 }
cristya19f1d72012-08-07 18:24:38 +00001076 min_distance=3.0*((double) QuantumRange+1.0)*((double)
cristy3ed852e2009-09-05 21:47:34 +00001077 QuantumRange+1.0);
1078 j=0;
1079 for (i=0; i < (int) number_colors; i++)
1080 {
cristya19f1d72012-08-07 18:24:38 +00001081 pixel.red=colors[i].red-(double) color->red;
cristy3ed852e2009-09-05 21:47:34 +00001082 distance=pixel.red*pixel.red;
1083 if (distance > min_distance)
1084 continue;
cristya19f1d72012-08-07 18:24:38 +00001085 pixel.green=colors[i].green-(double) color->green;
cristy3ed852e2009-09-05 21:47:34 +00001086 distance+=pixel.green*pixel.green;
1087 if (distance > min_distance)
1088 continue;
cristya19f1d72012-08-07 18:24:38 +00001089 pixel.blue=colors[i].blue-(double) color->blue;
cristy3ed852e2009-09-05 21:47:34 +00001090 distance+=pixel.blue*pixel.blue;
1091 if (distance > min_distance)
1092 continue;
1093 min_distance=distance;
1094 color->pixel=colors[i].pixel;
1095 j=i;
1096 }
1097 (void) XAllocColor(display,colormap,&colors[j]);
1098 if (query_server != MagickFalse)
1099 colors=(XColor *) RelinquishMagickMemory(colors);
1100}
1101
1102/*
1103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1104% %
1105% %
1106% %
1107% X B e s t V i s u a l I n f o %
1108% %
1109% %
1110% %
1111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1112%
1113% XBestVisualInfo() returns visual information for a visual that is the "best"
1114% the server supports. "Best" is defined as:
1115%
1116% 1. Restrict the visual list to those supported by the default screen.
1117%
1118% 2. If a visual type is specified, restrict the visual list to those of
1119% that type.
1120%
1121% 3. If a map type is specified, choose the visual that matches the id
1122% specified by the Standard Colormap.
1123%
1124% 4 From the list of visuals, choose one that can display the most
1125% simultaneous colors. If more than one visual can display the same
1126% number of simultaneous colors, one is chosen based on a rank.
1127%
1128% The format of the XBestVisualInfo method is:
1129%
1130% XVisualInfo *XBestVisualInfo(Display *display,
1131% XStandardColormap *map_info,XResourceInfo *resource_info)
1132%
1133% A description of each parameter follows:
1134%
1135% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1136% structure.
1137%
1138% o display: Specifies a connection to an X server; returned from
1139% XOpenDisplay.
1140%
1141% o map_info: If map_type is specified, this structure is initialized
1142% with info from the Standard Colormap.
1143%
1144% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1145%
1146*/
cristybcbda3f2011-09-03 13:01:22 +00001147MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001148 XStandardColormap *map_info,XResourceInfo *resource_info)
1149{
1150#define MaxStandardColormaps 7
1151#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1152 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1153 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1154 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1155
1156 char
1157 *map_type,
1158 *visual_type;
1159
cristyc57f6942010-11-12 01:47:39 +00001160 int
1161 visual_mask;
1162
cristy3ed852e2009-09-05 21:47:34 +00001163 register int
1164 i;
1165
cristy8891f9c2010-06-04 23:32:17 +00001166 size_t
1167 one;
1168
cristy3ed852e2009-09-05 21:47:34 +00001169 static int
1170 number_visuals;
1171
1172 static XVisualInfo
1173 visual_template;
1174
1175 XVisualInfo
1176 *visual_info,
1177 *visual_list;
1178
1179 /*
1180 Restrict visual search by screen number.
1181 */
1182 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1183 assert(display != (Display *) NULL);
1184 assert(map_info != (XStandardColormap *) NULL);
1185 assert(resource_info != (XResourceInfo *) NULL);
1186 map_type=resource_info->map_type;
1187 visual_type=resource_info->visual_type;
1188 visual_mask=VisualScreenMask;
1189 visual_template.screen=XDefaultScreen(display);
1190 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001191 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001192 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001193 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001194 visual_mask|=VisualDepthMask;
1195 if (visual_type != (char *) NULL)
1196 {
1197 /*
1198 Restrict visual search by class or visual id.
1199 */
1200 if (LocaleCompare("staticgray",visual_type) == 0)
1201 {
1202 visual_mask|=VisualClassMask;
1203 visual_template.klass=StaticGray;
1204 }
1205 else
1206 if (LocaleCompare("grayscale",visual_type) == 0)
1207 {
1208 visual_mask|=VisualClassMask;
1209 visual_template.klass=GrayScale;
1210 }
1211 else
1212 if (LocaleCompare("staticcolor",visual_type) == 0)
1213 {
1214 visual_mask|=VisualClassMask;
1215 visual_template.klass=StaticColor;
1216 }
1217 else
1218 if (LocaleCompare("pseudocolor",visual_type) == 0)
1219 {
1220 visual_mask|=VisualClassMask;
1221 visual_template.klass=PseudoColor;
1222 }
1223 else
1224 if (LocaleCompare("truecolor",visual_type) == 0)
1225 {
1226 visual_mask|=VisualClassMask;
1227 visual_template.klass=TrueColor;
1228 }
1229 else
1230 if (LocaleCompare("directcolor",visual_type) == 0)
1231 {
1232 visual_mask|=VisualClassMask;
1233 visual_template.klass=DirectColor;
1234 }
1235 else
1236 if (LocaleCompare("default",visual_type) == 0)
1237 {
1238 visual_mask|=VisualIDMask;
1239 visual_template.visualid=XVisualIDFromVisual(
1240 XDefaultVisual(display,XDefaultScreen(display)));
1241 }
1242 else
1243 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1244 {
1245 visual_mask|=VisualIDMask;
1246 visual_template.visualid=
1247 strtol(visual_type,(char **) NULL,0);
1248 }
1249 else
cristyc38fbf52013-11-03 13:55:54 +00001250 ThrowXWindowException(XServerError,
cristy3ed852e2009-09-05 21:47:34 +00001251 "UnrecognizedVisualSpecifier",visual_type);
1252 }
1253 /*
1254 Get all visuals that meet our criteria so far.
1255 */
1256 number_visuals=0;
1257 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1258 &number_visuals);
1259 visual_mask=VisualScreenMask | VisualIDMask;
1260 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1261 {
1262 /*
1263 Failed to get visual; try using the default visual.
1264 */
cristyc38fbf52013-11-03 13:55:54 +00001265 ThrowXWindowException(XServerWarning,"UnableToGetVisual",visual_type);
cristy3ed852e2009-09-05 21:47:34 +00001266 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1267 XDefaultScreen(display)));
1268 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1269 &number_visuals);
1270 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1271 return((XVisualInfo *) NULL);
cristyc38fbf52013-11-03 13:55:54 +00001272 ThrowXWindowException(XServerWarning,"UsingDefaultVisual",
cristy3ed852e2009-09-05 21:47:34 +00001273 XVisualClassName(visual_list->klass));
1274 }
1275 resource_info->color_recovery=MagickFalse;
1276 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1277 {
1278 Atom
1279 map_property;
1280
1281 char
1282 map_name[MaxTextExtent];
1283
1284 int
1285 j,
1286 number_maps;
1287
1288 Status
1289 status;
1290
1291 Window
1292 root_window;
1293
1294 XStandardColormap
1295 *map_list;
1296
1297 /*
1298 Choose a visual associated with a standard colormap.
1299 */
1300 root_window=XRootWindow(display,XDefaultScreen(display));
1301 status=False;
cristy53365c22013-11-24 15:13:41 +00001302 number_maps=0;
cristy3ed852e2009-09-05 21:47:34 +00001303 if (LocaleCompare(map_type,"list") != 0)
1304 {
1305 /*
1306 User specified Standard Colormap.
1307 */
cristyb51dff52011-05-19 16:55:47 +00001308 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001309 "RGB_%s_MAP",map_type);
1310 LocaleUpper(map_name);
1311 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1312 if (map_property != (Atom) NULL)
1313 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1314 map_property);
1315 }
1316 else
1317 {
1318 static const char
1319 *colormap[MaxStandardColormaps]=
1320 {
1321 "_HP_RGB_SMOOTH_MAP_LIST",
1322 "RGB_BEST_MAP",
1323 "RGB_DEFAULT_MAP",
1324 "RGB_GRAY_MAP",
1325 "RGB_RED_MAP",
1326 "RGB_GREEN_MAP",
1327 "RGB_BLUE_MAP",
1328 };
1329
1330 /*
1331 Choose a standard colormap from a list.
1332 */
1333 for (i=0; i < MaxStandardColormaps; i++)
1334 {
1335 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1336 if (map_property == (Atom) NULL)
1337 continue;
1338 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1339 map_property);
1340 if (status != False)
1341 break;
1342 }
1343 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1344 }
1345 if (status == False)
1346 {
cristyc38fbf52013-11-03 13:55:54 +00001347 ThrowXWindowException(XServerError,"UnableToGetStandardColormap",
cristy3ed852e2009-09-05 21:47:34 +00001348 map_type);
1349 return((XVisualInfo *) NULL);
1350 }
1351 /*
1352 Search all Standard Colormaps and visuals for ids that match.
1353 */
1354 *map_info=map_list[0];
1355#if !defined(PRE_R4_ICCCM)
1356 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1357 for (i=0; i < number_maps; i++)
1358 for (j=0; j < number_visuals; j++)
1359 if (map_list[i].visualid ==
1360 XVisualIDFromVisual(visual_list[j].visual))
1361 {
1362 *map_info=map_list[i];
1363 visual_template.visualid=XVisualIDFromVisual(
1364 visual_list[j].visual);
1365 break;
1366 }
1367 if (map_info->visualid != visual_template.visualid)
1368 {
cristyc38fbf52013-11-03 13:55:54 +00001369 ThrowXWindowException(XServerError,
cristy3ed852e2009-09-05 21:47:34 +00001370 "UnableToMatchVisualToStandardColormap",map_type);
1371 return((XVisualInfo *) NULL);
1372 }
1373#endif
1374 if (map_info->colormap == (Colormap) NULL)
1375 {
cristyc38fbf52013-11-03 13:55:54 +00001376 ThrowXWindowException(XServerError,"StandardColormapIsNotInitialized",
1377 map_type);
cristy3ed852e2009-09-05 21:47:34 +00001378 return((XVisualInfo *) NULL);
1379 }
1380 (void) XFree((void *) map_list);
1381 }
1382 else
1383 {
1384 static const unsigned int
1385 rank[]=
1386 {
1387 StaticGray,
1388 GrayScale,
1389 StaticColor,
1390 DirectColor,
1391 TrueColor,
1392 PseudoColor
1393 };
1394
1395 XVisualInfo
1396 *p;
1397
1398 /*
1399 Pick one visual that displays the most simultaneous colors.
1400 */
1401 visual_info=visual_list;
1402 p=visual_list;
1403 for (i=1; i < number_visuals; i++)
1404 {
1405 p++;
1406 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1407 visual_info=p;
1408 else
1409 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1410 if (rank[p->klass] > rank[visual_info->klass])
1411 visual_info=p;
1412 }
1413 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1414 }
1415 (void) XFree((void *) visual_list);
1416 /*
1417 Retrieve only one visual by its screen & id number.
1418 */
1419 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1420 &number_visuals);
1421 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1422 return((XVisualInfo *) NULL);
1423 return(visual_info);
1424}
1425
1426/*
1427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1428% %
1429% %
1430% %
1431% X C h e c k D e f i n e C u r s o r %
1432% %
1433% %
1434% %
1435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436%
1437% XCheckDefineCursor() prevents cursor changes on the root window.
1438%
1439% The format of the XXCheckDefineCursor method is:
1440%
1441% XCheckDefineCursor(display,window,cursor)
1442%
1443% A description of each parameter follows:
1444%
1445% o display: Specifies a connection to an X server; returned from
1446% XOpenDisplay.
1447%
1448% o window: the window.
1449%
1450% o cursor: the cursor.
1451%
1452*/
cristybcbda3f2011-09-03 13:01:22 +00001453MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001454 Cursor cursor)
1455{
1456 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1457 assert(display != (Display *) NULL);
1458 if (window == XRootWindow(display,XDefaultScreen(display)))
1459 return(0);
1460 return(XDefineCursor(display,window,cursor));
1461}
1462
1463/*
1464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1465% %
1466% %
1467% %
1468% X C h e c k R e f r e s h W i n d o w s %
1469% %
1470% %
1471% %
1472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1473%
1474% XCheckRefreshWindows() checks the X server for exposure events for a
1475% particular window and updates the areassociated with the exposure event.
1476%
1477% The format of the XCheckRefreshWindows method is:
1478%
1479% void XCheckRefreshWindows(Display *display,XWindows *windows)
1480%
1481% A description of each parameter follows:
1482%
1483% o display: Specifies a connection to an X server; returned from
1484% XOpenDisplay.
1485%
1486% o windows: Specifies a pointer to a XWindows structure.
1487%
1488*/
cristybcbda3f2011-09-03 13:01:22 +00001489MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001490{
1491 Window
1492 id;
1493
1494 XEvent
1495 event;
1496
1497 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1498 assert(display != (Display *) NULL);
1499 assert(windows != (XWindows *) NULL);
1500 XDelay(display,SuspendTime);
1501 id=windows->command.id;
1502 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1503 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1504 id=windows->image.id;
1505 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1506 XRefreshWindow(display,&windows->image,&event);
1507 XDelay(display,SuspendTime << 1);
1508 id=windows->command.id;
1509 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1510 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1511 id=windows->image.id;
1512 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1513 XRefreshWindow(display,&windows->image,&event);
1514}
1515
1516/*
1517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1518% %
1519% %
1520% %
1521% X C l i e n t M e s s a g e %
1522% %
1523% %
1524% %
1525%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1526%
1527% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1528% initialized with a particular protocol type and atom.
1529%
1530% The format of the XClientMessage function is:
1531%
1532% XClientMessage(display,window,protocol,reason,timestamp)
1533%
1534% A description of each parameter follows:
1535%
1536% o display: Specifies a pointer to the Display structure; returned from
1537% XOpenDisplay.
1538%
1539% o window: Specifies a pointer to a Window structure.
1540%
1541% o protocol: Specifies an atom value.
1542%
1543% o reason: Specifies an atom value which is the reason to send.
1544%
1545% o timestamp: Specifies a value of type Time.
1546%
1547*/
cristybcbda3f2011-09-03 13:01:22 +00001548MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001549 const Atom protocol,const Atom reason,const Time timestamp)
1550{
1551 XClientMessageEvent
1552 client_event;
1553
1554 assert(display != (Display *) NULL);
1555 client_event.type=ClientMessage;
1556 client_event.window=window;
1557 client_event.message_type=protocol;
1558 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001559 client_event.data.l[0]=(long) reason;
1560 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001561 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1562}
1563
1564/*
1565%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1566% %
1567% %
1568% %
1569+ X C l i e n t W i n d o w %
1570% %
1571% %
1572% %
1573%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1574%
1575% XClientWindow() finds a window, at or below the specified window, which has
1576% a WM_STATE property. If such a window is found, it is returned, otherwise
1577% the argument window is returned.
1578%
1579% The format of the XClientWindow function is:
1580%
1581% client_window=XClientWindow(display,target_window)
1582%
1583% A description of each parameter follows:
1584%
1585% o client_window: XClientWindow returns a window, at or below the specified
1586% window, which has a WM_STATE property otherwise the argument
1587% target_window is returned.
1588%
1589% o display: Specifies a pointer to the Display structure; returned from
1590% XOpenDisplay.
1591%
1592% o target_window: Specifies the window to find a WM_STATE property.
1593%
cristy3ed852e2009-09-05 21:47:34 +00001594*/
1595static Window XClientWindow(Display *display,Window target_window)
1596{
1597 Atom
1598 state,
1599 type;
1600
1601 int
1602 format;
1603
1604 Status
1605 status;
1606
1607 unsigned char
1608 *data;
1609
cristyf2faecf2010-05-28 19:19:36 +00001610 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001611 after,
1612 number_items;
1613
1614 Window
1615 client_window;
1616
1617 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1618 assert(display != (Display *) NULL);
1619 state=XInternAtom(display,"WM_STATE",MagickTrue);
1620 if (state == (Atom) NULL)
1621 return(target_window);
1622 type=(Atom) NULL;
1623 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1624 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1625 if ((status == Success) && (type != (Atom) NULL))
1626 return(target_window);
1627 client_window=XWindowByProperty(display,target_window,state);
1628 if (client_window == (Window) NULL)
1629 return(target_window);
1630 return(client_window);
1631}
1632
1633/*
1634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1635% %
1636% %
1637% %
cristyf34a1452009-10-24 22:29:27 +00001638+ X C o m p o n e n t T e r m i n u s %
1639% %
1640% %
1641% %
1642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1643%
1644% XComponentTerminus() destroys the module component.
1645%
1646% The format of the XComponentTerminus method is:
1647%
1648% XComponentTerminus(void)
1649%
1650*/
cristy5ff4eaf2011-09-03 01:38:02 +00001651MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001652{
1653 DestroyXResources();
1654}
1655
1656/*
1657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1658% %
1659% %
1660% %
cristy3ed852e2009-09-05 21:47:34 +00001661% X C o n f i g u r e I m a g e C o l o r m a p %
1662% %
1663% %
1664% %
1665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1666%
1667% XConfigureImageColormap() creates a new X colormap.
1668%
1669% The format of the XConfigureImageColormap method is:
1670%
1671% void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001672% XResourceInfo *resource_info,XWindows *windows,Image *image,
1673% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001674%
1675% A description of each parameter follows:
1676%
1677% o display: Specifies a connection to an X server; returned from
1678% XOpenDisplay.
1679%
1680% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1681%
1682% o windows: Specifies a pointer to a XWindows structure.
1683%
1684% o image: the image.
1685%
cristy6710d842011-10-20 23:23:00 +00001686% o exception: return any errors or warnings in this structure.
1687%
cristy3ed852e2009-09-05 21:47:34 +00001688*/
cristybcbda3f2011-09-03 13:01:22 +00001689MagickPrivate 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 Colormap
1694 colormap;
1695
1696 /*
1697 Make standard colormap.
1698 */
1699 XSetCursorState(display,windows,MagickTrue);
1700 XCheckRefreshWindows(display,windows);
1701 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
cristy6710d842011-10-20 23:23:00 +00001702 windows->map_info,windows->pixel_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00001703 colormap=windows->map_info->colormap;
1704 (void) XSetWindowColormap(display,windows->image.id,colormap);
1705 (void) XSetWindowColormap(display,windows->command.id,colormap);
1706 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1707 if (windows->magnify.mapped != MagickFalse)
1708 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1709 if (windows->pan.mapped != MagickFalse)
1710 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1711 XSetCursorState(display,windows,MagickFalse);
1712 XClientMessage(display,windows->image.id,windows->im_protocols,
1713 windows->im_update_colormap,CurrentTime);
1714}
1715
1716/*
1717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1718% %
1719% %
1720% %
1721% X C o n s t r a i n W i n d o w P o s i t i o n %
1722% %
1723% %
1724% %
1725%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1726%
1727% XConstrainWindowPosition() assures a window is positioned within the X
1728% server boundaries.
1729%
1730% The format of the XConstrainWindowPosition method is:
1731%
1732% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1733%
1734% A description of each parameter follows:
1735%
1736% o display: Specifies a pointer to the Display structure; returned from
1737% XOpenDisplay.
1738%
1739% o window_info: Specifies a pointer to a XWindowInfo structure.
1740%
1741*/
cristybcbda3f2011-09-03 13:01:22 +00001742MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001743 XWindowInfo *window_info)
1744{
1745 int
1746 limit;
1747
1748 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1749 assert(display != (Display *) NULL);
1750 assert(window_info != (XWindowInfo *) NULL);
1751 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1752 if (window_info->x < 0)
1753 window_info->x=0;
1754 else
1755 if (window_info->x > (int) limit)
1756 window_info->x=(int) limit;
1757 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1758 if (window_info->y < 0)
1759 window_info->y=0;
1760 else
1761 if (window_info->y > limit)
1762 window_info->y=limit;
1763}
1764
1765/*
1766%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1767% %
1768% %
1769% %
1770% X D e l a y %
1771% %
1772% %
1773% %
1774%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1775%
1776% XDelay() suspends program execution for the number of milliseconds
1777% specified.
1778%
1779% The format of the Delay method is:
1780%
cristybb503372010-05-27 20:51:26 +00001781% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001782%
1783% A description of each parameter follows:
1784%
1785% o display: Specifies a pointer to the Display structure; returned from
1786% XOpenDisplay.
1787%
1788% o milliseconds: Specifies the number of milliseconds to delay before
1789% returning.
1790%
1791*/
cristybcbda3f2011-09-03 13:01:22 +00001792MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001793{
1794 assert(display != (Display *) NULL);
1795 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001796 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001797}
1798
1799/*
1800%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1801% %
1802% %
1803% %
1804% X D e s t r o y R e s o u r c e I n f o %
1805% %
1806% %
1807% %
1808%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1809%
1810% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1811% structure.
1812%
1813% The format of the XDestroyResourceInfo method is:
1814%
1815% void XDestroyResourceInfo(XResourceInfo *resource_info)
1816%
1817% A description of each parameter follows:
1818%
1819% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1820%
1821*/
1822MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1823{
1824 if (resource_info->image_geometry != (char *) NULL)
1825 resource_info->image_geometry=(char *)
1826 RelinquishMagickMemory(resource_info->image_geometry);
1827 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1828 resource_info->quantize_info=DestroyQuantizeInfo(
1829 resource_info->quantize_info);
1830 if (resource_info->client_name != (char *) NULL)
1831 resource_info->client_name=(char *)
1832 RelinquishMagickMemory(resource_info->client_name);
1833 if (resource_info->name != (char *) NULL)
1834 resource_info->name=DestroyString(resource_info->name);
1835 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1836}
1837
1838/*
1839%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1840% %
1841% %
1842% %
1843% X D e s t r o y W i n d o w C o l o r s %
1844% %
1845% %
1846% %
1847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1848%
1849% XDestroyWindowColors() frees X11 color resources previously saved on a
1850% window by XRetainWindowColors or programs like xsetroot.
1851%
1852% The format of the XDestroyWindowColors method is:
1853%
1854% void XDestroyWindowColors(Display *display,Window window)
1855%
1856% A description of each parameter follows:
1857%
1858% o display: Specifies a connection to an X server; returned from
1859% XOpenDisplay.
1860%
1861% o window: Specifies a pointer to a Window structure.
1862%
1863*/
cristybcbda3f2011-09-03 13:01:22 +00001864MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001865{
1866 Atom
1867 property,
1868 type;
1869
1870 int
1871 format;
1872
1873 Status
1874 status;
1875
1876 unsigned char
1877 *data;
1878
cristyf2faecf2010-05-28 19:19:36 +00001879 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001880 after,
1881 length;
1882
1883 /*
1884 If there are previous resources on the root window, destroy them.
1885 */
1886 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1887 assert(display != (Display *) NULL);
1888 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1889 if (property == (Atom) NULL)
1890 {
cristyc38fbf52013-11-03 13:55:54 +00001891 ThrowXWindowException(XServerError,"UnableToCreateProperty",
cristy3ed852e2009-09-05 21:47:34 +00001892 "_XSETROOT_ID");
1893 return;
1894 }
1895 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1896 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1897 if (status != Success)
1898 return;
1899 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1900 {
1901 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1902 (void) XDeleteProperty(display,window,property);
1903 }
1904 if (type != None)
1905 (void) XFree((void *) data);
1906}
1907
1908/*
1909%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1910% %
1911% %
1912% %
1913% X D i s p l a y I m a g e I n f o %
1914% %
1915% %
1916% %
1917%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1918%
1919% XDisplayImageInfo() displays information about an X image.
1920%
1921% The format of the XDisplayImageInfo method is:
1922%
1923% void XDisplayImageInfo(Display *display,
1924% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001925% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001926%
1927% A description of each parameter follows:
1928%
1929% o display: Specifies a connection to an X server; returned from
1930% XOpenDisplay.
1931%
1932% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1933%
1934% o windows: Specifies a pointer to a XWindows structure.
1935%
1936% o undo_image: the undo image.
1937%
1938% o image: the image.
1939%
cristy6710d842011-10-20 23:23:00 +00001940% o exception: return any errors or warnings in this structure.
1941%
cristy3ed852e2009-09-05 21:47:34 +00001942*/
cristybcbda3f2011-09-03 13:01:22 +00001943MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001944 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001945 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001946{
1947 char
1948 filename[MaxTextExtent],
1949 *text,
1950 **textlist;
1951
1952 FILE
1953 *file;
1954
1955 int
1956 unique_file;
1957
cristybb503372010-05-27 20:51:26 +00001958 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001959 i;
1960
cristybb503372010-05-27 20:51:26 +00001961 size_t
cristy3ed852e2009-09-05 21:47:34 +00001962 number_pixels;
1963
cristy9d314ff2011-03-09 01:30:28 +00001964 ssize_t
1965 bytes;
1966
1967 unsigned int
1968 levels;
1969
cristy3ed852e2009-09-05 21:47:34 +00001970 /*
1971 Write info about the X server to a file.
1972 */
1973 assert(display != (Display *) NULL);
1974 assert(resource_info != (XResourceInfo *) NULL);
1975 assert(windows != (XWindows *) NULL);
1976 assert(image != (Image *) NULL);
1977 if (image->debug)
1978 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1979 file=(FILE *) NULL;
1980 unique_file=AcquireUniqueFileResource(filename);
1981 if (unique_file != -1)
1982 file=fdopen(unique_file,"w");
1983 if ((unique_file == -1) || (file == (FILE *) NULL))
1984 {
1985 XNoticeWidget(display,windows,"Unable to display image info",filename);
1986 return;
1987 }
1988 if (resource_info->gamma_correct != MagickFalse)
1989 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00001990 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00001991 resource_info->display_gamma);
1992 /*
1993 Write info about the X image to a file.
1994 */
cristyb51dff52011-05-19 16:55:47 +00001995 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00001996 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00001997 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00001998 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00001999 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002000 windows->visual_info->colormap_size);
2001 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002002 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002003 else
cristyb51dff52011-05-19 16:55:47 +00002004 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002005 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2006 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002007 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002008 (void) FormatLocaleFile(file," crop geometry: %s\n",
2009 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002010 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002011 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002012 else
cristyb51dff52011-05-19 16:55:47 +00002013 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002014 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002015 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002016 else
cristyb51dff52011-05-19 16:55:47 +00002017 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002018 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002019 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002020 else
cristyb51dff52011-05-19 16:55:47 +00002021 (void) FormatLocaleFile(file," shared memory: False\n");
2022 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002023 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002024 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002025 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002026 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002027 /*
2028 Write info about the undo cache to a file.
2029 */
2030 bytes=0;
2031 for (levels=0; undo_image != (Image *) NULL; levels++)
2032 {
2033 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002034 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002035 undo_image=GetPreviousImageInList(undo_image);
2036 }
cristyb51dff52011-05-19 16:55:47 +00002037 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002038 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2039 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002040 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002041 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002042 /*
2043 Write info about the image to a file.
2044 */
cristy6710d842011-10-20 23:23:00 +00002045 (void) IdentifyImage(image,file,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00002046 (void) fclose(file);
cristy3a5987c2013-11-07 14:18:46 +00002047 text=FileToString(filename,~0UL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002048 (void) RelinquishUniqueFileResource(filename);
2049 if (text == (char *) NULL)
2050 {
2051 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2052 "UnableToDisplayImageInfo");
2053 return;
2054 }
2055 textlist=StringToList(text);
2056 if (textlist != (char **) NULL)
2057 {
2058 char
2059 title[MaxTextExtent];
2060
2061 /*
2062 Display information about the image in the Text View widget.
2063 */
2064 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002065 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002066 image->filename);
2067 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2068 (char const **) textlist);
2069 for (i=0; textlist[i] != (char *) NULL; i++)
2070 textlist[i]=DestroyString(textlist[i]);
2071 textlist=(char **) RelinquishMagickMemory(textlist);
2072 }
2073 text=DestroyString(text);
2074}
2075
2076/*
2077%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2078% %
2079% %
2080% %
2081+ X D i t h e r I m a g e %
2082% %
2083% %
2084% %
2085%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2086%
2087% XDitherImage() dithers the reference image as required by the HP Color
2088% Recovery algorithm. The color values are quantized to 3 bits of red and
2089% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2090% standard colormap.
2091%
2092% The format of the XDitherImage method is:
2093%
cristy6710d842011-10-20 23:23:00 +00002094% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002095%
2096% A description of each parameter follows:
2097%
2098% o image: the image.
2099%
2100% o ximage: Specifies a pointer to a XImage structure; returned from
2101% XCreateImage.
2102%
cristy6710d842011-10-20 23:23:00 +00002103% o exception: return any errors or warnings in this structure.
2104%
cristy3ed852e2009-09-05 21:47:34 +00002105*/
cristy6710d842011-10-20 23:23:00 +00002106static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002107{
2108 static const short int
2109 dither_red[2][16]=
2110 {
2111 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2112 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2113 },
2114 dither_green[2][16]=
2115 {
2116 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2117 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2118 },
2119 dither_blue[2][16]=
2120 {
2121 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2122 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2123 };
2124
cristyc57f6942010-11-12 01:47:39 +00002125 CacheView
2126 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002127
2128 int
cristyc57f6942010-11-12 01:47:39 +00002129 value,
cristy3ed852e2009-09-05 21:47:34 +00002130 y;
2131
cristy101ab702011-10-13 13:06:32 +00002132 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002133 color;
cristy3ed852e2009-09-05 21:47:34 +00002134
2135 register char
2136 *q;
2137
cristy4c08aed2011-07-01 19:47:50 +00002138 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002139 *p;
2140
2141 register int
2142 i,
2143 j,
2144 x;
2145
2146 unsigned int
2147 scanline_pad;
2148
cristybb503372010-05-27 20:51:26 +00002149 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002150 pixel;
2151
2152 unsigned char
2153 *blue_map[2][16],
2154 *green_map[2][16],
2155 *red_map[2][16];
2156
2157 /*
2158 Allocate and initialize dither maps.
2159 */
2160 for (i=0; i < 2; i++)
2161 for (j=0; j < 16; j++)
2162 {
2163 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2164 sizeof(*red_map));
2165 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2166 sizeof(*green_map));
2167 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2168 sizeof(*blue_map));
2169 if ((red_map[i][j] == (unsigned char *) NULL) ||
2170 (green_map[i][j] == (unsigned char *) NULL) ||
2171 (blue_map[i][j] == (unsigned char *) NULL))
2172 {
cristyc38fbf52013-11-03 13:55:54 +00002173 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
2174 image->filename);
cristy3ed852e2009-09-05 21:47:34 +00002175 return;
2176 }
2177 }
2178 /*
2179 Initialize dither tables.
2180 */
2181 for (i=0; i < 2; i++)
2182 for (j=0; j < 16; j++)
2183 for (x=0; x < 256; x++)
2184 {
2185 value=x-16;
2186 if (x < 48)
2187 value=x/2+8;
2188 value+=dither_red[i][j];
2189 red_map[i][j][x]=(unsigned char)
2190 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2191 value=x-16;
2192 if (x < 48)
2193 value=x/2+8;
2194 value+=dither_green[i][j];
2195 green_map[i][j][x]=(unsigned char)
2196 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2197 value=x-32;
2198 if (x < 112)
2199 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002200 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002201 blue_map[i][j][x]=(unsigned char)
2202 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2203 }
2204 /*
2205 Dither image.
2206 */
2207 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002208 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002209 i=0;
2210 j=0;
2211 q=ximage->data;
cristy46ff2672012-12-14 15:32:26 +00002212 image_view=AcquireVirtualCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002213 for (y=0; y < (int) image->rows; y++)
2214 {
cristyc57f6942010-11-12 01:47:39 +00002215 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
cristy6710d842011-10-20 23:23:00 +00002216 exception);
cristy4c08aed2011-07-01 19:47:50 +00002217 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002218 break;
2219 for (x=0; x < (int) image->columns; x++)
2220 {
cristyada285b2012-07-07 19:00:46 +00002221 color.red=(double) ClampToQuantum((double) (red_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002222 (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002223 color.green=(double) ClampToQuantum((double) (green_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002224 (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002225 color.blue=(double) ClampToQuantum((double) (blue_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002226 (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002227 pixel=(size_t) (((size_t) color.red & 0xe0) |
2228 (((size_t) color.green & 0xe0) >> 3) |
2229 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002230 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002231 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002232 j++;
2233 if (j == 16)
2234 j=0;
2235 }
2236 q+=scanline_pad;
2237 i++;
2238 if (i == 2)
2239 i=0;
2240 }
cristyc57f6942010-11-12 01:47:39 +00002241 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002242 /*
2243 Free allocated memory.
2244 */
2245 for (i=0; i < 2; i++)
2246 for (j=0; j < 16; j++)
2247 {
2248 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2249 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2250 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2251 }
2252}
2253
2254/*
2255%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2256% %
2257% %
2258% %
2259% X D r a w I m a g e %
2260% %
2261% %
2262% %
2263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2264%
2265% XDrawImage() draws a line on the image.
2266%
2267% The format of the XDrawImage method is:
2268%
cristy6710d842011-10-20 23:23:00 +00002269% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2270% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002271%
2272% A description of each parameter follows:
2273%
2274% o display: Specifies a connection to an X server; returned from
2275% XOpenDisplay.
2276%
2277% o pixel: Specifies a pointer to a XPixelInfo structure.
2278%
2279% o draw_info: Specifies a pointer to a XDrawInfo structure.
2280%
2281% o image: the image.
2282%
cristy6710d842011-10-20 23:23:00 +00002283% o exception: return any errors or warnings in this structure.
2284%
cristy3ed852e2009-09-05 21:47:34 +00002285*/
cristybcbda3f2011-09-03 13:01:22 +00002286MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy6710d842011-10-20 23:23:00 +00002287 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2288 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002289{
cristyc57f6942010-11-12 01:47:39 +00002290 CacheView
2291 *draw_view;
2292
cristy3ed852e2009-09-05 21:47:34 +00002293 GC
2294 draw_context;
2295
2296 Image
2297 *draw_image;
2298
2299 int
2300 x,
2301 y;
2302
cristyb0a657e2012-08-29 00:45:37 +00002303 PixelTrait
2304 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002305
2306 Pixmap
2307 draw_pixmap;
2308
2309 unsigned int
2310 depth,
2311 height,
2312 width;
2313
2314 Window
2315 root_window;
2316
2317 XGCValues
2318 context_values;
2319
2320 XImage
2321 *draw_ximage;
2322
2323 /*
2324 Initialize drawd image.
2325 */
2326 assert(display != (Display *) NULL);
2327 assert(pixel != (XPixelInfo *) NULL);
2328 assert(draw_info != (XDrawInfo *) NULL);
2329 assert(image != (Image *) NULL);
2330 if (image->debug != MagickFalse)
2331 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2332 /*
2333 Initialize drawd pixmap.
2334 */
2335 root_window=XRootWindow(display,XDefaultScreen(display));
2336 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2337 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2338 draw_info->height,depth);
2339 if (draw_pixmap == (Pixmap) NULL)
2340 return(MagickFalse);
2341 /*
2342 Initialize graphics info.
2343 */
cristybb503372010-05-27 20:51:26 +00002344 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002345 context_values.foreground=0;
2346 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002347 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002348 (GCBackground | GCForeground | GCLineWidth),&context_values);
2349 if (draw_context == (GC) NULL)
2350 return(MagickFalse);
2351 /*
2352 Clear pixmap.
2353 */
2354 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2355 draw_info->height);
2356 /*
2357 Draw line to pixmap.
2358 */
2359 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002360 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002361 if (draw_info->stipple != (Pixmap) NULL)
2362 {
2363 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2364 (void) XSetStipple(display,draw_context,draw_info->stipple);
2365 }
cristy3ed852e2009-09-05 21:47:34 +00002366 switch (draw_info->element)
2367 {
2368 case PointElement:
2369 default:
2370 {
2371 (void) XDrawLines(display,draw_pixmap,draw_context,
2372 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2373 CoordModeOrigin);
2374 break;
2375 }
2376 case LineElement:
2377 {
2378 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2379 draw_info->line_info.y1,draw_info->line_info.x2,
2380 draw_info->line_info.y2);
2381 break;
2382 }
2383 case RectangleElement:
2384 {
2385 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2386 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2387 (unsigned int) draw_info->rectangle_info.width,
2388 (unsigned int) draw_info->rectangle_info.height);
2389 break;
2390 }
2391 case FillRectangleElement:
2392 {
2393 (void) XFillRectangle(display,draw_pixmap,draw_context,
2394 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2395 (unsigned int) draw_info->rectangle_info.width,
2396 (unsigned int) draw_info->rectangle_info.height);
2397 break;
2398 }
2399 case CircleElement:
2400 case EllipseElement:
2401 {
2402 (void) XDrawArc(display,draw_pixmap,draw_context,
2403 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2404 (unsigned int) draw_info->rectangle_info.width,
2405 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2406 break;
2407 }
2408 case FillCircleElement:
2409 case FillEllipseElement:
2410 {
2411 (void) XFillArc(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,0,360*64);
2415 break;
2416 }
2417 case PolygonElement:
2418 {
2419 XPoint
2420 *coordinate_info;
2421
2422 coordinate_info=draw_info->coordinate_info;
2423 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2424 (int) draw_info->number_coordinates,CoordModeOrigin);
2425 (void) XDrawLine(display,draw_pixmap,draw_context,
2426 coordinate_info[draw_info->number_coordinates-1].x,
2427 coordinate_info[draw_info->number_coordinates-1].y,
2428 coordinate_info[0].x,coordinate_info[0].y);
2429 break;
2430 }
2431 case FillPolygonElement:
2432 {
2433 (void) XFillPolygon(display,draw_pixmap,draw_context,
2434 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2435 CoordModeOrigin);
2436 break;
2437 }
2438 }
2439 (void) XFreeGC(display,draw_context);
2440 /*
2441 Initialize X image.
2442 */
2443 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2444 draw_info->height,AllPlanes,ZPixmap);
2445 if (draw_ximage == (XImage *) NULL)
2446 return(MagickFalse);
2447 (void) XFreePixmap(display,draw_pixmap);
2448 /*
2449 Initialize draw image.
2450 */
cristy6710d842011-10-20 23:23:00 +00002451 draw_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002452 if (draw_image == (Image *) NULL)
2453 return(MagickFalse);
2454 draw_image->columns=draw_info->width;
2455 draw_image->rows=draw_info->height;
2456 /*
2457 Transfer drawn X image to image.
2458 */
2459 width=(unsigned int) image->columns;
2460 height=(unsigned int) image->rows;
2461 x=0;
2462 y=0;
2463 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +00002464 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
2465 (ssize_t) y,&draw_image->background_color,exception);
cristy6710d842011-10-20 23:23:00 +00002466 if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002467 return(MagickFalse);
cristy8a46d822012-08-28 23:32:39 +00002468 draw_image->alpha_trait=BlendPixelTrait;
cristy6f5395d2012-12-14 18:30:30 +00002469 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002470 for (y=0; y < (int) draw_image->rows; y++)
2471 {
cristyc57f6942010-11-12 01:47:39 +00002472 register int
cristy3ed852e2009-09-05 21:47:34 +00002473 x;
2474
cristy4c08aed2011-07-01 19:47:50 +00002475 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002476 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002477
cristyc57f6942010-11-12 01:47:39 +00002478 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2479 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002480 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002481 break;
cristyc57f6942010-11-12 01:47:39 +00002482 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002483 {
2484 if (XGetPixel(draw_ximage,x,y) == 0)
2485 {
2486 /*
2487 Set this pixel to the background color.
2488 */
cristy803640d2011-11-17 02:11:32 +00002489 SetPixelInfoPixel(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002490 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002491 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002492 }
2493 else
2494 {
2495 /*
2496 Set this pixel to the pen color.
2497 */
cristy4c08aed2011-07-01 19:47:50 +00002498 SetPixelRed(draw_image,ScaleShortToQuantum(
2499 pixel->pen_color.red),q);
2500 SetPixelGreen(draw_image,ScaleShortToQuantum(
2501 pixel->pen_color.green),q);
2502 SetPixelBlue(draw_image,ScaleShortToQuantum(
2503 pixel->pen_color.blue),q);
2504 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2505 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002506 }
cristyed231572011-07-14 02:18:59 +00002507 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002508 }
cristyc57f6942010-11-12 01:47:39 +00002509 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002510 break;
2511 }
cristyc57f6942010-11-12 01:47:39 +00002512 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002513 XDestroyImage(draw_ximage);
2514 /*
2515 Determine draw geometry.
2516 */
2517 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2518 if ((width != (unsigned int) draw_image->columns) ||
2519 (height != (unsigned int) draw_image->rows))
2520 {
2521 char
2522 image_geometry[MaxTextExtent];
2523
2524 /*
2525 Scale image.
2526 */
cristyb51dff52011-05-19 16:55:47 +00002527 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002528 width,height);
cristye941a752011-10-15 01:52:48 +00002529 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2530 exception);
cristy3ed852e2009-09-05 21:47:34 +00002531 }
2532 if (draw_info->degrees != 0.0)
2533 {
2534 Image
2535 *rotate_image;
2536
2537 int
2538 rotations;
2539
cristya19f1d72012-08-07 18:24:38 +00002540 double
cristy3ed852e2009-09-05 21:47:34 +00002541 normalized_degrees;
2542
2543 /*
2544 Rotate image.
2545 */
cristy6710d842011-10-20 23:23:00 +00002546 rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +00002547 if (rotate_image == (Image *) NULL)
2548 return(MagickFalse);
2549 draw_image=DestroyImage(draw_image);
2550 draw_image=rotate_image;
2551 /*
2552 Annotation is relative to the degree of rotation.
2553 */
2554 normalized_degrees=draw_info->degrees;
2555 while (normalized_degrees < -45.0)
2556 normalized_degrees+=360.0;
2557 for (rotations=0; normalized_degrees > 45.0; rotations++)
2558 normalized_degrees-=90.0;
2559 switch (rotations % 4)
2560 {
2561 default:
2562 case 0:
2563 break;
2564 case 1:
2565 {
2566 /*
2567 Rotate 90 degrees.
2568 */
2569 x=x-(int) draw_image->columns/2;
2570 y=y+(int) draw_image->columns/2;
2571 break;
2572 }
2573 case 2:
2574 {
2575 /*
2576 Rotate 180 degrees.
2577 */
2578 x=x-(int) draw_image->columns;
2579 break;
2580 }
2581 case 3:
2582 {
2583 /*
2584 Rotate 270 degrees.
2585 */
2586 x=x-(int) draw_image->columns/2;
2587 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2588 break;
2589 }
2590 }
2591 }
2592 /*
2593 Composite text onto the image.
2594 */
cristy6f5395d2012-12-14 18:30:30 +00002595 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002596 for (y=0; y < (int) draw_image->rows; y++)
2597 {
cristyc57f6942010-11-12 01:47:39 +00002598 register int
cristy3ed852e2009-09-05 21:47:34 +00002599 x;
2600
cristy4c08aed2011-07-01 19:47:50 +00002601 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002602 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002603
cristyc57f6942010-11-12 01:47:39 +00002604 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2605 exception);
cristyacd2ed22011-08-30 01:44:23 +00002606 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002607 break;
cristyc57f6942010-11-12 01:47:39 +00002608 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002609 {
cristy4c08aed2011-07-01 19:47:50 +00002610 if (GetPixelAlpha(image,q) != TransparentAlpha)
2611 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002612 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002613 }
cristyc57f6942010-11-12 01:47:39 +00002614 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002615 break;
2616 }
cristyc57f6942010-11-12 01:47:39 +00002617 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002618 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2619 if (draw_info->stencil == TransparentStencil)
cristy39172402012-03-30 13:04:39 +00002620 (void) CompositeImage(image,draw_image,CopyAlphaCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002621 (ssize_t) x,(ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002622 else
2623 {
cristyb0a657e2012-08-29 00:45:37 +00002624 alpha_trait=image->alpha_trait;
cristy39172402012-03-30 13:04:39 +00002625 (void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002626 (ssize_t) x,(ssize_t) y,exception);
cristyb0a657e2012-08-29 00:45:37 +00002627 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002628 }
2629 draw_image=DestroyImage(draw_image);
2630 return(MagickTrue);
2631}
2632
2633/*
2634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2635% %
2636% %
2637% %
2638% X E r r o r %
2639% %
2640% %
2641% %
2642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2643%
2644% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2645% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002646% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2647% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002648%
2649% The format of the XError function is:
2650%
cristybcbda3f2011-09-03 13:01:22 +00002651% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002652%
2653% A description of each parameter follows:
2654%
2655% o display: Specifies a pointer to the Display structure; returned from
2656% XOpenDisplay.
2657%
2658% o error: Specifies the error event.
2659%
2660*/
2661
2662#if defined(__cplusplus) || defined(c_plusplus)
2663extern "C" {
2664#endif
2665
2666MagickExport int XError(Display *display,XErrorEvent *error)
2667{
2668 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2669 assert(display != (Display *) NULL);
2670 assert(error != (XErrorEvent *) NULL);
2671 xerror_alert=MagickTrue;
2672 switch (error->request_code)
2673 {
2674 case X_GetGeometry:
2675 {
2676 if ((int) error->error_code == BadDrawable)
2677 return(MagickFalse);
2678 break;
2679 }
2680 case X_GetWindowAttributes:
2681 case X_QueryTree:
2682 {
2683 if ((int) error->error_code == BadWindow)
2684 return(MagickFalse);
2685 break;
2686 }
2687 case X_QueryColors:
2688 {
2689 if ((int) error->error_code == BadValue)
2690 return(MagickFalse);
2691 break;
2692 }
2693 }
2694 return(MagickTrue);
2695}
2696
2697#if defined(__cplusplus) || defined(c_plusplus)
2698}
2699#endif
2700
2701/*
2702%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2703% %
2704% %
2705% %
2706% X F r e e R e s o u r c e s %
2707% %
2708% %
2709% %
2710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2711%
2712% XFreeResources() frees X11 resources.
2713%
2714% The format of the XFreeResources method is:
2715%
2716% void XFreeResources(Display *display,XVisualInfo *visual_info,
2717% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2718% XResourceInfo *resource_info,XWindowInfo *window_info)
2719% resource_info,window_info)
2720%
2721% A description of each parameter follows:
2722%
2723% o display: Specifies a connection to an X server; returned from
2724% XOpenDisplay.
2725%
2726% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2727% returned from XGetVisualInfo.
2728%
2729% o map_info: If map_type is specified, this structure is initialized
2730% with info from the Standard Colormap.
2731%
2732% o pixel: Specifies a pointer to a XPixelInfo structure.
2733%
2734% o font_info: Specifies a pointer to a XFontStruct structure.
2735%
2736% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2737%
2738% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2739%
2740*/
cristybcbda3f2011-09-03 13:01:22 +00002741MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002742 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2743 XResourceInfo *resource_info,XWindowInfo *window_info)
2744{
2745 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2746 assert(display != (Display *) NULL);
2747 assert(resource_info != (XResourceInfo *) NULL);
2748 if (window_info != (XWindowInfo *) NULL)
2749 {
2750 /*
2751 Free X image.
2752 */
2753 if (window_info->ximage != (XImage *) NULL)
2754 XDestroyImage(window_info->ximage);
2755 if (window_info->id != (Window) NULL)
2756 {
2757 /*
2758 Free destroy window and free cursors.
2759 */
2760 if (window_info->id != XRootWindow(display,visual_info->screen))
2761 (void) XDestroyWindow(display,window_info->id);
2762 if (window_info->annotate_context != (GC) NULL)
2763 (void) XFreeGC(display,window_info->annotate_context);
2764 if (window_info->highlight_context != (GC) NULL)
2765 (void) XFreeGC(display,window_info->highlight_context);
2766 if (window_info->widget_context != (GC) NULL)
2767 (void) XFreeGC(display,window_info->widget_context);
2768 if (window_info->cursor != (Cursor) NULL)
2769 (void) XFreeCursor(display,window_info->cursor);
2770 window_info->cursor=(Cursor) NULL;
2771 if (window_info->busy_cursor != (Cursor) NULL)
2772 (void) XFreeCursor(display,window_info->busy_cursor);
2773 window_info->busy_cursor=(Cursor) NULL;
2774 }
2775 }
2776 /*
2777 Free font.
2778 */
2779 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002780 {
2781 (void) XFreeFont(display,font_info);
2782 font_info=(XFontStruct *) NULL;
2783 }
cristy3ed852e2009-09-05 21:47:34 +00002784 if (map_info != (XStandardColormap *) NULL)
2785 {
2786 /*
2787 Free X Standard Colormap.
2788 */
2789 if (resource_info->map_type == (char *) NULL)
2790 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2791 (void) XFree((void *) map_info);
2792 }
2793 /*
2794 Free X visual info.
2795 */
2796 if (visual_info != (XVisualInfo *) NULL)
2797 (void) XFree((void *) visual_info);
2798 if (resource_info->close_server != MagickFalse)
2799 (void) XCloseDisplay(display);
2800}
2801
2802/*
2803%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2804% %
2805% %
2806% %
2807% X F r e e S t a n d a r d C o l o r m a p %
2808% %
2809% %
2810% %
2811%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2812%
2813% XFreeStandardColormap() frees an X11 colormap.
2814%
2815% The format of the XFreeStandardColormap method is:
2816%
2817% void XFreeStandardColormap(Display *display,
2818% const XVisualInfo *visual_info,XStandardColormap *map_info,
2819% XPixelInfo *pixel)
2820%
2821% A description of each parameter follows:
2822%
2823% o display: Specifies a connection to an X server; returned from
2824% XOpenDisplay.
2825%
2826% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2827% returned from XGetVisualInfo.
2828%
2829% o map_info: If map_type is specified, this structure is initialized
2830% with info from the Standard Colormap.
2831%
2832% o pixel: Specifies a pointer to a XPixelInfo structure.
2833%
2834*/
cristybcbda3f2011-09-03 13:01:22 +00002835MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002836 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2837{
2838 /*
2839 Free colormap.
2840 */
2841 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2842 assert(display != (Display *) NULL);
2843 assert(visual_info != (XVisualInfo *) NULL);
2844 assert(map_info != (XStandardColormap *) NULL);
2845 (void) XFlush(display);
2846 if (map_info->colormap != (Colormap) NULL)
2847 {
2848 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2849 (void) XFreeColormap(display,map_info->colormap);
2850 else
2851 if (pixel != (XPixelInfo *) NULL)
2852 if ((visual_info->klass != TrueColor) &&
2853 (visual_info->klass != DirectColor))
2854 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2855 (int) pixel->colors,0);
2856 }
2857 map_info->colormap=(Colormap) NULL;
2858 if (pixel != (XPixelInfo *) NULL)
2859 {
cristyf2faecf2010-05-28 19:19:36 +00002860 if (pixel->pixels != (unsigned long *) NULL)
2861 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2862 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002863 }
2864}
2865
2866/*
2867%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2868% %
2869% %
2870% %
2871% X G e t A n n o t a t e I n f o %
2872% %
2873% %
2874% %
2875%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2876%
2877% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2878%
2879% The format of the XGetAnnotateInfo method is:
2880%
2881% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2882%
2883% A description of each parameter follows:
2884%
2885% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2886%
2887*/
cristybcbda3f2011-09-03 13:01:22 +00002888MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002889{
2890 /*
2891 Initialize annotate structure.
2892 */
2893 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2894 assert(annotate_info != (XAnnotateInfo *) NULL);
2895 annotate_info->x=0;
2896 annotate_info->y=0;
2897 annotate_info->width=0;
2898 annotate_info->height=0;
2899 annotate_info->stencil=ForegroundStencil;
2900 annotate_info->degrees=0.0;
2901 annotate_info->font_info=(XFontStruct *) NULL;
2902 annotate_info->text=(char *) NULL;
2903 *annotate_info->geometry='\0';
2904 annotate_info->previous=(XAnnotateInfo *) NULL;
2905 annotate_info->next=(XAnnotateInfo *) NULL;
2906 (void) XSupportsLocale();
2907 (void) XSetLocaleModifiers("");
2908}
2909
2910/*
2911%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2912% %
2913% %
2914% %
2915% X G e t M a p I n f o %
2916% %
2917% %
2918% %
2919%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2920%
2921% XGetMapInfo() initializes the XStandardColormap structure.
2922%
2923% The format of the XStandardColormap method is:
2924%
2925% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2926% XStandardColormap *map_info)
2927%
2928% A description of each parameter follows:
2929%
2930% o colormap: Specifies the ID of the X server colormap.
2931%
2932% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2933% returned from XGetVisualInfo.
2934%
2935% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2936%
2937*/
cristybcbda3f2011-09-03 13:01:22 +00002938MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002939 const Colormap colormap,XStandardColormap *map_info)
2940{
2941 /*
2942 Initialize map info.
2943 */
2944 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2945 assert(visual_info != (XVisualInfo *) NULL);
2946 assert(map_info != (XStandardColormap *) NULL);
2947 map_info->colormap=colormap;
2948 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002949 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002950 if (map_info->red_max != 0)
2951 while ((map_info->red_max & 0x01) == 0)
2952 {
2953 map_info->red_max>>=1;
2954 map_info->red_mult<<=1;
2955 }
2956 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002957 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002958 if (map_info->green_max != 0)
2959 while ((map_info->green_max & 0x01) == 0)
2960 {
2961 map_info->green_max>>=1;
2962 map_info->green_mult<<=1;
2963 }
2964 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002965 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002966 if (map_info->blue_max != 0)
2967 while ((map_info->blue_max & 0x01) == 0)
2968 {
2969 map_info->blue_max>>=1;
2970 map_info->blue_mult<<=1;
2971 }
2972 map_info->base_pixel=0;
2973}
2974
2975/*
2976%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2977% %
2978% %
2979% %
2980% X G e t P i x e l I n f o %
2981% %
2982% %
2983% %
2984%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2985%
cristy101ab702011-10-13 13:06:32 +00002986% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00002987%
cristy4c08aed2011-07-01 19:47:50 +00002988% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00002989%
cristy4c08aed2011-07-01 19:47:50 +00002990% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002991% const XStandardColormap *map_info,const XResourceInfo *resource_info,
2992% Image *image,XPixelInfo *pixel)
2993% pixel)
2994%
2995% A description of each parameter follows:
2996%
2997% o display: Specifies a connection to an X server; returned from
2998% XOpenDisplay.
2999%
3000% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3001% returned from XGetVisualInfo.
3002%
3003% o map_info: If map_type is specified, this structure is initialized
3004% with info from the Standard Colormap.
3005%
3006% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3007%
3008% o image: the image.
3009%
3010% o pixel: Specifies a pointer to a XPixelInfo structure.
3011%
3012*/
cristybcbda3f2011-09-03 13:01:22 +00003013MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003014 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3015 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3016{
3017 static const char
3018 *PenColors[MaxNumberPens]=
3019 {
3020 "#000000000000", /* black */
3021 "#00000000ffff", /* blue */
3022 "#0000ffffffff", /* cyan */
3023 "#0000ffff0000", /* green */
3024 "#bdbdbdbdbdbd", /* gray */
3025 "#ffff00000000", /* red */
3026 "#ffff0000ffff", /* magenta */
3027 "#ffffffff0000", /* yellow */
3028 "#ffffffffffff", /* white */
3029 "#bdbdbdbdbdbd", /* gray */
3030 "#bdbdbdbdbdbd" /* gray */
3031 };
3032
3033 Colormap
3034 colormap;
3035
cristybcdf5672012-05-24 22:58:54 +00003036 extern const char
3037 BorderColor[],
3038 ForegroundColor[];
3039
cristybb503372010-05-27 20:51:26 +00003040 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003041 i;
3042
3043 Status
3044 status;
3045
3046 unsigned int
3047 packets;
3048
3049 /*
3050 Initialize pixel info.
3051 */
3052 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3053 assert(display != (Display *) NULL);
3054 assert(visual_info != (XVisualInfo *) NULL);
3055 assert(map_info != (XStandardColormap *) NULL);
3056 assert(resource_info != (XResourceInfo *) NULL);
3057 assert(pixel != (XPixelInfo *) NULL);
3058 pixel->colors=0;
3059 if (image != (Image *) NULL)
3060 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003061 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003062 packets=(unsigned int)
3063 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003064 if (pixel->pixels != (unsigned long *) NULL)
3065 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3066 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003067 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003068 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003069 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3070 image->filename);
3071 /*
3072 Set foreground color.
3073 */
3074 colormap=map_info->colormap;
3075 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3076 &pixel->foreground_color);
3077 status=XParseColor(display,colormap,resource_info->foreground_color,
3078 &pixel->foreground_color);
3079 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003080 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003081 resource_info->foreground_color);
3082 pixel->foreground_color.pixel=
3083 XStandardPixel(map_info,&pixel->foreground_color);
3084 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3085 /*
3086 Set background color.
3087 */
3088 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3089 status=XParseColor(display,colormap,resource_info->background_color,
3090 &pixel->background_color);
3091 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003092 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003093 resource_info->background_color);
3094 pixel->background_color.pixel=
3095 XStandardPixel(map_info,&pixel->background_color);
3096 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3097 /*
3098 Set border color.
3099 */
3100 (void) XParseColor(display,colormap,(char *) BorderColor,
3101 &pixel->border_color);
3102 status=XParseColor(display,colormap,resource_info->border_color,
3103 &pixel->border_color);
3104 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003105 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003106 resource_info->border_color);
3107 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3108 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3109 /*
3110 Set matte color.
3111 */
3112 pixel->matte_color=pixel->background_color;
3113 if (resource_info->matte_color != (char *) NULL)
3114 {
3115 /*
3116 Matte color is specified as a X resource or command line argument.
3117 */
3118 status=XParseColor(display,colormap,resource_info->matte_color,
3119 &pixel->matte_color);
3120 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003121 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003122 resource_info->matte_color);
3123 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3124 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3125 }
3126 /*
3127 Set highlight color.
3128 */
cristy5467fcf2014-05-18 17:20:55 +00003129 pixel->highlight_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003130 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3131 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
cristy5467fcf2014-05-18 17:20:55 +00003132 pixel->highlight_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003133 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3134 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
cristy5467fcf2014-05-18 17:20:55 +00003135 pixel->highlight_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003136 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3137 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
cristy5467fcf2014-05-18 17:20:55 +00003138 pixel->highlight_color.pixel=XStandardPixel(map_info,&pixel->highlight_color);
cristy3ed852e2009-09-05 21:47:34 +00003139 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3140 /*
3141 Set shadow color.
3142 */
cristya19f1d72012-08-07 18:24:38 +00003143 pixel->shadow_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003144 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003145 pixel->shadow_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003146 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003147 pixel->shadow_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003148 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3149 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3150 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3151 /*
3152 Set depth color.
3153 */
cristya19f1d72012-08-07 18:24:38 +00003154 pixel->depth_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003155 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003156 pixel->depth_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003157 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003158 pixel->depth_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003159 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3160 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3161 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3162 /*
3163 Set trough color.
3164 */
cristya19f1d72012-08-07 18:24:38 +00003165 pixel->trough_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003166 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003167 pixel->trough_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003168 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003169 pixel->trough_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003170 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3171 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3172 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3173 /*
3174 Set pen color.
3175 */
3176 for (i=0; i < MaxNumberPens; i++)
3177 {
3178 (void) XParseColor(display,colormap,(char *) PenColors[i],
3179 &pixel->pen_colors[i]);
3180 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3181 &pixel->pen_colors[i]);
3182 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003183 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003184 resource_info->pen_colors[i]);
3185 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3186 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3187 }
3188 pixel->box_color=pixel->background_color;
3189 pixel->pen_color=pixel->foreground_color;
3190 pixel->box_index=0;
3191 pixel->pen_index=1;
3192 if (image != (Image *) NULL)
3193 {
3194 if ((resource_info->gamma_correct != MagickFalse) &&
3195 (image->gamma != 0.0))
3196 {
3197 GeometryInfo
3198 geometry_info;
3199
3200 MagickStatusType
3201 flags;
3202
3203 /*
3204 Initialize map relative to display and image gamma.
3205 */
3206 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3207 red_gamma=geometry_info.rho;
3208 green_gamma=geometry_info.sigma;
3209 if ((flags & SigmaValue) == 0)
3210 green_gamma=red_gamma;
3211 blue_gamma=geometry_info.xi;
3212 if ((flags & XiValue) == 0)
3213 blue_gamma=red_gamma;
3214 red_gamma*=image->gamma;
3215 green_gamma*=image->gamma;
3216 blue_gamma*=image->gamma;
3217 }
3218 if (image->storage_class == PseudoClass)
3219 {
3220 /*
3221 Initialize pixel array for images of type PseudoClass.
3222 */
cristybb503372010-05-27 20:51:26 +00003223 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003224 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003225 for (i=0; i < MaxNumberPens; i++)
3226 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3227 pixel->colors+=MaxNumberPens;
3228 }
3229 }
3230}
3231
3232/*
3233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3234% %
3235% %
3236% %
3237% X G e t R e s o u r c e C l a s s %
3238% %
3239% %
3240% %
3241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3242%
3243% XGetResourceClass() queries the X server for the specified resource name or
3244% class. If the resource name or class is not defined in the database, the
3245% supplied default value is returned.
3246%
3247% The format of the XGetResourceClass method is:
3248%
3249% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3250% const char *keyword,char *resource_default)
3251%
3252% A description of each parameter follows:
3253%
3254% o database: Specifies a resource database; returned from
3255% XrmGetStringDatabase.
3256%
3257% o client_name: Specifies the application name used to retrieve resource
3258% info from the X server database.
3259%
3260% o keyword: Specifies the keyword of the value being retrieved.
3261%
3262% o resource_default: Specifies the default value to return if the query
3263% fails to find the specified keyword/class.
3264%
3265*/
3266MagickExport char *XGetResourceClass(XrmDatabase database,
3267 const char *client_name,const char *keyword,char *resource_default)
3268{
3269 char
3270 resource_class[MaxTextExtent],
3271 resource_name[MaxTextExtent];
3272
3273 static char
3274 *resource_type;
3275
3276 Status
3277 status;
3278
3279 XrmValue
3280 resource_value;
3281
3282 if (database == (XrmDatabase) NULL)
3283 return(resource_default);
3284 *resource_name='\0';
3285 *resource_class='\0';
3286 if (keyword != (char *) NULL)
3287 {
3288 int
3289 c,
3290 k;
3291
3292 /*
3293 Initialize resource keyword and class.
3294 */
cristyb51dff52011-05-19 16:55:47 +00003295 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003296 client_name,keyword);
3297 c=(int) (*client_name);
3298 if ((c >= XK_a) && (c <= XK_z))
3299 c-=(XK_a-XK_A);
3300 else
3301 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3302 c-=(XK_agrave-XK_Agrave);
3303 else
3304 if ((c >= XK_oslash) && (c <= XK_thorn))
3305 c-=(XK_oslash-XK_Ooblique);
3306 k=(int) (*keyword);
3307 if ((k >= XK_a) && (k <= XK_z))
3308 k-=(XK_a-XK_A);
3309 else
3310 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3311 k-=(XK_agrave-XK_Agrave);
3312 else
3313 if ((k >= XK_oslash) && (k <= XK_thorn))
3314 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003315 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003316 client_name+1,k,keyword+1);
3317 }
3318 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3319 &resource_value);
3320 if (status == False)
3321 return(resource_default);
3322 return(resource_value.addr);
3323}
3324
3325/*
3326%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3327% %
3328% %
3329% %
3330% X G e t R e s o u r c e D a t a b a s e %
3331% %
3332% %
3333% %
3334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3335%
3336% XGetResourceDatabase() creates a new resource database and initializes it.
3337%
3338% The format of the XGetResourceDatabase method is:
3339%
3340% XrmDatabase XGetResourceDatabase(Display *display,
3341% const char *client_name)
3342%
3343% A description of each parameter follows:
3344%
3345% o database: XGetResourceDatabase() returns the database after it is
3346% initialized.
3347%
3348% o display: Specifies a connection to an X server; returned from
3349% XOpenDisplay.
3350%
3351% o client_name: Specifies the application name used to retrieve resource
3352% info from the X server database.
3353%
3354*/
3355MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3356 const char *client_name)
3357{
3358 char
3359 filename[MaxTextExtent];
3360
3361 int
3362 c;
3363
3364 register const char
3365 *p;
3366
3367 XrmDatabase
3368 resource_database,
3369 server_database;
3370
3371 if (display == (Display *) NULL)
3372 return((XrmDatabase) NULL);
3373 assert(client_name != (char *) NULL);
3374 /*
3375 Initialize resource database.
3376 */
3377 XrmInitialize();
3378 (void) XGetDefault(display,(char *) client_name,"dummy");
3379 resource_database=XrmGetDatabase(display);
3380 /*
3381 Combine application database.
3382 */
3383 if (client_name != (char *) NULL)
3384 {
3385 /*
3386 Get basename of client.
3387 */
3388 p=client_name+(strlen(client_name)-1);
3389 while ((p > client_name) && (*p != '/'))
3390 p--;
3391 if (*p == '/')
3392 client_name=p+1;
3393 }
3394 c=(int) (*client_name);
3395 if ((c >= XK_a) && (c <= XK_z))
3396 c-=(XK_a-XK_A);
3397 else
3398 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3399 c-=(XK_agrave-XK_Agrave);
3400 else
3401 if ((c >= XK_oslash) && (c <= XK_thorn))
3402 c-=(XK_oslash-XK_Ooblique);
3403#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003404 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003405 X11_APPLICATION_PATH,c,client_name+1);
3406 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3407#endif
3408 if (XResourceManagerString(display) != (char *) NULL)
3409 {
3410 /*
3411 Combine server database.
3412 */
3413 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3414 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3415 }
3416 /*
3417 Merge user preferences database.
3418 */
3419#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003420 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003421 X11_PREFERENCES_PATH,client_name);
3422 ExpandFilename(filename);
3423 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3424#endif
3425 return(resource_database);
3426}
3427
3428/*
3429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3430% %
3431% %
3432% %
3433% X G e t R e s o u r c e I n f o %
3434% %
3435% %
3436% %
3437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3438%
3439% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3440%
3441% The format of the XGetResourceInfo method is:
3442%
3443% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3444% const char *client_name,XResourceInfo *resource_info)
3445%
3446% A description of each parameter follows:
3447%
3448% o image_info: the image info.
3449%
3450% o database: Specifies a resource database; returned from
3451% XrmGetStringDatabase.
3452%
3453% o client_name: Specifies the application name used to retrieve
3454% resource info from the X server database.
3455%
3456% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3457%
3458*/
3459MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3460 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3461{
3462 char
cristy00976d82011-02-20 20:31:28 +00003463 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003464 *resource_value;
3465
cristybcdf5672012-05-24 22:58:54 +00003466 extern const char
3467 BorderColor[],
3468 ForegroundColor[];
3469
cristy3ed852e2009-09-05 21:47:34 +00003470 /*
3471 Initialize resource info fields.
3472 */
3473 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3474 assert(resource_info != (XResourceInfo *) NULL);
3475 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3476 resource_info->resource_database=database;
3477 resource_info->image_info=(ImageInfo *) image_info;
3478 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3479 XMagickProgressMonitor,(void *) NULL);
3480 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3481 resource_info->close_server=MagickTrue;
3482 resource_info->client_name=AcquireString(client_name);
3483 resource_value=XGetResourceClass(database,client_name,"backdrop",
3484 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003485 resource_info->backdrop=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003486 resource_info->background_color=XGetResourceInstance(database,client_name,
3487 "background",(char *) "#d6d6d6d6d6d6");
3488 resource_info->border_color=XGetResourceInstance(database,client_name,
3489 "borderColor",BorderColor);
3490 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3491 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003492 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3493 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003494 resource_value=XGetResourceClass(database,client_name,"colormap",
3495 (char *) "shared");
3496 resource_info->colormap=UndefinedColormap;
3497 if (LocaleCompare("private",resource_value) == 0)
3498 resource_info->colormap=PrivateColormap;
3499 if (LocaleCompare("shared",resource_value) == 0)
3500 resource_info->colormap=SharedColormap;
3501 if (resource_info->colormap == UndefinedColormap)
cristyc38fbf52013-11-03 13:55:54 +00003502 ThrowXWindowException(OptionError,"UnrecognizedColormapType",
cristy3ed852e2009-09-05 21:47:34 +00003503 resource_value);
3504 resource_value=XGetResourceClass(database,client_name,
3505 "colorRecovery",(char *) "False");
anthony6f201312012-03-30 04:08:15 +00003506 resource_info->color_recovery=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003507 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3508 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003509 resource_info->confirm_exit=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003510 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3511 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003512 resource_info->confirm_edit=IsStringTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003513 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003514 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003515 resource_info->display_gamma=XGetResourceClass(database,client_name,
3516 "displayGamma",(char *) "2.2");
3517 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3518 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003519 resource_info->display_warnings=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003520 resource_info->font=XGetResourceClass(database,client_name,"font",
3521 (char *) NULL);
3522 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3523 resource_info->font);
3524 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3525 (char *) "fixed");
3526 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3527 (char *) "variable");
3528 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3529 (char *) "5x8");
3530 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3531 (char *) "6x10");
3532 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3533 (char *) "7x13bold");
3534 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3535 (char *) "8x13bold");
3536 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3537 (char *) "9x15bold");
3538 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3539 (char *) "10x20");
3540 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3541 (char *) "12x24");
3542 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3543 (char *) "fixed");
3544 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3545 (char *) "fixed");
3546 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3547 "foreground",ForegroundColor);
3548 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
cristy8bc259b2012-06-21 23:53:15 +00003549 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003550 resource_info->gamma_correct=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003551 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3552 client_name,"geometry",(char *) NULL));
3553 resource_value=XGetResourceClass(database,client_name,"gravity",
3554 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003555 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003556 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003557 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3558 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003559 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3560 "iconGeometry",(char *) NULL);
3561 resource_value=XGetResourceClass(database,client_name,"iconic",
3562 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003563 resource_info->iconic=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003564 resource_value=XGetResourceClass(database,client_name,"immutable",
3565 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3566 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003567 resource_info->immutable=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003568 resource_value=XGetResourceClass(database,client_name,"magnify",
3569 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003570 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003571 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3572 (char *) NULL);
3573 resource_info->matte_color=XGetResourceInstance(database,client_name,
3574 "mattecolor",(char *) NULL);
3575 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3576 "name",(char *) NULL));
3577 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3578 (char *) "black");
3579 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3580 (char *) "blue");
3581 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3582 (char *) "cyan");
3583 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3584 (char *) "green");
3585 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3586 (char *) "gray");
3587 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3588 (char *) "red");
3589 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3590 (char *) "magenta");
3591 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3592 (char *) "yellow");
3593 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3594 (char *) "white");
3595 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3596 (char *) "gray");
3597 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3598 (char *) "gray");
3599 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003600 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003601 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003602 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003603 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3604 "font",(char *) "fixed");
3605 resource_info->text_font=XGetResourceClass(database,client_name,
3606 "textFontList",resource_info->text_font);
3607 resource_info->title=XGetResourceClass(database,client_name,"title",
3608 (char *) NULL);
3609 resource_value=XGetResourceClass(database,client_name,"undoCache",
cristy92befbd2012-09-16 14:08:12 +00003610 (char *) "256");
cristye27293e2009-12-18 02:53:20 +00003611 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003612 resource_value=XGetResourceClass(database,client_name,"update",
3613 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003614 resource_info->update=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003615 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3616 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003617 resource_info->use_pixmap=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003618 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3619 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003620 resource_info->use_shared_memory=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003621 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3622 (char *) NULL);
3623 resource_info->window_group=XGetResourceClass(database,client_name,
3624 "windowGroup",(char *) NULL);
3625 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3626 (char *) NULL);
3627 resource_info->write_filename=XGetResourceClass(database,client_name,
3628 "writeFilename",(char *) NULL);
3629}
3630
3631/*
3632%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3633% %
3634% %
3635% %
3636% X G e t R e s o u r c e I n s t a n c e %
3637% %
3638% %
3639% %
3640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3641%
3642% XGetResourceInstance() queries the X server for the specified resource name.
3643% If the resource name is not defined in the database, the supplied default
3644% value is returned.
3645%
3646% The format of the XGetResourceInstance method is:
3647%
3648% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3649% const char *keyword,const char *resource_default)
3650%
3651% A description of each parameter follows:
3652%
3653% o database: Specifies a resource database; returned from
3654% XrmGetStringDatabase.
3655%
3656% o client_name: Specifies the application name used to retrieve
3657% resource info from the X server database.
3658%
3659% o keyword: Specifies the keyword of the value being retrieved.
3660%
3661% o resource_default: Specifies the default value to return if the query
3662% fails to find the specified keyword/class.
3663%
3664*/
3665MagickExport char *XGetResourceInstance(XrmDatabase database,
3666 const char *client_name,const char *keyword,const char *resource_default)
3667{
3668 char
3669 *resource_type,
3670 resource_name[MaxTextExtent];
3671
3672 Status
3673 status;
3674
3675 XrmValue
3676 resource_value;
3677
3678 if (database == (XrmDatabase) NULL)
3679 return((char *) resource_default);
3680 *resource_name='\0';
3681 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003682 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003683 keyword);
3684 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3685 &resource_value);
3686 if (status == False)
3687 return((char *) resource_default);
3688 return(resource_value.addr);
3689}
3690
3691/*
3692%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3693% %
3694% %
3695% %
3696% X G e t S c r e e n D e n s i t y %
3697% %
3698% %
3699% %
3700%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3701%
3702% XGetScreenDensity() returns the density of the X server screen in
3703% dots-per-inch.
3704%
3705% The format of the XGetScreenDensity method is:
3706%
3707% char *XGetScreenDensity(Display *display)
3708%
3709% A description of each parameter follows:
3710%
3711% o density: XGetScreenDensity() returns the density of the X screen in
3712% dots-per-inch.
3713%
3714% o display: Specifies a connection to an X server; returned from
3715% XOpenDisplay.
3716%
3717*/
3718MagickExport char *XGetScreenDensity(Display *display)
3719{
3720 char
3721 density[MaxTextExtent];
3722
3723 double
3724 x_density,
3725 y_density;
3726
3727 /*
3728 Set density as determined by screen size.
3729 */
3730 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3731 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3732 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3733 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003734 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003735 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003736 return(GetPageGeometry(density));
3737}
3738
3739/*
3740%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3741% %
3742% %
3743% %
3744+ X G e t S u b w i n d o w %
3745% %
3746% %
3747% %
3748%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3749%
3750% XGetSubwindow() returns the subwindow of a window chosen the user with the
3751% pointer and a button press.
3752%
3753% The format of the XGetSubwindow method is:
3754%
3755% Window XGetSubwindow(Display *display,Window window,int x,int y)
3756%
3757% A description of each parameter follows:
3758%
3759% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3760% otherwise the subwindow is returned.
3761%
3762% o display: Specifies a connection to an X server; returned from
3763% XOpenDisplay.
3764%
3765% o window: Specifies a pointer to a Window.
3766%
3767% o x: the x coordinate of the pointer relative to the origin of the
3768% window.
3769%
3770% o y: the y coordinate of the pointer relative to the origin of the
3771% window.
3772%
cristy3ed852e2009-09-05 21:47:34 +00003773*/
3774static Window XGetSubwindow(Display *display,Window window,int x,int y)
3775{
3776 int
3777 x_offset,
3778 y_offset;
3779
3780 Status
3781 status;
3782
3783 Window
3784 source_window,
3785 target_window;
3786
3787 assert(display != (Display *) NULL);
3788 source_window=XRootWindow(display,XDefaultScreen(display));
3789 if (window == (Window) NULL)
3790 return(source_window);
3791 target_window=window;
3792 for ( ; ; )
3793 {
3794 status=XTranslateCoordinates(display,source_window,window,x,y,
3795 &x_offset,&y_offset,&target_window);
3796 if (status != True)
3797 break;
3798 if (target_window == (Window) NULL)
3799 break;
3800 source_window=window;
3801 window=target_window;
3802 x=x_offset;
3803 y=y_offset;
3804 }
3805 if (target_window == (Window) NULL)
3806 target_window=window;
3807 return(target_window);
3808}
3809
3810/*
3811%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3812% %
3813% %
3814% %
3815% X G e t W i n d o w C o l o r %
3816% %
3817% %
3818% %
3819%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3820%
3821% XGetWindowColor() returns the color of a pixel interactively chosen from the
3822% X server.
3823%
3824% The format of the XGetWindowColor method is:
3825%
3826% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003827% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003828%
3829% A description of each parameter follows:
3830%
3831% o display: Specifies a connection to an X server; returned from
3832% XOpenDisplay.
3833%
3834% o windows: Specifies a pointer to a XWindows structure.
3835%
3836% o name: the name of the color if found in the X Color Database is
3837% returned in this character string.
3838%
cristy6710d842011-10-20 23:23:00 +00003839% o exception: return any errors or warnings in this structure.
3840%
cristy3ed852e2009-09-05 21:47:34 +00003841*/
cristybcbda3f2011-09-03 13:01:22 +00003842MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003843 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003844{
3845 int
3846 x,
3847 y;
3848
cristy101ab702011-10-13 13:06:32 +00003849 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003850 pixel;
3851
3852 RectangleInfo
3853 crop_info;
3854
3855 Status
3856 status;
3857
3858 Window
3859 child,
3860 client_window,
3861 root_window,
3862 target_window;
3863
3864 XColor
3865 color;
3866
3867 XImage
3868 *ximage;
3869
3870 XWindowAttributes
3871 window_attributes;
3872
3873 /*
3874 Choose a pixel from the X server.
3875 */
3876 assert(display != (Display *) NULL);
3877 assert(name != (char *) NULL);
3878 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3879 *name='\0';
3880 target_window=XSelectWindow(display,&crop_info);
3881 if (target_window == (Window) NULL)
3882 return(MagickFalse);
3883 root_window=XRootWindow(display,XDefaultScreen(display));
3884 client_window=target_window;
3885 if (target_window != root_window)
3886 {
3887 unsigned int
3888 d;
3889
3890 /*
3891 Get client window.
3892 */
3893 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3894 if (status != False)
3895 {
3896 client_window=XClientWindow(display,target_window);
3897 target_window=client_window;
3898 }
3899 }
3900 /*
3901 Verify window is viewable.
3902 */
3903 status=XGetWindowAttributes(display,target_window,&window_attributes);
3904 if ((status == False) || (window_attributes.map_state != IsViewable))
3905 return(MagickFalse);
3906 /*
3907 Get window X image.
3908 */
3909 (void) XTranslateCoordinates(display,root_window,target_window,
3910 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3911 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3912 if (ximage == (XImage *) NULL)
3913 return(MagickFalse);
3914 color.pixel=XGetPixel(ximage,0,0);
3915 XDestroyImage(ximage);
3916 /*
3917 Match color against the color database.
3918 */
3919 (void) XQueryColor(display,window_attributes.colormap,&color);
cristye42f6582012-02-11 17:59:50 +00003920 pixel.red=(double) ScaleShortToQuantum(color.red);
3921 pixel.green=(double) ScaleShortToQuantum(color.green);
3922 pixel.blue=(double) ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003923 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003924 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003925 exception);
cristy3ed852e2009-09-05 21:47:34 +00003926 return(MagickTrue);
3927}
3928
3929/*
3930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3931% %
3932% %
3933% %
3934+ X G e t W i n d o w I m a g e %
3935% %
3936% %
3937% %
3938%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3939%
3940% XGetWindowImage() reads an image from the target X window and returns it.
3941% XGetWindowImage() optionally descends the window hierarchy and overlays the
3942% target image with each child image in an optimized fashion. Any child
3943% window that have the same visual, colormap, and are contained by its parent
3944% are exempted.
3945%
3946% The format of the XGetWindowImage method is:
3947%
3948% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003949% const unsigned int borders,const unsigned int level,
3950% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003951%
3952% A description of each parameter follows:
3953%
3954% o display: Specifies a connection to an X server; returned from
3955% XOpenDisplay.
3956%
3957% o window: Specifies the window to obtain the image from.
3958%
3959% o borders: Specifies whether borders pixels are to be saved with
3960% the image.
3961%
3962% o level: Specifies an unsigned integer representing the level of
3963% decent in the window hierarchy. This value must be zero or one on
3964% the initial call to XGetWindowImage. A value of zero returns after
3965% one call. A value of one causes the function to descend the window
3966% hierarchy and overlay the target image with each subwindow image.
3967%
cristy6710d842011-10-20 23:23:00 +00003968% o exception: return any errors or warnings in this structure.
3969%
cristy3ed852e2009-09-05 21:47:34 +00003970*/
3971static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003972 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003973{
3974 typedef struct _ColormapInfo
3975 {
3976 Colormap
3977 colormap;
3978
3979 XColor
3980 *colors;
3981
3982 struct _ColormapInfo
3983 *next;
3984 } ColormapInfo;
3985
3986 typedef struct _WindowInfo
3987 {
3988 Window
3989 window,
3990 parent;
3991
3992 Visual
3993 *visual;
3994
3995 Colormap
3996 colormap;
3997
3998 XSegment
3999 bounds;
4000
4001 RectangleInfo
4002 crop_info;
4003 } WindowInfo;
4004
cristy3ed852e2009-09-05 21:47:34 +00004005 int
4006 display_height,
4007 display_width,
4008 id,
4009 x_offset,
4010 y_offset;
4011
cristy4c08aed2011-07-01 19:47:50 +00004012 Quantum
4013 index;
4014
cristy3ed852e2009-09-05 21:47:34 +00004015 RectangleInfo
4016 crop_info;
4017
cristy3ed852e2009-09-05 21:47:34 +00004018 register int
4019 i;
4020
4021 static ColormapInfo
4022 *colormap_info = (ColormapInfo *) NULL;
4023
4024 static int
4025 max_windows = 0,
4026 number_windows = 0;
4027
4028 static WindowInfo
4029 *window_info;
4030
4031 Status
4032 status;
4033
4034 Window
4035 child,
4036 root_window;
4037
4038 XWindowAttributes
4039 window_attributes;
4040
4041 /*
4042 Verify window is viewable.
4043 */
4044 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4045 assert(display != (Display *) NULL);
4046 status=XGetWindowAttributes(display,window,&window_attributes);
4047 if ((status == False) || (window_attributes.map_state != IsViewable))
4048 return((Image *) NULL);
4049 /*
4050 Cropping rectangle is relative to root window.
4051 */
4052 root_window=XRootWindow(display,XDefaultScreen(display));
4053 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4054 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004055 crop_info.x=(ssize_t) x_offset;
4056 crop_info.y=(ssize_t) y_offset;
4057 crop_info.width=(size_t) window_attributes.width;
4058 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004059 if (borders != MagickFalse)
4060 {
4061 /*
4062 Include border in image.
4063 */
cristybb503372010-05-27 20:51:26 +00004064 crop_info.x-=(ssize_t) window_attributes.border_width;
4065 crop_info.y-=(ssize_t) window_attributes.border_width;
4066 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4067 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004068 }
4069 /*
4070 Crop to root window.
4071 */
4072 if (crop_info.x < 0)
4073 {
4074 crop_info.width+=crop_info.x;
4075 crop_info.x=0;
4076 }
4077 if (crop_info.y < 0)
4078 {
4079 crop_info.height+=crop_info.y;
4080 crop_info.y=0;
4081 }
4082 display_width=XDisplayWidth(display,XDefaultScreen(display));
4083 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004084 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004085 display_height=XDisplayHeight(display,XDefaultScreen(display));
4086 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004087 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004088 /*
4089 Initialize window info attributes.
4090 */
4091 if (number_windows >= max_windows)
4092 {
4093 /*
4094 Allocate or resize window info buffer.
4095 */
4096 max_windows+=1024;
4097 if (window_info == (WindowInfo *) NULL)
4098 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4099 sizeof(*window_info));
4100 else
4101 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4102 max_windows,sizeof(*window_info));
4103 }
4104 if (window_info == (WindowInfo *) NULL)
4105 {
cristyc38fbf52013-11-03 13:55:54 +00004106 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed","...");
cristy3ed852e2009-09-05 21:47:34 +00004107 return((Image *) NULL);
4108 }
4109 id=number_windows++;
4110 window_info[id].window=window;
4111 window_info[id].visual=window_attributes.visual;
4112 window_info[id].colormap=window_attributes.colormap;
4113 window_info[id].bounds.x1=(short) crop_info.x;
4114 window_info[id].bounds.y1=(short) crop_info.y;
4115 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4116 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4117 crop_info.x-=x_offset;
4118 crop_info.y-=y_offset;
4119 window_info[id].crop_info=crop_info;
4120 if (level != 0)
4121 {
4122 unsigned int
4123 number_children;
4124
4125 Window
4126 *children;
4127
4128 /*
4129 Descend the window hierarchy.
4130 */
4131 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4132 &children,&number_children);
4133 for (i=0; i < id; i++)
4134 if ((window_info[i].window == window_info[id].parent) &&
4135 (window_info[i].visual == window_info[id].visual) &&
4136 (window_info[i].colormap == window_info[id].colormap))
4137 {
cristy64057b02013-01-11 00:09:58 +00004138 if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
4139 (window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
4140 (window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
4141 (window_info[id].bounds.y2 > window_info[i].bounds.y2))
cristy3ed852e2009-09-05 21:47:34 +00004142 {
4143 /*
4144 Eliminate windows not circumscribed by their parent.
4145 */
4146 number_windows--;
4147 break;
4148 }
4149 }
4150 if ((status == True) && (number_children != 0))
4151 {
4152 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004153 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4154 exception);
cristy3ed852e2009-09-05 21:47:34 +00004155 (void) XFree((void *) children);
4156 }
4157 }
4158 if (level <= 1)
4159 {
cristyc57f6942010-11-12 01:47:39 +00004160 CacheView
4161 *composite_view;
4162
cristy3ed852e2009-09-05 21:47:34 +00004163 ColormapInfo
4164 *next;
4165
cristy3ed852e2009-09-05 21:47:34 +00004166 Image
4167 *composite_image,
4168 *image;
4169
4170 int
4171 y;
4172
4173 MagickBooleanType
4174 import;
4175
4176 register int
4177 j,
4178 x;
4179
cristy4c08aed2011-07-01 19:47:50 +00004180 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004181 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004182
cristybb503372010-05-27 20:51:26 +00004183 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004184 pixel;
4185
4186 unsigned int
4187 number_colors;
4188
4189 XColor
4190 *colors;
4191
4192 XImage
4193 *ximage;
4194
4195 /*
4196 Get X image for each window in the list.
4197 */
4198 image=NewImageList();
4199 for (id=0; id < number_windows; id++)
4200 {
4201 /*
4202 Does target window intersect top level window?
4203 */
cristy088af952013-08-19 18:34:20 +00004204 import=((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
cristy3ed852e2009-09-05 21:47:34 +00004205 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4206 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4207 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4208 MagickTrue : MagickFalse;
4209 /*
4210 Is target window contained by another window with the same colormap?
4211 */
4212 for (j=0; j < id; j++)
4213 if ((window_info[id].visual == window_info[j].visual) &&
4214 (window_info[id].colormap == window_info[j].colormap))
4215 {
cristy64057b02013-01-11 00:09:58 +00004216 if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
4217 (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
4218 (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
4219 (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
cristy088af952013-08-19 18:34:20 +00004220 import=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00004221 }
cristy3ed852e2009-09-05 21:47:34 +00004222 if (import == MagickFalse)
4223 continue;
4224 /*
4225 Get X image.
4226 */
4227 ximage=XGetImage(display,window_info[id].window,(int)
4228 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4229 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4230 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4231 if (ximage == (XImage *) NULL)
4232 continue;
4233 /*
4234 Initialize window colormap.
4235 */
4236 number_colors=0;
4237 colors=(XColor *) NULL;
4238 if (window_info[id].colormap != (Colormap) NULL)
4239 {
4240 ColormapInfo
4241 *p;
4242
4243 /*
4244 Search colormap list for window colormap.
4245 */
4246 number_colors=(unsigned int) window_info[id].visual->map_entries;
4247 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4248 if (p->colormap == window_info[id].colormap)
4249 break;
4250 if (p == (ColormapInfo *) NULL)
4251 {
4252 /*
4253 Get the window colormap.
4254 */
4255 colors=(XColor *) AcquireQuantumMemory(number_colors,
4256 sizeof(*colors));
4257 if (colors == (XColor *) NULL)
4258 {
4259 XDestroyImage(ximage);
4260 return((Image *) NULL);
4261 }
4262 if ((window_info[id].visual->klass != DirectColor) &&
4263 (window_info[id].visual->klass != TrueColor))
4264 for (i=0; i < (int) number_colors; i++)
4265 {
cristybb503372010-05-27 20:51:26 +00004266 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004267 colors[i].pad='\0';
4268 }
4269 else
4270 {
cristybb503372010-05-27 20:51:26 +00004271 size_t
cristy3ed852e2009-09-05 21:47:34 +00004272 blue,
4273 blue_bit,
4274 green,
4275 green_bit,
4276 red,
4277 red_bit;
4278
4279 /*
4280 DirectColor or TrueColor visual.
4281 */
4282 red=0;
4283 green=0;
4284 blue=0;
4285 red_bit=window_info[id].visual->red_mask &
4286 (~(window_info[id].visual->red_mask)+1);
4287 green_bit=window_info[id].visual->green_mask &
4288 (~(window_info[id].visual->green_mask)+1);
4289 blue_bit=window_info[id].visual->blue_mask &
4290 (~(window_info[id].visual->blue_mask)+1);
4291 for (i=0; i < (int) number_colors; i++)
4292 {
cristy8891f9c2010-06-04 23:32:17 +00004293 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004294 colors[i].pad='\0';
4295 red+=red_bit;
4296 if (red > window_info[id].visual->red_mask)
4297 red=0;
4298 green+=green_bit;
4299 if (green > window_info[id].visual->green_mask)
4300 green=0;
4301 blue+=blue_bit;
4302 if (blue > window_info[id].visual->blue_mask)
4303 blue=0;
4304 }
4305 }
4306 (void) XQueryColors(display,window_info[id].colormap,colors,
4307 (int) number_colors);
4308 /*
4309 Append colormap to colormap list.
4310 */
cristy73bd4a52010-10-05 11:24:23 +00004311 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004312 if (p == (ColormapInfo *) NULL)
4313 return((Image *) NULL);
4314 p->colormap=window_info[id].colormap;
4315 p->colors=colors;
4316 p->next=colormap_info;
4317 colormap_info=p;
4318 }
4319 colors=p->colors;
4320 }
4321 /*
4322 Allocate image structure.
4323 */
cristy6710d842011-10-20 23:23:00 +00004324 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004325 if (composite_image == (Image *) NULL)
4326 {
4327 XDestroyImage(ximage);
4328 return((Image *) NULL);
4329 }
4330 /*
4331 Convert X image to MIFF format.
4332 */
4333 if ((window_info[id].visual->klass != TrueColor) &&
4334 (window_info[id].visual->klass != DirectColor))
4335 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004336 composite_image->columns=(size_t) ximage->width;
4337 composite_image->rows=(size_t) ximage->height;
cristy46ff2672012-12-14 15:32:26 +00004338 composite_view=AcquireAuthenticCacheView(composite_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00004339 switch (composite_image->storage_class)
4340 {
4341 case DirectClass:
4342 default:
4343 {
cristybb503372010-05-27 20:51:26 +00004344 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004345 color,
4346 index;
4347
cristybb503372010-05-27 20:51:26 +00004348 size_t
cristy3ed852e2009-09-05 21:47:34 +00004349 blue_mask,
4350 blue_shift,
4351 green_mask,
4352 green_shift,
4353 red_mask,
4354 red_shift;
4355
4356 /*
4357 Determine shift and mask for red, green, and blue.
4358 */
4359 red_mask=window_info[id].visual->red_mask;
4360 red_shift=0;
4361 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4362 {
4363 red_mask>>=1;
4364 red_shift++;
4365 }
4366 green_mask=window_info[id].visual->green_mask;
4367 green_shift=0;
4368 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4369 {
4370 green_mask>>=1;
4371 green_shift++;
4372 }
4373 blue_mask=window_info[id].visual->blue_mask;
4374 blue_shift=0;
4375 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4376 {
4377 blue_mask>>=1;
4378 blue_shift++;
4379 }
4380 /*
4381 Convert X image to DirectClass packets.
4382 */
4383 if ((number_colors != 0) &&
4384 (window_info[id].visual->klass == DirectColor))
4385 for (y=0; y < (int) composite_image->rows; y++)
4386 {
cristyc57f6942010-11-12 01:47:39 +00004387 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004388 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004389 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004390 break;
4391 for (x=0; x < (int) composite_image->columns; x++)
4392 {
4393 pixel=XGetPixel(ximage,x,y);
4394 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004395 SetPixelRed(composite_image,
4396 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004397 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004398 SetPixelGreen(composite_image,
4399 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004400 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004401 SetPixelBlue(composite_image,
4402 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004403 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004404 }
cristy0b1a7972011-10-22 22:17:02 +00004405 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4406 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004407 break;
4408 }
4409 else
4410 for (y=0; y < (int) composite_image->rows; y++)
4411 {
cristyc57f6942010-11-12 01:47:39 +00004412 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004413 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004414 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004415 break;
4416 for (x=0; x < (int) composite_image->columns; x++)
4417 {
4418 pixel=XGetPixel(ximage,x,y);
4419 color=(pixel >> red_shift) & red_mask;
cristy9a7df362014-01-14 15:03:18 +00004420 if (red_mask != 0)
4421 color=(65535UL*color)/red_mask;
4422 SetPixelRed(composite_image,ScaleShortToQuantum(
4423 (unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004424 color=(pixel >> green_shift) & green_mask;
cristy9a7df362014-01-14 15:03:18 +00004425 if (green_mask != 0)
4426 color=(65535UL*color)/green_mask;
4427 SetPixelGreen(composite_image,ScaleShortToQuantum(
4428 (unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004429 color=(pixel >> blue_shift) & blue_mask;
cristy9a7df362014-01-14 15:03:18 +00004430 if (blue_mask != 0)
4431 color=(65535UL*color)/blue_mask;
4432 SetPixelBlue(composite_image,ScaleShortToQuantum(
4433 (unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004434 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004435 }
cristy0b1a7972011-10-22 22:17:02 +00004436 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4437 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004438 break;
4439 }
4440 break;
4441 }
4442 case PseudoClass:
4443 {
4444 /*
4445 Create colormap.
4446 */
cristy0b1a7972011-10-22 22:17:02 +00004447 status=AcquireImageColormap(composite_image,number_colors,
4448 exception);
4449 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004450 {
4451 XDestroyImage(ximage);
4452 composite_image=DestroyImage(composite_image);
4453 return((Image *) NULL);
4454 }
4455 for (i=0; i < (int) composite_image->colors; i++)
4456 {
cristye42f6582012-02-11 17:59:50 +00004457 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004458 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004459 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004460 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004461 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004462 ScaleShortToQuantum(colors[i].blue);
4463 }
4464 /*
4465 Convert X image to PseudoClass packets.
4466 */
4467 for (y=0; y < (int) composite_image->rows; y++)
4468 {
cristyc57f6942010-11-12 01:47:39 +00004469 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4470 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004471 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004472 break;
cristy3ed852e2009-09-05 21:47:34 +00004473 for (x=0; x < (int) composite_image->columns; x++)
4474 {
cristy4c08aed2011-07-01 19:47:50 +00004475 index=(Quantum) XGetPixel(ximage,x,y);
4476 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004477 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004478 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004479 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004480 }
cristy0b1a7972011-10-22 22:17:02 +00004481 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4482 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004483 break;
4484 }
4485 break;
4486 }
4487 }
cristyc57f6942010-11-12 01:47:39 +00004488 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004489 XDestroyImage(ximage);
4490 if (image == (Image *) NULL)
4491 {
4492 image=composite_image;
4493 continue;
4494 }
4495 /*
4496 Composite any children in back-to-front order.
4497 */
4498 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4499 &x_offset,&y_offset,&child);
4500 x_offset-=(int) crop_info.x;
4501 if (x_offset < 0)
4502 x_offset=0;
4503 y_offset-=(int) crop_info.y;
4504 if (y_offset < 0)
4505 y_offset=0;
cristy39172402012-03-30 13:04:39 +00004506 (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00004507 (ssize_t) x_offset,(ssize_t) y_offset,exception);
cristy5f257b22012-03-07 00:27:29 +00004508 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004509 }
4510 /*
4511 Relinquish resources.
4512 */
4513 while (colormap_info != (ColormapInfo *) NULL)
4514 {
4515 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004516 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4517 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004518 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4519 colormap_info=next;
4520 }
4521 /*
4522 Relinquish resources and restore initial state.
4523 */
4524 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4525 max_windows=0;
4526 number_windows=0;
4527 colormap_info=(ColormapInfo *) NULL;
4528 return(image);
4529 }
4530 return((Image *) NULL);
4531}
4532
4533/*
4534%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4535% %
4536% %
4537% %
4538% X G e t W i n d o w I n f o %
4539% %
4540% %
4541% %
4542%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4543%
4544% XGetWindowInfo() initializes the XWindowInfo structure.
4545%
4546% The format of the XGetWindowInfo method is:
4547%
4548% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4549% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4550% XResourceInfo *resource_info,XWindowInfo *window)
4551% resource_info,window)
4552%
4553% A description of each parameter follows:
4554%
4555% o display: Specifies a connection to an X server; returned from
4556% XOpenDisplay.
4557%
4558% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4559% returned from XGetVisualInfo.
4560%
4561% o map_info: If map_type is specified, this structure is initialized
4562% with info from the Standard Colormap.
4563%
4564% o pixel: Specifies a pointer to a XPixelInfo structure.
4565%
4566% o font_info: Specifies a pointer to a XFontStruct structure.
4567%
4568% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4569%
4570*/
cristybcbda3f2011-09-03 13:01:22 +00004571MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004572 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4573 XResourceInfo *resource_info,XWindowInfo *window)
4574{
4575 /*
4576 Initialize window info.
4577 */
4578 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4579 assert(display != (Display *) NULL);
4580 assert(visual_info != (XVisualInfo *) NULL);
4581 assert(map_info != (XStandardColormap *) NULL);
4582 assert(pixel != (XPixelInfo *) NULL);
4583 assert(resource_info != (XResourceInfo *) NULL);
4584 assert(window != (XWindowInfo *) NULL);
4585 if (window->id != (Window) NULL)
4586 {
4587 if (window->cursor != (Cursor) NULL)
4588 (void) XFreeCursor(display,window->cursor);
4589 if (window->busy_cursor != (Cursor) NULL)
4590 (void) XFreeCursor(display,window->busy_cursor);
4591 if (window->highlight_stipple != (Pixmap) NULL)
4592 (void) XFreePixmap(display,window->highlight_stipple);
4593 if (window->shadow_stipple != (Pixmap) NULL)
4594 (void) XFreePixmap(display,window->shadow_stipple);
4595 if (window->name == (char *) NULL)
4596 window->name=AcquireString("");
4597 if (window->icon_name == (char *) NULL)
4598 window->icon_name=AcquireString("");
4599 }
4600 else
4601 {
4602 /*
4603 Initialize these attributes just once.
4604 */
4605 window->id=(Window) NULL;
4606 if (window->name == (char *) NULL)
4607 window->name=AcquireString("");
4608 if (window->icon_name == (char *) NULL)
4609 window->icon_name=AcquireString("");
4610 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4611 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4612 window->ximage=(XImage *) NULL;
4613 window->matte_image=(XImage *) NULL;
4614 window->pixmap=(Pixmap) NULL;
4615 window->matte_pixmap=(Pixmap) NULL;
4616 window->mapped=MagickFalse;
4617 window->stasis=MagickFalse;
4618 window->shared_memory=MagickTrue;
4619 window->segment_info=(void *) NULL;
4620#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4621 {
4622 XShmSegmentInfo
4623 *segment_info;
4624
4625 if (window->segment_info == (void *) NULL)
4626 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4627 segment_info=(XShmSegmentInfo *) window->segment_info;
4628 segment_info[0].shmid=(-1);
4629 segment_info[0].shmaddr=(char *) NULL;
4630 segment_info[1].shmid=(-1);
4631 segment_info[1].shmaddr=(char *) NULL;
4632 }
4633#endif
4634 }
4635 /*
4636 Initialize these attributes every time function is called.
4637 */
4638 window->screen=visual_info->screen;
4639 window->root=XRootWindow(display,visual_info->screen);
4640 window->visual=visual_info->visual;
4641 window->storage_class=(unsigned int) visual_info->klass;
4642 window->depth=(unsigned int) visual_info->depth;
4643 window->visual_info=visual_info;
4644 window->map_info=map_info;
4645 window->pixel_info=pixel;
4646 window->font_info=font_info;
4647 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4648 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4649 window->geometry=(char *) NULL;
4650 window->icon_geometry=(char *) NULL;
4651 if (resource_info->icon_geometry != (char *) NULL)
4652 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4653 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004654 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004655 window->width=1;
4656 window->height=1;
4657 window->min_width=1;
4658 window->min_height=1;
4659 window->width_inc=1;
4660 window->height_inc=1;
4661 window->border_width=resource_info->border_width;
4662 window->annotate_context=pixel->annotate_context;
4663 window->highlight_context=pixel->highlight_context;
4664 window->widget_context=pixel->widget_context;
4665 window->shadow_stipple=(Pixmap) NULL;
4666 window->highlight_stipple=(Pixmap) NULL;
4667 window->use_pixmap=MagickTrue;
4668 window->immutable=MagickFalse;
4669 window->shape=MagickFalse;
4670 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004671 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004672 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4673 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4674 window->attributes.background_pixel=pixel->background_color.pixel;
4675 window->attributes.background_pixmap=(Pixmap) NULL;
4676 window->attributes.bit_gravity=ForgetGravity;
4677 window->attributes.backing_store=WhenMapped;
4678 window->attributes.save_under=MagickTrue;
4679 window->attributes.border_pixel=pixel->border_color.pixel;
4680 window->attributes.colormap=map_info->colormap;
4681 window->attributes.cursor=window->cursor;
4682 window->attributes.do_not_propagate_mask=NoEventMask;
4683 window->attributes.event_mask=NoEventMask;
4684 window->attributes.override_redirect=MagickFalse;
4685 window->attributes.win_gravity=NorthWestGravity;
4686 window->orphan=MagickFalse;
4687}
4688
4689/*
4690%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4691% %
4692% %
4693% %
4694% X H i g h l i g h t E l l i p s e %
4695% %
4696% %
4697% %
4698%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4699%
4700% XHighlightEllipse() puts a border on the X server around a region defined by
4701% highlight_info.
4702%
4703% The format of the XHighlightEllipse method is:
4704%
4705% void XHighlightEllipse(Display *display,Window window,
4706% GC annotate_context,const RectangleInfo *highlight_info)
4707%
4708% A description of each parameter follows:
4709%
4710% o display: Specifies a connection to an X server; returned from
4711% XOpenDisplay.
4712%
4713% o window: Specifies a pointer to a Window structure.
4714%
4715% o annotate_context: Specifies a pointer to a GC structure.
4716%
4717% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4718% contains the extents of any highlighting rectangle.
4719%
4720*/
cristybcbda3f2011-09-03 13:01:22 +00004721MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004722 GC annotate_context,const RectangleInfo *highlight_info)
4723{
4724 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4725 assert(display != (Display *) NULL);
4726 assert(window != (Window) NULL);
4727 assert(annotate_context != (GC) NULL);
4728 assert(highlight_info != (RectangleInfo *) NULL);
4729 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4730 return;
4731 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4732 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4733 (unsigned int) highlight_info->height-1,0,360*64);
4734 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4735 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4736 (unsigned int) highlight_info->height-3,0,360*64);
4737}
4738
4739/*
4740%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4741% %
4742% %
4743% %
4744% X H i g h l i g h t L i n e %
4745% %
4746% %
4747% %
4748%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4749%
4750% XHighlightLine() puts a border on the X server around a region defined by
4751% highlight_info.
4752%
4753% The format of the XHighlightLine method is:
4754%
4755% void XHighlightLine(Display *display,Window window,GC annotate_context,
4756% const XSegment *highlight_info)
4757%
4758% A description of each parameter follows:
4759%
4760% o display: Specifies a connection to an X server; returned from
4761% XOpenDisplay.
4762%
4763% o window: Specifies a pointer to a Window structure.
4764%
4765% o annotate_context: Specifies a pointer to a GC structure.
4766%
4767% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4768% contains the extents of any highlighting rectangle.
4769%
4770*/
cristybcbda3f2011-09-03 13:01:22 +00004771MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004772 GC annotate_context,const XSegment *highlight_info)
4773{
4774 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4775 assert(display != (Display *) NULL);
4776 assert(window != (Window) NULL);
4777 assert(annotate_context != (GC) NULL);
4778 assert(highlight_info != (XSegment *) NULL);
4779 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4780 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4781}
4782
4783/*
4784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4785% %
4786% %
4787% %
4788% X H i g h l i g h t R e c t a n g l e %
4789% %
4790% %
4791% %
4792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4793%
4794% XHighlightRectangle() puts a border on the X server around a region defined
4795% by highlight_info.
4796%
4797% The format of the XHighlightRectangle method is:
4798%
4799% void XHighlightRectangle(Display *display,Window window,
4800% GC annotate_context,const RectangleInfo *highlight_info)
4801%
4802% A description of each parameter follows:
4803%
4804% o display: Specifies a connection to an X server; returned from
4805% XOpenDisplay.
4806%
4807% o window: Specifies a pointer to a Window structure.
4808%
4809% o annotate_context: Specifies a pointer to a GC structure.
4810%
4811% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4812% contains the extents of any highlighting rectangle.
4813%
4814*/
cristybcbda3f2011-09-03 13:01:22 +00004815MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004816 GC annotate_context,const RectangleInfo *highlight_info)
4817{
4818 assert(display != (Display *) NULL);
4819 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4820 assert(window != (Window) NULL);
4821 assert(annotate_context != (GC) NULL);
4822 assert(highlight_info != (RectangleInfo *) NULL);
4823 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4824 return;
4825 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4826 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4827 (unsigned int) highlight_info->height-1);
4828 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4829 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4830 (unsigned int) highlight_info->height-3);
4831}
4832
4833/*
4834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4835% %
4836% %
4837% %
4838% X I m p o r t I m a g e %
4839% %
4840% %
4841% %
4842%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4843%
4844% XImportImage() reads an image from an X window.
4845%
4846% The format of the XImportImage method is:
4847%
cristy6710d842011-10-20 23:23:00 +00004848% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4849% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004850%
4851% A description of each parameter follows:
4852%
4853% o image_info: the image info.
4854%
4855% o ximage_info: Specifies a pointer to an XImportInfo structure.
4856%
cristy6710d842011-10-20 23:23:00 +00004857% o exception: return any errors or warnings in this structure.
4858%
cristy3ed852e2009-09-05 21:47:34 +00004859*/
4860MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004861 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004862{
4863 Colormap
4864 *colormaps;
4865
4866 Display
4867 *display;
4868
4869 Image
4870 *image;
4871
4872 int
4873 number_colormaps,
4874 number_windows,
4875 x;
4876
4877 RectangleInfo
4878 crop_info;
4879
4880 Status
4881 status;
4882
4883 Window
4884 *children,
4885 client,
4886 prior_target,
4887 root,
4888 target;
4889
4890 XTextProperty
4891 window_name;
4892
4893 /*
4894 Open X server connection.
4895 */
4896 assert(image_info != (const ImageInfo *) NULL);
4897 assert(image_info->signature == MagickSignature);
4898 if (image_info->debug != MagickFalse)
4899 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4900 image_info->filename);
4901 assert(ximage_info != (XImportInfo *) NULL);
4902 display=XOpenDisplay(image_info->server_name);
4903 if (display == (Display *) NULL)
4904 {
cristyc38fbf52013-11-03 13:55:54 +00004905 ThrowXWindowException(XServerError,"UnableToOpenXServer",
cristy3ed852e2009-09-05 21:47:34 +00004906 XDisplayName(image_info->server_name));
4907 return((Image *) NULL);
4908 }
4909 /*
4910 Set our forgiving exception handler.
4911 */
4912 (void) XSetErrorHandler(XError);
4913 /*
4914 Select target window.
4915 */
4916 crop_info.x=0;
4917 crop_info.y=0;
4918 crop_info.width=0;
4919 crop_info.height=0;
4920 root=XRootWindow(display,XDefaultScreen(display));
4921 target=(Window) NULL;
cristy6f008fd2014-05-25 23:27:26 +00004922 if (*image_info->filename != '\0')
cristy3ed852e2009-09-05 21:47:34 +00004923 {
4924 if (LocaleCompare(image_info->filename,"root") == 0)
4925 target=root;
4926 else
4927 {
4928 /*
4929 Select window by ID or name.
4930 */
cristy02e64f82013-11-14 16:20:04 +00004931 if (isdigit((int) ((unsigned char) *image_info->filename)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00004932 target=XWindowByID(display,root,(Window)
4933 strtol(image_info->filename,(char **) NULL,0));
4934 if (target == (Window) NULL)
4935 target=XWindowByName(display,root,image_info->filename);
4936 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004937 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
4938 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00004939 }
4940 }
4941 /*
4942 If target window is not defined, interactively select one.
4943 */
4944 prior_target=target;
4945 if (target == (Window) NULL)
4946 target=XSelectWindow(display,&crop_info);
4947 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004948 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00004949 image_info->filename);
4950 client=target; /* obsolete */
4951 if (target != root)
4952 {
4953 unsigned int
4954 d;
4955
4956 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4957 if (status != False)
4958 {
4959 for ( ; ; )
4960 {
4961 Window
4962 parent;
4963
4964 /*
4965 Find window manager frame.
4966 */
4967 status=XQueryTree(display,target,&root,&parent,&children,&d);
4968 if ((status != False) && (children != (Window *) NULL))
4969 (void) XFree((char *) children);
4970 if ((status == False) || (parent == (Window) NULL) ||
4971 (parent == root))
4972 break;
4973 target=parent;
4974 }
4975 /*
4976 Get client window.
4977 */
4978 client=XClientWindow(display,target);
4979 if (ximage_info->frame == MagickFalse)
4980 target=client;
4981 if ((ximage_info->frame == MagickFalse) &&
4982 (prior_target != MagickFalse))
4983 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00004984 }
4985 }
4986 if (ximage_info->screen)
4987 {
4988 int
4989 y;
4990
4991 Window
4992 child;
4993
4994 XWindowAttributes
4995 window_attributes;
4996
4997 /*
4998 Obtain window image directly from screen.
4999 */
5000 status=XGetWindowAttributes(display,target,&window_attributes);
5001 if (status == False)
5002 {
cristyc38fbf52013-11-03 13:55:54 +00005003 ThrowXWindowException(XServerError,"UnableToReadXWindowAttributes",
5004 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00005005 (void) XCloseDisplay(display);
5006 return((Image *) NULL);
5007 }
5008 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005009 crop_info.x=(ssize_t) x;
5010 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005011 crop_info.width=(size_t) window_attributes.width;
5012 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005013 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005014 {
5015 /*
5016 Include border in image.
5017 */
5018 crop_info.x-=window_attributes.border_width;
5019 crop_info.y-=window_attributes.border_width;
5020 crop_info.width+=window_attributes.border_width << 1;
5021 crop_info.height+=window_attributes.border_width << 1;
5022 }
5023 target=root;
5024 }
5025 /*
5026 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5027 */
5028 number_windows=0;
5029 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5030 if ((status == True) && (number_windows > 0))
5031 {
5032 ximage_info->descend=MagickTrue;
5033 (void) XFree ((char *) children);
5034 }
5035 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5036 if (number_colormaps > 0)
5037 {
5038 if (number_colormaps > 1)
5039 ximage_info->descend=MagickTrue;
5040 (void) XFree((char *) colormaps);
5041 }
5042 /*
5043 Alert the user not to alter the screen.
5044 */
5045 if (ximage_info->silent == MagickFalse)
5046 (void) XBell(display,0);
5047 /*
5048 Get image by window id.
5049 */
5050 (void) XGrabServer(display);
5051 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005052 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005053 (void) XUngrabServer(display);
5054 if (image == (Image *) NULL)
cristyc38fbf52013-11-03 13:55:54 +00005055 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00005056 image_info->filename)
5057 else
5058 {
5059 (void) CopyMagickString(image->filename,image_info->filename,
5060 MaxTextExtent);
5061 if ((crop_info.width != 0) && (crop_info.height != 0))
5062 {
5063 Image
5064 *clone_image,
5065 *crop_image;
5066
5067 /*
5068 Crop image as defined by the cropping rectangle.
5069 */
cristy6710d842011-10-20 23:23:00 +00005070 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005071 if (clone_image != (Image *) NULL)
5072 {
cristy6710d842011-10-20 23:23:00 +00005073 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005074 if (crop_image != (Image *) NULL)
5075 {
5076 image=DestroyImage(image);
5077 image=crop_image;
5078 }
5079 }
5080 }
5081 status=XGetWMName(display,target,&window_name);
5082 if (status == True)
5083 {
cristy8418c7e2014-05-18 18:38:26 +00005084 if (*image_info->filename == '\0')
cristy3ed852e2009-09-05 21:47:34 +00005085 (void) CopyMagickString(image->filename,(char *) window_name.value,
5086 (size_t) window_name.nitems+1);
5087 (void) XFree((void *) window_name.value);
5088 }
5089 }
5090 if (ximage_info->silent == MagickFalse)
5091 {
5092 /*
5093 Alert the user we're done.
5094 */
5095 (void) XBell(display,0);
5096 (void) XBell(display,0);
5097 }
5098 (void) XCloseDisplay(display);
5099 return(image);
5100}
5101
5102/*
5103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5104% %
5105% %
5106% %
5107% X I n i t i a l i z e W i n d o w s %
5108% %
5109% %
5110% %
5111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5112%
5113% XInitializeWindows() initializes the XWindows structure.
5114%
5115% The format of the XInitializeWindows method is:
5116%
5117% XWindows *XInitializeWindows(Display *display,
5118% XResourceInfo *resource_info)
5119%
5120% A description of each parameter follows:
5121%
5122% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5123%
5124% o display: Specifies a connection to an X server; returned from
5125% XOpenDisplay.
5126%
5127% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5128%
5129*/
cristybcbda3f2011-09-03 13:01:22 +00005130MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005131 XResourceInfo *resource_info)
5132{
5133 Window
5134 root_window;
5135
5136 XWindows
5137 *windows;
5138
5139 /*
5140 Allocate windows structure.
5141 */
cristy73bd4a52010-10-05 11:24:23 +00005142 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005143 if (windows == (XWindows *) NULL)
5144 {
5145 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5146 "...");
5147 return((XWindows *) NULL);
5148 }
5149 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5150 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5151 sizeof(*windows->pixel_info));
5152 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5153 sizeof(*windows->icon_pixel));
5154 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5155 sizeof(*windows->icon_resources));
5156 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5157 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5158 (windows->icon_resources == (XResourceInfo *) NULL))
5159 {
5160 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5161 "...");
5162 return((XWindows *) NULL);
5163 }
5164 /*
5165 Initialize windows structure.
5166 */
5167 windows->display=display;
5168 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5169 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5170 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5171 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5172 windows->im_remote_command=
5173 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5174 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5175 windows->im_update_colormap=
5176 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5177 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5178 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5179 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5180 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5181 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005182#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005183 (void) XSynchronize(display,IsWindows95());
5184#endif
5185 if (IsEventLogging())
5186 {
5187 (void) XSynchronize(display,MagickTrue);
5188 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005189 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005190 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5191 (void) LogMagickEvent(X11Event,GetMagickModule(),
5192 " Window Manager: 0x%lx",windows->wm_protocols);
5193 (void) LogMagickEvent(X11Event,GetMagickModule(),
5194 " delete window: 0x%lx",windows->wm_delete_window);
5195 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5196 windows->wm_take_focus);
5197 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5198 windows->im_protocols);
5199 (void) LogMagickEvent(X11Event,GetMagickModule(),
5200 " remote command: 0x%lx",windows->im_remote_command);
5201 (void) LogMagickEvent(X11Event,GetMagickModule(),
5202 " update widget: 0x%lx",windows->im_update_widget);
5203 (void) LogMagickEvent(X11Event,GetMagickModule(),
5204 " update colormap: 0x%lx",windows->im_update_colormap);
5205 (void) LogMagickEvent(X11Event,GetMagickModule(),
5206 " former image: 0x%lx",windows->im_former_image);
5207 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5208 windows->im_next_image);
5209 (void) LogMagickEvent(X11Event,GetMagickModule(),
5210 " retain colors: 0x%lx",windows->im_retain_colors);
5211 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5212 windows->im_exit);
5213 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5214 windows->dnd_protocols);
5215 }
5216 /*
5217 Allocate standard colormap.
5218 */
5219 windows->map_info=XAllocStandardColormap();
5220 windows->icon_map=XAllocStandardColormap();
5221 if ((windows->map_info == (XStandardColormap *) NULL) ||
5222 (windows->icon_map == (XStandardColormap *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005223 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5224 "...");
cristy3ed852e2009-09-05 21:47:34 +00005225 windows->map_info->colormap=(Colormap) NULL;
5226 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005227 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005228 windows->pixel_info->annotate_context=(GC) NULL;
5229 windows->pixel_info->highlight_context=(GC) NULL;
5230 windows->pixel_info->widget_context=(GC) NULL;
5231 windows->font_info=(XFontStruct *) NULL;
5232 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005233 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005234 /*
5235 Allocate visual.
5236 */
5237 *windows->icon_resources=(*resource_info);
5238 windows->icon_resources->visual_type=(char *) "default";
5239 windows->icon_resources->colormap=SharedColormap;
5240 windows->visual_info=
5241 XBestVisualInfo(display,windows->map_info,resource_info);
5242 windows->icon_visual=
5243 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5244 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5245 (windows->icon_visual == (XVisualInfo *) NULL))
5246 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5247 resource_info->visual_type);
5248 if (IsEventLogging())
5249 {
5250 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5251 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5252 windows->visual_info->visualid);
5253 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5254 XVisualClassName(windows->visual_info->klass));
5255 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5256 windows->visual_info->depth);
5257 (void) LogMagickEvent(X11Event,GetMagickModule(),
5258 " size of colormap: %d entries",windows->visual_info->colormap_size);
5259 (void) LogMagickEvent(X11Event,GetMagickModule(),
5260 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5261 windows->visual_info->red_mask,windows->visual_info->green_mask,
5262 windows->visual_info->blue_mask);
5263 (void) LogMagickEvent(X11Event,GetMagickModule(),
5264 " significant bits in color: %d bits",
5265 windows->visual_info->bits_per_rgb);
5266 }
5267 /*
5268 Allocate class and manager hints.
5269 */
5270 windows->class_hints=XAllocClassHint();
5271 windows->manager_hints=XAllocWMHints();
5272 if ((windows->class_hints == (XClassHint *) NULL) ||
5273 (windows->manager_hints == (XWMHints *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005274 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5275 "...");
cristy3ed852e2009-09-05 21:47:34 +00005276 /*
5277 Determine group leader if we have one.
5278 */
5279 root_window=XRootWindow(display,windows->visual_info->screen);
5280 windows->group_leader.id=(Window) NULL;
5281 if (resource_info->window_group != (char *) NULL)
5282 {
cristy02e64f82013-11-14 16:20:04 +00005283 if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00005284 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5285 strtol((char *) resource_info->window_group,(char **) NULL,0));
5286 if (windows->group_leader.id == (Window) NULL)
5287 windows->group_leader.id=
5288 XWindowByName(display,root_window,resource_info->window_group);
5289 }
5290 return(windows);
5291}
5292
5293/*
5294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5295% %
5296% %
5297% %
5298% X M a k e C u r s o r %
5299% %
5300% %
5301% %
5302%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5303%
5304% XMakeCursor() creates a crosshairs X11 cursor.
5305%
5306% The format of the XMakeCursor method is:
5307%
5308% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5309% char *background_color,char *foreground_color)
5310%
5311% A description of each parameter follows:
5312%
5313% o display: Specifies a connection to an X server; returned from
5314% XOpenDisplay.
5315%
5316% o window: Specifies the ID of the window for which the cursor is
5317% assigned.
5318%
5319% o colormap: Specifies the ID of the colormap from which the background
5320% and foreground color will be retrieved.
5321%
5322% o background_color: Specifies the color to use for the cursor background.
5323%
5324% o foreground_color: Specifies the color to use for the cursor foreground.
5325%
5326*/
cristybcbda3f2011-09-03 13:01:22 +00005327MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005328 Colormap colormap,char *background_color,char *foreground_color)
5329{
5330#define scope_height 17
5331#define scope_x_hot 8
5332#define scope_y_hot 8
5333#define scope_width 17
5334
5335 static const unsigned char
5336 scope_bits[] =
5337 {
5338 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5339 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5340 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5341 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5342 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5343 },
5344 scope_mask_bits[] =
5345 {
5346 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5347 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5348 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5349 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5350 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5351 };
5352
5353 Cursor
5354 cursor;
5355
5356 Pixmap
5357 mask,
5358 source;
5359
5360 XColor
5361 background,
5362 foreground;
5363
5364 assert(display != (Display *) NULL);
5365 assert(window != (Window) NULL);
5366 assert(colormap != (Colormap) NULL);
5367 assert(background_color != (char *) NULL);
5368 assert(foreground_color != (char *) NULL);
5369 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5370 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5371 scope_height);
5372 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5373 scope_width,scope_height);
5374 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5375 {
cristyc38fbf52013-11-03 13:55:54 +00005376 ThrowXWindowException(XServerError,"UnableToCreatePixmap","...");
cristy3ed852e2009-09-05 21:47:34 +00005377 return((Cursor) NULL);
5378 }
5379 (void) XParseColor(display,colormap,background_color,&background);
5380 (void) XParseColor(display,colormap,foreground_color,&foreground);
5381 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5382 scope_x_hot,scope_y_hot);
5383 (void) XFreePixmap(display,source);
5384 (void) XFreePixmap(display,mask);
5385 return(cursor);
5386}
5387
5388/*
5389%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5390% %
5391% %
5392% %
5393% X M a k e I m a g e %
5394% %
5395% %
5396% %
5397%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5398%
5399% XMakeImage() creates an X11 image. If the image size differs from the X11
5400% image size, the image is first resized.
5401%
5402% The format of the XMakeImage method is:
5403%
5404% MagickBooleanType XMakeImage(Display *display,
5405% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005406% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005407%
5408% A description of each parameter follows:
5409%
5410% o display: Specifies a connection to an X server; returned from
5411% XOpenDisplay.
5412%
5413% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5414%
5415% o window: Specifies a pointer to a XWindowInfo structure.
5416%
5417% o image: the image.
5418%
5419% o width: Specifies the width in pixels of the rectangular area to
5420% display.
5421%
5422% o height: Specifies the height in pixels of the rectangular area to
5423% display.
5424%
cristy051718b2011-08-28 22:49:25 +00005425% o exception: return any errors or warnings in this structure.
5426%
cristy3ed852e2009-09-05 21:47:34 +00005427*/
cristybcbda3f2011-09-03 13:01:22 +00005428MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005429 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005430 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005431{
5432#define CheckOverflowException(length,width,height) \
5433 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5434
5435 int
5436 depth,
5437 format;
5438
5439 size_t
5440 length;
5441
5442 XImage
5443 *matte_image,
5444 *ximage;
5445
5446 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5447 assert(display != (Display *) NULL);
5448 assert(resource_info != (XResourceInfo *) NULL);
5449 assert(window != (XWindowInfo *) NULL);
5450 assert(width != 0);
5451 assert(height != 0);
5452 if ((window->width == 0) || (window->height == 0))
5453 return(MagickFalse);
5454 /*
5455 Apply user transforms to the image.
5456 */
5457 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5458 (void) XFlush(display);
5459 depth=(int) window->depth;
5460 if (window->destroy)
5461 window->image=DestroyImage(window->image);
5462 window->image=image;
5463 window->destroy=MagickFalse;
5464 if (window->image != (Image *) NULL)
5465 {
5466 if (window->crop_geometry != (char *) NULL)
5467 {
5468 Image
5469 *crop_image;
5470
5471 RectangleInfo
5472 crop_info;
5473
5474 /*
5475 Crop image.
5476 */
5477 window->image->page.x=0;
5478 window->image->page.y=0;
5479 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005480 &crop_info,exception);
5481 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005482 if (crop_image != (Image *) NULL)
5483 {
5484 if (window->image != image)
5485 window->image=DestroyImage(window->image);
5486 window->image=crop_image;
5487 window->destroy=MagickTrue;
5488 }
5489 }
5490 if ((width != (unsigned int) window->image->columns) ||
5491 (height != (unsigned int) window->image->rows))
5492 {
5493 Image
5494 *resize_image;
5495
5496 /*
5497 Resize image.
5498 */
5499 resize_image=NewImageList();
cristy865489b2013-10-12 01:03:29 +00005500 if ((window->pixel_info->colors == 0) &&
5501 (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5502 (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5503 resize_image=ResizeImage(window->image,width,height,
5504 image->filter,exception);
cristy3ed852e2009-09-05 21:47:34 +00005505 else
cristy865489b2013-10-12 01:03:29 +00005506 {
5507 if (window->image->storage_class == PseudoClass)
5508 resize_image=SampleImage(window->image,width,height,
5509 exception);
5510 else
5511 resize_image=ThumbnailImage(window->image,width,height,
5512 exception);
5513 }
cristy3ed852e2009-09-05 21:47:34 +00005514 if (resize_image != (Image *) NULL)
5515 {
5516 if (window->image != image)
5517 window->image=DestroyImage(window->image);
5518 window->image=resize_image;
5519 window->destroy=MagickTrue;
5520 }
5521 }
5522 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005523 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005524 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005525 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005526 }
5527 /*
5528 Create X image.
5529 */
5530 ximage=(XImage *) NULL;
5531 format=(depth == 1) ? XYBitmap : ZPixmap;
5532#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5533 if (window->shared_memory != MagickFalse)
5534 {
5535 XShmSegmentInfo
5536 *segment_info;
5537
5538 segment_info=(XShmSegmentInfo *) window->segment_info;
5539 segment_info[1].shmid=(-1);
5540 segment_info[1].shmaddr=(char *) NULL;
5541 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5542 (char *) NULL,&segment_info[1],width,height);
5543 if (ximage == (XImage *) NULL)
5544 window->shared_memory=MagickFalse;
cristy9c5171c2014-05-25 21:26:39 +00005545 else
5546 {
5547 length=(size_t) ximage->bytes_per_line*ximage->height;
5548 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5549 window->shared_memory=MagickFalse;
5550 }
cristy3ed852e2009-09-05 21:47:34 +00005551 if (window->shared_memory != MagickFalse)
5552 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5553 if (window->shared_memory != MagickFalse)
5554 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5555 if (segment_info[1].shmid < 0)
5556 window->shared_memory=MagickFalse;
5557 if (window->shared_memory != MagickFalse)
5558 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5559 else
5560 {
5561 if (ximage != (XImage *) NULL)
5562 XDestroyImage(ximage);
5563 ximage=(XImage *) NULL;
5564 if (segment_info[1].shmaddr)
5565 {
5566 (void) shmdt(segment_info[1].shmaddr);
5567 segment_info[1].shmaddr=(char *) NULL;
5568 }
5569 if (segment_info[1].shmid >= 0)
5570 {
5571 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5572 segment_info[1].shmid=(-1);
5573 }
5574 }
5575 }
5576#endif
5577 /*
5578 Allocate X image pixel data.
5579 */
5580#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5581 if (window->shared_memory)
5582 {
5583 Status
5584 status;
5585
5586 XShmSegmentInfo
5587 *segment_info;
5588
5589 (void) XSync(display,MagickFalse);
5590 xerror_alert=MagickFalse;
5591 segment_info=(XShmSegmentInfo *) window->segment_info;
5592 ximage->data=segment_info[1].shmaddr;
5593 segment_info[1].readOnly=MagickFalse;
5594 status=XShmAttach(display,&segment_info[1]);
5595 if (status != False)
5596 (void) XSync(display,MagickFalse);
5597 if ((status == False) || (xerror_alert != MagickFalse))
5598 {
5599 window->shared_memory=MagickFalse;
5600 if (status != False)
5601 XShmDetach(display,&segment_info[1]);
cristyfa18e622014-05-18 17:37:00 +00005602 ximage->data=NULL;
5603 XDestroyImage(ximage);
5604 ximage=(XImage *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005605 if (segment_info[1].shmid >= 0)
5606 {
5607 if (segment_info[1].shmaddr != NULL)
5608 (void) shmdt(segment_info[1].shmaddr);
5609 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5610 segment_info[1].shmid=(-1);
5611 segment_info[1].shmaddr=(char *) NULL;
5612 }
5613 }
5614 }
5615#endif
5616 if (window->shared_memory == MagickFalse)
5617 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5618 (char *) NULL,width,height,XBitmapPad(display),0);
5619 if (ximage == (XImage *) NULL)
5620 {
5621 /*
5622 Unable to create X image.
5623 */
5624 (void) XCheckDefineCursor(display,window->id,window->cursor);
5625 return(MagickFalse);
5626 }
5627 length=(size_t) ximage->bytes_per_line*ximage->height;
5628 if (IsEventLogging())
5629 {
5630 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5631 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5632 ximage->width,ximage->height);
5633 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5634 ximage->format);
5635 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5636 ximage->byte_order);
5637 (void) LogMagickEvent(X11Event,GetMagickModule(),
5638 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5639 ximage->bitmap_bit_order,ximage->bitmap_pad);
5640 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5641 ximage->depth);
5642 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5643 ximage->bytes_per_line);
5644 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5645 ximage->bits_per_pixel);
5646 (void) LogMagickEvent(X11Event,GetMagickModule(),
5647 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5648 ximage->green_mask,ximage->blue_mask);
5649 }
5650 if (window->shared_memory == MagickFalse)
5651 {
5652 if (ximage->format != XYBitmap)
cristy9aecad62013-04-18 10:37:47 +00005653 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5654 ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005655 else
cristy9aecad62013-04-18 10:37:47 +00005656 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5657 ximage->depth*ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005658 }
5659 if (ximage->data == (char *) NULL)
5660 {
5661 /*
5662 Unable to allocate pixel data.
5663 */
5664 XDestroyImage(ximage);
5665 ximage=(XImage *) NULL;
5666 (void) XCheckDefineCursor(display,window->id,window->cursor);
5667 return(MagickFalse);
5668 }
5669 if (window->ximage != (XImage *) NULL)
5670 {
5671 /*
5672 Destroy previous X image.
5673 */
5674 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5675#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5676 if (window->segment_info != (XShmSegmentInfo *) NULL)
5677 {
5678 XShmSegmentInfo
5679 *segment_info;
5680
5681 segment_info=(XShmSegmentInfo *) window->segment_info;
5682 if (segment_info[0].shmid >= 0)
5683 {
5684 (void) XSync(display,MagickFalse);
5685 (void) XShmDetach(display,&segment_info[0]);
5686 (void) XSync(display,MagickFalse);
5687 if (segment_info[0].shmaddr != (char *) NULL)
5688 (void) shmdt(segment_info[0].shmaddr);
5689 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5690 segment_info[0].shmid=(-1);
5691 segment_info[0].shmaddr=(char *) NULL;
5692 window->ximage->data=(char *) NULL;
5693 }
5694 }
5695#endif
5696 if (window->ximage->data != (char *) NULL)
5697 free(window->ximage->data);
5698 window->ximage->data=(char *) NULL;
5699 XDestroyImage(window->ximage);
5700 window->ximage=(XImage *) NULL;
5701 }
5702#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5703 if (window->segment_info != (XShmSegmentInfo *) NULL)
5704 {
5705 XShmSegmentInfo
5706 *segment_info;
5707
5708 segment_info=(XShmSegmentInfo *) window->segment_info;
5709 segment_info[0]=segment_info[1];
5710 }
5711#endif
5712 window->ximage=ximage;
5713 matte_image=(XImage *) NULL;
5714 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
cristy17f11b02014-12-20 19:37:04 +00005715 if ((window->image->alpha_trait != UndefinedPixelTrait) &&
cristyc57f6942010-11-12 01:47:39 +00005716 ((int) width <= XDisplayWidth(display,window->screen)) &&
5717 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005718 {
5719 /*
5720 Create matte image.
5721 */
5722 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5723 (char *) NULL,width,height,XBitmapPad(display),0);
5724 if (IsEventLogging())
5725 {
5726 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5727 (void) LogMagickEvent(X11Event,GetMagickModule(),
5728 " width, height: %dx%d",matte_image->width,matte_image->height);
5729 }
5730 if (matte_image != (XImage *) NULL)
5731 {
5732 /*
5733 Allocate matte image pixel data.
5734 */
cristy9aecad62013-04-18 10:37:47 +00005735 matte_image->data=(char *) malloc((size_t)
5736 matte_image->bytes_per_line*matte_image->depth*
5737 matte_image->height);
cristy3ed852e2009-09-05 21:47:34 +00005738 if (matte_image->data == (char *) NULL)
5739 {
5740 XDestroyImage(matte_image);
5741 matte_image=(XImage *) NULL;
5742 }
5743 }
5744 }
5745 if (window->matte_image != (XImage *) NULL)
5746 {
5747 /*
5748 Free matte image.
5749 */
5750 if (window->matte_image->data != (char *) NULL)
5751 free(window->matte_image->data);
5752 window->matte_image->data=(char *) NULL;
5753 XDestroyImage(window->matte_image);
5754 window->matte_image=(XImage *) NULL;
5755 }
5756 window->matte_image=matte_image;
5757 if (window->matte_pixmap != (Pixmap) NULL)
5758 {
5759 (void) XFreePixmap(display,window->matte_pixmap);
5760 window->matte_pixmap=(Pixmap) NULL;
5761#if defined(MAGICKCORE_HAVE_SHAPE)
5762 if (window->shape != MagickFalse)
5763 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5764#endif
5765 }
5766 window->stasis=MagickFalse;
5767 /*
5768 Convert pixels to X image data.
5769 */
5770 if (window->image != (Image *) NULL)
5771 {
5772 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5773 (ximage->bitmap_bit_order == LSBFirst)))
5774 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005775 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005776 else
5777 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005778 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005779 }
5780 if (window->matte_image != (XImage *) NULL)
5781 {
5782 /*
5783 Create matte pixmap.
5784 */
5785 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5786 if (window->matte_pixmap != (Pixmap) NULL)
5787 {
5788 GC
5789 graphics_context;
5790
5791 XGCValues
5792 context_values;
5793
5794 /*
5795 Copy matte image to matte pixmap.
5796 */
cristy4c08aed2011-07-01 19:47:50 +00005797 context_values.background=0;
5798 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005799 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005800 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005801 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5802 window->matte_image,0,0,0,0,width,height);
5803 (void) XFreeGC(display,graphics_context);
5804#if defined(MAGICKCORE_HAVE_SHAPE)
5805 if (window->shape != MagickFalse)
5806 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5807 window->matte_pixmap,ShapeSet);
5808#endif
5809 }
5810 }
5811 (void) XMakePixmap(display,resource_info,window);
5812 /*
5813 Restore cursor.
5814 */
5815 (void) XCheckDefineCursor(display,window->id,window->cursor);
5816 return(MagickTrue);
5817}
5818
5819/*
5820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5821% %
5822% %
5823% %
5824+ X M a k e I m a g e L S B F i r s t %
5825% %
5826% %
5827% %
5828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5829%
5830% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5831% pixels are copied in least-significant bit and byte first order. The
5832% server's scanline pad is respected. Rather than using one or two general
5833% cases, many special cases are found here to help speed up the image
5834% conversion.
5835%
5836% The format of the XMakeImageLSBFirst method is:
5837%
cristye941a752011-10-15 01:52:48 +00005838% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5839% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005840%
5841% A description of each parameter follows:
5842%
5843% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5844%
5845% o window: Specifies a pointer to a XWindowInfo structure.
5846%
5847% o image: the image.
5848%
5849% o ximage: Specifies a pointer to a XImage structure; returned from
5850% XCreateImage.
5851%
5852% o matte_image: Specifies a pointer to a XImage structure; returned from
5853% XCreateImage.
5854%
cristye941a752011-10-15 01:52:48 +00005855% o exception: return any errors or warnings in this structure.
5856%
cristy3ed852e2009-09-05 21:47:34 +00005857*/
5858static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005859 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5860 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005861{
cristyc57f6942010-11-12 01:47:39 +00005862 CacheView
5863 *canvas_view;
5864
cristy3ed852e2009-09-05 21:47:34 +00005865 Image
5866 *canvas;
5867
5868 int
5869 y;
5870
cristy4c08aed2011-07-01 19:47:50 +00005871 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005872 *p;
5873
5874 register int
5875 x;
5876
5877 register unsigned char
5878 *q;
5879
5880 unsigned char
5881 bit,
5882 byte;
5883
5884 unsigned int
5885 scanline_pad;
5886
cristyf2faecf2010-05-28 19:19:36 +00005887 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005888 pixel,
5889 *pixels;
5890
5891 XStandardColormap
5892 *map_info;
5893
5894 assert(resource_info != (XResourceInfo *) NULL);
5895 assert(window != (XWindowInfo *) NULL);
5896 assert(image != (Image *) NULL);
5897 if (image->debug != MagickFalse)
5898 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5899 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005900 if ((window->immutable == MagickFalse) &&
cristy17f11b02014-12-20 19:37:04 +00005901 (image->storage_class == DirectClass) && (image->alpha_trait != UndefinedPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00005902 {
5903 char
5904 size[MaxTextExtent];
5905
5906 Image
5907 *pattern;
5908
5909 ImageInfo
5910 *image_info;
5911
5912 image_info=AcquireImageInfo();
5913 (void) CopyMagickString(image_info->filename,
5914 resource_info->image_info->texture != (char *) NULL ?
5915 resource_info->image_info->texture : "pattern:checkerboard",
5916 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005917 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005918 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005919 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005920 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005921 image_info=DestroyImageInfo(image_info);
5922 if (pattern != (Image *) NULL)
5923 {
cristy6710d842011-10-20 23:23:00 +00005924 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005925 if (canvas != (Image *) NULL)
cristy39172402012-03-30 13:04:39 +00005926 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00005927 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00005928 pattern=DestroyImage(pattern);
5929 }
5930 }
5931 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5932 ximage->bits_per_pixel) >> 3));
5933 map_info=window->map_info;
5934 pixels=window->pixel_info->pixels;
5935 q=(unsigned char *) ximage->data;
5936 x=0;
cristy46ff2672012-12-14 15:32:26 +00005937 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00005938 if (ximage->format == XYBitmap)
5939 {
5940 register unsigned short
5941 polarity;
5942
5943 unsigned char
5944 background,
5945 foreground;
5946
5947 /*
5948 Convert canvas to big-endian bitmap.
5949 */
5950 background=(unsigned char)
5951 (XPixelIntensity(&window->pixel_info->foreground_color) <
5952 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5953 foreground=(unsigned char)
5954 (XPixelIntensity(&window->pixel_info->background_color) <
5955 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005956 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00005957 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00005958 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005959 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5960 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005961 for (y=0; y < (int) canvas->rows; y++)
5962 {
cristyc57f6942010-11-12 01:47:39 +00005963 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005964 exception);
cristy4c08aed2011-07-01 19:47:50 +00005965 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005966 break;
cristy3ed852e2009-09-05 21:47:34 +00005967 bit=0;
5968 byte=0;
5969 for (x=0; x < (int) canvas->columns; x++)
5970 {
5971 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005972 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005973 byte|=foreground;
5974 else
5975 byte|=background;
5976 bit++;
5977 if (bit == 8)
5978 {
5979 *q++=byte;
5980 bit=0;
5981 byte=0;
5982 }
cristyed231572011-07-14 02:18:59 +00005983 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005984 }
5985 if (bit != 0)
5986 *q=byte >> (8-bit);
5987 q+=scanline_pad;
5988 }
5989 }
5990 else
5991 if (window->pixel_info->colors != 0)
5992 switch (ximage->bits_per_pixel)
5993 {
5994 case 2:
5995 {
5996 register unsigned int
5997 nibble;
5998
5999 /*
6000 Convert to 2 bit color-mapped X canvas.
6001 */
6002 for (y=0; y < (int) canvas->rows; y++)
6003 {
cristyc57f6942010-11-12 01:47:39 +00006004 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006005 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006006 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006007 break;
cristy3ed852e2009-09-05 21:47:34 +00006008 nibble=0;
6009 for (x=0; x < (int) canvas->columns; x++)
6010 {
cristy4c08aed2011-07-01 19:47:50 +00006011 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006012 switch (nibble)
6013 {
6014 case 0:
6015 {
6016 *q=(unsigned char) pixel;
6017 nibble++;
6018 break;
6019 }
6020 case 1:
6021 {
6022 *q|=(unsigned char) (pixel << 2);
6023 nibble++;
6024 break;
6025 }
6026 case 2:
6027 {
6028 *q|=(unsigned char) (pixel << 4);
6029 nibble++;
6030 break;
6031 }
6032 case 3:
6033 {
6034 *q|=(unsigned char) (pixel << 6);
6035 q++;
6036 nibble=0;
6037 break;
6038 }
6039 }
cristyed231572011-07-14 02:18:59 +00006040 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006041 }
6042 q+=scanline_pad;
6043 }
6044 break;
6045 }
6046 case 4:
6047 {
6048 register unsigned int
6049 nibble;
6050
6051 /*
6052 Convert to 4 bit color-mapped X canvas.
6053 */
6054 for (y=0; y < (int) canvas->rows; y++)
6055 {
cristyc57f6942010-11-12 01:47:39 +00006056 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006057 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006058 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006059 break;
cristy3ed852e2009-09-05 21:47:34 +00006060 nibble=0;
6061 for (x=0; x < (int) canvas->columns; x++)
6062 {
cristy4c08aed2011-07-01 19:47:50 +00006063 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006064 switch (nibble)
6065 {
6066 case 0:
6067 {
6068 *q=(unsigned char) pixel;
6069 nibble++;
6070 break;
6071 }
6072 case 1:
6073 {
6074 *q|=(unsigned char) (pixel << 4);
6075 q++;
6076 nibble=0;
6077 break;
6078 }
6079 }
cristyed231572011-07-14 02:18:59 +00006080 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006081 }
6082 q+=scanline_pad;
6083 }
6084 break;
6085 }
6086 case 6:
6087 case 8:
6088 {
6089 /*
6090 Convert to 8 bit color-mapped X canvas.
6091 */
6092 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006093 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006094 {
cristy6710d842011-10-20 23:23:00 +00006095 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006096 break;
6097 }
6098 for (y=0; y < (int) canvas->rows; y++)
6099 {
cristyc57f6942010-11-12 01:47:39 +00006100 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006101 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006102 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006103 break;
cristy3ed852e2009-09-05 21:47:34 +00006104 for (x=0; x < (int) canvas->columns; x++)
6105 {
cristy4c08aed2011-07-01 19:47:50 +00006106 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006107 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006108 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006109 }
6110 q+=scanline_pad;
6111 }
6112 break;
6113 }
6114 default:
6115 {
6116 register int
6117 k;
6118
6119 register unsigned int
6120 bytes_per_pixel;
6121
cristy3ed852e2009-09-05 21:47:34 +00006122 /*
6123 Convert to multi-byte color-mapped X canvas.
6124 */
6125 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6126 for (y=0; y < (int) canvas->rows; y++)
6127 {
cristyc57f6942010-11-12 01:47:39 +00006128 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006129 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006130 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006131 break;
cristy3ed852e2009-09-05 21:47:34 +00006132 for (x=0; x < (int) canvas->columns; x++)
6133 {
cristy4c08aed2011-07-01 19:47:50 +00006134 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006135 for (k=0; k < (int) bytes_per_pixel; k++)
6136 {
cristy42daae12013-04-07 22:36:07 +00006137 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006138 pixel>>=8;
6139 }
cristyed231572011-07-14 02:18:59 +00006140 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006141 }
6142 q+=scanline_pad;
6143 }
6144 break;
6145 }
6146 }
6147 else
6148 switch (ximage->bits_per_pixel)
6149 {
6150 case 2:
6151 {
6152 register unsigned int
6153 nibble;
6154
6155 /*
6156 Convert to contiguous 2 bit continuous-tone X canvas.
6157 */
6158 for (y=0; y < (int) canvas->rows; y++)
6159 {
6160 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006161 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006162 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006163 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006164 break;
6165 for (x=0; x < (int) canvas->columns; x++)
6166 {
cristy4c08aed2011-07-01 19:47:50 +00006167 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006168 pixel&=0xf;
6169 switch (nibble)
6170 {
6171 case 0:
6172 {
6173 *q=(unsigned char) pixel;
6174 nibble++;
6175 break;
6176 }
6177 case 1:
6178 {
6179 *q|=(unsigned char) (pixel << 2);
6180 nibble++;
6181 break;
6182 }
6183 case 2:
6184 {
6185 *q|=(unsigned char) (pixel << 4);
6186 nibble++;
6187 break;
6188 }
6189 case 3:
6190 {
6191 *q|=(unsigned char) (pixel << 6);
6192 q++;
6193 nibble=0;
6194 break;
6195 }
6196 }
cristyed231572011-07-14 02:18:59 +00006197 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006198 }
6199 q+=scanline_pad;
6200 }
6201 break;
6202 }
6203 case 4:
6204 {
6205 register unsigned int
6206 nibble;
6207
6208 /*
6209 Convert to contiguous 4 bit continuous-tone X canvas.
6210 */
6211 for (y=0; y < (int) canvas->rows; y++)
6212 {
cristyc57f6942010-11-12 01:47:39 +00006213 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006214 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006215 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006216 break;
6217 nibble=0;
6218 for (x=0; x < (int) canvas->columns; x++)
6219 {
cristy4c08aed2011-07-01 19:47:50 +00006220 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006221 pixel&=0xf;
6222 switch (nibble)
6223 {
6224 case 0:
6225 {
6226 *q=(unsigned char) pixel;
6227 nibble++;
6228 break;
6229 }
6230 case 1:
6231 {
6232 *q|=(unsigned char) (pixel << 4);
6233 q++;
6234 nibble=0;
6235 break;
6236 }
6237 }
cristyed231572011-07-14 02:18:59 +00006238 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006239 }
6240 q+=scanline_pad;
6241 }
6242 break;
6243 }
6244 case 6:
6245 case 8:
6246 {
6247 /*
6248 Convert to contiguous 8 bit continuous-tone X canvas.
6249 */
6250 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006251 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006252 {
cristy6710d842011-10-20 23:23:00 +00006253 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006254 break;
6255 }
6256 for (y=0; y < (int) canvas->rows; y++)
6257 {
cristyc57f6942010-11-12 01:47:39 +00006258 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006259 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006260 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006261 break;
6262 for (x=0; x < (int) canvas->columns; x++)
6263 {
cristy4c08aed2011-07-01 19:47:50 +00006264 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006265 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006266 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006267 }
6268 q+=scanline_pad;
6269 }
6270 break;
6271 }
6272 default:
6273 {
6274 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6275 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6276 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6277 (map_info->blue_mult == 1))
6278 {
6279 /*
6280 Convert to 32 bit continuous-tone X canvas.
6281 */
6282 for (y=0; y < (int) canvas->rows; y++)
6283 {
cristyc57f6942010-11-12 01:47:39 +00006284 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006285 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006286 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006287 break;
6288 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6289 (blue_gamma != 1.0))
6290 {
6291 /*
6292 Gamma correct canvas.
6293 */
6294 for (x=(int) canvas->columns-1; x >= 0; x--)
6295 {
cristyccf844f2010-02-03 23:28:16 +00006296 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006297 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006298 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006299 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006300 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006301 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006302 *q++=0;
cristyed231572011-07-14 02:18:59 +00006303 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006304 }
6305 continue;
6306 }
6307 for (x=(int) canvas->columns-1; x >= 0; x--)
6308 {
cristy8bc259b2012-06-21 23:53:15 +00006309 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6310 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6311 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006312 *q++=0;
cristyed231572011-07-14 02:18:59 +00006313 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006314 }
6315 }
6316 }
6317 else
6318 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6319 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6320 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6321 (map_info->blue_mult == 65536L))
6322 {
6323 /*
6324 Convert to 32 bit continuous-tone X canvas.
6325 */
6326 for (y=0; y < (int) canvas->rows; y++)
6327 {
cristyc57f6942010-11-12 01:47:39 +00006328 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006329 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006330 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006331 break;
6332 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6333 (blue_gamma != 1.0))
6334 {
6335 /*
6336 Gamma correct canvas.
6337 */
6338 for (x=(int) canvas->columns-1; x >= 0; x--)
6339 {
cristyccf844f2010-02-03 23:28:16 +00006340 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006341 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006342 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006343 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006344 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006345 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006346 *q++=0;
cristyed231572011-07-14 02:18:59 +00006347 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006348 }
6349 continue;
6350 }
6351 for (x=(int) canvas->columns-1; x >= 0; x--)
6352 {
cristy8bc259b2012-06-21 23:53:15 +00006353 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6354 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6355 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006356 *q++=0;
cristyed231572011-07-14 02:18:59 +00006357 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006358 }
6359 }
6360 }
6361 else
6362 {
6363 register int
6364 k;
6365
6366 register unsigned int
6367 bytes_per_pixel;
6368
cristy3ed852e2009-09-05 21:47:34 +00006369 /*
6370 Convert to multi-byte continuous-tone X canvas.
6371 */
6372 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6373 for (y=0; y < (int) canvas->rows; y++)
6374 {
cristyc57f6942010-11-12 01:47:39 +00006375 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006376 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006377 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006378 break;
cristyc57f6942010-11-12 01:47:39 +00006379 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006380 {
cristy4c08aed2011-07-01 19:47:50 +00006381 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006382 for (k=0; k < (int) bytes_per_pixel; k++)
6383 {
cristy42daae12013-04-07 22:36:07 +00006384 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006385 pixel>>=8;
6386 }
cristyed231572011-07-14 02:18:59 +00006387 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006388 }
6389 q+=scanline_pad;
6390 }
6391 }
6392 break;
6393 }
6394 }
6395 if (matte_image != (XImage *) NULL)
6396 {
6397 /*
6398 Initialize matte canvas.
6399 */
6400 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6401 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6402 q=(unsigned char *) matte_image->data;
6403 for (y=0; y < (int) canvas->rows; y++)
6404 {
cristyc57f6942010-11-12 01:47:39 +00006405 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006406 exception);
cristy4c08aed2011-07-01 19:47:50 +00006407 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006408 break;
6409 bit=0;
6410 byte=0;
6411 for (x=(int) canvas->columns-1; x >= 0; x--)
6412 {
6413 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006414 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006415 byte|=0x80;
6416 bit++;
6417 if (bit == 8)
6418 {
6419 *q++=byte;
6420 bit=0;
6421 byte=0;
6422 }
cristyed231572011-07-14 02:18:59 +00006423 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006424 }
6425 if (bit != 0)
6426 *q=byte >> (8-bit);
6427 q+=scanline_pad;
6428 }
6429 }
cristyc57f6942010-11-12 01:47:39 +00006430 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006431 if (canvas != image)
6432 canvas=DestroyImage(canvas);
6433}
6434
6435/*
6436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6437% %
6438% %
6439% %
6440+ X M a k e I m a g e M S B F i r s t %
6441% %
6442% %
6443% %
6444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6445%
6446% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6447% image pixels are copied in most-significant bit and byte first order. The
6448% server's scanline pad is also respected. Rather than using one or two
6449% general cases, many special cases are found here to help speed up the image
6450% conversion.
6451%
6452% The format of the XMakeImageMSBFirst method is:
6453%
cristye941a752011-10-15 01:52:48 +00006454% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6455% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006456%
6457% A description of each parameter follows:
6458%
6459% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6460%
6461% o window: Specifies a pointer to a XWindowInfo structure.
6462%
6463% o image: the image.
6464%
6465% o ximage: Specifies a pointer to a XImage structure; returned from
6466% XCreateImage.
6467%
6468% o matte_image: Specifies a pointer to a XImage structure; returned from
6469% XCreateImage.
6470%
cristye941a752011-10-15 01:52:48 +00006471% o exception: return any errors or warnings in this structure.
6472%
cristy3ed852e2009-09-05 21:47:34 +00006473*/
6474static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006475 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6476 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006477{
cristyc57f6942010-11-12 01:47:39 +00006478 CacheView
6479 *canvas_view;
6480
cristy3ed852e2009-09-05 21:47:34 +00006481 Image
6482 *canvas;
6483
6484 int
6485 y;
6486
6487 register int
6488 x;
6489
cristy4c08aed2011-07-01 19:47:50 +00006490 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006491 *p;
6492
6493 register unsigned char
6494 *q;
6495
6496 unsigned char
6497 bit,
6498 byte;
6499
6500 unsigned int
6501 scanline_pad;
6502
cristyf2faecf2010-05-28 19:19:36 +00006503 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006504 pixel,
6505 *pixels;
6506
6507 XStandardColormap
6508 *map_info;
6509
6510 assert(resource_info != (XResourceInfo *) NULL);
6511 assert(window != (XWindowInfo *) NULL);
6512 assert(image != (Image *) NULL);
6513 if (image->debug != MagickFalse)
6514 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6515 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006516 if ((window->immutable != MagickFalse) &&
cristy17f11b02014-12-20 19:37:04 +00006517 (image->storage_class == DirectClass) && (image->alpha_trait != UndefinedPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00006518 {
6519 char
6520 size[MaxTextExtent];
6521
6522 Image
6523 *pattern;
6524
6525 ImageInfo
6526 *image_info;
6527
6528 image_info=AcquireImageInfo();
6529 (void) CopyMagickString(image_info->filename,
6530 resource_info->image_info->texture != (char *) NULL ?
6531 resource_info->image_info->texture : "pattern:checkerboard",
6532 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006533 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006534 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006535 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006536 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006537 image_info=DestroyImageInfo(image_info);
6538 if (pattern != (Image *) NULL)
6539 {
cristy6710d842011-10-20 23:23:00 +00006540 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006541 if (canvas != (Image *) NULL)
cristyfeb3e962012-03-29 17:25:55 +00006542 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6543 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00006544 pattern=DestroyImage(pattern);
6545 }
6546 }
cristy4c08aed2011-07-01 19:47:50 +00006547 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6548 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006549 map_info=window->map_info;
6550 pixels=window->pixel_info->pixels;
6551 q=(unsigned char *) ximage->data;
6552 x=0;
cristy46ff2672012-12-14 15:32:26 +00006553 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00006554 if (ximage->format == XYBitmap)
6555 {
6556 register unsigned short
6557 polarity;
6558
6559 unsigned char
6560 background,
6561 foreground;
6562
6563 /*
6564 Convert canvas to big-endian bitmap.
6565 */
6566 background=(unsigned char)
6567 (XPixelIntensity(&window->pixel_info->foreground_color) <
6568 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6569 foreground=(unsigned char)
6570 (XPixelIntensity(&window->pixel_info->background_color) <
6571 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006572 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00006573 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00006574 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006575 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6576 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006577 for (y=0; y < (int) canvas->rows; y++)
6578 {
cristyc57f6942010-11-12 01:47:39 +00006579 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006580 exception);
cristy4c08aed2011-07-01 19:47:50 +00006581 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006582 break;
cristy3ed852e2009-09-05 21:47:34 +00006583 bit=0;
6584 byte=0;
6585 for (x=(int) canvas->columns-1; x >= 0; x--)
6586 {
6587 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006588 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006589 byte|=foreground;
6590 else
6591 byte|=background;
6592 bit++;
6593 if (bit == 8)
6594 {
6595 *q++=byte;
6596 bit=0;
6597 byte=0;
6598 }
cristyed231572011-07-14 02:18:59 +00006599 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006600 }
6601 if (bit != 0)
6602 *q=byte << (8-bit);
6603 q+=scanline_pad;
6604 }
6605 }
6606 else
6607 if (window->pixel_info->colors != 0)
6608 switch (ximage->bits_per_pixel)
6609 {
6610 case 2:
6611 {
6612 register unsigned int
6613 nibble;
6614
6615 /*
6616 Convert to 2 bit color-mapped X canvas.
6617 */
6618 for (y=0; y < (int) canvas->rows; y++)
6619 {
cristyc57f6942010-11-12 01:47:39 +00006620 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006621 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006622 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006623 break;
cristy3ed852e2009-09-05 21:47:34 +00006624 nibble=0;
6625 for (x=0; x < (int) canvas->columns; x++)
6626 {
cristy4c08aed2011-07-01 19:47:50 +00006627 pixel=pixels[(ssize_t)
6628 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006629 switch (nibble)
6630 {
6631 case 0:
6632 {
6633 *q=(unsigned char) (pixel << 6);
6634 nibble++;
6635 break;
6636 }
6637 case 1:
6638 {
6639 *q|=(unsigned char) (pixel << 4);
6640 nibble++;
6641 break;
6642 }
6643 case 2:
6644 {
6645 *q|=(unsigned char) (pixel << 2);
6646 nibble++;
6647 break;
6648 }
6649 case 3:
6650 {
6651 *q|=(unsigned char) pixel;
6652 q++;
6653 nibble=0;
6654 break;
6655 }
6656 }
cristyed231572011-07-14 02:18:59 +00006657 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006658 }
6659 q+=scanline_pad;
6660 }
6661 break;
6662 }
6663 case 4:
6664 {
6665 register unsigned int
6666 nibble;
6667
6668 /*
6669 Convert to 4 bit color-mapped X canvas.
6670 */
6671 for (y=0; y < (int) canvas->rows; y++)
6672 {
cristyc57f6942010-11-12 01:47:39 +00006673 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006674 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006675 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006676 break;
cristy3ed852e2009-09-05 21:47:34 +00006677 nibble=0;
6678 for (x=0; x < (int) canvas->columns; x++)
6679 {
cristy4c08aed2011-07-01 19:47:50 +00006680 pixel=pixels[(ssize_t)
6681 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006682 switch (nibble)
6683 {
6684 case 0:
6685 {
6686 *q=(unsigned char) (pixel << 4);
6687 nibble++;
6688 break;
6689 }
6690 case 1:
6691 {
6692 *q|=(unsigned char) pixel;
6693 q++;
6694 nibble=0;
6695 break;
6696 }
6697 }
cristyed231572011-07-14 02:18:59 +00006698 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006699 }
6700 q+=scanline_pad;
6701 }
6702 break;
6703 }
6704 case 6:
6705 case 8:
6706 {
6707 /*
6708 Convert to 8 bit color-mapped X canvas.
6709 */
6710 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006711 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006712 {
cristy6710d842011-10-20 23:23:00 +00006713 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006714 break;
6715 }
6716 for (y=0; y < (int) canvas->rows; y++)
6717 {
cristyc57f6942010-11-12 01:47:39 +00006718 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006719 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006720 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006721 break;
cristy3ed852e2009-09-05 21:47:34 +00006722 for (x=0; x < (int) canvas->columns; x++)
6723 {
cristy6710d842011-10-20 23:23:00 +00006724 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006725 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006726 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006727 }
6728 q+=scanline_pad;
6729 }
6730 break;
6731 }
6732 default:
6733 {
6734 register int
6735 k;
6736
6737 register unsigned int
6738 bytes_per_pixel;
6739
6740 unsigned char
cristybb503372010-05-27 20:51:26 +00006741 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006742
6743 /*
6744 Convert to 8 bit color-mapped X canvas.
6745 */
6746 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6747 for (y=0; y < (int) canvas->rows; y++)
6748 {
cristyc57f6942010-11-12 01:47:39 +00006749 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006750 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006751 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006752 break;
cristy3ed852e2009-09-05 21:47:34 +00006753 for (x=0; x < (int) canvas->columns; x++)
6754 {
cristy4c08aed2011-07-01 19:47:50 +00006755 pixel=pixels[(ssize_t)
6756 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006757 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6758 {
6759 channel[k]=(unsigned char) pixel;
6760 pixel>>=8;
6761 }
6762 for (k=0; k < (int) bytes_per_pixel; k++)
6763 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006764 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006765 }
6766 q+=scanline_pad;
6767 }
6768 break;
6769 }
6770 }
6771 else
6772 switch (ximage->bits_per_pixel)
6773 {
6774 case 2:
6775 {
6776 register unsigned int
6777 nibble;
6778
6779 /*
6780 Convert to 4 bit continuous-tone X canvas.
6781 */
6782 for (y=0; y < (int) canvas->rows; y++)
6783 {
cristyc57f6942010-11-12 01:47:39 +00006784 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006785 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006786 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006787 break;
6788 nibble=0;
6789 for (x=(int) canvas->columns-1; x >= 0; x--)
6790 {
cristy4c08aed2011-07-01 19:47:50 +00006791 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006792 pixel&=0xf;
6793 switch (nibble)
6794 {
6795 case 0:
6796 {
6797 *q=(unsigned char) (pixel << 6);
6798 nibble++;
6799 break;
6800 }
6801 case 1:
6802 {
6803 *q|=(unsigned char) (pixel << 4);
6804 nibble++;
6805 break;
6806 }
6807 case 2:
6808 {
6809 *q|=(unsigned char) (pixel << 2);
6810 nibble++;
6811 break;
6812 }
6813 case 3:
6814 {
6815 *q|=(unsigned char) pixel;
6816 q++;
6817 nibble=0;
6818 break;
6819 }
6820 }
cristyed231572011-07-14 02:18:59 +00006821 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006822 }
6823 q+=scanline_pad;
6824 }
6825 break;
6826 }
6827 case 4:
6828 {
6829 register unsigned int
6830 nibble;
6831
6832 /*
6833 Convert to 4 bit continuous-tone X canvas.
6834 */
6835 for (y=0; y < (int) canvas->rows; y++)
6836 {
cristyc57f6942010-11-12 01:47:39 +00006837 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006838 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006839 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006840 break;
6841 nibble=0;
6842 for (x=(int) canvas->columns-1; x >= 0; x--)
6843 {
cristy4c08aed2011-07-01 19:47:50 +00006844 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006845 pixel&=0xf;
6846 switch (nibble)
6847 {
6848 case 0:
6849 {
6850 *q=(unsigned char) (pixel << 4);
6851 nibble++;
6852 break;
6853 }
6854 case 1:
6855 {
6856 *q|=(unsigned char) pixel;
6857 q++;
6858 nibble=0;
6859 break;
6860 }
6861 }
cristyed231572011-07-14 02:18:59 +00006862 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006863 }
6864 q+=scanline_pad;
6865 }
6866 break;
6867 }
6868 case 6:
6869 case 8:
6870 {
6871 /*
6872 Convert to 8 bit continuous-tone X canvas.
6873 */
6874 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006875 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006876 {
cristy6710d842011-10-20 23:23:00 +00006877 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006878 break;
6879 }
6880 for (y=0; y < (int) canvas->rows; y++)
6881 {
cristyc57f6942010-11-12 01:47:39 +00006882 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006883 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006884 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006885 break;
6886 for (x=(int) canvas->columns-1; x >= 0; x--)
6887 {
cristy4c08aed2011-07-01 19:47:50 +00006888 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006889 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006890 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006891 }
6892 q+=scanline_pad;
6893 }
6894 break;
6895 }
6896 default:
6897 {
6898 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6899 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6900 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6901 (map_info->blue_mult == 1))
6902 {
6903 /*
6904 Convert to 32 bit continuous-tone X canvas.
6905 */
6906 for (y=0; y < (int) canvas->rows; y++)
6907 {
cristyc57f6942010-11-12 01:47:39 +00006908 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006909 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006910 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006911 break;
6912 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6913 (blue_gamma != 1.0))
6914 {
6915 /*
6916 Gamma correct canvas.
6917 */
6918 for (x=(int) canvas->columns-1; x >= 0; x--)
6919 {
6920 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006921 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006922 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006923 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006924 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006925 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006926 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006927 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006928 }
6929 continue;
6930 }
6931 for (x=(int) canvas->columns-1; x >= 0; x--)
6932 {
6933 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006934 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6935 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6936 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006937 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006938 }
6939 }
6940 }
6941 else
6942 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6943 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6944 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6945 (map_info->blue_mult == 65536L))
6946 {
6947 /*
6948 Convert to 32 bit continuous-tone X canvas.
6949 */
6950 for (y=0; y < (int) canvas->rows; y++)
6951 {
cristyc57f6942010-11-12 01:47:39 +00006952 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006953 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006954 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006955 break;
6956 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6957 (blue_gamma != 1.0))
6958 {
6959 /*
6960 Gamma correct canvas.
6961 */
6962 for (x=(int) canvas->columns-1; x >= 0; x--)
6963 {
6964 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006965 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006966 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006967 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006968 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006969 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006970 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006971 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006972 }
6973 continue;
6974 }
6975 for (x=(int) canvas->columns-1; x >= 0; x--)
6976 {
6977 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006978 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6979 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6980 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006981 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006982 }
6983 }
6984 }
6985 else
6986 {
6987 register int
6988 k;
6989
6990 register unsigned int
6991 bytes_per_pixel;
6992
6993 unsigned char
cristybb503372010-05-27 20:51:26 +00006994 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006995
6996 /*
6997 Convert to multi-byte continuous-tone X canvas.
6998 */
6999 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7000 for (y=0; y < (int) canvas->rows; y++)
7001 {
cristyc57f6942010-11-12 01:47:39 +00007002 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007003 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007004 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007005 break;
7006 for (x=(int) canvas->columns-1; x >= 0; x--)
7007 {
cristy4c08aed2011-07-01 19:47:50 +00007008 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007009 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7010 {
7011 channel[k]=(unsigned char) pixel;
7012 pixel>>=8;
7013 }
7014 for (k=0; k < (int) bytes_per_pixel; k++)
7015 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007016 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007017 }
7018 q+=scanline_pad;
7019 }
7020 }
7021 break;
7022 }
7023 }
7024 if (matte_image != (XImage *) NULL)
7025 {
7026 /*
7027 Initialize matte canvas.
7028 */
7029 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7030 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7031 q=(unsigned char *) matte_image->data;
7032 for (y=0; y < (int) canvas->rows; y++)
7033 {
cristyc57f6942010-11-12 01:47:39 +00007034 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007035 exception);
cristy4c08aed2011-07-01 19:47:50 +00007036 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007037 break;
7038 bit=0;
7039 byte=0;
7040 for (x=(int) canvas->columns-1; x >= 0; x--)
7041 {
7042 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007043 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007044 byte|=0x01;
7045 bit++;
7046 if (bit == 8)
7047 {
7048 *q++=byte;
7049 bit=0;
7050 byte=0;
7051 }
cristyed231572011-07-14 02:18:59 +00007052 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007053 }
7054 if (bit != 0)
7055 *q=byte << (8-bit);
7056 q+=scanline_pad;
7057 }
7058 }
cristyc57f6942010-11-12 01:47:39 +00007059 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007060 if (canvas != image)
7061 canvas=DestroyImage(canvas);
7062}
7063
7064/*
7065%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7066% %
7067% %
7068% %
7069% X M a k e M a g n i f y I m a g e %
7070% %
7071% %
7072% %
7073%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7074%
7075% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7076%
7077% The format of the XMakeMagnifyImage method is:
7078%
cristy6710d842011-10-20 23:23:00 +00007079% void XMakeMagnifyImage(Display *display,XWindows *windows,
7080% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007081%
7082% A description of each parameter follows:
7083%
7084% o display: Specifies a connection to an X server; returned from
7085% XOpenDisplay.
7086%
7087% o windows: Specifies a pointer to a XWindows structure.
7088%
cristy6710d842011-10-20 23:23:00 +00007089% o exception: return any errors or warnings in this structure.
7090%
cristy3ed852e2009-09-05 21:47:34 +00007091*/
cristy6710d842011-10-20 23:23:00 +00007092MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7093 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007094{
7095 char
7096 tuple[MaxTextExtent];
7097
7098 int
7099 y;
7100
cristy4c08aed2011-07-01 19:47:50 +00007101 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007102 pixel;
7103
7104 register int
7105 x;
7106
cristybb503372010-05-27 20:51:26 +00007107 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007108 i;
7109
7110 register unsigned char
7111 *p,
7112 *q;
7113
cristy9d314ff2011-03-09 01:30:28 +00007114 ssize_t
7115 n;
7116
cristy3ed852e2009-09-05 21:47:34 +00007117 static unsigned int
7118 previous_magnify = 0;
7119
7120 static XWindowInfo
7121 magnify_window;
7122
7123 unsigned int
7124 height,
7125 j,
7126 k,
7127 l,
7128 magnify,
7129 scanline_pad,
7130 width;
7131
7132 XImage
7133 *ximage;
7134
7135 /*
7136 Check boundary conditions.
7137 */
7138 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7139 assert(display != (Display *) NULL);
7140 assert(windows != (XWindows *) NULL);
7141 magnify=1;
cristybb503372010-05-27 20:51:26 +00007142 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007143 magnify<<=1;
7144 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7145 magnify<<=1;
7146 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7147 magnify<<=1;
7148 while (magnify > windows->magnify.width)
7149 magnify>>=1;
7150 while (magnify > windows->magnify.height)
7151 magnify>>=1;
cristy58a749e2014-05-25 17:36:53 +00007152 if (magnify == 0)
7153 magnify=1;
cristy3ed852e2009-09-05 21:47:34 +00007154 if (magnify != previous_magnify)
7155 {
7156 Status
7157 status;
7158
7159 XTextProperty
7160 window_name;
7161
7162 /*
7163 New magnify factor: update magnify window name.
7164 */
7165 i=0;
7166 while ((1 << i) <= (int) magnify)
7167 i++;
cristyb51dff52011-05-19 16:55:47 +00007168 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007169 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007170 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7171 if (status != False)
7172 {
7173 XSetWMName(display,windows->magnify.id,&window_name);
7174 XSetWMIconName(display,windows->magnify.id,&window_name);
7175 (void) XFree((void *) window_name.value);
7176 }
7177 }
7178 previous_magnify=magnify;
7179 ximage=windows->image.ximage;
7180 width=(unsigned int) windows->magnify.ximage->width;
7181 height=(unsigned int) windows->magnify.ximage->height;
7182 if ((windows->magnify.x < 0) ||
7183 (windows->magnify.x >= windows->image.ximage->width))
7184 windows->magnify.x=windows->image.ximage->width >> 1;
7185 x=windows->magnify.x-((width/magnify) >> 1);
7186 if (x < 0)
7187 x=0;
7188 else
7189 if (x > (int) (ximage->width-(width/magnify)))
7190 x=ximage->width-width/magnify;
7191 if ((windows->magnify.y < 0) ||
7192 (windows->magnify.y >= windows->image.ximage->height))
7193 windows->magnify.y=windows->image.ximage->height >> 1;
7194 y=windows->magnify.y-((height/magnify) >> 1);
7195 if (y < 0)
7196 y=0;
7197 else
7198 if (y > (int) (ximage->height-(height/magnify)))
7199 y=ximage->height-height/magnify;
7200 q=(unsigned char *) windows->magnify.ximage->data;
7201 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7202 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7203 if (ximage->bits_per_pixel < 8)
7204 {
7205 register unsigned char
7206 background,
7207 byte,
7208 foreground,
7209 p_bit,
7210 q_bit;
7211
7212 register unsigned int
7213 plane;
7214
7215 XPixelInfo
7216 *pixel_info;
7217
7218 pixel_info=windows->magnify.pixel_info;
7219 switch (ximage->bitmap_bit_order)
7220 {
7221 case LSBFirst:
7222 {
7223 /*
7224 Magnify little-endian bitmap.
7225 */
7226 background=0x00;
7227 foreground=0x80;
7228 if (ximage->format == XYBitmap)
7229 {
7230 background=(unsigned char)
7231 (XPixelIntensity(&pixel_info->foreground_color) <
7232 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7233 foreground=(unsigned char)
7234 (XPixelIntensity(&pixel_info->background_color) <
7235 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7236 if (windows->magnify.depth > 1)
7237 Swap(background,foreground);
7238 }
cristybb503372010-05-27 20:51:26 +00007239 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007240 {
7241 /*
7242 Propogate pixel magnify rows.
7243 */
7244 for (j=0; j < magnify; j++)
7245 {
7246 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7247 ((x*ximage->bits_per_pixel) >> 3);
7248 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7249 q_bit=0;
7250 byte=0;
7251 for (k=0; k < width; k+=magnify)
7252 {
7253 /*
7254 Propogate pixel magnify columns.
7255 */
7256 for (l=0; l < magnify; l++)
7257 {
7258 /*
7259 Propogate each bit plane.
7260 */
7261 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7262 {
7263 byte>>=1;
7264 if (*p & (0x01 << (p_bit+plane)))
7265 byte|=foreground;
7266 else
7267 byte|=background;
7268 q_bit++;
7269 if (q_bit == 8)
7270 {
7271 *q++=byte;
7272 q_bit=0;
7273 byte=0;
7274 }
7275 }
7276 }
7277 p_bit+=ximage->bits_per_pixel;
7278 if (p_bit == 8)
7279 {
7280 p++;
7281 p_bit=0;
7282 }
7283 if (q_bit != 0)
7284 *q=byte >> (8-q_bit);
7285 q+=scanline_pad;
7286 }
7287 }
7288 y++;
7289 }
7290 break;
7291 }
7292 case MSBFirst:
7293 default:
7294 {
7295 /*
7296 Magnify big-endian bitmap.
7297 */
7298 background=0x00;
7299 foreground=0x01;
7300 if (ximage->format == XYBitmap)
7301 {
7302 background=(unsigned char)
7303 (XPixelIntensity(&pixel_info->foreground_color) <
7304 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7305 foreground=(unsigned char)
7306 (XPixelIntensity(&pixel_info->background_color) <
7307 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7308 if (windows->magnify.depth > 1)
7309 Swap(background,foreground);
7310 }
cristybb503372010-05-27 20:51:26 +00007311 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007312 {
7313 /*
7314 Propogate pixel magnify rows.
7315 */
7316 for (j=0; j < magnify; j++)
7317 {
7318 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7319 ((x*ximage->bits_per_pixel) >> 3);
7320 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7321 q_bit=0;
7322 byte=0;
7323 for (k=0; k < width; k+=magnify)
7324 {
7325 /*
7326 Propogate pixel magnify columns.
7327 */
7328 for (l=0; l < magnify; l++)
7329 {
7330 /*
7331 Propogate each bit plane.
7332 */
7333 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7334 {
7335 byte<<=1;
7336 if (*p & (0x80 >> (p_bit+plane)))
7337 byte|=foreground;
7338 else
7339 byte|=background;
7340 q_bit++;
7341 if (q_bit == 8)
7342 {
7343 *q++=byte;
7344 q_bit=0;
7345 byte=0;
7346 }
7347 }
7348 }
7349 p_bit+=ximage->bits_per_pixel;
7350 if (p_bit == 8)
7351 {
7352 p++;
7353 p_bit=0;
7354 }
7355 if (q_bit != 0)
7356 *q=byte << (8-q_bit);
7357 q+=scanline_pad;
7358 }
7359 }
7360 y++;
7361 }
7362 break;
7363 }
7364 }
7365 }
7366 else
7367 switch (ximage->bits_per_pixel)
7368 {
7369 case 6:
7370 case 8:
7371 {
7372 /*
7373 Magnify 8 bit X image.
7374 */
cristybb503372010-05-27 20:51:26 +00007375 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007376 {
7377 /*
7378 Propogate pixel magnify rows.
7379 */
7380 for (j=0; j < magnify; j++)
7381 {
7382 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7383 ((x*ximage->bits_per_pixel) >> 3);
7384 for (k=0; k < width; k+=magnify)
7385 {
7386 /*
7387 Propogate pixel magnify columns.
7388 */
7389 for (l=0; l < magnify; l++)
7390 *q++=(*p);
7391 p++;
7392 }
7393 q+=scanline_pad;
7394 }
7395 y++;
7396 }
7397 break;
7398 }
7399 default:
7400 {
7401 register unsigned int
7402 bytes_per_pixel,
7403 m;
7404
7405 /*
7406 Magnify multi-byte X image.
7407 */
7408 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007409 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007410 {
7411 /*
7412 Propogate pixel magnify rows.
7413 */
7414 for (j=0; j < magnify; j++)
7415 {
7416 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7417 ((x*ximage->bits_per_pixel) >> 3);
7418 for (k=0; k < width; k+=magnify)
7419 {
7420 /*
7421 Propogate pixel magnify columns.
7422 */
7423 for (l=0; l < magnify; l++)
7424 for (m=0; m < bytes_per_pixel; m++)
7425 *q++=(*(p+m));
7426 p+=bytes_per_pixel;
7427 }
7428 q+=scanline_pad;
7429 }
7430 y++;
7431 }
7432 break;
7433 }
7434 }
7435 /*
7436 Copy X image to magnify pixmap.
7437 */
7438 x=windows->magnify.x-((width/magnify) >> 1);
7439 if (x < 0)
7440 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7441 else
7442 if (x > (int) (ximage->width-(width/magnify)))
7443 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7444 else
7445 x=0;
7446 y=windows->magnify.y-((height/magnify) >> 1);
7447 if (y < 0)
7448 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7449 else
7450 if (y > (int) (ximage->height-(height/magnify)))
7451 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7452 else
7453 y=0;
7454 if ((x != 0) || (y != 0))
7455 (void) XFillRectangle(display,windows->magnify.pixmap,
7456 windows->magnify.annotate_context,0,0,width,height);
7457 (void) XPutImage(display,windows->magnify.pixmap,
7458 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7459 height-y);
7460 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7461 (magnify <= (height >> 1))))
7462 {
7463 RectangleInfo
7464 highlight_info;
7465
7466 /*
7467 Highlight center pixel.
7468 */
cristybb503372010-05-27 20:51:26 +00007469 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7470 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007471 highlight_info.width=magnify;
7472 highlight_info.height=magnify;
7473 (void) XDrawRectangle(display,windows->magnify.pixmap,
7474 windows->magnify.highlight_context,(int) highlight_info.x,
7475 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7476 (unsigned int) highlight_info.height-1);
7477 if (magnify > 2)
7478 (void) XDrawRectangle(display,windows->magnify.pixmap,
7479 windows->magnify.annotate_context,(int) highlight_info.x+1,
7480 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7481 (unsigned int) highlight_info.height-3);
7482 }
7483 /*
7484 Show center pixel color.
7485 */
cristy3aa93752011-12-18 15:54:24 +00007486 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007487 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007488 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007489 windows->magnify.x,windows->magnify.y);
7490 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007491 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007492 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007493 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007494 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007495 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007496 if (pixel.colorspace == CMYKColorspace)
7497 {
7498 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007499 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007500 }
cristy17f11b02014-12-20 19:37:04 +00007501 if (pixel.alpha_trait != UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00007502 {
7503 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007504 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007505 }
7506 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7507 height=(unsigned int) windows->magnify.font_info->ascent+
7508 windows->magnify.font_info->descent;
7509 x=windows->magnify.font_info->max_bounds.width >> 1;
7510 y=windows->magnify.font_info->ascent+(height >> 2);
7511 (void) XDrawImageString(display,windows->magnify.pixmap,
7512 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7513 GetColorTuple(&pixel,MagickTrue,tuple);
7514 y+=height;
7515 (void) XDrawImageString(display,windows->magnify.pixmap,
7516 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007517 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007518 exception);
cristy3ed852e2009-09-05 21:47:34 +00007519 y+=height;
7520 (void) XDrawImageString(display,windows->magnify.pixmap,
7521 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7522 /*
7523 Refresh magnify window.
7524 */
7525 magnify_window=windows->magnify;
7526 magnify_window.x=0;
7527 magnify_window.y=0;
7528 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7529}
7530
7531/*
7532%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7533% %
7534% %
7535% %
7536% X M a k e P i x m a p %
7537% %
7538% %
7539% %
7540%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7541%
7542% XMakePixmap() creates an X11 pixmap.
7543%
7544% The format of the XMakePixmap method is:
7545%
7546% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7547% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7548% XPixelInfo *pixel)
7549%
7550% A description of each parameter follows:
7551%
7552% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7553%
7554% o display: Specifies a connection to an X server; returned from
7555% XOpenDisplay.
7556%
7557% o window: Specifies a pointer to a XWindowInfo structure.
7558%
cristy3ed852e2009-09-05 21:47:34 +00007559*/
7560static MagickBooleanType XMakePixmap(Display *display,
7561 const XResourceInfo *resource_info,XWindowInfo *window)
7562{
7563 unsigned int
7564 height,
7565 width;
7566
7567 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7568 assert(display != (Display *) NULL);
7569 assert(resource_info != (XResourceInfo *) NULL);
7570 assert(window != (XWindowInfo *) NULL);
7571 if (window->pixmap != (Pixmap) NULL)
7572 {
7573 /*
7574 Destroy previous X pixmap.
7575 */
7576 (void) XFreePixmap(display,window->pixmap);
7577 window->pixmap=(Pixmap) NULL;
7578 }
7579 if (window->use_pixmap == MagickFalse)
7580 return(MagickFalse);
7581 if (window->ximage == (XImage *) NULL)
7582 return(MagickFalse);
7583 /*
7584 Display busy cursor.
7585 */
7586 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7587 (void) XFlush(display);
7588 /*
7589 Create pixmap.
7590 */
7591 width=(unsigned int) window->ximage->width;
7592 height=(unsigned int) window->ximage->height;
7593 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7594 if (window->pixmap == (Pixmap) NULL)
7595 {
7596 /*
7597 Unable to allocate pixmap.
7598 */
7599 (void) XCheckDefineCursor(display,window->id,window->cursor);
7600 return(MagickFalse);
7601 }
7602 /*
7603 Copy X image to pixmap.
7604 */
7605#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7606 if (window->shared_memory)
7607 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7608 window->ximage,0,0,0,0,width,height,MagickTrue);
7609#endif
7610 if (window->shared_memory == MagickFalse)
7611 (void) XPutImage(display,window->pixmap,window->annotate_context,
7612 window->ximage,0,0,0,0,width,height);
7613 if (IsEventLogging())
7614 {
7615 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7616 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7617 width,height);
7618 }
7619 /*
7620 Restore cursor.
7621 */
7622 (void) XCheckDefineCursor(display,window->id,window->cursor);
7623 return(MagickTrue);
7624}
7625
7626/*
7627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7628% %
7629% %
7630% %
7631% X M a k e S t a n d a r d C o l o r m a p %
7632% %
7633% %
7634% %
7635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7636%
7637% XMakeStandardColormap() creates an X11 Standard Colormap.
7638%
7639% The format of the XMakeStandardColormap method is:
7640%
cristy6710d842011-10-20 23:23:00 +00007641% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7642% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7643% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007644%
7645% A description of each parameter follows:
7646%
7647% o display: Specifies a connection to an X server; returned from
7648% XOpenDisplay.
7649%
7650% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7651% returned from XGetVisualInfo.
7652%
7653% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7654%
7655% o image: the image.
7656%
7657% o map_info: If a Standard Colormap type is specified, this structure is
7658% initialized with info from the Standard Colormap.
7659%
7660% o pixel: Specifies a pointer to a XPixelInfo structure.
7661%
cristy6710d842011-10-20 23:23:00 +00007662% o exception: return any errors or warnings in this structure.
7663%
cristy3ed852e2009-09-05 21:47:34 +00007664*/
7665
7666#if defined(__cplusplus) || defined(c_plusplus)
7667extern "C" {
7668#endif
7669
cristya19f1d72012-08-07 18:24:38 +00007670static inline double DiversityPixelIntensity(
cristy3ed852e2009-09-05 21:47:34 +00007671 const DiversityPacket *pixel)
7672{
cristya19f1d72012-08-07 18:24:38 +00007673 double
cristy3ed852e2009-09-05 21:47:34 +00007674 intensity;
7675
cristyd3d2a272013-06-24 16:09:41 +00007676 intensity=0.212656*pixel->red+0.715158*pixel->green+0.072186*pixel->blue;
cristy3ed852e2009-09-05 21:47:34 +00007677 return(intensity);
7678}
7679
7680static int IntensityCompare(const void *x,const void *y)
7681{
7682 DiversityPacket
7683 *color_1,
7684 *color_2;
7685
7686 int
7687 diversity;
7688
7689 color_1=(DiversityPacket *) x;
7690 color_2=(DiversityPacket *) y;
7691 diversity=(int) (DiversityPixelIntensity(color_2)-
7692 DiversityPixelIntensity(color_1));
7693 return(diversity);
7694}
7695
7696static int PopularityCompare(const void *x,const void *y)
7697{
7698 DiversityPacket
7699 *color_1,
7700 *color_2;
7701
7702 color_1=(DiversityPacket *) x;
7703 color_2=(DiversityPacket *) y;
7704 return((int) color_2->count-(int) color_1->count);
7705}
7706
7707#if defined(__cplusplus) || defined(c_plusplus)
7708}
7709#endif
7710
cristybb503372010-05-27 20:51:26 +00007711static inline Quantum ScaleXToQuantum(const size_t x,
7712 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007713{
cristya19f1d72012-08-07 18:24:38 +00007714 return((Quantum) (((double) QuantumRange*x)/scale+0.5));
cristy3ed852e2009-09-05 21:47:34 +00007715}
7716
cristybcbda3f2011-09-03 13:01:22 +00007717MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007718 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007719 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007720{
7721 Colormap
7722 colormap;
7723
cristybb503372010-05-27 20:51:26 +00007724 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007725 i;
7726
7727 Status
7728 status;
7729
cristybb503372010-05-27 20:51:26 +00007730 size_t
cristy3ed852e2009-09-05 21:47:34 +00007731 number_colors,
7732 retain_colors;
7733
7734 unsigned short
7735 gray_value;
7736
7737 XColor
7738 color,
7739 *colors,
7740 *p;
7741
7742 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7743 assert(display != (Display *) NULL);
7744 assert(visual_info != (XVisualInfo *) NULL);
7745 assert(map_info != (XStandardColormap *) NULL);
7746 assert(resource_info != (XResourceInfo *) NULL);
7747 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007748 if (resource_info->map_type != (char *) NULL)
7749 {
7750 /*
7751 Standard Colormap is already defined (i.e. xstdcmap).
7752 */
cristy4c08aed2011-07-01 19:47:50 +00007753 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007754 pixel);
7755 number_colors=(unsigned int) (map_info->base_pixel+
7756 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7757 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
cristy17f11b02014-12-20 19:37:04 +00007758 if ((image->alpha_trait == UndefinedPixelTrait) &&
cristy3ed852e2009-09-05 21:47:34 +00007759 (resource_info->color_recovery == MagickFalse) &&
cristycbda6112012-05-27 20:57:16 +00007760 (resource_info->quantize_info->dither_method != NoDitherMethod) &&
cristy3ed852e2009-09-05 21:47:34 +00007761 (number_colors < MaxColormapSize))
7762 {
7763 Image
7764 *affinity_image;
7765
cristy4c08aed2011-07-01 19:47:50 +00007766 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007767 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007768
7769 /*
7770 Improve image appearance with error diffusion.
7771 */
cristy6710d842011-10-20 23:23:00 +00007772 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007773 if (affinity_image == (Image *) NULL)
7774 ThrowXWindowFatalException(ResourceLimitFatalError,
7775 "UnableToDitherImage",image->filename);
7776 affinity_image->columns=number_colors;
7777 affinity_image->rows=1;
7778 /*
7779 Initialize colormap image.
7780 */
7781 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7782 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007783 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007784 {
cristybb503372010-05-27 20:51:26 +00007785 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007786 {
cristy4c08aed2011-07-01 19:47:50 +00007787 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007788 if (map_info->red_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007789 SetPixelRed(affinity_image,ScaleXToQuantum((size_t)
7790 (i/map_info->red_mult),map_info->red_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007791 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007792 if (map_info->green_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007793 SetPixelGreen(affinity_image,ScaleXToQuantum((size_t)
7794 ((i/map_info->green_mult) % (map_info->green_max+1)),
7795 map_info->green_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007796 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007797 if (map_info->blue_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007798 SetPixelBlue(affinity_image,ScaleXToQuantum((size_t)
7799 (i % map_info->green_mult),map_info->blue_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007800 SetPixelAlpha(affinity_image,
7801 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007802 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007803 }
7804 (void) SyncAuthenticPixels(affinity_image,exception);
7805 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007806 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007807 }
cristy4c08aed2011-07-01 19:47:50 +00007808 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007809 pixel);
cristy574cc262011-08-05 01:23:58 +00007810 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007811 affinity_image=DestroyImage(affinity_image);
7812 }
7813 if (IsEventLogging())
7814 {
7815 (void) LogMagickEvent(X11Event,GetMagickModule(),
7816 "Standard Colormap:");
7817 (void) LogMagickEvent(X11Event,GetMagickModule(),
7818 " colormap id: 0x%lx",map_info->colormap);
7819 (void) LogMagickEvent(X11Event,GetMagickModule(),
7820 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7821 map_info->green_max,map_info->blue_max);
7822 (void) LogMagickEvent(X11Event,GetMagickModule(),
7823 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7824 map_info->green_mult,map_info->blue_mult);
7825 }
7826 return;
7827 }
7828 if ((visual_info->klass != DirectColor) &&
7829 (visual_info->klass != TrueColor))
7830 if ((image->storage_class == DirectClass) ||
7831 ((int) image->colors > visual_info->colormap_size))
7832 {
7833 QuantizeInfo
7834 quantize_info;
7835
7836 /*
7837 Image has more colors than the visual supports.
7838 */
7839 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007840 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007841 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007842 }
7843 /*
7844 Free previous and create new colormap.
7845 */
7846 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7847 colormap=XDefaultColormap(display,visual_info->screen);
7848 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7849 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7850 visual_info->visual,visual_info->klass == DirectColor ?
7851 AllocAll : AllocNone);
7852 if (colormap == (Colormap) NULL)
7853 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7854 image->filename);
7855 /*
7856 Initialize the map and pixel info structures.
7857 */
7858 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007859 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007860 /*
7861 Allocating colors in server colormap is based on visual class.
7862 */
7863 switch (visual_info->klass)
7864 {
7865 case StaticGray:
7866 case StaticColor:
7867 {
7868 /*
7869 Define Standard Colormap for StaticGray or StaticColor visual.
7870 */
7871 number_colors=image->colors;
7872 colors=(XColor *) AcquireQuantumMemory((size_t)
7873 visual_info->colormap_size,sizeof(*colors));
7874 if (colors == (XColor *) NULL)
7875 ThrowXWindowFatalException(ResourceLimitFatalError,
7876 "UnableToCreateColormap",image->filename);
7877 p=colors;
7878 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007879 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007880 {
7881 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7882 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7883 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7884 if (visual_info->klass != StaticColor)
7885 {
7886 gray_value=(unsigned short) XPixelIntensity(&color);
7887 color.red=gray_value;
7888 color.green=gray_value;
7889 color.blue=gray_value;
7890 }
7891 status=XAllocColor(display,colormap,&color);
7892 if (status == False)
7893 {
7894 colormap=XCopyColormapAndFree(display,colormap);
7895 (void) XAllocColor(display,colormap,&color);
7896 }
7897 pixel->pixels[i]=color.pixel;
7898 *p++=color;
7899 }
7900 break;
7901 }
7902 case GrayScale:
7903 case PseudoColor:
7904 {
7905 unsigned int
7906 colormap_type;
7907
7908 /*
7909 Define Standard Colormap for GrayScale or PseudoColor visual.
7910 */
7911 number_colors=image->colors;
7912 colors=(XColor *) AcquireQuantumMemory((size_t)
7913 visual_info->colormap_size,sizeof(*colors));
7914 if (colors == (XColor *) NULL)
7915 ThrowXWindowFatalException(ResourceLimitFatalError,
7916 "UnableToCreateColormap",image->filename);
7917 /*
7918 Preallocate our GUI colors.
7919 */
7920 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7921 (void) XAllocColor(display,colormap,&pixel->background_color);
7922 (void) XAllocColor(display,colormap,&pixel->border_color);
7923 (void) XAllocColor(display,colormap,&pixel->matte_color);
7924 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7925 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7926 (void) XAllocColor(display,colormap,&pixel->depth_color);
7927 (void) XAllocColor(display,colormap,&pixel->trough_color);
7928 for (i=0; i < MaxNumberPens; i++)
7929 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7930 /*
7931 Determine if image colors will "fit" into X server colormap.
7932 */
7933 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007934 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007935 NULL,0,pixel->pixels,(unsigned int) image->colors);
7936 if (status != False)
7937 colormap_type=PrivateColormap;
7938 if (colormap_type == SharedColormap)
7939 {
cristyc57f6942010-11-12 01:47:39 +00007940 CacheView
7941 *image_view;
7942
cristy3ed852e2009-09-05 21:47:34 +00007943 DiversityPacket
7944 *diversity;
7945
7946 int
7947 y;
7948
7949 register int
7950 x;
7951
7952 unsigned short
7953 index;
7954
7955 XColor
7956 *server_colors;
7957
7958 /*
7959 Define Standard colormap for shared GrayScale or PseudoColor visual.
7960 */
7961 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7962 sizeof(*diversity));
7963 if (diversity == (DiversityPacket *) NULL)
7964 ThrowXWindowFatalException(ResourceLimitFatalError,
7965 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007966 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007967 {
cristye42f6582012-02-11 17:59:50 +00007968 diversity[i].red=ClampToQuantum(image->colormap[i].red);
7969 diversity[i].green=ClampToQuantum(image->colormap[i].green);
7970 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00007971 diversity[i].index=(unsigned short) i;
7972 diversity[i].count=0;
7973 }
cristy46ff2672012-12-14 15:32:26 +00007974 image_view=AcquireAuthenticCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007975 for (y=0; y < (int) image->rows; y++)
7976 {
cristyc57f6942010-11-12 01:47:39 +00007977 register int
cristy3ed852e2009-09-05 21:47:34 +00007978 x;
7979
cristy4c08aed2011-07-01 19:47:50 +00007980 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007981 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007982
cristyc57f6942010-11-12 01:47:39 +00007983 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7984 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007985 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007986 break;
cristyc57f6942010-11-12 01:47:39 +00007987 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00007988 {
7989 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00007990 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00007991 }
cristy3ed852e2009-09-05 21:47:34 +00007992 }
cristyc57f6942010-11-12 01:47:39 +00007993 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00007994 /*
7995 Sort colors by decreasing intensity.
7996 */
7997 qsort((void *) diversity,image->colors,sizeof(*diversity),
7998 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00007999 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008000 {
8001 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008002 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008003 }
8004 diversity[image->colors-1].count<<=4;
8005 qsort((void *) diversity,image->colors,sizeof(*diversity),
8006 PopularityCompare);
8007 /*
8008 Allocate colors.
8009 */
8010 p=colors;
8011 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008012 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008013 {
8014 index=diversity[i].index;
8015 color.red=
8016 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8017 color.green=
8018 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8019 color.blue=
8020 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8021 if (visual_info->klass != PseudoColor)
8022 {
8023 gray_value=(unsigned short) XPixelIntensity(&color);
8024 color.red=gray_value;
8025 color.green=gray_value;
8026 color.blue=gray_value;
8027 }
8028 status=XAllocColor(display,colormap,&color);
8029 if (status == False)
8030 break;
8031 pixel->pixels[index]=color.pixel;
8032 *p++=color;
8033 }
8034 /*
8035 Read X server colormap.
8036 */
8037 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8038 visual_info->colormap_size,sizeof(*server_colors));
8039 if (server_colors == (XColor *) NULL)
8040 ThrowXWindowFatalException(ResourceLimitFatalError,
8041 "UnableToCreateColormap",image->filename);
8042 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008043 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008044 (void) XQueryColors(display,colormap,server_colors,
8045 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8046 /*
8047 Select remaining colors from X server colormap.
8048 */
cristybb503372010-05-27 20:51:26 +00008049 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008050 {
8051 index=diversity[i].index;
cristy534d0a32013-04-13 16:27:24 +00008052 color.red=ScaleQuantumToShort(
8053 XRedGamma(image->colormap[index].red));
8054 color.green=ScaleQuantumToShort(
8055 XGreenGamma(image->colormap[index].green));
8056 color.blue=ScaleQuantumToShort(
8057 XBlueGamma(image->colormap[index].blue));
cristy3ed852e2009-09-05 21:47:34 +00008058 if (visual_info->klass != PseudoColor)
8059 {
8060 gray_value=(unsigned short) XPixelIntensity(&color);
8061 color.red=gray_value;
8062 color.green=gray_value;
8063 color.blue=gray_value;
8064 }
8065 XBestPixel(display,colormap,server_colors,(unsigned int)
8066 visual_info->colormap_size,&color);
8067 pixel->pixels[index]=color.pixel;
8068 *p++=color;
8069 }
8070 if ((int) image->colors < visual_info->colormap_size)
8071 {
8072 /*
8073 Fill up colors array-- more choices for pen colors.
8074 */
8075 retain_colors=MagickMin((unsigned int)
8076 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008077 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008078 *p++=server_colors[i];
8079 number_colors+=retain_colors;
8080 }
8081 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8082 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8083 break;
8084 }
8085 /*
8086 Define Standard colormap for private GrayScale or PseudoColor visual.
8087 */
8088 if (status == False)
8089 {
8090 /*
8091 Not enough colormap entries in the colormap-- Create a new colormap.
8092 */
8093 colormap=XCreateColormap(display,
8094 XRootWindow(display,visual_info->screen),visual_info->visual,
8095 AllocNone);
8096 if (colormap == (Colormap) NULL)
8097 ThrowXWindowFatalException(ResourceLimitFatalError,
8098 "UnableToCreateColormap",image->filename);
8099 map_info->colormap=colormap;
8100 if ((int) image->colors < visual_info->colormap_size)
8101 {
8102 /*
8103 Retain colors from the default colormap to help lessens the
8104 effects of colormap flashing.
8105 */
8106 retain_colors=MagickMin((unsigned int)
8107 (visual_info->colormap_size-image->colors),256);
8108 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008109 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008110 {
cristyc57f6942010-11-12 01:47:39 +00008111 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008112 p++;
8113 }
8114 (void) XQueryColors(display,
8115 XDefaultColormap(display,visual_info->screen),
8116 colors+image->colors,(int) retain_colors);
8117 /*
8118 Transfer colors from default to private colormap.
8119 */
8120 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008121 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008122 retain_colors);
8123 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008124 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008125 {
8126 p->pixel=pixel->pixels[i];
8127 p++;
8128 }
8129 (void) XStoreColors(display,colormap,colors+image->colors,
8130 (int) retain_colors);
8131 number_colors+=retain_colors;
8132 }
8133 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008134 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008135 image->colors);
8136 }
8137 /*
8138 Store the image colormap.
8139 */
8140 p=colors;
8141 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008142 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008143 {
8144 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8145 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8146 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8147 if (visual_info->klass != PseudoColor)
8148 {
8149 gray_value=(unsigned short) XPixelIntensity(&color);
8150 color.red=gray_value;
8151 color.green=gray_value;
8152 color.blue=gray_value;
8153 }
8154 color.pixel=pixel->pixels[i];
8155 *p++=color;
8156 }
8157 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8158 break;
8159 }
8160 case TrueColor:
8161 case DirectColor:
8162 default:
8163 {
8164 MagickBooleanType
8165 linear_colormap;
8166
8167 /*
8168 Define Standard Colormap for TrueColor or DirectColor visual.
8169 */
8170 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8171 (map_info->green_max*map_info->green_mult)+
8172 (map_info->blue_max*map_info->blue_mult)+1);
8173 linear_colormap=(number_colors > 4096) ||
8174 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8175 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8176 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8177 MagickTrue : MagickFalse;
8178 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008179 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008180 /*
8181 Allocate color array.
8182 */
8183 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8184 if (colors == (XColor *) NULL)
8185 ThrowXWindowFatalException(ResourceLimitFatalError,
8186 "UnableToCreateColormap",image->filename);
8187 /*
8188 Initialize linear color ramp.
8189 */
8190 p=colors;
8191 color.flags=(char) (DoRed | DoGreen | DoBlue);
8192 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008193 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008194 {
8195 color.blue=(unsigned short) 0;
8196 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008197 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008198 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8199 color.green=color.blue;
8200 color.red=color.blue;
8201 color.pixel=XStandardPixel(map_info,&color);
8202 *p++=color;
8203 }
8204 else
cristybb503372010-05-27 20:51:26 +00008205 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008206 {
8207 color.red=(unsigned short) 0;
8208 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008209 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008210 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8211 color.green=(unsigned int) 0;
8212 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008213 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008214 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8215 map_info->green_max));
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.pixel=XStandardPixel(map_info,&color);
8221 *p++=color;
8222 }
8223 if ((visual_info->klass == DirectColor) &&
8224 (colormap != XDefaultColormap(display,visual_info->screen)))
8225 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8226 else
cristybb503372010-05-27 20:51:26 +00008227 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008228 (void) XAllocColor(display,colormap,&colors[i]);
8229 break;
8230 }
8231 }
8232 if ((visual_info->klass != DirectColor) &&
8233 (visual_info->klass != TrueColor))
8234 {
8235 /*
8236 Set foreground, background, border, etc. pixels.
8237 */
8238 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8239 &pixel->foreground_color);
8240 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8241 &pixel->background_color);
8242 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8243 {
8244 /*
8245 Foreground and background colors must differ.
8246 */
8247 pixel->background_color.red=(~pixel->foreground_color.red);
8248 pixel->background_color.green=
8249 (~pixel->foreground_color.green);
8250 pixel->background_color.blue=
8251 (~pixel->foreground_color.blue);
8252 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8253 &pixel->background_color);
8254 }
8255 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8256 &pixel->border_color);
8257 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8258 &pixel->matte_color);
8259 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8260 &pixel->highlight_color);
8261 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8262 &pixel->shadow_color);
8263 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8264 &pixel->depth_color);
8265 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8266 &pixel->trough_color);
8267 for (i=0; i < MaxNumberPens; i++)
8268 {
8269 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8270 &pixel->pen_colors[i]);
8271 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8272 }
cristyc57f6942010-11-12 01:47:39 +00008273 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008274 }
8275 colors=(XColor *) RelinquishMagickMemory(colors);
8276 if (IsEventLogging())
8277 {
8278 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8279 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8280 map_info->colormap);
8281 (void) LogMagickEvent(X11Event,GetMagickModule(),
8282 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8283 map_info->green_max,map_info->blue_max);
8284 (void) LogMagickEvent(X11Event,GetMagickModule(),
8285 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8286 map_info->green_mult,map_info->blue_mult);
8287 }
8288}
8289
8290/*
8291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8292% %
8293% %
8294% %
8295% X M a k e W i n d o w %
8296% %
8297% %
8298% %
8299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8300%
8301% XMakeWindow() creates an X11 window.
8302%
8303% The format of the XMakeWindow method is:
8304%
8305% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8306% XClassHint *class_hint,XWMHints *manager_hints,
8307% XWindowInfo *window_info)
8308%
8309% A description of each parameter follows:
8310%
8311% o display: Specifies a connection to an X server; returned from
8312% XOpenDisplay.
8313%
8314% o parent: Specifies the parent window_info.
8315%
8316% o argv: Specifies the application's argument list.
8317%
8318% o argc: Specifies the number of arguments.
8319%
8320% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8321%
8322% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8323%
8324% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8325%
8326*/
cristybcbda3f2011-09-03 13:01:22 +00008327MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008328 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8329 XWindowInfo *window_info)
8330{
8331#define MinWindowSize 64
8332
8333 Atom
8334 atom_list[2];
8335
8336 int
8337 gravity;
8338
8339 static XTextProperty
8340 icon_name,
8341 window_name;
8342
8343 Status
8344 status;
8345
8346 XSizeHints
8347 *size_hints;
8348
8349 /*
8350 Set window info hints.
8351 */
8352 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8353 assert(display != (Display *) NULL);
8354 assert(window_info != (XWindowInfo *) NULL);
8355 size_hints=XAllocSizeHints();
8356 if (size_hints == (XSizeHints *) NULL)
8357 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008358 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008359 size_hints->x=window_info->x;
8360 size_hints->y=window_info->y;
8361 size_hints->width=(int) window_info->width;
8362 size_hints->height=(int) window_info->height;
8363 if (window_info->immutable != MagickFalse)
8364 {
8365 /*
8366 Window size cannot be changed.
8367 */
8368 size_hints->min_width=size_hints->width;
8369 size_hints->min_height=size_hints->height;
8370 size_hints->max_width=size_hints->width;
8371 size_hints->max_height=size_hints->height;
8372 size_hints->flags|=PMinSize;
8373 size_hints->flags|=PMaxSize;
8374 }
8375 else
8376 {
8377 /*
8378 Window size can be changed.
8379 */
8380 size_hints->min_width=(int) window_info->min_width;
8381 size_hints->min_height=(int) window_info->min_height;
8382 size_hints->flags|=PResizeInc;
8383 size_hints->width_inc=(int) window_info->width_inc;
8384 size_hints->height_inc=(int) window_info->height_inc;
8385#if !defined(PRE_R4_ICCCM)
8386 size_hints->flags|=PBaseSize;
8387 size_hints->base_width=size_hints->width_inc;
8388 size_hints->base_height=size_hints->height_inc;
8389#endif
8390 }
8391 gravity=NorthWestGravity;
8392 if (window_info->geometry != (char *) NULL)
8393 {
8394 char
8395 default_geometry[MaxTextExtent],
8396 geometry[MaxTextExtent];
8397
8398 int
8399 flags;
8400
8401 register char
8402 *p;
8403
8404 /*
8405 User specified geometry.
8406 */
cristyb51dff52011-05-19 16:55:47 +00008407 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008408 size_hints->width,size_hints->height);
8409 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8410 p=geometry;
8411 while (strlen(p) != 0)
8412 {
8413 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8414 p++;
8415 else
8416 (void) CopyMagickString(p,p+1,MaxTextExtent);
8417 }
8418 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8419 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8420 &size_hints->width,&size_hints->height,&gravity);
8421 if ((flags & WidthValue) && (flags & HeightValue))
8422 size_hints->flags|=USSize;
8423 if ((flags & XValue) && (flags & YValue))
8424 {
8425 size_hints->flags|=USPosition;
8426 window_info->x=size_hints->x;
8427 window_info->y=size_hints->y;
8428 }
8429 }
8430#if !defined(PRE_R4_ICCCM)
8431 size_hints->win_gravity=gravity;
8432 size_hints->flags|=PWinGravity;
8433#endif
8434 if (window_info->id == (Window) NULL)
8435 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8436 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8437 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008438 window_info->visual,(unsigned long) window_info->mask,
8439 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008440 else
8441 {
8442 MagickStatusType
8443 mask;
8444
8445 XEvent
8446 sans_event;
8447
8448 XWindowChanges
8449 window_changes;
8450
8451 /*
8452 Window already exists; change relevant attributes.
8453 */
cristyc57f6942010-11-12 01:47:39 +00008454 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8455 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008456 mask=ConfigureNotify;
8457 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8458 window_changes.x=window_info->x;
8459 window_changes.y=window_info->y;
8460 window_changes.width=(int) window_info->width;
8461 window_changes.height=(int) window_info->height;
8462 mask=(MagickStatusType) (CWWidth | CWHeight);
8463 if (window_info->flags & USPosition)
8464 mask|=CWX | CWY;
8465 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8466 mask,&window_changes);
8467 }
8468 if (window_info->id == (Window) NULL)
8469 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8470 window_info->name);
8471 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8472 if (status == False)
8473 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8474 window_info->name);
8475 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8476 if (status == False)
8477 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8478 window_info->icon_name);
8479 if (window_info->icon_geometry != (char *) NULL)
8480 {
8481 int
8482 flags,
8483 height,
8484 width;
8485
8486 /*
8487 User specified icon geometry.
8488 */
8489 size_hints->flags|=USPosition;
8490 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8491 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8492 &manager_hints->icon_y,&width,&height,&gravity);
8493 if ((flags & XValue) && (flags & YValue))
8494 manager_hints->flags|=IconPositionHint;
8495 }
8496 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8497 size_hints,manager_hints,class_hint);
8498 if (window_name.value != (void *) NULL)
8499 {
8500 (void) XFree((void *) window_name.value);
8501 window_name.value=(unsigned char *) NULL;
8502 window_name.nitems=0;
8503 }
8504 if (icon_name.value != (void *) NULL)
8505 {
8506 (void) XFree((void *) icon_name.value);
8507 icon_name.value=(unsigned char *) NULL;
8508 icon_name.nitems=0;
8509 }
8510 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8511 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8512 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8513 (void) XFree((void *) size_hints);
8514 if (window_info->shape != MagickFalse)
8515 {
8516#if defined(MAGICKCORE_HAVE_SHAPE)
8517 int
8518 error_base,
8519 event_base;
8520
8521 /*
8522 Can we apply a non-rectangular shaping mask?
8523 */
8524 error_base=0;
8525 event_base=0;
8526 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8527 window_info->shape=MagickFalse;
8528#else
8529 window_info->shape=MagickFalse;
8530#endif
8531 }
8532 if (window_info->shared_memory)
8533 {
8534#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8535 /*
8536 Can we use shared memory with this window?
8537 */
8538 if (XShmQueryExtension(display) == 0)
8539 window_info->shared_memory=MagickFalse;
8540#else
8541 window_info->shared_memory=MagickFalse;
8542#endif
8543 }
8544 window_info->image=NewImageList();
8545 window_info->destroy=MagickFalse;
8546}
8547
8548/*
8549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8550% %
8551% %
8552% %
8553% X M a g i c k P r o g r e s s M o n i t o r %
8554% %
8555% %
8556% %
8557%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8558%
8559% XMagickProgressMonitor() displays the progress a task is making in
8560% completing a task.
8561%
8562% The format of the XMagickProgressMonitor method is:
8563%
8564% void XMagickProgressMonitor(const char *task,
8565% const MagickOffsetType quantum,const MagickSizeType span,
8566% void *client_data)
8567%
8568% A description of each parameter follows:
8569%
8570% o task: Identifies the task in progress.
8571%
8572% o quantum: Specifies the quantum position within the span which represents
8573% how much progress has been made in completing a task.
8574%
8575% o span: Specifies the span relative to completing a task.
8576%
8577% o client_data: Pointer to any client data.
8578%
8579*/
8580
8581static const char *GetLocaleMonitorMessage(const char *text)
8582{
8583 char
8584 message[MaxTextExtent],
8585 tag[MaxTextExtent];
8586
8587 const char
8588 *locale_message;
8589
8590 register char
8591 *p;
8592
8593 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8594 p=strrchr(tag,'/');
8595 if (p != (char *) NULL)
8596 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008597 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008598 locale_message=GetLocaleMessage(message);
8599 if (locale_message == message)
8600 return(text);
8601 return(locale_message);
8602}
8603
cristybcbda3f2011-09-03 13:01:22 +00008604MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008605 const MagickOffsetType quantum,const MagickSizeType span,
8606 void *magick_unused(client_data))
8607{
8608 XWindows
8609 *windows;
8610
8611 windows=XSetWindows((XWindows *) ~0);
8612 if (windows == (XWindows *) NULL)
8613 return(MagickTrue);
8614 if (windows->info.mapped != MagickFalse)
8615 XProgressMonitorWidget(windows->display,windows,
8616 GetLocaleMonitorMessage(tag),quantum,span);
8617 return(MagickTrue);
8618}
8619
8620/*
8621%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8622% %
8623% %
8624% %
8625% X Q u e r y C o l o r D a t a b a s e %
8626% %
8627% %
8628% %
8629%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8630%
cristy9950d572011-10-01 18:22:35 +00008631% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008632% string.
8633%
8634% The format of the XQueryColorDatabase method is:
8635%
cristy9950d572011-10-01 18:22:35 +00008636% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008637%
8638% A description of each parameter follows:
8639%
8640% o target: Specifies the color to lookup in the X color database.
8641%
cristy101ab702011-10-13 13:06:32 +00008642% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008643% color is returned as this value.
8644%
8645*/
cristy9950d572011-10-01 18:22:35 +00008646MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008647 XColor *color)
8648{
8649 Colormap
8650 colormap;
8651
8652 static Display
8653 *display = (Display *) NULL;
8654
8655 Status
8656 status;
8657
8658 XColor
8659 xcolor;
8660
8661 /*
8662 Initialize color return value.
8663 */
8664 assert(color != (XColor *) NULL);
8665 color->red=0;
8666 color->green=0;
8667 color->blue=0;
8668 color->flags=(char) (DoRed | DoGreen | DoBlue);
8669 if ((target == (char *) NULL) || (*target == '\0'))
8670 target="#ffffffffffff";
8671 /*
8672 Let the X server define the color for us.
8673 */
8674 if (display == (Display *) NULL)
8675 display=XOpenDisplay((char *) NULL);
8676 if (display == (Display *) NULL)
8677 {
cristyc38fbf52013-11-03 13:55:54 +00008678 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target);
cristy3ed852e2009-09-05 21:47:34 +00008679 return(MagickFalse);
8680 }
8681 colormap=XDefaultColormap(display,XDefaultScreen(display));
8682 status=XParseColor(display,colormap,(char *) target,&xcolor);
8683 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00008684 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target)
cristy3ed852e2009-09-05 21:47:34 +00008685 else
8686 {
8687 color->red=xcolor.red;
8688 color->green=xcolor.green;
8689 color->blue=xcolor.blue;
8690 color->flags=xcolor.flags;
8691 }
8692 return(status != False ? MagickTrue : MagickFalse);
8693}
8694
8695/*
8696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8697% %
8698% %
8699% %
8700% X Q u e r y P o s i t i o n %
8701% %
8702% %
8703% %
8704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8705%
8706% XQueryPosition() gets the pointer coordinates relative to a window.
8707%
8708% The format of the XQueryPosition method is:
8709%
8710% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8711%
8712% A description of each parameter follows:
8713%
8714% o display: Specifies a connection to an X server; returned from
8715% XOpenDisplay.
8716%
8717% o window: Specifies a pointer to a Window.
8718%
8719% o x: Return the x coordinate of the pointer relative to the origin of the
8720% window.
8721%
8722% o y: Return the y coordinate of the pointer relative to the origin of the
8723% window.
8724%
8725*/
cristy534d0a32013-04-13 16:27:24 +00008726MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,
8727 int *y)
cristy3ed852e2009-09-05 21:47:34 +00008728{
8729 int
8730 x_root,
8731 y_root;
8732
8733 unsigned int
8734 mask;
8735
8736 Window
8737 root_window;
8738
8739 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8740 assert(display != (Display *) NULL);
8741 assert(window != (Window) NULL);
8742 assert(x != (int *) NULL);
8743 assert(y != (int *) NULL);
8744 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8745 x,y,&mask);
8746}
8747
8748/*
8749%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8750% %
8751% %
8752% %
8753% X R e f r e s h W i n d o w %
8754% %
8755% %
8756% %
8757%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8758%
8759% XRefreshWindow() refreshes an image in a X window.
8760%
8761% The format of the XRefreshWindow method is:
8762%
8763% void XRefreshWindow(Display *display,const XWindowInfo *window,
8764% const XEvent *event)
8765%
8766% A description of each parameter follows:
8767%
8768% o display: Specifies a connection to an X server; returned from
8769% XOpenDisplay.
8770%
8771% o window: Specifies a pointer to a XWindowInfo structure.
8772%
8773% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8774% the entire image is refreshed.
8775%
8776*/
cristybcbda3f2011-09-03 13:01:22 +00008777MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008778 const XEvent *event)
8779{
8780 int
8781 x,
8782 y;
8783
8784 unsigned int
8785 height,
8786 width;
8787
8788 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8789 assert(display != (Display *) NULL);
8790 assert(window != (XWindowInfo *) NULL);
8791 if (window->ximage == (XImage *) NULL)
8792 return;
8793 if (event != (XEvent *) NULL)
8794 {
8795 /*
8796 Determine geometry from expose event.
8797 */
8798 x=event->xexpose.x;
8799 y=event->xexpose.y;
8800 width=(unsigned int) event->xexpose.width;
8801 height=(unsigned int) event->xexpose.height;
8802 }
8803 else
8804 {
8805 XEvent
8806 sans_event;
8807
8808 /*
8809 Refresh entire window; discard outstanding expose events.
8810 */
8811 x=0;
8812 y=0;
8813 width=window->width;
8814 height=window->height;
8815 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008816 if (window->matte_pixmap != (Pixmap) NULL)
8817 {
8818#if defined(MAGICKCORE_HAVE_SHAPE)
8819 if (window->shape != MagickFalse)
8820 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8821 window->matte_pixmap,ShapeSet);
8822#endif
8823 }
cristy3ed852e2009-09-05 21:47:34 +00008824 }
8825 /*
8826 Check boundary conditions.
8827 */
8828 if ((window->ximage->width-(x+window->x)) < (int) width)
8829 width=(unsigned int) (window->ximage->width-(x+window->x));
8830 if ((window->ximage->height-(y+window->y)) < (int) height)
8831 height=(unsigned int) (window->ximage->height-(y+window->y));
8832 /*
8833 Refresh image.
8834 */
8835 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008836 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008837 if (window->pixmap != (Pixmap) NULL)
8838 {
8839 if (window->depth > 1)
8840 (void) XCopyArea(display,window->pixmap,window->id,
8841 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8842 else
8843 (void) XCopyPlane(display,window->pixmap,window->id,
8844 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8845 1L);
8846 }
8847 else
8848 {
8849#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8850 if (window->shared_memory)
8851 (void) XShmPutImage(display,window->id,window->annotate_context,
8852 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8853#endif
8854 if (window->shared_memory == MagickFalse)
8855 (void) XPutImage(display,window->id,window->annotate_context,
8856 window->ximage,x+window->x,y+window->y,x,y,width,height);
8857 }
8858 if (window->matte_pixmap != (Pixmap) NULL)
8859 (void) XSetClipMask(display,window->annotate_context,None);
8860 (void) XFlush(display);
8861}
8862
8863/*
8864%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8865% %
8866% %
8867% %
8868% X R e m o t e C o m m a n d %
8869% %
8870% %
8871% %
8872%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8873%
8874% XRemoteCommand() forces a remote display(1) to display the specified
8875% image filename.
8876%
8877% The format of the XRemoteCommand method is:
8878%
8879% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8880% const char *filename)
8881%
8882% A description of each parameter follows:
8883%
8884% o display: Specifies a connection to an X server; returned from
8885% XOpenDisplay.
8886%
8887% o window: Specifies the name or id of an X window.
8888%
8889% o filename: the name of the image filename to display.
8890%
8891*/
8892MagickExport MagickBooleanType XRemoteCommand(Display *display,
8893 const char *window,const char *filename)
8894{
8895 Atom
8896 remote_atom;
8897
8898 Window
8899 remote_window,
8900 root_window;
8901
8902 assert(filename != (char *) NULL);
8903 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8904 if (display == (Display *) NULL)
8905 display=XOpenDisplay((char *) NULL);
8906 if (display == (Display *) NULL)
8907 {
8908 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8909 return(MagickFalse);
8910 }
8911 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8912 remote_window=(Window) NULL;
8913 root_window=XRootWindow(display,XDefaultScreen(display));
8914 if (window != (char *) NULL)
8915 {
8916 /*
8917 Search window hierarchy and identify any clients by name or ID.
8918 */
cristy02e64f82013-11-14 16:20:04 +00008919 if (isdigit((int) ((unsigned char) *window)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00008920 remote_window=XWindowByID(display,root_window,(Window)
8921 strtol((char *) window,(char **) NULL,0));
8922 if (remote_window == (Window) NULL)
8923 remote_window=XWindowByName(display,root_window,window);
8924 }
8925 if (remote_window == (Window) NULL)
8926 remote_window=XWindowByProperty(display,root_window,remote_atom);
8927 if (remote_window == (Window) NULL)
8928 {
8929 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8930 filename);
8931 return(MagickFalse);
8932 }
8933 /*
8934 Send remote command.
8935 */
8936 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8937 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8938 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8939 (void) XSync(display,MagickFalse);
8940 return(MagickTrue);
8941}
8942
8943/*
8944%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8945% %
8946% %
8947% %
cristy534d0a32013-04-13 16:27:24 +00008948% X R e n d e r I m a g e %
8949% %
8950% %
8951% %
8952%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8953%
8954% XRenderImage() renders text on the image with an X11 font. It also returns
8955% the bounding box of the text relative to the image.
8956%
8957% The format of the XRenderImage method is:
8958%
8959% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
8960% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
8961%
8962% A description of each parameter follows:
8963%
8964% o image: the image.
8965%
8966% o draw_info: the draw info.
8967%
8968% o offset: (x,y) location of text relative to image.
8969%
8970% o metrics: bounding box of text.
8971%
8972% o exception: return any errors or warnings in this structure.
8973%
8974*/
8975MagickPrivate MagickBooleanType XRenderImage(Image *image,
8976 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
8977 ExceptionInfo *exception)
8978{
8979 const char
8980 *client_name;
8981
8982 DrawInfo
8983 cache_info;
8984
8985 Display
8986 *display;
8987
8988 ImageInfo
8989 *image_info;
8990
8991 MagickBooleanType
8992 status;
8993
8994 size_t
8995 height,
8996 width;
8997
8998 XAnnotateInfo
8999 annotate_info;
9000
9001 XFontStruct
9002 *font_info;
9003
9004 XPixelInfo
9005 pixel;
9006
9007 XResourceInfo
9008 resource_info;
9009
9010 XrmDatabase
9011 resource_database;
9012
9013 XStandardColormap
9014 *map_info;
9015
9016 XVisualInfo
9017 *visual_info;
9018
9019 /*
9020 Open X server connection.
9021 */
9022 display=XOpenDisplay(draw_info->server_name);
9023 if (display == (Display *) NULL)
9024 {
9025 ThrowXWindowException(XServerError,"UnableToOpenXServer",
9026 draw_info->server_name);
9027 return(MagickFalse);
9028 }
9029 /*
9030 Get user defaults from X resource database.
9031 */
9032 (void) XSetErrorHandler(XError);
9033 image_info=AcquireImageInfo();
9034 client_name=GetClientName();
9035 resource_database=XGetResourceDatabase(display,client_name);
9036 XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
9037 resource_info.close_server=MagickFalse;
9038 resource_info.colormap=PrivateColormap;
9039 resource_info.font=AcquireString(draw_info->font);
9040 resource_info.background_color=AcquireString("#ffffffffffff");
9041 resource_info.foreground_color=AcquireString("#000000000000");
9042 map_info=XAllocStandardColormap();
cristy5da5d1e2014-05-24 23:37:48 +00009043 visual_info=(XVisualInfo *) NULL;
9044 font_info=(XFontStruct *) NULL;
9045 pixel.pixels=(unsigned long *) NULL;
cristy534d0a32013-04-13 16:27:24 +00009046 if (map_info == (XStandardColormap *) NULL)
9047 {
9048 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9049 image->filename);
9050 return(MagickFalse);
9051 }
9052 /*
9053 Initialize visual info.
9054 */
9055 visual_info=XBestVisualInfo(display,map_info,&resource_info);
9056 if (visual_info == (XVisualInfo *) NULL)
9057 {
cristy5da5d1e2014-05-24 23:37:48 +00009058 XFreeResources(display,visual_info,map_info,&pixel,font_info,
9059 &resource_info,(XWindowInfo *) NULL);
cristyc38fbf52013-11-03 13:55:54 +00009060 ThrowXWindowException(XServerError,"UnableToGetVisual",image->filename);
cristy534d0a32013-04-13 16:27:24 +00009061 return(MagickFalse);
9062 }
9063 map_info->colormap=(Colormap) NULL;
cristy534d0a32013-04-13 16:27:24 +00009064 /*
9065 Initialize Standard Colormap info.
9066 */
9067 XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
9068 map_info);
9069 XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
9070 &pixel);
9071 pixel.annotate_context=XDefaultGC(display,visual_info->screen);
9072 /*
9073 Initialize font info.
9074 */
9075 font_info=XBestFont(display,&resource_info,MagickFalse);
9076 if (font_info == (XFontStruct *) NULL)
9077 {
cristy534d0a32013-04-13 16:27:24 +00009078 XFreeResources(display,visual_info,map_info,&pixel,font_info,
9079 &resource_info,(XWindowInfo *) NULL);
cristy5da5d1e2014-05-24 23:37:48 +00009080 ThrowXWindowException(XServerError,"UnableToLoadFont",draw_info->font);
cristy534d0a32013-04-13 16:27:24 +00009081 return(MagickFalse);
9082 }
9083 cache_info=(*draw_info);
9084 /*
9085 Initialize annotate info.
9086 */
9087 XGetAnnotateInfo(&annotate_info);
9088 annotate_info.stencil=ForegroundStencil;
9089 if (cache_info.font != draw_info->font)
9090 {
9091 /*
9092 Type name has changed.
9093 */
9094 (void) XFreeFont(display,font_info);
9095 (void) CloneString(&resource_info.font,draw_info->font);
9096 font_info=XBestFont(display,&resource_info,MagickFalse);
9097 if (font_info == (XFontStruct *) NULL)
9098 {
9099 ThrowXWindowException(XServerError,"UnableToLoadFont",
9100 draw_info->font);
9101 return(MagickFalse);
9102 }
9103 }
9104 if (image->debug != MagickFalse)
9105 (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
9106 "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
9107 draw_info->font : "none",draw_info->pointsize);
9108 cache_info=(*draw_info);
9109 annotate_info.font_info=font_info;
9110 annotate_info.text=(char *) draw_info->text;
9111 annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
9112 strlen(draw_info->text));
9113 annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
9114 metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
9115 metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
9116 metrics->ascent=(double) font_info->ascent+4;
9117 metrics->descent=(double) (-font_info->descent);
9118 metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
9119 metrics->height=font_info->ascent+font_info->descent;
9120 metrics->max_advance=(double) font_info->max_bounds.width;
9121 metrics->bounds.x1=0.0;
9122 metrics->bounds.y1=metrics->descent;
9123 metrics->bounds.x2=metrics->ascent+metrics->descent;
9124 metrics->bounds.y2=metrics->ascent+metrics->descent;
9125 metrics->underline_position=(-2.0);
9126 metrics->underline_thickness=1.0;
9127 if (draw_info->render == MagickFalse)
9128 return(MagickTrue);
9129 if (draw_info->fill.alpha == TransparentAlpha)
9130 return(MagickTrue);
9131 /*
9132 Render fill color.
9133 */
9134 width=annotate_info.width;
9135 height=annotate_info.height;
9136 if ((fabs(draw_info->affine.rx) >= MagickEpsilon) ||
9137 (fabs(draw_info->affine.ry) >= MagickEpsilon))
9138 {
9139 if ((fabs(draw_info->affine.sx-draw_info->affine.sy) < MagickEpsilon) &&
9140 (fabs(draw_info->affine.rx+draw_info->affine.ry) < MagickEpsilon))
9141 annotate_info.degrees=(double) (180.0/MagickPI)*
9142 atan2(draw_info->affine.rx,draw_info->affine.sx);
9143 }
9144 (void) FormatLocaleString(annotate_info.geometry,MaxTextExtent,
9145 "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
9146 ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
9147 draw_info->interline_spacing-0.5));
9148 pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
9149 pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
9150 pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);
9151 status=XAnnotateImage(display,&pixel,&annotate_info,image,exception);
9152 if (status == 0)
9153 {
9154 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9155 image->filename);
9156 return(MagickFalse);
9157 }
9158 return(MagickTrue);
9159}
9160
9161/*
9162%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9163% %
9164% %
9165% %
cristy3ed852e2009-09-05 21:47:34 +00009166% X R e t a i n W i n d o w C o l o r s %
9167% %
9168% %
9169% %
9170%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9171%
9172% XRetainWindowColors() sets X11 color resources on a window. This preserves
9173% the colors associated with an image displayed on the window.
9174%
9175% The format of the XRetainWindowColors method is:
9176%
9177% void XRetainWindowColors(Display *display,const Window window)
9178%
9179% A description of each parameter follows:
9180%
9181% o display: Specifies a connection to an X server; returned from
9182% XOpenDisplay.
9183%
9184% o window: Specifies a pointer to a XWindowInfo structure.
9185%
9186*/
9187MagickExport void XRetainWindowColors(Display *display,const Window window)
9188{
9189 Atom
9190 property;
9191
9192 Pixmap
9193 pixmap;
9194
9195 /*
9196 Put property on the window.
9197 */
9198 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9199 assert(display != (Display *) NULL);
9200 assert(window != (Window) NULL);
9201 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9202 if (property == (Atom) NULL)
9203 {
cristyc38fbf52013-11-03 13:55:54 +00009204 ThrowXWindowException(XServerError,"UnableToCreateProperty",
cristy3ed852e2009-09-05 21:47:34 +00009205 "_XSETROOT_ID");
9206 return;
9207 }
9208 pixmap=XCreatePixmap(display,window,1,1,1);
9209 if (pixmap == (Pixmap) NULL)
9210 {
cristyc38fbf52013-11-03 13:55:54 +00009211 ThrowXWindowException(XServerError,"UnableToCreateBitmap","");
cristy3ed852e2009-09-05 21:47:34 +00009212 return;
9213 }
9214 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9215 (unsigned char *) &pixmap,1);
9216 (void) XSetCloseDownMode(display,RetainPermanent);
9217}
9218
9219/*
9220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9221% %
9222% %
9223% %
9224% X S e l e c t W i n d o w %
9225% %
9226% %
9227% %
9228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9229%
9230% XSelectWindow() allows a user to select a window using the mouse. If the
9231% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9232% is returned in the crop_info structure.
9233%
9234% The format of the XSelectWindow function is:
9235%
9236% target_window=XSelectWindow(display,crop_info)
9237%
9238% A description of each parameter follows:
9239%
9240% o window: XSelectWindow returns the window id.
9241%
9242% o display: Specifies a pointer to the Display structure; returned from
9243% XOpenDisplay.
9244%
9245% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9246% contains the extents of any cropping rectangle.
9247%
cristy3ed852e2009-09-05 21:47:34 +00009248*/
9249static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9250{
9251#define MinimumCropArea (unsigned int) 9
9252
9253 Cursor
9254 target_cursor;
9255
9256 GC
9257 annotate_context;
9258
9259 int
9260 presses,
9261 x_offset,
9262 y_offset;
9263
9264 Status
9265 status;
9266
9267 Window
9268 root_window,
9269 target_window;
9270
9271 XEvent
9272 event;
9273
9274 XGCValues
9275 context_values;
9276
9277 /*
9278 Initialize graphic context.
9279 */
9280 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9281 assert(display != (Display *) NULL);
9282 assert(crop_info != (RectangleInfo *) NULL);
9283 root_window=XRootWindow(display,XDefaultScreen(display));
9284 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9285 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9286 context_values.function=GXinvert;
9287 context_values.plane_mask=
9288 context_values.background ^ context_values.foreground;
9289 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009290 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009291 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9292 if (annotate_context == (GC) NULL)
9293 return(MagickFalse);
9294 /*
9295 Grab the pointer using target cursor.
9296 */
9297 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9298 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9299 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9300 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9301 GrabModeAsync,root_window,target_cursor,CurrentTime);
9302 if (status != GrabSuccess)
9303 {
cristyc38fbf52013-11-03 13:55:54 +00009304 ThrowXWindowException(XServerError,"UnableToGrabMouse","");
cristy3ed852e2009-09-05 21:47:34 +00009305 return((Window) NULL);
9306 }
9307 /*
9308 Select a window.
9309 */
9310 crop_info->width=0;
9311 crop_info->height=0;
9312 presses=0;
9313 target_window=(Window) NULL;
9314 x_offset=0;
9315 y_offset=0;
9316 do
9317 {
9318 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9319 (void) XDrawRectangle(display,root_window,annotate_context,
9320 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9321 (unsigned int) crop_info->height-1);
9322 /*
9323 Allow another event.
9324 */
9325 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9326 (void) XWindowEvent(display,root_window,ButtonPressMask |
9327 ButtonReleaseMask | ButtonMotionMask,&event);
9328 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9329 (void) XDrawRectangle(display,root_window,annotate_context,
9330 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9331 (unsigned int) crop_info->height-1);
9332 switch (event.type)
9333 {
9334 case ButtonPress:
9335 {
9336 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9337 event.xbutton.x,event.xbutton.y);
9338 if (target_window == (Window) NULL)
9339 target_window=root_window;
9340 x_offset=event.xbutton.x_root;
9341 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009342 crop_info->x=(ssize_t) x_offset;
9343 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009344 crop_info->width=0;
9345 crop_info->height=0;
9346 presses++;
9347 break;
9348 }
9349 case ButtonRelease:
9350 {
9351 presses--;
9352 break;
9353 }
9354 case MotionNotify:
9355 {
9356 /*
9357 Discard pending button motion events.
9358 */
9359 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009360 crop_info->x=(ssize_t) event.xmotion.x;
9361 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009362 /*
9363 Check boundary conditions.
9364 */
9365 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009366 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009367 else
9368 {
cristyecd0ab52010-05-30 14:59:20 +00009369 crop_info->width=(size_t) (crop_info->x-x_offset);
9370 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009371 }
9372 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009373 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009374 else
9375 {
cristyecd0ab52010-05-30 14:59:20 +00009376 crop_info->height=(size_t) (crop_info->y-y_offset);
9377 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009378 }
9379 }
9380 default:
9381 break;
9382 }
9383 } while ((target_window == (Window) NULL) || (presses > 0));
9384 (void) XUngrabPointer(display,CurrentTime);
9385 (void) XFreeCursor(display,target_cursor);
9386 (void) XFreeGC(display,annotate_context);
9387 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9388 {
9389 crop_info->width=0;
9390 crop_info->height=0;
9391 }
9392 if ((crop_info->width != 0) && (crop_info->height != 0))
9393 target_window=root_window;
9394 return(target_window);
9395}
9396
9397/*
9398%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9399% %
9400% %
9401% %
9402% X S e t C u r s o r S t a t e %
9403% %
9404% %
9405% %
9406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9407%
9408% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9409% reset to their default.
9410%
9411% The format of the XXSetCursorState method is:
9412%
9413% XSetCursorState(display,windows,const MagickStatusType state)
9414%
9415% A description of each parameter follows:
9416%
9417% o display: Specifies a connection to an X server; returned from
9418% XOpenDisplay.
9419%
9420% o windows: Specifies a pointer to a XWindows structure.
9421%
9422% o state: An unsigned integer greater than 0 sets the cursor state
9423% to busy, otherwise the cursor are reset to their default.
9424%
9425*/
cristybcbda3f2011-09-03 13:01:22 +00009426MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009427 const MagickStatusType state)
9428{
9429 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9430 assert(display != (Display *) NULL);
9431 assert(windows != (XWindows *) NULL);
9432 if (state)
9433 {
9434 (void) XCheckDefineCursor(display,windows->image.id,
9435 windows->image.busy_cursor);
9436 (void) XCheckDefineCursor(display,windows->pan.id,
9437 windows->pan.busy_cursor);
9438 (void) XCheckDefineCursor(display,windows->magnify.id,
9439 windows->magnify.busy_cursor);
9440 (void) XCheckDefineCursor(display,windows->command.id,
9441 windows->command.busy_cursor);
9442 }
9443 else
9444 {
9445 (void) XCheckDefineCursor(display,windows->image.id,
9446 windows->image.cursor);
9447 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9448 (void) XCheckDefineCursor(display,windows->magnify.id,
9449 windows->magnify.cursor);
9450 (void) XCheckDefineCursor(display,windows->command.id,
9451 windows->command.cursor);
9452 (void) XCheckDefineCursor(display,windows->command.id,
9453 windows->widget.cursor);
9454 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9455 }
9456 windows->info.mapped=MagickFalse;
9457}
9458
9459/*
9460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9461% %
9462% %
9463% %
9464% X S e t W i n d o w s %
9465% %
9466% %
9467% %
9468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9469%
9470% XSetWindows() sets the X windows structure if the windows info is specified.
9471% Otherwise the current windows structure is returned.
9472%
9473% The format of the XSetWindows method is:
9474%
9475% XWindows *XSetWindows(XWindows *windows_info)
9476%
9477% A description of each parameter follows:
9478%
9479% o windows_info: Initialize the Windows structure with this information.
9480%
9481*/
cristybcbda3f2011-09-03 13:01:22 +00009482MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009483{
9484 static XWindows
9485 *windows = (XWindows *) NULL;
9486
9487 if (windows_info != (XWindows *) ~0)
9488 {
9489 windows=(XWindows *) RelinquishMagickMemory(windows);
9490 windows=windows_info;
9491 }
9492 return(windows);
9493}
9494/*
9495%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9496% %
9497% %
9498% %
9499% X U s e r P r e f e r e n c e s %
9500% %
9501% %
9502% %
9503%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9504%
9505% XUserPreferences() saves the preferences in a configuration file in the
9506% users' home directory.
9507%
9508% The format of the XUserPreferences method is:
9509%
9510% void XUserPreferences(XResourceInfo *resource_info)
9511%
9512% A description of each parameter follows:
9513%
9514% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9515%
9516*/
cristybcbda3f2011-09-03 13:01:22 +00009517MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009518{
9519#if defined(X11_PREFERENCES_PATH)
9520 char
9521 cache[MaxTextExtent],
9522 filename[MaxTextExtent],
9523 specifier[MaxTextExtent];
9524
9525 const char
cristy104cea82009-10-25 02:26:51 +00009526 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009527 *value;
9528
9529 XrmDatabase
9530 preferences_database;
9531
9532 /*
9533 Save user preferences to the client configuration file.
9534 */
9535 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009536 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009537 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009538 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009539 value=resource_info->backdrop ? "True" : "False";
9540 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009541 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009542 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9543 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009544 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009545 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009546 value=resource_info->confirm_exit ? "True" : "False";
9547 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009548 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009549 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009550 value=resource_info->confirm_edit ? "True" : "False";
9551 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009552 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009553 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009554 value=resource_info->display_warnings ? "True" : "False";
9555 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009556 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristycbda6112012-05-27 20:57:16 +00009557 value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9558 "True" : "False";
cristy3ed852e2009-09-05 21:47:34 +00009559 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009560 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009561 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009562 value=resource_info->gamma_correct ? "True" : "False";
9563 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009564 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9565 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009566 resource_info->undo_cache);
9567 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009568 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009569 value=resource_info->use_pixmap ? "True" : "False";
9570 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009571 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009572 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009573 ExpandFilename(filename);
9574 XrmPutFileDatabase(preferences_database,filename);
9575#endif
9576}
9577
9578/*
9579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9580% %
9581% %
9582% %
9583% X V i s u a l C l a s s N a m e %
9584% %
9585% %
9586% %
9587%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9588%
9589% XVisualClassName() returns the visual class name as a character string.
9590%
9591% The format of the XVisualClassName method is:
9592%
9593% char *XVisualClassName(const int visual_class)
9594%
9595% A description of each parameter follows:
9596%
9597% o visual_type: XVisualClassName returns the visual class as a character
9598% string.
9599%
9600% o class: Specifies the visual class.
9601%
cristy3ed852e2009-09-05 21:47:34 +00009602*/
9603static const char *XVisualClassName(const int visual_class)
9604{
9605 switch (visual_class)
9606 {
9607 case StaticGray: return("StaticGray");
9608 case GrayScale: return("GrayScale");
9609 case StaticColor: return("StaticColor");
9610 case PseudoColor: return("PseudoColor");
9611 case TrueColor: return("TrueColor");
9612 case DirectColor: return("DirectColor");
9613 }
9614 return("unknown visual class");
9615}
9616
9617/*
9618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9619% %
9620% %
9621% %
9622% X W a r n i n g %
9623% %
9624% %
9625% %
9626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9627%
9628% XWarning() displays a warning reason in a Notice widget.
9629%
9630% The format of the XWarning method is:
9631%
9632% void XWarning(const unsigned int warning,const char *reason,
9633% const char *description)
9634%
9635% A description of each parameter follows:
9636%
9637% o warning: Specifies the numeric warning category.
9638%
9639% o reason: Specifies the reason to display before terminating the
9640% program.
9641%
9642% o description: Specifies any description to the reason.
9643%
9644*/
cristybcbda3f2011-09-03 13:01:22 +00009645MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009646 const char *reason,const char *description)
9647{
9648 char
9649 text[MaxTextExtent];
9650
9651 XWindows
9652 *windows;
9653
9654 if (reason == (char *) NULL)
9655 return;
9656 (void) CopyMagickString(text,reason,MaxTextExtent);
9657 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9658 windows=XSetWindows((XWindows *) ~0);
9659 XNoticeWidget(windows->display,windows,text,(char *) description);
9660}
9661
9662/*
9663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9664% %
9665% %
9666% %
9667% X W i n d o w B y I D %
9668% %
9669% %
9670% %
9671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9672%
9673% XWindowByID() locates a child window with a given ID. If not window with
9674% the given name is found, 0 is returned. Only the window specified and its
9675% subwindows are searched.
9676%
9677% The format of the XWindowByID function is:
9678%
9679% child=XWindowByID(display,window,id)
9680%
9681% A description of each parameter follows:
9682%
9683% o child: XWindowByID returns the window with the specified
9684% id. If no windows are found, XWindowByID returns 0.
9685%
9686% o display: Specifies a pointer to the Display structure; returned from
9687% XOpenDisplay.
9688%
9689% o id: Specifies the id of the window to locate.
9690%
9691*/
cristybcbda3f2011-09-03 13:01:22 +00009692MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009693 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009694{
9695 RectangleInfo
9696 rectangle_info;
9697
9698 register int
9699 i;
9700
9701 Status
9702 status;
9703
9704 unsigned int
9705 number_children;
9706
9707 Window
9708 child,
9709 *children,
9710 window;
9711
9712 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9713 assert(display != (Display *) NULL);
9714 assert(root_window != (Window) NULL);
9715 if (id == 0)
9716 return(XSelectWindow(display,&rectangle_info));
9717 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009718 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009719 status=XQueryTree(display,root_window,&child,&child,&children,
9720 &number_children);
9721 if (status == False)
9722 return((Window) NULL);
9723 window=(Window) NULL;
9724 for (i=0; i < (int) number_children; i++)
9725 {
9726 /*
9727 Search each child and their children.
9728 */
9729 window=XWindowByID(display,children[i],id);
9730 if (window != (Window) NULL)
9731 break;
9732 }
9733 if (children != (Window *) NULL)
9734 (void) XFree((void *) children);
9735 return(window);
9736}
9737
9738/*
9739%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9740% %
9741% %
9742% %
9743% X W i n d o w B y N a m e %
9744% %
9745% %
9746% %
9747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9748%
9749% XWindowByName() locates a window with a given name on a display. If no
9750% window with the given name is found, 0 is returned. If more than one window
9751% has the given name, the first one is returned. Only root and its children
9752% are searched.
9753%
9754% The format of the XWindowByName function is:
9755%
9756% window=XWindowByName(display,root_window,name)
9757%
9758% A description of each parameter follows:
9759%
9760% o window: XWindowByName returns the window id.
9761%
9762% o display: Specifies a pointer to the Display structure; returned from
9763% XOpenDisplay.
9764%
9765% o root_window: Specifies the id of the root window.
9766%
9767% o name: Specifies the name of the window to locate.
9768%
9769*/
cristybcbda3f2011-09-03 13:01:22 +00009770MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009771 const char *name)
9772{
9773 register int
9774 i;
9775
9776 Status
9777 status;
9778
9779 unsigned int
9780 number_children;
9781
9782 Window
9783 *children,
9784 child,
9785 window;
9786
9787 XTextProperty
9788 window_name;
9789
9790 assert(display != (Display *) NULL);
9791 assert(root_window != (Window) NULL);
9792 assert(name != (char *) NULL);
9793 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9794 if (XGetWMName(display,root_window,&window_name) != 0)
9795 if (LocaleCompare((char *) window_name.value,name) == 0)
9796 return(root_window);
9797 status=XQueryTree(display,root_window,&child,&child,&children,
9798 &number_children);
9799 if (status == False)
9800 return((Window) NULL);
9801 window=(Window) NULL;
9802 for (i=0; i < (int) number_children; i++)
9803 {
9804 /*
9805 Search each child and their children.
9806 */
9807 window=XWindowByName(display,children[i],name);
9808 if (window != (Window) NULL)
9809 break;
9810 }
9811 if (children != (Window *) NULL)
9812 (void) XFree((void *) children);
9813 return(window);
9814}
9815
9816/*
9817%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9818% %
9819% %
9820% %
9821% X W i n d o w B y P r o p e r y %
9822% %
9823% %
9824% %
9825%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9826%
9827% XWindowByProperty() locates a child window with a given property. If not
9828% window with the given name is found, 0 is returned. If more than one window
9829% has the given property, the first one is returned. Only the window
9830% specified and its subwindows are searched.
9831%
9832% The format of the XWindowByProperty function is:
9833%
9834% child=XWindowByProperty(display,window,property)
9835%
9836% A description of each parameter follows:
9837%
9838% o child: XWindowByProperty returns the window id with the specified
9839% property. If no windows are found, XWindowByProperty returns 0.
9840%
9841% o display: Specifies a pointer to the Display structure; returned from
9842% XOpenDisplay.
9843%
9844% o property: Specifies the property of the window to locate.
9845%
9846*/
cristybcbda3f2011-09-03 13:01:22 +00009847MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009848 const Atom property)
9849{
9850 Atom
9851 type;
9852
9853 int
9854 format;
9855
9856 Status
9857 status;
9858
9859 unsigned char
9860 *data;
9861
9862 unsigned int
9863 i,
9864 number_children;
9865
cristyf2faecf2010-05-28 19:19:36 +00009866 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009867 after,
9868 number_items;
9869
9870 Window
9871 child,
9872 *children,
9873 parent,
9874 root;
9875
9876 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9877 assert(display != (Display *) NULL);
9878 assert(window != (Window) NULL);
9879 assert(property != (Atom) NULL);
9880 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9881 if (status == False)
9882 return((Window) NULL);
9883 type=(Atom) NULL;
9884 child=(Window) NULL;
9885 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9886 {
9887 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9888 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9889 if (data != NULL)
9890 (void) XFree((void *) data);
9891 if ((status == Success) && (type != (Atom) NULL))
9892 child=children[i];
9893 }
9894 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9895 child=XWindowByProperty(display,children[i],property);
9896 if (children != (Window *) NULL)
9897 (void) XFree((void *) children);
9898 return(child);
9899}
9900#else
9901
9902/*
9903%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9904% %
9905% %
9906% %
9907% X I m p o r t I m a g e %
9908% %
9909% %
9910% %
9911%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9912%
9913% XImportImage() reads an image from an X window.
9914%
9915% The format of the XImportImage method is:
9916%
cristya0dc96a2011-12-19 23:58:54 +00009917% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9918% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009919%
9920% A description of each parameter follows:
9921%
9922% o image_info: the image info..
9923%
9924% o ximage_info: Specifies a pointer to an XImportInfo structure.
9925%
cristya0dc96a2011-12-19 23:58:54 +00009926% o exception: return any errors or warnings in this structure.
9927%
cristy3ed852e2009-09-05 21:47:34 +00009928*/
cristy4bc52022012-12-13 14:15:41 +00009929MagickExport Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009930 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009931{
9932 assert(image_info != (const ImageInfo *) NULL);
9933 assert(image_info->signature == MagickSignature);
9934 if (image_info->debug != MagickFalse)
9935 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9936 image_info->filename);
9937 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009938 assert(exception != (ExceptionInfo *) NULL);
9939 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009940 return((Image *) NULL);
9941}
cristy534d0a32013-04-13 16:27:24 +00009942
9943/*
9944%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9945% %
9946% %
9947% %
9948% X R e n d e r X 1 1 %
9949% %
9950% %
9951% %
9952%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9953%
9954% XRenderImage() renders text on the image with an X11 font. It also returns
9955% the bounding box of the text relative to the image.
9956%
9957% The format of the XRenderImage method is:
9958%
9959% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
9960% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
9961%
9962% A description of each parameter follows:
9963%
9964% o image: the image.
9965%
9966% o draw_info: the draw info.
9967%
9968% o offset: (x,y) location of text relative to image.
9969%
9970% o metrics: bounding box of text.
9971%
9972% o exception: return any errors or warnings in this structure.
9973%
9974*/
9975MagickPrivate MagickBooleanType XRenderImage(Image *image,
9976 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
9977 ExceptionInfo *exception)
9978{
9979 (void) draw_info;
9980 (void) offset;
9981 (void) metrics;
9982 (void) ThrowMagickException(exception,GetMagickModule(),
9983 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","'%s' (X11)",
9984 image->filename);
9985 return(MagickFalse);
9986}
cristy3ed852e2009-09-05 21:47:34 +00009987#endif
9988
9989/*
9990%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9991% %
9992% %
9993% %
cristy576974e2009-10-25 20:45:31 +00009994+ X C o m p o n e n t G e n e s i s %
9995% %
9996% %
9997% %
9998%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9999%
10000% XComponentGenesis() instantiates the X component.
10001%
10002% The format of the XComponentGenesis method is:
10003%
10004% MagickBooleanType XComponentGenesis(void)
10005%
10006*/
cristy5ff4eaf2011-09-03 01:38:02 +000010007MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +000010008{
10009 return(MagickTrue);
10010}
10011
10012/*
10013%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10014% %
10015% %
10016% %
cristy3ed852e2009-09-05 21:47:34 +000010017% X G e t I m p o r t I n f o %
10018% %
10019% %
10020% %
10021%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10022%
10023% XGetImportInfo() initializes the XImportInfo structure.
10024%
10025% The format of the XGetImportInfo method is:
10026%
10027% void XGetImportInfo(XImportInfo *ximage_info)
10028%
10029% A description of each parameter follows:
10030%
10031% o ximage_info: Specifies a pointer to an ImageInfo structure.
10032%
10033*/
10034MagickExport void XGetImportInfo(XImportInfo *ximage_info)
10035{
10036 assert(ximage_info != (XImportInfo *) NULL);
10037 ximage_info->frame=MagickFalse;
10038 ximage_info->borders=MagickFalse;
10039 ximage_info->screen=MagickFalse;
10040 ximage_info->descend=MagickTrue;
10041 ximage_info->silent=MagickFalse;
10042}