blob: 3d7fe2324f43bc2de09557f2026d9519dd4fe326 [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 */
3145 pixel->highlight_color.red=(unsigned short) ((
3146 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3147 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3148 pixel->highlight_color.green=(unsigned short) ((
3149 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3150 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3151 pixel->highlight_color.blue=(unsigned short) ((
3152 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3153 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3154 pixel->highlight_color.pixel=
3155 XStandardPixel(map_info,&pixel->highlight_color);
3156 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3157 /*
3158 Set shadow color.
3159 */
cristya19f1d72012-08-07 18:24:38 +00003160 pixel->shadow_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003161 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003162 pixel->shadow_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003163 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003164 pixel->shadow_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003165 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3166 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3167 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3168 /*
3169 Set depth color.
3170 */
cristya19f1d72012-08-07 18:24:38 +00003171 pixel->depth_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003172 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003173 pixel->depth_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003174 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003175 pixel->depth_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003176 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3177 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3178 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3179 /*
3180 Set trough color.
3181 */
cristya19f1d72012-08-07 18:24:38 +00003182 pixel->trough_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003183 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003184 pixel->trough_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003185 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003186 pixel->trough_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003187 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3188 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3189 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3190 /*
3191 Set pen color.
3192 */
3193 for (i=0; i < MaxNumberPens; i++)
3194 {
3195 (void) XParseColor(display,colormap,(char *) PenColors[i],
3196 &pixel->pen_colors[i]);
3197 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3198 &pixel->pen_colors[i]);
3199 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003200 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003201 resource_info->pen_colors[i]);
3202 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3203 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3204 }
3205 pixel->box_color=pixel->background_color;
3206 pixel->pen_color=pixel->foreground_color;
3207 pixel->box_index=0;
3208 pixel->pen_index=1;
3209 if (image != (Image *) NULL)
3210 {
3211 if ((resource_info->gamma_correct != MagickFalse) &&
3212 (image->gamma != 0.0))
3213 {
3214 GeometryInfo
3215 geometry_info;
3216
3217 MagickStatusType
3218 flags;
3219
3220 /*
3221 Initialize map relative to display and image gamma.
3222 */
3223 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3224 red_gamma=geometry_info.rho;
3225 green_gamma=geometry_info.sigma;
3226 if ((flags & SigmaValue) == 0)
3227 green_gamma=red_gamma;
3228 blue_gamma=geometry_info.xi;
3229 if ((flags & XiValue) == 0)
3230 blue_gamma=red_gamma;
3231 red_gamma*=image->gamma;
3232 green_gamma*=image->gamma;
3233 blue_gamma*=image->gamma;
3234 }
3235 if (image->storage_class == PseudoClass)
3236 {
3237 /*
3238 Initialize pixel array for images of type PseudoClass.
3239 */
cristybb503372010-05-27 20:51:26 +00003240 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003241 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003242 for (i=0; i < MaxNumberPens; i++)
3243 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3244 pixel->colors+=MaxNumberPens;
3245 }
3246 }
3247}
3248
3249/*
3250%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3251% %
3252% %
3253% %
3254% X G e t R e s o u r c e C l a s s %
3255% %
3256% %
3257% %
3258%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3259%
3260% XGetResourceClass() queries the X server for the specified resource name or
3261% class. If the resource name or class is not defined in the database, the
3262% supplied default value is returned.
3263%
3264% The format of the XGetResourceClass method is:
3265%
3266% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3267% const char *keyword,char *resource_default)
3268%
3269% A description of each parameter follows:
3270%
3271% o database: Specifies a resource database; returned from
3272% XrmGetStringDatabase.
3273%
3274% o client_name: Specifies the application name used to retrieve resource
3275% info from the X server database.
3276%
3277% o keyword: Specifies the keyword of the value being retrieved.
3278%
3279% o resource_default: Specifies the default value to return if the query
3280% fails to find the specified keyword/class.
3281%
3282*/
3283MagickExport char *XGetResourceClass(XrmDatabase database,
3284 const char *client_name,const char *keyword,char *resource_default)
3285{
3286 char
3287 resource_class[MaxTextExtent],
3288 resource_name[MaxTextExtent];
3289
3290 static char
3291 *resource_type;
3292
3293 Status
3294 status;
3295
3296 XrmValue
3297 resource_value;
3298
3299 if (database == (XrmDatabase) NULL)
3300 return(resource_default);
3301 *resource_name='\0';
3302 *resource_class='\0';
3303 if (keyword != (char *) NULL)
3304 {
3305 int
3306 c,
3307 k;
3308
3309 /*
3310 Initialize resource keyword and class.
3311 */
cristyb51dff52011-05-19 16:55:47 +00003312 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003313 client_name,keyword);
3314 c=(int) (*client_name);
3315 if ((c >= XK_a) && (c <= XK_z))
3316 c-=(XK_a-XK_A);
3317 else
3318 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3319 c-=(XK_agrave-XK_Agrave);
3320 else
3321 if ((c >= XK_oslash) && (c <= XK_thorn))
3322 c-=(XK_oslash-XK_Ooblique);
3323 k=(int) (*keyword);
3324 if ((k >= XK_a) && (k <= XK_z))
3325 k-=(XK_a-XK_A);
3326 else
3327 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3328 k-=(XK_agrave-XK_Agrave);
3329 else
3330 if ((k >= XK_oslash) && (k <= XK_thorn))
3331 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003332 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003333 client_name+1,k,keyword+1);
3334 }
3335 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3336 &resource_value);
3337 if (status == False)
3338 return(resource_default);
3339 return(resource_value.addr);
3340}
3341
3342/*
3343%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3344% %
3345% %
3346% %
3347% X G e t R e s o u r c e D a t a b a s e %
3348% %
3349% %
3350% %
3351%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3352%
3353% XGetResourceDatabase() creates a new resource database and initializes it.
3354%
3355% The format of the XGetResourceDatabase method is:
3356%
3357% XrmDatabase XGetResourceDatabase(Display *display,
3358% const char *client_name)
3359%
3360% A description of each parameter follows:
3361%
3362% o database: XGetResourceDatabase() returns the database after it is
3363% initialized.
3364%
3365% o display: Specifies a connection to an X server; returned from
3366% XOpenDisplay.
3367%
3368% o client_name: Specifies the application name used to retrieve resource
3369% info from the X server database.
3370%
3371*/
3372MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3373 const char *client_name)
3374{
3375 char
3376 filename[MaxTextExtent];
3377
3378 int
3379 c;
3380
3381 register const char
3382 *p;
3383
3384 XrmDatabase
3385 resource_database,
3386 server_database;
3387
3388 if (display == (Display *) NULL)
3389 return((XrmDatabase) NULL);
3390 assert(client_name != (char *) NULL);
3391 /*
3392 Initialize resource database.
3393 */
3394 XrmInitialize();
3395 (void) XGetDefault(display,(char *) client_name,"dummy");
3396 resource_database=XrmGetDatabase(display);
3397 /*
3398 Combine application database.
3399 */
3400 if (client_name != (char *) NULL)
3401 {
3402 /*
3403 Get basename of client.
3404 */
3405 p=client_name+(strlen(client_name)-1);
3406 while ((p > client_name) && (*p != '/'))
3407 p--;
3408 if (*p == '/')
3409 client_name=p+1;
3410 }
3411 c=(int) (*client_name);
3412 if ((c >= XK_a) && (c <= XK_z))
3413 c-=(XK_a-XK_A);
3414 else
3415 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3416 c-=(XK_agrave-XK_Agrave);
3417 else
3418 if ((c >= XK_oslash) && (c <= XK_thorn))
3419 c-=(XK_oslash-XK_Ooblique);
3420#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003421 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003422 X11_APPLICATION_PATH,c,client_name+1);
3423 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3424#endif
3425 if (XResourceManagerString(display) != (char *) NULL)
3426 {
3427 /*
3428 Combine server database.
3429 */
3430 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3431 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3432 }
3433 /*
3434 Merge user preferences database.
3435 */
3436#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003437 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003438 X11_PREFERENCES_PATH,client_name);
3439 ExpandFilename(filename);
3440 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3441#endif
3442 return(resource_database);
3443}
3444
3445/*
3446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3447% %
3448% %
3449% %
3450% X G e t R e s o u r c e I n f o %
3451% %
3452% %
3453% %
3454%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3455%
3456% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3457%
3458% The format of the XGetResourceInfo method is:
3459%
3460% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3461% const char *client_name,XResourceInfo *resource_info)
3462%
3463% A description of each parameter follows:
3464%
3465% o image_info: the image info.
3466%
3467% o database: Specifies a resource database; returned from
3468% XrmGetStringDatabase.
3469%
3470% o client_name: Specifies the application name used to retrieve
3471% resource info from the X server database.
3472%
3473% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3474%
3475*/
3476MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3477 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3478{
3479 char
cristy00976d82011-02-20 20:31:28 +00003480 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003481 *resource_value;
3482
cristybcdf5672012-05-24 22:58:54 +00003483 extern const char
3484 BorderColor[],
3485 ForegroundColor[];
3486
cristy3ed852e2009-09-05 21:47:34 +00003487 /*
3488 Initialize resource info fields.
3489 */
3490 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3491 assert(resource_info != (XResourceInfo *) NULL);
3492 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3493 resource_info->resource_database=database;
3494 resource_info->image_info=(ImageInfo *) image_info;
3495 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3496 XMagickProgressMonitor,(void *) NULL);
3497 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3498 resource_info->close_server=MagickTrue;
3499 resource_info->client_name=AcquireString(client_name);
3500 resource_value=XGetResourceClass(database,client_name,"backdrop",
3501 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003502 resource_info->backdrop=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003503 resource_info->background_color=XGetResourceInstance(database,client_name,
3504 "background",(char *) "#d6d6d6d6d6d6");
3505 resource_info->border_color=XGetResourceInstance(database,client_name,
3506 "borderColor",BorderColor);
3507 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3508 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003509 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3510 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003511 resource_value=XGetResourceClass(database,client_name,"colormap",
3512 (char *) "shared");
3513 resource_info->colormap=UndefinedColormap;
3514 if (LocaleCompare("private",resource_value) == 0)
3515 resource_info->colormap=PrivateColormap;
3516 if (LocaleCompare("shared",resource_value) == 0)
3517 resource_info->colormap=SharedColormap;
3518 if (resource_info->colormap == UndefinedColormap)
cristyc38fbf52013-11-03 13:55:54 +00003519 ThrowXWindowException(OptionError,"UnrecognizedColormapType",
cristy3ed852e2009-09-05 21:47:34 +00003520 resource_value);
3521 resource_value=XGetResourceClass(database,client_name,
3522 "colorRecovery",(char *) "False");
anthony6f201312012-03-30 04:08:15 +00003523 resource_info->color_recovery=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003524 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3525 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003526 resource_info->confirm_exit=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003527 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3528 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003529 resource_info->confirm_edit=IsStringTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003530 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003531 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003532 resource_info->display_gamma=XGetResourceClass(database,client_name,
3533 "displayGamma",(char *) "2.2");
3534 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3535 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003536 resource_info->display_warnings=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003537 resource_info->font=XGetResourceClass(database,client_name,"font",
3538 (char *) NULL);
3539 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3540 resource_info->font);
3541 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3542 (char *) "fixed");
3543 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3544 (char *) "variable");
3545 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3546 (char *) "5x8");
3547 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3548 (char *) "6x10");
3549 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3550 (char *) "7x13bold");
3551 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3552 (char *) "8x13bold");
3553 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3554 (char *) "9x15bold");
3555 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3556 (char *) "10x20");
3557 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3558 (char *) "12x24");
3559 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3560 (char *) "fixed");
3561 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3562 (char *) "fixed");
3563 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3564 "foreground",ForegroundColor);
3565 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
cristy8bc259b2012-06-21 23:53:15 +00003566 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003567 resource_info->gamma_correct=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003568 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3569 client_name,"geometry",(char *) NULL));
3570 resource_value=XGetResourceClass(database,client_name,"gravity",
3571 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003572 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003573 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003574 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3575 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003576 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3577 "iconGeometry",(char *) NULL);
3578 resource_value=XGetResourceClass(database,client_name,"iconic",
3579 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003580 resource_info->iconic=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003581 resource_value=XGetResourceClass(database,client_name,"immutable",
3582 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3583 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003584 resource_info->immutable=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003585 resource_value=XGetResourceClass(database,client_name,"magnify",
3586 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003587 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003588 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3589 (char *) NULL);
3590 resource_info->matte_color=XGetResourceInstance(database,client_name,
3591 "mattecolor",(char *) NULL);
3592 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3593 "name",(char *) NULL));
3594 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3595 (char *) "black");
3596 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3597 (char *) "blue");
3598 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3599 (char *) "cyan");
3600 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3601 (char *) "green");
3602 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3603 (char *) "gray");
3604 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3605 (char *) "red");
3606 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3607 (char *) "magenta");
3608 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3609 (char *) "yellow");
3610 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3611 (char *) "white");
3612 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3613 (char *) "gray");
3614 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3615 (char *) "gray");
3616 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003617 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003618 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003619 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003620 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3621 "font",(char *) "fixed");
3622 resource_info->text_font=XGetResourceClass(database,client_name,
3623 "textFontList",resource_info->text_font);
3624 resource_info->title=XGetResourceClass(database,client_name,"title",
3625 (char *) NULL);
3626 resource_value=XGetResourceClass(database,client_name,"undoCache",
cristy92befbd2012-09-16 14:08:12 +00003627 (char *) "256");
cristye27293e2009-12-18 02:53:20 +00003628 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003629 resource_value=XGetResourceClass(database,client_name,"update",
3630 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003631 resource_info->update=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003632 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3633 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003634 resource_info->use_pixmap=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003635 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3636 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003637 resource_info->use_shared_memory=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003638 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3639 (char *) NULL);
3640 resource_info->window_group=XGetResourceClass(database,client_name,
3641 "windowGroup",(char *) NULL);
3642 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3643 (char *) NULL);
3644 resource_info->write_filename=XGetResourceClass(database,client_name,
3645 "writeFilename",(char *) NULL);
3646}
3647
3648/*
3649%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3650% %
3651% %
3652% %
3653% X G e t R e s o u r c e I n s t a n c e %
3654% %
3655% %
3656% %
3657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3658%
3659% XGetResourceInstance() queries the X server for the specified resource name.
3660% If the resource name is not defined in the database, the supplied default
3661% value is returned.
3662%
3663% The format of the XGetResourceInstance method is:
3664%
3665% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3666% const char *keyword,const char *resource_default)
3667%
3668% A description of each parameter follows:
3669%
3670% o database: Specifies a resource database; returned from
3671% XrmGetStringDatabase.
3672%
3673% o client_name: Specifies the application name used to retrieve
3674% resource info from the X server database.
3675%
3676% o keyword: Specifies the keyword of the value being retrieved.
3677%
3678% o resource_default: Specifies the default value to return if the query
3679% fails to find the specified keyword/class.
3680%
3681*/
3682MagickExport char *XGetResourceInstance(XrmDatabase database,
3683 const char *client_name,const char *keyword,const char *resource_default)
3684{
3685 char
3686 *resource_type,
3687 resource_name[MaxTextExtent];
3688
3689 Status
3690 status;
3691
3692 XrmValue
3693 resource_value;
3694
3695 if (database == (XrmDatabase) NULL)
3696 return((char *) resource_default);
3697 *resource_name='\0';
3698 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003699 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003700 keyword);
3701 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3702 &resource_value);
3703 if (status == False)
3704 return((char *) resource_default);
3705 return(resource_value.addr);
3706}
3707
3708/*
3709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3710% %
3711% %
3712% %
3713% X G e t S c r e e n D e n s i t y %
3714% %
3715% %
3716% %
3717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3718%
3719% XGetScreenDensity() returns the density of the X server screen in
3720% dots-per-inch.
3721%
3722% The format of the XGetScreenDensity method is:
3723%
3724% char *XGetScreenDensity(Display *display)
3725%
3726% A description of each parameter follows:
3727%
3728% o density: XGetScreenDensity() returns the density of the X screen in
3729% dots-per-inch.
3730%
3731% o display: Specifies a connection to an X server; returned from
3732% XOpenDisplay.
3733%
3734*/
3735MagickExport char *XGetScreenDensity(Display *display)
3736{
3737 char
3738 density[MaxTextExtent];
3739
3740 double
3741 x_density,
3742 y_density;
3743
3744 /*
3745 Set density as determined by screen size.
3746 */
3747 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3748 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3749 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3750 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003751 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003752 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003753 return(GetPageGeometry(density));
3754}
3755
3756/*
3757%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3758% %
3759% %
3760% %
3761+ X G e t S u b w i n d o w %
3762% %
3763% %
3764% %
3765%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3766%
3767% XGetSubwindow() returns the subwindow of a window chosen the user with the
3768% pointer and a button press.
3769%
3770% The format of the XGetSubwindow method is:
3771%
3772% Window XGetSubwindow(Display *display,Window window,int x,int y)
3773%
3774% A description of each parameter follows:
3775%
3776% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3777% otherwise the subwindow is returned.
3778%
3779% o display: Specifies a connection to an X server; returned from
3780% XOpenDisplay.
3781%
3782% o window: Specifies a pointer to a Window.
3783%
3784% o x: the x coordinate of the pointer relative to the origin of the
3785% window.
3786%
3787% o y: the y coordinate of the pointer relative to the origin of the
3788% window.
3789%
cristy3ed852e2009-09-05 21:47:34 +00003790*/
3791static Window XGetSubwindow(Display *display,Window window,int x,int y)
3792{
3793 int
3794 x_offset,
3795 y_offset;
3796
3797 Status
3798 status;
3799
3800 Window
3801 source_window,
3802 target_window;
3803
3804 assert(display != (Display *) NULL);
3805 source_window=XRootWindow(display,XDefaultScreen(display));
3806 if (window == (Window) NULL)
3807 return(source_window);
3808 target_window=window;
3809 for ( ; ; )
3810 {
3811 status=XTranslateCoordinates(display,source_window,window,x,y,
3812 &x_offset,&y_offset,&target_window);
3813 if (status != True)
3814 break;
3815 if (target_window == (Window) NULL)
3816 break;
3817 source_window=window;
3818 window=target_window;
3819 x=x_offset;
3820 y=y_offset;
3821 }
3822 if (target_window == (Window) NULL)
3823 target_window=window;
3824 return(target_window);
3825}
3826
3827/*
3828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3829% %
3830% %
3831% %
3832% X G e t W i n d o w C o l o r %
3833% %
3834% %
3835% %
3836%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3837%
3838% XGetWindowColor() returns the color of a pixel interactively chosen from the
3839% X server.
3840%
3841% The format of the XGetWindowColor method is:
3842%
3843% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003844% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003845%
3846% A description of each parameter follows:
3847%
3848% o display: Specifies a connection to an X server; returned from
3849% XOpenDisplay.
3850%
3851% o windows: Specifies a pointer to a XWindows structure.
3852%
3853% o name: the name of the color if found in the X Color Database is
3854% returned in this character string.
3855%
cristy6710d842011-10-20 23:23:00 +00003856% o exception: return any errors or warnings in this structure.
3857%
cristy3ed852e2009-09-05 21:47:34 +00003858*/
cristybcbda3f2011-09-03 13:01:22 +00003859MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003860 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003861{
3862 int
3863 x,
3864 y;
3865
cristy101ab702011-10-13 13:06:32 +00003866 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003867 pixel;
3868
3869 RectangleInfo
3870 crop_info;
3871
3872 Status
3873 status;
3874
3875 Window
3876 child,
3877 client_window,
3878 root_window,
3879 target_window;
3880
3881 XColor
3882 color;
3883
3884 XImage
3885 *ximage;
3886
3887 XWindowAttributes
3888 window_attributes;
3889
3890 /*
3891 Choose a pixel from the X server.
3892 */
3893 assert(display != (Display *) NULL);
3894 assert(name != (char *) NULL);
3895 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3896 *name='\0';
3897 target_window=XSelectWindow(display,&crop_info);
3898 if (target_window == (Window) NULL)
3899 return(MagickFalse);
3900 root_window=XRootWindow(display,XDefaultScreen(display));
3901 client_window=target_window;
3902 if (target_window != root_window)
3903 {
3904 unsigned int
3905 d;
3906
3907 /*
3908 Get client window.
3909 */
3910 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3911 if (status != False)
3912 {
3913 client_window=XClientWindow(display,target_window);
3914 target_window=client_window;
3915 }
3916 }
3917 /*
3918 Verify window is viewable.
3919 */
3920 status=XGetWindowAttributes(display,target_window,&window_attributes);
3921 if ((status == False) || (window_attributes.map_state != IsViewable))
3922 return(MagickFalse);
3923 /*
3924 Get window X image.
3925 */
3926 (void) XTranslateCoordinates(display,root_window,target_window,
3927 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3928 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3929 if (ximage == (XImage *) NULL)
3930 return(MagickFalse);
3931 color.pixel=XGetPixel(ximage,0,0);
3932 XDestroyImage(ximage);
3933 /*
3934 Match color against the color database.
3935 */
3936 (void) XQueryColor(display,window_attributes.colormap,&color);
cristye42f6582012-02-11 17:59:50 +00003937 pixel.red=(double) ScaleShortToQuantum(color.red);
3938 pixel.green=(double) ScaleShortToQuantum(color.green);
3939 pixel.blue=(double) ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003940 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003941 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003942 exception);
cristy3ed852e2009-09-05 21:47:34 +00003943 return(MagickTrue);
3944}
3945
3946/*
3947%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3948% %
3949% %
3950% %
3951+ X G e t W i n d o w I m a g e %
3952% %
3953% %
3954% %
3955%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3956%
3957% XGetWindowImage() reads an image from the target X window and returns it.
3958% XGetWindowImage() optionally descends the window hierarchy and overlays the
3959% target image with each child image in an optimized fashion. Any child
3960% window that have the same visual, colormap, and are contained by its parent
3961% are exempted.
3962%
3963% The format of the XGetWindowImage method is:
3964%
3965% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003966% const unsigned int borders,const unsigned int level,
3967% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003968%
3969% A description of each parameter follows:
3970%
3971% o display: Specifies a connection to an X server; returned from
3972% XOpenDisplay.
3973%
3974% o window: Specifies the window to obtain the image from.
3975%
3976% o borders: Specifies whether borders pixels are to be saved with
3977% the image.
3978%
3979% o level: Specifies an unsigned integer representing the level of
3980% decent in the window hierarchy. This value must be zero or one on
3981% the initial call to XGetWindowImage. A value of zero returns after
3982% one call. A value of one causes the function to descend the window
3983% hierarchy and overlay the target image with each subwindow image.
3984%
cristy6710d842011-10-20 23:23:00 +00003985% o exception: return any errors or warnings in this structure.
3986%
cristy3ed852e2009-09-05 21:47:34 +00003987*/
3988static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003989 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003990{
3991 typedef struct _ColormapInfo
3992 {
3993 Colormap
3994 colormap;
3995
3996 XColor
3997 *colors;
3998
3999 struct _ColormapInfo
4000 *next;
4001 } ColormapInfo;
4002
4003 typedef struct _WindowInfo
4004 {
4005 Window
4006 window,
4007 parent;
4008
4009 Visual
4010 *visual;
4011
4012 Colormap
4013 colormap;
4014
4015 XSegment
4016 bounds;
4017
4018 RectangleInfo
4019 crop_info;
4020 } WindowInfo;
4021
cristy3ed852e2009-09-05 21:47:34 +00004022 int
4023 display_height,
4024 display_width,
4025 id,
4026 x_offset,
4027 y_offset;
4028
cristy4c08aed2011-07-01 19:47:50 +00004029 Quantum
4030 index;
4031
cristy3ed852e2009-09-05 21:47:34 +00004032 RectangleInfo
4033 crop_info;
4034
cristy3ed852e2009-09-05 21:47:34 +00004035 register int
4036 i;
4037
4038 static ColormapInfo
4039 *colormap_info = (ColormapInfo *) NULL;
4040
4041 static int
4042 max_windows = 0,
4043 number_windows = 0;
4044
4045 static WindowInfo
4046 *window_info;
4047
4048 Status
4049 status;
4050
4051 Window
4052 child,
4053 root_window;
4054
4055 XWindowAttributes
4056 window_attributes;
4057
4058 /*
4059 Verify window is viewable.
4060 */
4061 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4062 assert(display != (Display *) NULL);
4063 status=XGetWindowAttributes(display,window,&window_attributes);
4064 if ((status == False) || (window_attributes.map_state != IsViewable))
4065 return((Image *) NULL);
4066 /*
4067 Cropping rectangle is relative to root window.
4068 */
4069 root_window=XRootWindow(display,XDefaultScreen(display));
4070 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4071 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004072 crop_info.x=(ssize_t) x_offset;
4073 crop_info.y=(ssize_t) y_offset;
4074 crop_info.width=(size_t) window_attributes.width;
4075 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004076 if (borders != MagickFalse)
4077 {
4078 /*
4079 Include border in image.
4080 */
cristybb503372010-05-27 20:51:26 +00004081 crop_info.x-=(ssize_t) window_attributes.border_width;
4082 crop_info.y-=(ssize_t) window_attributes.border_width;
4083 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4084 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004085 }
4086 /*
4087 Crop to root window.
4088 */
4089 if (crop_info.x < 0)
4090 {
4091 crop_info.width+=crop_info.x;
4092 crop_info.x=0;
4093 }
4094 if (crop_info.y < 0)
4095 {
4096 crop_info.height+=crop_info.y;
4097 crop_info.y=0;
4098 }
4099 display_width=XDisplayWidth(display,XDefaultScreen(display));
4100 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004101 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004102 display_height=XDisplayHeight(display,XDefaultScreen(display));
4103 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004104 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004105 /*
4106 Initialize window info attributes.
4107 */
4108 if (number_windows >= max_windows)
4109 {
4110 /*
4111 Allocate or resize window info buffer.
4112 */
4113 max_windows+=1024;
4114 if (window_info == (WindowInfo *) NULL)
4115 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4116 sizeof(*window_info));
4117 else
4118 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4119 max_windows,sizeof(*window_info));
4120 }
4121 if (window_info == (WindowInfo *) NULL)
4122 {
cristyc38fbf52013-11-03 13:55:54 +00004123 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed","...");
cristy3ed852e2009-09-05 21:47:34 +00004124 return((Image *) NULL);
4125 }
4126 id=number_windows++;
4127 window_info[id].window=window;
4128 window_info[id].visual=window_attributes.visual;
4129 window_info[id].colormap=window_attributes.colormap;
4130 window_info[id].bounds.x1=(short) crop_info.x;
4131 window_info[id].bounds.y1=(short) crop_info.y;
4132 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4133 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4134 crop_info.x-=x_offset;
4135 crop_info.y-=y_offset;
4136 window_info[id].crop_info=crop_info;
4137 if (level != 0)
4138 {
4139 unsigned int
4140 number_children;
4141
4142 Window
4143 *children;
4144
4145 /*
4146 Descend the window hierarchy.
4147 */
4148 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4149 &children,&number_children);
4150 for (i=0; i < id; i++)
4151 if ((window_info[i].window == window_info[id].parent) &&
4152 (window_info[i].visual == window_info[id].visual) &&
4153 (window_info[i].colormap == window_info[id].colormap))
4154 {
cristy64057b02013-01-11 00:09:58 +00004155 if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
4156 (window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
4157 (window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
4158 (window_info[id].bounds.y2 > window_info[i].bounds.y2))
cristy3ed852e2009-09-05 21:47:34 +00004159 {
4160 /*
4161 Eliminate windows not circumscribed by their parent.
4162 */
4163 number_windows--;
4164 break;
4165 }
4166 }
4167 if ((status == True) && (number_children != 0))
4168 {
4169 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004170 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4171 exception);
cristy3ed852e2009-09-05 21:47:34 +00004172 (void) XFree((void *) children);
4173 }
4174 }
4175 if (level <= 1)
4176 {
cristyc57f6942010-11-12 01:47:39 +00004177 CacheView
4178 *composite_view;
4179
cristy3ed852e2009-09-05 21:47:34 +00004180 ColormapInfo
4181 *next;
4182
cristy3ed852e2009-09-05 21:47:34 +00004183 Image
4184 *composite_image,
4185 *image;
4186
4187 int
4188 y;
4189
4190 MagickBooleanType
4191 import;
4192
4193 register int
4194 j,
4195 x;
4196
cristy4c08aed2011-07-01 19:47:50 +00004197 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004198 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004199
cristybb503372010-05-27 20:51:26 +00004200 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004201 pixel;
4202
4203 unsigned int
4204 number_colors;
4205
4206 XColor
4207 *colors;
4208
4209 XImage
4210 *ximage;
4211
4212 /*
4213 Get X image for each window in the list.
4214 */
4215 image=NewImageList();
4216 for (id=0; id < number_windows; id++)
4217 {
4218 /*
4219 Does target window intersect top level window?
4220 */
cristy088af952013-08-19 18:34:20 +00004221 import=((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
cristy3ed852e2009-09-05 21:47:34 +00004222 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4223 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4224 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4225 MagickTrue : MagickFalse;
4226 /*
4227 Is target window contained by another window with the same colormap?
4228 */
4229 for (j=0; j < id; j++)
4230 if ((window_info[id].visual == window_info[j].visual) &&
4231 (window_info[id].colormap == window_info[j].colormap))
4232 {
cristy64057b02013-01-11 00:09:58 +00004233 if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
4234 (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
4235 (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
4236 (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
cristy088af952013-08-19 18:34:20 +00004237 import=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00004238 }
cristy3ed852e2009-09-05 21:47:34 +00004239 if (import == MagickFalse)
4240 continue;
4241 /*
4242 Get X image.
4243 */
4244 ximage=XGetImage(display,window_info[id].window,(int)
4245 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4246 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4247 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4248 if (ximage == (XImage *) NULL)
4249 continue;
4250 /*
4251 Initialize window colormap.
4252 */
4253 number_colors=0;
4254 colors=(XColor *) NULL;
4255 if (window_info[id].colormap != (Colormap) NULL)
4256 {
4257 ColormapInfo
4258 *p;
4259
4260 /*
4261 Search colormap list for window colormap.
4262 */
4263 number_colors=(unsigned int) window_info[id].visual->map_entries;
4264 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4265 if (p->colormap == window_info[id].colormap)
4266 break;
4267 if (p == (ColormapInfo *) NULL)
4268 {
4269 /*
4270 Get the window colormap.
4271 */
4272 colors=(XColor *) AcquireQuantumMemory(number_colors,
4273 sizeof(*colors));
4274 if (colors == (XColor *) NULL)
4275 {
4276 XDestroyImage(ximage);
4277 return((Image *) NULL);
4278 }
4279 if ((window_info[id].visual->klass != DirectColor) &&
4280 (window_info[id].visual->klass != TrueColor))
4281 for (i=0; i < (int) number_colors; i++)
4282 {
cristybb503372010-05-27 20:51:26 +00004283 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004284 colors[i].pad='\0';
4285 }
4286 else
4287 {
cristybb503372010-05-27 20:51:26 +00004288 size_t
cristy3ed852e2009-09-05 21:47:34 +00004289 blue,
4290 blue_bit,
4291 green,
4292 green_bit,
4293 red,
4294 red_bit;
4295
4296 /*
4297 DirectColor or TrueColor visual.
4298 */
4299 red=0;
4300 green=0;
4301 blue=0;
4302 red_bit=window_info[id].visual->red_mask &
4303 (~(window_info[id].visual->red_mask)+1);
4304 green_bit=window_info[id].visual->green_mask &
4305 (~(window_info[id].visual->green_mask)+1);
4306 blue_bit=window_info[id].visual->blue_mask &
4307 (~(window_info[id].visual->blue_mask)+1);
4308 for (i=0; i < (int) number_colors; i++)
4309 {
cristy8891f9c2010-06-04 23:32:17 +00004310 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004311 colors[i].pad='\0';
4312 red+=red_bit;
4313 if (red > window_info[id].visual->red_mask)
4314 red=0;
4315 green+=green_bit;
4316 if (green > window_info[id].visual->green_mask)
4317 green=0;
4318 blue+=blue_bit;
4319 if (blue > window_info[id].visual->blue_mask)
4320 blue=0;
4321 }
4322 }
4323 (void) XQueryColors(display,window_info[id].colormap,colors,
4324 (int) number_colors);
4325 /*
4326 Append colormap to colormap list.
4327 */
cristy73bd4a52010-10-05 11:24:23 +00004328 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004329 if (p == (ColormapInfo *) NULL)
4330 return((Image *) NULL);
4331 p->colormap=window_info[id].colormap;
4332 p->colors=colors;
4333 p->next=colormap_info;
4334 colormap_info=p;
4335 }
4336 colors=p->colors;
4337 }
4338 /*
4339 Allocate image structure.
4340 */
cristy6710d842011-10-20 23:23:00 +00004341 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004342 if (composite_image == (Image *) NULL)
4343 {
4344 XDestroyImage(ximage);
4345 return((Image *) NULL);
4346 }
4347 /*
4348 Convert X image to MIFF format.
4349 */
4350 if ((window_info[id].visual->klass != TrueColor) &&
4351 (window_info[id].visual->klass != DirectColor))
4352 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004353 composite_image->columns=(size_t) ximage->width;
4354 composite_image->rows=(size_t) ximage->height;
cristy46ff2672012-12-14 15:32:26 +00004355 composite_view=AcquireAuthenticCacheView(composite_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00004356 switch (composite_image->storage_class)
4357 {
4358 case DirectClass:
4359 default:
4360 {
cristybb503372010-05-27 20:51:26 +00004361 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004362 color,
4363 index;
4364
cristybb503372010-05-27 20:51:26 +00004365 size_t
cristy3ed852e2009-09-05 21:47:34 +00004366 blue_mask,
4367 blue_shift,
4368 green_mask,
4369 green_shift,
4370 red_mask,
4371 red_shift;
4372
4373 /*
4374 Determine shift and mask for red, green, and blue.
4375 */
4376 red_mask=window_info[id].visual->red_mask;
4377 red_shift=0;
4378 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4379 {
4380 red_mask>>=1;
4381 red_shift++;
4382 }
4383 green_mask=window_info[id].visual->green_mask;
4384 green_shift=0;
4385 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4386 {
4387 green_mask>>=1;
4388 green_shift++;
4389 }
4390 blue_mask=window_info[id].visual->blue_mask;
4391 blue_shift=0;
4392 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4393 {
4394 blue_mask>>=1;
4395 blue_shift++;
4396 }
4397 /*
4398 Convert X image to DirectClass packets.
4399 */
4400 if ((number_colors != 0) &&
4401 (window_info[id].visual->klass == DirectColor))
4402 for (y=0; y < (int) composite_image->rows; y++)
4403 {
cristyc57f6942010-11-12 01:47:39 +00004404 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004405 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004406 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004407 break;
4408 for (x=0; x < (int) composite_image->columns; x++)
4409 {
4410 pixel=XGetPixel(ximage,x,y);
4411 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004412 SetPixelRed(composite_image,
4413 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004414 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004415 SetPixelGreen(composite_image,
4416 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004417 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004418 SetPixelBlue(composite_image,
4419 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004420 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004421 }
cristy0b1a7972011-10-22 22:17:02 +00004422 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4423 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004424 break;
4425 }
4426 else
4427 for (y=0; y < (int) composite_image->rows; y++)
4428 {
cristyc57f6942010-11-12 01:47:39 +00004429 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004430 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004431 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004432 break;
4433 for (x=0; x < (int) composite_image->columns; x++)
4434 {
4435 pixel=XGetPixel(ximage,x,y);
4436 color=(pixel >> red_shift) & red_mask;
4437 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004438 SetPixelRed(composite_image,
4439 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004440 color=(pixel >> green_shift) & green_mask;
4441 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004442 SetPixelGreen(composite_image,
4443 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004444 color=(pixel >> blue_shift) & blue_mask;
4445 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004446 SetPixelBlue(composite_image,
4447 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004448 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004449 }
cristy0b1a7972011-10-22 22:17:02 +00004450 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4451 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004452 break;
4453 }
4454 break;
4455 }
4456 case PseudoClass:
4457 {
4458 /*
4459 Create colormap.
4460 */
cristy0b1a7972011-10-22 22:17:02 +00004461 status=AcquireImageColormap(composite_image,number_colors,
4462 exception);
4463 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004464 {
4465 XDestroyImage(ximage);
4466 composite_image=DestroyImage(composite_image);
4467 return((Image *) NULL);
4468 }
4469 for (i=0; i < (int) composite_image->colors; i++)
4470 {
cristye42f6582012-02-11 17:59:50 +00004471 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004472 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004473 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004474 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004475 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004476 ScaleShortToQuantum(colors[i].blue);
4477 }
4478 /*
4479 Convert X image to PseudoClass packets.
4480 */
4481 for (y=0; y < (int) composite_image->rows; y++)
4482 {
cristyc57f6942010-11-12 01:47:39 +00004483 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4484 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004485 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004486 break;
cristy3ed852e2009-09-05 21:47:34 +00004487 for (x=0; x < (int) composite_image->columns; x++)
4488 {
cristy4c08aed2011-07-01 19:47:50 +00004489 index=(Quantum) XGetPixel(ximage,x,y);
4490 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004491 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004492 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004493 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004494 }
cristy0b1a7972011-10-22 22:17:02 +00004495 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4496 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004497 break;
4498 }
4499 break;
4500 }
4501 }
cristyc57f6942010-11-12 01:47:39 +00004502 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004503 XDestroyImage(ximage);
4504 if (image == (Image *) NULL)
4505 {
4506 image=composite_image;
4507 continue;
4508 }
4509 /*
4510 Composite any children in back-to-front order.
4511 */
4512 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4513 &x_offset,&y_offset,&child);
4514 x_offset-=(int) crop_info.x;
4515 if (x_offset < 0)
4516 x_offset=0;
4517 y_offset-=(int) crop_info.y;
4518 if (y_offset < 0)
4519 y_offset=0;
cristy39172402012-03-30 13:04:39 +00004520 (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00004521 (ssize_t) x_offset,(ssize_t) y_offset,exception);
cristy5f257b22012-03-07 00:27:29 +00004522 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004523 }
4524 /*
4525 Relinquish resources.
4526 */
4527 while (colormap_info != (ColormapInfo *) NULL)
4528 {
4529 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004530 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4531 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004532 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4533 colormap_info=next;
4534 }
4535 /*
4536 Relinquish resources and restore initial state.
4537 */
4538 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4539 max_windows=0;
4540 number_windows=0;
4541 colormap_info=(ColormapInfo *) NULL;
4542 return(image);
4543 }
4544 return((Image *) NULL);
4545}
4546
4547/*
4548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4549% %
4550% %
4551% %
4552% X G e t W i n d o w I n f o %
4553% %
4554% %
4555% %
4556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4557%
4558% XGetWindowInfo() initializes the XWindowInfo structure.
4559%
4560% The format of the XGetWindowInfo method is:
4561%
4562% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4563% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4564% XResourceInfo *resource_info,XWindowInfo *window)
4565% resource_info,window)
4566%
4567% A description of each parameter follows:
4568%
4569% o display: Specifies a connection to an X server; returned from
4570% XOpenDisplay.
4571%
4572% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4573% returned from XGetVisualInfo.
4574%
4575% o map_info: If map_type is specified, this structure is initialized
4576% with info from the Standard Colormap.
4577%
4578% o pixel: Specifies a pointer to a XPixelInfo structure.
4579%
4580% o font_info: Specifies a pointer to a XFontStruct structure.
4581%
4582% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4583%
4584*/
cristybcbda3f2011-09-03 13:01:22 +00004585MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004586 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4587 XResourceInfo *resource_info,XWindowInfo *window)
4588{
4589 /*
4590 Initialize window info.
4591 */
4592 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4593 assert(display != (Display *) NULL);
4594 assert(visual_info != (XVisualInfo *) NULL);
4595 assert(map_info != (XStandardColormap *) NULL);
4596 assert(pixel != (XPixelInfo *) NULL);
4597 assert(resource_info != (XResourceInfo *) NULL);
4598 assert(window != (XWindowInfo *) NULL);
4599 if (window->id != (Window) NULL)
4600 {
4601 if (window->cursor != (Cursor) NULL)
4602 (void) XFreeCursor(display,window->cursor);
4603 if (window->busy_cursor != (Cursor) NULL)
4604 (void) XFreeCursor(display,window->busy_cursor);
4605 if (window->highlight_stipple != (Pixmap) NULL)
4606 (void) XFreePixmap(display,window->highlight_stipple);
4607 if (window->shadow_stipple != (Pixmap) NULL)
4608 (void) XFreePixmap(display,window->shadow_stipple);
4609 if (window->name == (char *) NULL)
4610 window->name=AcquireString("");
4611 if (window->icon_name == (char *) NULL)
4612 window->icon_name=AcquireString("");
4613 }
4614 else
4615 {
4616 /*
4617 Initialize these attributes just once.
4618 */
4619 window->id=(Window) NULL;
4620 if (window->name == (char *) NULL)
4621 window->name=AcquireString("");
4622 if (window->icon_name == (char *) NULL)
4623 window->icon_name=AcquireString("");
4624 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4625 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4626 window->ximage=(XImage *) NULL;
4627 window->matte_image=(XImage *) NULL;
4628 window->pixmap=(Pixmap) NULL;
4629 window->matte_pixmap=(Pixmap) NULL;
4630 window->mapped=MagickFalse;
4631 window->stasis=MagickFalse;
4632 window->shared_memory=MagickTrue;
4633 window->segment_info=(void *) NULL;
4634#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4635 {
4636 XShmSegmentInfo
4637 *segment_info;
4638
4639 if (window->segment_info == (void *) NULL)
4640 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4641 segment_info=(XShmSegmentInfo *) window->segment_info;
4642 segment_info[0].shmid=(-1);
4643 segment_info[0].shmaddr=(char *) NULL;
4644 segment_info[1].shmid=(-1);
4645 segment_info[1].shmaddr=(char *) NULL;
4646 }
4647#endif
4648 }
4649 /*
4650 Initialize these attributes every time function is called.
4651 */
4652 window->screen=visual_info->screen;
4653 window->root=XRootWindow(display,visual_info->screen);
4654 window->visual=visual_info->visual;
4655 window->storage_class=(unsigned int) visual_info->klass;
4656 window->depth=(unsigned int) visual_info->depth;
4657 window->visual_info=visual_info;
4658 window->map_info=map_info;
4659 window->pixel_info=pixel;
4660 window->font_info=font_info;
4661 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4662 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4663 window->geometry=(char *) NULL;
4664 window->icon_geometry=(char *) NULL;
4665 if (resource_info->icon_geometry != (char *) NULL)
4666 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4667 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004668 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004669 window->width=1;
4670 window->height=1;
4671 window->min_width=1;
4672 window->min_height=1;
4673 window->width_inc=1;
4674 window->height_inc=1;
4675 window->border_width=resource_info->border_width;
4676 window->annotate_context=pixel->annotate_context;
4677 window->highlight_context=pixel->highlight_context;
4678 window->widget_context=pixel->widget_context;
4679 window->shadow_stipple=(Pixmap) NULL;
4680 window->highlight_stipple=(Pixmap) NULL;
4681 window->use_pixmap=MagickTrue;
4682 window->immutable=MagickFalse;
4683 window->shape=MagickFalse;
4684 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004685 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004686 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4687 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4688 window->attributes.background_pixel=pixel->background_color.pixel;
4689 window->attributes.background_pixmap=(Pixmap) NULL;
4690 window->attributes.bit_gravity=ForgetGravity;
4691 window->attributes.backing_store=WhenMapped;
4692 window->attributes.save_under=MagickTrue;
4693 window->attributes.border_pixel=pixel->border_color.pixel;
4694 window->attributes.colormap=map_info->colormap;
4695 window->attributes.cursor=window->cursor;
4696 window->attributes.do_not_propagate_mask=NoEventMask;
4697 window->attributes.event_mask=NoEventMask;
4698 window->attributes.override_redirect=MagickFalse;
4699 window->attributes.win_gravity=NorthWestGravity;
4700 window->orphan=MagickFalse;
4701}
4702
4703/*
4704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4705% %
4706% %
4707% %
4708% X H i g h l i g h t E l l i p s e %
4709% %
4710% %
4711% %
4712%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4713%
4714% XHighlightEllipse() puts a border on the X server around a region defined by
4715% highlight_info.
4716%
4717% The format of the XHighlightEllipse method is:
4718%
4719% void XHighlightEllipse(Display *display,Window window,
4720% GC annotate_context,const RectangleInfo *highlight_info)
4721%
4722% A description of each parameter follows:
4723%
4724% o display: Specifies a connection to an X server; returned from
4725% XOpenDisplay.
4726%
4727% o window: Specifies a pointer to a Window structure.
4728%
4729% o annotate_context: Specifies a pointer to a GC structure.
4730%
4731% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4732% contains the extents of any highlighting rectangle.
4733%
4734*/
cristybcbda3f2011-09-03 13:01:22 +00004735MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004736 GC annotate_context,const RectangleInfo *highlight_info)
4737{
4738 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4739 assert(display != (Display *) NULL);
4740 assert(window != (Window) NULL);
4741 assert(annotate_context != (GC) NULL);
4742 assert(highlight_info != (RectangleInfo *) NULL);
4743 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4744 return;
4745 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4746 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4747 (unsigned int) highlight_info->height-1,0,360*64);
4748 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4749 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4750 (unsigned int) highlight_info->height-3,0,360*64);
4751}
4752
4753/*
4754%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4755% %
4756% %
4757% %
4758% X H i g h l i g h t L i n e %
4759% %
4760% %
4761% %
4762%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4763%
4764% XHighlightLine() puts a border on the X server around a region defined by
4765% highlight_info.
4766%
4767% The format of the XHighlightLine method is:
4768%
4769% void XHighlightLine(Display *display,Window window,GC annotate_context,
4770% const XSegment *highlight_info)
4771%
4772% A description of each parameter follows:
4773%
4774% o display: Specifies a connection to an X server; returned from
4775% XOpenDisplay.
4776%
4777% o window: Specifies a pointer to a Window structure.
4778%
4779% o annotate_context: Specifies a pointer to a GC structure.
4780%
4781% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4782% contains the extents of any highlighting rectangle.
4783%
4784*/
cristybcbda3f2011-09-03 13:01:22 +00004785MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004786 GC annotate_context,const XSegment *highlight_info)
4787{
4788 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4789 assert(display != (Display *) NULL);
4790 assert(window != (Window) NULL);
4791 assert(annotate_context != (GC) NULL);
4792 assert(highlight_info != (XSegment *) NULL);
4793 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4794 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4795}
4796
4797/*
4798%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4799% %
4800% %
4801% %
4802% X H i g h l i g h t R e c t a n g l e %
4803% %
4804% %
4805% %
4806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4807%
4808% XHighlightRectangle() puts a border on the X server around a region defined
4809% by highlight_info.
4810%
4811% The format of the XHighlightRectangle method is:
4812%
4813% void XHighlightRectangle(Display *display,Window window,
4814% GC annotate_context,const RectangleInfo *highlight_info)
4815%
4816% A description of each parameter follows:
4817%
4818% o display: Specifies a connection to an X server; returned from
4819% XOpenDisplay.
4820%
4821% o window: Specifies a pointer to a Window structure.
4822%
4823% o annotate_context: Specifies a pointer to a GC structure.
4824%
4825% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4826% contains the extents of any highlighting rectangle.
4827%
4828*/
cristybcbda3f2011-09-03 13:01:22 +00004829MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004830 GC annotate_context,const RectangleInfo *highlight_info)
4831{
4832 assert(display != (Display *) NULL);
4833 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4834 assert(window != (Window) NULL);
4835 assert(annotate_context != (GC) NULL);
4836 assert(highlight_info != (RectangleInfo *) NULL);
4837 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4838 return;
4839 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4840 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4841 (unsigned int) highlight_info->height-1);
4842 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4843 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4844 (unsigned int) highlight_info->height-3);
4845}
4846
4847/*
4848%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4849% %
4850% %
4851% %
4852% X I m p o r t I m a g e %
4853% %
4854% %
4855% %
4856%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4857%
4858% XImportImage() reads an image from an X window.
4859%
4860% The format of the XImportImage method is:
4861%
cristy6710d842011-10-20 23:23:00 +00004862% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4863% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004864%
4865% A description of each parameter follows:
4866%
4867% o image_info: the image info.
4868%
4869% o ximage_info: Specifies a pointer to an XImportInfo structure.
4870%
cristy6710d842011-10-20 23:23:00 +00004871% o exception: return any errors or warnings in this structure.
4872%
cristy3ed852e2009-09-05 21:47:34 +00004873*/
4874MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004875 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004876{
4877 Colormap
4878 *colormaps;
4879
4880 Display
4881 *display;
4882
4883 Image
4884 *image;
4885
4886 int
4887 number_colormaps,
4888 number_windows,
4889 x;
4890
4891 RectangleInfo
4892 crop_info;
4893
4894 Status
4895 status;
4896
4897 Window
4898 *children,
4899 client,
4900 prior_target,
4901 root,
4902 target;
4903
4904 XTextProperty
4905 window_name;
4906
4907 /*
4908 Open X server connection.
4909 */
4910 assert(image_info != (const ImageInfo *) NULL);
4911 assert(image_info->signature == MagickSignature);
4912 if (image_info->debug != MagickFalse)
4913 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4914 image_info->filename);
4915 assert(ximage_info != (XImportInfo *) NULL);
4916 display=XOpenDisplay(image_info->server_name);
4917 if (display == (Display *) NULL)
4918 {
cristyc38fbf52013-11-03 13:55:54 +00004919 ThrowXWindowException(XServerError,"UnableToOpenXServer",
cristy3ed852e2009-09-05 21:47:34 +00004920 XDisplayName(image_info->server_name));
4921 return((Image *) NULL);
4922 }
4923 /*
4924 Set our forgiving exception handler.
4925 */
4926 (void) XSetErrorHandler(XError);
4927 /*
4928 Select target window.
4929 */
4930 crop_info.x=0;
4931 crop_info.y=0;
4932 crop_info.width=0;
4933 crop_info.height=0;
4934 root=XRootWindow(display,XDefaultScreen(display));
4935 target=(Window) NULL;
4936 if ((image_info->filename != (char *) NULL) &&
4937 (*image_info->filename != '\0'))
4938 {
4939 if (LocaleCompare(image_info->filename,"root") == 0)
4940 target=root;
4941 else
4942 {
4943 /*
4944 Select window by ID or name.
4945 */
cristy02e64f82013-11-14 16:20:04 +00004946 if (isdigit((int) ((unsigned char) *image_info->filename)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00004947 target=XWindowByID(display,root,(Window)
4948 strtol(image_info->filename,(char **) NULL,0));
4949 if (target == (Window) NULL)
4950 target=XWindowByName(display,root,image_info->filename);
4951 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004952 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
4953 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00004954 }
4955 }
4956 /*
4957 If target window is not defined, interactively select one.
4958 */
4959 prior_target=target;
4960 if (target == (Window) NULL)
4961 target=XSelectWindow(display,&crop_info);
4962 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004963 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00004964 image_info->filename);
4965 client=target; /* obsolete */
4966 if (target != root)
4967 {
4968 unsigned int
4969 d;
4970
4971 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4972 if (status != False)
4973 {
4974 for ( ; ; )
4975 {
4976 Window
4977 parent;
4978
4979 /*
4980 Find window manager frame.
4981 */
4982 status=XQueryTree(display,target,&root,&parent,&children,&d);
4983 if ((status != False) && (children != (Window *) NULL))
4984 (void) XFree((char *) children);
4985 if ((status == False) || (parent == (Window) NULL) ||
4986 (parent == root))
4987 break;
4988 target=parent;
4989 }
4990 /*
4991 Get client window.
4992 */
4993 client=XClientWindow(display,target);
4994 if (ximage_info->frame == MagickFalse)
4995 target=client;
4996 if ((ximage_info->frame == MagickFalse) &&
4997 (prior_target != MagickFalse))
4998 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00004999 }
5000 }
5001 if (ximage_info->screen)
5002 {
5003 int
5004 y;
5005
5006 Window
5007 child;
5008
5009 XWindowAttributes
5010 window_attributes;
5011
5012 /*
5013 Obtain window image directly from screen.
5014 */
5015 status=XGetWindowAttributes(display,target,&window_attributes);
5016 if (status == False)
5017 {
cristyc38fbf52013-11-03 13:55:54 +00005018 ThrowXWindowException(XServerError,"UnableToReadXWindowAttributes",
5019 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00005020 (void) XCloseDisplay(display);
5021 return((Image *) NULL);
5022 }
5023 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005024 crop_info.x=(ssize_t) x;
5025 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005026 crop_info.width=(size_t) window_attributes.width;
5027 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005028 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005029 {
5030 /*
5031 Include border in image.
5032 */
5033 crop_info.x-=window_attributes.border_width;
5034 crop_info.y-=window_attributes.border_width;
5035 crop_info.width+=window_attributes.border_width << 1;
5036 crop_info.height+=window_attributes.border_width << 1;
5037 }
5038 target=root;
5039 }
5040 /*
5041 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5042 */
5043 number_windows=0;
5044 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5045 if ((status == True) && (number_windows > 0))
5046 {
5047 ximage_info->descend=MagickTrue;
5048 (void) XFree ((char *) children);
5049 }
5050 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5051 if (number_colormaps > 0)
5052 {
5053 if (number_colormaps > 1)
5054 ximage_info->descend=MagickTrue;
5055 (void) XFree((char *) colormaps);
5056 }
5057 /*
5058 Alert the user not to alter the screen.
5059 */
5060 if (ximage_info->silent == MagickFalse)
5061 (void) XBell(display,0);
5062 /*
5063 Get image by window id.
5064 */
5065 (void) XGrabServer(display);
5066 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005067 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005068 (void) XUngrabServer(display);
5069 if (image == (Image *) NULL)
cristyc38fbf52013-11-03 13:55:54 +00005070 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00005071 image_info->filename)
5072 else
5073 {
5074 (void) CopyMagickString(image->filename,image_info->filename,
5075 MaxTextExtent);
5076 if ((crop_info.width != 0) && (crop_info.height != 0))
5077 {
5078 Image
5079 *clone_image,
5080 *crop_image;
5081
5082 /*
5083 Crop image as defined by the cropping rectangle.
5084 */
cristy6710d842011-10-20 23:23:00 +00005085 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005086 if (clone_image != (Image *) NULL)
5087 {
cristy6710d842011-10-20 23:23:00 +00005088 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005089 if (crop_image != (Image *) NULL)
5090 {
5091 image=DestroyImage(image);
5092 image=crop_image;
5093 }
5094 }
5095 }
5096 status=XGetWMName(display,target,&window_name);
5097 if (status == True)
5098 {
5099 if ((image_info->filename != (char *) NULL) &&
5100 (*image_info->filename == '\0'))
5101 (void) CopyMagickString(image->filename,(char *) window_name.value,
5102 (size_t) window_name.nitems+1);
5103 (void) XFree((void *) window_name.value);
5104 }
5105 }
5106 if (ximage_info->silent == MagickFalse)
5107 {
5108 /*
5109 Alert the user we're done.
5110 */
5111 (void) XBell(display,0);
5112 (void) XBell(display,0);
5113 }
5114 (void) XCloseDisplay(display);
5115 return(image);
5116}
5117
5118/*
5119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5120% %
5121% %
5122% %
5123% X I n i t i a l i z e W i n d o w s %
5124% %
5125% %
5126% %
5127%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5128%
5129% XInitializeWindows() initializes the XWindows structure.
5130%
5131% The format of the XInitializeWindows method is:
5132%
5133% XWindows *XInitializeWindows(Display *display,
5134% XResourceInfo *resource_info)
5135%
5136% A description of each parameter follows:
5137%
5138% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5139%
5140% o display: Specifies a connection to an X server; returned from
5141% XOpenDisplay.
5142%
5143% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5144%
5145*/
cristybcbda3f2011-09-03 13:01:22 +00005146MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005147 XResourceInfo *resource_info)
5148{
5149 Window
5150 root_window;
5151
5152 XWindows
5153 *windows;
5154
5155 /*
5156 Allocate windows structure.
5157 */
cristy73bd4a52010-10-05 11:24:23 +00005158 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005159 if (windows == (XWindows *) NULL)
5160 {
5161 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5162 "...");
5163 return((XWindows *) NULL);
5164 }
5165 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5166 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5167 sizeof(*windows->pixel_info));
5168 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5169 sizeof(*windows->icon_pixel));
5170 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5171 sizeof(*windows->icon_resources));
5172 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5173 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5174 (windows->icon_resources == (XResourceInfo *) NULL))
5175 {
5176 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5177 "...");
5178 return((XWindows *) NULL);
5179 }
5180 /*
5181 Initialize windows structure.
5182 */
5183 windows->display=display;
5184 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5185 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5186 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5187 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5188 windows->im_remote_command=
5189 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5190 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5191 windows->im_update_colormap=
5192 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5193 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5194 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5195 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5196 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5197 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005198#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005199 (void) XSynchronize(display,IsWindows95());
5200#endif
5201 if (IsEventLogging())
5202 {
5203 (void) XSynchronize(display,MagickTrue);
5204 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005205 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005206 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5207 (void) LogMagickEvent(X11Event,GetMagickModule(),
5208 " Window Manager: 0x%lx",windows->wm_protocols);
5209 (void) LogMagickEvent(X11Event,GetMagickModule(),
5210 " delete window: 0x%lx",windows->wm_delete_window);
5211 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5212 windows->wm_take_focus);
5213 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5214 windows->im_protocols);
5215 (void) LogMagickEvent(X11Event,GetMagickModule(),
5216 " remote command: 0x%lx",windows->im_remote_command);
5217 (void) LogMagickEvent(X11Event,GetMagickModule(),
5218 " update widget: 0x%lx",windows->im_update_widget);
5219 (void) LogMagickEvent(X11Event,GetMagickModule(),
5220 " update colormap: 0x%lx",windows->im_update_colormap);
5221 (void) LogMagickEvent(X11Event,GetMagickModule(),
5222 " former image: 0x%lx",windows->im_former_image);
5223 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5224 windows->im_next_image);
5225 (void) LogMagickEvent(X11Event,GetMagickModule(),
5226 " retain colors: 0x%lx",windows->im_retain_colors);
5227 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5228 windows->im_exit);
5229 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5230 windows->dnd_protocols);
5231 }
5232 /*
5233 Allocate standard colormap.
5234 */
5235 windows->map_info=XAllocStandardColormap();
5236 windows->icon_map=XAllocStandardColormap();
5237 if ((windows->map_info == (XStandardColormap *) NULL) ||
5238 (windows->icon_map == (XStandardColormap *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005239 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5240 "...");
cristy3ed852e2009-09-05 21:47:34 +00005241 windows->map_info->colormap=(Colormap) NULL;
5242 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005243 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005244 windows->pixel_info->annotate_context=(GC) NULL;
5245 windows->pixel_info->highlight_context=(GC) NULL;
5246 windows->pixel_info->widget_context=(GC) NULL;
5247 windows->font_info=(XFontStruct *) NULL;
5248 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005249 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005250 /*
5251 Allocate visual.
5252 */
5253 *windows->icon_resources=(*resource_info);
5254 windows->icon_resources->visual_type=(char *) "default";
5255 windows->icon_resources->colormap=SharedColormap;
5256 windows->visual_info=
5257 XBestVisualInfo(display,windows->map_info,resource_info);
5258 windows->icon_visual=
5259 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5260 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5261 (windows->icon_visual == (XVisualInfo *) NULL))
5262 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5263 resource_info->visual_type);
5264 if (IsEventLogging())
5265 {
5266 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5267 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5268 windows->visual_info->visualid);
5269 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5270 XVisualClassName(windows->visual_info->klass));
5271 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5272 windows->visual_info->depth);
5273 (void) LogMagickEvent(X11Event,GetMagickModule(),
5274 " size of colormap: %d entries",windows->visual_info->colormap_size);
5275 (void) LogMagickEvent(X11Event,GetMagickModule(),
5276 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5277 windows->visual_info->red_mask,windows->visual_info->green_mask,
5278 windows->visual_info->blue_mask);
5279 (void) LogMagickEvent(X11Event,GetMagickModule(),
5280 " significant bits in color: %d bits",
5281 windows->visual_info->bits_per_rgb);
5282 }
5283 /*
5284 Allocate class and manager hints.
5285 */
5286 windows->class_hints=XAllocClassHint();
5287 windows->manager_hints=XAllocWMHints();
5288 if ((windows->class_hints == (XClassHint *) NULL) ||
5289 (windows->manager_hints == (XWMHints *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005290 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5291 "...");
cristy3ed852e2009-09-05 21:47:34 +00005292 /*
5293 Determine group leader if we have one.
5294 */
5295 root_window=XRootWindow(display,windows->visual_info->screen);
5296 windows->group_leader.id=(Window) NULL;
5297 if (resource_info->window_group != (char *) NULL)
5298 {
cristy02e64f82013-11-14 16:20:04 +00005299 if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00005300 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5301 strtol((char *) resource_info->window_group,(char **) NULL,0));
5302 if (windows->group_leader.id == (Window) NULL)
5303 windows->group_leader.id=
5304 XWindowByName(display,root_window,resource_info->window_group);
5305 }
5306 return(windows);
5307}
5308
5309/*
5310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5311% %
5312% %
5313% %
5314% X M a k e C u r s o r %
5315% %
5316% %
5317% %
5318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5319%
5320% XMakeCursor() creates a crosshairs X11 cursor.
5321%
5322% The format of the XMakeCursor method is:
5323%
5324% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5325% char *background_color,char *foreground_color)
5326%
5327% A description of each parameter follows:
5328%
5329% o display: Specifies a connection to an X server; returned from
5330% XOpenDisplay.
5331%
5332% o window: Specifies the ID of the window for which the cursor is
5333% assigned.
5334%
5335% o colormap: Specifies the ID of the colormap from which the background
5336% and foreground color will be retrieved.
5337%
5338% o background_color: Specifies the color to use for the cursor background.
5339%
5340% o foreground_color: Specifies the color to use for the cursor foreground.
5341%
5342*/
cristybcbda3f2011-09-03 13:01:22 +00005343MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005344 Colormap colormap,char *background_color,char *foreground_color)
5345{
5346#define scope_height 17
5347#define scope_x_hot 8
5348#define scope_y_hot 8
5349#define scope_width 17
5350
5351 static const unsigned char
5352 scope_bits[] =
5353 {
5354 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5355 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5356 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5357 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5358 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5359 },
5360 scope_mask_bits[] =
5361 {
5362 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5363 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5364 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5365 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5366 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5367 };
5368
5369 Cursor
5370 cursor;
5371
5372 Pixmap
5373 mask,
5374 source;
5375
5376 XColor
5377 background,
5378 foreground;
5379
5380 assert(display != (Display *) NULL);
5381 assert(window != (Window) NULL);
5382 assert(colormap != (Colormap) NULL);
5383 assert(background_color != (char *) NULL);
5384 assert(foreground_color != (char *) NULL);
5385 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5386 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5387 scope_height);
5388 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5389 scope_width,scope_height);
5390 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5391 {
cristyc38fbf52013-11-03 13:55:54 +00005392 ThrowXWindowException(XServerError,"UnableToCreatePixmap","...");
cristy3ed852e2009-09-05 21:47:34 +00005393 return((Cursor) NULL);
5394 }
5395 (void) XParseColor(display,colormap,background_color,&background);
5396 (void) XParseColor(display,colormap,foreground_color,&foreground);
5397 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5398 scope_x_hot,scope_y_hot);
5399 (void) XFreePixmap(display,source);
5400 (void) XFreePixmap(display,mask);
5401 return(cursor);
5402}
5403
5404/*
5405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5406% %
5407% %
5408% %
5409% X M a k e I m a g e %
5410% %
5411% %
5412% %
5413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5414%
5415% XMakeImage() creates an X11 image. If the image size differs from the X11
5416% image size, the image is first resized.
5417%
5418% The format of the XMakeImage method is:
5419%
5420% MagickBooleanType XMakeImage(Display *display,
5421% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005422% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005423%
5424% A description of each parameter follows:
5425%
5426% o display: Specifies a connection to an X server; returned from
5427% XOpenDisplay.
5428%
5429% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5430%
5431% o window: Specifies a pointer to a XWindowInfo structure.
5432%
5433% o image: the image.
5434%
5435% o width: Specifies the width in pixels of the rectangular area to
5436% display.
5437%
5438% o height: Specifies the height in pixels of the rectangular area to
5439% display.
5440%
cristy051718b2011-08-28 22:49:25 +00005441% o exception: return any errors or warnings in this structure.
5442%
cristy3ed852e2009-09-05 21:47:34 +00005443*/
cristybcbda3f2011-09-03 13:01:22 +00005444MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005445 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005446 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005447{
5448#define CheckOverflowException(length,width,height) \
5449 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5450
5451 int
5452 depth,
5453 format;
5454
5455 size_t
5456 length;
5457
5458 XImage
5459 *matte_image,
5460 *ximage;
5461
5462 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5463 assert(display != (Display *) NULL);
5464 assert(resource_info != (XResourceInfo *) NULL);
5465 assert(window != (XWindowInfo *) NULL);
5466 assert(width != 0);
5467 assert(height != 0);
5468 if ((window->width == 0) || (window->height == 0))
5469 return(MagickFalse);
5470 /*
5471 Apply user transforms to the image.
5472 */
5473 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5474 (void) XFlush(display);
5475 depth=(int) window->depth;
5476 if (window->destroy)
5477 window->image=DestroyImage(window->image);
5478 window->image=image;
5479 window->destroy=MagickFalse;
5480 if (window->image != (Image *) NULL)
5481 {
5482 if (window->crop_geometry != (char *) NULL)
5483 {
5484 Image
5485 *crop_image;
5486
5487 RectangleInfo
5488 crop_info;
5489
5490 /*
5491 Crop image.
5492 */
5493 window->image->page.x=0;
5494 window->image->page.y=0;
5495 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005496 &crop_info,exception);
5497 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005498 if (crop_image != (Image *) NULL)
5499 {
5500 if (window->image != image)
5501 window->image=DestroyImage(window->image);
5502 window->image=crop_image;
5503 window->destroy=MagickTrue;
5504 }
5505 }
5506 if ((width != (unsigned int) window->image->columns) ||
5507 (height != (unsigned int) window->image->rows))
5508 {
5509 Image
5510 *resize_image;
5511
5512 /*
5513 Resize image.
5514 */
5515 resize_image=NewImageList();
cristy865489b2013-10-12 01:03:29 +00005516 if ((window->pixel_info->colors == 0) &&
5517 (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5518 (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5519 resize_image=ResizeImage(window->image,width,height,
5520 image->filter,exception);
cristy3ed852e2009-09-05 21:47:34 +00005521 else
cristy865489b2013-10-12 01:03:29 +00005522 {
5523 if (window->image->storage_class == PseudoClass)
5524 resize_image=SampleImage(window->image,width,height,
5525 exception);
5526 else
5527 resize_image=ThumbnailImage(window->image,width,height,
5528 exception);
5529 }
cristy3ed852e2009-09-05 21:47:34 +00005530 if (resize_image != (Image *) NULL)
5531 {
5532 if (window->image != image)
5533 window->image=DestroyImage(window->image);
5534 window->image=resize_image;
5535 window->destroy=MagickTrue;
5536 }
5537 }
5538 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005539 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005540 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005541 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005542 }
5543 /*
5544 Create X image.
5545 */
5546 ximage=(XImage *) NULL;
5547 format=(depth == 1) ? XYBitmap : ZPixmap;
5548#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5549 if (window->shared_memory != MagickFalse)
5550 {
5551 XShmSegmentInfo
5552 *segment_info;
5553
5554 segment_info=(XShmSegmentInfo *) window->segment_info;
5555 segment_info[1].shmid=(-1);
5556 segment_info[1].shmaddr=(char *) NULL;
5557 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5558 (char *) NULL,&segment_info[1],width,height);
5559 if (ximage == (XImage *) NULL)
5560 window->shared_memory=MagickFalse;
5561 length=(size_t) ximage->bytes_per_line*ximage->height;
5562 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5563 window->shared_memory=MagickFalse;
5564 if (window->shared_memory != MagickFalse)
5565 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5566 if (window->shared_memory != MagickFalse)
5567 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5568 if (segment_info[1].shmid < 0)
5569 window->shared_memory=MagickFalse;
5570 if (window->shared_memory != MagickFalse)
5571 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5572 else
5573 {
5574 if (ximage != (XImage *) NULL)
5575 XDestroyImage(ximage);
5576 ximage=(XImage *) NULL;
5577 if (segment_info[1].shmaddr)
5578 {
5579 (void) shmdt(segment_info[1].shmaddr);
5580 segment_info[1].shmaddr=(char *) NULL;
5581 }
5582 if (segment_info[1].shmid >= 0)
5583 {
5584 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5585 segment_info[1].shmid=(-1);
5586 }
5587 }
5588 }
5589#endif
5590 /*
5591 Allocate X image pixel data.
5592 */
5593#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5594 if (window->shared_memory)
5595 {
5596 Status
5597 status;
5598
5599 XShmSegmentInfo
5600 *segment_info;
5601
5602 (void) XSync(display,MagickFalse);
5603 xerror_alert=MagickFalse;
5604 segment_info=(XShmSegmentInfo *) window->segment_info;
5605 ximage->data=segment_info[1].shmaddr;
5606 segment_info[1].readOnly=MagickFalse;
5607 status=XShmAttach(display,&segment_info[1]);
5608 if (status != False)
5609 (void) XSync(display,MagickFalse);
5610 if ((status == False) || (xerror_alert != MagickFalse))
5611 {
5612 window->shared_memory=MagickFalse;
5613 if (status != False)
5614 XShmDetach(display,&segment_info[1]);
5615 if (ximage != (XImage *) NULL)
5616 {
5617 ximage->data=NULL;
5618 XDestroyImage(ximage);
5619 ximage=(XImage *) NULL;
5620 }
5621 if (segment_info[1].shmid >= 0)
5622 {
5623 if (segment_info[1].shmaddr != NULL)
5624 (void) shmdt(segment_info[1].shmaddr);
5625 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5626 segment_info[1].shmid=(-1);
5627 segment_info[1].shmaddr=(char *) NULL;
5628 }
5629 }
5630 }
5631#endif
5632 if (window->shared_memory == MagickFalse)
5633 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5634 (char *) NULL,width,height,XBitmapPad(display),0);
5635 if (ximage == (XImage *) NULL)
5636 {
5637 /*
5638 Unable to create X image.
5639 */
5640 (void) XCheckDefineCursor(display,window->id,window->cursor);
5641 return(MagickFalse);
5642 }
5643 length=(size_t) ximage->bytes_per_line*ximage->height;
5644 if (IsEventLogging())
5645 {
5646 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5647 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5648 ximage->width,ximage->height);
5649 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5650 ximage->format);
5651 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5652 ximage->byte_order);
5653 (void) LogMagickEvent(X11Event,GetMagickModule(),
5654 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5655 ximage->bitmap_bit_order,ximage->bitmap_pad);
5656 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5657 ximage->depth);
5658 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5659 ximage->bytes_per_line);
5660 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5661 ximage->bits_per_pixel);
5662 (void) LogMagickEvent(X11Event,GetMagickModule(),
5663 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5664 ximage->green_mask,ximage->blue_mask);
5665 }
5666 if (window->shared_memory == MagickFalse)
5667 {
5668 if (ximage->format != XYBitmap)
cristy9aecad62013-04-18 10:37:47 +00005669 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5670 ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005671 else
cristy9aecad62013-04-18 10:37:47 +00005672 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5673 ximage->depth*ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005674 }
5675 if (ximage->data == (char *) NULL)
5676 {
5677 /*
5678 Unable to allocate pixel data.
5679 */
5680 XDestroyImage(ximage);
5681 ximage=(XImage *) NULL;
5682 (void) XCheckDefineCursor(display,window->id,window->cursor);
5683 return(MagickFalse);
5684 }
5685 if (window->ximage != (XImage *) NULL)
5686 {
5687 /*
5688 Destroy previous X image.
5689 */
5690 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5691#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5692 if (window->segment_info != (XShmSegmentInfo *) NULL)
5693 {
5694 XShmSegmentInfo
5695 *segment_info;
5696
5697 segment_info=(XShmSegmentInfo *) window->segment_info;
5698 if (segment_info[0].shmid >= 0)
5699 {
5700 (void) XSync(display,MagickFalse);
5701 (void) XShmDetach(display,&segment_info[0]);
5702 (void) XSync(display,MagickFalse);
5703 if (segment_info[0].shmaddr != (char *) NULL)
5704 (void) shmdt(segment_info[0].shmaddr);
5705 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5706 segment_info[0].shmid=(-1);
5707 segment_info[0].shmaddr=(char *) NULL;
5708 window->ximage->data=(char *) NULL;
5709 }
5710 }
5711#endif
5712 if (window->ximage->data != (char *) NULL)
5713 free(window->ximage->data);
5714 window->ximage->data=(char *) NULL;
5715 XDestroyImage(window->ximage);
5716 window->ximage=(XImage *) NULL;
5717 }
5718#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5719 if (window->segment_info != (XShmSegmentInfo *) NULL)
5720 {
5721 XShmSegmentInfo
5722 *segment_info;
5723
5724 segment_info=(XShmSegmentInfo *) window->segment_info;
5725 segment_info[0]=segment_info[1];
5726 }
5727#endif
5728 window->ximage=ximage;
5729 matte_image=(XImage *) NULL;
5730 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
cristy8a46d822012-08-28 23:32:39 +00005731 if ((window->image->alpha_trait == BlendPixelTrait) &&
cristyc57f6942010-11-12 01:47:39 +00005732 ((int) width <= XDisplayWidth(display,window->screen)) &&
5733 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005734 {
5735 /*
5736 Create matte image.
5737 */
5738 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5739 (char *) NULL,width,height,XBitmapPad(display),0);
5740 if (IsEventLogging())
5741 {
5742 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5743 (void) LogMagickEvent(X11Event,GetMagickModule(),
5744 " width, height: %dx%d",matte_image->width,matte_image->height);
5745 }
5746 if (matte_image != (XImage *) NULL)
5747 {
5748 /*
5749 Allocate matte image pixel data.
5750 */
cristy9aecad62013-04-18 10:37:47 +00005751 matte_image->data=(char *) malloc((size_t)
5752 matte_image->bytes_per_line*matte_image->depth*
5753 matte_image->height);
cristy3ed852e2009-09-05 21:47:34 +00005754 if (matte_image->data == (char *) NULL)
5755 {
5756 XDestroyImage(matte_image);
5757 matte_image=(XImage *) NULL;
5758 }
5759 }
5760 }
5761 if (window->matte_image != (XImage *) NULL)
5762 {
5763 /*
5764 Free matte image.
5765 */
5766 if (window->matte_image->data != (char *) NULL)
5767 free(window->matte_image->data);
5768 window->matte_image->data=(char *) NULL;
5769 XDestroyImage(window->matte_image);
5770 window->matte_image=(XImage *) NULL;
5771 }
5772 window->matte_image=matte_image;
5773 if (window->matte_pixmap != (Pixmap) NULL)
5774 {
5775 (void) XFreePixmap(display,window->matte_pixmap);
5776 window->matte_pixmap=(Pixmap) NULL;
5777#if defined(MAGICKCORE_HAVE_SHAPE)
5778 if (window->shape != MagickFalse)
5779 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5780#endif
5781 }
5782 window->stasis=MagickFalse;
5783 /*
5784 Convert pixels to X image data.
5785 */
5786 if (window->image != (Image *) NULL)
5787 {
5788 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5789 (ximage->bitmap_bit_order == LSBFirst)))
5790 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005791 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005792 else
5793 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005794 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005795 }
5796 if (window->matte_image != (XImage *) NULL)
5797 {
5798 /*
5799 Create matte pixmap.
5800 */
5801 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5802 if (window->matte_pixmap != (Pixmap) NULL)
5803 {
5804 GC
5805 graphics_context;
5806
5807 XGCValues
5808 context_values;
5809
5810 /*
5811 Copy matte image to matte pixmap.
5812 */
cristy4c08aed2011-07-01 19:47:50 +00005813 context_values.background=0;
5814 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005815 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005816 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005817 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5818 window->matte_image,0,0,0,0,width,height);
5819 (void) XFreeGC(display,graphics_context);
5820#if defined(MAGICKCORE_HAVE_SHAPE)
5821 if (window->shape != MagickFalse)
5822 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5823 window->matte_pixmap,ShapeSet);
5824#endif
5825 }
5826 }
5827 (void) XMakePixmap(display,resource_info,window);
5828 /*
5829 Restore cursor.
5830 */
5831 (void) XCheckDefineCursor(display,window->id,window->cursor);
5832 return(MagickTrue);
5833}
5834
5835/*
5836%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5837% %
5838% %
5839% %
5840+ X M a k e I m a g e L S B F i r s t %
5841% %
5842% %
5843% %
5844%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5845%
5846% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5847% pixels are copied in least-significant bit and byte first order. The
5848% server's scanline pad is respected. Rather than using one or two general
5849% cases, many special cases are found here to help speed up the image
5850% conversion.
5851%
5852% The format of the XMakeImageLSBFirst method is:
5853%
cristye941a752011-10-15 01:52:48 +00005854% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5855% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005856%
5857% A description of each parameter follows:
5858%
5859% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5860%
5861% o window: Specifies a pointer to a XWindowInfo structure.
5862%
5863% o image: the image.
5864%
5865% o ximage: Specifies a pointer to a XImage structure; returned from
5866% XCreateImage.
5867%
5868% o matte_image: Specifies a pointer to a XImage structure; returned from
5869% XCreateImage.
5870%
cristye941a752011-10-15 01:52:48 +00005871% o exception: return any errors or warnings in this structure.
5872%
cristy3ed852e2009-09-05 21:47:34 +00005873*/
5874static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005875 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5876 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005877{
cristyc57f6942010-11-12 01:47:39 +00005878 CacheView
5879 *canvas_view;
5880
cristy3ed852e2009-09-05 21:47:34 +00005881 Image
5882 *canvas;
5883
5884 int
5885 y;
5886
cristy4c08aed2011-07-01 19:47:50 +00005887 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005888 *p;
5889
5890 register int
5891 x;
5892
5893 register unsigned char
5894 *q;
5895
5896 unsigned char
5897 bit,
5898 byte;
5899
5900 unsigned int
5901 scanline_pad;
5902
cristyf2faecf2010-05-28 19:19:36 +00005903 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005904 pixel,
5905 *pixels;
5906
5907 XStandardColormap
5908 *map_info;
5909
5910 assert(resource_info != (XResourceInfo *) NULL);
5911 assert(window != (XWindowInfo *) NULL);
5912 assert(image != (Image *) NULL);
5913 if (image->debug != MagickFalse)
5914 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5915 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005916 if ((window->immutable == MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00005917 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00005918 {
5919 char
5920 size[MaxTextExtent];
5921
5922 Image
5923 *pattern;
5924
5925 ImageInfo
5926 *image_info;
5927
5928 image_info=AcquireImageInfo();
5929 (void) CopyMagickString(image_info->filename,
5930 resource_info->image_info->texture != (char *) NULL ?
5931 resource_info->image_info->texture : "pattern:checkerboard",
5932 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005933 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005934 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005935 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005936 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005937 image_info=DestroyImageInfo(image_info);
5938 if (pattern != (Image *) NULL)
5939 {
cristy6710d842011-10-20 23:23:00 +00005940 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005941 if (canvas != (Image *) NULL)
cristy39172402012-03-30 13:04:39 +00005942 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00005943 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00005944 pattern=DestroyImage(pattern);
5945 }
5946 }
5947 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5948 ximage->bits_per_pixel) >> 3));
5949 map_info=window->map_info;
5950 pixels=window->pixel_info->pixels;
5951 q=(unsigned char *) ximage->data;
5952 x=0;
cristy46ff2672012-12-14 15:32:26 +00005953 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00005954 if (ximage->format == XYBitmap)
5955 {
5956 register unsigned short
5957 polarity;
5958
5959 unsigned char
5960 background,
5961 foreground;
5962
5963 /*
5964 Convert canvas to big-endian bitmap.
5965 */
5966 background=(unsigned char)
5967 (XPixelIntensity(&window->pixel_info->foreground_color) <
5968 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5969 foreground=(unsigned char)
5970 (XPixelIntensity(&window->pixel_info->background_color) <
5971 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005972 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00005973 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00005974 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005975 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5976 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005977 for (y=0; y < (int) canvas->rows; y++)
5978 {
cristyc57f6942010-11-12 01:47:39 +00005979 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005980 exception);
cristy4c08aed2011-07-01 19:47:50 +00005981 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005982 break;
cristy3ed852e2009-09-05 21:47:34 +00005983 bit=0;
5984 byte=0;
5985 for (x=0; x < (int) canvas->columns; x++)
5986 {
5987 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005988 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005989 byte|=foreground;
5990 else
5991 byte|=background;
5992 bit++;
5993 if (bit == 8)
5994 {
5995 *q++=byte;
5996 bit=0;
5997 byte=0;
5998 }
cristyed231572011-07-14 02:18:59 +00005999 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006000 }
6001 if (bit != 0)
6002 *q=byte >> (8-bit);
6003 q+=scanline_pad;
6004 }
6005 }
6006 else
6007 if (window->pixel_info->colors != 0)
6008 switch (ximage->bits_per_pixel)
6009 {
6010 case 2:
6011 {
6012 register unsigned int
6013 nibble;
6014
6015 /*
6016 Convert to 2 bit color-mapped X canvas.
6017 */
6018 for (y=0; y < (int) canvas->rows; y++)
6019 {
cristyc57f6942010-11-12 01:47:39 +00006020 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006021 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006022 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006023 break;
cristy3ed852e2009-09-05 21:47:34 +00006024 nibble=0;
6025 for (x=0; x < (int) canvas->columns; x++)
6026 {
cristy4c08aed2011-07-01 19:47:50 +00006027 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006028 switch (nibble)
6029 {
6030 case 0:
6031 {
6032 *q=(unsigned char) pixel;
6033 nibble++;
6034 break;
6035 }
6036 case 1:
6037 {
6038 *q|=(unsigned char) (pixel << 2);
6039 nibble++;
6040 break;
6041 }
6042 case 2:
6043 {
6044 *q|=(unsigned char) (pixel << 4);
6045 nibble++;
6046 break;
6047 }
6048 case 3:
6049 {
6050 *q|=(unsigned char) (pixel << 6);
6051 q++;
6052 nibble=0;
6053 break;
6054 }
6055 }
cristyed231572011-07-14 02:18:59 +00006056 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006057 }
6058 q+=scanline_pad;
6059 }
6060 break;
6061 }
6062 case 4:
6063 {
6064 register unsigned int
6065 nibble;
6066
6067 /*
6068 Convert to 4 bit color-mapped X canvas.
6069 */
6070 for (y=0; y < (int) canvas->rows; y++)
6071 {
cristyc57f6942010-11-12 01:47:39 +00006072 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006073 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006074 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006075 break;
cristy3ed852e2009-09-05 21:47:34 +00006076 nibble=0;
6077 for (x=0; x < (int) canvas->columns; x++)
6078 {
cristy4c08aed2011-07-01 19:47:50 +00006079 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006080 switch (nibble)
6081 {
6082 case 0:
6083 {
6084 *q=(unsigned char) pixel;
6085 nibble++;
6086 break;
6087 }
6088 case 1:
6089 {
6090 *q|=(unsigned char) (pixel << 4);
6091 q++;
6092 nibble=0;
6093 break;
6094 }
6095 }
cristyed231572011-07-14 02:18:59 +00006096 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006097 }
6098 q+=scanline_pad;
6099 }
6100 break;
6101 }
6102 case 6:
6103 case 8:
6104 {
6105 /*
6106 Convert to 8 bit color-mapped X canvas.
6107 */
6108 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006109 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006110 {
cristy6710d842011-10-20 23:23:00 +00006111 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006112 break;
6113 }
6114 for (y=0; y < (int) canvas->rows; y++)
6115 {
cristyc57f6942010-11-12 01:47:39 +00006116 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006117 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006118 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006119 break;
cristy3ed852e2009-09-05 21:47:34 +00006120 for (x=0; x < (int) canvas->columns; x++)
6121 {
cristy4c08aed2011-07-01 19:47:50 +00006122 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006123 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006124 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006125 }
6126 q+=scanline_pad;
6127 }
6128 break;
6129 }
6130 default:
6131 {
6132 register int
6133 k;
6134
6135 register unsigned int
6136 bytes_per_pixel;
6137
cristy3ed852e2009-09-05 21:47:34 +00006138 /*
6139 Convert to multi-byte color-mapped X canvas.
6140 */
6141 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6142 for (y=0; y < (int) canvas->rows; y++)
6143 {
cristyc57f6942010-11-12 01:47:39 +00006144 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006145 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006146 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006147 break;
cristy3ed852e2009-09-05 21:47:34 +00006148 for (x=0; x < (int) canvas->columns; x++)
6149 {
cristy4c08aed2011-07-01 19:47:50 +00006150 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006151 for (k=0; k < (int) bytes_per_pixel; k++)
6152 {
cristy42daae12013-04-07 22:36:07 +00006153 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006154 pixel>>=8;
6155 }
cristyed231572011-07-14 02:18:59 +00006156 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006157 }
6158 q+=scanline_pad;
6159 }
6160 break;
6161 }
6162 }
6163 else
6164 switch (ximage->bits_per_pixel)
6165 {
6166 case 2:
6167 {
6168 register unsigned int
6169 nibble;
6170
6171 /*
6172 Convert to contiguous 2 bit continuous-tone X canvas.
6173 */
6174 for (y=0; y < (int) canvas->rows; y++)
6175 {
6176 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006177 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006178 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006179 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006180 break;
6181 for (x=0; x < (int) canvas->columns; x++)
6182 {
cristy4c08aed2011-07-01 19:47:50 +00006183 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006184 pixel&=0xf;
6185 switch (nibble)
6186 {
6187 case 0:
6188 {
6189 *q=(unsigned char) pixel;
6190 nibble++;
6191 break;
6192 }
6193 case 1:
6194 {
6195 *q|=(unsigned char) (pixel << 2);
6196 nibble++;
6197 break;
6198 }
6199 case 2:
6200 {
6201 *q|=(unsigned char) (pixel << 4);
6202 nibble++;
6203 break;
6204 }
6205 case 3:
6206 {
6207 *q|=(unsigned char) (pixel << 6);
6208 q++;
6209 nibble=0;
6210 break;
6211 }
6212 }
cristyed231572011-07-14 02:18:59 +00006213 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006214 }
6215 q+=scanline_pad;
6216 }
6217 break;
6218 }
6219 case 4:
6220 {
6221 register unsigned int
6222 nibble;
6223
6224 /*
6225 Convert to contiguous 4 bit continuous-tone X canvas.
6226 */
6227 for (y=0; y < (int) canvas->rows; y++)
6228 {
cristyc57f6942010-11-12 01:47:39 +00006229 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006230 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006231 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006232 break;
6233 nibble=0;
6234 for (x=0; x < (int) canvas->columns; x++)
6235 {
cristy4c08aed2011-07-01 19:47:50 +00006236 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006237 pixel&=0xf;
6238 switch (nibble)
6239 {
6240 case 0:
6241 {
6242 *q=(unsigned char) pixel;
6243 nibble++;
6244 break;
6245 }
6246 case 1:
6247 {
6248 *q|=(unsigned char) (pixel << 4);
6249 q++;
6250 nibble=0;
6251 break;
6252 }
6253 }
cristyed231572011-07-14 02:18:59 +00006254 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006255 }
6256 q+=scanline_pad;
6257 }
6258 break;
6259 }
6260 case 6:
6261 case 8:
6262 {
6263 /*
6264 Convert to contiguous 8 bit continuous-tone X canvas.
6265 */
6266 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006267 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006268 {
cristy6710d842011-10-20 23:23:00 +00006269 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006270 break;
6271 }
6272 for (y=0; y < (int) canvas->rows; y++)
6273 {
cristyc57f6942010-11-12 01:47:39 +00006274 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006275 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006276 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006277 break;
6278 for (x=0; x < (int) canvas->columns; x++)
6279 {
cristy4c08aed2011-07-01 19:47:50 +00006280 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006281 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006282 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006283 }
6284 q+=scanline_pad;
6285 }
6286 break;
6287 }
6288 default:
6289 {
6290 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6291 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6292 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6293 (map_info->blue_mult == 1))
6294 {
6295 /*
6296 Convert to 32 bit continuous-tone X canvas.
6297 */
6298 for (y=0; y < (int) canvas->rows; y++)
6299 {
cristyc57f6942010-11-12 01:47:39 +00006300 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006301 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006302 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006303 break;
6304 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6305 (blue_gamma != 1.0))
6306 {
6307 /*
6308 Gamma correct canvas.
6309 */
6310 for (x=(int) canvas->columns-1; x >= 0; x--)
6311 {
cristyccf844f2010-02-03 23:28:16 +00006312 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006313 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006314 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006315 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006316 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006317 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006318 *q++=0;
cristyed231572011-07-14 02:18:59 +00006319 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006320 }
6321 continue;
6322 }
6323 for (x=(int) canvas->columns-1; x >= 0; x--)
6324 {
cristy8bc259b2012-06-21 23:53:15 +00006325 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6326 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6327 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006328 *q++=0;
cristyed231572011-07-14 02:18:59 +00006329 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006330 }
6331 }
6332 }
6333 else
6334 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6335 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6336 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6337 (map_info->blue_mult == 65536L))
6338 {
6339 /*
6340 Convert to 32 bit continuous-tone X canvas.
6341 */
6342 for (y=0; y < (int) canvas->rows; y++)
6343 {
cristyc57f6942010-11-12 01:47:39 +00006344 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006345 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006346 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006347 break;
6348 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6349 (blue_gamma != 1.0))
6350 {
6351 /*
6352 Gamma correct canvas.
6353 */
6354 for (x=(int) canvas->columns-1; x >= 0; x--)
6355 {
cristyccf844f2010-02-03 23:28:16 +00006356 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006357 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006358 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006359 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006360 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006361 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006362 *q++=0;
cristyed231572011-07-14 02:18:59 +00006363 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006364 }
6365 continue;
6366 }
6367 for (x=(int) canvas->columns-1; x >= 0; x--)
6368 {
cristy8bc259b2012-06-21 23:53:15 +00006369 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6370 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6371 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006372 *q++=0;
cristyed231572011-07-14 02:18:59 +00006373 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006374 }
6375 }
6376 }
6377 else
6378 {
6379 register int
6380 k;
6381
6382 register unsigned int
6383 bytes_per_pixel;
6384
cristy3ed852e2009-09-05 21:47:34 +00006385 /*
6386 Convert to multi-byte continuous-tone X canvas.
6387 */
6388 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6389 for (y=0; y < (int) canvas->rows; y++)
6390 {
cristyc57f6942010-11-12 01:47:39 +00006391 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006392 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006393 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006394 break;
cristyc57f6942010-11-12 01:47:39 +00006395 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006396 {
cristy4c08aed2011-07-01 19:47:50 +00006397 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006398 for (k=0; k < (int) bytes_per_pixel; k++)
6399 {
cristy42daae12013-04-07 22:36:07 +00006400 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006401 pixel>>=8;
6402 }
cristyed231572011-07-14 02:18:59 +00006403 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006404 }
6405 q+=scanline_pad;
6406 }
6407 }
6408 break;
6409 }
6410 }
6411 if (matte_image != (XImage *) NULL)
6412 {
6413 /*
6414 Initialize matte canvas.
6415 */
6416 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6417 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6418 q=(unsigned char *) matte_image->data;
6419 for (y=0; y < (int) canvas->rows; y++)
6420 {
cristyc57f6942010-11-12 01:47:39 +00006421 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006422 exception);
cristy4c08aed2011-07-01 19:47:50 +00006423 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006424 break;
6425 bit=0;
6426 byte=0;
6427 for (x=(int) canvas->columns-1; x >= 0; x--)
6428 {
6429 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006430 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006431 byte|=0x80;
6432 bit++;
6433 if (bit == 8)
6434 {
6435 *q++=byte;
6436 bit=0;
6437 byte=0;
6438 }
cristyed231572011-07-14 02:18:59 +00006439 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006440 }
6441 if (bit != 0)
6442 *q=byte >> (8-bit);
6443 q+=scanline_pad;
6444 }
6445 }
cristyc57f6942010-11-12 01:47:39 +00006446 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006447 if (canvas != image)
6448 canvas=DestroyImage(canvas);
6449}
6450
6451/*
6452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6453% %
6454% %
6455% %
6456+ X M a k e I m a g e M S B F i r s t %
6457% %
6458% %
6459% %
6460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6461%
6462% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6463% image pixels are copied in most-significant bit and byte first order. The
6464% server's scanline pad is also respected. Rather than using one or two
6465% general cases, many special cases are found here to help speed up the image
6466% conversion.
6467%
6468% The format of the XMakeImageMSBFirst method is:
6469%
cristye941a752011-10-15 01:52:48 +00006470% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6471% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006472%
6473% A description of each parameter follows:
6474%
6475% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6476%
6477% o window: Specifies a pointer to a XWindowInfo structure.
6478%
6479% o image: the image.
6480%
6481% o ximage: Specifies a pointer to a XImage structure; returned from
6482% XCreateImage.
6483%
6484% o matte_image: Specifies a pointer to a XImage structure; returned from
6485% XCreateImage.
6486%
cristye941a752011-10-15 01:52:48 +00006487% o exception: return any errors or warnings in this structure.
6488%
cristy3ed852e2009-09-05 21:47:34 +00006489*/
6490static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006491 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6492 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006493{
cristyc57f6942010-11-12 01:47:39 +00006494 CacheView
6495 *canvas_view;
6496
cristy3ed852e2009-09-05 21:47:34 +00006497 Image
6498 *canvas;
6499
6500 int
6501 y;
6502
6503 register int
6504 x;
6505
cristy4c08aed2011-07-01 19:47:50 +00006506 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006507 *p;
6508
6509 register unsigned char
6510 *q;
6511
6512 unsigned char
6513 bit,
6514 byte;
6515
6516 unsigned int
6517 scanline_pad;
6518
cristyf2faecf2010-05-28 19:19:36 +00006519 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006520 pixel,
6521 *pixels;
6522
6523 XStandardColormap
6524 *map_info;
6525
6526 assert(resource_info != (XResourceInfo *) NULL);
6527 assert(window != (XWindowInfo *) NULL);
6528 assert(image != (Image *) NULL);
6529 if (image->debug != MagickFalse)
6530 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6531 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006532 if ((window->immutable != MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00006533 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00006534 {
6535 char
6536 size[MaxTextExtent];
6537
6538 Image
6539 *pattern;
6540
6541 ImageInfo
6542 *image_info;
6543
6544 image_info=AcquireImageInfo();
6545 (void) CopyMagickString(image_info->filename,
6546 resource_info->image_info->texture != (char *) NULL ?
6547 resource_info->image_info->texture : "pattern:checkerboard",
6548 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006549 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006550 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006551 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006552 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006553 image_info=DestroyImageInfo(image_info);
6554 if (pattern != (Image *) NULL)
6555 {
cristy6710d842011-10-20 23:23:00 +00006556 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006557 if (canvas != (Image *) NULL)
cristyfeb3e962012-03-29 17:25:55 +00006558 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6559 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00006560 pattern=DestroyImage(pattern);
6561 }
6562 }
cristy4c08aed2011-07-01 19:47:50 +00006563 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6564 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006565 map_info=window->map_info;
6566 pixels=window->pixel_info->pixels;
6567 q=(unsigned char *) ximage->data;
6568 x=0;
cristy46ff2672012-12-14 15:32:26 +00006569 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00006570 if (ximage->format == XYBitmap)
6571 {
6572 register unsigned short
6573 polarity;
6574
6575 unsigned char
6576 background,
6577 foreground;
6578
6579 /*
6580 Convert canvas to big-endian bitmap.
6581 */
6582 background=(unsigned char)
6583 (XPixelIntensity(&window->pixel_info->foreground_color) <
6584 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6585 foreground=(unsigned char)
6586 (XPixelIntensity(&window->pixel_info->background_color) <
6587 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006588 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00006589 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00006590 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006591 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6592 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006593 for (y=0; y < (int) canvas->rows; y++)
6594 {
cristyc57f6942010-11-12 01:47:39 +00006595 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006596 exception);
cristy4c08aed2011-07-01 19:47:50 +00006597 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006598 break;
cristy3ed852e2009-09-05 21:47:34 +00006599 bit=0;
6600 byte=0;
6601 for (x=(int) canvas->columns-1; x >= 0; x--)
6602 {
6603 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006604 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006605 byte|=foreground;
6606 else
6607 byte|=background;
6608 bit++;
6609 if (bit == 8)
6610 {
6611 *q++=byte;
6612 bit=0;
6613 byte=0;
6614 }
cristyed231572011-07-14 02:18:59 +00006615 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006616 }
6617 if (bit != 0)
6618 *q=byte << (8-bit);
6619 q+=scanline_pad;
6620 }
6621 }
6622 else
6623 if (window->pixel_info->colors != 0)
6624 switch (ximage->bits_per_pixel)
6625 {
6626 case 2:
6627 {
6628 register unsigned int
6629 nibble;
6630
6631 /*
6632 Convert to 2 bit color-mapped X canvas.
6633 */
6634 for (y=0; y < (int) canvas->rows; y++)
6635 {
cristyc57f6942010-11-12 01:47:39 +00006636 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006637 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006638 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006639 break;
cristy3ed852e2009-09-05 21:47:34 +00006640 nibble=0;
6641 for (x=0; x < (int) canvas->columns; x++)
6642 {
cristy4c08aed2011-07-01 19:47:50 +00006643 pixel=pixels[(ssize_t)
6644 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006645 switch (nibble)
6646 {
6647 case 0:
6648 {
6649 *q=(unsigned char) (pixel << 6);
6650 nibble++;
6651 break;
6652 }
6653 case 1:
6654 {
6655 *q|=(unsigned char) (pixel << 4);
6656 nibble++;
6657 break;
6658 }
6659 case 2:
6660 {
6661 *q|=(unsigned char) (pixel << 2);
6662 nibble++;
6663 break;
6664 }
6665 case 3:
6666 {
6667 *q|=(unsigned char) pixel;
6668 q++;
6669 nibble=0;
6670 break;
6671 }
6672 }
cristyed231572011-07-14 02:18:59 +00006673 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006674 }
6675 q+=scanline_pad;
6676 }
6677 break;
6678 }
6679 case 4:
6680 {
6681 register unsigned int
6682 nibble;
6683
6684 /*
6685 Convert to 4 bit color-mapped X canvas.
6686 */
6687 for (y=0; y < (int) canvas->rows; y++)
6688 {
cristyc57f6942010-11-12 01:47:39 +00006689 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006690 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006691 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006692 break;
cristy3ed852e2009-09-05 21:47:34 +00006693 nibble=0;
6694 for (x=0; x < (int) canvas->columns; x++)
6695 {
cristy4c08aed2011-07-01 19:47:50 +00006696 pixel=pixels[(ssize_t)
6697 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006698 switch (nibble)
6699 {
6700 case 0:
6701 {
6702 *q=(unsigned char) (pixel << 4);
6703 nibble++;
6704 break;
6705 }
6706 case 1:
6707 {
6708 *q|=(unsigned char) pixel;
6709 q++;
6710 nibble=0;
6711 break;
6712 }
6713 }
cristyed231572011-07-14 02:18:59 +00006714 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006715 }
6716 q+=scanline_pad;
6717 }
6718 break;
6719 }
6720 case 6:
6721 case 8:
6722 {
6723 /*
6724 Convert to 8 bit color-mapped X canvas.
6725 */
6726 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006727 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006728 {
cristy6710d842011-10-20 23:23:00 +00006729 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006730 break;
6731 }
6732 for (y=0; y < (int) canvas->rows; y++)
6733 {
cristyc57f6942010-11-12 01:47:39 +00006734 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006735 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006736 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006737 break;
cristy3ed852e2009-09-05 21:47:34 +00006738 for (x=0; x < (int) canvas->columns; x++)
6739 {
cristy6710d842011-10-20 23:23:00 +00006740 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006741 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006742 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006743 }
6744 q+=scanline_pad;
6745 }
6746 break;
6747 }
6748 default:
6749 {
6750 register int
6751 k;
6752
6753 register unsigned int
6754 bytes_per_pixel;
6755
6756 unsigned char
cristybb503372010-05-27 20:51:26 +00006757 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006758
6759 /*
6760 Convert to 8 bit color-mapped X canvas.
6761 */
6762 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6763 for (y=0; y < (int) canvas->rows; y++)
6764 {
cristyc57f6942010-11-12 01:47:39 +00006765 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006766 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006767 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006768 break;
cristy3ed852e2009-09-05 21:47:34 +00006769 for (x=0; x < (int) canvas->columns; x++)
6770 {
cristy4c08aed2011-07-01 19:47:50 +00006771 pixel=pixels[(ssize_t)
6772 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006773 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6774 {
6775 channel[k]=(unsigned char) pixel;
6776 pixel>>=8;
6777 }
6778 for (k=0; k < (int) bytes_per_pixel; k++)
6779 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006780 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006781 }
6782 q+=scanline_pad;
6783 }
6784 break;
6785 }
6786 }
6787 else
6788 switch (ximage->bits_per_pixel)
6789 {
6790 case 2:
6791 {
6792 register unsigned int
6793 nibble;
6794
6795 /*
6796 Convert to 4 bit continuous-tone X canvas.
6797 */
6798 for (y=0; y < (int) canvas->rows; y++)
6799 {
cristyc57f6942010-11-12 01:47:39 +00006800 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006801 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006802 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006803 break;
6804 nibble=0;
6805 for (x=(int) canvas->columns-1; x >= 0; x--)
6806 {
cristy4c08aed2011-07-01 19:47:50 +00006807 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006808 pixel&=0xf;
6809 switch (nibble)
6810 {
6811 case 0:
6812 {
6813 *q=(unsigned char) (pixel << 6);
6814 nibble++;
6815 break;
6816 }
6817 case 1:
6818 {
6819 *q|=(unsigned char) (pixel << 4);
6820 nibble++;
6821 break;
6822 }
6823 case 2:
6824 {
6825 *q|=(unsigned char) (pixel << 2);
6826 nibble++;
6827 break;
6828 }
6829 case 3:
6830 {
6831 *q|=(unsigned char) pixel;
6832 q++;
6833 nibble=0;
6834 break;
6835 }
6836 }
cristyed231572011-07-14 02:18:59 +00006837 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006838 }
6839 q+=scanline_pad;
6840 }
6841 break;
6842 }
6843 case 4:
6844 {
6845 register unsigned int
6846 nibble;
6847
6848 /*
6849 Convert to 4 bit continuous-tone X canvas.
6850 */
6851 for (y=0; y < (int) canvas->rows; y++)
6852 {
cristyc57f6942010-11-12 01:47:39 +00006853 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006854 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006855 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006856 break;
6857 nibble=0;
6858 for (x=(int) canvas->columns-1; x >= 0; x--)
6859 {
cristy4c08aed2011-07-01 19:47:50 +00006860 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006861 pixel&=0xf;
6862 switch (nibble)
6863 {
6864 case 0:
6865 {
6866 *q=(unsigned char) (pixel << 4);
6867 nibble++;
6868 break;
6869 }
6870 case 1:
6871 {
6872 *q|=(unsigned char) pixel;
6873 q++;
6874 nibble=0;
6875 break;
6876 }
6877 }
cristyed231572011-07-14 02:18:59 +00006878 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006879 }
6880 q+=scanline_pad;
6881 }
6882 break;
6883 }
6884 case 6:
6885 case 8:
6886 {
6887 /*
6888 Convert to 8 bit continuous-tone X canvas.
6889 */
6890 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006891 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006892 {
cristy6710d842011-10-20 23:23:00 +00006893 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006894 break;
6895 }
6896 for (y=0; y < (int) canvas->rows; y++)
6897 {
cristyc57f6942010-11-12 01:47:39 +00006898 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006899 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006900 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006901 break;
6902 for (x=(int) canvas->columns-1; x >= 0; x--)
6903 {
cristy4c08aed2011-07-01 19:47:50 +00006904 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006905 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006906 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006907 }
6908 q+=scanline_pad;
6909 }
6910 break;
6911 }
6912 default:
6913 {
6914 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6915 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6916 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6917 (map_info->blue_mult == 1))
6918 {
6919 /*
6920 Convert to 32 bit continuous-tone X canvas.
6921 */
6922 for (y=0; y < (int) canvas->rows; y++)
6923 {
cristyc57f6942010-11-12 01:47:39 +00006924 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006925 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006926 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006927 break;
6928 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6929 (blue_gamma != 1.0))
6930 {
6931 /*
6932 Gamma correct canvas.
6933 */
6934 for (x=(int) canvas->columns-1; x >= 0; x--)
6935 {
6936 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006937 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006938 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006939 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006940 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006941 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006942 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006943 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006944 }
6945 continue;
6946 }
6947 for (x=(int) canvas->columns-1; x >= 0; x--)
6948 {
6949 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006950 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6951 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6952 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006953 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006954 }
6955 }
6956 }
6957 else
6958 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6959 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6960 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6961 (map_info->blue_mult == 65536L))
6962 {
6963 /*
6964 Convert to 32 bit continuous-tone X canvas.
6965 */
6966 for (y=0; y < (int) canvas->rows; y++)
6967 {
cristyc57f6942010-11-12 01:47:39 +00006968 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006969 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006970 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006971 break;
6972 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6973 (blue_gamma != 1.0))
6974 {
6975 /*
6976 Gamma correct canvas.
6977 */
6978 for (x=(int) canvas->columns-1; x >= 0; x--)
6979 {
6980 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006981 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006982 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006983 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006984 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006985 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006986 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006987 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006988 }
6989 continue;
6990 }
6991 for (x=(int) canvas->columns-1; x >= 0; x--)
6992 {
6993 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006994 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6995 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6996 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006997 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006998 }
6999 }
7000 }
7001 else
7002 {
7003 register int
7004 k;
7005
7006 register unsigned int
7007 bytes_per_pixel;
7008
7009 unsigned char
cristybb503372010-05-27 20:51:26 +00007010 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007011
7012 /*
7013 Convert to multi-byte continuous-tone X canvas.
7014 */
7015 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7016 for (y=0; y < (int) canvas->rows; y++)
7017 {
cristyc57f6942010-11-12 01:47:39 +00007018 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007019 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007020 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007021 break;
7022 for (x=(int) canvas->columns-1; x >= 0; x--)
7023 {
cristy4c08aed2011-07-01 19:47:50 +00007024 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007025 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7026 {
7027 channel[k]=(unsigned char) pixel;
7028 pixel>>=8;
7029 }
7030 for (k=0; k < (int) bytes_per_pixel; k++)
7031 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007032 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007033 }
7034 q+=scanline_pad;
7035 }
7036 }
7037 break;
7038 }
7039 }
7040 if (matte_image != (XImage *) NULL)
7041 {
7042 /*
7043 Initialize matte canvas.
7044 */
7045 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7046 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7047 q=(unsigned char *) matte_image->data;
7048 for (y=0; y < (int) canvas->rows; y++)
7049 {
cristyc57f6942010-11-12 01:47:39 +00007050 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007051 exception);
cristy4c08aed2011-07-01 19:47:50 +00007052 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007053 break;
7054 bit=0;
7055 byte=0;
7056 for (x=(int) canvas->columns-1; x >= 0; x--)
7057 {
7058 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007059 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007060 byte|=0x01;
7061 bit++;
7062 if (bit == 8)
7063 {
7064 *q++=byte;
7065 bit=0;
7066 byte=0;
7067 }
cristyed231572011-07-14 02:18:59 +00007068 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007069 }
7070 if (bit != 0)
7071 *q=byte << (8-bit);
7072 q+=scanline_pad;
7073 }
7074 }
cristyc57f6942010-11-12 01:47:39 +00007075 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007076 if (canvas != image)
7077 canvas=DestroyImage(canvas);
7078}
7079
7080/*
7081%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7082% %
7083% %
7084% %
7085% X M a k e M a g n i f y I m a g e %
7086% %
7087% %
7088% %
7089%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7090%
7091% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7092%
7093% The format of the XMakeMagnifyImage method is:
7094%
cristy6710d842011-10-20 23:23:00 +00007095% void XMakeMagnifyImage(Display *display,XWindows *windows,
7096% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007097%
7098% A description of each parameter follows:
7099%
7100% o display: Specifies a connection to an X server; returned from
7101% XOpenDisplay.
7102%
7103% o windows: Specifies a pointer to a XWindows structure.
7104%
cristy6710d842011-10-20 23:23:00 +00007105% o exception: return any errors or warnings in this structure.
7106%
cristy3ed852e2009-09-05 21:47:34 +00007107*/
cristy6710d842011-10-20 23:23:00 +00007108MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7109 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007110{
7111 char
7112 tuple[MaxTextExtent];
7113
7114 int
7115 y;
7116
cristy4c08aed2011-07-01 19:47:50 +00007117 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007118 pixel;
7119
7120 register int
7121 x;
7122
cristybb503372010-05-27 20:51:26 +00007123 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007124 i;
7125
7126 register unsigned char
7127 *p,
7128 *q;
7129
cristy9d314ff2011-03-09 01:30:28 +00007130 ssize_t
7131 n;
7132
cristy3ed852e2009-09-05 21:47:34 +00007133 static unsigned int
7134 previous_magnify = 0;
7135
7136 static XWindowInfo
7137 magnify_window;
7138
7139 unsigned int
7140 height,
7141 j,
7142 k,
7143 l,
7144 magnify,
7145 scanline_pad,
7146 width;
7147
7148 XImage
7149 *ximage;
7150
7151 /*
7152 Check boundary conditions.
7153 */
7154 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7155 assert(display != (Display *) NULL);
7156 assert(windows != (XWindows *) NULL);
7157 magnify=1;
cristybb503372010-05-27 20:51:26 +00007158 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007159 magnify<<=1;
7160 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7161 magnify<<=1;
7162 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7163 magnify<<=1;
7164 while (magnify > windows->magnify.width)
7165 magnify>>=1;
7166 while (magnify > windows->magnify.height)
7167 magnify>>=1;
7168 if (magnify != previous_magnify)
7169 {
7170 Status
7171 status;
7172
7173 XTextProperty
7174 window_name;
7175
7176 /*
7177 New magnify factor: update magnify window name.
7178 */
7179 i=0;
7180 while ((1 << i) <= (int) magnify)
7181 i++;
cristyb51dff52011-05-19 16:55:47 +00007182 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007183 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007184 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7185 if (status != False)
7186 {
7187 XSetWMName(display,windows->magnify.id,&window_name);
7188 XSetWMIconName(display,windows->magnify.id,&window_name);
7189 (void) XFree((void *) window_name.value);
7190 }
7191 }
7192 previous_magnify=magnify;
7193 ximage=windows->image.ximage;
7194 width=(unsigned int) windows->magnify.ximage->width;
7195 height=(unsigned int) windows->magnify.ximage->height;
7196 if ((windows->magnify.x < 0) ||
7197 (windows->magnify.x >= windows->image.ximage->width))
7198 windows->magnify.x=windows->image.ximage->width >> 1;
7199 x=windows->magnify.x-((width/magnify) >> 1);
7200 if (x < 0)
7201 x=0;
7202 else
7203 if (x > (int) (ximage->width-(width/magnify)))
7204 x=ximage->width-width/magnify;
7205 if ((windows->magnify.y < 0) ||
7206 (windows->magnify.y >= windows->image.ximage->height))
7207 windows->magnify.y=windows->image.ximage->height >> 1;
7208 y=windows->magnify.y-((height/magnify) >> 1);
7209 if (y < 0)
7210 y=0;
7211 else
7212 if (y > (int) (ximage->height-(height/magnify)))
7213 y=ximage->height-height/magnify;
7214 q=(unsigned char *) windows->magnify.ximage->data;
7215 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7216 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7217 if (ximage->bits_per_pixel < 8)
7218 {
7219 register unsigned char
7220 background,
7221 byte,
7222 foreground,
7223 p_bit,
7224 q_bit;
7225
7226 register unsigned int
7227 plane;
7228
7229 XPixelInfo
7230 *pixel_info;
7231
7232 pixel_info=windows->magnify.pixel_info;
7233 switch (ximage->bitmap_bit_order)
7234 {
7235 case LSBFirst:
7236 {
7237 /*
7238 Magnify little-endian bitmap.
7239 */
7240 background=0x00;
7241 foreground=0x80;
7242 if (ximage->format == XYBitmap)
7243 {
7244 background=(unsigned char)
7245 (XPixelIntensity(&pixel_info->foreground_color) <
7246 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7247 foreground=(unsigned char)
7248 (XPixelIntensity(&pixel_info->background_color) <
7249 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7250 if (windows->magnify.depth > 1)
7251 Swap(background,foreground);
7252 }
cristybb503372010-05-27 20:51:26 +00007253 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007254 {
7255 /*
7256 Propogate pixel magnify rows.
7257 */
7258 for (j=0; j < magnify; j++)
7259 {
7260 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7261 ((x*ximage->bits_per_pixel) >> 3);
7262 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7263 q_bit=0;
7264 byte=0;
7265 for (k=0; k < width; k+=magnify)
7266 {
7267 /*
7268 Propogate pixel magnify columns.
7269 */
7270 for (l=0; l < magnify; l++)
7271 {
7272 /*
7273 Propogate each bit plane.
7274 */
7275 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7276 {
7277 byte>>=1;
7278 if (*p & (0x01 << (p_bit+plane)))
7279 byte|=foreground;
7280 else
7281 byte|=background;
7282 q_bit++;
7283 if (q_bit == 8)
7284 {
7285 *q++=byte;
7286 q_bit=0;
7287 byte=0;
7288 }
7289 }
7290 }
7291 p_bit+=ximage->bits_per_pixel;
7292 if (p_bit == 8)
7293 {
7294 p++;
7295 p_bit=0;
7296 }
7297 if (q_bit != 0)
7298 *q=byte >> (8-q_bit);
7299 q+=scanline_pad;
7300 }
7301 }
7302 y++;
7303 }
7304 break;
7305 }
7306 case MSBFirst:
7307 default:
7308 {
7309 /*
7310 Magnify big-endian bitmap.
7311 */
7312 background=0x00;
7313 foreground=0x01;
7314 if (ximage->format == XYBitmap)
7315 {
7316 background=(unsigned char)
7317 (XPixelIntensity(&pixel_info->foreground_color) <
7318 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7319 foreground=(unsigned char)
7320 (XPixelIntensity(&pixel_info->background_color) <
7321 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7322 if (windows->magnify.depth > 1)
7323 Swap(background,foreground);
7324 }
cristybb503372010-05-27 20:51:26 +00007325 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007326 {
7327 /*
7328 Propogate pixel magnify rows.
7329 */
7330 for (j=0; j < magnify; j++)
7331 {
7332 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7333 ((x*ximage->bits_per_pixel) >> 3);
7334 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7335 q_bit=0;
7336 byte=0;
7337 for (k=0; k < width; k+=magnify)
7338 {
7339 /*
7340 Propogate pixel magnify columns.
7341 */
7342 for (l=0; l < magnify; l++)
7343 {
7344 /*
7345 Propogate each bit plane.
7346 */
7347 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7348 {
7349 byte<<=1;
7350 if (*p & (0x80 >> (p_bit+plane)))
7351 byte|=foreground;
7352 else
7353 byte|=background;
7354 q_bit++;
7355 if (q_bit == 8)
7356 {
7357 *q++=byte;
7358 q_bit=0;
7359 byte=0;
7360 }
7361 }
7362 }
7363 p_bit+=ximage->bits_per_pixel;
7364 if (p_bit == 8)
7365 {
7366 p++;
7367 p_bit=0;
7368 }
7369 if (q_bit != 0)
7370 *q=byte << (8-q_bit);
7371 q+=scanline_pad;
7372 }
7373 }
7374 y++;
7375 }
7376 break;
7377 }
7378 }
7379 }
7380 else
7381 switch (ximage->bits_per_pixel)
7382 {
7383 case 6:
7384 case 8:
7385 {
7386 /*
7387 Magnify 8 bit X image.
7388 */
cristybb503372010-05-27 20:51:26 +00007389 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007390 {
7391 /*
7392 Propogate pixel magnify rows.
7393 */
7394 for (j=0; j < magnify; j++)
7395 {
7396 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7397 ((x*ximage->bits_per_pixel) >> 3);
7398 for (k=0; k < width; k+=magnify)
7399 {
7400 /*
7401 Propogate pixel magnify columns.
7402 */
7403 for (l=0; l < magnify; l++)
7404 *q++=(*p);
7405 p++;
7406 }
7407 q+=scanline_pad;
7408 }
7409 y++;
7410 }
7411 break;
7412 }
7413 default:
7414 {
7415 register unsigned int
7416 bytes_per_pixel,
7417 m;
7418
7419 /*
7420 Magnify multi-byte X image.
7421 */
7422 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007423 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007424 {
7425 /*
7426 Propogate pixel magnify rows.
7427 */
7428 for (j=0; j < magnify; j++)
7429 {
7430 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7431 ((x*ximage->bits_per_pixel) >> 3);
7432 for (k=0; k < width; k+=magnify)
7433 {
7434 /*
7435 Propogate pixel magnify columns.
7436 */
7437 for (l=0; l < magnify; l++)
7438 for (m=0; m < bytes_per_pixel; m++)
7439 *q++=(*(p+m));
7440 p+=bytes_per_pixel;
7441 }
7442 q+=scanline_pad;
7443 }
7444 y++;
7445 }
7446 break;
7447 }
7448 }
7449 /*
7450 Copy X image to magnify pixmap.
7451 */
7452 x=windows->magnify.x-((width/magnify) >> 1);
7453 if (x < 0)
7454 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7455 else
7456 if (x > (int) (ximage->width-(width/magnify)))
7457 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7458 else
7459 x=0;
7460 y=windows->magnify.y-((height/magnify) >> 1);
7461 if (y < 0)
7462 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7463 else
7464 if (y > (int) (ximage->height-(height/magnify)))
7465 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7466 else
7467 y=0;
7468 if ((x != 0) || (y != 0))
7469 (void) XFillRectangle(display,windows->magnify.pixmap,
7470 windows->magnify.annotate_context,0,0,width,height);
7471 (void) XPutImage(display,windows->magnify.pixmap,
7472 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7473 height-y);
7474 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7475 (magnify <= (height >> 1))))
7476 {
7477 RectangleInfo
7478 highlight_info;
7479
7480 /*
7481 Highlight center pixel.
7482 */
cristybb503372010-05-27 20:51:26 +00007483 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7484 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007485 highlight_info.width=magnify;
7486 highlight_info.height=magnify;
7487 (void) XDrawRectangle(display,windows->magnify.pixmap,
7488 windows->magnify.highlight_context,(int) highlight_info.x,
7489 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7490 (unsigned int) highlight_info.height-1);
7491 if (magnify > 2)
7492 (void) XDrawRectangle(display,windows->magnify.pixmap,
7493 windows->magnify.annotate_context,(int) highlight_info.x+1,
7494 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7495 (unsigned int) highlight_info.height-3);
7496 }
7497 /*
7498 Show center pixel color.
7499 */
cristy3aa93752011-12-18 15:54:24 +00007500 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007501 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007502 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007503 windows->magnify.x,windows->magnify.y);
7504 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007505 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007506 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007507 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007508 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007509 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007510 if (pixel.colorspace == CMYKColorspace)
7511 {
7512 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007513 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007514 }
cristy8a46d822012-08-28 23:32:39 +00007515 if (pixel.alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00007516 {
7517 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007518 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007519 }
7520 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7521 height=(unsigned int) windows->magnify.font_info->ascent+
7522 windows->magnify.font_info->descent;
7523 x=windows->magnify.font_info->max_bounds.width >> 1;
7524 y=windows->magnify.font_info->ascent+(height >> 2);
7525 (void) XDrawImageString(display,windows->magnify.pixmap,
7526 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7527 GetColorTuple(&pixel,MagickTrue,tuple);
7528 y+=height;
7529 (void) XDrawImageString(display,windows->magnify.pixmap,
7530 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007531 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007532 exception);
cristy3ed852e2009-09-05 21:47:34 +00007533 y+=height;
7534 (void) XDrawImageString(display,windows->magnify.pixmap,
7535 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7536 /*
7537 Refresh magnify window.
7538 */
7539 magnify_window=windows->magnify;
7540 magnify_window.x=0;
7541 magnify_window.y=0;
7542 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7543}
7544
7545/*
7546%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7547% %
7548% %
7549% %
7550% X M a k e P i x m a p %
7551% %
7552% %
7553% %
7554%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7555%
7556% XMakePixmap() creates an X11 pixmap.
7557%
7558% The format of the XMakePixmap method is:
7559%
7560% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7561% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7562% XPixelInfo *pixel)
7563%
7564% A description of each parameter follows:
7565%
7566% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7567%
7568% o display: Specifies a connection to an X server; returned from
7569% XOpenDisplay.
7570%
7571% o window: Specifies a pointer to a XWindowInfo structure.
7572%
cristy3ed852e2009-09-05 21:47:34 +00007573*/
7574static MagickBooleanType XMakePixmap(Display *display,
7575 const XResourceInfo *resource_info,XWindowInfo *window)
7576{
7577 unsigned int
7578 height,
7579 width;
7580
7581 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7582 assert(display != (Display *) NULL);
7583 assert(resource_info != (XResourceInfo *) NULL);
7584 assert(window != (XWindowInfo *) NULL);
7585 if (window->pixmap != (Pixmap) NULL)
7586 {
7587 /*
7588 Destroy previous X pixmap.
7589 */
7590 (void) XFreePixmap(display,window->pixmap);
7591 window->pixmap=(Pixmap) NULL;
7592 }
7593 if (window->use_pixmap == MagickFalse)
7594 return(MagickFalse);
7595 if (window->ximage == (XImage *) NULL)
7596 return(MagickFalse);
7597 /*
7598 Display busy cursor.
7599 */
7600 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7601 (void) XFlush(display);
7602 /*
7603 Create pixmap.
7604 */
7605 width=(unsigned int) window->ximage->width;
7606 height=(unsigned int) window->ximage->height;
7607 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7608 if (window->pixmap == (Pixmap) NULL)
7609 {
7610 /*
7611 Unable to allocate pixmap.
7612 */
7613 (void) XCheckDefineCursor(display,window->id,window->cursor);
7614 return(MagickFalse);
7615 }
7616 /*
7617 Copy X image to pixmap.
7618 */
7619#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7620 if (window->shared_memory)
7621 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7622 window->ximage,0,0,0,0,width,height,MagickTrue);
7623#endif
7624 if (window->shared_memory == MagickFalse)
7625 (void) XPutImage(display,window->pixmap,window->annotate_context,
7626 window->ximage,0,0,0,0,width,height);
7627 if (IsEventLogging())
7628 {
7629 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7630 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7631 width,height);
7632 }
7633 /*
7634 Restore cursor.
7635 */
7636 (void) XCheckDefineCursor(display,window->id,window->cursor);
7637 return(MagickTrue);
7638}
7639
7640/*
7641%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7642% %
7643% %
7644% %
7645% X M a k e S t a n d a r d C o l o r m a p %
7646% %
7647% %
7648% %
7649%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7650%
7651% XMakeStandardColormap() creates an X11 Standard Colormap.
7652%
7653% The format of the XMakeStandardColormap method is:
7654%
cristy6710d842011-10-20 23:23:00 +00007655% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7656% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7657% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007658%
7659% A description of each parameter follows:
7660%
7661% o display: Specifies a connection to an X server; returned from
7662% XOpenDisplay.
7663%
7664% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7665% returned from XGetVisualInfo.
7666%
7667% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7668%
7669% o image: the image.
7670%
7671% o map_info: If a Standard Colormap type is specified, this structure is
7672% initialized with info from the Standard Colormap.
7673%
7674% o pixel: Specifies a pointer to a XPixelInfo structure.
7675%
cristy6710d842011-10-20 23:23:00 +00007676% o exception: return any errors or warnings in this structure.
7677%
cristy3ed852e2009-09-05 21:47:34 +00007678*/
7679
7680#if defined(__cplusplus) || defined(c_plusplus)
7681extern "C" {
7682#endif
7683
cristya19f1d72012-08-07 18:24:38 +00007684static inline double DiversityPixelIntensity(
cristy3ed852e2009-09-05 21:47:34 +00007685 const DiversityPacket *pixel)
7686{
cristya19f1d72012-08-07 18:24:38 +00007687 double
cristy3ed852e2009-09-05 21:47:34 +00007688 intensity;
7689
cristyd3d2a272013-06-24 16:09:41 +00007690 intensity=0.212656*pixel->red+0.715158*pixel->green+0.072186*pixel->blue;
cristy3ed852e2009-09-05 21:47:34 +00007691 return(intensity);
7692}
7693
7694static int IntensityCompare(const void *x,const void *y)
7695{
7696 DiversityPacket
7697 *color_1,
7698 *color_2;
7699
7700 int
7701 diversity;
7702
7703 color_1=(DiversityPacket *) x;
7704 color_2=(DiversityPacket *) y;
7705 diversity=(int) (DiversityPixelIntensity(color_2)-
7706 DiversityPixelIntensity(color_1));
7707 return(diversity);
7708}
7709
7710static int PopularityCompare(const void *x,const void *y)
7711{
7712 DiversityPacket
7713 *color_1,
7714 *color_2;
7715
7716 color_1=(DiversityPacket *) x;
7717 color_2=(DiversityPacket *) y;
7718 return((int) color_2->count-(int) color_1->count);
7719}
7720
7721#if defined(__cplusplus) || defined(c_plusplus)
7722}
7723#endif
7724
cristybb503372010-05-27 20:51:26 +00007725static inline Quantum ScaleXToQuantum(const size_t x,
7726 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007727{
cristya19f1d72012-08-07 18:24:38 +00007728 return((Quantum) (((double) QuantumRange*x)/scale+0.5));
cristy3ed852e2009-09-05 21:47:34 +00007729}
7730
cristybcbda3f2011-09-03 13:01:22 +00007731MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007732 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007733 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007734{
7735 Colormap
7736 colormap;
7737
cristybb503372010-05-27 20:51:26 +00007738 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007739 i;
7740
7741 Status
7742 status;
7743
cristybb503372010-05-27 20:51:26 +00007744 size_t
cristy3ed852e2009-09-05 21:47:34 +00007745 number_colors,
7746 retain_colors;
7747
7748 unsigned short
7749 gray_value;
7750
7751 XColor
7752 color,
7753 *colors,
7754 *p;
7755
7756 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7757 assert(display != (Display *) NULL);
7758 assert(visual_info != (XVisualInfo *) NULL);
7759 assert(map_info != (XStandardColormap *) NULL);
7760 assert(resource_info != (XResourceInfo *) NULL);
7761 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007762 if (resource_info->map_type != (char *) NULL)
7763 {
7764 /*
7765 Standard Colormap is already defined (i.e. xstdcmap).
7766 */
cristy4c08aed2011-07-01 19:47:50 +00007767 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007768 pixel);
7769 number_colors=(unsigned int) (map_info->base_pixel+
7770 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7771 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
cristy8a46d822012-08-28 23:32:39 +00007772 if ((image->alpha_trait != BlendPixelTrait) &&
cristy3ed852e2009-09-05 21:47:34 +00007773 (resource_info->color_recovery == MagickFalse) &&
cristycbda6112012-05-27 20:57:16 +00007774 (resource_info->quantize_info->dither_method != NoDitherMethod) &&
cristy3ed852e2009-09-05 21:47:34 +00007775 (number_colors < MaxColormapSize))
7776 {
7777 Image
7778 *affinity_image;
7779
cristy4c08aed2011-07-01 19:47:50 +00007780 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007781 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007782
7783 /*
7784 Improve image appearance with error diffusion.
7785 */
cristy6710d842011-10-20 23:23:00 +00007786 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007787 if (affinity_image == (Image *) NULL)
7788 ThrowXWindowFatalException(ResourceLimitFatalError,
7789 "UnableToDitherImage",image->filename);
7790 affinity_image->columns=number_colors;
7791 affinity_image->rows=1;
7792 /*
7793 Initialize colormap image.
7794 */
7795 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7796 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007797 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007798 {
cristybb503372010-05-27 20:51:26 +00007799 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007800 {
cristy4c08aed2011-07-01 19:47:50 +00007801 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007802 if (map_info->red_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007803 SetPixelRed(affinity_image,ScaleXToQuantum((size_t)
7804 (i/map_info->red_mult),map_info->red_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007805 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007806 if (map_info->green_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007807 SetPixelGreen(affinity_image,ScaleXToQuantum((size_t)
7808 ((i/map_info->green_mult) % (map_info->green_max+1)),
7809 map_info->green_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007810 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007811 if (map_info->blue_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007812 SetPixelBlue(affinity_image,ScaleXToQuantum((size_t)
7813 (i % map_info->green_mult),map_info->blue_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007814 SetPixelAlpha(affinity_image,
7815 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007816 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007817 }
7818 (void) SyncAuthenticPixels(affinity_image,exception);
7819 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007820 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007821 }
cristy4c08aed2011-07-01 19:47:50 +00007822 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007823 pixel);
cristy574cc262011-08-05 01:23:58 +00007824 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007825 affinity_image=DestroyImage(affinity_image);
7826 }
7827 if (IsEventLogging())
7828 {
7829 (void) LogMagickEvent(X11Event,GetMagickModule(),
7830 "Standard Colormap:");
7831 (void) LogMagickEvent(X11Event,GetMagickModule(),
7832 " colormap id: 0x%lx",map_info->colormap);
7833 (void) LogMagickEvent(X11Event,GetMagickModule(),
7834 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7835 map_info->green_max,map_info->blue_max);
7836 (void) LogMagickEvent(X11Event,GetMagickModule(),
7837 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7838 map_info->green_mult,map_info->blue_mult);
7839 }
7840 return;
7841 }
7842 if ((visual_info->klass != DirectColor) &&
7843 (visual_info->klass != TrueColor))
7844 if ((image->storage_class == DirectClass) ||
7845 ((int) image->colors > visual_info->colormap_size))
7846 {
7847 QuantizeInfo
7848 quantize_info;
7849
7850 /*
7851 Image has more colors than the visual supports.
7852 */
7853 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007854 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007855 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007856 }
7857 /*
7858 Free previous and create new colormap.
7859 */
7860 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7861 colormap=XDefaultColormap(display,visual_info->screen);
7862 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7863 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7864 visual_info->visual,visual_info->klass == DirectColor ?
7865 AllocAll : AllocNone);
7866 if (colormap == (Colormap) NULL)
7867 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7868 image->filename);
7869 /*
7870 Initialize the map and pixel info structures.
7871 */
7872 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007873 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007874 /*
7875 Allocating colors in server colormap is based on visual class.
7876 */
7877 switch (visual_info->klass)
7878 {
7879 case StaticGray:
7880 case StaticColor:
7881 {
7882 /*
7883 Define Standard Colormap for StaticGray or StaticColor visual.
7884 */
7885 number_colors=image->colors;
7886 colors=(XColor *) AcquireQuantumMemory((size_t)
7887 visual_info->colormap_size,sizeof(*colors));
7888 if (colors == (XColor *) NULL)
7889 ThrowXWindowFatalException(ResourceLimitFatalError,
7890 "UnableToCreateColormap",image->filename);
7891 p=colors;
7892 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007893 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007894 {
7895 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7896 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7897 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7898 if (visual_info->klass != StaticColor)
7899 {
7900 gray_value=(unsigned short) XPixelIntensity(&color);
7901 color.red=gray_value;
7902 color.green=gray_value;
7903 color.blue=gray_value;
7904 }
7905 status=XAllocColor(display,colormap,&color);
7906 if (status == False)
7907 {
7908 colormap=XCopyColormapAndFree(display,colormap);
7909 (void) XAllocColor(display,colormap,&color);
7910 }
7911 pixel->pixels[i]=color.pixel;
7912 *p++=color;
7913 }
7914 break;
7915 }
7916 case GrayScale:
7917 case PseudoColor:
7918 {
7919 unsigned int
7920 colormap_type;
7921
7922 /*
7923 Define Standard Colormap for GrayScale or PseudoColor visual.
7924 */
7925 number_colors=image->colors;
7926 colors=(XColor *) AcquireQuantumMemory((size_t)
7927 visual_info->colormap_size,sizeof(*colors));
7928 if (colors == (XColor *) NULL)
7929 ThrowXWindowFatalException(ResourceLimitFatalError,
7930 "UnableToCreateColormap",image->filename);
7931 /*
7932 Preallocate our GUI colors.
7933 */
7934 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7935 (void) XAllocColor(display,colormap,&pixel->background_color);
7936 (void) XAllocColor(display,colormap,&pixel->border_color);
7937 (void) XAllocColor(display,colormap,&pixel->matte_color);
7938 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7939 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7940 (void) XAllocColor(display,colormap,&pixel->depth_color);
7941 (void) XAllocColor(display,colormap,&pixel->trough_color);
7942 for (i=0; i < MaxNumberPens; i++)
7943 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7944 /*
7945 Determine if image colors will "fit" into X server colormap.
7946 */
7947 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007948 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007949 NULL,0,pixel->pixels,(unsigned int) image->colors);
7950 if (status != False)
7951 colormap_type=PrivateColormap;
7952 if (colormap_type == SharedColormap)
7953 {
cristyc57f6942010-11-12 01:47:39 +00007954 CacheView
7955 *image_view;
7956
cristy3ed852e2009-09-05 21:47:34 +00007957 DiversityPacket
7958 *diversity;
7959
7960 int
7961 y;
7962
7963 register int
7964 x;
7965
7966 unsigned short
7967 index;
7968
7969 XColor
7970 *server_colors;
7971
7972 /*
7973 Define Standard colormap for shared GrayScale or PseudoColor visual.
7974 */
7975 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7976 sizeof(*diversity));
7977 if (diversity == (DiversityPacket *) NULL)
7978 ThrowXWindowFatalException(ResourceLimitFatalError,
7979 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007980 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007981 {
cristye42f6582012-02-11 17:59:50 +00007982 diversity[i].red=ClampToQuantum(image->colormap[i].red);
7983 diversity[i].green=ClampToQuantum(image->colormap[i].green);
7984 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00007985 diversity[i].index=(unsigned short) i;
7986 diversity[i].count=0;
7987 }
cristy46ff2672012-12-14 15:32:26 +00007988 image_view=AcquireAuthenticCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007989 for (y=0; y < (int) image->rows; y++)
7990 {
cristyc57f6942010-11-12 01:47:39 +00007991 register int
cristy3ed852e2009-09-05 21:47:34 +00007992 x;
7993
cristy4c08aed2011-07-01 19:47:50 +00007994 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007995 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007996
cristyc57f6942010-11-12 01:47:39 +00007997 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7998 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007999 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008000 break;
cristyc57f6942010-11-12 01:47:39 +00008001 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008002 {
8003 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008004 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008005 }
cristy3ed852e2009-09-05 21:47:34 +00008006 }
cristyc57f6942010-11-12 01:47:39 +00008007 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008008 /*
8009 Sort colors by decreasing intensity.
8010 */
8011 qsort((void *) diversity,image->colors,sizeof(*diversity),
8012 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008013 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008014 {
8015 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008016 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008017 }
8018 diversity[image->colors-1].count<<=4;
8019 qsort((void *) diversity,image->colors,sizeof(*diversity),
8020 PopularityCompare);
8021 /*
8022 Allocate colors.
8023 */
8024 p=colors;
8025 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008026 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008027 {
8028 index=diversity[i].index;
8029 color.red=
8030 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8031 color.green=
8032 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8033 color.blue=
8034 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8035 if (visual_info->klass != PseudoColor)
8036 {
8037 gray_value=(unsigned short) XPixelIntensity(&color);
8038 color.red=gray_value;
8039 color.green=gray_value;
8040 color.blue=gray_value;
8041 }
8042 status=XAllocColor(display,colormap,&color);
8043 if (status == False)
8044 break;
8045 pixel->pixels[index]=color.pixel;
8046 *p++=color;
8047 }
8048 /*
8049 Read X server colormap.
8050 */
8051 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8052 visual_info->colormap_size,sizeof(*server_colors));
8053 if (server_colors == (XColor *) NULL)
8054 ThrowXWindowFatalException(ResourceLimitFatalError,
8055 "UnableToCreateColormap",image->filename);
8056 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008057 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008058 (void) XQueryColors(display,colormap,server_colors,
8059 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8060 /*
8061 Select remaining colors from X server colormap.
8062 */
cristybb503372010-05-27 20:51:26 +00008063 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008064 {
8065 index=diversity[i].index;
cristy534d0a32013-04-13 16:27:24 +00008066 color.red=ScaleQuantumToShort(
8067 XRedGamma(image->colormap[index].red));
8068 color.green=ScaleQuantumToShort(
8069 XGreenGamma(image->colormap[index].green));
8070 color.blue=ScaleQuantumToShort(
8071 XBlueGamma(image->colormap[index].blue));
cristy3ed852e2009-09-05 21:47:34 +00008072 if (visual_info->klass != PseudoColor)
8073 {
8074 gray_value=(unsigned short) XPixelIntensity(&color);
8075 color.red=gray_value;
8076 color.green=gray_value;
8077 color.blue=gray_value;
8078 }
8079 XBestPixel(display,colormap,server_colors,(unsigned int)
8080 visual_info->colormap_size,&color);
8081 pixel->pixels[index]=color.pixel;
8082 *p++=color;
8083 }
8084 if ((int) image->colors < visual_info->colormap_size)
8085 {
8086 /*
8087 Fill up colors array-- more choices for pen colors.
8088 */
8089 retain_colors=MagickMin((unsigned int)
8090 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008091 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008092 *p++=server_colors[i];
8093 number_colors+=retain_colors;
8094 }
8095 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8096 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8097 break;
8098 }
8099 /*
8100 Define Standard colormap for private GrayScale or PseudoColor visual.
8101 */
8102 if (status == False)
8103 {
8104 /*
8105 Not enough colormap entries in the colormap-- Create a new colormap.
8106 */
8107 colormap=XCreateColormap(display,
8108 XRootWindow(display,visual_info->screen),visual_info->visual,
8109 AllocNone);
8110 if (colormap == (Colormap) NULL)
8111 ThrowXWindowFatalException(ResourceLimitFatalError,
8112 "UnableToCreateColormap",image->filename);
8113 map_info->colormap=colormap;
8114 if ((int) image->colors < visual_info->colormap_size)
8115 {
8116 /*
8117 Retain colors from the default colormap to help lessens the
8118 effects of colormap flashing.
8119 */
8120 retain_colors=MagickMin((unsigned int)
8121 (visual_info->colormap_size-image->colors),256);
8122 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008123 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008124 {
cristyc57f6942010-11-12 01:47:39 +00008125 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008126 p++;
8127 }
8128 (void) XQueryColors(display,
8129 XDefaultColormap(display,visual_info->screen),
8130 colors+image->colors,(int) retain_colors);
8131 /*
8132 Transfer colors from default to private colormap.
8133 */
8134 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008135 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008136 retain_colors);
8137 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008138 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008139 {
8140 p->pixel=pixel->pixels[i];
8141 p++;
8142 }
8143 (void) XStoreColors(display,colormap,colors+image->colors,
8144 (int) retain_colors);
8145 number_colors+=retain_colors;
8146 }
8147 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008148 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008149 image->colors);
8150 }
8151 /*
8152 Store the image colormap.
8153 */
8154 p=colors;
8155 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008156 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008157 {
8158 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8159 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8160 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8161 if (visual_info->klass != PseudoColor)
8162 {
8163 gray_value=(unsigned short) XPixelIntensity(&color);
8164 color.red=gray_value;
8165 color.green=gray_value;
8166 color.blue=gray_value;
8167 }
8168 color.pixel=pixel->pixels[i];
8169 *p++=color;
8170 }
8171 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8172 break;
8173 }
8174 case TrueColor:
8175 case DirectColor:
8176 default:
8177 {
8178 MagickBooleanType
8179 linear_colormap;
8180
8181 /*
8182 Define Standard Colormap for TrueColor or DirectColor visual.
8183 */
8184 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8185 (map_info->green_max*map_info->green_mult)+
8186 (map_info->blue_max*map_info->blue_mult)+1);
8187 linear_colormap=(number_colors > 4096) ||
8188 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8189 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8190 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8191 MagickTrue : MagickFalse;
8192 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008193 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008194 /*
8195 Allocate color array.
8196 */
8197 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8198 if (colors == (XColor *) NULL)
8199 ThrowXWindowFatalException(ResourceLimitFatalError,
8200 "UnableToCreateColormap",image->filename);
8201 /*
8202 Initialize linear color ramp.
8203 */
8204 p=colors;
8205 color.flags=(char) (DoRed | DoGreen | DoBlue);
8206 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008207 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008208 {
8209 color.blue=(unsigned short) 0;
8210 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008211 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008212 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8213 color.green=color.blue;
8214 color.red=color.blue;
8215 color.pixel=XStandardPixel(map_info,&color);
8216 *p++=color;
8217 }
8218 else
cristybb503372010-05-27 20:51:26 +00008219 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008220 {
8221 color.red=(unsigned short) 0;
8222 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008223 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008224 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8225 color.green=(unsigned int) 0;
8226 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008227 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008228 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8229 map_info->green_max));
8230 color.blue=(unsigned short) 0;
8231 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008232 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008233 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8234 color.pixel=XStandardPixel(map_info,&color);
8235 *p++=color;
8236 }
8237 if ((visual_info->klass == DirectColor) &&
8238 (colormap != XDefaultColormap(display,visual_info->screen)))
8239 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8240 else
cristybb503372010-05-27 20:51:26 +00008241 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008242 (void) XAllocColor(display,colormap,&colors[i]);
8243 break;
8244 }
8245 }
8246 if ((visual_info->klass != DirectColor) &&
8247 (visual_info->klass != TrueColor))
8248 {
8249 /*
8250 Set foreground, background, border, etc. pixels.
8251 */
8252 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8253 &pixel->foreground_color);
8254 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8255 &pixel->background_color);
8256 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8257 {
8258 /*
8259 Foreground and background colors must differ.
8260 */
8261 pixel->background_color.red=(~pixel->foreground_color.red);
8262 pixel->background_color.green=
8263 (~pixel->foreground_color.green);
8264 pixel->background_color.blue=
8265 (~pixel->foreground_color.blue);
8266 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8267 &pixel->background_color);
8268 }
8269 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8270 &pixel->border_color);
8271 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8272 &pixel->matte_color);
8273 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8274 &pixel->highlight_color);
8275 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8276 &pixel->shadow_color);
8277 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8278 &pixel->depth_color);
8279 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8280 &pixel->trough_color);
8281 for (i=0; i < MaxNumberPens; i++)
8282 {
8283 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8284 &pixel->pen_colors[i]);
8285 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8286 }
cristyc57f6942010-11-12 01:47:39 +00008287 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008288 }
8289 colors=(XColor *) RelinquishMagickMemory(colors);
8290 if (IsEventLogging())
8291 {
8292 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8293 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8294 map_info->colormap);
8295 (void) LogMagickEvent(X11Event,GetMagickModule(),
8296 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8297 map_info->green_max,map_info->blue_max);
8298 (void) LogMagickEvent(X11Event,GetMagickModule(),
8299 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8300 map_info->green_mult,map_info->blue_mult);
8301 }
8302}
8303
8304/*
8305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8306% %
8307% %
8308% %
8309% X M a k e W i n d o w %
8310% %
8311% %
8312% %
8313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8314%
8315% XMakeWindow() creates an X11 window.
8316%
8317% The format of the XMakeWindow method is:
8318%
8319% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8320% XClassHint *class_hint,XWMHints *manager_hints,
8321% XWindowInfo *window_info)
8322%
8323% A description of each parameter follows:
8324%
8325% o display: Specifies a connection to an X server; returned from
8326% XOpenDisplay.
8327%
8328% o parent: Specifies the parent window_info.
8329%
8330% o argv: Specifies the application's argument list.
8331%
8332% o argc: Specifies the number of arguments.
8333%
8334% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8335%
8336% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8337%
8338% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8339%
8340*/
cristybcbda3f2011-09-03 13:01:22 +00008341MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008342 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8343 XWindowInfo *window_info)
8344{
8345#define MinWindowSize 64
8346
8347 Atom
8348 atom_list[2];
8349
8350 int
8351 gravity;
8352
8353 static XTextProperty
8354 icon_name,
8355 window_name;
8356
8357 Status
8358 status;
8359
8360 XSizeHints
8361 *size_hints;
8362
8363 /*
8364 Set window info hints.
8365 */
8366 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8367 assert(display != (Display *) NULL);
8368 assert(window_info != (XWindowInfo *) NULL);
8369 size_hints=XAllocSizeHints();
8370 if (size_hints == (XSizeHints *) NULL)
8371 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008372 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008373 size_hints->x=window_info->x;
8374 size_hints->y=window_info->y;
8375 size_hints->width=(int) window_info->width;
8376 size_hints->height=(int) window_info->height;
8377 if (window_info->immutable != MagickFalse)
8378 {
8379 /*
8380 Window size cannot be changed.
8381 */
8382 size_hints->min_width=size_hints->width;
8383 size_hints->min_height=size_hints->height;
8384 size_hints->max_width=size_hints->width;
8385 size_hints->max_height=size_hints->height;
8386 size_hints->flags|=PMinSize;
8387 size_hints->flags|=PMaxSize;
8388 }
8389 else
8390 {
8391 /*
8392 Window size can be changed.
8393 */
8394 size_hints->min_width=(int) window_info->min_width;
8395 size_hints->min_height=(int) window_info->min_height;
8396 size_hints->flags|=PResizeInc;
8397 size_hints->width_inc=(int) window_info->width_inc;
8398 size_hints->height_inc=(int) window_info->height_inc;
8399#if !defined(PRE_R4_ICCCM)
8400 size_hints->flags|=PBaseSize;
8401 size_hints->base_width=size_hints->width_inc;
8402 size_hints->base_height=size_hints->height_inc;
8403#endif
8404 }
8405 gravity=NorthWestGravity;
8406 if (window_info->geometry != (char *) NULL)
8407 {
8408 char
8409 default_geometry[MaxTextExtent],
8410 geometry[MaxTextExtent];
8411
8412 int
8413 flags;
8414
8415 register char
8416 *p;
8417
8418 /*
8419 User specified geometry.
8420 */
cristyb51dff52011-05-19 16:55:47 +00008421 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008422 size_hints->width,size_hints->height);
8423 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8424 p=geometry;
8425 while (strlen(p) != 0)
8426 {
8427 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8428 p++;
8429 else
8430 (void) CopyMagickString(p,p+1,MaxTextExtent);
8431 }
8432 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8433 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8434 &size_hints->width,&size_hints->height,&gravity);
8435 if ((flags & WidthValue) && (flags & HeightValue))
8436 size_hints->flags|=USSize;
8437 if ((flags & XValue) && (flags & YValue))
8438 {
8439 size_hints->flags|=USPosition;
8440 window_info->x=size_hints->x;
8441 window_info->y=size_hints->y;
8442 }
8443 }
8444#if !defined(PRE_R4_ICCCM)
8445 size_hints->win_gravity=gravity;
8446 size_hints->flags|=PWinGravity;
8447#endif
8448 if (window_info->id == (Window) NULL)
8449 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8450 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8451 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008452 window_info->visual,(unsigned long) window_info->mask,
8453 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008454 else
8455 {
8456 MagickStatusType
8457 mask;
8458
8459 XEvent
8460 sans_event;
8461
8462 XWindowChanges
8463 window_changes;
8464
8465 /*
8466 Window already exists; change relevant attributes.
8467 */
cristyc57f6942010-11-12 01:47:39 +00008468 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8469 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008470 mask=ConfigureNotify;
8471 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8472 window_changes.x=window_info->x;
8473 window_changes.y=window_info->y;
8474 window_changes.width=(int) window_info->width;
8475 window_changes.height=(int) window_info->height;
8476 mask=(MagickStatusType) (CWWidth | CWHeight);
8477 if (window_info->flags & USPosition)
8478 mask|=CWX | CWY;
8479 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8480 mask,&window_changes);
8481 }
8482 if (window_info->id == (Window) NULL)
8483 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8484 window_info->name);
8485 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8486 if (status == False)
8487 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8488 window_info->name);
8489 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8490 if (status == False)
8491 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8492 window_info->icon_name);
8493 if (window_info->icon_geometry != (char *) NULL)
8494 {
8495 int
8496 flags,
8497 height,
8498 width;
8499
8500 /*
8501 User specified icon geometry.
8502 */
8503 size_hints->flags|=USPosition;
8504 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8505 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8506 &manager_hints->icon_y,&width,&height,&gravity);
8507 if ((flags & XValue) && (flags & YValue))
8508 manager_hints->flags|=IconPositionHint;
8509 }
8510 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8511 size_hints,manager_hints,class_hint);
8512 if (window_name.value != (void *) NULL)
8513 {
8514 (void) XFree((void *) window_name.value);
8515 window_name.value=(unsigned char *) NULL;
8516 window_name.nitems=0;
8517 }
8518 if (icon_name.value != (void *) NULL)
8519 {
8520 (void) XFree((void *) icon_name.value);
8521 icon_name.value=(unsigned char *) NULL;
8522 icon_name.nitems=0;
8523 }
8524 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8525 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8526 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8527 (void) XFree((void *) size_hints);
8528 if (window_info->shape != MagickFalse)
8529 {
8530#if defined(MAGICKCORE_HAVE_SHAPE)
8531 int
8532 error_base,
8533 event_base;
8534
8535 /*
8536 Can we apply a non-rectangular shaping mask?
8537 */
8538 error_base=0;
8539 event_base=0;
8540 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8541 window_info->shape=MagickFalse;
8542#else
8543 window_info->shape=MagickFalse;
8544#endif
8545 }
8546 if (window_info->shared_memory)
8547 {
8548#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8549 /*
8550 Can we use shared memory with this window?
8551 */
8552 if (XShmQueryExtension(display) == 0)
8553 window_info->shared_memory=MagickFalse;
8554#else
8555 window_info->shared_memory=MagickFalse;
8556#endif
8557 }
8558 window_info->image=NewImageList();
8559 window_info->destroy=MagickFalse;
8560}
8561
8562/*
8563%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8564% %
8565% %
8566% %
8567% X M a g i c k P r o g r e s s M o n i t o r %
8568% %
8569% %
8570% %
8571%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8572%
8573% XMagickProgressMonitor() displays the progress a task is making in
8574% completing a task.
8575%
8576% The format of the XMagickProgressMonitor method is:
8577%
8578% void XMagickProgressMonitor(const char *task,
8579% const MagickOffsetType quantum,const MagickSizeType span,
8580% void *client_data)
8581%
8582% A description of each parameter follows:
8583%
8584% o task: Identifies the task in progress.
8585%
8586% o quantum: Specifies the quantum position within the span which represents
8587% how much progress has been made in completing a task.
8588%
8589% o span: Specifies the span relative to completing a task.
8590%
8591% o client_data: Pointer to any client data.
8592%
8593*/
8594
8595static const char *GetLocaleMonitorMessage(const char *text)
8596{
8597 char
8598 message[MaxTextExtent],
8599 tag[MaxTextExtent];
8600
8601 const char
8602 *locale_message;
8603
8604 register char
8605 *p;
8606
8607 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8608 p=strrchr(tag,'/');
8609 if (p != (char *) NULL)
8610 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008611 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008612 locale_message=GetLocaleMessage(message);
8613 if (locale_message == message)
8614 return(text);
8615 return(locale_message);
8616}
8617
cristybcbda3f2011-09-03 13:01:22 +00008618MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008619 const MagickOffsetType quantum,const MagickSizeType span,
8620 void *magick_unused(client_data))
8621{
8622 XWindows
8623 *windows;
8624
8625 windows=XSetWindows((XWindows *) ~0);
8626 if (windows == (XWindows *) NULL)
8627 return(MagickTrue);
8628 if (windows->info.mapped != MagickFalse)
8629 XProgressMonitorWidget(windows->display,windows,
8630 GetLocaleMonitorMessage(tag),quantum,span);
8631 return(MagickTrue);
8632}
8633
8634/*
8635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8636% %
8637% %
8638% %
8639% X Q u e r y C o l o r D a t a b a s e %
8640% %
8641% %
8642% %
8643%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8644%
cristy9950d572011-10-01 18:22:35 +00008645% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008646% string.
8647%
8648% The format of the XQueryColorDatabase method is:
8649%
cristy9950d572011-10-01 18:22:35 +00008650% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008651%
8652% A description of each parameter follows:
8653%
8654% o target: Specifies the color to lookup in the X color database.
8655%
cristy101ab702011-10-13 13:06:32 +00008656% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008657% color is returned as this value.
8658%
8659*/
cristy9950d572011-10-01 18:22:35 +00008660MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008661 XColor *color)
8662{
8663 Colormap
8664 colormap;
8665
8666 static Display
8667 *display = (Display *) NULL;
8668
8669 Status
8670 status;
8671
8672 XColor
8673 xcolor;
8674
8675 /*
8676 Initialize color return value.
8677 */
8678 assert(color != (XColor *) NULL);
8679 color->red=0;
8680 color->green=0;
8681 color->blue=0;
8682 color->flags=(char) (DoRed | DoGreen | DoBlue);
8683 if ((target == (char *) NULL) || (*target == '\0'))
8684 target="#ffffffffffff";
8685 /*
8686 Let the X server define the color for us.
8687 */
8688 if (display == (Display *) NULL)
8689 display=XOpenDisplay((char *) NULL);
8690 if (display == (Display *) NULL)
8691 {
cristyc38fbf52013-11-03 13:55:54 +00008692 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target);
cristy3ed852e2009-09-05 21:47:34 +00008693 return(MagickFalse);
8694 }
8695 colormap=XDefaultColormap(display,XDefaultScreen(display));
8696 status=XParseColor(display,colormap,(char *) target,&xcolor);
8697 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00008698 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target)
cristy3ed852e2009-09-05 21:47:34 +00008699 else
8700 {
8701 color->red=xcolor.red;
8702 color->green=xcolor.green;
8703 color->blue=xcolor.blue;
8704 color->flags=xcolor.flags;
8705 }
8706 return(status != False ? MagickTrue : MagickFalse);
8707}
8708
8709/*
8710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8711% %
8712% %
8713% %
8714% X Q u e r y P o s i t i o n %
8715% %
8716% %
8717% %
8718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8719%
8720% XQueryPosition() gets the pointer coordinates relative to a window.
8721%
8722% The format of the XQueryPosition method is:
8723%
8724% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8725%
8726% A description of each parameter follows:
8727%
8728% o display: Specifies a connection to an X server; returned from
8729% XOpenDisplay.
8730%
8731% o window: Specifies a pointer to a Window.
8732%
8733% o x: Return the x coordinate of the pointer relative to the origin of the
8734% window.
8735%
8736% o y: Return the y coordinate of the pointer relative to the origin of the
8737% window.
8738%
8739*/
cristy534d0a32013-04-13 16:27:24 +00008740MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,
8741 int *y)
cristy3ed852e2009-09-05 21:47:34 +00008742{
8743 int
8744 x_root,
8745 y_root;
8746
8747 unsigned int
8748 mask;
8749
8750 Window
8751 root_window;
8752
8753 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8754 assert(display != (Display *) NULL);
8755 assert(window != (Window) NULL);
8756 assert(x != (int *) NULL);
8757 assert(y != (int *) NULL);
8758 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8759 x,y,&mask);
8760}
8761
8762/*
8763%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8764% %
8765% %
8766% %
8767% X R e f r e s h W i n d o w %
8768% %
8769% %
8770% %
8771%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8772%
8773% XRefreshWindow() refreshes an image in a X window.
8774%
8775% The format of the XRefreshWindow method is:
8776%
8777% void XRefreshWindow(Display *display,const XWindowInfo *window,
8778% const XEvent *event)
8779%
8780% A description of each parameter follows:
8781%
8782% o display: Specifies a connection to an X server; returned from
8783% XOpenDisplay.
8784%
8785% o window: Specifies a pointer to a XWindowInfo structure.
8786%
8787% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8788% the entire image is refreshed.
8789%
8790*/
cristybcbda3f2011-09-03 13:01:22 +00008791MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008792 const XEvent *event)
8793{
8794 int
8795 x,
8796 y;
8797
8798 unsigned int
8799 height,
8800 width;
8801
8802 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8803 assert(display != (Display *) NULL);
8804 assert(window != (XWindowInfo *) NULL);
8805 if (window->ximage == (XImage *) NULL)
8806 return;
8807 if (event != (XEvent *) NULL)
8808 {
8809 /*
8810 Determine geometry from expose event.
8811 */
8812 x=event->xexpose.x;
8813 y=event->xexpose.y;
8814 width=(unsigned int) event->xexpose.width;
8815 height=(unsigned int) event->xexpose.height;
8816 }
8817 else
8818 {
8819 XEvent
8820 sans_event;
8821
8822 /*
8823 Refresh entire window; discard outstanding expose events.
8824 */
8825 x=0;
8826 y=0;
8827 width=window->width;
8828 height=window->height;
8829 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008830 if (window->matte_pixmap != (Pixmap) NULL)
8831 {
8832#if defined(MAGICKCORE_HAVE_SHAPE)
8833 if (window->shape != MagickFalse)
8834 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8835 window->matte_pixmap,ShapeSet);
8836#endif
8837 }
cristy3ed852e2009-09-05 21:47:34 +00008838 }
8839 /*
8840 Check boundary conditions.
8841 */
8842 if ((window->ximage->width-(x+window->x)) < (int) width)
8843 width=(unsigned int) (window->ximage->width-(x+window->x));
8844 if ((window->ximage->height-(y+window->y)) < (int) height)
8845 height=(unsigned int) (window->ximage->height-(y+window->y));
8846 /*
8847 Refresh image.
8848 */
8849 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008850 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008851 if (window->pixmap != (Pixmap) NULL)
8852 {
8853 if (window->depth > 1)
8854 (void) XCopyArea(display,window->pixmap,window->id,
8855 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8856 else
8857 (void) XCopyPlane(display,window->pixmap,window->id,
8858 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8859 1L);
8860 }
8861 else
8862 {
8863#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8864 if (window->shared_memory)
8865 (void) XShmPutImage(display,window->id,window->annotate_context,
8866 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8867#endif
8868 if (window->shared_memory == MagickFalse)
8869 (void) XPutImage(display,window->id,window->annotate_context,
8870 window->ximage,x+window->x,y+window->y,x,y,width,height);
8871 }
8872 if (window->matte_pixmap != (Pixmap) NULL)
8873 (void) XSetClipMask(display,window->annotate_context,None);
8874 (void) XFlush(display);
8875}
8876
8877/*
8878%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8879% %
8880% %
8881% %
8882% X R e m o t e C o m m a n d %
8883% %
8884% %
8885% %
8886%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8887%
8888% XRemoteCommand() forces a remote display(1) to display the specified
8889% image filename.
8890%
8891% The format of the XRemoteCommand method is:
8892%
8893% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8894% const char *filename)
8895%
8896% A description of each parameter follows:
8897%
8898% o display: Specifies a connection to an X server; returned from
8899% XOpenDisplay.
8900%
8901% o window: Specifies the name or id of an X window.
8902%
8903% o filename: the name of the image filename to display.
8904%
8905*/
8906MagickExport MagickBooleanType XRemoteCommand(Display *display,
8907 const char *window,const char *filename)
8908{
8909 Atom
8910 remote_atom;
8911
8912 Window
8913 remote_window,
8914 root_window;
8915
8916 assert(filename != (char *) NULL);
8917 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8918 if (display == (Display *) NULL)
8919 display=XOpenDisplay((char *) NULL);
8920 if (display == (Display *) NULL)
8921 {
8922 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8923 return(MagickFalse);
8924 }
8925 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8926 remote_window=(Window) NULL;
8927 root_window=XRootWindow(display,XDefaultScreen(display));
8928 if (window != (char *) NULL)
8929 {
8930 /*
8931 Search window hierarchy and identify any clients by name or ID.
8932 */
cristy02e64f82013-11-14 16:20:04 +00008933 if (isdigit((int) ((unsigned char) *window)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00008934 remote_window=XWindowByID(display,root_window,(Window)
8935 strtol((char *) window,(char **) NULL,0));
8936 if (remote_window == (Window) NULL)
8937 remote_window=XWindowByName(display,root_window,window);
8938 }
8939 if (remote_window == (Window) NULL)
8940 remote_window=XWindowByProperty(display,root_window,remote_atom);
8941 if (remote_window == (Window) NULL)
8942 {
8943 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8944 filename);
8945 return(MagickFalse);
8946 }
8947 /*
8948 Send remote command.
8949 */
8950 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8951 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8952 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8953 (void) XSync(display,MagickFalse);
8954 return(MagickTrue);
8955}
8956
8957/*
8958%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8959% %
8960% %
8961% %
cristy534d0a32013-04-13 16:27:24 +00008962% X R e n d e r I m a g e %
8963% %
8964% %
8965% %
8966%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8967%
8968% XRenderImage() renders text on the image with an X11 font. It also returns
8969% the bounding box of the text relative to the image.
8970%
8971% The format of the XRenderImage method is:
8972%
8973% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
8974% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
8975%
8976% A description of each parameter follows:
8977%
8978% o image: the image.
8979%
8980% o draw_info: the draw info.
8981%
8982% o offset: (x,y) location of text relative to image.
8983%
8984% o metrics: bounding box of text.
8985%
8986% o exception: return any errors or warnings in this structure.
8987%
8988*/
8989MagickPrivate MagickBooleanType XRenderImage(Image *image,
8990 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
8991 ExceptionInfo *exception)
8992{
8993 const char
8994 *client_name;
8995
8996 DrawInfo
8997 cache_info;
8998
8999 Display
9000 *display;
9001
9002 ImageInfo
9003 *image_info;
9004
9005 MagickBooleanType
9006 status;
9007
9008 size_t
9009 height,
9010 width;
9011
9012 XAnnotateInfo
9013 annotate_info;
9014
9015 XFontStruct
9016 *font_info;
9017
9018 XPixelInfo
9019 pixel;
9020
9021 XResourceInfo
9022 resource_info;
9023
9024 XrmDatabase
9025 resource_database;
9026
9027 XStandardColormap
9028 *map_info;
9029
9030 XVisualInfo
9031 *visual_info;
9032
9033 /*
9034 Open X server connection.
9035 */
9036 display=XOpenDisplay(draw_info->server_name);
9037 if (display == (Display *) NULL)
9038 {
9039 ThrowXWindowException(XServerError,"UnableToOpenXServer",
9040 draw_info->server_name);
9041 return(MagickFalse);
9042 }
9043 /*
9044 Get user defaults from X resource database.
9045 */
9046 (void) XSetErrorHandler(XError);
9047 image_info=AcquireImageInfo();
9048 client_name=GetClientName();
9049 resource_database=XGetResourceDatabase(display,client_name);
9050 XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
9051 resource_info.close_server=MagickFalse;
9052 resource_info.colormap=PrivateColormap;
9053 resource_info.font=AcquireString(draw_info->font);
9054 resource_info.background_color=AcquireString("#ffffffffffff");
9055 resource_info.foreground_color=AcquireString("#000000000000");
9056 map_info=XAllocStandardColormap();
9057 if (map_info == (XStandardColormap *) NULL)
9058 {
9059 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9060 image->filename);
9061 return(MagickFalse);
9062 }
9063 /*
9064 Initialize visual info.
9065 */
9066 visual_info=XBestVisualInfo(display,map_info,&resource_info);
9067 if (visual_info == (XVisualInfo *) NULL)
9068 {
cristyc38fbf52013-11-03 13:55:54 +00009069 ThrowXWindowException(XServerError,"UnableToGetVisual",image->filename);
cristy534d0a32013-04-13 16:27:24 +00009070 return(MagickFalse);
9071 }
9072 map_info->colormap=(Colormap) NULL;
9073 pixel.pixels=(unsigned long *) NULL;
9074 /*
9075 Initialize Standard Colormap info.
9076 */
9077 XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
9078 map_info);
9079 XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
9080 &pixel);
9081 pixel.annotate_context=XDefaultGC(display,visual_info->screen);
9082 /*
9083 Initialize font info.
9084 */
9085 font_info=XBestFont(display,&resource_info,MagickFalse);
9086 if (font_info == (XFontStruct *) NULL)
9087 {
9088 ThrowXWindowException(XServerError,"UnableToLoadFont",draw_info->font);
9089 return(MagickFalse);
9090 }
9091 if ((map_info == (XStandardColormap *) NULL) ||
9092 (visual_info == (XVisualInfo *) NULL) ||
9093 (font_info == (XFontStruct *) NULL))
9094 {
9095 XFreeResources(display,visual_info,map_info,&pixel,font_info,
9096 &resource_info,(XWindowInfo *) NULL);
9097 ThrowXWindowException(XServerError,"UnableToLoadFont",image->filename);
9098 return(MagickFalse);
9099 }
9100 cache_info=(*draw_info);
9101 /*
9102 Initialize annotate info.
9103 */
9104 XGetAnnotateInfo(&annotate_info);
9105 annotate_info.stencil=ForegroundStencil;
9106 if (cache_info.font != draw_info->font)
9107 {
9108 /*
9109 Type name has changed.
9110 */
9111 (void) XFreeFont(display,font_info);
9112 (void) CloneString(&resource_info.font,draw_info->font);
9113 font_info=XBestFont(display,&resource_info,MagickFalse);
9114 if (font_info == (XFontStruct *) NULL)
9115 {
9116 ThrowXWindowException(XServerError,"UnableToLoadFont",
9117 draw_info->font);
9118 return(MagickFalse);
9119 }
9120 }
9121 if (image->debug != MagickFalse)
9122 (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
9123 "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
9124 draw_info->font : "none",draw_info->pointsize);
9125 cache_info=(*draw_info);
9126 annotate_info.font_info=font_info;
9127 annotate_info.text=(char *) draw_info->text;
9128 annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
9129 strlen(draw_info->text));
9130 annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
9131 metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
9132 metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
9133 metrics->ascent=(double) font_info->ascent+4;
9134 metrics->descent=(double) (-font_info->descent);
9135 metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
9136 metrics->height=font_info->ascent+font_info->descent;
9137 metrics->max_advance=(double) font_info->max_bounds.width;
9138 metrics->bounds.x1=0.0;
9139 metrics->bounds.y1=metrics->descent;
9140 metrics->bounds.x2=metrics->ascent+metrics->descent;
9141 metrics->bounds.y2=metrics->ascent+metrics->descent;
9142 metrics->underline_position=(-2.0);
9143 metrics->underline_thickness=1.0;
9144 if (draw_info->render == MagickFalse)
9145 return(MagickTrue);
9146 if (draw_info->fill.alpha == TransparentAlpha)
9147 return(MagickTrue);
9148 /*
9149 Render fill color.
9150 */
9151 width=annotate_info.width;
9152 height=annotate_info.height;
9153 if ((fabs(draw_info->affine.rx) >= MagickEpsilon) ||
9154 (fabs(draw_info->affine.ry) >= MagickEpsilon))
9155 {
9156 if ((fabs(draw_info->affine.sx-draw_info->affine.sy) < MagickEpsilon) &&
9157 (fabs(draw_info->affine.rx+draw_info->affine.ry) < MagickEpsilon))
9158 annotate_info.degrees=(double) (180.0/MagickPI)*
9159 atan2(draw_info->affine.rx,draw_info->affine.sx);
9160 }
9161 (void) FormatLocaleString(annotate_info.geometry,MaxTextExtent,
9162 "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
9163 ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
9164 draw_info->interline_spacing-0.5));
9165 pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
9166 pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
9167 pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);
9168 status=XAnnotateImage(display,&pixel,&annotate_info,image,exception);
9169 if (status == 0)
9170 {
9171 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9172 image->filename);
9173 return(MagickFalse);
9174 }
9175 return(MagickTrue);
9176}
9177
9178/*
9179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9180% %
9181% %
9182% %
cristy3ed852e2009-09-05 21:47:34 +00009183% X R e t a i n W i n d o w C o l o r s %
9184% %
9185% %
9186% %
9187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9188%
9189% XRetainWindowColors() sets X11 color resources on a window. This preserves
9190% the colors associated with an image displayed on the window.
9191%
9192% The format of the XRetainWindowColors method is:
9193%
9194% void XRetainWindowColors(Display *display,const Window window)
9195%
9196% A description of each parameter follows:
9197%
9198% o display: Specifies a connection to an X server; returned from
9199% XOpenDisplay.
9200%
9201% o window: Specifies a pointer to a XWindowInfo structure.
9202%
9203*/
9204MagickExport void XRetainWindowColors(Display *display,const Window window)
9205{
9206 Atom
9207 property;
9208
9209 Pixmap
9210 pixmap;
9211
9212 /*
9213 Put property on the window.
9214 */
9215 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9216 assert(display != (Display *) NULL);
9217 assert(window != (Window) NULL);
9218 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9219 if (property == (Atom) NULL)
9220 {
cristyc38fbf52013-11-03 13:55:54 +00009221 ThrowXWindowException(XServerError,"UnableToCreateProperty",
cristy3ed852e2009-09-05 21:47:34 +00009222 "_XSETROOT_ID");
9223 return;
9224 }
9225 pixmap=XCreatePixmap(display,window,1,1,1);
9226 if (pixmap == (Pixmap) NULL)
9227 {
cristyc38fbf52013-11-03 13:55:54 +00009228 ThrowXWindowException(XServerError,"UnableToCreateBitmap","");
cristy3ed852e2009-09-05 21:47:34 +00009229 return;
9230 }
9231 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9232 (unsigned char *) &pixmap,1);
9233 (void) XSetCloseDownMode(display,RetainPermanent);
9234}
9235
9236/*
9237%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9238% %
9239% %
9240% %
9241% X S e l e c t W i n d o w %
9242% %
9243% %
9244% %
9245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9246%
9247% XSelectWindow() allows a user to select a window using the mouse. If the
9248% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9249% is returned in the crop_info structure.
9250%
9251% The format of the XSelectWindow function is:
9252%
9253% target_window=XSelectWindow(display,crop_info)
9254%
9255% A description of each parameter follows:
9256%
9257% o window: XSelectWindow returns the window id.
9258%
9259% o display: Specifies a pointer to the Display structure; returned from
9260% XOpenDisplay.
9261%
9262% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9263% contains the extents of any cropping rectangle.
9264%
cristy3ed852e2009-09-05 21:47:34 +00009265*/
9266static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9267{
9268#define MinimumCropArea (unsigned int) 9
9269
9270 Cursor
9271 target_cursor;
9272
9273 GC
9274 annotate_context;
9275
9276 int
9277 presses,
9278 x_offset,
9279 y_offset;
9280
9281 Status
9282 status;
9283
9284 Window
9285 root_window,
9286 target_window;
9287
9288 XEvent
9289 event;
9290
9291 XGCValues
9292 context_values;
9293
9294 /*
9295 Initialize graphic context.
9296 */
9297 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9298 assert(display != (Display *) NULL);
9299 assert(crop_info != (RectangleInfo *) NULL);
9300 root_window=XRootWindow(display,XDefaultScreen(display));
9301 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9302 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9303 context_values.function=GXinvert;
9304 context_values.plane_mask=
9305 context_values.background ^ context_values.foreground;
9306 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009307 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009308 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9309 if (annotate_context == (GC) NULL)
9310 return(MagickFalse);
9311 /*
9312 Grab the pointer using target cursor.
9313 */
9314 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9315 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9316 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9317 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9318 GrabModeAsync,root_window,target_cursor,CurrentTime);
9319 if (status != GrabSuccess)
9320 {
cristyc38fbf52013-11-03 13:55:54 +00009321 ThrowXWindowException(XServerError,"UnableToGrabMouse","");
cristy3ed852e2009-09-05 21:47:34 +00009322 return((Window) NULL);
9323 }
9324 /*
9325 Select a window.
9326 */
9327 crop_info->width=0;
9328 crop_info->height=0;
9329 presses=0;
9330 target_window=(Window) NULL;
9331 x_offset=0;
9332 y_offset=0;
9333 do
9334 {
9335 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9336 (void) XDrawRectangle(display,root_window,annotate_context,
9337 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9338 (unsigned int) crop_info->height-1);
9339 /*
9340 Allow another event.
9341 */
9342 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9343 (void) XWindowEvent(display,root_window,ButtonPressMask |
9344 ButtonReleaseMask | ButtonMotionMask,&event);
9345 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9346 (void) XDrawRectangle(display,root_window,annotate_context,
9347 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9348 (unsigned int) crop_info->height-1);
9349 switch (event.type)
9350 {
9351 case ButtonPress:
9352 {
9353 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9354 event.xbutton.x,event.xbutton.y);
9355 if (target_window == (Window) NULL)
9356 target_window=root_window;
9357 x_offset=event.xbutton.x_root;
9358 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009359 crop_info->x=(ssize_t) x_offset;
9360 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009361 crop_info->width=0;
9362 crop_info->height=0;
9363 presses++;
9364 break;
9365 }
9366 case ButtonRelease:
9367 {
9368 presses--;
9369 break;
9370 }
9371 case MotionNotify:
9372 {
9373 /*
9374 Discard pending button motion events.
9375 */
9376 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009377 crop_info->x=(ssize_t) event.xmotion.x;
9378 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009379 /*
9380 Check boundary conditions.
9381 */
9382 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009383 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009384 else
9385 {
cristyecd0ab52010-05-30 14:59:20 +00009386 crop_info->width=(size_t) (crop_info->x-x_offset);
9387 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009388 }
9389 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009390 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009391 else
9392 {
cristyecd0ab52010-05-30 14:59:20 +00009393 crop_info->height=(size_t) (crop_info->y-y_offset);
9394 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009395 }
9396 }
9397 default:
9398 break;
9399 }
9400 } while ((target_window == (Window) NULL) || (presses > 0));
9401 (void) XUngrabPointer(display,CurrentTime);
9402 (void) XFreeCursor(display,target_cursor);
9403 (void) XFreeGC(display,annotate_context);
9404 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9405 {
9406 crop_info->width=0;
9407 crop_info->height=0;
9408 }
9409 if ((crop_info->width != 0) && (crop_info->height != 0))
9410 target_window=root_window;
9411 return(target_window);
9412}
9413
9414/*
9415%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9416% %
9417% %
9418% %
9419% X S e t C u r s o r S t a t e %
9420% %
9421% %
9422% %
9423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9424%
9425% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9426% reset to their default.
9427%
9428% The format of the XXSetCursorState method is:
9429%
9430% XSetCursorState(display,windows,const MagickStatusType state)
9431%
9432% A description of each parameter follows:
9433%
9434% o display: Specifies a connection to an X server; returned from
9435% XOpenDisplay.
9436%
9437% o windows: Specifies a pointer to a XWindows structure.
9438%
9439% o state: An unsigned integer greater than 0 sets the cursor state
9440% to busy, otherwise the cursor are reset to their default.
9441%
9442*/
cristybcbda3f2011-09-03 13:01:22 +00009443MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009444 const MagickStatusType state)
9445{
9446 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9447 assert(display != (Display *) NULL);
9448 assert(windows != (XWindows *) NULL);
9449 if (state)
9450 {
9451 (void) XCheckDefineCursor(display,windows->image.id,
9452 windows->image.busy_cursor);
9453 (void) XCheckDefineCursor(display,windows->pan.id,
9454 windows->pan.busy_cursor);
9455 (void) XCheckDefineCursor(display,windows->magnify.id,
9456 windows->magnify.busy_cursor);
9457 (void) XCheckDefineCursor(display,windows->command.id,
9458 windows->command.busy_cursor);
9459 }
9460 else
9461 {
9462 (void) XCheckDefineCursor(display,windows->image.id,
9463 windows->image.cursor);
9464 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9465 (void) XCheckDefineCursor(display,windows->magnify.id,
9466 windows->magnify.cursor);
9467 (void) XCheckDefineCursor(display,windows->command.id,
9468 windows->command.cursor);
9469 (void) XCheckDefineCursor(display,windows->command.id,
9470 windows->widget.cursor);
9471 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9472 }
9473 windows->info.mapped=MagickFalse;
9474}
9475
9476/*
9477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9478% %
9479% %
9480% %
9481% X S e t W i n d o w s %
9482% %
9483% %
9484% %
9485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9486%
9487% XSetWindows() sets the X windows structure if the windows info is specified.
9488% Otherwise the current windows structure is returned.
9489%
9490% The format of the XSetWindows method is:
9491%
9492% XWindows *XSetWindows(XWindows *windows_info)
9493%
9494% A description of each parameter follows:
9495%
9496% o windows_info: Initialize the Windows structure with this information.
9497%
9498*/
cristybcbda3f2011-09-03 13:01:22 +00009499MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009500{
9501 static XWindows
9502 *windows = (XWindows *) NULL;
9503
9504 if (windows_info != (XWindows *) ~0)
9505 {
9506 windows=(XWindows *) RelinquishMagickMemory(windows);
9507 windows=windows_info;
9508 }
9509 return(windows);
9510}
9511/*
9512%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9513% %
9514% %
9515% %
9516% X U s e r P r e f e r e n c e s %
9517% %
9518% %
9519% %
9520%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9521%
9522% XUserPreferences() saves the preferences in a configuration file in the
9523% users' home directory.
9524%
9525% The format of the XUserPreferences method is:
9526%
9527% void XUserPreferences(XResourceInfo *resource_info)
9528%
9529% A description of each parameter follows:
9530%
9531% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9532%
9533*/
cristybcbda3f2011-09-03 13:01:22 +00009534MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009535{
9536#if defined(X11_PREFERENCES_PATH)
9537 char
9538 cache[MaxTextExtent],
9539 filename[MaxTextExtent],
9540 specifier[MaxTextExtent];
9541
9542 const char
cristy104cea82009-10-25 02:26:51 +00009543 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009544 *value;
9545
9546 XrmDatabase
9547 preferences_database;
9548
9549 /*
9550 Save user preferences to the client configuration file.
9551 */
9552 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009553 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009554 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009555 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009556 value=resource_info->backdrop ? "True" : "False";
9557 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009558 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009559 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9560 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009561 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009562 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009563 value=resource_info->confirm_exit ? "True" : "False";
9564 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009565 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009566 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009567 value=resource_info->confirm_edit ? "True" : "False";
9568 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009569 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009570 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009571 value=resource_info->display_warnings ? "True" : "False";
9572 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009573 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristycbda6112012-05-27 20:57:16 +00009574 value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9575 "True" : "False";
cristy3ed852e2009-09-05 21:47:34 +00009576 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009577 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009578 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009579 value=resource_info->gamma_correct ? "True" : "False";
9580 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009581 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9582 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009583 resource_info->undo_cache);
9584 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009585 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009586 value=resource_info->use_pixmap ? "True" : "False";
9587 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009588 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009589 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009590 ExpandFilename(filename);
9591 XrmPutFileDatabase(preferences_database,filename);
9592#endif
9593}
9594
9595/*
9596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9597% %
9598% %
9599% %
9600% X V i s u a l C l a s s N a m e %
9601% %
9602% %
9603% %
9604%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9605%
9606% XVisualClassName() returns the visual class name as a character string.
9607%
9608% The format of the XVisualClassName method is:
9609%
9610% char *XVisualClassName(const int visual_class)
9611%
9612% A description of each parameter follows:
9613%
9614% o visual_type: XVisualClassName returns the visual class as a character
9615% string.
9616%
9617% o class: Specifies the visual class.
9618%
cristy3ed852e2009-09-05 21:47:34 +00009619*/
9620static const char *XVisualClassName(const int visual_class)
9621{
9622 switch (visual_class)
9623 {
9624 case StaticGray: return("StaticGray");
9625 case GrayScale: return("GrayScale");
9626 case StaticColor: return("StaticColor");
9627 case PseudoColor: return("PseudoColor");
9628 case TrueColor: return("TrueColor");
9629 case DirectColor: return("DirectColor");
9630 }
9631 return("unknown visual class");
9632}
9633
9634/*
9635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9636% %
9637% %
9638% %
9639% X W a r n i n g %
9640% %
9641% %
9642% %
9643%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9644%
9645% XWarning() displays a warning reason in a Notice widget.
9646%
9647% The format of the XWarning method is:
9648%
9649% void XWarning(const unsigned int warning,const char *reason,
9650% const char *description)
9651%
9652% A description of each parameter follows:
9653%
9654% o warning: Specifies the numeric warning category.
9655%
9656% o reason: Specifies the reason to display before terminating the
9657% program.
9658%
9659% o description: Specifies any description to the reason.
9660%
9661*/
cristybcbda3f2011-09-03 13:01:22 +00009662MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009663 const char *reason,const char *description)
9664{
9665 char
9666 text[MaxTextExtent];
9667
9668 XWindows
9669 *windows;
9670
9671 if (reason == (char *) NULL)
9672 return;
9673 (void) CopyMagickString(text,reason,MaxTextExtent);
9674 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9675 windows=XSetWindows((XWindows *) ~0);
9676 XNoticeWidget(windows->display,windows,text,(char *) description);
9677}
9678
9679/*
9680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9681% %
9682% %
9683% %
9684% X W i n d o w B y I D %
9685% %
9686% %
9687% %
9688%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9689%
9690% XWindowByID() locates a child window with a given ID. If not window with
9691% the given name is found, 0 is returned. Only the window specified and its
9692% subwindows are searched.
9693%
9694% The format of the XWindowByID function is:
9695%
9696% child=XWindowByID(display,window,id)
9697%
9698% A description of each parameter follows:
9699%
9700% o child: XWindowByID returns the window with the specified
9701% id. If no windows are found, XWindowByID returns 0.
9702%
9703% o display: Specifies a pointer to the Display structure; returned from
9704% XOpenDisplay.
9705%
9706% o id: Specifies the id of the window to locate.
9707%
9708*/
cristybcbda3f2011-09-03 13:01:22 +00009709MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009710 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009711{
9712 RectangleInfo
9713 rectangle_info;
9714
9715 register int
9716 i;
9717
9718 Status
9719 status;
9720
9721 unsigned int
9722 number_children;
9723
9724 Window
9725 child,
9726 *children,
9727 window;
9728
9729 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9730 assert(display != (Display *) NULL);
9731 assert(root_window != (Window) NULL);
9732 if (id == 0)
9733 return(XSelectWindow(display,&rectangle_info));
9734 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009735 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009736 status=XQueryTree(display,root_window,&child,&child,&children,
9737 &number_children);
9738 if (status == False)
9739 return((Window) NULL);
9740 window=(Window) NULL;
9741 for (i=0; i < (int) number_children; i++)
9742 {
9743 /*
9744 Search each child and their children.
9745 */
9746 window=XWindowByID(display,children[i],id);
9747 if (window != (Window) NULL)
9748 break;
9749 }
9750 if (children != (Window *) NULL)
9751 (void) XFree((void *) children);
9752 return(window);
9753}
9754
9755/*
9756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9757% %
9758% %
9759% %
9760% X W i n d o w B y N a m e %
9761% %
9762% %
9763% %
9764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9765%
9766% XWindowByName() locates a window with a given name on a display. If no
9767% window with the given name is found, 0 is returned. If more than one window
9768% has the given name, the first one is returned. Only root and its children
9769% are searched.
9770%
9771% The format of the XWindowByName function is:
9772%
9773% window=XWindowByName(display,root_window,name)
9774%
9775% A description of each parameter follows:
9776%
9777% o window: XWindowByName returns the window id.
9778%
9779% o display: Specifies a pointer to the Display structure; returned from
9780% XOpenDisplay.
9781%
9782% o root_window: Specifies the id of the root window.
9783%
9784% o name: Specifies the name of the window to locate.
9785%
9786*/
cristybcbda3f2011-09-03 13:01:22 +00009787MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009788 const char *name)
9789{
9790 register int
9791 i;
9792
9793 Status
9794 status;
9795
9796 unsigned int
9797 number_children;
9798
9799 Window
9800 *children,
9801 child,
9802 window;
9803
9804 XTextProperty
9805 window_name;
9806
9807 assert(display != (Display *) NULL);
9808 assert(root_window != (Window) NULL);
9809 assert(name != (char *) NULL);
9810 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9811 if (XGetWMName(display,root_window,&window_name) != 0)
9812 if (LocaleCompare((char *) window_name.value,name) == 0)
9813 return(root_window);
9814 status=XQueryTree(display,root_window,&child,&child,&children,
9815 &number_children);
9816 if (status == False)
9817 return((Window) NULL);
9818 window=(Window) NULL;
9819 for (i=0; i < (int) number_children; i++)
9820 {
9821 /*
9822 Search each child and their children.
9823 */
9824 window=XWindowByName(display,children[i],name);
9825 if (window != (Window) NULL)
9826 break;
9827 }
9828 if (children != (Window *) NULL)
9829 (void) XFree((void *) children);
9830 return(window);
9831}
9832
9833/*
9834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9835% %
9836% %
9837% %
9838% X W i n d o w B y P r o p e r y %
9839% %
9840% %
9841% %
9842%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9843%
9844% XWindowByProperty() locates a child window with a given property. If not
9845% window with the given name is found, 0 is returned. If more than one window
9846% has the given property, the first one is returned. Only the window
9847% specified and its subwindows are searched.
9848%
9849% The format of the XWindowByProperty function is:
9850%
9851% child=XWindowByProperty(display,window,property)
9852%
9853% A description of each parameter follows:
9854%
9855% o child: XWindowByProperty returns the window id with the specified
9856% property. If no windows are found, XWindowByProperty returns 0.
9857%
9858% o display: Specifies a pointer to the Display structure; returned from
9859% XOpenDisplay.
9860%
9861% o property: Specifies the property of the window to locate.
9862%
9863*/
cristybcbda3f2011-09-03 13:01:22 +00009864MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009865 const Atom property)
9866{
9867 Atom
9868 type;
9869
9870 int
9871 format;
9872
9873 Status
9874 status;
9875
9876 unsigned char
9877 *data;
9878
9879 unsigned int
9880 i,
9881 number_children;
9882
cristyf2faecf2010-05-28 19:19:36 +00009883 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009884 after,
9885 number_items;
9886
9887 Window
9888 child,
9889 *children,
9890 parent,
9891 root;
9892
9893 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9894 assert(display != (Display *) NULL);
9895 assert(window != (Window) NULL);
9896 assert(property != (Atom) NULL);
9897 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9898 if (status == False)
9899 return((Window) NULL);
9900 type=(Atom) NULL;
9901 child=(Window) NULL;
9902 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9903 {
9904 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9905 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9906 if (data != NULL)
9907 (void) XFree((void *) data);
9908 if ((status == Success) && (type != (Atom) NULL))
9909 child=children[i];
9910 }
9911 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9912 child=XWindowByProperty(display,children[i],property);
9913 if (children != (Window *) NULL)
9914 (void) XFree((void *) children);
9915 return(child);
9916}
9917#else
9918
9919/*
9920%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9921% %
9922% %
9923% %
9924% X I m p o r t I m a g e %
9925% %
9926% %
9927% %
9928%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9929%
9930% XImportImage() reads an image from an X window.
9931%
9932% The format of the XImportImage method is:
9933%
cristya0dc96a2011-12-19 23:58:54 +00009934% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9935% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009936%
9937% A description of each parameter follows:
9938%
9939% o image_info: the image info..
9940%
9941% o ximage_info: Specifies a pointer to an XImportInfo structure.
9942%
cristya0dc96a2011-12-19 23:58:54 +00009943% o exception: return any errors or warnings in this structure.
9944%
cristy3ed852e2009-09-05 21:47:34 +00009945*/
cristy4bc52022012-12-13 14:15:41 +00009946MagickExport Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009947 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009948{
9949 assert(image_info != (const ImageInfo *) NULL);
9950 assert(image_info->signature == MagickSignature);
9951 if (image_info->debug != MagickFalse)
9952 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9953 image_info->filename);
9954 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009955 assert(exception != (ExceptionInfo *) NULL);
9956 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009957 return((Image *) NULL);
9958}
cristy534d0a32013-04-13 16:27:24 +00009959
9960/*
9961%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9962% %
9963% %
9964% %
9965% X R e n d e r X 1 1 %
9966% %
9967% %
9968% %
9969%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9970%
9971% XRenderImage() renders text on the image with an X11 font. It also returns
9972% the bounding box of the text relative to the image.
9973%
9974% The format of the XRenderImage method is:
9975%
9976% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
9977% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
9978%
9979% A description of each parameter follows:
9980%
9981% o image: the image.
9982%
9983% o draw_info: the draw info.
9984%
9985% o offset: (x,y) location of text relative to image.
9986%
9987% o metrics: bounding box of text.
9988%
9989% o exception: return any errors or warnings in this structure.
9990%
9991*/
9992MagickPrivate MagickBooleanType XRenderImage(Image *image,
9993 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
9994 ExceptionInfo *exception)
9995{
9996 (void) draw_info;
9997 (void) offset;
9998 (void) metrics;
9999 (void) ThrowMagickException(exception,GetMagickModule(),
10000 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","'%s' (X11)",
10001 image->filename);
10002 return(MagickFalse);
10003}
cristy3ed852e2009-09-05 21:47:34 +000010004#endif
10005
10006/*
10007%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10008% %
10009% %
10010% %
cristy576974e2009-10-25 20:45:31 +000010011+ X C o m p o n e n t G e n e s i s %
10012% %
10013% %
10014% %
10015%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10016%
10017% XComponentGenesis() instantiates the X component.
10018%
10019% The format of the XComponentGenesis method is:
10020%
10021% MagickBooleanType XComponentGenesis(void)
10022%
10023*/
cristy5ff4eaf2011-09-03 01:38:02 +000010024MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +000010025{
10026 return(MagickTrue);
10027}
10028
10029/*
10030%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10031% %
10032% %
10033% %
cristy3ed852e2009-09-05 21:47:34 +000010034% X G e t I m p o r t I n f o %
10035% %
10036% %
10037% %
10038%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10039%
10040% XGetImportInfo() initializes the XImportInfo structure.
10041%
10042% The format of the XGetImportInfo method is:
10043%
10044% void XGetImportInfo(XImportInfo *ximage_info)
10045%
10046% A description of each parameter follows:
10047%
10048% o ximage_info: Specifies a pointer to an ImageInfo structure.
10049%
10050*/
10051MagickExport void XGetImportInfo(XImportInfo *ximage_info)
10052{
10053 assert(ximage_info != (XImportInfo *) NULL);
10054 ximage_info->frame=MagickFalse;
10055 ximage_info->borders=MagickFalse;
10056 ximage_info->screen=MagickFalse;
10057 ximage_info->descend=MagickTrue;
10058 ximage_info->silent=MagickFalse;
10059}