blob: a9ec377c48d3528eeefeb5efdf5c25f539f0aec7 [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% %
cristyfe676ee2013-11-18 13:03:38 +000020% Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/animate.h"
44#include "MagickCore/artifact.h"
45#include "MagickCore/blob.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/client.h"
48#include "MagickCore/color.h"
49#include "MagickCore/color-private.h"
50#include "MagickCore/colormap.h"
51#include "MagickCore/composite.h"
cristy030436f2012-01-06 21:56:17 +000052#include "MagickCore/constitute.h"
cristy4c08aed2011-07-01 19:47:50 +000053#include "MagickCore/display.h"
cristyc53413d2011-11-17 13:04:26 +000054#include "MagickCore/distort.h"
cristy4c08aed2011-07-01 19:47:50 +000055#include "MagickCore/exception.h"
56#include "MagickCore/exception-private.h"
57#include "MagickCore/geometry.h"
58#include "MagickCore/identify.h"
59#include "MagickCore/image.h"
60#include "MagickCore/image-private.h"
61#include "MagickCore/list.h"
62#include "MagickCore/locale_.h"
63#include "MagickCore/log.h"
64#include "MagickCore/magick.h"
65#include "MagickCore/memory_.h"
66#include "MagickCore/monitor.h"
cristy2c5fc272012-02-22 01:27:46 +000067#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000068#include "MagickCore/option.h"
69#include "MagickCore/pixel-accessor.h"
70#include "MagickCore/PreRvIcccm.h"
71#include "MagickCore/quantize.h"
72#include "MagickCore/quantum.h"
73#include "MagickCore/quantum-private.h"
74#include "MagickCore/resource_.h"
75#include "MagickCore/resize.h"
cristy4c08aed2011-07-01 19:47:50 +000076#include "MagickCore/statistic.h"
77#include "MagickCore/string_.h"
78#include "MagickCore/string-private.h"
79#include "MagickCore/transform.h"
cristy63a81872012-03-22 15:52:52 +000080#include "MagickCore/token.h"
cristy4c08aed2011-07-01 19:47:50 +000081#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000082#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000083#include "MagickCore/widget.h"
cristybcbda3f2011-09-03 13:01:22 +000084#include "MagickCore/widget-private.h"
cristy4c08aed2011-07-01 19:47:50 +000085#include "MagickCore/xwindow.h"
86#include "MagickCore/xwindow-private.h"
87#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000088#if defined(__BEOS__)
89#include <OS.h>
90#endif
91#if defined(MAGICKCORE_X11_DELEGATE)
92#include <X11/Xproto.h>
93#include <X11/Xlocale.h>
94#if defined(MAGICK_HAVE_POLL)
95# include <sys/poll.h>
96#endif
97#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
98#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
99# include <machine/param.h>
100#endif
101#include <sys/ipc.h>
102#include <sys/shm.h>
103#include <X11/extensions/XShm.h>
104#endif
105#if defined(MAGICKCORE_HAVE_SHAPE)
106#include <X11/extensions/shape.h>
107#endif
108
109/*
110 X defines.
111*/
cristyce70c172010-01-07 17:15:30 +0000112#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000113 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
114 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000115#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000116 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
117 map->red_mult)+ \
118 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
119 map->green_mult)+ \
120 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
121 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000122#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
123 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
124 map->red_mult)+ \
125 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
126 map->green_mult)+ \
127 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
128 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000129#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000130 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
131 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000132#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000133 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
134 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000135#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000136 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
137 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
138 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000139
140#define AccentuateModulate ScaleCharToQuantum(80)
141#define HighlightModulate ScaleCharToQuantum(125)
142#define ShadowModulate ScaleCharToQuantum(135)
143#define DepthModulate ScaleCharToQuantum(185)
144#define TroughModulate ScaleCharToQuantum(110)
145
146#define XLIB_ILLEGAL_ACCESS 1
147#undef ForgetGravity
148#undef NorthWestGravity
149#undef NorthGravity
150#undef NorthEastGravity
151#undef WestGravity
152#undef CenterGravity
153#undef EastGravity
154#undef SouthWestGravity
155#undef SouthGravity
156#undef SouthEastGravity
157#undef StaticGravity
158
159#undef index
160#if defined(hpux9)
161#define XFD_SET int
162#else
163#define XFD_SET fd_set
164#endif
165
166/*
167 Enumeration declarations.
168*/
169typedef enum
170{
171#undef DoRed
172 DoRed = 0x0001,
173#undef DoGreen
174 DoGreen = 0x0002,
175#undef DoBlue
176 DoBlue = 0x0004,
177 DoMatte = 0x0008
178} XColorFlags;
179
180/*
181 Typedef declarations.
182*/
183typedef struct _DiversityPacket
184{
185 Quantum
186 red,
187 green,
188 blue;
189
190 unsigned short
191 index;
192
cristybb503372010-05-27 20:51:26 +0000193 size_t
cristy3ed852e2009-09-05 21:47:34 +0000194 count;
195} DiversityPacket;
196
197/*
198 Constant declaractions.
199*/
200static MagickBooleanType
201 xerror_alert = MagickFalse;
202
203/*
204 Method prototypes.
205*/
206static const char
207 *XVisualClassName(const int);
208
cristya19f1d72012-08-07 18:24:38 +0000209static double
cristy3ed852e2009-09-05 21:47:34 +0000210 blue_gamma = 1.0,
211 green_gamma = 1.0,
212 red_gamma = 1.0;
213
214static MagickBooleanType
215 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
216
217static void
218 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000219 XImage *,XImage *,ExceptionInfo *),
cristy3ed852e2009-09-05 21:47:34 +0000220 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000221 XImage *,XImage *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +0000222
223static Window
224 XSelectWindow(Display *,RectangleInfo *);
225
226/*
227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228% %
229% %
230% %
231% D e s t r o y X R e s o u r c e s %
232% %
233% %
234% %
235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236%
237% DestroyXResources() destroys any X resources.
238%
239% The format of the DestroyXResources method is:
240%
241% void DestroyXResources()
242%
243% A description of each parameter follows:
244%
245*/
246MagickExport void DestroyXResources(void)
247{
248 register int
249 i;
250
251 unsigned int
252 number_windows;
253
254 XWindowInfo
255 *magick_windows[MaxXWindows];
256
257 XWindows
258 *windows;
259
260 DestroyXWidget();
261 windows=XSetWindows((XWindows *) ~0);
262 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
263 return;
264 number_windows=0;
265 magick_windows[number_windows++]=(&windows->context);
266 magick_windows[number_windows++]=(&windows->group_leader);
267 magick_windows[number_windows++]=(&windows->backdrop);
268 magick_windows[number_windows++]=(&windows->icon);
269 magick_windows[number_windows++]=(&windows->image);
270 magick_windows[number_windows++]=(&windows->info);
271 magick_windows[number_windows++]=(&windows->magnify);
272 magick_windows[number_windows++]=(&windows->pan);
273 magick_windows[number_windows++]=(&windows->command);
274 magick_windows[number_windows++]=(&windows->widget);
275 magick_windows[number_windows++]=(&windows->popup);
276 magick_windows[number_windows++]=(&windows->context);
277 for (i=0; i < (int) number_windows; i++)
278 {
279 if (magick_windows[i]->mapped != MagickFalse)
280 {
281 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
282 magick_windows[i]->screen);
283 magick_windows[i]->mapped=MagickFalse;
284 }
285 if (magick_windows[i]->name != (char *) NULL)
286 magick_windows[i]->name=(char *)
287 RelinquishMagickMemory(magick_windows[i]->name);
288 if (magick_windows[i]->icon_name != (char *) NULL)
289 magick_windows[i]->icon_name=(char *)
290 RelinquishMagickMemory(magick_windows[i]->icon_name);
291 if (magick_windows[i]->cursor != (Cursor) NULL)
292 {
293 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
294 magick_windows[i]->cursor=(Cursor) NULL;
295 }
296 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
297 {
298 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
299 magick_windows[i]->busy_cursor=(Cursor) NULL;
300 }
301 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
302 {
303 (void) XFreePixmap(windows->display,
304 magick_windows[i]->highlight_stipple);
305 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
306 }
307 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
308 {
309 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
310 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
311 }
312 if (magick_windows[i]->ximage != (XImage *) NULL)
313 {
314 XDestroyImage(magick_windows[i]->ximage);
315 magick_windows[i]->ximage=(XImage *) NULL;
316 }
317 if (magick_windows[i]->pixmap != (Pixmap) NULL)
318 {
319 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
320 magick_windows[i]->pixmap=(Pixmap) NULL;
321 }
322 if (magick_windows[i]->id != (Window) NULL)
323 {
324 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
325 magick_windows[i]->id=(Window) NULL;
326 }
327 if (magick_windows[i]->destroy != MagickFalse)
328 {
329 if (magick_windows[i]->image != (Image *) NULL)
330 {
331 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
332 magick_windows[i]->image=NewImageList();
333 }
334 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
335 {
336 (void) XFreePixmap(windows->display,
337 magick_windows[i]->matte_pixmap);
338 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
339 }
340 }
341 if (magick_windows[i]->segment_info != (void *) NULL)
342 {
343#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
344 XShmSegmentInfo
345 *segment_info;
346
347 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
348 if (segment_info != (XShmSegmentInfo *) NULL)
349 if (segment_info[0].shmid >= 0)
350 {
351 if (segment_info[0].shmaddr != NULL)
352 (void) shmdt(segment_info[0].shmaddr);
353 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
354 segment_info[0].shmaddr=NULL;
355 segment_info[0].shmid=(-1);
356 }
357#endif
358 magick_windows[i]->segment_info=(void *)
359 RelinquishMagickMemory(magick_windows[i]->segment_info);
360 }
361 }
362 windows->icon_resources=(XResourceInfo *)
363 RelinquishMagickMemory(windows->icon_resources);
364 if (windows->icon_pixel != (XPixelInfo *) NULL)
365 {
cristyf2faecf2010-05-28 19:19:36 +0000366 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
367 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000368 RelinquishMagickMemory(windows->icon_pixel->pixels);
369 if (windows->icon_pixel->annotate_context != (GC) NULL)
370 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
371 windows->icon_pixel=(XPixelInfo *)
372 RelinquishMagickMemory(windows->icon_pixel);
373 }
374 if (windows->pixel_info != (XPixelInfo *) NULL)
375 {
cristyf2faecf2010-05-28 19:19:36 +0000376 if (windows->pixel_info->pixels != (unsigned long *) NULL)
377 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000378 RelinquishMagickMemory(windows->pixel_info->pixels);
379 if (windows->pixel_info->annotate_context != (GC) NULL)
380 XFreeGC(windows->display,windows->pixel_info->annotate_context);
381 if (windows->pixel_info->widget_context != (GC) NULL)
382 XFreeGC(windows->display,windows->pixel_info->widget_context);
383 if (windows->pixel_info->highlight_context != (GC) NULL)
384 XFreeGC(windows->display,windows->pixel_info->highlight_context);
385 windows->pixel_info=(XPixelInfo *)
386 RelinquishMagickMemory(windows->pixel_info);
387 }
388 if (windows->font_info != (XFontStruct *) NULL)
389 {
390 XFreeFont(windows->display,windows->font_info);
391 windows->font_info=(XFontStruct *) NULL;
392 }
393 if (windows->class_hints != (XClassHint *) NULL)
394 {
cristyc9cc4a72011-09-18 02:12:41 +0000395 if (windows->class_hints->res_name != (char *) NULL)
396 windows->class_hints->res_name=DestroyString(
397 windows->class_hints->res_name);
398 if (windows->class_hints->res_class != (char *) NULL)
399 windows->class_hints->res_class=DestroyString(
400 windows->class_hints->res_class);
cristy3ed852e2009-09-05 21:47:34 +0000401 XFree(windows->class_hints);
402 windows->class_hints=(XClassHint *) NULL;
403 }
404 if (windows->manager_hints != (XWMHints *) NULL)
405 {
406 XFree(windows->manager_hints);
407 windows->manager_hints=(XWMHints *) NULL;
408 }
409 if (windows->map_info != (XStandardColormap *) NULL)
410 {
411 XFree(windows->map_info);
412 windows->map_info=(XStandardColormap *) NULL;
413 }
414 if (windows->icon_map != (XStandardColormap *) NULL)
415 {
416 XFree(windows->icon_map);
417 windows->icon_map=(XStandardColormap *) NULL;
418 }
419 if (windows->visual_info != (XVisualInfo *) NULL)
420 {
421 XFree(windows->visual_info);
422 windows->visual_info=(XVisualInfo *) NULL;
423 }
424 if (windows->icon_visual != (XVisualInfo *) NULL)
425 {
426 XFree(windows->icon_visual);
427 windows->icon_visual=(XVisualInfo *) NULL;
428 }
429 (void) XSetWindows((XWindows *) NULL);
430}
431
432/*
433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434% %
435% %
436% %
437% X A n n o t a t e I m a g e %
438% %
439% %
440% %
441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
442%
443% XAnnotateImage() annotates the image with text.
444%
445% The format of the XAnnotateImage method is:
446%
447% MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000448% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
449% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000450%
451% A description of each parameter follows:
452%
453% o display: Specifies a connection to an X server; returned from
454% XOpenDisplay.
455%
456% o pixel: Specifies a pointer to a XPixelInfo structure.
457%
458% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
459%
460% o image: the image.
461%
cristy7c3af952011-10-20 16:04:16 +0000462% o exception: return any errors or warnings in this structure.
463%
cristy3ed852e2009-09-05 21:47:34 +0000464*/
cristybcbda3f2011-09-03 13:01:22 +0000465MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000466 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
467 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000468{
cristyc57f6942010-11-12 01:47:39 +0000469 CacheView
470 *annotate_view;
471
cristy3ed852e2009-09-05 21:47:34 +0000472 GC
473 annotate_context;
474
cristy3ed852e2009-09-05 21:47:34 +0000475 Image
476 *annotate_image;
477
478 int
479 x,
480 y;
481
cristyb0a657e2012-08-29 00:45:37 +0000482 PixelTrait
483 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +0000484
485 Pixmap
486 annotate_pixmap;
487
488 unsigned int
489 depth,
490 height,
491 width;
492
493 Window
494 root_window;
495
496 XGCValues
497 context_values;
498
499 XImage
500 *annotate_ximage;
501
502 /*
503 Initialize annotated image.
504 */
505 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
506 assert(display != (Display *) NULL);
507 assert(pixel != (XPixelInfo *) NULL);
508 assert(annotate_info != (XAnnotateInfo *) NULL);
509 assert(image != (Image *) NULL);
510 /*
511 Initialize annotated pixmap.
512 */
513 root_window=XRootWindow(display,XDefaultScreen(display));
514 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
515 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
516 annotate_info->height,depth);
517 if (annotate_pixmap == (Pixmap) NULL)
518 return(MagickFalse);
519 /*
520 Initialize graphics info.
521 */
522 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000523 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000524 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000525 annotate_context=XCreateGC(display,root_window,(unsigned long)
526 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000527 if (annotate_context == (GC) NULL)
528 return(MagickFalse);
529 /*
530 Draw text to pixmap.
531 */
532 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
533 (int) annotate_info->font_info->ascent,annotate_info->text,
534 (int) strlen(annotate_info->text));
535 (void) XFreeGC(display,annotate_context);
536 /*
537 Initialize annotated X image.
538 */
539 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
540 annotate_info->height,AllPlanes,ZPixmap);
541 if (annotate_ximage == (XImage *) NULL)
542 return(MagickFalse);
543 (void) XFreePixmap(display,annotate_pixmap);
544 /*
545 Initialize annotated image.
546 */
cristy6710d842011-10-20 23:23:00 +0000547 annotate_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +0000548 if (annotate_image == (Image *) NULL)
549 return(MagickFalse);
550 annotate_image->columns=annotate_info->width;
551 annotate_image->rows=annotate_info->height;
552 /*
553 Transfer annotated X image to image.
554 */
555 width=(unsigned int) image->columns;
556 height=(unsigned int) image->rows;
557 x=0;
558 y=0;
559 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +0000560 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
561 (ssize_t) y,&annotate_image->background_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000562 if (annotate_info->stencil == ForegroundStencil)
cristy8a46d822012-08-28 23:32:39 +0000563 annotate_image->alpha_trait=BlendPixelTrait;
cristy6f5395d2012-12-14 18:30:30 +0000564 annotate_view=AcquireAuthenticCacheView(annotate_image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000565 for (y=0; y < (int) annotate_image->rows; y++)
566 {
cristyc57f6942010-11-12 01:47:39 +0000567 register int
cristy3ed852e2009-09-05 21:47:34 +0000568 x;
569
cristy4c08aed2011-07-01 19:47:50 +0000570 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000571 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000572
cristyc57f6942010-11-12 01:47:39 +0000573 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
574 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000575 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000576 break;
cristyc57f6942010-11-12 01:47:39 +0000577 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000578 {
cristy4c08aed2011-07-01 19:47:50 +0000579 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000580 if (XGetPixel(annotate_ximage,x,y) == 0)
581 {
582 /*
583 Set this pixel to the background color.
584 */
cristy4c08aed2011-07-01 19:47:50 +0000585 SetPixelRed(annotate_image,ScaleShortToQuantum(
586 pixel->box_color.red),q);
587 SetPixelGreen(annotate_image,ScaleShortToQuantum(
588 pixel->box_color.green),q);
589 SetPixelBlue(annotate_image,ScaleShortToQuantum(
590 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000591 if ((annotate_info->stencil == ForegroundStencil) ||
592 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000593 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000594 }
595 else
596 {
597 /*
598 Set this pixel to the pen color.
599 */
cristy4c08aed2011-07-01 19:47:50 +0000600 SetPixelRed(annotate_image,ScaleShortToQuantum(
601 pixel->pen_color.red),q);
602 SetPixelGreen(annotate_image,ScaleShortToQuantum(
603 pixel->pen_color.green),q);
604 SetPixelBlue(annotate_image,ScaleShortToQuantum(
605 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000606 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000607 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000608 }
cristyed231572011-07-14 02:18:59 +0000609 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000610 }
cristyc57f6942010-11-12 01:47:39 +0000611 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000612 break;
613 }
cristyc57f6942010-11-12 01:47:39 +0000614 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000615 XDestroyImage(annotate_ximage);
616 /*
617 Determine annotate geometry.
618 */
619 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
620 if ((width != (unsigned int) annotate_image->columns) ||
621 (height != (unsigned int) annotate_image->rows))
622 {
623 char
624 image_geometry[MaxTextExtent];
625
626 /*
627 Scale image.
628 */
cristyb51dff52011-05-19 16:55:47 +0000629 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000630 width,height);
cristye941a752011-10-15 01:52:48 +0000631 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
632 exception);
cristy3ed852e2009-09-05 21:47:34 +0000633 }
634 if (annotate_info->degrees != 0.0)
635 {
636 Image
637 *rotate_image;
638
639 int
640 rotations;
641
cristya19f1d72012-08-07 18:24:38 +0000642 double
cristy3ed852e2009-09-05 21:47:34 +0000643 normalized_degrees;
644
645 /*
646 Rotate image.
647 */
cristy6710d842011-10-20 23:23:00 +0000648 rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +0000649 if (rotate_image == (Image *) NULL)
650 return(MagickFalse);
651 annotate_image=DestroyImage(annotate_image);
652 annotate_image=rotate_image;
653 /*
654 Annotation is relative to the degree of rotation.
655 */
656 normalized_degrees=annotate_info->degrees;
657 while (normalized_degrees < -45.0)
658 normalized_degrees+=360.0;
659 for (rotations=0; normalized_degrees > 45.0; rotations++)
660 normalized_degrees-=90.0;
661 switch (rotations % 4)
662 {
663 default:
664 case 0:
665 break;
666 case 1:
667 {
668 /*
669 Rotate 90 degrees.
670 */
671 x-=(int) annotate_image->columns/2;
672 y+=(int) annotate_image->columns/2;
673 break;
674 }
675 case 2:
676 {
677 /*
678 Rotate 180 degrees.
679 */
680 x=x-(int) annotate_image->columns;
681 break;
682 }
683 case 3:
684 {
685 /*
686 Rotate 270 degrees.
687 */
688 x=x-(int) annotate_image->columns/2;
689 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
690 break;
691 }
692 }
693 }
694 /*
695 Composite text onto the image.
696 */
697 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyb0a657e2012-08-29 00:45:37 +0000698 alpha_trait=image->alpha_trait;
cristyfeb3e962012-03-29 17:25:55 +0000699 (void) CompositeImage(image,annotate_image,
cristyb0a657e2012-08-29 00:45:37 +0000700 annotate_image->alpha_trait == BlendPixelTrait ? OverCompositeOp :
701 CopyCompositeOp,MagickTrue,(ssize_t) x,(ssize_t) y,exception);
702 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +0000703 annotate_image=DestroyImage(annotate_image);
704 return(MagickTrue);
705}
706
707/*
708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
709% %
710% %
711% %
712% X B e s t F o n t %
713% %
714% %
715% %
716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
717%
718% XBestFont() returns the "best" font. "Best" is defined as a font specified
719% in the X resource database or a font such that the text width displayed
720% with the font does not exceed the specified maximum width.
721%
722% The format of the XBestFont method is:
723%
724% XFontStruct *XBestFont(Display *display,
725% const XResourceInfo *resource_info,const MagickBooleanType text_font)
726%
727% A description of each parameter follows:
728%
729% o font: XBestFont returns a pointer to a XFontStruct structure.
730%
731% o display: Specifies a connection to an X server; returned from
732% XOpenDisplay.
733%
734% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
735%
736% o text_font: True is font should be mono-spaced (typewriter style).
737%
cristy3ed852e2009-09-05 21:47:34 +0000738*/
739
740static char **FontToList(char *font)
741{
742 char
743 **fontlist;
744
745 register char
746 *p,
747 *q;
748
749 register int
750 i;
751
752 unsigned int
753 fonts;
754
755 if (font == (char *) NULL)
756 return((char **) NULL);
757 /*
758 Convert string to an ASCII list.
759 */
760 fonts=1U;
761 for (p=font; *p != '\0'; p++)
762 if ((*p == ':') || (*p == ';') || (*p == ','))
763 fonts++;
764 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
765 if (fontlist == (char **) NULL)
766 {
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*/
1147
1148static inline int MagickMax(const int x,const int y)
1149{
1150 if (x > y)
1151 return(x);
1152 return(y);
1153}
1154
cristybb503372010-05-27 20:51:26 +00001155static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001156 const unsigned int y)
1157{
1158 if (x < y)
1159 return(x);
1160 return(y);
1161}
1162
cristybcbda3f2011-09-03 13:01:22 +00001163MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001164 XStandardColormap *map_info,XResourceInfo *resource_info)
1165{
1166#define MaxStandardColormaps 7
1167#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1168 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1169 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1170 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1171
1172 char
1173 *map_type,
1174 *visual_type;
1175
cristyc57f6942010-11-12 01:47:39 +00001176 int
1177 visual_mask;
1178
cristy3ed852e2009-09-05 21:47:34 +00001179 register int
1180 i;
1181
cristy8891f9c2010-06-04 23:32:17 +00001182 size_t
1183 one;
1184
cristy3ed852e2009-09-05 21:47:34 +00001185 static int
1186 number_visuals;
1187
1188 static XVisualInfo
1189 visual_template;
1190
1191 XVisualInfo
1192 *visual_info,
1193 *visual_list;
1194
1195 /*
1196 Restrict visual search by screen number.
1197 */
1198 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1199 assert(display != (Display *) NULL);
1200 assert(map_info != (XStandardColormap *) NULL);
1201 assert(resource_info != (XResourceInfo *) NULL);
1202 map_type=resource_info->map_type;
1203 visual_type=resource_info->visual_type;
1204 visual_mask=VisualScreenMask;
1205 visual_template.screen=XDefaultScreen(display);
1206 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001207 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001208 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001209 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001210 visual_mask|=VisualDepthMask;
1211 if (visual_type != (char *) NULL)
1212 {
1213 /*
1214 Restrict visual search by class or visual id.
1215 */
1216 if (LocaleCompare("staticgray",visual_type) == 0)
1217 {
1218 visual_mask|=VisualClassMask;
1219 visual_template.klass=StaticGray;
1220 }
1221 else
1222 if (LocaleCompare("grayscale",visual_type) == 0)
1223 {
1224 visual_mask|=VisualClassMask;
1225 visual_template.klass=GrayScale;
1226 }
1227 else
1228 if (LocaleCompare("staticcolor",visual_type) == 0)
1229 {
1230 visual_mask|=VisualClassMask;
1231 visual_template.klass=StaticColor;
1232 }
1233 else
1234 if (LocaleCompare("pseudocolor",visual_type) == 0)
1235 {
1236 visual_mask|=VisualClassMask;
1237 visual_template.klass=PseudoColor;
1238 }
1239 else
1240 if (LocaleCompare("truecolor",visual_type) == 0)
1241 {
1242 visual_mask|=VisualClassMask;
1243 visual_template.klass=TrueColor;
1244 }
1245 else
1246 if (LocaleCompare("directcolor",visual_type) == 0)
1247 {
1248 visual_mask|=VisualClassMask;
1249 visual_template.klass=DirectColor;
1250 }
1251 else
1252 if (LocaleCompare("default",visual_type) == 0)
1253 {
1254 visual_mask|=VisualIDMask;
1255 visual_template.visualid=XVisualIDFromVisual(
1256 XDefaultVisual(display,XDefaultScreen(display)));
1257 }
1258 else
1259 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1260 {
1261 visual_mask|=VisualIDMask;
1262 visual_template.visualid=
1263 strtol(visual_type,(char **) NULL,0);
1264 }
1265 else
cristyc38fbf52013-11-03 13:55:54 +00001266 ThrowXWindowException(XServerError,
cristy3ed852e2009-09-05 21:47:34 +00001267 "UnrecognizedVisualSpecifier",visual_type);
1268 }
1269 /*
1270 Get all visuals that meet our criteria so far.
1271 */
1272 number_visuals=0;
1273 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1274 &number_visuals);
1275 visual_mask=VisualScreenMask | VisualIDMask;
1276 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1277 {
1278 /*
1279 Failed to get visual; try using the default visual.
1280 */
cristyc38fbf52013-11-03 13:55:54 +00001281 ThrowXWindowException(XServerWarning,"UnableToGetVisual",visual_type);
cristy3ed852e2009-09-05 21:47:34 +00001282 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1283 XDefaultScreen(display)));
1284 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1285 &number_visuals);
1286 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1287 return((XVisualInfo *) NULL);
cristyc38fbf52013-11-03 13:55:54 +00001288 ThrowXWindowException(XServerWarning,"UsingDefaultVisual",
cristy3ed852e2009-09-05 21:47:34 +00001289 XVisualClassName(visual_list->klass));
1290 }
1291 resource_info->color_recovery=MagickFalse;
1292 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1293 {
1294 Atom
1295 map_property;
1296
1297 char
1298 map_name[MaxTextExtent];
1299
1300 int
1301 j,
1302 number_maps;
1303
1304 Status
1305 status;
1306
1307 Window
1308 root_window;
1309
1310 XStandardColormap
1311 *map_list;
1312
1313 /*
1314 Choose a visual associated with a standard colormap.
1315 */
1316 root_window=XRootWindow(display,XDefaultScreen(display));
1317 status=False;
cristy53365c22013-11-24 15:13:41 +00001318 number_maps=0;
cristy3ed852e2009-09-05 21:47:34 +00001319 if (LocaleCompare(map_type,"list") != 0)
1320 {
1321 /*
1322 User specified Standard Colormap.
1323 */
cristyb51dff52011-05-19 16:55:47 +00001324 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001325 "RGB_%s_MAP",map_type);
1326 LocaleUpper(map_name);
1327 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1328 if (map_property != (Atom) NULL)
1329 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1330 map_property);
1331 }
1332 else
1333 {
1334 static const char
1335 *colormap[MaxStandardColormaps]=
1336 {
1337 "_HP_RGB_SMOOTH_MAP_LIST",
1338 "RGB_BEST_MAP",
1339 "RGB_DEFAULT_MAP",
1340 "RGB_GRAY_MAP",
1341 "RGB_RED_MAP",
1342 "RGB_GREEN_MAP",
1343 "RGB_BLUE_MAP",
1344 };
1345
1346 /*
1347 Choose a standard colormap from a list.
1348 */
1349 for (i=0; i < MaxStandardColormaps; i++)
1350 {
1351 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1352 if (map_property == (Atom) NULL)
1353 continue;
1354 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1355 map_property);
1356 if (status != False)
1357 break;
1358 }
1359 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1360 }
1361 if (status == False)
1362 {
cristyc38fbf52013-11-03 13:55:54 +00001363 ThrowXWindowException(XServerError,"UnableToGetStandardColormap",
cristy3ed852e2009-09-05 21:47:34 +00001364 map_type);
1365 return((XVisualInfo *) NULL);
1366 }
1367 /*
1368 Search all Standard Colormaps and visuals for ids that match.
1369 */
1370 *map_info=map_list[0];
1371#if !defined(PRE_R4_ICCCM)
1372 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1373 for (i=0; i < number_maps; i++)
1374 for (j=0; j < number_visuals; j++)
1375 if (map_list[i].visualid ==
1376 XVisualIDFromVisual(visual_list[j].visual))
1377 {
1378 *map_info=map_list[i];
1379 visual_template.visualid=XVisualIDFromVisual(
1380 visual_list[j].visual);
1381 break;
1382 }
1383 if (map_info->visualid != visual_template.visualid)
1384 {
cristyc38fbf52013-11-03 13:55:54 +00001385 ThrowXWindowException(XServerError,
cristy3ed852e2009-09-05 21:47:34 +00001386 "UnableToMatchVisualToStandardColormap",map_type);
1387 return((XVisualInfo *) NULL);
1388 }
1389#endif
1390 if (map_info->colormap == (Colormap) NULL)
1391 {
cristyc38fbf52013-11-03 13:55:54 +00001392 ThrowXWindowException(XServerError,"StandardColormapIsNotInitialized",
1393 map_type);
cristy3ed852e2009-09-05 21:47:34 +00001394 return((XVisualInfo *) NULL);
1395 }
1396 (void) XFree((void *) map_list);
1397 }
1398 else
1399 {
1400 static const unsigned int
1401 rank[]=
1402 {
1403 StaticGray,
1404 GrayScale,
1405 StaticColor,
1406 DirectColor,
1407 TrueColor,
1408 PseudoColor
1409 };
1410
1411 XVisualInfo
1412 *p;
1413
1414 /*
1415 Pick one visual that displays the most simultaneous colors.
1416 */
1417 visual_info=visual_list;
1418 p=visual_list;
1419 for (i=1; i < number_visuals; i++)
1420 {
1421 p++;
1422 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1423 visual_info=p;
1424 else
1425 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1426 if (rank[p->klass] > rank[visual_info->klass])
1427 visual_info=p;
1428 }
1429 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1430 }
1431 (void) XFree((void *) visual_list);
1432 /*
1433 Retrieve only one visual by its screen & id number.
1434 */
1435 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1436 &number_visuals);
1437 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1438 return((XVisualInfo *) NULL);
1439 return(visual_info);
1440}
1441
1442/*
1443%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1444% %
1445% %
1446% %
1447% X C h e c k D e f i n e C u r s o r %
1448% %
1449% %
1450% %
1451%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1452%
1453% XCheckDefineCursor() prevents cursor changes on the root window.
1454%
1455% The format of the XXCheckDefineCursor method is:
1456%
1457% XCheckDefineCursor(display,window,cursor)
1458%
1459% A description of each parameter follows:
1460%
1461% o display: Specifies a connection to an X server; returned from
1462% XOpenDisplay.
1463%
1464% o window: the window.
1465%
1466% o cursor: the cursor.
1467%
1468*/
cristybcbda3f2011-09-03 13:01:22 +00001469MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001470 Cursor cursor)
1471{
1472 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1473 assert(display != (Display *) NULL);
1474 if (window == XRootWindow(display,XDefaultScreen(display)))
1475 return(0);
1476 return(XDefineCursor(display,window,cursor));
1477}
1478
1479/*
1480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1481% %
1482% %
1483% %
1484% X C h e c k R e f r e s h W i n d o w s %
1485% %
1486% %
1487% %
1488%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1489%
1490% XCheckRefreshWindows() checks the X server for exposure events for a
1491% particular window and updates the areassociated with the exposure event.
1492%
1493% The format of the XCheckRefreshWindows method is:
1494%
1495% void XCheckRefreshWindows(Display *display,XWindows *windows)
1496%
1497% A description of each parameter follows:
1498%
1499% o display: Specifies a connection to an X server; returned from
1500% XOpenDisplay.
1501%
1502% o windows: Specifies a pointer to a XWindows structure.
1503%
1504*/
cristybcbda3f2011-09-03 13:01:22 +00001505MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001506{
1507 Window
1508 id;
1509
1510 XEvent
1511 event;
1512
1513 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1514 assert(display != (Display *) NULL);
1515 assert(windows != (XWindows *) NULL);
1516 XDelay(display,SuspendTime);
1517 id=windows->command.id;
1518 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1519 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1520 id=windows->image.id;
1521 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1522 XRefreshWindow(display,&windows->image,&event);
1523 XDelay(display,SuspendTime << 1);
1524 id=windows->command.id;
1525 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1526 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1527 id=windows->image.id;
1528 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1529 XRefreshWindow(display,&windows->image,&event);
1530}
1531
1532/*
1533%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1534% %
1535% %
1536% %
1537% X C l i e n t M e s s a g e %
1538% %
1539% %
1540% %
1541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1542%
1543% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1544% initialized with a particular protocol type and atom.
1545%
1546% The format of the XClientMessage function is:
1547%
1548% XClientMessage(display,window,protocol,reason,timestamp)
1549%
1550% A description of each parameter follows:
1551%
1552% o display: Specifies a pointer to the Display structure; returned from
1553% XOpenDisplay.
1554%
1555% o window: Specifies a pointer to a Window structure.
1556%
1557% o protocol: Specifies an atom value.
1558%
1559% o reason: Specifies an atom value which is the reason to send.
1560%
1561% o timestamp: Specifies a value of type Time.
1562%
1563*/
cristybcbda3f2011-09-03 13:01:22 +00001564MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001565 const Atom protocol,const Atom reason,const Time timestamp)
1566{
1567 XClientMessageEvent
1568 client_event;
1569
1570 assert(display != (Display *) NULL);
1571 client_event.type=ClientMessage;
1572 client_event.window=window;
1573 client_event.message_type=protocol;
1574 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001575 client_event.data.l[0]=(long) reason;
1576 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001577 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1578}
1579
1580/*
1581%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1582% %
1583% %
1584% %
1585+ X C l i e n t W i n d o w %
1586% %
1587% %
1588% %
1589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1590%
1591% XClientWindow() finds a window, at or below the specified window, which has
1592% a WM_STATE property. If such a window is found, it is returned, otherwise
1593% the argument window is returned.
1594%
1595% The format of the XClientWindow function is:
1596%
1597% client_window=XClientWindow(display,target_window)
1598%
1599% A description of each parameter follows:
1600%
1601% o client_window: XClientWindow returns a window, at or below the specified
1602% window, which has a WM_STATE property otherwise the argument
1603% target_window is returned.
1604%
1605% o display: Specifies a pointer to the Display structure; returned from
1606% XOpenDisplay.
1607%
1608% o target_window: Specifies the window to find a WM_STATE property.
1609%
cristy3ed852e2009-09-05 21:47:34 +00001610*/
1611static Window XClientWindow(Display *display,Window target_window)
1612{
1613 Atom
1614 state,
1615 type;
1616
1617 int
1618 format;
1619
1620 Status
1621 status;
1622
1623 unsigned char
1624 *data;
1625
cristyf2faecf2010-05-28 19:19:36 +00001626 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001627 after,
1628 number_items;
1629
1630 Window
1631 client_window;
1632
1633 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1634 assert(display != (Display *) NULL);
1635 state=XInternAtom(display,"WM_STATE",MagickTrue);
1636 if (state == (Atom) NULL)
1637 return(target_window);
1638 type=(Atom) NULL;
1639 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1640 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1641 if ((status == Success) && (type != (Atom) NULL))
1642 return(target_window);
1643 client_window=XWindowByProperty(display,target_window,state);
1644 if (client_window == (Window) NULL)
1645 return(target_window);
1646 return(client_window);
1647}
1648
1649/*
1650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1651% %
1652% %
1653% %
cristyf34a1452009-10-24 22:29:27 +00001654+ X C o m p o n e n t T e r m i n u s %
1655% %
1656% %
1657% %
1658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1659%
1660% XComponentTerminus() destroys the module component.
1661%
1662% The format of the XComponentTerminus method is:
1663%
1664% XComponentTerminus(void)
1665%
1666*/
cristy5ff4eaf2011-09-03 01:38:02 +00001667MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001668{
1669 DestroyXResources();
1670}
1671
1672/*
1673%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1674% %
1675% %
1676% %
cristy3ed852e2009-09-05 21:47:34 +00001677% X C o n f i g u r e I m a g e C o l o r m a p %
1678% %
1679% %
1680% %
1681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1682%
1683% XConfigureImageColormap() creates a new X colormap.
1684%
1685% The format of the XConfigureImageColormap method is:
1686%
1687% void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001688% XResourceInfo *resource_info,XWindows *windows,Image *image,
1689% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001690%
1691% A description of each parameter follows:
1692%
1693% o display: Specifies a connection to an X server; returned from
1694% XOpenDisplay.
1695%
1696% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1697%
1698% o windows: Specifies a pointer to a XWindows structure.
1699%
1700% o image: the image.
1701%
cristy6710d842011-10-20 23:23:00 +00001702% o exception: return any errors or warnings in this structure.
1703%
cristy3ed852e2009-09-05 21:47:34 +00001704*/
cristybcbda3f2011-09-03 13:01:22 +00001705MagickPrivate void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001706 XResourceInfo *resource_info,XWindows *windows,Image *image,
1707 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001708{
1709 Colormap
1710 colormap;
1711
1712 /*
1713 Make standard colormap.
1714 */
1715 XSetCursorState(display,windows,MagickTrue);
1716 XCheckRefreshWindows(display,windows);
1717 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
cristy6710d842011-10-20 23:23:00 +00001718 windows->map_info,windows->pixel_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00001719 colormap=windows->map_info->colormap;
1720 (void) XSetWindowColormap(display,windows->image.id,colormap);
1721 (void) XSetWindowColormap(display,windows->command.id,colormap);
1722 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1723 if (windows->magnify.mapped != MagickFalse)
1724 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1725 if (windows->pan.mapped != MagickFalse)
1726 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1727 XSetCursorState(display,windows,MagickFalse);
1728 XClientMessage(display,windows->image.id,windows->im_protocols,
1729 windows->im_update_colormap,CurrentTime);
1730}
1731
1732/*
1733%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1734% %
1735% %
1736% %
1737% X C o n s t r a i n W i n d o w P o s i t i o n %
1738% %
1739% %
1740% %
1741%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1742%
1743% XConstrainWindowPosition() assures a window is positioned within the X
1744% server boundaries.
1745%
1746% The format of the XConstrainWindowPosition method is:
1747%
1748% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1749%
1750% A description of each parameter follows:
1751%
1752% o display: Specifies a pointer to the Display structure; returned from
1753% XOpenDisplay.
1754%
1755% o window_info: Specifies a pointer to a XWindowInfo structure.
1756%
1757*/
cristybcbda3f2011-09-03 13:01:22 +00001758MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001759 XWindowInfo *window_info)
1760{
1761 int
1762 limit;
1763
1764 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1765 assert(display != (Display *) NULL);
1766 assert(window_info != (XWindowInfo *) NULL);
1767 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1768 if (window_info->x < 0)
1769 window_info->x=0;
1770 else
1771 if (window_info->x > (int) limit)
1772 window_info->x=(int) limit;
1773 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1774 if (window_info->y < 0)
1775 window_info->y=0;
1776 else
1777 if (window_info->y > limit)
1778 window_info->y=limit;
1779}
1780
1781/*
1782%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1783% %
1784% %
1785% %
1786% X D e l a y %
1787% %
1788% %
1789% %
1790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1791%
1792% XDelay() suspends program execution for the number of milliseconds
1793% specified.
1794%
1795% The format of the Delay method is:
1796%
cristybb503372010-05-27 20:51:26 +00001797% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001798%
1799% A description of each parameter follows:
1800%
1801% o display: Specifies a pointer to the Display structure; returned from
1802% XOpenDisplay.
1803%
1804% o milliseconds: Specifies the number of milliseconds to delay before
1805% returning.
1806%
1807*/
cristybcbda3f2011-09-03 13:01:22 +00001808MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001809{
1810 assert(display != (Display *) NULL);
1811 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001812 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001813}
1814
1815/*
1816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1817% %
1818% %
1819% %
1820% X D e s t r o y R e s o u r c e I n f o %
1821% %
1822% %
1823% %
1824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1825%
1826% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1827% structure.
1828%
1829% The format of the XDestroyResourceInfo method is:
1830%
1831% void XDestroyResourceInfo(XResourceInfo *resource_info)
1832%
1833% A description of each parameter follows:
1834%
1835% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1836%
1837*/
1838MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1839{
1840 if (resource_info->image_geometry != (char *) NULL)
1841 resource_info->image_geometry=(char *)
1842 RelinquishMagickMemory(resource_info->image_geometry);
1843 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1844 resource_info->quantize_info=DestroyQuantizeInfo(
1845 resource_info->quantize_info);
1846 if (resource_info->client_name != (char *) NULL)
1847 resource_info->client_name=(char *)
1848 RelinquishMagickMemory(resource_info->client_name);
1849 if (resource_info->name != (char *) NULL)
1850 resource_info->name=DestroyString(resource_info->name);
1851 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1852}
1853
1854/*
1855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1856% %
1857% %
1858% %
1859% X D e s t r o y W i n d o w C o l o r s %
1860% %
1861% %
1862% %
1863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1864%
1865% XDestroyWindowColors() frees X11 color resources previously saved on a
1866% window by XRetainWindowColors or programs like xsetroot.
1867%
1868% The format of the XDestroyWindowColors method is:
1869%
1870% void XDestroyWindowColors(Display *display,Window window)
1871%
1872% A description of each parameter follows:
1873%
1874% o display: Specifies a connection to an X server; returned from
1875% XOpenDisplay.
1876%
1877% o window: Specifies a pointer to a Window structure.
1878%
1879*/
cristybcbda3f2011-09-03 13:01:22 +00001880MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001881{
1882 Atom
1883 property,
1884 type;
1885
1886 int
1887 format;
1888
1889 Status
1890 status;
1891
1892 unsigned char
1893 *data;
1894
cristyf2faecf2010-05-28 19:19:36 +00001895 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001896 after,
1897 length;
1898
1899 /*
1900 If there are previous resources on the root window, destroy them.
1901 */
1902 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1903 assert(display != (Display *) NULL);
1904 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1905 if (property == (Atom) NULL)
1906 {
cristyc38fbf52013-11-03 13:55:54 +00001907 ThrowXWindowException(XServerError,"UnableToCreateProperty",
cristy3ed852e2009-09-05 21:47:34 +00001908 "_XSETROOT_ID");
1909 return;
1910 }
1911 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1912 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1913 if (status != Success)
1914 return;
1915 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1916 {
1917 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1918 (void) XDeleteProperty(display,window,property);
1919 }
1920 if (type != None)
1921 (void) XFree((void *) data);
1922}
1923
1924/*
1925%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1926% %
1927% %
1928% %
1929% X D i s p l a y I m a g e I n f o %
1930% %
1931% %
1932% %
1933%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1934%
1935% XDisplayImageInfo() displays information about an X image.
1936%
1937% The format of the XDisplayImageInfo method is:
1938%
1939% void XDisplayImageInfo(Display *display,
1940% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001941% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001942%
1943% A description of each parameter follows:
1944%
1945% o display: Specifies a connection to an X server; returned from
1946% XOpenDisplay.
1947%
1948% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1949%
1950% o windows: Specifies a pointer to a XWindows structure.
1951%
1952% o undo_image: the undo image.
1953%
1954% o image: the image.
1955%
cristy6710d842011-10-20 23:23:00 +00001956% o exception: return any errors or warnings in this structure.
1957%
cristy3ed852e2009-09-05 21:47:34 +00001958*/
cristybcbda3f2011-09-03 13:01:22 +00001959MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001960 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001961 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001962{
1963 char
1964 filename[MaxTextExtent],
1965 *text,
1966 **textlist;
1967
1968 FILE
1969 *file;
1970
1971 int
1972 unique_file;
1973
cristybb503372010-05-27 20:51:26 +00001974 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001975 i;
1976
cristybb503372010-05-27 20:51:26 +00001977 size_t
cristy3ed852e2009-09-05 21:47:34 +00001978 number_pixels;
1979
cristy9d314ff2011-03-09 01:30:28 +00001980 ssize_t
1981 bytes;
1982
1983 unsigned int
1984 levels;
1985
cristy3ed852e2009-09-05 21:47:34 +00001986 /*
1987 Write info about the X server to a file.
1988 */
1989 assert(display != (Display *) NULL);
1990 assert(resource_info != (XResourceInfo *) NULL);
1991 assert(windows != (XWindows *) NULL);
1992 assert(image != (Image *) NULL);
1993 if (image->debug)
1994 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1995 file=(FILE *) NULL;
1996 unique_file=AcquireUniqueFileResource(filename);
1997 if (unique_file != -1)
1998 file=fdopen(unique_file,"w");
1999 if ((unique_file == -1) || (file == (FILE *) NULL))
2000 {
2001 XNoticeWidget(display,windows,"Unable to display image info",filename);
2002 return;
2003 }
2004 if (resource_info->gamma_correct != MagickFalse)
2005 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002006 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002007 resource_info->display_gamma);
2008 /*
2009 Write info about the X image to a file.
2010 */
cristyb51dff52011-05-19 16:55:47 +00002011 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002012 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002013 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002014 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002015 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002016 windows->visual_info->colormap_size);
2017 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002018 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002019 else
cristyb51dff52011-05-19 16:55:47 +00002020 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002021 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2022 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002023 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002024 (void) FormatLocaleFile(file," crop geometry: %s\n",
2025 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002026 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002027 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002028 else
cristyb51dff52011-05-19 16:55:47 +00002029 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002030 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002031 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002032 else
cristyb51dff52011-05-19 16:55:47 +00002033 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002034 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002035 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002036 else
cristyb51dff52011-05-19 16:55:47 +00002037 (void) FormatLocaleFile(file," shared memory: False\n");
2038 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002039 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002040 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002041 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002042 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002043 /*
2044 Write info about the undo cache to a file.
2045 */
2046 bytes=0;
2047 for (levels=0; undo_image != (Image *) NULL; levels++)
2048 {
2049 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002050 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002051 undo_image=GetPreviousImageInList(undo_image);
2052 }
cristyb51dff52011-05-19 16:55:47 +00002053 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002054 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2055 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002056 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002057 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002058 /*
2059 Write info about the image to a file.
2060 */
cristy6710d842011-10-20 23:23:00 +00002061 (void) IdentifyImage(image,file,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00002062 (void) fclose(file);
cristy3a5987c2013-11-07 14:18:46 +00002063 text=FileToString(filename,~0UL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002064 (void) RelinquishUniqueFileResource(filename);
2065 if (text == (char *) NULL)
2066 {
2067 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2068 "UnableToDisplayImageInfo");
2069 return;
2070 }
2071 textlist=StringToList(text);
2072 if (textlist != (char **) NULL)
2073 {
2074 char
2075 title[MaxTextExtent];
2076
2077 /*
2078 Display information about the image in the Text View widget.
2079 */
2080 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002081 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002082 image->filename);
2083 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2084 (char const **) textlist);
2085 for (i=0; textlist[i] != (char *) NULL; i++)
2086 textlist[i]=DestroyString(textlist[i]);
2087 textlist=(char **) RelinquishMagickMemory(textlist);
2088 }
2089 text=DestroyString(text);
2090}
2091
2092/*
2093%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2094% %
2095% %
2096% %
2097+ X D i t h e r I m a g e %
2098% %
2099% %
2100% %
2101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2102%
2103% XDitherImage() dithers the reference image as required by the HP Color
2104% Recovery algorithm. The color values are quantized to 3 bits of red and
2105% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2106% standard colormap.
2107%
2108% The format of the XDitherImage method is:
2109%
cristy6710d842011-10-20 23:23:00 +00002110% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002111%
2112% A description of each parameter follows:
2113%
2114% o image: the image.
2115%
2116% o ximage: Specifies a pointer to a XImage structure; returned from
2117% XCreateImage.
2118%
cristy6710d842011-10-20 23:23:00 +00002119% o exception: return any errors or warnings in this structure.
2120%
cristy3ed852e2009-09-05 21:47:34 +00002121*/
cristy6710d842011-10-20 23:23:00 +00002122static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002123{
2124 static const short int
2125 dither_red[2][16]=
2126 {
2127 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2128 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2129 },
2130 dither_green[2][16]=
2131 {
2132 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2133 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2134 },
2135 dither_blue[2][16]=
2136 {
2137 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2138 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2139 };
2140
cristyc57f6942010-11-12 01:47:39 +00002141 CacheView
2142 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002143
2144 int
cristyc57f6942010-11-12 01:47:39 +00002145 value,
cristy3ed852e2009-09-05 21:47:34 +00002146 y;
2147
cristy101ab702011-10-13 13:06:32 +00002148 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002149 color;
cristy3ed852e2009-09-05 21:47:34 +00002150
2151 register char
2152 *q;
2153
cristy4c08aed2011-07-01 19:47:50 +00002154 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002155 *p;
2156
2157 register int
2158 i,
2159 j,
2160 x;
2161
2162 unsigned int
2163 scanline_pad;
2164
cristybb503372010-05-27 20:51:26 +00002165 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002166 pixel;
2167
2168 unsigned char
2169 *blue_map[2][16],
2170 *green_map[2][16],
2171 *red_map[2][16];
2172
2173 /*
2174 Allocate and initialize dither maps.
2175 */
2176 for (i=0; i < 2; i++)
2177 for (j=0; j < 16; j++)
2178 {
2179 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2180 sizeof(*red_map));
2181 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2182 sizeof(*green_map));
2183 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2184 sizeof(*blue_map));
2185 if ((red_map[i][j] == (unsigned char *) NULL) ||
2186 (green_map[i][j] == (unsigned char *) NULL) ||
2187 (blue_map[i][j] == (unsigned char *) NULL))
2188 {
cristyc38fbf52013-11-03 13:55:54 +00002189 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
2190 image->filename);
cristy3ed852e2009-09-05 21:47:34 +00002191 return;
2192 }
2193 }
2194 /*
2195 Initialize dither tables.
2196 */
2197 for (i=0; i < 2; i++)
2198 for (j=0; j < 16; j++)
2199 for (x=0; x < 256; x++)
2200 {
2201 value=x-16;
2202 if (x < 48)
2203 value=x/2+8;
2204 value+=dither_red[i][j];
2205 red_map[i][j][x]=(unsigned char)
2206 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2207 value=x-16;
2208 if (x < 48)
2209 value=x/2+8;
2210 value+=dither_green[i][j];
2211 green_map[i][j][x]=(unsigned char)
2212 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2213 value=x-32;
2214 if (x < 112)
2215 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002216 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002217 blue_map[i][j][x]=(unsigned char)
2218 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2219 }
2220 /*
2221 Dither image.
2222 */
2223 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002224 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002225 i=0;
2226 j=0;
2227 q=ximage->data;
cristy46ff2672012-12-14 15:32:26 +00002228 image_view=AcquireVirtualCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002229 for (y=0; y < (int) image->rows; y++)
2230 {
cristyc57f6942010-11-12 01:47:39 +00002231 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
cristy6710d842011-10-20 23:23:00 +00002232 exception);
cristy4c08aed2011-07-01 19:47:50 +00002233 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002234 break;
2235 for (x=0; x < (int) image->columns; x++)
2236 {
cristyada285b2012-07-07 19:00:46 +00002237 color.red=(double) ClampToQuantum((double) (red_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002238 (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002239 color.green=(double) ClampToQuantum((double) (green_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002240 (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002241 color.blue=(double) ClampToQuantum((double) (blue_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002242 (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002243 pixel=(size_t) (((size_t) color.red & 0xe0) |
2244 (((size_t) color.green & 0xe0) >> 3) |
2245 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002246 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002247 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002248 j++;
2249 if (j == 16)
2250 j=0;
2251 }
2252 q+=scanline_pad;
2253 i++;
2254 if (i == 2)
2255 i=0;
2256 }
cristyc57f6942010-11-12 01:47:39 +00002257 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002258 /*
2259 Free allocated memory.
2260 */
2261 for (i=0; i < 2; i++)
2262 for (j=0; j < 16; j++)
2263 {
2264 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2265 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2266 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2267 }
2268}
2269
2270/*
2271%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2272% %
2273% %
2274% %
2275% X D r a w I m a g e %
2276% %
2277% %
2278% %
2279%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2280%
2281% XDrawImage() draws a line on the image.
2282%
2283% The format of the XDrawImage method is:
2284%
cristy6710d842011-10-20 23:23:00 +00002285% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2286% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002287%
2288% A description of each parameter follows:
2289%
2290% o display: Specifies a connection to an X server; returned from
2291% XOpenDisplay.
2292%
2293% o pixel: Specifies a pointer to a XPixelInfo structure.
2294%
2295% o draw_info: Specifies a pointer to a XDrawInfo structure.
2296%
2297% o image: the image.
2298%
cristy6710d842011-10-20 23:23:00 +00002299% o exception: return any errors or warnings in this structure.
2300%
cristy3ed852e2009-09-05 21:47:34 +00002301*/
cristybcbda3f2011-09-03 13:01:22 +00002302MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy6710d842011-10-20 23:23:00 +00002303 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2304 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002305{
cristyc57f6942010-11-12 01:47:39 +00002306 CacheView
2307 *draw_view;
2308
cristy3ed852e2009-09-05 21:47:34 +00002309 GC
2310 draw_context;
2311
2312 Image
2313 *draw_image;
2314
2315 int
2316 x,
2317 y;
2318
cristyb0a657e2012-08-29 00:45:37 +00002319 PixelTrait
2320 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002321
2322 Pixmap
2323 draw_pixmap;
2324
2325 unsigned int
2326 depth,
2327 height,
2328 width;
2329
2330 Window
2331 root_window;
2332
2333 XGCValues
2334 context_values;
2335
2336 XImage
2337 *draw_ximage;
2338
2339 /*
2340 Initialize drawd image.
2341 */
2342 assert(display != (Display *) NULL);
2343 assert(pixel != (XPixelInfo *) NULL);
2344 assert(draw_info != (XDrawInfo *) NULL);
2345 assert(image != (Image *) NULL);
2346 if (image->debug != MagickFalse)
2347 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2348 /*
2349 Initialize drawd pixmap.
2350 */
2351 root_window=XRootWindow(display,XDefaultScreen(display));
2352 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2353 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2354 draw_info->height,depth);
2355 if (draw_pixmap == (Pixmap) NULL)
2356 return(MagickFalse);
2357 /*
2358 Initialize graphics info.
2359 */
cristybb503372010-05-27 20:51:26 +00002360 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002361 context_values.foreground=0;
2362 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002363 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002364 (GCBackground | GCForeground | GCLineWidth),&context_values);
2365 if (draw_context == (GC) NULL)
2366 return(MagickFalse);
2367 /*
2368 Clear pixmap.
2369 */
2370 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2371 draw_info->height);
2372 /*
2373 Draw line to pixmap.
2374 */
2375 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002376 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002377 if (draw_info->stipple != (Pixmap) NULL)
2378 {
2379 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2380 (void) XSetStipple(display,draw_context,draw_info->stipple);
2381 }
cristy3ed852e2009-09-05 21:47:34 +00002382 switch (draw_info->element)
2383 {
2384 case PointElement:
2385 default:
2386 {
2387 (void) XDrawLines(display,draw_pixmap,draw_context,
2388 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2389 CoordModeOrigin);
2390 break;
2391 }
2392 case LineElement:
2393 {
2394 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2395 draw_info->line_info.y1,draw_info->line_info.x2,
2396 draw_info->line_info.y2);
2397 break;
2398 }
2399 case RectangleElement:
2400 {
2401 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2402 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2403 (unsigned int) draw_info->rectangle_info.width,
2404 (unsigned int) draw_info->rectangle_info.height);
2405 break;
2406 }
2407 case FillRectangleElement:
2408 {
2409 (void) XFillRectangle(display,draw_pixmap,draw_context,
2410 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2411 (unsigned int) draw_info->rectangle_info.width,
2412 (unsigned int) draw_info->rectangle_info.height);
2413 break;
2414 }
2415 case CircleElement:
2416 case EllipseElement:
2417 {
2418 (void) XDrawArc(display,draw_pixmap,draw_context,
2419 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2420 (unsigned int) draw_info->rectangle_info.width,
2421 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2422 break;
2423 }
2424 case FillCircleElement:
2425 case FillEllipseElement:
2426 {
2427 (void) XFillArc(display,draw_pixmap,draw_context,
2428 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2429 (unsigned int) draw_info->rectangle_info.width,
2430 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2431 break;
2432 }
2433 case PolygonElement:
2434 {
2435 XPoint
2436 *coordinate_info;
2437
2438 coordinate_info=draw_info->coordinate_info;
2439 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2440 (int) draw_info->number_coordinates,CoordModeOrigin);
2441 (void) XDrawLine(display,draw_pixmap,draw_context,
2442 coordinate_info[draw_info->number_coordinates-1].x,
2443 coordinate_info[draw_info->number_coordinates-1].y,
2444 coordinate_info[0].x,coordinate_info[0].y);
2445 break;
2446 }
2447 case FillPolygonElement:
2448 {
2449 (void) XFillPolygon(display,draw_pixmap,draw_context,
2450 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2451 CoordModeOrigin);
2452 break;
2453 }
2454 }
2455 (void) XFreeGC(display,draw_context);
2456 /*
2457 Initialize X image.
2458 */
2459 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2460 draw_info->height,AllPlanes,ZPixmap);
2461 if (draw_ximage == (XImage *) NULL)
2462 return(MagickFalse);
2463 (void) XFreePixmap(display,draw_pixmap);
2464 /*
2465 Initialize draw image.
2466 */
cristy6710d842011-10-20 23:23:00 +00002467 draw_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002468 if (draw_image == (Image *) NULL)
2469 return(MagickFalse);
2470 draw_image->columns=draw_info->width;
2471 draw_image->rows=draw_info->height;
2472 /*
2473 Transfer drawn X image to image.
2474 */
2475 width=(unsigned int) image->columns;
2476 height=(unsigned int) image->rows;
2477 x=0;
2478 y=0;
2479 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +00002480 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
2481 (ssize_t) y,&draw_image->background_color,exception);
cristy6710d842011-10-20 23:23:00 +00002482 if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002483 return(MagickFalse);
cristy8a46d822012-08-28 23:32:39 +00002484 draw_image->alpha_trait=BlendPixelTrait;
cristy6f5395d2012-12-14 18:30:30 +00002485 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002486 for (y=0; y < (int) draw_image->rows; y++)
2487 {
cristyc57f6942010-11-12 01:47:39 +00002488 register int
cristy3ed852e2009-09-05 21:47:34 +00002489 x;
2490
cristy4c08aed2011-07-01 19:47:50 +00002491 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002492 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002493
cristyc57f6942010-11-12 01:47:39 +00002494 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2495 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002496 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002497 break;
cristyc57f6942010-11-12 01:47:39 +00002498 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002499 {
2500 if (XGetPixel(draw_ximage,x,y) == 0)
2501 {
2502 /*
2503 Set this pixel to the background color.
2504 */
cristy803640d2011-11-17 02:11:32 +00002505 SetPixelInfoPixel(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002506 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002507 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002508 }
2509 else
2510 {
2511 /*
2512 Set this pixel to the pen color.
2513 */
cristy4c08aed2011-07-01 19:47:50 +00002514 SetPixelRed(draw_image,ScaleShortToQuantum(
2515 pixel->pen_color.red),q);
2516 SetPixelGreen(draw_image,ScaleShortToQuantum(
2517 pixel->pen_color.green),q);
2518 SetPixelBlue(draw_image,ScaleShortToQuantum(
2519 pixel->pen_color.blue),q);
2520 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2521 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002522 }
cristyed231572011-07-14 02:18:59 +00002523 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002524 }
cristyc57f6942010-11-12 01:47:39 +00002525 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002526 break;
2527 }
cristyc57f6942010-11-12 01:47:39 +00002528 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002529 XDestroyImage(draw_ximage);
2530 /*
2531 Determine draw geometry.
2532 */
2533 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2534 if ((width != (unsigned int) draw_image->columns) ||
2535 (height != (unsigned int) draw_image->rows))
2536 {
2537 char
2538 image_geometry[MaxTextExtent];
2539
2540 /*
2541 Scale image.
2542 */
cristyb51dff52011-05-19 16:55:47 +00002543 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002544 width,height);
cristye941a752011-10-15 01:52:48 +00002545 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2546 exception);
cristy3ed852e2009-09-05 21:47:34 +00002547 }
2548 if (draw_info->degrees != 0.0)
2549 {
2550 Image
2551 *rotate_image;
2552
2553 int
2554 rotations;
2555
cristya19f1d72012-08-07 18:24:38 +00002556 double
cristy3ed852e2009-09-05 21:47:34 +00002557 normalized_degrees;
2558
2559 /*
2560 Rotate image.
2561 */
cristy6710d842011-10-20 23:23:00 +00002562 rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +00002563 if (rotate_image == (Image *) NULL)
2564 return(MagickFalse);
2565 draw_image=DestroyImage(draw_image);
2566 draw_image=rotate_image;
2567 /*
2568 Annotation is relative to the degree of rotation.
2569 */
2570 normalized_degrees=draw_info->degrees;
2571 while (normalized_degrees < -45.0)
2572 normalized_degrees+=360.0;
2573 for (rotations=0; normalized_degrees > 45.0; rotations++)
2574 normalized_degrees-=90.0;
2575 switch (rotations % 4)
2576 {
2577 default:
2578 case 0:
2579 break;
2580 case 1:
2581 {
2582 /*
2583 Rotate 90 degrees.
2584 */
2585 x=x-(int) draw_image->columns/2;
2586 y=y+(int) draw_image->columns/2;
2587 break;
2588 }
2589 case 2:
2590 {
2591 /*
2592 Rotate 180 degrees.
2593 */
2594 x=x-(int) draw_image->columns;
2595 break;
2596 }
2597 case 3:
2598 {
2599 /*
2600 Rotate 270 degrees.
2601 */
2602 x=x-(int) draw_image->columns/2;
2603 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2604 break;
2605 }
2606 }
2607 }
2608 /*
2609 Composite text onto the image.
2610 */
cristy6f5395d2012-12-14 18:30:30 +00002611 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002612 for (y=0; y < (int) draw_image->rows; y++)
2613 {
cristyc57f6942010-11-12 01:47:39 +00002614 register int
cristy3ed852e2009-09-05 21:47:34 +00002615 x;
2616
cristy4c08aed2011-07-01 19:47:50 +00002617 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002618 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002619
cristyc57f6942010-11-12 01:47:39 +00002620 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2621 exception);
cristyacd2ed22011-08-30 01:44:23 +00002622 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002623 break;
cristyc57f6942010-11-12 01:47:39 +00002624 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002625 {
cristy4c08aed2011-07-01 19:47:50 +00002626 if (GetPixelAlpha(image,q) != TransparentAlpha)
2627 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002628 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002629 }
cristyc57f6942010-11-12 01:47:39 +00002630 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002631 break;
2632 }
cristyc57f6942010-11-12 01:47:39 +00002633 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002634 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2635 if (draw_info->stencil == TransparentStencil)
cristy39172402012-03-30 13:04:39 +00002636 (void) CompositeImage(image,draw_image,CopyAlphaCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002637 (ssize_t) x,(ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002638 else
2639 {
cristyb0a657e2012-08-29 00:45:37 +00002640 alpha_trait=image->alpha_trait;
cristy39172402012-03-30 13:04:39 +00002641 (void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002642 (ssize_t) x,(ssize_t) y,exception);
cristyb0a657e2012-08-29 00:45:37 +00002643 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002644 }
2645 draw_image=DestroyImage(draw_image);
2646 return(MagickTrue);
2647}
2648
2649/*
2650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2651% %
2652% %
2653% %
2654% X E r r o r %
2655% %
2656% %
2657% %
2658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2659%
2660% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2661% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002662% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2663% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002664%
2665% The format of the XError function is:
2666%
cristybcbda3f2011-09-03 13:01:22 +00002667% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002668%
2669% A description of each parameter follows:
2670%
2671% o display: Specifies a pointer to the Display structure; returned from
2672% XOpenDisplay.
2673%
2674% o error: Specifies the error event.
2675%
2676*/
2677
2678#if defined(__cplusplus) || defined(c_plusplus)
2679extern "C" {
2680#endif
2681
2682MagickExport int XError(Display *display,XErrorEvent *error)
2683{
2684 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2685 assert(display != (Display *) NULL);
2686 assert(error != (XErrorEvent *) NULL);
2687 xerror_alert=MagickTrue;
2688 switch (error->request_code)
2689 {
2690 case X_GetGeometry:
2691 {
2692 if ((int) error->error_code == BadDrawable)
2693 return(MagickFalse);
2694 break;
2695 }
2696 case X_GetWindowAttributes:
2697 case X_QueryTree:
2698 {
2699 if ((int) error->error_code == BadWindow)
2700 return(MagickFalse);
2701 break;
2702 }
2703 case X_QueryColors:
2704 {
2705 if ((int) error->error_code == BadValue)
2706 return(MagickFalse);
2707 break;
2708 }
2709 }
2710 return(MagickTrue);
2711}
2712
2713#if defined(__cplusplus) || defined(c_plusplus)
2714}
2715#endif
2716
2717/*
2718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2719% %
2720% %
2721% %
2722% X F r e e R e s o u r c e s %
2723% %
2724% %
2725% %
2726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2727%
2728% XFreeResources() frees X11 resources.
2729%
2730% The format of the XFreeResources method is:
2731%
2732% void XFreeResources(Display *display,XVisualInfo *visual_info,
2733% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2734% XResourceInfo *resource_info,XWindowInfo *window_info)
2735% resource_info,window_info)
2736%
2737% A description of each parameter follows:
2738%
2739% o display: Specifies a connection to an X server; returned from
2740% XOpenDisplay.
2741%
2742% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2743% returned from XGetVisualInfo.
2744%
2745% o map_info: If map_type is specified, this structure is initialized
2746% with info from the Standard Colormap.
2747%
2748% o pixel: Specifies a pointer to a XPixelInfo structure.
2749%
2750% o font_info: Specifies a pointer to a XFontStruct structure.
2751%
2752% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2753%
2754% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2755%
2756*/
cristybcbda3f2011-09-03 13:01:22 +00002757MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002758 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2759 XResourceInfo *resource_info,XWindowInfo *window_info)
2760{
2761 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2762 assert(display != (Display *) NULL);
2763 assert(resource_info != (XResourceInfo *) NULL);
2764 if (window_info != (XWindowInfo *) NULL)
2765 {
2766 /*
2767 Free X image.
2768 */
2769 if (window_info->ximage != (XImage *) NULL)
2770 XDestroyImage(window_info->ximage);
2771 if (window_info->id != (Window) NULL)
2772 {
2773 /*
2774 Free destroy window and free cursors.
2775 */
2776 if (window_info->id != XRootWindow(display,visual_info->screen))
2777 (void) XDestroyWindow(display,window_info->id);
2778 if (window_info->annotate_context != (GC) NULL)
2779 (void) XFreeGC(display,window_info->annotate_context);
2780 if (window_info->highlight_context != (GC) NULL)
2781 (void) XFreeGC(display,window_info->highlight_context);
2782 if (window_info->widget_context != (GC) NULL)
2783 (void) XFreeGC(display,window_info->widget_context);
2784 if (window_info->cursor != (Cursor) NULL)
2785 (void) XFreeCursor(display,window_info->cursor);
2786 window_info->cursor=(Cursor) NULL;
2787 if (window_info->busy_cursor != (Cursor) NULL)
2788 (void) XFreeCursor(display,window_info->busy_cursor);
2789 window_info->busy_cursor=(Cursor) NULL;
2790 }
2791 }
2792 /*
2793 Free font.
2794 */
2795 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002796 {
2797 (void) XFreeFont(display,font_info);
2798 font_info=(XFontStruct *) NULL;
2799 }
cristy3ed852e2009-09-05 21:47:34 +00002800 if (map_info != (XStandardColormap *) NULL)
2801 {
2802 /*
2803 Free X Standard Colormap.
2804 */
2805 if (resource_info->map_type == (char *) NULL)
2806 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2807 (void) XFree((void *) map_info);
2808 }
2809 /*
2810 Free X visual info.
2811 */
2812 if (visual_info != (XVisualInfo *) NULL)
2813 (void) XFree((void *) visual_info);
2814 if (resource_info->close_server != MagickFalse)
2815 (void) XCloseDisplay(display);
2816}
2817
2818/*
2819%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2820% %
2821% %
2822% %
2823% X F r e e S t a n d a r d C o l o r m a p %
2824% %
2825% %
2826% %
2827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2828%
2829% XFreeStandardColormap() frees an X11 colormap.
2830%
2831% The format of the XFreeStandardColormap method is:
2832%
2833% void XFreeStandardColormap(Display *display,
2834% const XVisualInfo *visual_info,XStandardColormap *map_info,
2835% XPixelInfo *pixel)
2836%
2837% A description of each parameter follows:
2838%
2839% o display: Specifies a connection to an X server; returned from
2840% XOpenDisplay.
2841%
2842% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2843% returned from XGetVisualInfo.
2844%
2845% o map_info: If map_type is specified, this structure is initialized
2846% with info from the Standard Colormap.
2847%
2848% o pixel: Specifies a pointer to a XPixelInfo structure.
2849%
2850*/
cristybcbda3f2011-09-03 13:01:22 +00002851MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002852 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2853{
2854 /*
2855 Free colormap.
2856 */
2857 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2858 assert(display != (Display *) NULL);
2859 assert(visual_info != (XVisualInfo *) NULL);
2860 assert(map_info != (XStandardColormap *) NULL);
2861 (void) XFlush(display);
2862 if (map_info->colormap != (Colormap) NULL)
2863 {
2864 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2865 (void) XFreeColormap(display,map_info->colormap);
2866 else
2867 if (pixel != (XPixelInfo *) NULL)
2868 if ((visual_info->klass != TrueColor) &&
2869 (visual_info->klass != DirectColor))
2870 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2871 (int) pixel->colors,0);
2872 }
2873 map_info->colormap=(Colormap) NULL;
2874 if (pixel != (XPixelInfo *) NULL)
2875 {
cristyf2faecf2010-05-28 19:19:36 +00002876 if (pixel->pixels != (unsigned long *) NULL)
2877 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2878 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002879 }
2880}
2881
2882/*
2883%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2884% %
2885% %
2886% %
2887% X G e t A n n o t a t e I n f o %
2888% %
2889% %
2890% %
2891%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2892%
2893% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2894%
2895% The format of the XGetAnnotateInfo method is:
2896%
2897% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2898%
2899% A description of each parameter follows:
2900%
2901% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2902%
2903*/
cristybcbda3f2011-09-03 13:01:22 +00002904MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002905{
2906 /*
2907 Initialize annotate structure.
2908 */
2909 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2910 assert(annotate_info != (XAnnotateInfo *) NULL);
2911 annotate_info->x=0;
2912 annotate_info->y=0;
2913 annotate_info->width=0;
2914 annotate_info->height=0;
2915 annotate_info->stencil=ForegroundStencil;
2916 annotate_info->degrees=0.0;
2917 annotate_info->font_info=(XFontStruct *) NULL;
2918 annotate_info->text=(char *) NULL;
2919 *annotate_info->geometry='\0';
2920 annotate_info->previous=(XAnnotateInfo *) NULL;
2921 annotate_info->next=(XAnnotateInfo *) NULL;
2922 (void) XSupportsLocale();
2923 (void) XSetLocaleModifiers("");
2924}
2925
2926/*
2927%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2928% %
2929% %
2930% %
2931% X G e t M a p I n f o %
2932% %
2933% %
2934% %
2935%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2936%
2937% XGetMapInfo() initializes the XStandardColormap structure.
2938%
2939% The format of the XStandardColormap method is:
2940%
2941% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2942% XStandardColormap *map_info)
2943%
2944% A description of each parameter follows:
2945%
2946% o colormap: Specifies the ID of the X server colormap.
2947%
2948% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2949% returned from XGetVisualInfo.
2950%
2951% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2952%
2953*/
cristybcbda3f2011-09-03 13:01:22 +00002954MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002955 const Colormap colormap,XStandardColormap *map_info)
2956{
2957 /*
2958 Initialize map info.
2959 */
2960 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2961 assert(visual_info != (XVisualInfo *) NULL);
2962 assert(map_info != (XStandardColormap *) NULL);
2963 map_info->colormap=colormap;
2964 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002965 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002966 if (map_info->red_max != 0)
2967 while ((map_info->red_max & 0x01) == 0)
2968 {
2969 map_info->red_max>>=1;
2970 map_info->red_mult<<=1;
2971 }
2972 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002973 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002974 if (map_info->green_max != 0)
2975 while ((map_info->green_max & 0x01) == 0)
2976 {
2977 map_info->green_max>>=1;
2978 map_info->green_mult<<=1;
2979 }
2980 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002981 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002982 if (map_info->blue_max != 0)
2983 while ((map_info->blue_max & 0x01) == 0)
2984 {
2985 map_info->blue_max>>=1;
2986 map_info->blue_mult<<=1;
2987 }
2988 map_info->base_pixel=0;
2989}
2990
2991/*
2992%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2993% %
2994% %
2995% %
2996% X G e t P i x e l I n f o %
2997% %
2998% %
2999% %
3000%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3001%
cristy101ab702011-10-13 13:06:32 +00003002% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00003003%
cristy4c08aed2011-07-01 19:47:50 +00003004% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00003005%
cristy4c08aed2011-07-01 19:47:50 +00003006% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00003007% const XStandardColormap *map_info,const XResourceInfo *resource_info,
3008% Image *image,XPixelInfo *pixel)
3009% pixel)
3010%
3011% A description of each parameter follows:
3012%
3013% o display: Specifies a connection to an X server; returned from
3014% XOpenDisplay.
3015%
3016% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3017% returned from XGetVisualInfo.
3018%
3019% o map_info: If map_type is specified, this structure is initialized
3020% with info from the Standard Colormap.
3021%
3022% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3023%
3024% o image: the image.
3025%
3026% o pixel: Specifies a pointer to a XPixelInfo structure.
3027%
3028*/
cristybcbda3f2011-09-03 13:01:22 +00003029MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003030 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3031 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3032{
3033 static const char
3034 *PenColors[MaxNumberPens]=
3035 {
3036 "#000000000000", /* black */
3037 "#00000000ffff", /* blue */
3038 "#0000ffffffff", /* cyan */
3039 "#0000ffff0000", /* green */
3040 "#bdbdbdbdbdbd", /* gray */
3041 "#ffff00000000", /* red */
3042 "#ffff0000ffff", /* magenta */
3043 "#ffffffff0000", /* yellow */
3044 "#ffffffffffff", /* white */
3045 "#bdbdbdbdbdbd", /* gray */
3046 "#bdbdbdbdbdbd" /* gray */
3047 };
3048
3049 Colormap
3050 colormap;
3051
cristybcdf5672012-05-24 22:58:54 +00003052 extern const char
3053 BorderColor[],
3054 ForegroundColor[];
3055
cristybb503372010-05-27 20:51:26 +00003056 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003057 i;
3058
3059 Status
3060 status;
3061
3062 unsigned int
3063 packets;
3064
3065 /*
3066 Initialize pixel info.
3067 */
3068 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3069 assert(display != (Display *) NULL);
3070 assert(visual_info != (XVisualInfo *) NULL);
3071 assert(map_info != (XStandardColormap *) NULL);
3072 assert(resource_info != (XResourceInfo *) NULL);
3073 assert(pixel != (XPixelInfo *) NULL);
3074 pixel->colors=0;
3075 if (image != (Image *) NULL)
3076 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003077 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003078 packets=(unsigned int)
3079 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003080 if (pixel->pixels != (unsigned long *) NULL)
3081 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3082 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003083 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003084 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003085 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3086 image->filename);
3087 /*
3088 Set foreground color.
3089 */
3090 colormap=map_info->colormap;
3091 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3092 &pixel->foreground_color);
3093 status=XParseColor(display,colormap,resource_info->foreground_color,
3094 &pixel->foreground_color);
3095 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003096 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003097 resource_info->foreground_color);
3098 pixel->foreground_color.pixel=
3099 XStandardPixel(map_info,&pixel->foreground_color);
3100 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3101 /*
3102 Set background color.
3103 */
3104 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3105 status=XParseColor(display,colormap,resource_info->background_color,
3106 &pixel->background_color);
3107 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003108 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003109 resource_info->background_color);
3110 pixel->background_color.pixel=
3111 XStandardPixel(map_info,&pixel->background_color);
3112 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3113 /*
3114 Set border color.
3115 */
3116 (void) XParseColor(display,colormap,(char *) BorderColor,
3117 &pixel->border_color);
3118 status=XParseColor(display,colormap,resource_info->border_color,
3119 &pixel->border_color);
3120 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003121 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003122 resource_info->border_color);
3123 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3124 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3125 /*
3126 Set matte color.
3127 */
3128 pixel->matte_color=pixel->background_color;
3129 if (resource_info->matte_color != (char *) NULL)
3130 {
3131 /*
3132 Matte color is specified as a X resource or command line argument.
3133 */
3134 status=XParseColor(display,colormap,resource_info->matte_color,
3135 &pixel->matte_color);
3136 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003137 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003138 resource_info->matte_color);
3139 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3140 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3141 }
3142 /*
3143 Set highlight color.
3144 */
cristy5467fcf2014-05-18 17:20:55 +00003145 pixel->highlight_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003146 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3147 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
cristy5467fcf2014-05-18 17:20:55 +00003148 pixel->highlight_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003149 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3150 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
cristy5467fcf2014-05-18 17:20:55 +00003151 pixel->highlight_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003152 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3153 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
cristy5467fcf2014-05-18 17:20:55 +00003154 pixel->highlight_color.pixel=XStandardPixel(map_info,&pixel->highlight_color);
cristy3ed852e2009-09-05 21:47:34 +00003155 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3156 /*
3157 Set shadow color.
3158 */
cristya19f1d72012-08-07 18:24:38 +00003159 pixel->shadow_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003160 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003161 pixel->shadow_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003162 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003163 pixel->shadow_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003164 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3165 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3166 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3167 /*
3168 Set depth color.
3169 */
cristya19f1d72012-08-07 18:24:38 +00003170 pixel->depth_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003171 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003172 pixel->depth_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003173 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003174 pixel->depth_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003175 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3176 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3177 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3178 /*
3179 Set trough color.
3180 */
cristya19f1d72012-08-07 18:24:38 +00003181 pixel->trough_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003182 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003183 pixel->trough_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003184 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003185 pixel->trough_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003186 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3187 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3188 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3189 /*
3190 Set pen color.
3191 */
3192 for (i=0; i < MaxNumberPens; i++)
3193 {
3194 (void) XParseColor(display,colormap,(char *) PenColors[i],
3195 &pixel->pen_colors[i]);
3196 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3197 &pixel->pen_colors[i]);
3198 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003199 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003200 resource_info->pen_colors[i]);
3201 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3202 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3203 }
3204 pixel->box_color=pixel->background_color;
3205 pixel->pen_color=pixel->foreground_color;
3206 pixel->box_index=0;
3207 pixel->pen_index=1;
3208 if (image != (Image *) NULL)
3209 {
3210 if ((resource_info->gamma_correct != MagickFalse) &&
3211 (image->gamma != 0.0))
3212 {
3213 GeometryInfo
3214 geometry_info;
3215
3216 MagickStatusType
3217 flags;
3218
3219 /*
3220 Initialize map relative to display and image gamma.
3221 */
3222 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3223 red_gamma=geometry_info.rho;
3224 green_gamma=geometry_info.sigma;
3225 if ((flags & SigmaValue) == 0)
3226 green_gamma=red_gamma;
3227 blue_gamma=geometry_info.xi;
3228 if ((flags & XiValue) == 0)
3229 blue_gamma=red_gamma;
3230 red_gamma*=image->gamma;
3231 green_gamma*=image->gamma;
3232 blue_gamma*=image->gamma;
3233 }
3234 if (image->storage_class == PseudoClass)
3235 {
3236 /*
3237 Initialize pixel array for images of type PseudoClass.
3238 */
cristybb503372010-05-27 20:51:26 +00003239 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003240 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003241 for (i=0; i < MaxNumberPens; i++)
3242 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3243 pixel->colors+=MaxNumberPens;
3244 }
3245 }
3246}
3247
3248/*
3249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3250% %
3251% %
3252% %
3253% X G e t R e s o u r c e C l a s s %
3254% %
3255% %
3256% %
3257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3258%
3259% XGetResourceClass() queries the X server for the specified resource name or
3260% class. If the resource name or class is not defined in the database, the
3261% supplied default value is returned.
3262%
3263% The format of the XGetResourceClass method is:
3264%
3265% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3266% const char *keyword,char *resource_default)
3267%
3268% A description of each parameter follows:
3269%
3270% o database: Specifies a resource database; returned from
3271% XrmGetStringDatabase.
3272%
3273% o client_name: Specifies the application name used to retrieve resource
3274% info from the X server database.
3275%
3276% o keyword: Specifies the keyword of the value being retrieved.
3277%
3278% o resource_default: Specifies the default value to return if the query
3279% fails to find the specified keyword/class.
3280%
3281*/
3282MagickExport char *XGetResourceClass(XrmDatabase database,
3283 const char *client_name,const char *keyword,char *resource_default)
3284{
3285 char
3286 resource_class[MaxTextExtent],
3287 resource_name[MaxTextExtent];
3288
3289 static char
3290 *resource_type;
3291
3292 Status
3293 status;
3294
3295 XrmValue
3296 resource_value;
3297
3298 if (database == (XrmDatabase) NULL)
3299 return(resource_default);
3300 *resource_name='\0';
3301 *resource_class='\0';
3302 if (keyword != (char *) NULL)
3303 {
3304 int
3305 c,
3306 k;
3307
3308 /*
3309 Initialize resource keyword and class.
3310 */
cristyb51dff52011-05-19 16:55:47 +00003311 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003312 client_name,keyword);
3313 c=(int) (*client_name);
3314 if ((c >= XK_a) && (c <= XK_z))
3315 c-=(XK_a-XK_A);
3316 else
3317 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3318 c-=(XK_agrave-XK_Agrave);
3319 else
3320 if ((c >= XK_oslash) && (c <= XK_thorn))
3321 c-=(XK_oslash-XK_Ooblique);
3322 k=(int) (*keyword);
3323 if ((k >= XK_a) && (k <= XK_z))
3324 k-=(XK_a-XK_A);
3325 else
3326 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3327 k-=(XK_agrave-XK_Agrave);
3328 else
3329 if ((k >= XK_oslash) && (k <= XK_thorn))
3330 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003331 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003332 client_name+1,k,keyword+1);
3333 }
3334 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3335 &resource_value);
3336 if (status == False)
3337 return(resource_default);
3338 return(resource_value.addr);
3339}
3340
3341/*
3342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3343% %
3344% %
3345% %
3346% X G e t R e s o u r c e D a t a b a s e %
3347% %
3348% %
3349% %
3350%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3351%
3352% XGetResourceDatabase() creates a new resource database and initializes it.
3353%
3354% The format of the XGetResourceDatabase method is:
3355%
3356% XrmDatabase XGetResourceDatabase(Display *display,
3357% const char *client_name)
3358%
3359% A description of each parameter follows:
3360%
3361% o database: XGetResourceDatabase() returns the database after it is
3362% initialized.
3363%
3364% o display: Specifies a connection to an X server; returned from
3365% XOpenDisplay.
3366%
3367% o client_name: Specifies the application name used to retrieve resource
3368% info from the X server database.
3369%
3370*/
3371MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3372 const char *client_name)
3373{
3374 char
3375 filename[MaxTextExtent];
3376
3377 int
3378 c;
3379
3380 register const char
3381 *p;
3382
3383 XrmDatabase
3384 resource_database,
3385 server_database;
3386
3387 if (display == (Display *) NULL)
3388 return((XrmDatabase) NULL);
3389 assert(client_name != (char *) NULL);
3390 /*
3391 Initialize resource database.
3392 */
3393 XrmInitialize();
3394 (void) XGetDefault(display,(char *) client_name,"dummy");
3395 resource_database=XrmGetDatabase(display);
3396 /*
3397 Combine application database.
3398 */
3399 if (client_name != (char *) NULL)
3400 {
3401 /*
3402 Get basename of client.
3403 */
3404 p=client_name+(strlen(client_name)-1);
3405 while ((p > client_name) && (*p != '/'))
3406 p--;
3407 if (*p == '/')
3408 client_name=p+1;
3409 }
3410 c=(int) (*client_name);
3411 if ((c >= XK_a) && (c <= XK_z))
3412 c-=(XK_a-XK_A);
3413 else
3414 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3415 c-=(XK_agrave-XK_Agrave);
3416 else
3417 if ((c >= XK_oslash) && (c <= XK_thorn))
3418 c-=(XK_oslash-XK_Ooblique);
3419#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003420 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003421 X11_APPLICATION_PATH,c,client_name+1);
3422 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3423#endif
3424 if (XResourceManagerString(display) != (char *) NULL)
3425 {
3426 /*
3427 Combine server database.
3428 */
3429 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3430 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3431 }
3432 /*
3433 Merge user preferences database.
3434 */
3435#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003436 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003437 X11_PREFERENCES_PATH,client_name);
3438 ExpandFilename(filename);
3439 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3440#endif
3441 return(resource_database);
3442}
3443
3444/*
3445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3446% %
3447% %
3448% %
3449% X G e t R e s o u r c e I n f o %
3450% %
3451% %
3452% %
3453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3454%
3455% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3456%
3457% The format of the XGetResourceInfo method is:
3458%
3459% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3460% const char *client_name,XResourceInfo *resource_info)
3461%
3462% A description of each parameter follows:
3463%
3464% o image_info: the image info.
3465%
3466% o database: Specifies a resource database; returned from
3467% XrmGetStringDatabase.
3468%
3469% o client_name: Specifies the application name used to retrieve
3470% resource info from the X server database.
3471%
3472% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3473%
3474*/
3475MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3476 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3477{
3478 char
cristy00976d82011-02-20 20:31:28 +00003479 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003480 *resource_value;
3481
cristybcdf5672012-05-24 22:58:54 +00003482 extern const char
3483 BorderColor[],
3484 ForegroundColor[];
3485
cristy3ed852e2009-09-05 21:47:34 +00003486 /*
3487 Initialize resource info fields.
3488 */
3489 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3490 assert(resource_info != (XResourceInfo *) NULL);
3491 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3492 resource_info->resource_database=database;
3493 resource_info->image_info=(ImageInfo *) image_info;
3494 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3495 XMagickProgressMonitor,(void *) NULL);
3496 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3497 resource_info->close_server=MagickTrue;
3498 resource_info->client_name=AcquireString(client_name);
3499 resource_value=XGetResourceClass(database,client_name,"backdrop",
3500 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003501 resource_info->backdrop=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003502 resource_info->background_color=XGetResourceInstance(database,client_name,
3503 "background",(char *) "#d6d6d6d6d6d6");
3504 resource_info->border_color=XGetResourceInstance(database,client_name,
3505 "borderColor",BorderColor);
3506 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3507 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003508 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3509 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003510 resource_value=XGetResourceClass(database,client_name,"colormap",
3511 (char *) "shared");
3512 resource_info->colormap=UndefinedColormap;
3513 if (LocaleCompare("private",resource_value) == 0)
3514 resource_info->colormap=PrivateColormap;
3515 if (LocaleCompare("shared",resource_value) == 0)
3516 resource_info->colormap=SharedColormap;
3517 if (resource_info->colormap == UndefinedColormap)
cristyc38fbf52013-11-03 13:55:54 +00003518 ThrowXWindowException(OptionError,"UnrecognizedColormapType",
cristy3ed852e2009-09-05 21:47:34 +00003519 resource_value);
3520 resource_value=XGetResourceClass(database,client_name,
3521 "colorRecovery",(char *) "False");
anthony6f201312012-03-30 04:08:15 +00003522 resource_info->color_recovery=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003523 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3524 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003525 resource_info->confirm_exit=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003526 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3527 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003528 resource_info->confirm_edit=IsStringTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003529 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003530 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003531 resource_info->display_gamma=XGetResourceClass(database,client_name,
3532 "displayGamma",(char *) "2.2");
3533 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3534 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003535 resource_info->display_warnings=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003536 resource_info->font=XGetResourceClass(database,client_name,"font",
3537 (char *) NULL);
3538 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3539 resource_info->font);
3540 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3541 (char *) "fixed");
3542 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3543 (char *) "variable");
3544 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3545 (char *) "5x8");
3546 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3547 (char *) "6x10");
3548 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3549 (char *) "7x13bold");
3550 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3551 (char *) "8x13bold");
3552 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3553 (char *) "9x15bold");
3554 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3555 (char *) "10x20");
3556 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3557 (char *) "12x24");
3558 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3559 (char *) "fixed");
3560 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3561 (char *) "fixed");
3562 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3563 "foreground",ForegroundColor);
3564 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
cristy8bc259b2012-06-21 23:53:15 +00003565 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003566 resource_info->gamma_correct=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003567 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3568 client_name,"geometry",(char *) NULL));
3569 resource_value=XGetResourceClass(database,client_name,"gravity",
3570 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003571 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003572 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003573 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3574 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003575 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3576 "iconGeometry",(char *) NULL);
3577 resource_value=XGetResourceClass(database,client_name,"iconic",
3578 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003579 resource_info->iconic=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003580 resource_value=XGetResourceClass(database,client_name,"immutable",
3581 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3582 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003583 resource_info->immutable=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003584 resource_value=XGetResourceClass(database,client_name,"magnify",
3585 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003586 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003587 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3588 (char *) NULL);
3589 resource_info->matte_color=XGetResourceInstance(database,client_name,
3590 "mattecolor",(char *) NULL);
3591 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3592 "name",(char *) NULL));
3593 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3594 (char *) "black");
3595 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3596 (char *) "blue");
3597 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3598 (char *) "cyan");
3599 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3600 (char *) "green");
3601 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3602 (char *) "gray");
3603 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3604 (char *) "red");
3605 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3606 (char *) "magenta");
3607 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3608 (char *) "yellow");
3609 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3610 (char *) "white");
3611 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3612 (char *) "gray");
3613 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3614 (char *) "gray");
3615 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003616 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003617 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003618 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003619 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3620 "font",(char *) "fixed");
3621 resource_info->text_font=XGetResourceClass(database,client_name,
3622 "textFontList",resource_info->text_font);
3623 resource_info->title=XGetResourceClass(database,client_name,"title",
3624 (char *) NULL);
3625 resource_value=XGetResourceClass(database,client_name,"undoCache",
cristy92befbd2012-09-16 14:08:12 +00003626 (char *) "256");
cristye27293e2009-12-18 02:53:20 +00003627 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003628 resource_value=XGetResourceClass(database,client_name,"update",
3629 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003630 resource_info->update=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003631 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3632 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003633 resource_info->use_pixmap=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003634 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3635 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003636 resource_info->use_shared_memory=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003637 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3638 (char *) NULL);
3639 resource_info->window_group=XGetResourceClass(database,client_name,
3640 "windowGroup",(char *) NULL);
3641 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3642 (char *) NULL);
3643 resource_info->write_filename=XGetResourceClass(database,client_name,
3644 "writeFilename",(char *) NULL);
3645}
3646
3647/*
3648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3649% %
3650% %
3651% %
3652% X G e t R e s o u r c e I n s t a n c e %
3653% %
3654% %
3655% %
3656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3657%
3658% XGetResourceInstance() queries the X server for the specified resource name.
3659% If the resource name is not defined in the database, the supplied default
3660% value is returned.
3661%
3662% The format of the XGetResourceInstance method is:
3663%
3664% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3665% const char *keyword,const char *resource_default)
3666%
3667% A description of each parameter follows:
3668%
3669% o database: Specifies a resource database; returned from
3670% XrmGetStringDatabase.
3671%
3672% o client_name: Specifies the application name used to retrieve
3673% resource info from the X server database.
3674%
3675% o keyword: Specifies the keyword of the value being retrieved.
3676%
3677% o resource_default: Specifies the default value to return if the query
3678% fails to find the specified keyword/class.
3679%
3680*/
3681MagickExport char *XGetResourceInstance(XrmDatabase database,
3682 const char *client_name,const char *keyword,const char *resource_default)
3683{
3684 char
3685 *resource_type,
3686 resource_name[MaxTextExtent];
3687
3688 Status
3689 status;
3690
3691 XrmValue
3692 resource_value;
3693
3694 if (database == (XrmDatabase) NULL)
3695 return((char *) resource_default);
3696 *resource_name='\0';
3697 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003698 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003699 keyword);
3700 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3701 &resource_value);
3702 if (status == False)
3703 return((char *) resource_default);
3704 return(resource_value.addr);
3705}
3706
3707/*
3708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3709% %
3710% %
3711% %
3712% X G e t S c r e e n D e n s i t y %
3713% %
3714% %
3715% %
3716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3717%
3718% XGetScreenDensity() returns the density of the X server screen in
3719% dots-per-inch.
3720%
3721% The format of the XGetScreenDensity method is:
3722%
3723% char *XGetScreenDensity(Display *display)
3724%
3725% A description of each parameter follows:
3726%
3727% o density: XGetScreenDensity() returns the density of the X screen in
3728% dots-per-inch.
3729%
3730% o display: Specifies a connection to an X server; returned from
3731% XOpenDisplay.
3732%
3733*/
3734MagickExport char *XGetScreenDensity(Display *display)
3735{
3736 char
3737 density[MaxTextExtent];
3738
3739 double
3740 x_density,
3741 y_density;
3742
3743 /*
3744 Set density as determined by screen size.
3745 */
3746 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3747 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3748 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3749 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003750 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003751 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003752 return(GetPageGeometry(density));
3753}
3754
3755/*
3756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3757% %
3758% %
3759% %
3760+ X G e t S u b w i n d o w %
3761% %
3762% %
3763% %
3764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3765%
3766% XGetSubwindow() returns the subwindow of a window chosen the user with the
3767% pointer and a button press.
3768%
3769% The format of the XGetSubwindow method is:
3770%
3771% Window XGetSubwindow(Display *display,Window window,int x,int y)
3772%
3773% A description of each parameter follows:
3774%
3775% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3776% otherwise the subwindow is returned.
3777%
3778% o display: Specifies a connection to an X server; returned from
3779% XOpenDisplay.
3780%
3781% o window: Specifies a pointer to a Window.
3782%
3783% o x: the x coordinate of the pointer relative to the origin of the
3784% window.
3785%
3786% o y: the y coordinate of the pointer relative to the origin of the
3787% window.
3788%
cristy3ed852e2009-09-05 21:47:34 +00003789*/
3790static Window XGetSubwindow(Display *display,Window window,int x,int y)
3791{
3792 int
3793 x_offset,
3794 y_offset;
3795
3796 Status
3797 status;
3798
3799 Window
3800 source_window,
3801 target_window;
3802
3803 assert(display != (Display *) NULL);
3804 source_window=XRootWindow(display,XDefaultScreen(display));
3805 if (window == (Window) NULL)
3806 return(source_window);
3807 target_window=window;
3808 for ( ; ; )
3809 {
3810 status=XTranslateCoordinates(display,source_window,window,x,y,
3811 &x_offset,&y_offset,&target_window);
3812 if (status != True)
3813 break;
3814 if (target_window == (Window) NULL)
3815 break;
3816 source_window=window;
3817 window=target_window;
3818 x=x_offset;
3819 y=y_offset;
3820 }
3821 if (target_window == (Window) NULL)
3822 target_window=window;
3823 return(target_window);
3824}
3825
3826/*
3827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3828% %
3829% %
3830% %
3831% X G e t W i n d o w C o l o r %
3832% %
3833% %
3834% %
3835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3836%
3837% XGetWindowColor() returns the color of a pixel interactively chosen from the
3838% X server.
3839%
3840% The format of the XGetWindowColor method is:
3841%
3842% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003843% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003844%
3845% A description of each parameter follows:
3846%
3847% o display: Specifies a connection to an X server; returned from
3848% XOpenDisplay.
3849%
3850% o windows: Specifies a pointer to a XWindows structure.
3851%
3852% o name: the name of the color if found in the X Color Database is
3853% returned in this character string.
3854%
cristy6710d842011-10-20 23:23:00 +00003855% o exception: return any errors or warnings in this structure.
3856%
cristy3ed852e2009-09-05 21:47:34 +00003857*/
cristybcbda3f2011-09-03 13:01:22 +00003858MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003859 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003860{
3861 int
3862 x,
3863 y;
3864
cristy101ab702011-10-13 13:06:32 +00003865 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003866 pixel;
3867
3868 RectangleInfo
3869 crop_info;
3870
3871 Status
3872 status;
3873
3874 Window
3875 child,
3876 client_window,
3877 root_window,
3878 target_window;
3879
3880 XColor
3881 color;
3882
3883 XImage
3884 *ximage;
3885
3886 XWindowAttributes
3887 window_attributes;
3888
3889 /*
3890 Choose a pixel from the X server.
3891 */
3892 assert(display != (Display *) NULL);
3893 assert(name != (char *) NULL);
3894 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3895 *name='\0';
3896 target_window=XSelectWindow(display,&crop_info);
3897 if (target_window == (Window) NULL)
3898 return(MagickFalse);
3899 root_window=XRootWindow(display,XDefaultScreen(display));
3900 client_window=target_window;
3901 if (target_window != root_window)
3902 {
3903 unsigned int
3904 d;
3905
3906 /*
3907 Get client window.
3908 */
3909 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3910 if (status != False)
3911 {
3912 client_window=XClientWindow(display,target_window);
3913 target_window=client_window;
3914 }
3915 }
3916 /*
3917 Verify window is viewable.
3918 */
3919 status=XGetWindowAttributes(display,target_window,&window_attributes);
3920 if ((status == False) || (window_attributes.map_state != IsViewable))
3921 return(MagickFalse);
3922 /*
3923 Get window X image.
3924 */
3925 (void) XTranslateCoordinates(display,root_window,target_window,
3926 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3927 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3928 if (ximage == (XImage *) NULL)
3929 return(MagickFalse);
3930 color.pixel=XGetPixel(ximage,0,0);
3931 XDestroyImage(ximage);
3932 /*
3933 Match color against the color database.
3934 */
3935 (void) XQueryColor(display,window_attributes.colormap,&color);
cristye42f6582012-02-11 17:59:50 +00003936 pixel.red=(double) ScaleShortToQuantum(color.red);
3937 pixel.green=(double) ScaleShortToQuantum(color.green);
3938 pixel.blue=(double) ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003939 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003940 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003941 exception);
cristy3ed852e2009-09-05 21:47:34 +00003942 return(MagickTrue);
3943}
3944
3945/*
3946%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3947% %
3948% %
3949% %
3950+ X G e t W i n d o w I m a g e %
3951% %
3952% %
3953% %
3954%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3955%
3956% XGetWindowImage() reads an image from the target X window and returns it.
3957% XGetWindowImage() optionally descends the window hierarchy and overlays the
3958% target image with each child image in an optimized fashion. Any child
3959% window that have the same visual, colormap, and are contained by its parent
3960% are exempted.
3961%
3962% The format of the XGetWindowImage method is:
3963%
3964% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003965% const unsigned int borders,const unsigned int level,
3966% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003967%
3968% A description of each parameter follows:
3969%
3970% o display: Specifies a connection to an X server; returned from
3971% XOpenDisplay.
3972%
3973% o window: Specifies the window to obtain the image from.
3974%
3975% o borders: Specifies whether borders pixels are to be saved with
3976% the image.
3977%
3978% o level: Specifies an unsigned integer representing the level of
3979% decent in the window hierarchy. This value must be zero or one on
3980% the initial call to XGetWindowImage. A value of zero returns after
3981% one call. A value of one causes the function to descend the window
3982% hierarchy and overlay the target image with each subwindow image.
3983%
cristy6710d842011-10-20 23:23:00 +00003984% o exception: return any errors or warnings in this structure.
3985%
cristy3ed852e2009-09-05 21:47:34 +00003986*/
3987static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003988 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003989{
3990 typedef struct _ColormapInfo
3991 {
3992 Colormap
3993 colormap;
3994
3995 XColor
3996 *colors;
3997
3998 struct _ColormapInfo
3999 *next;
4000 } ColormapInfo;
4001
4002 typedef struct _WindowInfo
4003 {
4004 Window
4005 window,
4006 parent;
4007
4008 Visual
4009 *visual;
4010
4011 Colormap
4012 colormap;
4013
4014 XSegment
4015 bounds;
4016
4017 RectangleInfo
4018 crop_info;
4019 } WindowInfo;
4020
cristy3ed852e2009-09-05 21:47:34 +00004021 int
4022 display_height,
4023 display_width,
4024 id,
4025 x_offset,
4026 y_offset;
4027
cristy4c08aed2011-07-01 19:47:50 +00004028 Quantum
4029 index;
4030
cristy3ed852e2009-09-05 21:47:34 +00004031 RectangleInfo
4032 crop_info;
4033
cristy3ed852e2009-09-05 21:47:34 +00004034 register int
4035 i;
4036
4037 static ColormapInfo
4038 *colormap_info = (ColormapInfo *) NULL;
4039
4040 static int
4041 max_windows = 0,
4042 number_windows = 0;
4043
4044 static WindowInfo
4045 *window_info;
4046
4047 Status
4048 status;
4049
4050 Window
4051 child,
4052 root_window;
4053
4054 XWindowAttributes
4055 window_attributes;
4056
4057 /*
4058 Verify window is viewable.
4059 */
4060 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4061 assert(display != (Display *) NULL);
4062 status=XGetWindowAttributes(display,window,&window_attributes);
4063 if ((status == False) || (window_attributes.map_state != IsViewable))
4064 return((Image *) NULL);
4065 /*
4066 Cropping rectangle is relative to root window.
4067 */
4068 root_window=XRootWindow(display,XDefaultScreen(display));
4069 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4070 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004071 crop_info.x=(ssize_t) x_offset;
4072 crop_info.y=(ssize_t) y_offset;
4073 crop_info.width=(size_t) window_attributes.width;
4074 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004075 if (borders != MagickFalse)
4076 {
4077 /*
4078 Include border in image.
4079 */
cristybb503372010-05-27 20:51:26 +00004080 crop_info.x-=(ssize_t) window_attributes.border_width;
4081 crop_info.y-=(ssize_t) window_attributes.border_width;
4082 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4083 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004084 }
4085 /*
4086 Crop to root window.
4087 */
4088 if (crop_info.x < 0)
4089 {
4090 crop_info.width+=crop_info.x;
4091 crop_info.x=0;
4092 }
4093 if (crop_info.y < 0)
4094 {
4095 crop_info.height+=crop_info.y;
4096 crop_info.y=0;
4097 }
4098 display_width=XDisplayWidth(display,XDefaultScreen(display));
4099 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004100 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004101 display_height=XDisplayHeight(display,XDefaultScreen(display));
4102 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004103 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004104 /*
4105 Initialize window info attributes.
4106 */
4107 if (number_windows >= max_windows)
4108 {
4109 /*
4110 Allocate or resize window info buffer.
4111 */
4112 max_windows+=1024;
4113 if (window_info == (WindowInfo *) NULL)
4114 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4115 sizeof(*window_info));
4116 else
4117 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4118 max_windows,sizeof(*window_info));
4119 }
4120 if (window_info == (WindowInfo *) NULL)
4121 {
cristyc38fbf52013-11-03 13:55:54 +00004122 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed","...");
cristy3ed852e2009-09-05 21:47:34 +00004123 return((Image *) NULL);
4124 }
4125 id=number_windows++;
4126 window_info[id].window=window;
4127 window_info[id].visual=window_attributes.visual;
4128 window_info[id].colormap=window_attributes.colormap;
4129 window_info[id].bounds.x1=(short) crop_info.x;
4130 window_info[id].bounds.y1=(short) crop_info.y;
4131 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4132 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4133 crop_info.x-=x_offset;
4134 crop_info.y-=y_offset;
4135 window_info[id].crop_info=crop_info;
4136 if (level != 0)
4137 {
4138 unsigned int
4139 number_children;
4140
4141 Window
4142 *children;
4143
4144 /*
4145 Descend the window hierarchy.
4146 */
4147 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4148 &children,&number_children);
4149 for (i=0; i < id; i++)
4150 if ((window_info[i].window == window_info[id].parent) &&
4151 (window_info[i].visual == window_info[id].visual) &&
4152 (window_info[i].colormap == window_info[id].colormap))
4153 {
cristy64057b02013-01-11 00:09:58 +00004154 if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
4155 (window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
4156 (window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
4157 (window_info[id].bounds.y2 > window_info[i].bounds.y2))
cristy3ed852e2009-09-05 21:47:34 +00004158 {
4159 /*
4160 Eliminate windows not circumscribed by their parent.
4161 */
4162 number_windows--;
4163 break;
4164 }
4165 }
4166 if ((status == True) && (number_children != 0))
4167 {
4168 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004169 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4170 exception);
cristy3ed852e2009-09-05 21:47:34 +00004171 (void) XFree((void *) children);
4172 }
4173 }
4174 if (level <= 1)
4175 {
cristyc57f6942010-11-12 01:47:39 +00004176 CacheView
4177 *composite_view;
4178
cristy3ed852e2009-09-05 21:47:34 +00004179 ColormapInfo
4180 *next;
4181
cristy3ed852e2009-09-05 21:47:34 +00004182 Image
4183 *composite_image,
4184 *image;
4185
4186 int
4187 y;
4188
4189 MagickBooleanType
4190 import;
4191
4192 register int
4193 j,
4194 x;
4195
cristy4c08aed2011-07-01 19:47:50 +00004196 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004197 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004198
cristybb503372010-05-27 20:51:26 +00004199 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004200 pixel;
4201
4202 unsigned int
4203 number_colors;
4204
4205 XColor
4206 *colors;
4207
4208 XImage
4209 *ximage;
4210
4211 /*
4212 Get X image for each window in the list.
4213 */
4214 image=NewImageList();
4215 for (id=0; id < number_windows; id++)
4216 {
4217 /*
4218 Does target window intersect top level window?
4219 */
cristy088af952013-08-19 18:34:20 +00004220 import=((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
cristy3ed852e2009-09-05 21:47:34 +00004221 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4222 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4223 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4224 MagickTrue : MagickFalse;
4225 /*
4226 Is target window contained by another window with the same colormap?
4227 */
4228 for (j=0; j < id; j++)
4229 if ((window_info[id].visual == window_info[j].visual) &&
4230 (window_info[id].colormap == window_info[j].colormap))
4231 {
cristy64057b02013-01-11 00:09:58 +00004232 if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
4233 (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
4234 (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
4235 (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
cristy088af952013-08-19 18:34:20 +00004236 import=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00004237 }
cristy3ed852e2009-09-05 21:47:34 +00004238 if (import == MagickFalse)
4239 continue;
4240 /*
4241 Get X image.
4242 */
4243 ximage=XGetImage(display,window_info[id].window,(int)
4244 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4245 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4246 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4247 if (ximage == (XImage *) NULL)
4248 continue;
4249 /*
4250 Initialize window colormap.
4251 */
4252 number_colors=0;
4253 colors=(XColor *) NULL;
4254 if (window_info[id].colormap != (Colormap) NULL)
4255 {
4256 ColormapInfo
4257 *p;
4258
4259 /*
4260 Search colormap list for window colormap.
4261 */
4262 number_colors=(unsigned int) window_info[id].visual->map_entries;
4263 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4264 if (p->colormap == window_info[id].colormap)
4265 break;
4266 if (p == (ColormapInfo *) NULL)
4267 {
4268 /*
4269 Get the window colormap.
4270 */
4271 colors=(XColor *) AcquireQuantumMemory(number_colors,
4272 sizeof(*colors));
4273 if (colors == (XColor *) NULL)
4274 {
4275 XDestroyImage(ximage);
4276 return((Image *) NULL);
4277 }
4278 if ((window_info[id].visual->klass != DirectColor) &&
4279 (window_info[id].visual->klass != TrueColor))
4280 for (i=0; i < (int) number_colors; i++)
4281 {
cristybb503372010-05-27 20:51:26 +00004282 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004283 colors[i].pad='\0';
4284 }
4285 else
4286 {
cristybb503372010-05-27 20:51:26 +00004287 size_t
cristy3ed852e2009-09-05 21:47:34 +00004288 blue,
4289 blue_bit,
4290 green,
4291 green_bit,
4292 red,
4293 red_bit;
4294
4295 /*
4296 DirectColor or TrueColor visual.
4297 */
4298 red=0;
4299 green=0;
4300 blue=0;
4301 red_bit=window_info[id].visual->red_mask &
4302 (~(window_info[id].visual->red_mask)+1);
4303 green_bit=window_info[id].visual->green_mask &
4304 (~(window_info[id].visual->green_mask)+1);
4305 blue_bit=window_info[id].visual->blue_mask &
4306 (~(window_info[id].visual->blue_mask)+1);
4307 for (i=0; i < (int) number_colors; i++)
4308 {
cristy8891f9c2010-06-04 23:32:17 +00004309 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004310 colors[i].pad='\0';
4311 red+=red_bit;
4312 if (red > window_info[id].visual->red_mask)
4313 red=0;
4314 green+=green_bit;
4315 if (green > window_info[id].visual->green_mask)
4316 green=0;
4317 blue+=blue_bit;
4318 if (blue > window_info[id].visual->blue_mask)
4319 blue=0;
4320 }
4321 }
4322 (void) XQueryColors(display,window_info[id].colormap,colors,
4323 (int) number_colors);
4324 /*
4325 Append colormap to colormap list.
4326 */
cristy73bd4a52010-10-05 11:24:23 +00004327 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004328 if (p == (ColormapInfo *) NULL)
4329 return((Image *) NULL);
4330 p->colormap=window_info[id].colormap;
4331 p->colors=colors;
4332 p->next=colormap_info;
4333 colormap_info=p;
4334 }
4335 colors=p->colors;
4336 }
4337 /*
4338 Allocate image structure.
4339 */
cristy6710d842011-10-20 23:23:00 +00004340 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004341 if (composite_image == (Image *) NULL)
4342 {
4343 XDestroyImage(ximage);
4344 return((Image *) NULL);
4345 }
4346 /*
4347 Convert X image to MIFF format.
4348 */
4349 if ((window_info[id].visual->klass != TrueColor) &&
4350 (window_info[id].visual->klass != DirectColor))
4351 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004352 composite_image->columns=(size_t) ximage->width;
4353 composite_image->rows=(size_t) ximage->height;
cristy46ff2672012-12-14 15:32:26 +00004354 composite_view=AcquireAuthenticCacheView(composite_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00004355 switch (composite_image->storage_class)
4356 {
4357 case DirectClass:
4358 default:
4359 {
cristybb503372010-05-27 20:51:26 +00004360 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004361 color,
4362 index;
4363
cristybb503372010-05-27 20:51:26 +00004364 size_t
cristy3ed852e2009-09-05 21:47:34 +00004365 blue_mask,
4366 blue_shift,
4367 green_mask,
4368 green_shift,
4369 red_mask,
4370 red_shift;
4371
4372 /*
4373 Determine shift and mask for red, green, and blue.
4374 */
4375 red_mask=window_info[id].visual->red_mask;
4376 red_shift=0;
4377 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4378 {
4379 red_mask>>=1;
4380 red_shift++;
4381 }
4382 green_mask=window_info[id].visual->green_mask;
4383 green_shift=0;
4384 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4385 {
4386 green_mask>>=1;
4387 green_shift++;
4388 }
4389 blue_mask=window_info[id].visual->blue_mask;
4390 blue_shift=0;
4391 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4392 {
4393 blue_mask>>=1;
4394 blue_shift++;
4395 }
4396 /*
4397 Convert X image to DirectClass packets.
4398 */
4399 if ((number_colors != 0) &&
4400 (window_info[id].visual->klass == DirectColor))
4401 for (y=0; y < (int) composite_image->rows; y++)
4402 {
cristyc57f6942010-11-12 01:47:39 +00004403 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004404 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004405 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004406 break;
4407 for (x=0; x < (int) composite_image->columns; x++)
4408 {
4409 pixel=XGetPixel(ximage,x,y);
4410 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004411 SetPixelRed(composite_image,
4412 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004413 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004414 SetPixelGreen(composite_image,
4415 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004416 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004417 SetPixelBlue(composite_image,
4418 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004419 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004420 }
cristy0b1a7972011-10-22 22:17:02 +00004421 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4422 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004423 break;
4424 }
4425 else
4426 for (y=0; y < (int) composite_image->rows; y++)
4427 {
cristyc57f6942010-11-12 01:47:39 +00004428 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004429 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004430 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004431 break;
4432 for (x=0; x < (int) composite_image->columns; x++)
4433 {
4434 pixel=XGetPixel(ximage,x,y);
4435 color=(pixel >> red_shift) & red_mask;
cristy9a7df362014-01-14 15:03:18 +00004436 if (red_mask != 0)
4437 color=(65535UL*color)/red_mask;
4438 SetPixelRed(composite_image,ScaleShortToQuantum(
4439 (unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004440 color=(pixel >> green_shift) & green_mask;
cristy9a7df362014-01-14 15:03:18 +00004441 if (green_mask != 0)
4442 color=(65535UL*color)/green_mask;
4443 SetPixelGreen(composite_image,ScaleShortToQuantum(
4444 (unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004445 color=(pixel >> blue_shift) & blue_mask;
cristy9a7df362014-01-14 15:03:18 +00004446 if (blue_mask != 0)
4447 color=(65535UL*color)/blue_mask;
4448 SetPixelBlue(composite_image,ScaleShortToQuantum(
4449 (unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004450 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004451 }
cristy0b1a7972011-10-22 22:17:02 +00004452 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4453 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004454 break;
4455 }
4456 break;
4457 }
4458 case PseudoClass:
4459 {
4460 /*
4461 Create colormap.
4462 */
cristy0b1a7972011-10-22 22:17:02 +00004463 status=AcquireImageColormap(composite_image,number_colors,
4464 exception);
4465 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004466 {
4467 XDestroyImage(ximage);
4468 composite_image=DestroyImage(composite_image);
4469 return((Image *) NULL);
4470 }
4471 for (i=0; i < (int) composite_image->colors; i++)
4472 {
cristye42f6582012-02-11 17:59:50 +00004473 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004474 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004475 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004476 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004477 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004478 ScaleShortToQuantum(colors[i].blue);
4479 }
4480 /*
4481 Convert X image to PseudoClass packets.
4482 */
4483 for (y=0; y < (int) composite_image->rows; y++)
4484 {
cristyc57f6942010-11-12 01:47:39 +00004485 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4486 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004487 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004488 break;
cristy3ed852e2009-09-05 21:47:34 +00004489 for (x=0; x < (int) composite_image->columns; x++)
4490 {
cristy4c08aed2011-07-01 19:47:50 +00004491 index=(Quantum) XGetPixel(ximage,x,y);
4492 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004493 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004494 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004495 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004496 }
cristy0b1a7972011-10-22 22:17:02 +00004497 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4498 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004499 break;
4500 }
4501 break;
4502 }
4503 }
cristyc57f6942010-11-12 01:47:39 +00004504 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004505 XDestroyImage(ximage);
4506 if (image == (Image *) NULL)
4507 {
4508 image=composite_image;
4509 continue;
4510 }
4511 /*
4512 Composite any children in back-to-front order.
4513 */
4514 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4515 &x_offset,&y_offset,&child);
4516 x_offset-=(int) crop_info.x;
4517 if (x_offset < 0)
4518 x_offset=0;
4519 y_offset-=(int) crop_info.y;
4520 if (y_offset < 0)
4521 y_offset=0;
cristy39172402012-03-30 13:04:39 +00004522 (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00004523 (ssize_t) x_offset,(ssize_t) y_offset,exception);
cristy5f257b22012-03-07 00:27:29 +00004524 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004525 }
4526 /*
4527 Relinquish resources.
4528 */
4529 while (colormap_info != (ColormapInfo *) NULL)
4530 {
4531 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004532 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4533 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004534 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4535 colormap_info=next;
4536 }
4537 /*
4538 Relinquish resources and restore initial state.
4539 */
4540 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4541 max_windows=0;
4542 number_windows=0;
4543 colormap_info=(ColormapInfo *) NULL;
4544 return(image);
4545 }
4546 return((Image *) NULL);
4547}
4548
4549/*
4550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4551% %
4552% %
4553% %
4554% X G e t W i n d o w I n f o %
4555% %
4556% %
4557% %
4558%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4559%
4560% XGetWindowInfo() initializes the XWindowInfo structure.
4561%
4562% The format of the XGetWindowInfo method is:
4563%
4564% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4565% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4566% XResourceInfo *resource_info,XWindowInfo *window)
4567% resource_info,window)
4568%
4569% A description of each parameter follows:
4570%
4571% o display: Specifies a connection to an X server; returned from
4572% XOpenDisplay.
4573%
4574% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4575% returned from XGetVisualInfo.
4576%
4577% o map_info: If map_type is specified, this structure is initialized
4578% with info from the Standard Colormap.
4579%
4580% o pixel: Specifies a pointer to a XPixelInfo structure.
4581%
4582% o font_info: Specifies a pointer to a XFontStruct structure.
4583%
4584% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4585%
4586*/
cristybcbda3f2011-09-03 13:01:22 +00004587MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004588 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4589 XResourceInfo *resource_info,XWindowInfo *window)
4590{
4591 /*
4592 Initialize window info.
4593 */
4594 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4595 assert(display != (Display *) NULL);
4596 assert(visual_info != (XVisualInfo *) NULL);
4597 assert(map_info != (XStandardColormap *) NULL);
4598 assert(pixel != (XPixelInfo *) NULL);
4599 assert(resource_info != (XResourceInfo *) NULL);
4600 assert(window != (XWindowInfo *) NULL);
4601 if (window->id != (Window) NULL)
4602 {
4603 if (window->cursor != (Cursor) NULL)
4604 (void) XFreeCursor(display,window->cursor);
4605 if (window->busy_cursor != (Cursor) NULL)
4606 (void) XFreeCursor(display,window->busy_cursor);
4607 if (window->highlight_stipple != (Pixmap) NULL)
4608 (void) XFreePixmap(display,window->highlight_stipple);
4609 if (window->shadow_stipple != (Pixmap) NULL)
4610 (void) XFreePixmap(display,window->shadow_stipple);
4611 if (window->name == (char *) NULL)
4612 window->name=AcquireString("");
4613 if (window->icon_name == (char *) NULL)
4614 window->icon_name=AcquireString("");
4615 }
4616 else
4617 {
4618 /*
4619 Initialize these attributes just once.
4620 */
4621 window->id=(Window) NULL;
4622 if (window->name == (char *) NULL)
4623 window->name=AcquireString("");
4624 if (window->icon_name == (char *) NULL)
4625 window->icon_name=AcquireString("");
4626 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4627 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4628 window->ximage=(XImage *) NULL;
4629 window->matte_image=(XImage *) NULL;
4630 window->pixmap=(Pixmap) NULL;
4631 window->matte_pixmap=(Pixmap) NULL;
4632 window->mapped=MagickFalse;
4633 window->stasis=MagickFalse;
4634 window->shared_memory=MagickTrue;
4635 window->segment_info=(void *) NULL;
4636#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4637 {
4638 XShmSegmentInfo
4639 *segment_info;
4640
4641 if (window->segment_info == (void *) NULL)
4642 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4643 segment_info=(XShmSegmentInfo *) window->segment_info;
4644 segment_info[0].shmid=(-1);
4645 segment_info[0].shmaddr=(char *) NULL;
4646 segment_info[1].shmid=(-1);
4647 segment_info[1].shmaddr=(char *) NULL;
4648 }
4649#endif
4650 }
4651 /*
4652 Initialize these attributes every time function is called.
4653 */
4654 window->screen=visual_info->screen;
4655 window->root=XRootWindow(display,visual_info->screen);
4656 window->visual=visual_info->visual;
4657 window->storage_class=(unsigned int) visual_info->klass;
4658 window->depth=(unsigned int) visual_info->depth;
4659 window->visual_info=visual_info;
4660 window->map_info=map_info;
4661 window->pixel_info=pixel;
4662 window->font_info=font_info;
4663 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4664 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4665 window->geometry=(char *) NULL;
4666 window->icon_geometry=(char *) NULL;
4667 if (resource_info->icon_geometry != (char *) NULL)
4668 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4669 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004670 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004671 window->width=1;
4672 window->height=1;
4673 window->min_width=1;
4674 window->min_height=1;
4675 window->width_inc=1;
4676 window->height_inc=1;
4677 window->border_width=resource_info->border_width;
4678 window->annotate_context=pixel->annotate_context;
4679 window->highlight_context=pixel->highlight_context;
4680 window->widget_context=pixel->widget_context;
4681 window->shadow_stipple=(Pixmap) NULL;
4682 window->highlight_stipple=(Pixmap) NULL;
4683 window->use_pixmap=MagickTrue;
4684 window->immutable=MagickFalse;
4685 window->shape=MagickFalse;
4686 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004687 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004688 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4689 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4690 window->attributes.background_pixel=pixel->background_color.pixel;
4691 window->attributes.background_pixmap=(Pixmap) NULL;
4692 window->attributes.bit_gravity=ForgetGravity;
4693 window->attributes.backing_store=WhenMapped;
4694 window->attributes.save_under=MagickTrue;
4695 window->attributes.border_pixel=pixel->border_color.pixel;
4696 window->attributes.colormap=map_info->colormap;
4697 window->attributes.cursor=window->cursor;
4698 window->attributes.do_not_propagate_mask=NoEventMask;
4699 window->attributes.event_mask=NoEventMask;
4700 window->attributes.override_redirect=MagickFalse;
4701 window->attributes.win_gravity=NorthWestGravity;
4702 window->orphan=MagickFalse;
4703}
4704
4705/*
4706%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4707% %
4708% %
4709% %
4710% X H i g h l i g h t E l l i p s e %
4711% %
4712% %
4713% %
4714%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4715%
4716% XHighlightEllipse() puts a border on the X server around a region defined by
4717% highlight_info.
4718%
4719% The format of the XHighlightEllipse method is:
4720%
4721% void XHighlightEllipse(Display *display,Window window,
4722% GC annotate_context,const RectangleInfo *highlight_info)
4723%
4724% A description of each parameter follows:
4725%
4726% o display: Specifies a connection to an X server; returned from
4727% XOpenDisplay.
4728%
4729% o window: Specifies a pointer to a Window structure.
4730%
4731% o annotate_context: Specifies a pointer to a GC structure.
4732%
4733% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4734% contains the extents of any highlighting rectangle.
4735%
4736*/
cristybcbda3f2011-09-03 13:01:22 +00004737MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004738 GC annotate_context,const RectangleInfo *highlight_info)
4739{
4740 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4741 assert(display != (Display *) NULL);
4742 assert(window != (Window) NULL);
4743 assert(annotate_context != (GC) NULL);
4744 assert(highlight_info != (RectangleInfo *) NULL);
4745 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4746 return;
4747 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4748 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4749 (unsigned int) highlight_info->height-1,0,360*64);
4750 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4751 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4752 (unsigned int) highlight_info->height-3,0,360*64);
4753}
4754
4755/*
4756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4757% %
4758% %
4759% %
4760% X H i g h l i g h t L i n e %
4761% %
4762% %
4763% %
4764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4765%
4766% XHighlightLine() puts a border on the X server around a region defined by
4767% highlight_info.
4768%
4769% The format of the XHighlightLine method is:
4770%
4771% void XHighlightLine(Display *display,Window window,GC annotate_context,
4772% const XSegment *highlight_info)
4773%
4774% A description of each parameter follows:
4775%
4776% o display: Specifies a connection to an X server; returned from
4777% XOpenDisplay.
4778%
4779% o window: Specifies a pointer to a Window structure.
4780%
4781% o annotate_context: Specifies a pointer to a GC structure.
4782%
4783% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4784% contains the extents of any highlighting rectangle.
4785%
4786*/
cristybcbda3f2011-09-03 13:01:22 +00004787MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004788 GC annotate_context,const XSegment *highlight_info)
4789{
4790 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4791 assert(display != (Display *) NULL);
4792 assert(window != (Window) NULL);
4793 assert(annotate_context != (GC) NULL);
4794 assert(highlight_info != (XSegment *) NULL);
4795 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4796 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4797}
4798
4799/*
4800%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4801% %
4802% %
4803% %
4804% X H i g h l i g h t R e c t a n g l e %
4805% %
4806% %
4807% %
4808%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4809%
4810% XHighlightRectangle() puts a border on the X server around a region defined
4811% by highlight_info.
4812%
4813% The format of the XHighlightRectangle method is:
4814%
4815% void XHighlightRectangle(Display *display,Window window,
4816% GC annotate_context,const RectangleInfo *highlight_info)
4817%
4818% A description of each parameter follows:
4819%
4820% o display: Specifies a connection to an X server; returned from
4821% XOpenDisplay.
4822%
4823% o window: Specifies a pointer to a Window structure.
4824%
4825% o annotate_context: Specifies a pointer to a GC structure.
4826%
4827% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4828% contains the extents of any highlighting rectangle.
4829%
4830*/
cristybcbda3f2011-09-03 13:01:22 +00004831MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004832 GC annotate_context,const RectangleInfo *highlight_info)
4833{
4834 assert(display != (Display *) NULL);
4835 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4836 assert(window != (Window) NULL);
4837 assert(annotate_context != (GC) NULL);
4838 assert(highlight_info != (RectangleInfo *) NULL);
4839 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4840 return;
4841 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4842 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4843 (unsigned int) highlight_info->height-1);
4844 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4845 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4846 (unsigned int) highlight_info->height-3);
4847}
4848
4849/*
4850%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4851% %
4852% %
4853% %
4854% X I m p o r t I m a g e %
4855% %
4856% %
4857% %
4858%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4859%
4860% XImportImage() reads an image from an X window.
4861%
4862% The format of the XImportImage method is:
4863%
cristy6710d842011-10-20 23:23:00 +00004864% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4865% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004866%
4867% A description of each parameter follows:
4868%
4869% o image_info: the image info.
4870%
4871% o ximage_info: Specifies a pointer to an XImportInfo structure.
4872%
cristy6710d842011-10-20 23:23:00 +00004873% o exception: return any errors or warnings in this structure.
4874%
cristy3ed852e2009-09-05 21:47:34 +00004875*/
4876MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004877 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004878{
4879 Colormap
4880 *colormaps;
4881
4882 Display
4883 *display;
4884
4885 Image
4886 *image;
4887
4888 int
4889 number_colormaps,
4890 number_windows,
4891 x;
4892
4893 RectangleInfo
4894 crop_info;
4895
4896 Status
4897 status;
4898
4899 Window
4900 *children,
4901 client,
4902 prior_target,
4903 root,
4904 target;
4905
4906 XTextProperty
4907 window_name;
4908
4909 /*
4910 Open X server connection.
4911 */
4912 assert(image_info != (const ImageInfo *) NULL);
4913 assert(image_info->signature == MagickSignature);
4914 if (image_info->debug != MagickFalse)
4915 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4916 image_info->filename);
4917 assert(ximage_info != (XImportInfo *) NULL);
4918 display=XOpenDisplay(image_info->server_name);
4919 if (display == (Display *) NULL)
4920 {
cristyc38fbf52013-11-03 13:55:54 +00004921 ThrowXWindowException(XServerError,"UnableToOpenXServer",
cristy3ed852e2009-09-05 21:47:34 +00004922 XDisplayName(image_info->server_name));
4923 return((Image *) NULL);
4924 }
4925 /*
4926 Set our forgiving exception handler.
4927 */
4928 (void) XSetErrorHandler(XError);
4929 /*
4930 Select target window.
4931 */
4932 crop_info.x=0;
4933 crop_info.y=0;
4934 crop_info.width=0;
4935 crop_info.height=0;
4936 root=XRootWindow(display,XDefaultScreen(display));
4937 target=(Window) NULL;
4938 if ((image_info->filename != (char *) NULL) &&
4939 (*image_info->filename != '\0'))
4940 {
4941 if (LocaleCompare(image_info->filename,"root") == 0)
4942 target=root;
4943 else
4944 {
4945 /*
4946 Select window by ID or name.
4947 */
cristy02e64f82013-11-14 16:20:04 +00004948 if (isdigit((int) ((unsigned char) *image_info->filename)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00004949 target=XWindowByID(display,root,(Window)
4950 strtol(image_info->filename,(char **) NULL,0));
4951 if (target == (Window) NULL)
4952 target=XWindowByName(display,root,image_info->filename);
4953 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004954 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
4955 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00004956 }
4957 }
4958 /*
4959 If target window is not defined, interactively select one.
4960 */
4961 prior_target=target;
4962 if (target == (Window) NULL)
4963 target=XSelectWindow(display,&crop_info);
4964 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004965 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00004966 image_info->filename);
4967 client=target; /* obsolete */
4968 if (target != root)
4969 {
4970 unsigned int
4971 d;
4972
4973 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4974 if (status != False)
4975 {
4976 for ( ; ; )
4977 {
4978 Window
4979 parent;
4980
4981 /*
4982 Find window manager frame.
4983 */
4984 status=XQueryTree(display,target,&root,&parent,&children,&d);
4985 if ((status != False) && (children != (Window *) NULL))
4986 (void) XFree((char *) children);
4987 if ((status == False) || (parent == (Window) NULL) ||
4988 (parent == root))
4989 break;
4990 target=parent;
4991 }
4992 /*
4993 Get client window.
4994 */
4995 client=XClientWindow(display,target);
4996 if (ximage_info->frame == MagickFalse)
4997 target=client;
4998 if ((ximage_info->frame == MagickFalse) &&
4999 (prior_target != MagickFalse))
5000 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00005001 }
5002 }
5003 if (ximage_info->screen)
5004 {
5005 int
5006 y;
5007
5008 Window
5009 child;
5010
5011 XWindowAttributes
5012 window_attributes;
5013
5014 /*
5015 Obtain window image directly from screen.
5016 */
5017 status=XGetWindowAttributes(display,target,&window_attributes);
5018 if (status == False)
5019 {
cristyc38fbf52013-11-03 13:55:54 +00005020 ThrowXWindowException(XServerError,"UnableToReadXWindowAttributes",
5021 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00005022 (void) XCloseDisplay(display);
5023 return((Image *) NULL);
5024 }
5025 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005026 crop_info.x=(ssize_t) x;
5027 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005028 crop_info.width=(size_t) window_attributes.width;
5029 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005030 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005031 {
5032 /*
5033 Include border in image.
5034 */
5035 crop_info.x-=window_attributes.border_width;
5036 crop_info.y-=window_attributes.border_width;
5037 crop_info.width+=window_attributes.border_width << 1;
5038 crop_info.height+=window_attributes.border_width << 1;
5039 }
5040 target=root;
5041 }
5042 /*
5043 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5044 */
5045 number_windows=0;
5046 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5047 if ((status == True) && (number_windows > 0))
5048 {
5049 ximage_info->descend=MagickTrue;
5050 (void) XFree ((char *) children);
5051 }
5052 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5053 if (number_colormaps > 0)
5054 {
5055 if (number_colormaps > 1)
5056 ximage_info->descend=MagickTrue;
5057 (void) XFree((char *) colormaps);
5058 }
5059 /*
5060 Alert the user not to alter the screen.
5061 */
5062 if (ximage_info->silent == MagickFalse)
5063 (void) XBell(display,0);
5064 /*
5065 Get image by window id.
5066 */
5067 (void) XGrabServer(display);
5068 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005069 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005070 (void) XUngrabServer(display);
5071 if (image == (Image *) NULL)
cristyc38fbf52013-11-03 13:55:54 +00005072 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00005073 image_info->filename)
5074 else
5075 {
5076 (void) CopyMagickString(image->filename,image_info->filename,
5077 MaxTextExtent);
5078 if ((crop_info.width != 0) && (crop_info.height != 0))
5079 {
5080 Image
5081 *clone_image,
5082 *crop_image;
5083
5084 /*
5085 Crop image as defined by the cropping rectangle.
5086 */
cristy6710d842011-10-20 23:23:00 +00005087 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005088 if (clone_image != (Image *) NULL)
5089 {
cristy6710d842011-10-20 23:23:00 +00005090 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005091 if (crop_image != (Image *) NULL)
5092 {
5093 image=DestroyImage(image);
5094 image=crop_image;
5095 }
5096 }
5097 }
5098 status=XGetWMName(display,target,&window_name);
5099 if (status == True)
5100 {
5101 if ((image_info->filename != (char *) NULL) &&
5102 (*image_info->filename == '\0'))
5103 (void) CopyMagickString(image->filename,(char *) window_name.value,
5104 (size_t) window_name.nitems+1);
5105 (void) XFree((void *) window_name.value);
5106 }
5107 }
5108 if (ximage_info->silent == MagickFalse)
5109 {
5110 /*
5111 Alert the user we're done.
5112 */
5113 (void) XBell(display,0);
5114 (void) XBell(display,0);
5115 }
5116 (void) XCloseDisplay(display);
5117 return(image);
5118}
5119
5120/*
5121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5122% %
5123% %
5124% %
5125% X I n i t i a l i z e W i n d o w s %
5126% %
5127% %
5128% %
5129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5130%
5131% XInitializeWindows() initializes the XWindows structure.
5132%
5133% The format of the XInitializeWindows method is:
5134%
5135% XWindows *XInitializeWindows(Display *display,
5136% XResourceInfo *resource_info)
5137%
5138% A description of each parameter follows:
5139%
5140% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5141%
5142% o display: Specifies a connection to an X server; returned from
5143% XOpenDisplay.
5144%
5145% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5146%
5147*/
cristybcbda3f2011-09-03 13:01:22 +00005148MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005149 XResourceInfo *resource_info)
5150{
5151 Window
5152 root_window;
5153
5154 XWindows
5155 *windows;
5156
5157 /*
5158 Allocate windows structure.
5159 */
cristy73bd4a52010-10-05 11:24:23 +00005160 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005161 if (windows == (XWindows *) NULL)
5162 {
5163 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5164 "...");
5165 return((XWindows *) NULL);
5166 }
5167 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5168 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5169 sizeof(*windows->pixel_info));
5170 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5171 sizeof(*windows->icon_pixel));
5172 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5173 sizeof(*windows->icon_resources));
5174 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5175 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5176 (windows->icon_resources == (XResourceInfo *) NULL))
5177 {
5178 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5179 "...");
5180 return((XWindows *) NULL);
5181 }
5182 /*
5183 Initialize windows structure.
5184 */
5185 windows->display=display;
5186 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5187 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5188 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5189 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5190 windows->im_remote_command=
5191 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5192 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5193 windows->im_update_colormap=
5194 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5195 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5196 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5197 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5198 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5199 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005200#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005201 (void) XSynchronize(display,IsWindows95());
5202#endif
5203 if (IsEventLogging())
5204 {
5205 (void) XSynchronize(display,MagickTrue);
5206 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005207 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005208 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5209 (void) LogMagickEvent(X11Event,GetMagickModule(),
5210 " Window Manager: 0x%lx",windows->wm_protocols);
5211 (void) LogMagickEvent(X11Event,GetMagickModule(),
5212 " delete window: 0x%lx",windows->wm_delete_window);
5213 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5214 windows->wm_take_focus);
5215 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5216 windows->im_protocols);
5217 (void) LogMagickEvent(X11Event,GetMagickModule(),
5218 " remote command: 0x%lx",windows->im_remote_command);
5219 (void) LogMagickEvent(X11Event,GetMagickModule(),
5220 " update widget: 0x%lx",windows->im_update_widget);
5221 (void) LogMagickEvent(X11Event,GetMagickModule(),
5222 " update colormap: 0x%lx",windows->im_update_colormap);
5223 (void) LogMagickEvent(X11Event,GetMagickModule(),
5224 " former image: 0x%lx",windows->im_former_image);
5225 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5226 windows->im_next_image);
5227 (void) LogMagickEvent(X11Event,GetMagickModule(),
5228 " retain colors: 0x%lx",windows->im_retain_colors);
5229 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5230 windows->im_exit);
5231 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5232 windows->dnd_protocols);
5233 }
5234 /*
5235 Allocate standard colormap.
5236 */
5237 windows->map_info=XAllocStandardColormap();
5238 windows->icon_map=XAllocStandardColormap();
5239 if ((windows->map_info == (XStandardColormap *) NULL) ||
5240 (windows->icon_map == (XStandardColormap *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005241 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5242 "...");
cristy3ed852e2009-09-05 21:47:34 +00005243 windows->map_info->colormap=(Colormap) NULL;
5244 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005245 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005246 windows->pixel_info->annotate_context=(GC) NULL;
5247 windows->pixel_info->highlight_context=(GC) NULL;
5248 windows->pixel_info->widget_context=(GC) NULL;
5249 windows->font_info=(XFontStruct *) NULL;
5250 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005251 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005252 /*
5253 Allocate visual.
5254 */
5255 *windows->icon_resources=(*resource_info);
5256 windows->icon_resources->visual_type=(char *) "default";
5257 windows->icon_resources->colormap=SharedColormap;
5258 windows->visual_info=
5259 XBestVisualInfo(display,windows->map_info,resource_info);
5260 windows->icon_visual=
5261 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5262 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5263 (windows->icon_visual == (XVisualInfo *) NULL))
5264 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5265 resource_info->visual_type);
5266 if (IsEventLogging())
5267 {
5268 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5269 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5270 windows->visual_info->visualid);
5271 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5272 XVisualClassName(windows->visual_info->klass));
5273 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5274 windows->visual_info->depth);
5275 (void) LogMagickEvent(X11Event,GetMagickModule(),
5276 " size of colormap: %d entries",windows->visual_info->colormap_size);
5277 (void) LogMagickEvent(X11Event,GetMagickModule(),
5278 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5279 windows->visual_info->red_mask,windows->visual_info->green_mask,
5280 windows->visual_info->blue_mask);
5281 (void) LogMagickEvent(X11Event,GetMagickModule(),
5282 " significant bits in color: %d bits",
5283 windows->visual_info->bits_per_rgb);
5284 }
5285 /*
5286 Allocate class and manager hints.
5287 */
5288 windows->class_hints=XAllocClassHint();
5289 windows->manager_hints=XAllocWMHints();
5290 if ((windows->class_hints == (XClassHint *) NULL) ||
5291 (windows->manager_hints == (XWMHints *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005292 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5293 "...");
cristy3ed852e2009-09-05 21:47:34 +00005294 /*
5295 Determine group leader if we have one.
5296 */
5297 root_window=XRootWindow(display,windows->visual_info->screen);
5298 windows->group_leader.id=(Window) NULL;
5299 if (resource_info->window_group != (char *) NULL)
5300 {
cristy02e64f82013-11-14 16:20:04 +00005301 if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00005302 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5303 strtol((char *) resource_info->window_group,(char **) NULL,0));
5304 if (windows->group_leader.id == (Window) NULL)
5305 windows->group_leader.id=
5306 XWindowByName(display,root_window,resource_info->window_group);
5307 }
5308 return(windows);
5309}
5310
5311/*
5312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5313% %
5314% %
5315% %
5316% X M a k e C u r s o r %
5317% %
5318% %
5319% %
5320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5321%
5322% XMakeCursor() creates a crosshairs X11 cursor.
5323%
5324% The format of the XMakeCursor method is:
5325%
5326% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5327% char *background_color,char *foreground_color)
5328%
5329% A description of each parameter follows:
5330%
5331% o display: Specifies a connection to an X server; returned from
5332% XOpenDisplay.
5333%
5334% o window: Specifies the ID of the window for which the cursor is
5335% assigned.
5336%
5337% o colormap: Specifies the ID of the colormap from which the background
5338% and foreground color will be retrieved.
5339%
5340% o background_color: Specifies the color to use for the cursor background.
5341%
5342% o foreground_color: Specifies the color to use for the cursor foreground.
5343%
5344*/
cristybcbda3f2011-09-03 13:01:22 +00005345MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005346 Colormap colormap,char *background_color,char *foreground_color)
5347{
5348#define scope_height 17
5349#define scope_x_hot 8
5350#define scope_y_hot 8
5351#define scope_width 17
5352
5353 static const unsigned char
5354 scope_bits[] =
5355 {
5356 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5357 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5358 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5359 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5360 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5361 },
5362 scope_mask_bits[] =
5363 {
5364 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5365 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5366 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5367 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5368 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5369 };
5370
5371 Cursor
5372 cursor;
5373
5374 Pixmap
5375 mask,
5376 source;
5377
5378 XColor
5379 background,
5380 foreground;
5381
5382 assert(display != (Display *) NULL);
5383 assert(window != (Window) NULL);
5384 assert(colormap != (Colormap) NULL);
5385 assert(background_color != (char *) NULL);
5386 assert(foreground_color != (char *) NULL);
5387 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5388 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5389 scope_height);
5390 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5391 scope_width,scope_height);
5392 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5393 {
cristyc38fbf52013-11-03 13:55:54 +00005394 ThrowXWindowException(XServerError,"UnableToCreatePixmap","...");
cristy3ed852e2009-09-05 21:47:34 +00005395 return((Cursor) NULL);
5396 }
5397 (void) XParseColor(display,colormap,background_color,&background);
5398 (void) XParseColor(display,colormap,foreground_color,&foreground);
5399 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5400 scope_x_hot,scope_y_hot);
5401 (void) XFreePixmap(display,source);
5402 (void) XFreePixmap(display,mask);
5403 return(cursor);
5404}
5405
5406/*
5407%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5408% %
5409% %
5410% %
5411% X M a k e I m a g e %
5412% %
5413% %
5414% %
5415%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5416%
5417% XMakeImage() creates an X11 image. If the image size differs from the X11
5418% image size, the image is first resized.
5419%
5420% The format of the XMakeImage method is:
5421%
5422% MagickBooleanType XMakeImage(Display *display,
5423% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005424% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005425%
5426% A description of each parameter follows:
5427%
5428% o display: Specifies a connection to an X server; returned from
5429% XOpenDisplay.
5430%
5431% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5432%
5433% o window: Specifies a pointer to a XWindowInfo structure.
5434%
5435% o image: the image.
5436%
5437% o width: Specifies the width in pixels of the rectangular area to
5438% display.
5439%
5440% o height: Specifies the height in pixels of the rectangular area to
5441% display.
5442%
cristy051718b2011-08-28 22:49:25 +00005443% o exception: return any errors or warnings in this structure.
5444%
cristy3ed852e2009-09-05 21:47:34 +00005445*/
cristybcbda3f2011-09-03 13:01:22 +00005446MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005447 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005448 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005449{
5450#define CheckOverflowException(length,width,height) \
5451 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5452
5453 int
5454 depth,
5455 format;
5456
5457 size_t
5458 length;
5459
5460 XImage
5461 *matte_image,
5462 *ximage;
5463
5464 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5465 assert(display != (Display *) NULL);
5466 assert(resource_info != (XResourceInfo *) NULL);
5467 assert(window != (XWindowInfo *) NULL);
5468 assert(width != 0);
5469 assert(height != 0);
5470 if ((window->width == 0) || (window->height == 0))
5471 return(MagickFalse);
5472 /*
5473 Apply user transforms to the image.
5474 */
5475 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5476 (void) XFlush(display);
5477 depth=(int) window->depth;
5478 if (window->destroy)
5479 window->image=DestroyImage(window->image);
5480 window->image=image;
5481 window->destroy=MagickFalse;
5482 if (window->image != (Image *) NULL)
5483 {
5484 if (window->crop_geometry != (char *) NULL)
5485 {
5486 Image
5487 *crop_image;
5488
5489 RectangleInfo
5490 crop_info;
5491
5492 /*
5493 Crop image.
5494 */
5495 window->image->page.x=0;
5496 window->image->page.y=0;
5497 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005498 &crop_info,exception);
5499 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005500 if (crop_image != (Image *) NULL)
5501 {
5502 if (window->image != image)
5503 window->image=DestroyImage(window->image);
5504 window->image=crop_image;
5505 window->destroy=MagickTrue;
5506 }
5507 }
5508 if ((width != (unsigned int) window->image->columns) ||
5509 (height != (unsigned int) window->image->rows))
5510 {
5511 Image
5512 *resize_image;
5513
5514 /*
5515 Resize image.
5516 */
5517 resize_image=NewImageList();
cristy865489b2013-10-12 01:03:29 +00005518 if ((window->pixel_info->colors == 0) &&
5519 (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5520 (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5521 resize_image=ResizeImage(window->image,width,height,
5522 image->filter,exception);
cristy3ed852e2009-09-05 21:47:34 +00005523 else
cristy865489b2013-10-12 01:03:29 +00005524 {
5525 if (window->image->storage_class == PseudoClass)
5526 resize_image=SampleImage(window->image,width,height,
5527 exception);
5528 else
5529 resize_image=ThumbnailImage(window->image,width,height,
5530 exception);
5531 }
cristy3ed852e2009-09-05 21:47:34 +00005532 if (resize_image != (Image *) NULL)
5533 {
5534 if (window->image != image)
5535 window->image=DestroyImage(window->image);
5536 window->image=resize_image;
5537 window->destroy=MagickTrue;
5538 }
5539 }
5540 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005541 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005542 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005543 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005544 }
5545 /*
5546 Create X image.
5547 */
5548 ximage=(XImage *) NULL;
5549 format=(depth == 1) ? XYBitmap : ZPixmap;
5550#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5551 if (window->shared_memory != MagickFalse)
5552 {
5553 XShmSegmentInfo
5554 *segment_info;
5555
5556 segment_info=(XShmSegmentInfo *) window->segment_info;
5557 segment_info[1].shmid=(-1);
5558 segment_info[1].shmaddr=(char *) NULL;
5559 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5560 (char *) NULL,&segment_info[1],width,height);
5561 if (ximage == (XImage *) NULL)
5562 window->shared_memory=MagickFalse;
5563 length=(size_t) ximage->bytes_per_line*ximage->height;
5564 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5565 window->shared_memory=MagickFalse;
5566 if (window->shared_memory != MagickFalse)
5567 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5568 if (window->shared_memory != MagickFalse)
5569 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5570 if (segment_info[1].shmid < 0)
5571 window->shared_memory=MagickFalse;
5572 if (window->shared_memory != MagickFalse)
5573 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5574 else
5575 {
5576 if (ximage != (XImage *) NULL)
5577 XDestroyImage(ximage);
5578 ximage=(XImage *) NULL;
5579 if (segment_info[1].shmaddr)
5580 {
5581 (void) shmdt(segment_info[1].shmaddr);
5582 segment_info[1].shmaddr=(char *) NULL;
5583 }
5584 if (segment_info[1].shmid >= 0)
5585 {
5586 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5587 segment_info[1].shmid=(-1);
5588 }
5589 }
5590 }
5591#endif
5592 /*
5593 Allocate X image pixel data.
5594 */
5595#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5596 if (window->shared_memory)
5597 {
5598 Status
5599 status;
5600
5601 XShmSegmentInfo
5602 *segment_info;
5603
5604 (void) XSync(display,MagickFalse);
5605 xerror_alert=MagickFalse;
5606 segment_info=(XShmSegmentInfo *) window->segment_info;
5607 ximage->data=segment_info[1].shmaddr;
5608 segment_info[1].readOnly=MagickFalse;
5609 status=XShmAttach(display,&segment_info[1]);
5610 if (status != False)
5611 (void) XSync(display,MagickFalse);
5612 if ((status == False) || (xerror_alert != MagickFalse))
5613 {
5614 window->shared_memory=MagickFalse;
5615 if (status != False)
5616 XShmDetach(display,&segment_info[1]);
5617 if (ximage != (XImage *) NULL)
5618 {
5619 ximage->data=NULL;
5620 XDestroyImage(ximage);
5621 ximage=(XImage *) NULL;
5622 }
5623 if (segment_info[1].shmid >= 0)
5624 {
5625 if (segment_info[1].shmaddr != NULL)
5626 (void) shmdt(segment_info[1].shmaddr);
5627 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5628 segment_info[1].shmid=(-1);
5629 segment_info[1].shmaddr=(char *) NULL;
5630 }
5631 }
5632 }
5633#endif
5634 if (window->shared_memory == MagickFalse)
5635 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5636 (char *) NULL,width,height,XBitmapPad(display),0);
5637 if (ximage == (XImage *) NULL)
5638 {
5639 /*
5640 Unable to create X image.
5641 */
5642 (void) XCheckDefineCursor(display,window->id,window->cursor);
5643 return(MagickFalse);
5644 }
5645 length=(size_t) ximage->bytes_per_line*ximage->height;
5646 if (IsEventLogging())
5647 {
5648 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5649 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5650 ximage->width,ximage->height);
5651 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5652 ximage->format);
5653 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5654 ximage->byte_order);
5655 (void) LogMagickEvent(X11Event,GetMagickModule(),
5656 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5657 ximage->bitmap_bit_order,ximage->bitmap_pad);
5658 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5659 ximage->depth);
5660 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5661 ximage->bytes_per_line);
5662 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5663 ximage->bits_per_pixel);
5664 (void) LogMagickEvent(X11Event,GetMagickModule(),
5665 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5666 ximage->green_mask,ximage->blue_mask);
5667 }
5668 if (window->shared_memory == MagickFalse)
5669 {
5670 if (ximage->format != XYBitmap)
cristy9aecad62013-04-18 10:37:47 +00005671 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5672 ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005673 else
cristy9aecad62013-04-18 10:37:47 +00005674 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5675 ximage->depth*ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005676 }
5677 if (ximage->data == (char *) NULL)
5678 {
5679 /*
5680 Unable to allocate pixel data.
5681 */
5682 XDestroyImage(ximage);
5683 ximage=(XImage *) NULL;
5684 (void) XCheckDefineCursor(display,window->id,window->cursor);
5685 return(MagickFalse);
5686 }
5687 if (window->ximage != (XImage *) NULL)
5688 {
5689 /*
5690 Destroy previous X image.
5691 */
5692 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5693#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5694 if (window->segment_info != (XShmSegmentInfo *) NULL)
5695 {
5696 XShmSegmentInfo
5697 *segment_info;
5698
5699 segment_info=(XShmSegmentInfo *) window->segment_info;
5700 if (segment_info[0].shmid >= 0)
5701 {
5702 (void) XSync(display,MagickFalse);
5703 (void) XShmDetach(display,&segment_info[0]);
5704 (void) XSync(display,MagickFalse);
5705 if (segment_info[0].shmaddr != (char *) NULL)
5706 (void) shmdt(segment_info[0].shmaddr);
5707 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5708 segment_info[0].shmid=(-1);
5709 segment_info[0].shmaddr=(char *) NULL;
5710 window->ximage->data=(char *) NULL;
5711 }
5712 }
5713#endif
5714 if (window->ximage->data != (char *) NULL)
5715 free(window->ximage->data);
5716 window->ximage->data=(char *) NULL;
5717 XDestroyImage(window->ximage);
5718 window->ximage=(XImage *) NULL;
5719 }
5720#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5721 if (window->segment_info != (XShmSegmentInfo *) NULL)
5722 {
5723 XShmSegmentInfo
5724 *segment_info;
5725
5726 segment_info=(XShmSegmentInfo *) window->segment_info;
5727 segment_info[0]=segment_info[1];
5728 }
5729#endif
5730 window->ximage=ximage;
5731 matte_image=(XImage *) NULL;
5732 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
cristy8a46d822012-08-28 23:32:39 +00005733 if ((window->image->alpha_trait == BlendPixelTrait) &&
cristyc57f6942010-11-12 01:47:39 +00005734 ((int) width <= XDisplayWidth(display,window->screen)) &&
5735 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005736 {
5737 /*
5738 Create matte image.
5739 */
5740 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5741 (char *) NULL,width,height,XBitmapPad(display),0);
5742 if (IsEventLogging())
5743 {
5744 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5745 (void) LogMagickEvent(X11Event,GetMagickModule(),
5746 " width, height: %dx%d",matte_image->width,matte_image->height);
5747 }
5748 if (matte_image != (XImage *) NULL)
5749 {
5750 /*
5751 Allocate matte image pixel data.
5752 */
cristy9aecad62013-04-18 10:37:47 +00005753 matte_image->data=(char *) malloc((size_t)
5754 matte_image->bytes_per_line*matte_image->depth*
5755 matte_image->height);
cristy3ed852e2009-09-05 21:47:34 +00005756 if (matte_image->data == (char *) NULL)
5757 {
5758 XDestroyImage(matte_image);
5759 matte_image=(XImage *) NULL;
5760 }
5761 }
5762 }
5763 if (window->matte_image != (XImage *) NULL)
5764 {
5765 /*
5766 Free matte image.
5767 */
5768 if (window->matte_image->data != (char *) NULL)
5769 free(window->matte_image->data);
5770 window->matte_image->data=(char *) NULL;
5771 XDestroyImage(window->matte_image);
5772 window->matte_image=(XImage *) NULL;
5773 }
5774 window->matte_image=matte_image;
5775 if (window->matte_pixmap != (Pixmap) NULL)
5776 {
5777 (void) XFreePixmap(display,window->matte_pixmap);
5778 window->matte_pixmap=(Pixmap) NULL;
5779#if defined(MAGICKCORE_HAVE_SHAPE)
5780 if (window->shape != MagickFalse)
5781 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5782#endif
5783 }
5784 window->stasis=MagickFalse;
5785 /*
5786 Convert pixels to X image data.
5787 */
5788 if (window->image != (Image *) NULL)
5789 {
5790 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5791 (ximage->bitmap_bit_order == LSBFirst)))
5792 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005793 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005794 else
5795 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005796 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005797 }
5798 if (window->matte_image != (XImage *) NULL)
5799 {
5800 /*
5801 Create matte pixmap.
5802 */
5803 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5804 if (window->matte_pixmap != (Pixmap) NULL)
5805 {
5806 GC
5807 graphics_context;
5808
5809 XGCValues
5810 context_values;
5811
5812 /*
5813 Copy matte image to matte pixmap.
5814 */
cristy4c08aed2011-07-01 19:47:50 +00005815 context_values.background=0;
5816 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005817 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005818 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005819 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5820 window->matte_image,0,0,0,0,width,height);
5821 (void) XFreeGC(display,graphics_context);
5822#if defined(MAGICKCORE_HAVE_SHAPE)
5823 if (window->shape != MagickFalse)
5824 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5825 window->matte_pixmap,ShapeSet);
5826#endif
5827 }
5828 }
5829 (void) XMakePixmap(display,resource_info,window);
5830 /*
5831 Restore cursor.
5832 */
5833 (void) XCheckDefineCursor(display,window->id,window->cursor);
5834 return(MagickTrue);
5835}
5836
5837/*
5838%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5839% %
5840% %
5841% %
5842+ X M a k e I m a g e L S B F i r s t %
5843% %
5844% %
5845% %
5846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5847%
5848% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5849% pixels are copied in least-significant bit and byte first order. The
5850% server's scanline pad is respected. Rather than using one or two general
5851% cases, many special cases are found here to help speed up the image
5852% conversion.
5853%
5854% The format of the XMakeImageLSBFirst method is:
5855%
cristye941a752011-10-15 01:52:48 +00005856% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5857% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005858%
5859% A description of each parameter follows:
5860%
5861% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5862%
5863% o window: Specifies a pointer to a XWindowInfo structure.
5864%
5865% o image: the image.
5866%
5867% o ximage: Specifies a pointer to a XImage structure; returned from
5868% XCreateImage.
5869%
5870% o matte_image: Specifies a pointer to a XImage structure; returned from
5871% XCreateImage.
5872%
cristye941a752011-10-15 01:52:48 +00005873% o exception: return any errors or warnings in this structure.
5874%
cristy3ed852e2009-09-05 21:47:34 +00005875*/
5876static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005877 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5878 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005879{
cristyc57f6942010-11-12 01:47:39 +00005880 CacheView
5881 *canvas_view;
5882
cristy3ed852e2009-09-05 21:47:34 +00005883 Image
5884 *canvas;
5885
5886 int
5887 y;
5888
cristy4c08aed2011-07-01 19:47:50 +00005889 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005890 *p;
5891
5892 register int
5893 x;
5894
5895 register unsigned char
5896 *q;
5897
5898 unsigned char
5899 bit,
5900 byte;
5901
5902 unsigned int
5903 scanline_pad;
5904
cristyf2faecf2010-05-28 19:19:36 +00005905 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005906 pixel,
5907 *pixels;
5908
5909 XStandardColormap
5910 *map_info;
5911
5912 assert(resource_info != (XResourceInfo *) NULL);
5913 assert(window != (XWindowInfo *) NULL);
5914 assert(image != (Image *) NULL);
5915 if (image->debug != MagickFalse)
5916 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5917 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005918 if ((window->immutable == MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00005919 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00005920 {
5921 char
5922 size[MaxTextExtent];
5923
5924 Image
5925 *pattern;
5926
5927 ImageInfo
5928 *image_info;
5929
5930 image_info=AcquireImageInfo();
5931 (void) CopyMagickString(image_info->filename,
5932 resource_info->image_info->texture != (char *) NULL ?
5933 resource_info->image_info->texture : "pattern:checkerboard",
5934 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005935 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005936 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005937 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005938 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005939 image_info=DestroyImageInfo(image_info);
5940 if (pattern != (Image *) NULL)
5941 {
cristy6710d842011-10-20 23:23:00 +00005942 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005943 if (canvas != (Image *) NULL)
cristy39172402012-03-30 13:04:39 +00005944 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00005945 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00005946 pattern=DestroyImage(pattern);
5947 }
5948 }
5949 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5950 ximage->bits_per_pixel) >> 3));
5951 map_info=window->map_info;
5952 pixels=window->pixel_info->pixels;
5953 q=(unsigned char *) ximage->data;
5954 x=0;
cristy46ff2672012-12-14 15:32:26 +00005955 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00005956 if (ximage->format == XYBitmap)
5957 {
5958 register unsigned short
5959 polarity;
5960
5961 unsigned char
5962 background,
5963 foreground;
5964
5965 /*
5966 Convert canvas to big-endian bitmap.
5967 */
5968 background=(unsigned char)
5969 (XPixelIntensity(&window->pixel_info->foreground_color) <
5970 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5971 foreground=(unsigned char)
5972 (XPixelIntensity(&window->pixel_info->background_color) <
5973 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005974 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00005975 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00005976 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005977 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5978 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005979 for (y=0; y < (int) canvas->rows; y++)
5980 {
cristyc57f6942010-11-12 01:47:39 +00005981 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005982 exception);
cristy4c08aed2011-07-01 19:47:50 +00005983 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005984 break;
cristy3ed852e2009-09-05 21:47:34 +00005985 bit=0;
5986 byte=0;
5987 for (x=0; x < (int) canvas->columns; x++)
5988 {
5989 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005990 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005991 byte|=foreground;
5992 else
5993 byte|=background;
5994 bit++;
5995 if (bit == 8)
5996 {
5997 *q++=byte;
5998 bit=0;
5999 byte=0;
6000 }
cristyed231572011-07-14 02:18:59 +00006001 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006002 }
6003 if (bit != 0)
6004 *q=byte >> (8-bit);
6005 q+=scanline_pad;
6006 }
6007 }
6008 else
6009 if (window->pixel_info->colors != 0)
6010 switch (ximage->bits_per_pixel)
6011 {
6012 case 2:
6013 {
6014 register unsigned int
6015 nibble;
6016
6017 /*
6018 Convert to 2 bit color-mapped X canvas.
6019 */
6020 for (y=0; y < (int) canvas->rows; y++)
6021 {
cristyc57f6942010-11-12 01:47:39 +00006022 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006023 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006024 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006025 break;
cristy3ed852e2009-09-05 21:47:34 +00006026 nibble=0;
6027 for (x=0; x < (int) canvas->columns; x++)
6028 {
cristy4c08aed2011-07-01 19:47:50 +00006029 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006030 switch (nibble)
6031 {
6032 case 0:
6033 {
6034 *q=(unsigned char) pixel;
6035 nibble++;
6036 break;
6037 }
6038 case 1:
6039 {
6040 *q|=(unsigned char) (pixel << 2);
6041 nibble++;
6042 break;
6043 }
6044 case 2:
6045 {
6046 *q|=(unsigned char) (pixel << 4);
6047 nibble++;
6048 break;
6049 }
6050 case 3:
6051 {
6052 *q|=(unsigned char) (pixel << 6);
6053 q++;
6054 nibble=0;
6055 break;
6056 }
6057 }
cristyed231572011-07-14 02:18:59 +00006058 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006059 }
6060 q+=scanline_pad;
6061 }
6062 break;
6063 }
6064 case 4:
6065 {
6066 register unsigned int
6067 nibble;
6068
6069 /*
6070 Convert to 4 bit color-mapped X canvas.
6071 */
6072 for (y=0; y < (int) canvas->rows; y++)
6073 {
cristyc57f6942010-11-12 01:47:39 +00006074 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006075 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006076 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006077 break;
cristy3ed852e2009-09-05 21:47:34 +00006078 nibble=0;
6079 for (x=0; x < (int) canvas->columns; x++)
6080 {
cristy4c08aed2011-07-01 19:47:50 +00006081 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006082 switch (nibble)
6083 {
6084 case 0:
6085 {
6086 *q=(unsigned char) pixel;
6087 nibble++;
6088 break;
6089 }
6090 case 1:
6091 {
6092 *q|=(unsigned char) (pixel << 4);
6093 q++;
6094 nibble=0;
6095 break;
6096 }
6097 }
cristyed231572011-07-14 02:18:59 +00006098 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006099 }
6100 q+=scanline_pad;
6101 }
6102 break;
6103 }
6104 case 6:
6105 case 8:
6106 {
6107 /*
6108 Convert to 8 bit color-mapped X canvas.
6109 */
6110 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006111 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006112 {
cristy6710d842011-10-20 23:23:00 +00006113 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006114 break;
6115 }
6116 for (y=0; y < (int) canvas->rows; y++)
6117 {
cristyc57f6942010-11-12 01:47:39 +00006118 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006119 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006120 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006121 break;
cristy3ed852e2009-09-05 21:47:34 +00006122 for (x=0; x < (int) canvas->columns; x++)
6123 {
cristy4c08aed2011-07-01 19:47:50 +00006124 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006125 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006126 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006127 }
6128 q+=scanline_pad;
6129 }
6130 break;
6131 }
6132 default:
6133 {
6134 register int
6135 k;
6136
6137 register unsigned int
6138 bytes_per_pixel;
6139
cristy3ed852e2009-09-05 21:47:34 +00006140 /*
6141 Convert to multi-byte color-mapped X canvas.
6142 */
6143 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6144 for (y=0; y < (int) canvas->rows; y++)
6145 {
cristyc57f6942010-11-12 01:47:39 +00006146 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006147 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006148 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006149 break;
cristy3ed852e2009-09-05 21:47:34 +00006150 for (x=0; x < (int) canvas->columns; x++)
6151 {
cristy4c08aed2011-07-01 19:47:50 +00006152 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006153 for (k=0; k < (int) bytes_per_pixel; k++)
6154 {
cristy42daae12013-04-07 22:36:07 +00006155 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006156 pixel>>=8;
6157 }
cristyed231572011-07-14 02:18:59 +00006158 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006159 }
6160 q+=scanline_pad;
6161 }
6162 break;
6163 }
6164 }
6165 else
6166 switch (ximage->bits_per_pixel)
6167 {
6168 case 2:
6169 {
6170 register unsigned int
6171 nibble;
6172
6173 /*
6174 Convert to contiguous 2 bit continuous-tone X canvas.
6175 */
6176 for (y=0; y < (int) canvas->rows; y++)
6177 {
6178 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006179 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006180 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006181 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006182 break;
6183 for (x=0; x < (int) canvas->columns; x++)
6184 {
cristy4c08aed2011-07-01 19:47:50 +00006185 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006186 pixel&=0xf;
6187 switch (nibble)
6188 {
6189 case 0:
6190 {
6191 *q=(unsigned char) pixel;
6192 nibble++;
6193 break;
6194 }
6195 case 1:
6196 {
6197 *q|=(unsigned char) (pixel << 2);
6198 nibble++;
6199 break;
6200 }
6201 case 2:
6202 {
6203 *q|=(unsigned char) (pixel << 4);
6204 nibble++;
6205 break;
6206 }
6207 case 3:
6208 {
6209 *q|=(unsigned char) (pixel << 6);
6210 q++;
6211 nibble=0;
6212 break;
6213 }
6214 }
cristyed231572011-07-14 02:18:59 +00006215 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006216 }
6217 q+=scanline_pad;
6218 }
6219 break;
6220 }
6221 case 4:
6222 {
6223 register unsigned int
6224 nibble;
6225
6226 /*
6227 Convert to contiguous 4 bit continuous-tone X canvas.
6228 */
6229 for (y=0; y < (int) canvas->rows; y++)
6230 {
cristyc57f6942010-11-12 01:47:39 +00006231 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006232 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006233 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006234 break;
6235 nibble=0;
6236 for (x=0; x < (int) canvas->columns; x++)
6237 {
cristy4c08aed2011-07-01 19:47:50 +00006238 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006239 pixel&=0xf;
6240 switch (nibble)
6241 {
6242 case 0:
6243 {
6244 *q=(unsigned char) pixel;
6245 nibble++;
6246 break;
6247 }
6248 case 1:
6249 {
6250 *q|=(unsigned char) (pixel << 4);
6251 q++;
6252 nibble=0;
6253 break;
6254 }
6255 }
cristyed231572011-07-14 02:18:59 +00006256 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006257 }
6258 q+=scanline_pad;
6259 }
6260 break;
6261 }
6262 case 6:
6263 case 8:
6264 {
6265 /*
6266 Convert to contiguous 8 bit continuous-tone X canvas.
6267 */
6268 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006269 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006270 {
cristy6710d842011-10-20 23:23:00 +00006271 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006272 break;
6273 }
6274 for (y=0; y < (int) canvas->rows; y++)
6275 {
cristyc57f6942010-11-12 01:47:39 +00006276 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006277 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006278 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006279 break;
6280 for (x=0; x < (int) canvas->columns; x++)
6281 {
cristy4c08aed2011-07-01 19:47:50 +00006282 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006283 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006284 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006285 }
6286 q+=scanline_pad;
6287 }
6288 break;
6289 }
6290 default:
6291 {
6292 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6293 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6294 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6295 (map_info->blue_mult == 1))
6296 {
6297 /*
6298 Convert to 32 bit continuous-tone X canvas.
6299 */
6300 for (y=0; y < (int) canvas->rows; y++)
6301 {
cristyc57f6942010-11-12 01:47:39 +00006302 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006303 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006304 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006305 break;
6306 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6307 (blue_gamma != 1.0))
6308 {
6309 /*
6310 Gamma correct canvas.
6311 */
6312 for (x=(int) canvas->columns-1; x >= 0; x--)
6313 {
cristyccf844f2010-02-03 23:28:16 +00006314 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006315 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006316 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006317 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006318 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006319 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006320 *q++=0;
cristyed231572011-07-14 02:18:59 +00006321 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006322 }
6323 continue;
6324 }
6325 for (x=(int) canvas->columns-1; x >= 0; x--)
6326 {
cristy8bc259b2012-06-21 23:53:15 +00006327 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6328 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6329 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006330 *q++=0;
cristyed231572011-07-14 02:18:59 +00006331 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006332 }
6333 }
6334 }
6335 else
6336 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6337 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6338 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6339 (map_info->blue_mult == 65536L))
6340 {
6341 /*
6342 Convert to 32 bit continuous-tone X canvas.
6343 */
6344 for (y=0; y < (int) canvas->rows; y++)
6345 {
cristyc57f6942010-11-12 01:47:39 +00006346 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006347 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006348 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006349 break;
6350 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6351 (blue_gamma != 1.0))
6352 {
6353 /*
6354 Gamma correct canvas.
6355 */
6356 for (x=(int) canvas->columns-1; x >= 0; x--)
6357 {
cristyccf844f2010-02-03 23:28:16 +00006358 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006359 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006360 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006361 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006362 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006363 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006364 *q++=0;
cristyed231572011-07-14 02:18:59 +00006365 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006366 }
6367 continue;
6368 }
6369 for (x=(int) canvas->columns-1; x >= 0; x--)
6370 {
cristy8bc259b2012-06-21 23:53:15 +00006371 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6372 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6373 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006374 *q++=0;
cristyed231572011-07-14 02:18:59 +00006375 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006376 }
6377 }
6378 }
6379 else
6380 {
6381 register int
6382 k;
6383
6384 register unsigned int
6385 bytes_per_pixel;
6386
cristy3ed852e2009-09-05 21:47:34 +00006387 /*
6388 Convert to multi-byte continuous-tone X canvas.
6389 */
6390 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6391 for (y=0; y < (int) canvas->rows; y++)
6392 {
cristyc57f6942010-11-12 01:47:39 +00006393 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006394 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006395 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006396 break;
cristyc57f6942010-11-12 01:47:39 +00006397 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006398 {
cristy4c08aed2011-07-01 19:47:50 +00006399 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006400 for (k=0; k < (int) bytes_per_pixel; k++)
6401 {
cristy42daae12013-04-07 22:36:07 +00006402 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006403 pixel>>=8;
6404 }
cristyed231572011-07-14 02:18:59 +00006405 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006406 }
6407 q+=scanline_pad;
6408 }
6409 }
6410 break;
6411 }
6412 }
6413 if (matte_image != (XImage *) NULL)
6414 {
6415 /*
6416 Initialize matte canvas.
6417 */
6418 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6419 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6420 q=(unsigned char *) matte_image->data;
6421 for (y=0; y < (int) canvas->rows; y++)
6422 {
cristyc57f6942010-11-12 01:47:39 +00006423 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006424 exception);
cristy4c08aed2011-07-01 19:47:50 +00006425 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006426 break;
6427 bit=0;
6428 byte=0;
6429 for (x=(int) canvas->columns-1; x >= 0; x--)
6430 {
6431 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006432 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006433 byte|=0x80;
6434 bit++;
6435 if (bit == 8)
6436 {
6437 *q++=byte;
6438 bit=0;
6439 byte=0;
6440 }
cristyed231572011-07-14 02:18:59 +00006441 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006442 }
6443 if (bit != 0)
6444 *q=byte >> (8-bit);
6445 q+=scanline_pad;
6446 }
6447 }
cristyc57f6942010-11-12 01:47:39 +00006448 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006449 if (canvas != image)
6450 canvas=DestroyImage(canvas);
6451}
6452
6453/*
6454%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6455% %
6456% %
6457% %
6458+ X M a k e I m a g e M S B F i r s t %
6459% %
6460% %
6461% %
6462%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6463%
6464% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6465% image pixels are copied in most-significant bit and byte first order. The
6466% server's scanline pad is also respected. Rather than using one or two
6467% general cases, many special cases are found here to help speed up the image
6468% conversion.
6469%
6470% The format of the XMakeImageMSBFirst method is:
6471%
cristye941a752011-10-15 01:52:48 +00006472% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6473% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006474%
6475% A description of each parameter follows:
6476%
6477% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6478%
6479% o window: Specifies a pointer to a XWindowInfo structure.
6480%
6481% o image: the image.
6482%
6483% o ximage: Specifies a pointer to a XImage structure; returned from
6484% XCreateImage.
6485%
6486% o matte_image: Specifies a pointer to a XImage structure; returned from
6487% XCreateImage.
6488%
cristye941a752011-10-15 01:52:48 +00006489% o exception: return any errors or warnings in this structure.
6490%
cristy3ed852e2009-09-05 21:47:34 +00006491*/
6492static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006493 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6494 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006495{
cristyc57f6942010-11-12 01:47:39 +00006496 CacheView
6497 *canvas_view;
6498
cristy3ed852e2009-09-05 21:47:34 +00006499 Image
6500 *canvas;
6501
6502 int
6503 y;
6504
6505 register int
6506 x;
6507
cristy4c08aed2011-07-01 19:47:50 +00006508 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006509 *p;
6510
6511 register unsigned char
6512 *q;
6513
6514 unsigned char
6515 bit,
6516 byte;
6517
6518 unsigned int
6519 scanline_pad;
6520
cristyf2faecf2010-05-28 19:19:36 +00006521 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006522 pixel,
6523 *pixels;
6524
6525 XStandardColormap
6526 *map_info;
6527
6528 assert(resource_info != (XResourceInfo *) NULL);
6529 assert(window != (XWindowInfo *) NULL);
6530 assert(image != (Image *) NULL);
6531 if (image->debug != MagickFalse)
6532 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6533 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006534 if ((window->immutable != MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00006535 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00006536 {
6537 char
6538 size[MaxTextExtent];
6539
6540 Image
6541 *pattern;
6542
6543 ImageInfo
6544 *image_info;
6545
6546 image_info=AcquireImageInfo();
6547 (void) CopyMagickString(image_info->filename,
6548 resource_info->image_info->texture != (char *) NULL ?
6549 resource_info->image_info->texture : "pattern:checkerboard",
6550 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006551 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006552 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006553 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006554 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006555 image_info=DestroyImageInfo(image_info);
6556 if (pattern != (Image *) NULL)
6557 {
cristy6710d842011-10-20 23:23:00 +00006558 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006559 if (canvas != (Image *) NULL)
cristyfeb3e962012-03-29 17:25:55 +00006560 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6561 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00006562 pattern=DestroyImage(pattern);
6563 }
6564 }
cristy4c08aed2011-07-01 19:47:50 +00006565 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6566 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006567 map_info=window->map_info;
6568 pixels=window->pixel_info->pixels;
6569 q=(unsigned char *) ximage->data;
6570 x=0;
cristy46ff2672012-12-14 15:32:26 +00006571 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00006572 if (ximage->format == XYBitmap)
6573 {
6574 register unsigned short
6575 polarity;
6576
6577 unsigned char
6578 background,
6579 foreground;
6580
6581 /*
6582 Convert canvas to big-endian bitmap.
6583 */
6584 background=(unsigned char)
6585 (XPixelIntensity(&window->pixel_info->foreground_color) <
6586 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6587 foreground=(unsigned char)
6588 (XPixelIntensity(&window->pixel_info->background_color) <
6589 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006590 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00006591 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00006592 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006593 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6594 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006595 for (y=0; y < (int) canvas->rows; y++)
6596 {
cristyc57f6942010-11-12 01:47:39 +00006597 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006598 exception);
cristy4c08aed2011-07-01 19:47:50 +00006599 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006600 break;
cristy3ed852e2009-09-05 21:47:34 +00006601 bit=0;
6602 byte=0;
6603 for (x=(int) canvas->columns-1; x >= 0; x--)
6604 {
6605 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006606 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006607 byte|=foreground;
6608 else
6609 byte|=background;
6610 bit++;
6611 if (bit == 8)
6612 {
6613 *q++=byte;
6614 bit=0;
6615 byte=0;
6616 }
cristyed231572011-07-14 02:18:59 +00006617 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006618 }
6619 if (bit != 0)
6620 *q=byte << (8-bit);
6621 q+=scanline_pad;
6622 }
6623 }
6624 else
6625 if (window->pixel_info->colors != 0)
6626 switch (ximage->bits_per_pixel)
6627 {
6628 case 2:
6629 {
6630 register unsigned int
6631 nibble;
6632
6633 /*
6634 Convert to 2 bit color-mapped X canvas.
6635 */
6636 for (y=0; y < (int) canvas->rows; y++)
6637 {
cristyc57f6942010-11-12 01:47:39 +00006638 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006639 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006640 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006641 break;
cristy3ed852e2009-09-05 21:47:34 +00006642 nibble=0;
6643 for (x=0; x < (int) canvas->columns; x++)
6644 {
cristy4c08aed2011-07-01 19:47:50 +00006645 pixel=pixels[(ssize_t)
6646 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006647 switch (nibble)
6648 {
6649 case 0:
6650 {
6651 *q=(unsigned char) (pixel << 6);
6652 nibble++;
6653 break;
6654 }
6655 case 1:
6656 {
6657 *q|=(unsigned char) (pixel << 4);
6658 nibble++;
6659 break;
6660 }
6661 case 2:
6662 {
6663 *q|=(unsigned char) (pixel << 2);
6664 nibble++;
6665 break;
6666 }
6667 case 3:
6668 {
6669 *q|=(unsigned char) pixel;
6670 q++;
6671 nibble=0;
6672 break;
6673 }
6674 }
cristyed231572011-07-14 02:18:59 +00006675 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006676 }
6677 q+=scanline_pad;
6678 }
6679 break;
6680 }
6681 case 4:
6682 {
6683 register unsigned int
6684 nibble;
6685
6686 /*
6687 Convert to 4 bit color-mapped X canvas.
6688 */
6689 for (y=0; y < (int) canvas->rows; y++)
6690 {
cristyc57f6942010-11-12 01:47:39 +00006691 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006692 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006693 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006694 break;
cristy3ed852e2009-09-05 21:47:34 +00006695 nibble=0;
6696 for (x=0; x < (int) canvas->columns; x++)
6697 {
cristy4c08aed2011-07-01 19:47:50 +00006698 pixel=pixels[(ssize_t)
6699 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006700 switch (nibble)
6701 {
6702 case 0:
6703 {
6704 *q=(unsigned char) (pixel << 4);
6705 nibble++;
6706 break;
6707 }
6708 case 1:
6709 {
6710 *q|=(unsigned char) pixel;
6711 q++;
6712 nibble=0;
6713 break;
6714 }
6715 }
cristyed231572011-07-14 02:18:59 +00006716 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006717 }
6718 q+=scanline_pad;
6719 }
6720 break;
6721 }
6722 case 6:
6723 case 8:
6724 {
6725 /*
6726 Convert to 8 bit color-mapped X canvas.
6727 */
6728 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006729 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006730 {
cristy6710d842011-10-20 23:23:00 +00006731 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006732 break;
6733 }
6734 for (y=0; y < (int) canvas->rows; y++)
6735 {
cristyc57f6942010-11-12 01:47:39 +00006736 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006737 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006738 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006739 break;
cristy3ed852e2009-09-05 21:47:34 +00006740 for (x=0; x < (int) canvas->columns; x++)
6741 {
cristy6710d842011-10-20 23:23:00 +00006742 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006743 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006744 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006745 }
6746 q+=scanline_pad;
6747 }
6748 break;
6749 }
6750 default:
6751 {
6752 register int
6753 k;
6754
6755 register unsigned int
6756 bytes_per_pixel;
6757
6758 unsigned char
cristybb503372010-05-27 20:51:26 +00006759 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006760
6761 /*
6762 Convert to 8 bit color-mapped X canvas.
6763 */
6764 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6765 for (y=0; y < (int) canvas->rows; y++)
6766 {
cristyc57f6942010-11-12 01:47:39 +00006767 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006768 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006769 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006770 break;
cristy3ed852e2009-09-05 21:47:34 +00006771 for (x=0; x < (int) canvas->columns; x++)
6772 {
cristy4c08aed2011-07-01 19:47:50 +00006773 pixel=pixels[(ssize_t)
6774 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006775 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6776 {
6777 channel[k]=(unsigned char) pixel;
6778 pixel>>=8;
6779 }
6780 for (k=0; k < (int) bytes_per_pixel; k++)
6781 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006782 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006783 }
6784 q+=scanline_pad;
6785 }
6786 break;
6787 }
6788 }
6789 else
6790 switch (ximage->bits_per_pixel)
6791 {
6792 case 2:
6793 {
6794 register unsigned int
6795 nibble;
6796
6797 /*
6798 Convert to 4 bit continuous-tone X canvas.
6799 */
6800 for (y=0; y < (int) canvas->rows; y++)
6801 {
cristyc57f6942010-11-12 01:47:39 +00006802 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006803 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006804 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006805 break;
6806 nibble=0;
6807 for (x=(int) canvas->columns-1; x >= 0; x--)
6808 {
cristy4c08aed2011-07-01 19:47:50 +00006809 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006810 pixel&=0xf;
6811 switch (nibble)
6812 {
6813 case 0:
6814 {
6815 *q=(unsigned char) (pixel << 6);
6816 nibble++;
6817 break;
6818 }
6819 case 1:
6820 {
6821 *q|=(unsigned char) (pixel << 4);
6822 nibble++;
6823 break;
6824 }
6825 case 2:
6826 {
6827 *q|=(unsigned char) (pixel << 2);
6828 nibble++;
6829 break;
6830 }
6831 case 3:
6832 {
6833 *q|=(unsigned char) pixel;
6834 q++;
6835 nibble=0;
6836 break;
6837 }
6838 }
cristyed231572011-07-14 02:18:59 +00006839 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006840 }
6841 q+=scanline_pad;
6842 }
6843 break;
6844 }
6845 case 4:
6846 {
6847 register unsigned int
6848 nibble;
6849
6850 /*
6851 Convert to 4 bit continuous-tone X canvas.
6852 */
6853 for (y=0; y < (int) canvas->rows; y++)
6854 {
cristyc57f6942010-11-12 01:47:39 +00006855 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006856 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006857 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006858 break;
6859 nibble=0;
6860 for (x=(int) canvas->columns-1; x >= 0; x--)
6861 {
cristy4c08aed2011-07-01 19:47:50 +00006862 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006863 pixel&=0xf;
6864 switch (nibble)
6865 {
6866 case 0:
6867 {
6868 *q=(unsigned char) (pixel << 4);
6869 nibble++;
6870 break;
6871 }
6872 case 1:
6873 {
6874 *q|=(unsigned char) pixel;
6875 q++;
6876 nibble=0;
6877 break;
6878 }
6879 }
cristyed231572011-07-14 02:18:59 +00006880 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006881 }
6882 q+=scanline_pad;
6883 }
6884 break;
6885 }
6886 case 6:
6887 case 8:
6888 {
6889 /*
6890 Convert to 8 bit continuous-tone X canvas.
6891 */
6892 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006893 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006894 {
cristy6710d842011-10-20 23:23:00 +00006895 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006896 break;
6897 }
6898 for (y=0; y < (int) canvas->rows; y++)
6899 {
cristyc57f6942010-11-12 01:47:39 +00006900 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006901 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006902 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006903 break;
6904 for (x=(int) canvas->columns-1; x >= 0; x--)
6905 {
cristy4c08aed2011-07-01 19:47:50 +00006906 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006907 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006908 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006909 }
6910 q+=scanline_pad;
6911 }
6912 break;
6913 }
6914 default:
6915 {
6916 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6917 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6918 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6919 (map_info->blue_mult == 1))
6920 {
6921 /*
6922 Convert to 32 bit continuous-tone X canvas.
6923 */
6924 for (y=0; y < (int) canvas->rows; y++)
6925 {
cristyc57f6942010-11-12 01:47:39 +00006926 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006927 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006928 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006929 break;
6930 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6931 (blue_gamma != 1.0))
6932 {
6933 /*
6934 Gamma correct canvas.
6935 */
6936 for (x=(int) canvas->columns-1; x >= 0; x--)
6937 {
6938 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006939 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006940 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006941 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006942 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006943 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006944 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006945 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006946 }
6947 continue;
6948 }
6949 for (x=(int) canvas->columns-1; x >= 0; x--)
6950 {
6951 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006952 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6953 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6954 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006955 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006956 }
6957 }
6958 }
6959 else
6960 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6961 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6962 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6963 (map_info->blue_mult == 65536L))
6964 {
6965 /*
6966 Convert to 32 bit continuous-tone X canvas.
6967 */
6968 for (y=0; y < (int) canvas->rows; y++)
6969 {
cristyc57f6942010-11-12 01:47:39 +00006970 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006971 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006972 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006973 break;
6974 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6975 (blue_gamma != 1.0))
6976 {
6977 /*
6978 Gamma correct canvas.
6979 */
6980 for (x=(int) canvas->columns-1; x >= 0; x--)
6981 {
6982 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006983 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006984 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006985 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006986 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006987 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006988 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006989 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006990 }
6991 continue;
6992 }
6993 for (x=(int) canvas->columns-1; x >= 0; x--)
6994 {
6995 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006996 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6997 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6998 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006999 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007000 }
7001 }
7002 }
7003 else
7004 {
7005 register int
7006 k;
7007
7008 register unsigned int
7009 bytes_per_pixel;
7010
7011 unsigned char
cristybb503372010-05-27 20:51:26 +00007012 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007013
7014 /*
7015 Convert to multi-byte continuous-tone X canvas.
7016 */
7017 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7018 for (y=0; y < (int) canvas->rows; y++)
7019 {
cristyc57f6942010-11-12 01:47:39 +00007020 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007021 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007022 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007023 break;
7024 for (x=(int) canvas->columns-1; x >= 0; x--)
7025 {
cristy4c08aed2011-07-01 19:47:50 +00007026 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007027 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7028 {
7029 channel[k]=(unsigned char) pixel;
7030 pixel>>=8;
7031 }
7032 for (k=0; k < (int) bytes_per_pixel; k++)
7033 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007034 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007035 }
7036 q+=scanline_pad;
7037 }
7038 }
7039 break;
7040 }
7041 }
7042 if (matte_image != (XImage *) NULL)
7043 {
7044 /*
7045 Initialize matte canvas.
7046 */
7047 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7048 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7049 q=(unsigned char *) matte_image->data;
7050 for (y=0; y < (int) canvas->rows; y++)
7051 {
cristyc57f6942010-11-12 01:47:39 +00007052 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007053 exception);
cristy4c08aed2011-07-01 19:47:50 +00007054 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007055 break;
7056 bit=0;
7057 byte=0;
7058 for (x=(int) canvas->columns-1; x >= 0; x--)
7059 {
7060 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007061 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007062 byte|=0x01;
7063 bit++;
7064 if (bit == 8)
7065 {
7066 *q++=byte;
7067 bit=0;
7068 byte=0;
7069 }
cristyed231572011-07-14 02:18:59 +00007070 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007071 }
7072 if (bit != 0)
7073 *q=byte << (8-bit);
7074 q+=scanline_pad;
7075 }
7076 }
cristyc57f6942010-11-12 01:47:39 +00007077 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007078 if (canvas != image)
7079 canvas=DestroyImage(canvas);
7080}
7081
7082/*
7083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7084% %
7085% %
7086% %
7087% X M a k e M a g n i f y I m a g e %
7088% %
7089% %
7090% %
7091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7092%
7093% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7094%
7095% The format of the XMakeMagnifyImage method is:
7096%
cristy6710d842011-10-20 23:23:00 +00007097% void XMakeMagnifyImage(Display *display,XWindows *windows,
7098% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007099%
7100% A description of each parameter follows:
7101%
7102% o display: Specifies a connection to an X server; returned from
7103% XOpenDisplay.
7104%
7105% o windows: Specifies a pointer to a XWindows structure.
7106%
cristy6710d842011-10-20 23:23:00 +00007107% o exception: return any errors or warnings in this structure.
7108%
cristy3ed852e2009-09-05 21:47:34 +00007109*/
cristy6710d842011-10-20 23:23:00 +00007110MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7111 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007112{
7113 char
7114 tuple[MaxTextExtent];
7115
7116 int
7117 y;
7118
cristy4c08aed2011-07-01 19:47:50 +00007119 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007120 pixel;
7121
7122 register int
7123 x;
7124
cristybb503372010-05-27 20:51:26 +00007125 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007126 i;
7127
7128 register unsigned char
7129 *p,
7130 *q;
7131
cristy9d314ff2011-03-09 01:30:28 +00007132 ssize_t
7133 n;
7134
cristy3ed852e2009-09-05 21:47:34 +00007135 static unsigned int
7136 previous_magnify = 0;
7137
7138 static XWindowInfo
7139 magnify_window;
7140
7141 unsigned int
7142 height,
7143 j,
7144 k,
7145 l,
7146 magnify,
7147 scanline_pad,
7148 width;
7149
7150 XImage
7151 *ximage;
7152
7153 /*
7154 Check boundary conditions.
7155 */
7156 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7157 assert(display != (Display *) NULL);
7158 assert(windows != (XWindows *) NULL);
7159 magnify=1;
cristybb503372010-05-27 20:51:26 +00007160 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007161 magnify<<=1;
7162 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7163 magnify<<=1;
7164 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7165 magnify<<=1;
7166 while (magnify > windows->magnify.width)
7167 magnify>>=1;
7168 while (magnify > windows->magnify.height)
7169 magnify>>=1;
7170 if (magnify != previous_magnify)
7171 {
7172 Status
7173 status;
7174
7175 XTextProperty
7176 window_name;
7177
7178 /*
7179 New magnify factor: update magnify window name.
7180 */
7181 i=0;
7182 while ((1 << i) <= (int) magnify)
7183 i++;
cristyb51dff52011-05-19 16:55:47 +00007184 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007185 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007186 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7187 if (status != False)
7188 {
7189 XSetWMName(display,windows->magnify.id,&window_name);
7190 XSetWMIconName(display,windows->magnify.id,&window_name);
7191 (void) XFree((void *) window_name.value);
7192 }
7193 }
7194 previous_magnify=magnify;
7195 ximage=windows->image.ximage;
7196 width=(unsigned int) windows->magnify.ximage->width;
7197 height=(unsigned int) windows->magnify.ximage->height;
7198 if ((windows->magnify.x < 0) ||
7199 (windows->magnify.x >= windows->image.ximage->width))
7200 windows->magnify.x=windows->image.ximage->width >> 1;
7201 x=windows->magnify.x-((width/magnify) >> 1);
7202 if (x < 0)
7203 x=0;
7204 else
7205 if (x > (int) (ximage->width-(width/magnify)))
7206 x=ximage->width-width/magnify;
7207 if ((windows->magnify.y < 0) ||
7208 (windows->magnify.y >= windows->image.ximage->height))
7209 windows->magnify.y=windows->image.ximage->height >> 1;
7210 y=windows->magnify.y-((height/magnify) >> 1);
7211 if (y < 0)
7212 y=0;
7213 else
7214 if (y > (int) (ximage->height-(height/magnify)))
7215 y=ximage->height-height/magnify;
7216 q=(unsigned char *) windows->magnify.ximage->data;
7217 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7218 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7219 if (ximage->bits_per_pixel < 8)
7220 {
7221 register unsigned char
7222 background,
7223 byte,
7224 foreground,
7225 p_bit,
7226 q_bit;
7227
7228 register unsigned int
7229 plane;
7230
7231 XPixelInfo
7232 *pixel_info;
7233
7234 pixel_info=windows->magnify.pixel_info;
7235 switch (ximage->bitmap_bit_order)
7236 {
7237 case LSBFirst:
7238 {
7239 /*
7240 Magnify little-endian bitmap.
7241 */
7242 background=0x00;
7243 foreground=0x80;
7244 if (ximage->format == XYBitmap)
7245 {
7246 background=(unsigned char)
7247 (XPixelIntensity(&pixel_info->foreground_color) <
7248 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7249 foreground=(unsigned char)
7250 (XPixelIntensity(&pixel_info->background_color) <
7251 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7252 if (windows->magnify.depth > 1)
7253 Swap(background,foreground);
7254 }
cristybb503372010-05-27 20:51:26 +00007255 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007256 {
7257 /*
7258 Propogate pixel magnify rows.
7259 */
7260 for (j=0; j < magnify; j++)
7261 {
7262 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7263 ((x*ximage->bits_per_pixel) >> 3);
7264 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7265 q_bit=0;
7266 byte=0;
7267 for (k=0; k < width; k+=magnify)
7268 {
7269 /*
7270 Propogate pixel magnify columns.
7271 */
7272 for (l=0; l < magnify; l++)
7273 {
7274 /*
7275 Propogate each bit plane.
7276 */
7277 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7278 {
7279 byte>>=1;
7280 if (*p & (0x01 << (p_bit+plane)))
7281 byte|=foreground;
7282 else
7283 byte|=background;
7284 q_bit++;
7285 if (q_bit == 8)
7286 {
7287 *q++=byte;
7288 q_bit=0;
7289 byte=0;
7290 }
7291 }
7292 }
7293 p_bit+=ximage->bits_per_pixel;
7294 if (p_bit == 8)
7295 {
7296 p++;
7297 p_bit=0;
7298 }
7299 if (q_bit != 0)
7300 *q=byte >> (8-q_bit);
7301 q+=scanline_pad;
7302 }
7303 }
7304 y++;
7305 }
7306 break;
7307 }
7308 case MSBFirst:
7309 default:
7310 {
7311 /*
7312 Magnify big-endian bitmap.
7313 */
7314 background=0x00;
7315 foreground=0x01;
7316 if (ximage->format == XYBitmap)
7317 {
7318 background=(unsigned char)
7319 (XPixelIntensity(&pixel_info->foreground_color) <
7320 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7321 foreground=(unsigned char)
7322 (XPixelIntensity(&pixel_info->background_color) <
7323 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7324 if (windows->magnify.depth > 1)
7325 Swap(background,foreground);
7326 }
cristybb503372010-05-27 20:51:26 +00007327 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007328 {
7329 /*
7330 Propogate pixel magnify rows.
7331 */
7332 for (j=0; j < magnify; j++)
7333 {
7334 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7335 ((x*ximage->bits_per_pixel) >> 3);
7336 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7337 q_bit=0;
7338 byte=0;
7339 for (k=0; k < width; k+=magnify)
7340 {
7341 /*
7342 Propogate pixel magnify columns.
7343 */
7344 for (l=0; l < magnify; l++)
7345 {
7346 /*
7347 Propogate each bit plane.
7348 */
7349 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7350 {
7351 byte<<=1;
7352 if (*p & (0x80 >> (p_bit+plane)))
7353 byte|=foreground;
7354 else
7355 byte|=background;
7356 q_bit++;
7357 if (q_bit == 8)
7358 {
7359 *q++=byte;
7360 q_bit=0;
7361 byte=0;
7362 }
7363 }
7364 }
7365 p_bit+=ximage->bits_per_pixel;
7366 if (p_bit == 8)
7367 {
7368 p++;
7369 p_bit=0;
7370 }
7371 if (q_bit != 0)
7372 *q=byte << (8-q_bit);
7373 q+=scanline_pad;
7374 }
7375 }
7376 y++;
7377 }
7378 break;
7379 }
7380 }
7381 }
7382 else
7383 switch (ximage->bits_per_pixel)
7384 {
7385 case 6:
7386 case 8:
7387 {
7388 /*
7389 Magnify 8 bit X image.
7390 */
cristybb503372010-05-27 20:51:26 +00007391 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007392 {
7393 /*
7394 Propogate pixel magnify rows.
7395 */
7396 for (j=0; j < magnify; j++)
7397 {
7398 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7399 ((x*ximage->bits_per_pixel) >> 3);
7400 for (k=0; k < width; k+=magnify)
7401 {
7402 /*
7403 Propogate pixel magnify columns.
7404 */
7405 for (l=0; l < magnify; l++)
7406 *q++=(*p);
7407 p++;
7408 }
7409 q+=scanline_pad;
7410 }
7411 y++;
7412 }
7413 break;
7414 }
7415 default:
7416 {
7417 register unsigned int
7418 bytes_per_pixel,
7419 m;
7420
7421 /*
7422 Magnify multi-byte X image.
7423 */
7424 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007425 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007426 {
7427 /*
7428 Propogate pixel magnify rows.
7429 */
7430 for (j=0; j < magnify; j++)
7431 {
7432 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7433 ((x*ximage->bits_per_pixel) >> 3);
7434 for (k=0; k < width; k+=magnify)
7435 {
7436 /*
7437 Propogate pixel magnify columns.
7438 */
7439 for (l=0; l < magnify; l++)
7440 for (m=0; m < bytes_per_pixel; m++)
7441 *q++=(*(p+m));
7442 p+=bytes_per_pixel;
7443 }
7444 q+=scanline_pad;
7445 }
7446 y++;
7447 }
7448 break;
7449 }
7450 }
7451 /*
7452 Copy X image to magnify pixmap.
7453 */
7454 x=windows->magnify.x-((width/magnify) >> 1);
7455 if (x < 0)
7456 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7457 else
7458 if (x > (int) (ximage->width-(width/magnify)))
7459 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7460 else
7461 x=0;
7462 y=windows->magnify.y-((height/magnify) >> 1);
7463 if (y < 0)
7464 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7465 else
7466 if (y > (int) (ximage->height-(height/magnify)))
7467 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7468 else
7469 y=0;
7470 if ((x != 0) || (y != 0))
7471 (void) XFillRectangle(display,windows->magnify.pixmap,
7472 windows->magnify.annotate_context,0,0,width,height);
7473 (void) XPutImage(display,windows->magnify.pixmap,
7474 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7475 height-y);
7476 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7477 (magnify <= (height >> 1))))
7478 {
7479 RectangleInfo
7480 highlight_info;
7481
7482 /*
7483 Highlight center pixel.
7484 */
cristybb503372010-05-27 20:51:26 +00007485 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7486 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007487 highlight_info.width=magnify;
7488 highlight_info.height=magnify;
7489 (void) XDrawRectangle(display,windows->magnify.pixmap,
7490 windows->magnify.highlight_context,(int) highlight_info.x,
7491 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7492 (unsigned int) highlight_info.height-1);
7493 if (magnify > 2)
7494 (void) XDrawRectangle(display,windows->magnify.pixmap,
7495 windows->magnify.annotate_context,(int) highlight_info.x+1,
7496 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7497 (unsigned int) highlight_info.height-3);
7498 }
7499 /*
7500 Show center pixel color.
7501 */
cristy3aa93752011-12-18 15:54:24 +00007502 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007503 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007504 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007505 windows->magnify.x,windows->magnify.y);
7506 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007507 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007508 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007509 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007510 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007511 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007512 if (pixel.colorspace == CMYKColorspace)
7513 {
7514 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007515 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007516 }
cristy8a46d822012-08-28 23:32:39 +00007517 if (pixel.alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00007518 {
7519 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007520 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007521 }
7522 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7523 height=(unsigned int) windows->magnify.font_info->ascent+
7524 windows->magnify.font_info->descent;
7525 x=windows->magnify.font_info->max_bounds.width >> 1;
7526 y=windows->magnify.font_info->ascent+(height >> 2);
7527 (void) XDrawImageString(display,windows->magnify.pixmap,
7528 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7529 GetColorTuple(&pixel,MagickTrue,tuple);
7530 y+=height;
7531 (void) XDrawImageString(display,windows->magnify.pixmap,
7532 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007533 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007534 exception);
cristy3ed852e2009-09-05 21:47:34 +00007535 y+=height;
7536 (void) XDrawImageString(display,windows->magnify.pixmap,
7537 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7538 /*
7539 Refresh magnify window.
7540 */
7541 magnify_window=windows->magnify;
7542 magnify_window.x=0;
7543 magnify_window.y=0;
7544 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7545}
7546
7547/*
7548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7549% %
7550% %
7551% %
7552% X M a k e P i x m a p %
7553% %
7554% %
7555% %
7556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7557%
7558% XMakePixmap() creates an X11 pixmap.
7559%
7560% The format of the XMakePixmap method is:
7561%
7562% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7563% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7564% XPixelInfo *pixel)
7565%
7566% A description of each parameter follows:
7567%
7568% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7569%
7570% o display: Specifies a connection to an X server; returned from
7571% XOpenDisplay.
7572%
7573% o window: Specifies a pointer to a XWindowInfo structure.
7574%
cristy3ed852e2009-09-05 21:47:34 +00007575*/
7576static MagickBooleanType XMakePixmap(Display *display,
7577 const XResourceInfo *resource_info,XWindowInfo *window)
7578{
7579 unsigned int
7580 height,
7581 width;
7582
7583 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7584 assert(display != (Display *) NULL);
7585 assert(resource_info != (XResourceInfo *) NULL);
7586 assert(window != (XWindowInfo *) NULL);
7587 if (window->pixmap != (Pixmap) NULL)
7588 {
7589 /*
7590 Destroy previous X pixmap.
7591 */
7592 (void) XFreePixmap(display,window->pixmap);
7593 window->pixmap=(Pixmap) NULL;
7594 }
7595 if (window->use_pixmap == MagickFalse)
7596 return(MagickFalse);
7597 if (window->ximage == (XImage *) NULL)
7598 return(MagickFalse);
7599 /*
7600 Display busy cursor.
7601 */
7602 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7603 (void) XFlush(display);
7604 /*
7605 Create pixmap.
7606 */
7607 width=(unsigned int) window->ximage->width;
7608 height=(unsigned int) window->ximage->height;
7609 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7610 if (window->pixmap == (Pixmap) NULL)
7611 {
7612 /*
7613 Unable to allocate pixmap.
7614 */
7615 (void) XCheckDefineCursor(display,window->id,window->cursor);
7616 return(MagickFalse);
7617 }
7618 /*
7619 Copy X image to pixmap.
7620 */
7621#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7622 if (window->shared_memory)
7623 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7624 window->ximage,0,0,0,0,width,height,MagickTrue);
7625#endif
7626 if (window->shared_memory == MagickFalse)
7627 (void) XPutImage(display,window->pixmap,window->annotate_context,
7628 window->ximage,0,0,0,0,width,height);
7629 if (IsEventLogging())
7630 {
7631 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7632 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7633 width,height);
7634 }
7635 /*
7636 Restore cursor.
7637 */
7638 (void) XCheckDefineCursor(display,window->id,window->cursor);
7639 return(MagickTrue);
7640}
7641
7642/*
7643%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7644% %
7645% %
7646% %
7647% X M a k e S t a n d a r d C o l o r m a p %
7648% %
7649% %
7650% %
7651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7652%
7653% XMakeStandardColormap() creates an X11 Standard Colormap.
7654%
7655% The format of the XMakeStandardColormap method is:
7656%
cristy6710d842011-10-20 23:23:00 +00007657% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7658% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7659% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007660%
7661% A description of each parameter follows:
7662%
7663% o display: Specifies a connection to an X server; returned from
7664% XOpenDisplay.
7665%
7666% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7667% returned from XGetVisualInfo.
7668%
7669% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7670%
7671% o image: the image.
7672%
7673% o map_info: If a Standard Colormap type is specified, this structure is
7674% initialized with info from the Standard Colormap.
7675%
7676% o pixel: Specifies a pointer to a XPixelInfo structure.
7677%
cristy6710d842011-10-20 23:23:00 +00007678% o exception: return any errors or warnings in this structure.
7679%
cristy3ed852e2009-09-05 21:47:34 +00007680*/
7681
7682#if defined(__cplusplus) || defined(c_plusplus)
7683extern "C" {
7684#endif
7685
cristya19f1d72012-08-07 18:24:38 +00007686static inline double DiversityPixelIntensity(
cristy3ed852e2009-09-05 21:47:34 +00007687 const DiversityPacket *pixel)
7688{
cristya19f1d72012-08-07 18:24:38 +00007689 double
cristy3ed852e2009-09-05 21:47:34 +00007690 intensity;
7691
cristyd3d2a272013-06-24 16:09:41 +00007692 intensity=0.212656*pixel->red+0.715158*pixel->green+0.072186*pixel->blue;
cristy3ed852e2009-09-05 21:47:34 +00007693 return(intensity);
7694}
7695
7696static int IntensityCompare(const void *x,const void *y)
7697{
7698 DiversityPacket
7699 *color_1,
7700 *color_2;
7701
7702 int
7703 diversity;
7704
7705 color_1=(DiversityPacket *) x;
7706 color_2=(DiversityPacket *) y;
7707 diversity=(int) (DiversityPixelIntensity(color_2)-
7708 DiversityPixelIntensity(color_1));
7709 return(diversity);
7710}
7711
7712static int PopularityCompare(const void *x,const void *y)
7713{
7714 DiversityPacket
7715 *color_1,
7716 *color_2;
7717
7718 color_1=(DiversityPacket *) x;
7719 color_2=(DiversityPacket *) y;
7720 return((int) color_2->count-(int) color_1->count);
7721}
7722
7723#if defined(__cplusplus) || defined(c_plusplus)
7724}
7725#endif
7726
cristybb503372010-05-27 20:51:26 +00007727static inline Quantum ScaleXToQuantum(const size_t x,
7728 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007729{
cristya19f1d72012-08-07 18:24:38 +00007730 return((Quantum) (((double) QuantumRange*x)/scale+0.5));
cristy3ed852e2009-09-05 21:47:34 +00007731}
7732
cristybcbda3f2011-09-03 13:01:22 +00007733MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007734 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007735 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007736{
7737 Colormap
7738 colormap;
7739
cristybb503372010-05-27 20:51:26 +00007740 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007741 i;
7742
7743 Status
7744 status;
7745
cristybb503372010-05-27 20:51:26 +00007746 size_t
cristy3ed852e2009-09-05 21:47:34 +00007747 number_colors,
7748 retain_colors;
7749
7750 unsigned short
7751 gray_value;
7752
7753 XColor
7754 color,
7755 *colors,
7756 *p;
7757
7758 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7759 assert(display != (Display *) NULL);
7760 assert(visual_info != (XVisualInfo *) NULL);
7761 assert(map_info != (XStandardColormap *) NULL);
7762 assert(resource_info != (XResourceInfo *) NULL);
7763 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007764 if (resource_info->map_type != (char *) NULL)
7765 {
7766 /*
7767 Standard Colormap is already defined (i.e. xstdcmap).
7768 */
cristy4c08aed2011-07-01 19:47:50 +00007769 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007770 pixel);
7771 number_colors=(unsigned int) (map_info->base_pixel+
7772 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7773 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
cristy8a46d822012-08-28 23:32:39 +00007774 if ((image->alpha_trait != BlendPixelTrait) &&
cristy3ed852e2009-09-05 21:47:34 +00007775 (resource_info->color_recovery == MagickFalse) &&
cristycbda6112012-05-27 20:57:16 +00007776 (resource_info->quantize_info->dither_method != NoDitherMethod) &&
cristy3ed852e2009-09-05 21:47:34 +00007777 (number_colors < MaxColormapSize))
7778 {
7779 Image
7780 *affinity_image;
7781
cristy4c08aed2011-07-01 19:47:50 +00007782 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007783 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007784
7785 /*
7786 Improve image appearance with error diffusion.
7787 */
cristy6710d842011-10-20 23:23:00 +00007788 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007789 if (affinity_image == (Image *) NULL)
7790 ThrowXWindowFatalException(ResourceLimitFatalError,
7791 "UnableToDitherImage",image->filename);
7792 affinity_image->columns=number_colors;
7793 affinity_image->rows=1;
7794 /*
7795 Initialize colormap image.
7796 */
7797 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7798 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007799 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007800 {
cristybb503372010-05-27 20:51:26 +00007801 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007802 {
cristy4c08aed2011-07-01 19:47:50 +00007803 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007804 if (map_info->red_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007805 SetPixelRed(affinity_image,ScaleXToQuantum((size_t)
7806 (i/map_info->red_mult),map_info->red_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007807 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007808 if (map_info->green_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007809 SetPixelGreen(affinity_image,ScaleXToQuantum((size_t)
7810 ((i/map_info->green_mult) % (map_info->green_max+1)),
7811 map_info->green_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007812 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007813 if (map_info->blue_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007814 SetPixelBlue(affinity_image,ScaleXToQuantum((size_t)
7815 (i % map_info->green_mult),map_info->blue_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007816 SetPixelAlpha(affinity_image,
7817 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007818 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007819 }
7820 (void) SyncAuthenticPixels(affinity_image,exception);
7821 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007822 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007823 }
cristy4c08aed2011-07-01 19:47:50 +00007824 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007825 pixel);
cristy574cc262011-08-05 01:23:58 +00007826 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007827 affinity_image=DestroyImage(affinity_image);
7828 }
7829 if (IsEventLogging())
7830 {
7831 (void) LogMagickEvent(X11Event,GetMagickModule(),
7832 "Standard Colormap:");
7833 (void) LogMagickEvent(X11Event,GetMagickModule(),
7834 " colormap id: 0x%lx",map_info->colormap);
7835 (void) LogMagickEvent(X11Event,GetMagickModule(),
7836 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7837 map_info->green_max,map_info->blue_max);
7838 (void) LogMagickEvent(X11Event,GetMagickModule(),
7839 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7840 map_info->green_mult,map_info->blue_mult);
7841 }
7842 return;
7843 }
7844 if ((visual_info->klass != DirectColor) &&
7845 (visual_info->klass != TrueColor))
7846 if ((image->storage_class == DirectClass) ||
7847 ((int) image->colors > visual_info->colormap_size))
7848 {
7849 QuantizeInfo
7850 quantize_info;
7851
7852 /*
7853 Image has more colors than the visual supports.
7854 */
7855 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007856 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007857 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007858 }
7859 /*
7860 Free previous and create new colormap.
7861 */
7862 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7863 colormap=XDefaultColormap(display,visual_info->screen);
7864 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7865 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7866 visual_info->visual,visual_info->klass == DirectColor ?
7867 AllocAll : AllocNone);
7868 if (colormap == (Colormap) NULL)
7869 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7870 image->filename);
7871 /*
7872 Initialize the map and pixel info structures.
7873 */
7874 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007875 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007876 /*
7877 Allocating colors in server colormap is based on visual class.
7878 */
7879 switch (visual_info->klass)
7880 {
7881 case StaticGray:
7882 case StaticColor:
7883 {
7884 /*
7885 Define Standard Colormap for StaticGray or StaticColor visual.
7886 */
7887 number_colors=image->colors;
7888 colors=(XColor *) AcquireQuantumMemory((size_t)
7889 visual_info->colormap_size,sizeof(*colors));
7890 if (colors == (XColor *) NULL)
7891 ThrowXWindowFatalException(ResourceLimitFatalError,
7892 "UnableToCreateColormap",image->filename);
7893 p=colors;
7894 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007895 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007896 {
7897 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7898 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7899 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7900 if (visual_info->klass != StaticColor)
7901 {
7902 gray_value=(unsigned short) XPixelIntensity(&color);
7903 color.red=gray_value;
7904 color.green=gray_value;
7905 color.blue=gray_value;
7906 }
7907 status=XAllocColor(display,colormap,&color);
7908 if (status == False)
7909 {
7910 colormap=XCopyColormapAndFree(display,colormap);
7911 (void) XAllocColor(display,colormap,&color);
7912 }
7913 pixel->pixels[i]=color.pixel;
7914 *p++=color;
7915 }
7916 break;
7917 }
7918 case GrayScale:
7919 case PseudoColor:
7920 {
7921 unsigned int
7922 colormap_type;
7923
7924 /*
7925 Define Standard Colormap for GrayScale or PseudoColor visual.
7926 */
7927 number_colors=image->colors;
7928 colors=(XColor *) AcquireQuantumMemory((size_t)
7929 visual_info->colormap_size,sizeof(*colors));
7930 if (colors == (XColor *) NULL)
7931 ThrowXWindowFatalException(ResourceLimitFatalError,
7932 "UnableToCreateColormap",image->filename);
7933 /*
7934 Preallocate our GUI colors.
7935 */
7936 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7937 (void) XAllocColor(display,colormap,&pixel->background_color);
7938 (void) XAllocColor(display,colormap,&pixel->border_color);
7939 (void) XAllocColor(display,colormap,&pixel->matte_color);
7940 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7941 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7942 (void) XAllocColor(display,colormap,&pixel->depth_color);
7943 (void) XAllocColor(display,colormap,&pixel->trough_color);
7944 for (i=0; i < MaxNumberPens; i++)
7945 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7946 /*
7947 Determine if image colors will "fit" into X server colormap.
7948 */
7949 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007950 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007951 NULL,0,pixel->pixels,(unsigned int) image->colors);
7952 if (status != False)
7953 colormap_type=PrivateColormap;
7954 if (colormap_type == SharedColormap)
7955 {
cristyc57f6942010-11-12 01:47:39 +00007956 CacheView
7957 *image_view;
7958
cristy3ed852e2009-09-05 21:47:34 +00007959 DiversityPacket
7960 *diversity;
7961
7962 int
7963 y;
7964
7965 register int
7966 x;
7967
7968 unsigned short
7969 index;
7970
7971 XColor
7972 *server_colors;
7973
7974 /*
7975 Define Standard colormap for shared GrayScale or PseudoColor visual.
7976 */
7977 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7978 sizeof(*diversity));
7979 if (diversity == (DiversityPacket *) NULL)
7980 ThrowXWindowFatalException(ResourceLimitFatalError,
7981 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007982 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007983 {
cristye42f6582012-02-11 17:59:50 +00007984 diversity[i].red=ClampToQuantum(image->colormap[i].red);
7985 diversity[i].green=ClampToQuantum(image->colormap[i].green);
7986 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00007987 diversity[i].index=(unsigned short) i;
7988 diversity[i].count=0;
7989 }
cristy46ff2672012-12-14 15:32:26 +00007990 image_view=AcquireAuthenticCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007991 for (y=0; y < (int) image->rows; y++)
7992 {
cristyc57f6942010-11-12 01:47:39 +00007993 register int
cristy3ed852e2009-09-05 21:47:34 +00007994 x;
7995
cristy4c08aed2011-07-01 19:47:50 +00007996 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007997 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007998
cristyc57f6942010-11-12 01:47:39 +00007999 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8000 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008001 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008002 break;
cristyc57f6942010-11-12 01:47:39 +00008003 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008004 {
8005 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008006 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008007 }
cristy3ed852e2009-09-05 21:47:34 +00008008 }
cristyc57f6942010-11-12 01:47:39 +00008009 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008010 /*
8011 Sort colors by decreasing intensity.
8012 */
8013 qsort((void *) diversity,image->colors,sizeof(*diversity),
8014 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008015 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008016 {
8017 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008018 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008019 }
8020 diversity[image->colors-1].count<<=4;
8021 qsort((void *) diversity,image->colors,sizeof(*diversity),
8022 PopularityCompare);
8023 /*
8024 Allocate colors.
8025 */
8026 p=colors;
8027 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008028 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008029 {
8030 index=diversity[i].index;
8031 color.red=
8032 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8033 color.green=
8034 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8035 color.blue=
8036 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8037 if (visual_info->klass != PseudoColor)
8038 {
8039 gray_value=(unsigned short) XPixelIntensity(&color);
8040 color.red=gray_value;
8041 color.green=gray_value;
8042 color.blue=gray_value;
8043 }
8044 status=XAllocColor(display,colormap,&color);
8045 if (status == False)
8046 break;
8047 pixel->pixels[index]=color.pixel;
8048 *p++=color;
8049 }
8050 /*
8051 Read X server colormap.
8052 */
8053 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8054 visual_info->colormap_size,sizeof(*server_colors));
8055 if (server_colors == (XColor *) NULL)
8056 ThrowXWindowFatalException(ResourceLimitFatalError,
8057 "UnableToCreateColormap",image->filename);
8058 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008059 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008060 (void) XQueryColors(display,colormap,server_colors,
8061 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8062 /*
8063 Select remaining colors from X server colormap.
8064 */
cristybb503372010-05-27 20:51:26 +00008065 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008066 {
8067 index=diversity[i].index;
cristy534d0a32013-04-13 16:27:24 +00008068 color.red=ScaleQuantumToShort(
8069 XRedGamma(image->colormap[index].red));
8070 color.green=ScaleQuantumToShort(
8071 XGreenGamma(image->colormap[index].green));
8072 color.blue=ScaleQuantumToShort(
8073 XBlueGamma(image->colormap[index].blue));
cristy3ed852e2009-09-05 21:47:34 +00008074 if (visual_info->klass != PseudoColor)
8075 {
8076 gray_value=(unsigned short) XPixelIntensity(&color);
8077 color.red=gray_value;
8078 color.green=gray_value;
8079 color.blue=gray_value;
8080 }
8081 XBestPixel(display,colormap,server_colors,(unsigned int)
8082 visual_info->colormap_size,&color);
8083 pixel->pixels[index]=color.pixel;
8084 *p++=color;
8085 }
8086 if ((int) image->colors < visual_info->colormap_size)
8087 {
8088 /*
8089 Fill up colors array-- more choices for pen colors.
8090 */
8091 retain_colors=MagickMin((unsigned int)
8092 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008093 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008094 *p++=server_colors[i];
8095 number_colors+=retain_colors;
8096 }
8097 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8098 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8099 break;
8100 }
8101 /*
8102 Define Standard colormap for private GrayScale or PseudoColor visual.
8103 */
8104 if (status == False)
8105 {
8106 /*
8107 Not enough colormap entries in the colormap-- Create a new colormap.
8108 */
8109 colormap=XCreateColormap(display,
8110 XRootWindow(display,visual_info->screen),visual_info->visual,
8111 AllocNone);
8112 if (colormap == (Colormap) NULL)
8113 ThrowXWindowFatalException(ResourceLimitFatalError,
8114 "UnableToCreateColormap",image->filename);
8115 map_info->colormap=colormap;
8116 if ((int) image->colors < visual_info->colormap_size)
8117 {
8118 /*
8119 Retain colors from the default colormap to help lessens the
8120 effects of colormap flashing.
8121 */
8122 retain_colors=MagickMin((unsigned int)
8123 (visual_info->colormap_size-image->colors),256);
8124 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008125 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008126 {
cristyc57f6942010-11-12 01:47:39 +00008127 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008128 p++;
8129 }
8130 (void) XQueryColors(display,
8131 XDefaultColormap(display,visual_info->screen),
8132 colors+image->colors,(int) retain_colors);
8133 /*
8134 Transfer colors from default to private colormap.
8135 */
8136 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008137 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008138 retain_colors);
8139 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008140 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008141 {
8142 p->pixel=pixel->pixels[i];
8143 p++;
8144 }
8145 (void) XStoreColors(display,colormap,colors+image->colors,
8146 (int) retain_colors);
8147 number_colors+=retain_colors;
8148 }
8149 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008150 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008151 image->colors);
8152 }
8153 /*
8154 Store the image colormap.
8155 */
8156 p=colors;
8157 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008158 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008159 {
8160 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8161 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8162 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8163 if (visual_info->klass != PseudoColor)
8164 {
8165 gray_value=(unsigned short) XPixelIntensity(&color);
8166 color.red=gray_value;
8167 color.green=gray_value;
8168 color.blue=gray_value;
8169 }
8170 color.pixel=pixel->pixels[i];
8171 *p++=color;
8172 }
8173 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8174 break;
8175 }
8176 case TrueColor:
8177 case DirectColor:
8178 default:
8179 {
8180 MagickBooleanType
8181 linear_colormap;
8182
8183 /*
8184 Define Standard Colormap for TrueColor or DirectColor visual.
8185 */
8186 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8187 (map_info->green_max*map_info->green_mult)+
8188 (map_info->blue_max*map_info->blue_mult)+1);
8189 linear_colormap=(number_colors > 4096) ||
8190 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8191 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8192 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8193 MagickTrue : MagickFalse;
8194 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008195 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008196 /*
8197 Allocate color array.
8198 */
8199 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8200 if (colors == (XColor *) NULL)
8201 ThrowXWindowFatalException(ResourceLimitFatalError,
8202 "UnableToCreateColormap",image->filename);
8203 /*
8204 Initialize linear color ramp.
8205 */
8206 p=colors;
8207 color.flags=(char) (DoRed | DoGreen | DoBlue);
8208 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008209 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008210 {
8211 color.blue=(unsigned short) 0;
8212 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008213 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008214 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8215 color.green=color.blue;
8216 color.red=color.blue;
8217 color.pixel=XStandardPixel(map_info,&color);
8218 *p++=color;
8219 }
8220 else
cristybb503372010-05-27 20:51:26 +00008221 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008222 {
8223 color.red=(unsigned short) 0;
8224 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008225 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008226 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8227 color.green=(unsigned int) 0;
8228 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008229 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008230 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8231 map_info->green_max));
8232 color.blue=(unsigned short) 0;
8233 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008234 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008235 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8236 color.pixel=XStandardPixel(map_info,&color);
8237 *p++=color;
8238 }
8239 if ((visual_info->klass == DirectColor) &&
8240 (colormap != XDefaultColormap(display,visual_info->screen)))
8241 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8242 else
cristybb503372010-05-27 20:51:26 +00008243 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008244 (void) XAllocColor(display,colormap,&colors[i]);
8245 break;
8246 }
8247 }
8248 if ((visual_info->klass != DirectColor) &&
8249 (visual_info->klass != TrueColor))
8250 {
8251 /*
8252 Set foreground, background, border, etc. pixels.
8253 */
8254 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8255 &pixel->foreground_color);
8256 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8257 &pixel->background_color);
8258 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8259 {
8260 /*
8261 Foreground and background colors must differ.
8262 */
8263 pixel->background_color.red=(~pixel->foreground_color.red);
8264 pixel->background_color.green=
8265 (~pixel->foreground_color.green);
8266 pixel->background_color.blue=
8267 (~pixel->foreground_color.blue);
8268 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8269 &pixel->background_color);
8270 }
8271 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8272 &pixel->border_color);
8273 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8274 &pixel->matte_color);
8275 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8276 &pixel->highlight_color);
8277 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8278 &pixel->shadow_color);
8279 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8280 &pixel->depth_color);
8281 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8282 &pixel->trough_color);
8283 for (i=0; i < MaxNumberPens; i++)
8284 {
8285 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8286 &pixel->pen_colors[i]);
8287 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8288 }
cristyc57f6942010-11-12 01:47:39 +00008289 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008290 }
8291 colors=(XColor *) RelinquishMagickMemory(colors);
8292 if (IsEventLogging())
8293 {
8294 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8295 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8296 map_info->colormap);
8297 (void) LogMagickEvent(X11Event,GetMagickModule(),
8298 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8299 map_info->green_max,map_info->blue_max);
8300 (void) LogMagickEvent(X11Event,GetMagickModule(),
8301 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8302 map_info->green_mult,map_info->blue_mult);
8303 }
8304}
8305
8306/*
8307%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8308% %
8309% %
8310% %
8311% X M a k e W i n d o w %
8312% %
8313% %
8314% %
8315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8316%
8317% XMakeWindow() creates an X11 window.
8318%
8319% The format of the XMakeWindow method is:
8320%
8321% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8322% XClassHint *class_hint,XWMHints *manager_hints,
8323% XWindowInfo *window_info)
8324%
8325% A description of each parameter follows:
8326%
8327% o display: Specifies a connection to an X server; returned from
8328% XOpenDisplay.
8329%
8330% o parent: Specifies the parent window_info.
8331%
8332% o argv: Specifies the application's argument list.
8333%
8334% o argc: Specifies the number of arguments.
8335%
8336% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8337%
8338% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8339%
8340% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8341%
8342*/
cristybcbda3f2011-09-03 13:01:22 +00008343MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008344 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8345 XWindowInfo *window_info)
8346{
8347#define MinWindowSize 64
8348
8349 Atom
8350 atom_list[2];
8351
8352 int
8353 gravity;
8354
8355 static XTextProperty
8356 icon_name,
8357 window_name;
8358
8359 Status
8360 status;
8361
8362 XSizeHints
8363 *size_hints;
8364
8365 /*
8366 Set window info hints.
8367 */
8368 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8369 assert(display != (Display *) NULL);
8370 assert(window_info != (XWindowInfo *) NULL);
8371 size_hints=XAllocSizeHints();
8372 if (size_hints == (XSizeHints *) NULL)
8373 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008374 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008375 size_hints->x=window_info->x;
8376 size_hints->y=window_info->y;
8377 size_hints->width=(int) window_info->width;
8378 size_hints->height=(int) window_info->height;
8379 if (window_info->immutable != MagickFalse)
8380 {
8381 /*
8382 Window size cannot be changed.
8383 */
8384 size_hints->min_width=size_hints->width;
8385 size_hints->min_height=size_hints->height;
8386 size_hints->max_width=size_hints->width;
8387 size_hints->max_height=size_hints->height;
8388 size_hints->flags|=PMinSize;
8389 size_hints->flags|=PMaxSize;
8390 }
8391 else
8392 {
8393 /*
8394 Window size can be changed.
8395 */
8396 size_hints->min_width=(int) window_info->min_width;
8397 size_hints->min_height=(int) window_info->min_height;
8398 size_hints->flags|=PResizeInc;
8399 size_hints->width_inc=(int) window_info->width_inc;
8400 size_hints->height_inc=(int) window_info->height_inc;
8401#if !defined(PRE_R4_ICCCM)
8402 size_hints->flags|=PBaseSize;
8403 size_hints->base_width=size_hints->width_inc;
8404 size_hints->base_height=size_hints->height_inc;
8405#endif
8406 }
8407 gravity=NorthWestGravity;
8408 if (window_info->geometry != (char *) NULL)
8409 {
8410 char
8411 default_geometry[MaxTextExtent],
8412 geometry[MaxTextExtent];
8413
8414 int
8415 flags;
8416
8417 register char
8418 *p;
8419
8420 /*
8421 User specified geometry.
8422 */
cristyb51dff52011-05-19 16:55:47 +00008423 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008424 size_hints->width,size_hints->height);
8425 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8426 p=geometry;
8427 while (strlen(p) != 0)
8428 {
8429 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8430 p++;
8431 else
8432 (void) CopyMagickString(p,p+1,MaxTextExtent);
8433 }
8434 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8435 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8436 &size_hints->width,&size_hints->height,&gravity);
8437 if ((flags & WidthValue) && (flags & HeightValue))
8438 size_hints->flags|=USSize;
8439 if ((flags & XValue) && (flags & YValue))
8440 {
8441 size_hints->flags|=USPosition;
8442 window_info->x=size_hints->x;
8443 window_info->y=size_hints->y;
8444 }
8445 }
8446#if !defined(PRE_R4_ICCCM)
8447 size_hints->win_gravity=gravity;
8448 size_hints->flags|=PWinGravity;
8449#endif
8450 if (window_info->id == (Window) NULL)
8451 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8452 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8453 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008454 window_info->visual,(unsigned long) window_info->mask,
8455 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008456 else
8457 {
8458 MagickStatusType
8459 mask;
8460
8461 XEvent
8462 sans_event;
8463
8464 XWindowChanges
8465 window_changes;
8466
8467 /*
8468 Window already exists; change relevant attributes.
8469 */
cristyc57f6942010-11-12 01:47:39 +00008470 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8471 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008472 mask=ConfigureNotify;
8473 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8474 window_changes.x=window_info->x;
8475 window_changes.y=window_info->y;
8476 window_changes.width=(int) window_info->width;
8477 window_changes.height=(int) window_info->height;
8478 mask=(MagickStatusType) (CWWidth | CWHeight);
8479 if (window_info->flags & USPosition)
8480 mask|=CWX | CWY;
8481 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8482 mask,&window_changes);
8483 }
8484 if (window_info->id == (Window) NULL)
8485 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8486 window_info->name);
8487 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8488 if (status == False)
8489 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8490 window_info->name);
8491 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8492 if (status == False)
8493 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8494 window_info->icon_name);
8495 if (window_info->icon_geometry != (char *) NULL)
8496 {
8497 int
8498 flags,
8499 height,
8500 width;
8501
8502 /*
8503 User specified icon geometry.
8504 */
8505 size_hints->flags|=USPosition;
8506 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8507 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8508 &manager_hints->icon_y,&width,&height,&gravity);
8509 if ((flags & XValue) && (flags & YValue))
8510 manager_hints->flags|=IconPositionHint;
8511 }
8512 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8513 size_hints,manager_hints,class_hint);
8514 if (window_name.value != (void *) NULL)
8515 {
8516 (void) XFree((void *) window_name.value);
8517 window_name.value=(unsigned char *) NULL;
8518 window_name.nitems=0;
8519 }
8520 if (icon_name.value != (void *) NULL)
8521 {
8522 (void) XFree((void *) icon_name.value);
8523 icon_name.value=(unsigned char *) NULL;
8524 icon_name.nitems=0;
8525 }
8526 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8527 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8528 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8529 (void) XFree((void *) size_hints);
8530 if (window_info->shape != MagickFalse)
8531 {
8532#if defined(MAGICKCORE_HAVE_SHAPE)
8533 int
8534 error_base,
8535 event_base;
8536
8537 /*
8538 Can we apply a non-rectangular shaping mask?
8539 */
8540 error_base=0;
8541 event_base=0;
8542 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8543 window_info->shape=MagickFalse;
8544#else
8545 window_info->shape=MagickFalse;
8546#endif
8547 }
8548 if (window_info->shared_memory)
8549 {
8550#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8551 /*
8552 Can we use shared memory with this window?
8553 */
8554 if (XShmQueryExtension(display) == 0)
8555 window_info->shared_memory=MagickFalse;
8556#else
8557 window_info->shared_memory=MagickFalse;
8558#endif
8559 }
8560 window_info->image=NewImageList();
8561 window_info->destroy=MagickFalse;
8562}
8563
8564/*
8565%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8566% %
8567% %
8568% %
8569% X M a g i c k P r o g r e s s M o n i t o r %
8570% %
8571% %
8572% %
8573%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8574%
8575% XMagickProgressMonitor() displays the progress a task is making in
8576% completing a task.
8577%
8578% The format of the XMagickProgressMonitor method is:
8579%
8580% void XMagickProgressMonitor(const char *task,
8581% const MagickOffsetType quantum,const MagickSizeType span,
8582% void *client_data)
8583%
8584% A description of each parameter follows:
8585%
8586% o task: Identifies the task in progress.
8587%
8588% o quantum: Specifies the quantum position within the span which represents
8589% how much progress has been made in completing a task.
8590%
8591% o span: Specifies the span relative to completing a task.
8592%
8593% o client_data: Pointer to any client data.
8594%
8595*/
8596
8597static const char *GetLocaleMonitorMessage(const char *text)
8598{
8599 char
8600 message[MaxTextExtent],
8601 tag[MaxTextExtent];
8602
8603 const char
8604 *locale_message;
8605
8606 register char
8607 *p;
8608
8609 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8610 p=strrchr(tag,'/');
8611 if (p != (char *) NULL)
8612 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008613 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008614 locale_message=GetLocaleMessage(message);
8615 if (locale_message == message)
8616 return(text);
8617 return(locale_message);
8618}
8619
cristybcbda3f2011-09-03 13:01:22 +00008620MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008621 const MagickOffsetType quantum,const MagickSizeType span,
8622 void *magick_unused(client_data))
8623{
8624 XWindows
8625 *windows;
8626
8627 windows=XSetWindows((XWindows *) ~0);
8628 if (windows == (XWindows *) NULL)
8629 return(MagickTrue);
8630 if (windows->info.mapped != MagickFalse)
8631 XProgressMonitorWidget(windows->display,windows,
8632 GetLocaleMonitorMessage(tag),quantum,span);
8633 return(MagickTrue);
8634}
8635
8636/*
8637%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8638% %
8639% %
8640% %
8641% X Q u e r y C o l o r D a t a b a s e %
8642% %
8643% %
8644% %
8645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8646%
cristy9950d572011-10-01 18:22:35 +00008647% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008648% string.
8649%
8650% The format of the XQueryColorDatabase method is:
8651%
cristy9950d572011-10-01 18:22:35 +00008652% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008653%
8654% A description of each parameter follows:
8655%
8656% o target: Specifies the color to lookup in the X color database.
8657%
cristy101ab702011-10-13 13:06:32 +00008658% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008659% color is returned as this value.
8660%
8661*/
cristy9950d572011-10-01 18:22:35 +00008662MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008663 XColor *color)
8664{
8665 Colormap
8666 colormap;
8667
8668 static Display
8669 *display = (Display *) NULL;
8670
8671 Status
8672 status;
8673
8674 XColor
8675 xcolor;
8676
8677 /*
8678 Initialize color return value.
8679 */
8680 assert(color != (XColor *) NULL);
8681 color->red=0;
8682 color->green=0;
8683 color->blue=0;
8684 color->flags=(char) (DoRed | DoGreen | DoBlue);
8685 if ((target == (char *) NULL) || (*target == '\0'))
8686 target="#ffffffffffff";
8687 /*
8688 Let the X server define the color for us.
8689 */
8690 if (display == (Display *) NULL)
8691 display=XOpenDisplay((char *) NULL);
8692 if (display == (Display *) NULL)
8693 {
cristyc38fbf52013-11-03 13:55:54 +00008694 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target);
cristy3ed852e2009-09-05 21:47:34 +00008695 return(MagickFalse);
8696 }
8697 colormap=XDefaultColormap(display,XDefaultScreen(display));
8698 status=XParseColor(display,colormap,(char *) target,&xcolor);
8699 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00008700 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target)
cristy3ed852e2009-09-05 21:47:34 +00008701 else
8702 {
8703 color->red=xcolor.red;
8704 color->green=xcolor.green;
8705 color->blue=xcolor.blue;
8706 color->flags=xcolor.flags;
8707 }
8708 return(status != False ? MagickTrue : MagickFalse);
8709}
8710
8711/*
8712%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8713% %
8714% %
8715% %
8716% X Q u e r y P o s i t i o n %
8717% %
8718% %
8719% %
8720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8721%
8722% XQueryPosition() gets the pointer coordinates relative to a window.
8723%
8724% The format of the XQueryPosition method is:
8725%
8726% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8727%
8728% A description of each parameter follows:
8729%
8730% o display: Specifies a connection to an X server; returned from
8731% XOpenDisplay.
8732%
8733% o window: Specifies a pointer to a Window.
8734%
8735% o x: Return the x coordinate of the pointer relative to the origin of the
8736% window.
8737%
8738% o y: Return the y coordinate of the pointer relative to the origin of the
8739% window.
8740%
8741*/
cristy534d0a32013-04-13 16:27:24 +00008742MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,
8743 int *y)
cristy3ed852e2009-09-05 21:47:34 +00008744{
8745 int
8746 x_root,
8747 y_root;
8748
8749 unsigned int
8750 mask;
8751
8752 Window
8753 root_window;
8754
8755 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8756 assert(display != (Display *) NULL);
8757 assert(window != (Window) NULL);
8758 assert(x != (int *) NULL);
8759 assert(y != (int *) NULL);
8760 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8761 x,y,&mask);
8762}
8763
8764/*
8765%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8766% %
8767% %
8768% %
8769% X R e f r e s h W i n d o w %
8770% %
8771% %
8772% %
8773%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8774%
8775% XRefreshWindow() refreshes an image in a X window.
8776%
8777% The format of the XRefreshWindow method is:
8778%
8779% void XRefreshWindow(Display *display,const XWindowInfo *window,
8780% const XEvent *event)
8781%
8782% A description of each parameter follows:
8783%
8784% o display: Specifies a connection to an X server; returned from
8785% XOpenDisplay.
8786%
8787% o window: Specifies a pointer to a XWindowInfo structure.
8788%
8789% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8790% the entire image is refreshed.
8791%
8792*/
cristybcbda3f2011-09-03 13:01:22 +00008793MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008794 const XEvent *event)
8795{
8796 int
8797 x,
8798 y;
8799
8800 unsigned int
8801 height,
8802 width;
8803
8804 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8805 assert(display != (Display *) NULL);
8806 assert(window != (XWindowInfo *) NULL);
8807 if (window->ximage == (XImage *) NULL)
8808 return;
8809 if (event != (XEvent *) NULL)
8810 {
8811 /*
8812 Determine geometry from expose event.
8813 */
8814 x=event->xexpose.x;
8815 y=event->xexpose.y;
8816 width=(unsigned int) event->xexpose.width;
8817 height=(unsigned int) event->xexpose.height;
8818 }
8819 else
8820 {
8821 XEvent
8822 sans_event;
8823
8824 /*
8825 Refresh entire window; discard outstanding expose events.
8826 */
8827 x=0;
8828 y=0;
8829 width=window->width;
8830 height=window->height;
8831 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008832 if (window->matte_pixmap != (Pixmap) NULL)
8833 {
8834#if defined(MAGICKCORE_HAVE_SHAPE)
8835 if (window->shape != MagickFalse)
8836 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8837 window->matte_pixmap,ShapeSet);
8838#endif
8839 }
cristy3ed852e2009-09-05 21:47:34 +00008840 }
8841 /*
8842 Check boundary conditions.
8843 */
8844 if ((window->ximage->width-(x+window->x)) < (int) width)
8845 width=(unsigned int) (window->ximage->width-(x+window->x));
8846 if ((window->ximage->height-(y+window->y)) < (int) height)
8847 height=(unsigned int) (window->ximage->height-(y+window->y));
8848 /*
8849 Refresh image.
8850 */
8851 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008852 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008853 if (window->pixmap != (Pixmap) NULL)
8854 {
8855 if (window->depth > 1)
8856 (void) XCopyArea(display,window->pixmap,window->id,
8857 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8858 else
8859 (void) XCopyPlane(display,window->pixmap,window->id,
8860 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8861 1L);
8862 }
8863 else
8864 {
8865#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8866 if (window->shared_memory)
8867 (void) XShmPutImage(display,window->id,window->annotate_context,
8868 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8869#endif
8870 if (window->shared_memory == MagickFalse)
8871 (void) XPutImage(display,window->id,window->annotate_context,
8872 window->ximage,x+window->x,y+window->y,x,y,width,height);
8873 }
8874 if (window->matte_pixmap != (Pixmap) NULL)
8875 (void) XSetClipMask(display,window->annotate_context,None);
8876 (void) XFlush(display);
8877}
8878
8879/*
8880%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8881% %
8882% %
8883% %
8884% X R e m o t e C o m m a n d %
8885% %
8886% %
8887% %
8888%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8889%
8890% XRemoteCommand() forces a remote display(1) to display the specified
8891% image filename.
8892%
8893% The format of the XRemoteCommand method is:
8894%
8895% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8896% const char *filename)
8897%
8898% A description of each parameter follows:
8899%
8900% o display: Specifies a connection to an X server; returned from
8901% XOpenDisplay.
8902%
8903% o window: Specifies the name or id of an X window.
8904%
8905% o filename: the name of the image filename to display.
8906%
8907*/
8908MagickExport MagickBooleanType XRemoteCommand(Display *display,
8909 const char *window,const char *filename)
8910{
8911 Atom
8912 remote_atom;
8913
8914 Window
8915 remote_window,
8916 root_window;
8917
8918 assert(filename != (char *) NULL);
8919 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8920 if (display == (Display *) NULL)
8921 display=XOpenDisplay((char *) NULL);
8922 if (display == (Display *) NULL)
8923 {
8924 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8925 return(MagickFalse);
8926 }
8927 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8928 remote_window=(Window) NULL;
8929 root_window=XRootWindow(display,XDefaultScreen(display));
8930 if (window != (char *) NULL)
8931 {
8932 /*
8933 Search window hierarchy and identify any clients by name or ID.
8934 */
cristy02e64f82013-11-14 16:20:04 +00008935 if (isdigit((int) ((unsigned char) *window)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00008936 remote_window=XWindowByID(display,root_window,(Window)
8937 strtol((char *) window,(char **) NULL,0));
8938 if (remote_window == (Window) NULL)
8939 remote_window=XWindowByName(display,root_window,window);
8940 }
8941 if (remote_window == (Window) NULL)
8942 remote_window=XWindowByProperty(display,root_window,remote_atom);
8943 if (remote_window == (Window) NULL)
8944 {
8945 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8946 filename);
8947 return(MagickFalse);
8948 }
8949 /*
8950 Send remote command.
8951 */
8952 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8953 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8954 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8955 (void) XSync(display,MagickFalse);
8956 return(MagickTrue);
8957}
8958
8959/*
8960%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8961% %
8962% %
8963% %
cristy534d0a32013-04-13 16:27:24 +00008964% X R e n d e r I m a g e %
8965% %
8966% %
8967% %
8968%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8969%
8970% XRenderImage() renders text on the image with an X11 font. It also returns
8971% the bounding box of the text relative to the image.
8972%
8973% The format of the XRenderImage method is:
8974%
8975% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
8976% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
8977%
8978% A description of each parameter follows:
8979%
8980% o image: the image.
8981%
8982% o draw_info: the draw info.
8983%
8984% o offset: (x,y) location of text relative to image.
8985%
8986% o metrics: bounding box of text.
8987%
8988% o exception: return any errors or warnings in this structure.
8989%
8990*/
8991MagickPrivate MagickBooleanType XRenderImage(Image *image,
8992 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
8993 ExceptionInfo *exception)
8994{
8995 const char
8996 *client_name;
8997
8998 DrawInfo
8999 cache_info;
9000
9001 Display
9002 *display;
9003
9004 ImageInfo
9005 *image_info;
9006
9007 MagickBooleanType
9008 status;
9009
9010 size_t
9011 height,
9012 width;
9013
9014 XAnnotateInfo
9015 annotate_info;
9016
9017 XFontStruct
9018 *font_info;
9019
9020 XPixelInfo
9021 pixel;
9022
9023 XResourceInfo
9024 resource_info;
9025
9026 XrmDatabase
9027 resource_database;
9028
9029 XStandardColormap
9030 *map_info;
9031
9032 XVisualInfo
9033 *visual_info;
9034
9035 /*
9036 Open X server connection.
9037 */
9038 display=XOpenDisplay(draw_info->server_name);
9039 if (display == (Display *) NULL)
9040 {
9041 ThrowXWindowException(XServerError,"UnableToOpenXServer",
9042 draw_info->server_name);
9043 return(MagickFalse);
9044 }
9045 /*
9046 Get user defaults from X resource database.
9047 */
9048 (void) XSetErrorHandler(XError);
9049 image_info=AcquireImageInfo();
9050 client_name=GetClientName();
9051 resource_database=XGetResourceDatabase(display,client_name);
9052 XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
9053 resource_info.close_server=MagickFalse;
9054 resource_info.colormap=PrivateColormap;
9055 resource_info.font=AcquireString(draw_info->font);
9056 resource_info.background_color=AcquireString("#ffffffffffff");
9057 resource_info.foreground_color=AcquireString("#000000000000");
9058 map_info=XAllocStandardColormap();
9059 if (map_info == (XStandardColormap *) NULL)
9060 {
9061 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9062 image->filename);
9063 return(MagickFalse);
9064 }
9065 /*
9066 Initialize visual info.
9067 */
9068 visual_info=XBestVisualInfo(display,map_info,&resource_info);
9069 if (visual_info == (XVisualInfo *) NULL)
9070 {
cristyc38fbf52013-11-03 13:55:54 +00009071 ThrowXWindowException(XServerError,"UnableToGetVisual",image->filename);
cristy534d0a32013-04-13 16:27:24 +00009072 return(MagickFalse);
9073 }
9074 map_info->colormap=(Colormap) NULL;
9075 pixel.pixels=(unsigned long *) NULL;
9076 /*
9077 Initialize Standard Colormap info.
9078 */
9079 XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
9080 map_info);
9081 XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
9082 &pixel);
9083 pixel.annotate_context=XDefaultGC(display,visual_info->screen);
9084 /*
9085 Initialize font info.
9086 */
9087 font_info=XBestFont(display,&resource_info,MagickFalse);
9088 if (font_info == (XFontStruct *) NULL)
9089 {
9090 ThrowXWindowException(XServerError,"UnableToLoadFont",draw_info->font);
9091 return(MagickFalse);
9092 }
9093 if ((map_info == (XStandardColormap *) NULL) ||
9094 (visual_info == (XVisualInfo *) NULL) ||
9095 (font_info == (XFontStruct *) NULL))
9096 {
9097 XFreeResources(display,visual_info,map_info,&pixel,font_info,
9098 &resource_info,(XWindowInfo *) NULL);
9099 ThrowXWindowException(XServerError,"UnableToLoadFont",image->filename);
9100 return(MagickFalse);
9101 }
9102 cache_info=(*draw_info);
9103 /*
9104 Initialize annotate info.
9105 */
9106 XGetAnnotateInfo(&annotate_info);
9107 annotate_info.stencil=ForegroundStencil;
9108 if (cache_info.font != draw_info->font)
9109 {
9110 /*
9111 Type name has changed.
9112 */
9113 (void) XFreeFont(display,font_info);
9114 (void) CloneString(&resource_info.font,draw_info->font);
9115 font_info=XBestFont(display,&resource_info,MagickFalse);
9116 if (font_info == (XFontStruct *) NULL)
9117 {
9118 ThrowXWindowException(XServerError,"UnableToLoadFont",
9119 draw_info->font);
9120 return(MagickFalse);
9121 }
9122 }
9123 if (image->debug != MagickFalse)
9124 (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
9125 "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
9126 draw_info->font : "none",draw_info->pointsize);
9127 cache_info=(*draw_info);
9128 annotate_info.font_info=font_info;
9129 annotate_info.text=(char *) draw_info->text;
9130 annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
9131 strlen(draw_info->text));
9132 annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
9133 metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
9134 metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
9135 metrics->ascent=(double) font_info->ascent+4;
9136 metrics->descent=(double) (-font_info->descent);
9137 metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
9138 metrics->height=font_info->ascent+font_info->descent;
9139 metrics->max_advance=(double) font_info->max_bounds.width;
9140 metrics->bounds.x1=0.0;
9141 metrics->bounds.y1=metrics->descent;
9142 metrics->bounds.x2=metrics->ascent+metrics->descent;
9143 metrics->bounds.y2=metrics->ascent+metrics->descent;
9144 metrics->underline_position=(-2.0);
9145 metrics->underline_thickness=1.0;
9146 if (draw_info->render == MagickFalse)
9147 return(MagickTrue);
9148 if (draw_info->fill.alpha == TransparentAlpha)
9149 return(MagickTrue);
9150 /*
9151 Render fill color.
9152 */
9153 width=annotate_info.width;
9154 height=annotate_info.height;
9155 if ((fabs(draw_info->affine.rx) >= MagickEpsilon) ||
9156 (fabs(draw_info->affine.ry) >= MagickEpsilon))
9157 {
9158 if ((fabs(draw_info->affine.sx-draw_info->affine.sy) < MagickEpsilon) &&
9159 (fabs(draw_info->affine.rx+draw_info->affine.ry) < MagickEpsilon))
9160 annotate_info.degrees=(double) (180.0/MagickPI)*
9161 atan2(draw_info->affine.rx,draw_info->affine.sx);
9162 }
9163 (void) FormatLocaleString(annotate_info.geometry,MaxTextExtent,
9164 "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
9165 ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
9166 draw_info->interline_spacing-0.5));
9167 pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
9168 pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
9169 pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);
9170 status=XAnnotateImage(display,&pixel,&annotate_info,image,exception);
9171 if (status == 0)
9172 {
9173 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9174 image->filename);
9175 return(MagickFalse);
9176 }
9177 return(MagickTrue);
9178}
9179
9180/*
9181%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9182% %
9183% %
9184% %
cristy3ed852e2009-09-05 21:47:34 +00009185% X R e t a i n W i n d o w C o l o r s %
9186% %
9187% %
9188% %
9189%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9190%
9191% XRetainWindowColors() sets X11 color resources on a window. This preserves
9192% the colors associated with an image displayed on the window.
9193%
9194% The format of the XRetainWindowColors method is:
9195%
9196% void XRetainWindowColors(Display *display,const Window window)
9197%
9198% A description of each parameter follows:
9199%
9200% o display: Specifies a connection to an X server; returned from
9201% XOpenDisplay.
9202%
9203% o window: Specifies a pointer to a XWindowInfo structure.
9204%
9205*/
9206MagickExport void XRetainWindowColors(Display *display,const Window window)
9207{
9208 Atom
9209 property;
9210
9211 Pixmap
9212 pixmap;
9213
9214 /*
9215 Put property on the window.
9216 */
9217 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9218 assert(display != (Display *) NULL);
9219 assert(window != (Window) NULL);
9220 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9221 if (property == (Atom) NULL)
9222 {
cristyc38fbf52013-11-03 13:55:54 +00009223 ThrowXWindowException(XServerError,"UnableToCreateProperty",
cristy3ed852e2009-09-05 21:47:34 +00009224 "_XSETROOT_ID");
9225 return;
9226 }
9227 pixmap=XCreatePixmap(display,window,1,1,1);
9228 if (pixmap == (Pixmap) NULL)
9229 {
cristyc38fbf52013-11-03 13:55:54 +00009230 ThrowXWindowException(XServerError,"UnableToCreateBitmap","");
cristy3ed852e2009-09-05 21:47:34 +00009231 return;
9232 }
9233 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9234 (unsigned char *) &pixmap,1);
9235 (void) XSetCloseDownMode(display,RetainPermanent);
9236}
9237
9238/*
9239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9240% %
9241% %
9242% %
9243% X S e l e c t W i n d o w %
9244% %
9245% %
9246% %
9247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9248%
9249% XSelectWindow() allows a user to select a window using the mouse. If the
9250% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9251% is returned in the crop_info structure.
9252%
9253% The format of the XSelectWindow function is:
9254%
9255% target_window=XSelectWindow(display,crop_info)
9256%
9257% A description of each parameter follows:
9258%
9259% o window: XSelectWindow returns the window id.
9260%
9261% o display: Specifies a pointer to the Display structure; returned from
9262% XOpenDisplay.
9263%
9264% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9265% contains the extents of any cropping rectangle.
9266%
cristy3ed852e2009-09-05 21:47:34 +00009267*/
9268static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9269{
9270#define MinimumCropArea (unsigned int) 9
9271
9272 Cursor
9273 target_cursor;
9274
9275 GC
9276 annotate_context;
9277
9278 int
9279 presses,
9280 x_offset,
9281 y_offset;
9282
9283 Status
9284 status;
9285
9286 Window
9287 root_window,
9288 target_window;
9289
9290 XEvent
9291 event;
9292
9293 XGCValues
9294 context_values;
9295
9296 /*
9297 Initialize graphic context.
9298 */
9299 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9300 assert(display != (Display *) NULL);
9301 assert(crop_info != (RectangleInfo *) NULL);
9302 root_window=XRootWindow(display,XDefaultScreen(display));
9303 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9304 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9305 context_values.function=GXinvert;
9306 context_values.plane_mask=
9307 context_values.background ^ context_values.foreground;
9308 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009309 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009310 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9311 if (annotate_context == (GC) NULL)
9312 return(MagickFalse);
9313 /*
9314 Grab the pointer using target cursor.
9315 */
9316 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9317 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9318 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9319 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9320 GrabModeAsync,root_window,target_cursor,CurrentTime);
9321 if (status != GrabSuccess)
9322 {
cristyc38fbf52013-11-03 13:55:54 +00009323 ThrowXWindowException(XServerError,"UnableToGrabMouse","");
cristy3ed852e2009-09-05 21:47:34 +00009324 return((Window) NULL);
9325 }
9326 /*
9327 Select a window.
9328 */
9329 crop_info->width=0;
9330 crop_info->height=0;
9331 presses=0;
9332 target_window=(Window) NULL;
9333 x_offset=0;
9334 y_offset=0;
9335 do
9336 {
9337 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9338 (void) XDrawRectangle(display,root_window,annotate_context,
9339 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9340 (unsigned int) crop_info->height-1);
9341 /*
9342 Allow another event.
9343 */
9344 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9345 (void) XWindowEvent(display,root_window,ButtonPressMask |
9346 ButtonReleaseMask | ButtonMotionMask,&event);
9347 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9348 (void) XDrawRectangle(display,root_window,annotate_context,
9349 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9350 (unsigned int) crop_info->height-1);
9351 switch (event.type)
9352 {
9353 case ButtonPress:
9354 {
9355 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9356 event.xbutton.x,event.xbutton.y);
9357 if (target_window == (Window) NULL)
9358 target_window=root_window;
9359 x_offset=event.xbutton.x_root;
9360 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009361 crop_info->x=(ssize_t) x_offset;
9362 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009363 crop_info->width=0;
9364 crop_info->height=0;
9365 presses++;
9366 break;
9367 }
9368 case ButtonRelease:
9369 {
9370 presses--;
9371 break;
9372 }
9373 case MotionNotify:
9374 {
9375 /*
9376 Discard pending button motion events.
9377 */
9378 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009379 crop_info->x=(ssize_t) event.xmotion.x;
9380 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009381 /*
9382 Check boundary conditions.
9383 */
9384 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009385 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009386 else
9387 {
cristyecd0ab52010-05-30 14:59:20 +00009388 crop_info->width=(size_t) (crop_info->x-x_offset);
9389 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009390 }
9391 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009392 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009393 else
9394 {
cristyecd0ab52010-05-30 14:59:20 +00009395 crop_info->height=(size_t) (crop_info->y-y_offset);
9396 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009397 }
9398 }
9399 default:
9400 break;
9401 }
9402 } while ((target_window == (Window) NULL) || (presses > 0));
9403 (void) XUngrabPointer(display,CurrentTime);
9404 (void) XFreeCursor(display,target_cursor);
9405 (void) XFreeGC(display,annotate_context);
9406 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9407 {
9408 crop_info->width=0;
9409 crop_info->height=0;
9410 }
9411 if ((crop_info->width != 0) && (crop_info->height != 0))
9412 target_window=root_window;
9413 return(target_window);
9414}
9415
9416/*
9417%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9418% %
9419% %
9420% %
9421% X S e t C u r s o r S t a t e %
9422% %
9423% %
9424% %
9425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9426%
9427% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9428% reset to their default.
9429%
9430% The format of the XXSetCursorState method is:
9431%
9432% XSetCursorState(display,windows,const MagickStatusType state)
9433%
9434% A description of each parameter follows:
9435%
9436% o display: Specifies a connection to an X server; returned from
9437% XOpenDisplay.
9438%
9439% o windows: Specifies a pointer to a XWindows structure.
9440%
9441% o state: An unsigned integer greater than 0 sets the cursor state
9442% to busy, otherwise the cursor are reset to their default.
9443%
9444*/
cristybcbda3f2011-09-03 13:01:22 +00009445MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009446 const MagickStatusType state)
9447{
9448 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9449 assert(display != (Display *) NULL);
9450 assert(windows != (XWindows *) NULL);
9451 if (state)
9452 {
9453 (void) XCheckDefineCursor(display,windows->image.id,
9454 windows->image.busy_cursor);
9455 (void) XCheckDefineCursor(display,windows->pan.id,
9456 windows->pan.busy_cursor);
9457 (void) XCheckDefineCursor(display,windows->magnify.id,
9458 windows->magnify.busy_cursor);
9459 (void) XCheckDefineCursor(display,windows->command.id,
9460 windows->command.busy_cursor);
9461 }
9462 else
9463 {
9464 (void) XCheckDefineCursor(display,windows->image.id,
9465 windows->image.cursor);
9466 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9467 (void) XCheckDefineCursor(display,windows->magnify.id,
9468 windows->magnify.cursor);
9469 (void) XCheckDefineCursor(display,windows->command.id,
9470 windows->command.cursor);
9471 (void) XCheckDefineCursor(display,windows->command.id,
9472 windows->widget.cursor);
9473 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9474 }
9475 windows->info.mapped=MagickFalse;
9476}
9477
9478/*
9479%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9480% %
9481% %
9482% %
9483% X S e t W i n d o w s %
9484% %
9485% %
9486% %
9487%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9488%
9489% XSetWindows() sets the X windows structure if the windows info is specified.
9490% Otherwise the current windows structure is returned.
9491%
9492% The format of the XSetWindows method is:
9493%
9494% XWindows *XSetWindows(XWindows *windows_info)
9495%
9496% A description of each parameter follows:
9497%
9498% o windows_info: Initialize the Windows structure with this information.
9499%
9500*/
cristybcbda3f2011-09-03 13:01:22 +00009501MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009502{
9503 static XWindows
9504 *windows = (XWindows *) NULL;
9505
9506 if (windows_info != (XWindows *) ~0)
9507 {
9508 windows=(XWindows *) RelinquishMagickMemory(windows);
9509 windows=windows_info;
9510 }
9511 return(windows);
9512}
9513/*
9514%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9515% %
9516% %
9517% %
9518% X U s e r P r e f e r e n c e s %
9519% %
9520% %
9521% %
9522%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9523%
9524% XUserPreferences() saves the preferences in a configuration file in the
9525% users' home directory.
9526%
9527% The format of the XUserPreferences method is:
9528%
9529% void XUserPreferences(XResourceInfo *resource_info)
9530%
9531% A description of each parameter follows:
9532%
9533% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9534%
9535*/
cristybcbda3f2011-09-03 13:01:22 +00009536MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009537{
9538#if defined(X11_PREFERENCES_PATH)
9539 char
9540 cache[MaxTextExtent],
9541 filename[MaxTextExtent],
9542 specifier[MaxTextExtent];
9543
9544 const char
cristy104cea82009-10-25 02:26:51 +00009545 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009546 *value;
9547
9548 XrmDatabase
9549 preferences_database;
9550
9551 /*
9552 Save user preferences to the client configuration file.
9553 */
9554 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009555 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009556 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009557 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009558 value=resource_info->backdrop ? "True" : "False";
9559 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009560 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009561 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9562 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009563 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009564 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009565 value=resource_info->confirm_exit ? "True" : "False";
9566 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009567 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009568 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009569 value=resource_info->confirm_edit ? "True" : "False";
9570 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009571 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009572 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009573 value=resource_info->display_warnings ? "True" : "False";
9574 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009575 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristycbda6112012-05-27 20:57:16 +00009576 value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9577 "True" : "False";
cristy3ed852e2009-09-05 21:47:34 +00009578 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009579 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009580 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009581 value=resource_info->gamma_correct ? "True" : "False";
9582 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009583 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9584 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009585 resource_info->undo_cache);
9586 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009587 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009588 value=resource_info->use_pixmap ? "True" : "False";
9589 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009590 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009591 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009592 ExpandFilename(filename);
9593 XrmPutFileDatabase(preferences_database,filename);
9594#endif
9595}
9596
9597/*
9598%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9599% %
9600% %
9601% %
9602% X V i s u a l C l a s s N a m e %
9603% %
9604% %
9605% %
9606%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9607%
9608% XVisualClassName() returns the visual class name as a character string.
9609%
9610% The format of the XVisualClassName method is:
9611%
9612% char *XVisualClassName(const int visual_class)
9613%
9614% A description of each parameter follows:
9615%
9616% o visual_type: XVisualClassName returns the visual class as a character
9617% string.
9618%
9619% o class: Specifies the visual class.
9620%
cristy3ed852e2009-09-05 21:47:34 +00009621*/
9622static const char *XVisualClassName(const int visual_class)
9623{
9624 switch (visual_class)
9625 {
9626 case StaticGray: return("StaticGray");
9627 case GrayScale: return("GrayScale");
9628 case StaticColor: return("StaticColor");
9629 case PseudoColor: return("PseudoColor");
9630 case TrueColor: return("TrueColor");
9631 case DirectColor: return("DirectColor");
9632 }
9633 return("unknown visual class");
9634}
9635
9636/*
9637%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9638% %
9639% %
9640% %
9641% X W a r n i n g %
9642% %
9643% %
9644% %
9645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9646%
9647% XWarning() displays a warning reason in a Notice widget.
9648%
9649% The format of the XWarning method is:
9650%
9651% void XWarning(const unsigned int warning,const char *reason,
9652% const char *description)
9653%
9654% A description of each parameter follows:
9655%
9656% o warning: Specifies the numeric warning category.
9657%
9658% o reason: Specifies the reason to display before terminating the
9659% program.
9660%
9661% o description: Specifies any description to the reason.
9662%
9663*/
cristybcbda3f2011-09-03 13:01:22 +00009664MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009665 const char *reason,const char *description)
9666{
9667 char
9668 text[MaxTextExtent];
9669
9670 XWindows
9671 *windows;
9672
9673 if (reason == (char *) NULL)
9674 return;
9675 (void) CopyMagickString(text,reason,MaxTextExtent);
9676 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9677 windows=XSetWindows((XWindows *) ~0);
9678 XNoticeWidget(windows->display,windows,text,(char *) description);
9679}
9680
9681/*
9682%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9683% %
9684% %
9685% %
9686% X W i n d o w B y I D %
9687% %
9688% %
9689% %
9690%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9691%
9692% XWindowByID() locates a child window with a given ID. If not window with
9693% the given name is found, 0 is returned. Only the window specified and its
9694% subwindows are searched.
9695%
9696% The format of the XWindowByID function is:
9697%
9698% child=XWindowByID(display,window,id)
9699%
9700% A description of each parameter follows:
9701%
9702% o child: XWindowByID returns the window with the specified
9703% id. If no windows are found, XWindowByID returns 0.
9704%
9705% o display: Specifies a pointer to the Display structure; returned from
9706% XOpenDisplay.
9707%
9708% o id: Specifies the id of the window to locate.
9709%
9710*/
cristybcbda3f2011-09-03 13:01:22 +00009711MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009712 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009713{
9714 RectangleInfo
9715 rectangle_info;
9716
9717 register int
9718 i;
9719
9720 Status
9721 status;
9722
9723 unsigned int
9724 number_children;
9725
9726 Window
9727 child,
9728 *children,
9729 window;
9730
9731 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9732 assert(display != (Display *) NULL);
9733 assert(root_window != (Window) NULL);
9734 if (id == 0)
9735 return(XSelectWindow(display,&rectangle_info));
9736 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009737 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009738 status=XQueryTree(display,root_window,&child,&child,&children,
9739 &number_children);
9740 if (status == False)
9741 return((Window) NULL);
9742 window=(Window) NULL;
9743 for (i=0; i < (int) number_children; i++)
9744 {
9745 /*
9746 Search each child and their children.
9747 */
9748 window=XWindowByID(display,children[i],id);
9749 if (window != (Window) NULL)
9750 break;
9751 }
9752 if (children != (Window *) NULL)
9753 (void) XFree((void *) children);
9754 return(window);
9755}
9756
9757/*
9758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9759% %
9760% %
9761% %
9762% X W i n d o w B y N a m e %
9763% %
9764% %
9765% %
9766%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9767%
9768% XWindowByName() locates a window with a given name on a display. If no
9769% window with the given name is found, 0 is returned. If more than one window
9770% has the given name, the first one is returned. Only root and its children
9771% are searched.
9772%
9773% The format of the XWindowByName function is:
9774%
9775% window=XWindowByName(display,root_window,name)
9776%
9777% A description of each parameter follows:
9778%
9779% o window: XWindowByName returns the window id.
9780%
9781% o display: Specifies a pointer to the Display structure; returned from
9782% XOpenDisplay.
9783%
9784% o root_window: Specifies the id of the root window.
9785%
9786% o name: Specifies the name of the window to locate.
9787%
9788*/
cristybcbda3f2011-09-03 13:01:22 +00009789MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009790 const char *name)
9791{
9792 register int
9793 i;
9794
9795 Status
9796 status;
9797
9798 unsigned int
9799 number_children;
9800
9801 Window
9802 *children,
9803 child,
9804 window;
9805
9806 XTextProperty
9807 window_name;
9808
9809 assert(display != (Display *) NULL);
9810 assert(root_window != (Window) NULL);
9811 assert(name != (char *) NULL);
9812 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9813 if (XGetWMName(display,root_window,&window_name) != 0)
9814 if (LocaleCompare((char *) window_name.value,name) == 0)
9815 return(root_window);
9816 status=XQueryTree(display,root_window,&child,&child,&children,
9817 &number_children);
9818 if (status == False)
9819 return((Window) NULL);
9820 window=(Window) NULL;
9821 for (i=0; i < (int) number_children; i++)
9822 {
9823 /*
9824 Search each child and their children.
9825 */
9826 window=XWindowByName(display,children[i],name);
9827 if (window != (Window) NULL)
9828 break;
9829 }
9830 if (children != (Window *) NULL)
9831 (void) XFree((void *) children);
9832 return(window);
9833}
9834
9835/*
9836%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9837% %
9838% %
9839% %
9840% X W i n d o w B y P r o p e r y %
9841% %
9842% %
9843% %
9844%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9845%
9846% XWindowByProperty() locates a child window with a given property. If not
9847% window with the given name is found, 0 is returned. If more than one window
9848% has the given property, the first one is returned. Only the window
9849% specified and its subwindows are searched.
9850%
9851% The format of the XWindowByProperty function is:
9852%
9853% child=XWindowByProperty(display,window,property)
9854%
9855% A description of each parameter follows:
9856%
9857% o child: XWindowByProperty returns the window id with the specified
9858% property. If no windows are found, XWindowByProperty returns 0.
9859%
9860% o display: Specifies a pointer to the Display structure; returned from
9861% XOpenDisplay.
9862%
9863% o property: Specifies the property of the window to locate.
9864%
9865*/
cristybcbda3f2011-09-03 13:01:22 +00009866MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009867 const Atom property)
9868{
9869 Atom
9870 type;
9871
9872 int
9873 format;
9874
9875 Status
9876 status;
9877
9878 unsigned char
9879 *data;
9880
9881 unsigned int
9882 i,
9883 number_children;
9884
cristyf2faecf2010-05-28 19:19:36 +00009885 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009886 after,
9887 number_items;
9888
9889 Window
9890 child,
9891 *children,
9892 parent,
9893 root;
9894
9895 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9896 assert(display != (Display *) NULL);
9897 assert(window != (Window) NULL);
9898 assert(property != (Atom) NULL);
9899 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9900 if (status == False)
9901 return((Window) NULL);
9902 type=(Atom) NULL;
9903 child=(Window) NULL;
9904 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9905 {
9906 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9907 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9908 if (data != NULL)
9909 (void) XFree((void *) data);
9910 if ((status == Success) && (type != (Atom) NULL))
9911 child=children[i];
9912 }
9913 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9914 child=XWindowByProperty(display,children[i],property);
9915 if (children != (Window *) NULL)
9916 (void) XFree((void *) children);
9917 return(child);
9918}
9919#else
9920
9921/*
9922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9923% %
9924% %
9925% %
9926% X I m p o r t I m a g e %
9927% %
9928% %
9929% %
9930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9931%
9932% XImportImage() reads an image from an X window.
9933%
9934% The format of the XImportImage method is:
9935%
cristya0dc96a2011-12-19 23:58:54 +00009936% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9937% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009938%
9939% A description of each parameter follows:
9940%
9941% o image_info: the image info..
9942%
9943% o ximage_info: Specifies a pointer to an XImportInfo structure.
9944%
cristya0dc96a2011-12-19 23:58:54 +00009945% o exception: return any errors or warnings in this structure.
9946%
cristy3ed852e2009-09-05 21:47:34 +00009947*/
cristy4bc52022012-12-13 14:15:41 +00009948MagickExport Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009949 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009950{
9951 assert(image_info != (const ImageInfo *) NULL);
9952 assert(image_info->signature == MagickSignature);
9953 if (image_info->debug != MagickFalse)
9954 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9955 image_info->filename);
9956 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009957 assert(exception != (ExceptionInfo *) NULL);
9958 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009959 return((Image *) NULL);
9960}
cristy534d0a32013-04-13 16:27:24 +00009961
9962/*
9963%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9964% %
9965% %
9966% %
9967% X R e n d e r X 1 1 %
9968% %
9969% %
9970% %
9971%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9972%
9973% XRenderImage() renders text on the image with an X11 font. It also returns
9974% the bounding box of the text relative to the image.
9975%
9976% The format of the XRenderImage method is:
9977%
9978% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
9979% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
9980%
9981% A description of each parameter follows:
9982%
9983% o image: the image.
9984%
9985% o draw_info: the draw info.
9986%
9987% o offset: (x,y) location of text relative to image.
9988%
9989% o metrics: bounding box of text.
9990%
9991% o exception: return any errors or warnings in this structure.
9992%
9993*/
9994MagickPrivate MagickBooleanType XRenderImage(Image *image,
9995 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
9996 ExceptionInfo *exception)
9997{
9998 (void) draw_info;
9999 (void) offset;
10000 (void) metrics;
10001 (void) ThrowMagickException(exception,GetMagickModule(),
10002 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","'%s' (X11)",
10003 image->filename);
10004 return(MagickFalse);
10005}
cristy3ed852e2009-09-05 21:47:34 +000010006#endif
10007
10008/*
10009%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10010% %
10011% %
10012% %
cristy576974e2009-10-25 20:45:31 +000010013+ X C o m p o n e n t G e n e s i s %
10014% %
10015% %
10016% %
10017%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10018%
10019% XComponentGenesis() instantiates the X component.
10020%
10021% The format of the XComponentGenesis method is:
10022%
10023% MagickBooleanType XComponentGenesis(void)
10024%
10025*/
cristy5ff4eaf2011-09-03 01:38:02 +000010026MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +000010027{
10028 return(MagickTrue);
10029}
10030
10031/*
10032%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10033% %
10034% %
10035% %
cristy3ed852e2009-09-05 21:47:34 +000010036% X G e t I m p o r t I n f o %
10037% %
10038% %
10039% %
10040%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10041%
10042% XGetImportInfo() initializes the XImportInfo structure.
10043%
10044% The format of the XGetImportInfo method is:
10045%
10046% void XGetImportInfo(XImportInfo *ximage_info)
10047%
10048% A description of each parameter follows:
10049%
10050% o ximage_info: Specifies a pointer to an ImageInfo structure.
10051%
10052*/
10053MagickExport void XGetImportInfo(XImportInfo *ximage_info)
10054{
10055 assert(ximage_info != (XImportInfo *) NULL);
10056 ximage_info->frame=MagickFalse;
10057 ximage_info->borders=MagickFalse;
10058 ximage_info->screen=MagickFalse;
10059 ximage_info->descend=MagickTrue;
10060 ximage_info->silent=MagickFalse;
10061}