blob: 95d8ba1f3c5a635327f6eeb6a9d0387078253d12 [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;
cristy9a7df362014-01-14 15:03:18 +00004437 if (red_mask != 0)
4438 color=(65535UL*color)/red_mask;
4439 SetPixelRed(composite_image,ScaleShortToQuantum(
4440 (unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004441 color=(pixel >> green_shift) & green_mask;
cristy9a7df362014-01-14 15:03:18 +00004442 if (green_mask != 0)
4443 color=(65535UL*color)/green_mask;
4444 SetPixelGreen(composite_image,ScaleShortToQuantum(
4445 (unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004446 color=(pixel >> blue_shift) & blue_mask;
cristy9a7df362014-01-14 15:03:18 +00004447 if (blue_mask != 0)
4448 color=(65535UL*color)/blue_mask;
4449 SetPixelBlue(composite_image,ScaleShortToQuantum(
4450 (unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004451 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004452 }
cristy0b1a7972011-10-22 22:17:02 +00004453 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4454 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004455 break;
4456 }
4457 break;
4458 }
4459 case PseudoClass:
4460 {
4461 /*
4462 Create colormap.
4463 */
cristy0b1a7972011-10-22 22:17:02 +00004464 status=AcquireImageColormap(composite_image,number_colors,
4465 exception);
4466 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004467 {
4468 XDestroyImage(ximage);
4469 composite_image=DestroyImage(composite_image);
4470 return((Image *) NULL);
4471 }
4472 for (i=0; i < (int) composite_image->colors; i++)
4473 {
cristye42f6582012-02-11 17:59:50 +00004474 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004475 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004476 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004477 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004478 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004479 ScaleShortToQuantum(colors[i].blue);
4480 }
4481 /*
4482 Convert X image to PseudoClass packets.
4483 */
4484 for (y=0; y < (int) composite_image->rows; y++)
4485 {
cristyc57f6942010-11-12 01:47:39 +00004486 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4487 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004488 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004489 break;
cristy3ed852e2009-09-05 21:47:34 +00004490 for (x=0; x < (int) composite_image->columns; x++)
4491 {
cristy4c08aed2011-07-01 19:47:50 +00004492 index=(Quantum) XGetPixel(ximage,x,y);
4493 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004494 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004495 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004496 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004497 }
cristy0b1a7972011-10-22 22:17:02 +00004498 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4499 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004500 break;
4501 }
4502 break;
4503 }
4504 }
cristyc57f6942010-11-12 01:47:39 +00004505 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004506 XDestroyImage(ximage);
4507 if (image == (Image *) NULL)
4508 {
4509 image=composite_image;
4510 continue;
4511 }
4512 /*
4513 Composite any children in back-to-front order.
4514 */
4515 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4516 &x_offset,&y_offset,&child);
4517 x_offset-=(int) crop_info.x;
4518 if (x_offset < 0)
4519 x_offset=0;
4520 y_offset-=(int) crop_info.y;
4521 if (y_offset < 0)
4522 y_offset=0;
cristy39172402012-03-30 13:04:39 +00004523 (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00004524 (ssize_t) x_offset,(ssize_t) y_offset,exception);
cristy5f257b22012-03-07 00:27:29 +00004525 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004526 }
4527 /*
4528 Relinquish resources.
4529 */
4530 while (colormap_info != (ColormapInfo *) NULL)
4531 {
4532 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004533 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4534 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004535 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4536 colormap_info=next;
4537 }
4538 /*
4539 Relinquish resources and restore initial state.
4540 */
4541 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4542 max_windows=0;
4543 number_windows=0;
4544 colormap_info=(ColormapInfo *) NULL;
4545 return(image);
4546 }
4547 return((Image *) NULL);
4548}
4549
4550/*
4551%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4552% %
4553% %
4554% %
4555% X G e t W i n d o w I n f o %
4556% %
4557% %
4558% %
4559%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4560%
4561% XGetWindowInfo() initializes the XWindowInfo structure.
4562%
4563% The format of the XGetWindowInfo method is:
4564%
4565% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4566% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4567% XResourceInfo *resource_info,XWindowInfo *window)
4568% resource_info,window)
4569%
4570% A description of each parameter follows:
4571%
4572% o display: Specifies a connection to an X server; returned from
4573% XOpenDisplay.
4574%
4575% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4576% returned from XGetVisualInfo.
4577%
4578% o map_info: If map_type is specified, this structure is initialized
4579% with info from the Standard Colormap.
4580%
4581% o pixel: Specifies a pointer to a XPixelInfo structure.
4582%
4583% o font_info: Specifies a pointer to a XFontStruct structure.
4584%
4585% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4586%
4587*/
cristybcbda3f2011-09-03 13:01:22 +00004588MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004589 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4590 XResourceInfo *resource_info,XWindowInfo *window)
4591{
4592 /*
4593 Initialize window info.
4594 */
4595 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4596 assert(display != (Display *) NULL);
4597 assert(visual_info != (XVisualInfo *) NULL);
4598 assert(map_info != (XStandardColormap *) NULL);
4599 assert(pixel != (XPixelInfo *) NULL);
4600 assert(resource_info != (XResourceInfo *) NULL);
4601 assert(window != (XWindowInfo *) NULL);
4602 if (window->id != (Window) NULL)
4603 {
4604 if (window->cursor != (Cursor) NULL)
4605 (void) XFreeCursor(display,window->cursor);
4606 if (window->busy_cursor != (Cursor) NULL)
4607 (void) XFreeCursor(display,window->busy_cursor);
4608 if (window->highlight_stipple != (Pixmap) NULL)
4609 (void) XFreePixmap(display,window->highlight_stipple);
4610 if (window->shadow_stipple != (Pixmap) NULL)
4611 (void) XFreePixmap(display,window->shadow_stipple);
4612 if (window->name == (char *) NULL)
4613 window->name=AcquireString("");
4614 if (window->icon_name == (char *) NULL)
4615 window->icon_name=AcquireString("");
4616 }
4617 else
4618 {
4619 /*
4620 Initialize these attributes just once.
4621 */
4622 window->id=(Window) NULL;
4623 if (window->name == (char *) NULL)
4624 window->name=AcquireString("");
4625 if (window->icon_name == (char *) NULL)
4626 window->icon_name=AcquireString("");
4627 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4628 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4629 window->ximage=(XImage *) NULL;
4630 window->matte_image=(XImage *) NULL;
4631 window->pixmap=(Pixmap) NULL;
4632 window->matte_pixmap=(Pixmap) NULL;
4633 window->mapped=MagickFalse;
4634 window->stasis=MagickFalse;
4635 window->shared_memory=MagickTrue;
4636 window->segment_info=(void *) NULL;
4637#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4638 {
4639 XShmSegmentInfo
4640 *segment_info;
4641
4642 if (window->segment_info == (void *) NULL)
4643 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4644 segment_info=(XShmSegmentInfo *) window->segment_info;
4645 segment_info[0].shmid=(-1);
4646 segment_info[0].shmaddr=(char *) NULL;
4647 segment_info[1].shmid=(-1);
4648 segment_info[1].shmaddr=(char *) NULL;
4649 }
4650#endif
4651 }
4652 /*
4653 Initialize these attributes every time function is called.
4654 */
4655 window->screen=visual_info->screen;
4656 window->root=XRootWindow(display,visual_info->screen);
4657 window->visual=visual_info->visual;
4658 window->storage_class=(unsigned int) visual_info->klass;
4659 window->depth=(unsigned int) visual_info->depth;
4660 window->visual_info=visual_info;
4661 window->map_info=map_info;
4662 window->pixel_info=pixel;
4663 window->font_info=font_info;
4664 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4665 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4666 window->geometry=(char *) NULL;
4667 window->icon_geometry=(char *) NULL;
4668 if (resource_info->icon_geometry != (char *) NULL)
4669 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4670 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004671 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004672 window->width=1;
4673 window->height=1;
4674 window->min_width=1;
4675 window->min_height=1;
4676 window->width_inc=1;
4677 window->height_inc=1;
4678 window->border_width=resource_info->border_width;
4679 window->annotate_context=pixel->annotate_context;
4680 window->highlight_context=pixel->highlight_context;
4681 window->widget_context=pixel->widget_context;
4682 window->shadow_stipple=(Pixmap) NULL;
4683 window->highlight_stipple=(Pixmap) NULL;
4684 window->use_pixmap=MagickTrue;
4685 window->immutable=MagickFalse;
4686 window->shape=MagickFalse;
4687 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004688 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004689 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4690 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4691 window->attributes.background_pixel=pixel->background_color.pixel;
4692 window->attributes.background_pixmap=(Pixmap) NULL;
4693 window->attributes.bit_gravity=ForgetGravity;
4694 window->attributes.backing_store=WhenMapped;
4695 window->attributes.save_under=MagickTrue;
4696 window->attributes.border_pixel=pixel->border_color.pixel;
4697 window->attributes.colormap=map_info->colormap;
4698 window->attributes.cursor=window->cursor;
4699 window->attributes.do_not_propagate_mask=NoEventMask;
4700 window->attributes.event_mask=NoEventMask;
4701 window->attributes.override_redirect=MagickFalse;
4702 window->attributes.win_gravity=NorthWestGravity;
4703 window->orphan=MagickFalse;
4704}
4705
4706/*
4707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4708% %
4709% %
4710% %
4711% X H i g h l i g h t E l l i p s e %
4712% %
4713% %
4714% %
4715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4716%
4717% XHighlightEllipse() puts a border on the X server around a region defined by
4718% highlight_info.
4719%
4720% The format of the XHighlightEllipse method is:
4721%
4722% void XHighlightEllipse(Display *display,Window window,
4723% GC annotate_context,const RectangleInfo *highlight_info)
4724%
4725% A description of each parameter follows:
4726%
4727% o display: Specifies a connection to an X server; returned from
4728% XOpenDisplay.
4729%
4730% o window: Specifies a pointer to a Window structure.
4731%
4732% o annotate_context: Specifies a pointer to a GC structure.
4733%
4734% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4735% contains the extents of any highlighting rectangle.
4736%
4737*/
cristybcbda3f2011-09-03 13:01:22 +00004738MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004739 GC annotate_context,const RectangleInfo *highlight_info)
4740{
4741 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4742 assert(display != (Display *) NULL);
4743 assert(window != (Window) NULL);
4744 assert(annotate_context != (GC) NULL);
4745 assert(highlight_info != (RectangleInfo *) NULL);
4746 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4747 return;
4748 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4749 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4750 (unsigned int) highlight_info->height-1,0,360*64);
4751 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4752 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4753 (unsigned int) highlight_info->height-3,0,360*64);
4754}
4755
4756/*
4757%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4758% %
4759% %
4760% %
4761% X H i g h l i g h t L i n e %
4762% %
4763% %
4764% %
4765%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4766%
4767% XHighlightLine() puts a border on the X server around a region defined by
4768% highlight_info.
4769%
4770% The format of the XHighlightLine method is:
4771%
4772% void XHighlightLine(Display *display,Window window,GC annotate_context,
4773% const XSegment *highlight_info)
4774%
4775% A description of each parameter follows:
4776%
4777% o display: Specifies a connection to an X server; returned from
4778% XOpenDisplay.
4779%
4780% o window: Specifies a pointer to a Window structure.
4781%
4782% o annotate_context: Specifies a pointer to a GC structure.
4783%
4784% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4785% contains the extents of any highlighting rectangle.
4786%
4787*/
cristybcbda3f2011-09-03 13:01:22 +00004788MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004789 GC annotate_context,const XSegment *highlight_info)
4790{
4791 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4792 assert(display != (Display *) NULL);
4793 assert(window != (Window) NULL);
4794 assert(annotate_context != (GC) NULL);
4795 assert(highlight_info != (XSegment *) NULL);
4796 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4797 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4798}
4799
4800/*
4801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4802% %
4803% %
4804% %
4805% X H i g h l i g h t R e c t a n g l e %
4806% %
4807% %
4808% %
4809%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4810%
4811% XHighlightRectangle() puts a border on the X server around a region defined
4812% by highlight_info.
4813%
4814% The format of the XHighlightRectangle method is:
4815%
4816% void XHighlightRectangle(Display *display,Window window,
4817% GC annotate_context,const RectangleInfo *highlight_info)
4818%
4819% A description of each parameter follows:
4820%
4821% o display: Specifies a connection to an X server; returned from
4822% XOpenDisplay.
4823%
4824% o window: Specifies a pointer to a Window structure.
4825%
4826% o annotate_context: Specifies a pointer to a GC structure.
4827%
4828% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4829% contains the extents of any highlighting rectangle.
4830%
4831*/
cristybcbda3f2011-09-03 13:01:22 +00004832MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004833 GC annotate_context,const RectangleInfo *highlight_info)
4834{
4835 assert(display != (Display *) NULL);
4836 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4837 assert(window != (Window) NULL);
4838 assert(annotate_context != (GC) NULL);
4839 assert(highlight_info != (RectangleInfo *) NULL);
4840 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4841 return;
4842 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4843 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4844 (unsigned int) highlight_info->height-1);
4845 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4846 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4847 (unsigned int) highlight_info->height-3);
4848}
4849
4850/*
4851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4852% %
4853% %
4854% %
4855% X I m p o r t I m a g e %
4856% %
4857% %
4858% %
4859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4860%
4861% XImportImage() reads an image from an X window.
4862%
4863% The format of the XImportImage method is:
4864%
cristy6710d842011-10-20 23:23:00 +00004865% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4866% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004867%
4868% A description of each parameter follows:
4869%
4870% o image_info: the image info.
4871%
4872% o ximage_info: Specifies a pointer to an XImportInfo structure.
4873%
cristy6710d842011-10-20 23:23:00 +00004874% o exception: return any errors or warnings in this structure.
4875%
cristy3ed852e2009-09-05 21:47:34 +00004876*/
4877MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004878 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004879{
4880 Colormap
4881 *colormaps;
4882
4883 Display
4884 *display;
4885
4886 Image
4887 *image;
4888
4889 int
4890 number_colormaps,
4891 number_windows,
4892 x;
4893
4894 RectangleInfo
4895 crop_info;
4896
4897 Status
4898 status;
4899
4900 Window
4901 *children,
4902 client,
4903 prior_target,
4904 root,
4905 target;
4906
4907 XTextProperty
4908 window_name;
4909
4910 /*
4911 Open X server connection.
4912 */
4913 assert(image_info != (const ImageInfo *) NULL);
4914 assert(image_info->signature == MagickSignature);
4915 if (image_info->debug != MagickFalse)
4916 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4917 image_info->filename);
4918 assert(ximage_info != (XImportInfo *) NULL);
4919 display=XOpenDisplay(image_info->server_name);
4920 if (display == (Display *) NULL)
4921 {
cristyc38fbf52013-11-03 13:55:54 +00004922 ThrowXWindowException(XServerError,"UnableToOpenXServer",
cristy3ed852e2009-09-05 21:47:34 +00004923 XDisplayName(image_info->server_name));
4924 return((Image *) NULL);
4925 }
4926 /*
4927 Set our forgiving exception handler.
4928 */
4929 (void) XSetErrorHandler(XError);
4930 /*
4931 Select target window.
4932 */
4933 crop_info.x=0;
4934 crop_info.y=0;
4935 crop_info.width=0;
4936 crop_info.height=0;
4937 root=XRootWindow(display,XDefaultScreen(display));
4938 target=(Window) NULL;
4939 if ((image_info->filename != (char *) NULL) &&
4940 (*image_info->filename != '\0'))
4941 {
4942 if (LocaleCompare(image_info->filename,"root") == 0)
4943 target=root;
4944 else
4945 {
4946 /*
4947 Select window by ID or name.
4948 */
cristy02e64f82013-11-14 16:20:04 +00004949 if (isdigit((int) ((unsigned char) *image_info->filename)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00004950 target=XWindowByID(display,root,(Window)
4951 strtol(image_info->filename,(char **) NULL,0));
4952 if (target == (Window) NULL)
4953 target=XWindowByName(display,root,image_info->filename);
4954 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004955 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
4956 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00004957 }
4958 }
4959 /*
4960 If target window is not defined, interactively select one.
4961 */
4962 prior_target=target;
4963 if (target == (Window) NULL)
4964 target=XSelectWindow(display,&crop_info);
4965 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004966 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00004967 image_info->filename);
4968 client=target; /* obsolete */
4969 if (target != root)
4970 {
4971 unsigned int
4972 d;
4973
4974 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4975 if (status != False)
4976 {
4977 for ( ; ; )
4978 {
4979 Window
4980 parent;
4981
4982 /*
4983 Find window manager frame.
4984 */
4985 status=XQueryTree(display,target,&root,&parent,&children,&d);
4986 if ((status != False) && (children != (Window *) NULL))
4987 (void) XFree((char *) children);
4988 if ((status == False) || (parent == (Window) NULL) ||
4989 (parent == root))
4990 break;
4991 target=parent;
4992 }
4993 /*
4994 Get client window.
4995 */
4996 client=XClientWindow(display,target);
4997 if (ximage_info->frame == MagickFalse)
4998 target=client;
4999 if ((ximage_info->frame == MagickFalse) &&
5000 (prior_target != MagickFalse))
5001 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00005002 }
5003 }
5004 if (ximage_info->screen)
5005 {
5006 int
5007 y;
5008
5009 Window
5010 child;
5011
5012 XWindowAttributes
5013 window_attributes;
5014
5015 /*
5016 Obtain window image directly from screen.
5017 */
5018 status=XGetWindowAttributes(display,target,&window_attributes);
5019 if (status == False)
5020 {
cristyc38fbf52013-11-03 13:55:54 +00005021 ThrowXWindowException(XServerError,"UnableToReadXWindowAttributes",
5022 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00005023 (void) XCloseDisplay(display);
5024 return((Image *) NULL);
5025 }
5026 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005027 crop_info.x=(ssize_t) x;
5028 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005029 crop_info.width=(size_t) window_attributes.width;
5030 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005031 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005032 {
5033 /*
5034 Include border in image.
5035 */
5036 crop_info.x-=window_attributes.border_width;
5037 crop_info.y-=window_attributes.border_width;
5038 crop_info.width+=window_attributes.border_width << 1;
5039 crop_info.height+=window_attributes.border_width << 1;
5040 }
5041 target=root;
5042 }
5043 /*
5044 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5045 */
5046 number_windows=0;
5047 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5048 if ((status == True) && (number_windows > 0))
5049 {
5050 ximage_info->descend=MagickTrue;
5051 (void) XFree ((char *) children);
5052 }
5053 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5054 if (number_colormaps > 0)
5055 {
5056 if (number_colormaps > 1)
5057 ximage_info->descend=MagickTrue;
5058 (void) XFree((char *) colormaps);
5059 }
5060 /*
5061 Alert the user not to alter the screen.
5062 */
5063 if (ximage_info->silent == MagickFalse)
5064 (void) XBell(display,0);
5065 /*
5066 Get image by window id.
5067 */
5068 (void) XGrabServer(display);
5069 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005070 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005071 (void) XUngrabServer(display);
5072 if (image == (Image *) NULL)
cristyc38fbf52013-11-03 13:55:54 +00005073 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00005074 image_info->filename)
5075 else
5076 {
5077 (void) CopyMagickString(image->filename,image_info->filename,
5078 MaxTextExtent);
5079 if ((crop_info.width != 0) && (crop_info.height != 0))
5080 {
5081 Image
5082 *clone_image,
5083 *crop_image;
5084
5085 /*
5086 Crop image as defined by the cropping rectangle.
5087 */
cristy6710d842011-10-20 23:23:00 +00005088 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005089 if (clone_image != (Image *) NULL)
5090 {
cristy6710d842011-10-20 23:23:00 +00005091 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005092 if (crop_image != (Image *) NULL)
5093 {
5094 image=DestroyImage(image);
5095 image=crop_image;
5096 }
5097 }
5098 }
5099 status=XGetWMName(display,target,&window_name);
5100 if (status == True)
5101 {
5102 if ((image_info->filename != (char *) NULL) &&
5103 (*image_info->filename == '\0'))
5104 (void) CopyMagickString(image->filename,(char *) window_name.value,
5105 (size_t) window_name.nitems+1);
5106 (void) XFree((void *) window_name.value);
5107 }
5108 }
5109 if (ximage_info->silent == MagickFalse)
5110 {
5111 /*
5112 Alert the user we're done.
5113 */
5114 (void) XBell(display,0);
5115 (void) XBell(display,0);
5116 }
5117 (void) XCloseDisplay(display);
5118 return(image);
5119}
5120
5121/*
5122%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5123% %
5124% %
5125% %
5126% X I n i t i a l i z e W i n d o w s %
5127% %
5128% %
5129% %
5130%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5131%
5132% XInitializeWindows() initializes the XWindows structure.
5133%
5134% The format of the XInitializeWindows method is:
5135%
5136% XWindows *XInitializeWindows(Display *display,
5137% XResourceInfo *resource_info)
5138%
5139% A description of each parameter follows:
5140%
5141% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5142%
5143% o display: Specifies a connection to an X server; returned from
5144% XOpenDisplay.
5145%
5146% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5147%
5148*/
cristybcbda3f2011-09-03 13:01:22 +00005149MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005150 XResourceInfo *resource_info)
5151{
5152 Window
5153 root_window;
5154
5155 XWindows
5156 *windows;
5157
5158 /*
5159 Allocate windows structure.
5160 */
cristy73bd4a52010-10-05 11:24:23 +00005161 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005162 if (windows == (XWindows *) NULL)
5163 {
5164 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5165 "...");
5166 return((XWindows *) NULL);
5167 }
5168 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5169 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5170 sizeof(*windows->pixel_info));
5171 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5172 sizeof(*windows->icon_pixel));
5173 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5174 sizeof(*windows->icon_resources));
5175 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5176 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5177 (windows->icon_resources == (XResourceInfo *) NULL))
5178 {
5179 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5180 "...");
5181 return((XWindows *) NULL);
5182 }
5183 /*
5184 Initialize windows structure.
5185 */
5186 windows->display=display;
5187 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5188 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5189 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5190 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5191 windows->im_remote_command=
5192 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5193 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5194 windows->im_update_colormap=
5195 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5196 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5197 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5198 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5199 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5200 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005201#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005202 (void) XSynchronize(display,IsWindows95());
5203#endif
5204 if (IsEventLogging())
5205 {
5206 (void) XSynchronize(display,MagickTrue);
5207 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005208 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005209 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5210 (void) LogMagickEvent(X11Event,GetMagickModule(),
5211 " Window Manager: 0x%lx",windows->wm_protocols);
5212 (void) LogMagickEvent(X11Event,GetMagickModule(),
5213 " delete window: 0x%lx",windows->wm_delete_window);
5214 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5215 windows->wm_take_focus);
5216 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5217 windows->im_protocols);
5218 (void) LogMagickEvent(X11Event,GetMagickModule(),
5219 " remote command: 0x%lx",windows->im_remote_command);
5220 (void) LogMagickEvent(X11Event,GetMagickModule(),
5221 " update widget: 0x%lx",windows->im_update_widget);
5222 (void) LogMagickEvent(X11Event,GetMagickModule(),
5223 " update colormap: 0x%lx",windows->im_update_colormap);
5224 (void) LogMagickEvent(X11Event,GetMagickModule(),
5225 " former image: 0x%lx",windows->im_former_image);
5226 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5227 windows->im_next_image);
5228 (void) LogMagickEvent(X11Event,GetMagickModule(),
5229 " retain colors: 0x%lx",windows->im_retain_colors);
5230 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5231 windows->im_exit);
5232 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5233 windows->dnd_protocols);
5234 }
5235 /*
5236 Allocate standard colormap.
5237 */
5238 windows->map_info=XAllocStandardColormap();
5239 windows->icon_map=XAllocStandardColormap();
5240 if ((windows->map_info == (XStandardColormap *) NULL) ||
5241 (windows->icon_map == (XStandardColormap *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005242 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5243 "...");
cristy3ed852e2009-09-05 21:47:34 +00005244 windows->map_info->colormap=(Colormap) NULL;
5245 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005246 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005247 windows->pixel_info->annotate_context=(GC) NULL;
5248 windows->pixel_info->highlight_context=(GC) NULL;
5249 windows->pixel_info->widget_context=(GC) NULL;
5250 windows->font_info=(XFontStruct *) NULL;
5251 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005252 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005253 /*
5254 Allocate visual.
5255 */
5256 *windows->icon_resources=(*resource_info);
5257 windows->icon_resources->visual_type=(char *) "default";
5258 windows->icon_resources->colormap=SharedColormap;
5259 windows->visual_info=
5260 XBestVisualInfo(display,windows->map_info,resource_info);
5261 windows->icon_visual=
5262 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5263 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5264 (windows->icon_visual == (XVisualInfo *) NULL))
5265 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5266 resource_info->visual_type);
5267 if (IsEventLogging())
5268 {
5269 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5270 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5271 windows->visual_info->visualid);
5272 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5273 XVisualClassName(windows->visual_info->klass));
5274 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5275 windows->visual_info->depth);
5276 (void) LogMagickEvent(X11Event,GetMagickModule(),
5277 " size of colormap: %d entries",windows->visual_info->colormap_size);
5278 (void) LogMagickEvent(X11Event,GetMagickModule(),
5279 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5280 windows->visual_info->red_mask,windows->visual_info->green_mask,
5281 windows->visual_info->blue_mask);
5282 (void) LogMagickEvent(X11Event,GetMagickModule(),
5283 " significant bits in color: %d bits",
5284 windows->visual_info->bits_per_rgb);
5285 }
5286 /*
5287 Allocate class and manager hints.
5288 */
5289 windows->class_hints=XAllocClassHint();
5290 windows->manager_hints=XAllocWMHints();
5291 if ((windows->class_hints == (XClassHint *) NULL) ||
5292 (windows->manager_hints == (XWMHints *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005293 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5294 "...");
cristy3ed852e2009-09-05 21:47:34 +00005295 /*
5296 Determine group leader if we have one.
5297 */
5298 root_window=XRootWindow(display,windows->visual_info->screen);
5299 windows->group_leader.id=(Window) NULL;
5300 if (resource_info->window_group != (char *) NULL)
5301 {
cristy02e64f82013-11-14 16:20:04 +00005302 if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00005303 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5304 strtol((char *) resource_info->window_group,(char **) NULL,0));
5305 if (windows->group_leader.id == (Window) NULL)
5306 windows->group_leader.id=
5307 XWindowByName(display,root_window,resource_info->window_group);
5308 }
5309 return(windows);
5310}
5311
5312/*
5313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5314% %
5315% %
5316% %
5317% X M a k e C u r s o r %
5318% %
5319% %
5320% %
5321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5322%
5323% XMakeCursor() creates a crosshairs X11 cursor.
5324%
5325% The format of the XMakeCursor method is:
5326%
5327% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5328% char *background_color,char *foreground_color)
5329%
5330% A description of each parameter follows:
5331%
5332% o display: Specifies a connection to an X server; returned from
5333% XOpenDisplay.
5334%
5335% o window: Specifies the ID of the window for which the cursor is
5336% assigned.
5337%
5338% o colormap: Specifies the ID of the colormap from which the background
5339% and foreground color will be retrieved.
5340%
5341% o background_color: Specifies the color to use for the cursor background.
5342%
5343% o foreground_color: Specifies the color to use for the cursor foreground.
5344%
5345*/
cristybcbda3f2011-09-03 13:01:22 +00005346MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005347 Colormap colormap,char *background_color,char *foreground_color)
5348{
5349#define scope_height 17
5350#define scope_x_hot 8
5351#define scope_y_hot 8
5352#define scope_width 17
5353
5354 static const unsigned char
5355 scope_bits[] =
5356 {
5357 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5358 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5359 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5360 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5361 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5362 },
5363 scope_mask_bits[] =
5364 {
5365 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5366 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5367 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5368 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5369 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5370 };
5371
5372 Cursor
5373 cursor;
5374
5375 Pixmap
5376 mask,
5377 source;
5378
5379 XColor
5380 background,
5381 foreground;
5382
5383 assert(display != (Display *) NULL);
5384 assert(window != (Window) NULL);
5385 assert(colormap != (Colormap) NULL);
5386 assert(background_color != (char *) NULL);
5387 assert(foreground_color != (char *) NULL);
5388 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5389 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5390 scope_height);
5391 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5392 scope_width,scope_height);
5393 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5394 {
cristyc38fbf52013-11-03 13:55:54 +00005395 ThrowXWindowException(XServerError,"UnableToCreatePixmap","...");
cristy3ed852e2009-09-05 21:47:34 +00005396 return((Cursor) NULL);
5397 }
5398 (void) XParseColor(display,colormap,background_color,&background);
5399 (void) XParseColor(display,colormap,foreground_color,&foreground);
5400 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5401 scope_x_hot,scope_y_hot);
5402 (void) XFreePixmap(display,source);
5403 (void) XFreePixmap(display,mask);
5404 return(cursor);
5405}
5406
5407/*
5408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5409% %
5410% %
5411% %
5412% X M a k e I m a g e %
5413% %
5414% %
5415% %
5416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5417%
5418% XMakeImage() creates an X11 image. If the image size differs from the X11
5419% image size, the image is first resized.
5420%
5421% The format of the XMakeImage method is:
5422%
5423% MagickBooleanType XMakeImage(Display *display,
5424% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005425% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005426%
5427% A description of each parameter follows:
5428%
5429% o display: Specifies a connection to an X server; returned from
5430% XOpenDisplay.
5431%
5432% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5433%
5434% o window: Specifies a pointer to a XWindowInfo structure.
5435%
5436% o image: the image.
5437%
5438% o width: Specifies the width in pixels of the rectangular area to
5439% display.
5440%
5441% o height: Specifies the height in pixels of the rectangular area to
5442% display.
5443%
cristy051718b2011-08-28 22:49:25 +00005444% o exception: return any errors or warnings in this structure.
5445%
cristy3ed852e2009-09-05 21:47:34 +00005446*/
cristybcbda3f2011-09-03 13:01:22 +00005447MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005448 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005449 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005450{
5451#define CheckOverflowException(length,width,height) \
5452 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5453
5454 int
5455 depth,
5456 format;
5457
5458 size_t
5459 length;
5460
5461 XImage
5462 *matte_image,
5463 *ximage;
5464
5465 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5466 assert(display != (Display *) NULL);
5467 assert(resource_info != (XResourceInfo *) NULL);
5468 assert(window != (XWindowInfo *) NULL);
5469 assert(width != 0);
5470 assert(height != 0);
5471 if ((window->width == 0) || (window->height == 0))
5472 return(MagickFalse);
5473 /*
5474 Apply user transforms to the image.
5475 */
5476 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5477 (void) XFlush(display);
5478 depth=(int) window->depth;
5479 if (window->destroy)
5480 window->image=DestroyImage(window->image);
5481 window->image=image;
5482 window->destroy=MagickFalse;
5483 if (window->image != (Image *) NULL)
5484 {
5485 if (window->crop_geometry != (char *) NULL)
5486 {
5487 Image
5488 *crop_image;
5489
5490 RectangleInfo
5491 crop_info;
5492
5493 /*
5494 Crop image.
5495 */
5496 window->image->page.x=0;
5497 window->image->page.y=0;
5498 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005499 &crop_info,exception);
5500 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005501 if (crop_image != (Image *) NULL)
5502 {
5503 if (window->image != image)
5504 window->image=DestroyImage(window->image);
5505 window->image=crop_image;
5506 window->destroy=MagickTrue;
5507 }
5508 }
5509 if ((width != (unsigned int) window->image->columns) ||
5510 (height != (unsigned int) window->image->rows))
5511 {
5512 Image
5513 *resize_image;
5514
5515 /*
5516 Resize image.
5517 */
5518 resize_image=NewImageList();
cristy865489b2013-10-12 01:03:29 +00005519 if ((window->pixel_info->colors == 0) &&
5520 (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5521 (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5522 resize_image=ResizeImage(window->image,width,height,
5523 image->filter,exception);
cristy3ed852e2009-09-05 21:47:34 +00005524 else
cristy865489b2013-10-12 01:03:29 +00005525 {
5526 if (window->image->storage_class == PseudoClass)
5527 resize_image=SampleImage(window->image,width,height,
5528 exception);
5529 else
5530 resize_image=ThumbnailImage(window->image,width,height,
5531 exception);
5532 }
cristy3ed852e2009-09-05 21:47:34 +00005533 if (resize_image != (Image *) NULL)
5534 {
5535 if (window->image != image)
5536 window->image=DestroyImage(window->image);
5537 window->image=resize_image;
5538 window->destroy=MagickTrue;
5539 }
5540 }
5541 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005542 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005543 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005544 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005545 }
5546 /*
5547 Create X image.
5548 */
5549 ximage=(XImage *) NULL;
5550 format=(depth == 1) ? XYBitmap : ZPixmap;
5551#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5552 if (window->shared_memory != MagickFalse)
5553 {
5554 XShmSegmentInfo
5555 *segment_info;
5556
5557 segment_info=(XShmSegmentInfo *) window->segment_info;
5558 segment_info[1].shmid=(-1);
5559 segment_info[1].shmaddr=(char *) NULL;
5560 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5561 (char *) NULL,&segment_info[1],width,height);
5562 if (ximage == (XImage *) NULL)
5563 window->shared_memory=MagickFalse;
5564 length=(size_t) ximage->bytes_per_line*ximage->height;
5565 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5566 window->shared_memory=MagickFalse;
5567 if (window->shared_memory != MagickFalse)
5568 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5569 if (window->shared_memory != MagickFalse)
5570 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5571 if (segment_info[1].shmid < 0)
5572 window->shared_memory=MagickFalse;
5573 if (window->shared_memory != MagickFalse)
5574 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5575 else
5576 {
5577 if (ximage != (XImage *) NULL)
5578 XDestroyImage(ximage);
5579 ximage=(XImage *) NULL;
5580 if (segment_info[1].shmaddr)
5581 {
5582 (void) shmdt(segment_info[1].shmaddr);
5583 segment_info[1].shmaddr=(char *) NULL;
5584 }
5585 if (segment_info[1].shmid >= 0)
5586 {
5587 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5588 segment_info[1].shmid=(-1);
5589 }
5590 }
5591 }
5592#endif
5593 /*
5594 Allocate X image pixel data.
5595 */
5596#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5597 if (window->shared_memory)
5598 {
5599 Status
5600 status;
5601
5602 XShmSegmentInfo
5603 *segment_info;
5604
5605 (void) XSync(display,MagickFalse);
5606 xerror_alert=MagickFalse;
5607 segment_info=(XShmSegmentInfo *) window->segment_info;
5608 ximage->data=segment_info[1].shmaddr;
5609 segment_info[1].readOnly=MagickFalse;
5610 status=XShmAttach(display,&segment_info[1]);
5611 if (status != False)
5612 (void) XSync(display,MagickFalse);
5613 if ((status == False) || (xerror_alert != MagickFalse))
5614 {
5615 window->shared_memory=MagickFalse;
5616 if (status != False)
5617 XShmDetach(display,&segment_info[1]);
5618 if (ximage != (XImage *) NULL)
5619 {
5620 ximage->data=NULL;
5621 XDestroyImage(ximage);
5622 ximage=(XImage *) NULL;
5623 }
5624 if (segment_info[1].shmid >= 0)
5625 {
5626 if (segment_info[1].shmaddr != NULL)
5627 (void) shmdt(segment_info[1].shmaddr);
5628 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5629 segment_info[1].shmid=(-1);
5630 segment_info[1].shmaddr=(char *) NULL;
5631 }
5632 }
5633 }
5634#endif
5635 if (window->shared_memory == MagickFalse)
5636 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5637 (char *) NULL,width,height,XBitmapPad(display),0);
5638 if (ximage == (XImage *) NULL)
5639 {
5640 /*
5641 Unable to create X image.
5642 */
5643 (void) XCheckDefineCursor(display,window->id,window->cursor);
5644 return(MagickFalse);
5645 }
5646 length=(size_t) ximage->bytes_per_line*ximage->height;
5647 if (IsEventLogging())
5648 {
5649 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5650 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5651 ximage->width,ximage->height);
5652 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5653 ximage->format);
5654 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5655 ximage->byte_order);
5656 (void) LogMagickEvent(X11Event,GetMagickModule(),
5657 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5658 ximage->bitmap_bit_order,ximage->bitmap_pad);
5659 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5660 ximage->depth);
5661 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5662 ximage->bytes_per_line);
5663 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5664 ximage->bits_per_pixel);
5665 (void) LogMagickEvent(X11Event,GetMagickModule(),
5666 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5667 ximage->green_mask,ximage->blue_mask);
5668 }
5669 if (window->shared_memory == MagickFalse)
5670 {
5671 if (ximage->format != XYBitmap)
cristy9aecad62013-04-18 10:37:47 +00005672 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5673 ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005674 else
cristy9aecad62013-04-18 10:37:47 +00005675 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5676 ximage->depth*ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005677 }
5678 if (ximage->data == (char *) NULL)
5679 {
5680 /*
5681 Unable to allocate pixel data.
5682 */
5683 XDestroyImage(ximage);
5684 ximage=(XImage *) NULL;
5685 (void) XCheckDefineCursor(display,window->id,window->cursor);
5686 return(MagickFalse);
5687 }
5688 if (window->ximage != (XImage *) NULL)
5689 {
5690 /*
5691 Destroy previous X image.
5692 */
5693 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5694#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5695 if (window->segment_info != (XShmSegmentInfo *) NULL)
5696 {
5697 XShmSegmentInfo
5698 *segment_info;
5699
5700 segment_info=(XShmSegmentInfo *) window->segment_info;
5701 if (segment_info[0].shmid >= 0)
5702 {
5703 (void) XSync(display,MagickFalse);
5704 (void) XShmDetach(display,&segment_info[0]);
5705 (void) XSync(display,MagickFalse);
5706 if (segment_info[0].shmaddr != (char *) NULL)
5707 (void) shmdt(segment_info[0].shmaddr);
5708 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5709 segment_info[0].shmid=(-1);
5710 segment_info[0].shmaddr=(char *) NULL;
5711 window->ximage->data=(char *) NULL;
5712 }
5713 }
5714#endif
5715 if (window->ximage->data != (char *) NULL)
5716 free(window->ximage->data);
5717 window->ximage->data=(char *) NULL;
5718 XDestroyImage(window->ximage);
5719 window->ximage=(XImage *) NULL;
5720 }
5721#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5722 if (window->segment_info != (XShmSegmentInfo *) NULL)
5723 {
5724 XShmSegmentInfo
5725 *segment_info;
5726
5727 segment_info=(XShmSegmentInfo *) window->segment_info;
5728 segment_info[0]=segment_info[1];
5729 }
5730#endif
5731 window->ximage=ximage;
5732 matte_image=(XImage *) NULL;
5733 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
cristy8a46d822012-08-28 23:32:39 +00005734 if ((window->image->alpha_trait == BlendPixelTrait) &&
cristyc57f6942010-11-12 01:47:39 +00005735 ((int) width <= XDisplayWidth(display,window->screen)) &&
5736 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005737 {
5738 /*
5739 Create matte image.
5740 */
5741 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5742 (char *) NULL,width,height,XBitmapPad(display),0);
5743 if (IsEventLogging())
5744 {
5745 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5746 (void) LogMagickEvent(X11Event,GetMagickModule(),
5747 " width, height: %dx%d",matte_image->width,matte_image->height);
5748 }
5749 if (matte_image != (XImage *) NULL)
5750 {
5751 /*
5752 Allocate matte image pixel data.
5753 */
cristy9aecad62013-04-18 10:37:47 +00005754 matte_image->data=(char *) malloc((size_t)
5755 matte_image->bytes_per_line*matte_image->depth*
5756 matte_image->height);
cristy3ed852e2009-09-05 21:47:34 +00005757 if (matte_image->data == (char *) NULL)
5758 {
5759 XDestroyImage(matte_image);
5760 matte_image=(XImage *) NULL;
5761 }
5762 }
5763 }
5764 if (window->matte_image != (XImage *) NULL)
5765 {
5766 /*
5767 Free matte image.
5768 */
5769 if (window->matte_image->data != (char *) NULL)
5770 free(window->matte_image->data);
5771 window->matte_image->data=(char *) NULL;
5772 XDestroyImage(window->matte_image);
5773 window->matte_image=(XImage *) NULL;
5774 }
5775 window->matte_image=matte_image;
5776 if (window->matte_pixmap != (Pixmap) NULL)
5777 {
5778 (void) XFreePixmap(display,window->matte_pixmap);
5779 window->matte_pixmap=(Pixmap) NULL;
5780#if defined(MAGICKCORE_HAVE_SHAPE)
5781 if (window->shape != MagickFalse)
5782 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5783#endif
5784 }
5785 window->stasis=MagickFalse;
5786 /*
5787 Convert pixels to X image data.
5788 */
5789 if (window->image != (Image *) NULL)
5790 {
5791 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5792 (ximage->bitmap_bit_order == LSBFirst)))
5793 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005794 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005795 else
5796 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005797 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005798 }
5799 if (window->matte_image != (XImage *) NULL)
5800 {
5801 /*
5802 Create matte pixmap.
5803 */
5804 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5805 if (window->matte_pixmap != (Pixmap) NULL)
5806 {
5807 GC
5808 graphics_context;
5809
5810 XGCValues
5811 context_values;
5812
5813 /*
5814 Copy matte image to matte pixmap.
5815 */
cristy4c08aed2011-07-01 19:47:50 +00005816 context_values.background=0;
5817 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005818 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005819 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005820 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5821 window->matte_image,0,0,0,0,width,height);
5822 (void) XFreeGC(display,graphics_context);
5823#if defined(MAGICKCORE_HAVE_SHAPE)
5824 if (window->shape != MagickFalse)
5825 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5826 window->matte_pixmap,ShapeSet);
5827#endif
5828 }
5829 }
5830 (void) XMakePixmap(display,resource_info,window);
5831 /*
5832 Restore cursor.
5833 */
5834 (void) XCheckDefineCursor(display,window->id,window->cursor);
5835 return(MagickTrue);
5836}
5837
5838/*
5839%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5840% %
5841% %
5842% %
5843+ X M a k e I m a g e L S B F i r s t %
5844% %
5845% %
5846% %
5847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5848%
5849% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5850% pixels are copied in least-significant bit and byte first order. The
5851% server's scanline pad is respected. Rather than using one or two general
5852% cases, many special cases are found here to help speed up the image
5853% conversion.
5854%
5855% The format of the XMakeImageLSBFirst method is:
5856%
cristye941a752011-10-15 01:52:48 +00005857% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5858% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005859%
5860% A description of each parameter follows:
5861%
5862% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5863%
5864% o window: Specifies a pointer to a XWindowInfo structure.
5865%
5866% o image: the image.
5867%
5868% o ximage: Specifies a pointer to a XImage structure; returned from
5869% XCreateImage.
5870%
5871% o matte_image: Specifies a pointer to a XImage structure; returned from
5872% XCreateImage.
5873%
cristye941a752011-10-15 01:52:48 +00005874% o exception: return any errors or warnings in this structure.
5875%
cristy3ed852e2009-09-05 21:47:34 +00005876*/
5877static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005878 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5879 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005880{
cristyc57f6942010-11-12 01:47:39 +00005881 CacheView
5882 *canvas_view;
5883
cristy3ed852e2009-09-05 21:47:34 +00005884 Image
5885 *canvas;
5886
5887 int
5888 y;
5889
cristy4c08aed2011-07-01 19:47:50 +00005890 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005891 *p;
5892
5893 register int
5894 x;
5895
5896 register unsigned char
5897 *q;
5898
5899 unsigned char
5900 bit,
5901 byte;
5902
5903 unsigned int
5904 scanline_pad;
5905
cristyf2faecf2010-05-28 19:19:36 +00005906 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005907 pixel,
5908 *pixels;
5909
5910 XStandardColormap
5911 *map_info;
5912
5913 assert(resource_info != (XResourceInfo *) NULL);
5914 assert(window != (XWindowInfo *) NULL);
5915 assert(image != (Image *) NULL);
5916 if (image->debug != MagickFalse)
5917 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5918 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005919 if ((window->immutable == MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00005920 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00005921 {
5922 char
5923 size[MaxTextExtent];
5924
5925 Image
5926 *pattern;
5927
5928 ImageInfo
5929 *image_info;
5930
5931 image_info=AcquireImageInfo();
5932 (void) CopyMagickString(image_info->filename,
5933 resource_info->image_info->texture != (char *) NULL ?
5934 resource_info->image_info->texture : "pattern:checkerboard",
5935 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005936 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005937 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005938 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005939 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005940 image_info=DestroyImageInfo(image_info);
5941 if (pattern != (Image *) NULL)
5942 {
cristy6710d842011-10-20 23:23:00 +00005943 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005944 if (canvas != (Image *) NULL)
cristy39172402012-03-30 13:04:39 +00005945 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00005946 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00005947 pattern=DestroyImage(pattern);
5948 }
5949 }
5950 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5951 ximage->bits_per_pixel) >> 3));
5952 map_info=window->map_info;
5953 pixels=window->pixel_info->pixels;
5954 q=(unsigned char *) ximage->data;
5955 x=0;
cristy46ff2672012-12-14 15:32:26 +00005956 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00005957 if (ximage->format == XYBitmap)
5958 {
5959 register unsigned short
5960 polarity;
5961
5962 unsigned char
5963 background,
5964 foreground;
5965
5966 /*
5967 Convert canvas to big-endian bitmap.
5968 */
5969 background=(unsigned char)
5970 (XPixelIntensity(&window->pixel_info->foreground_color) <
5971 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5972 foreground=(unsigned char)
5973 (XPixelIntensity(&window->pixel_info->background_color) <
5974 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005975 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00005976 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00005977 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005978 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5979 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005980 for (y=0; y < (int) canvas->rows; y++)
5981 {
cristyc57f6942010-11-12 01:47:39 +00005982 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005983 exception);
cristy4c08aed2011-07-01 19:47:50 +00005984 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005985 break;
cristy3ed852e2009-09-05 21:47:34 +00005986 bit=0;
5987 byte=0;
5988 for (x=0; x < (int) canvas->columns; x++)
5989 {
5990 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005991 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005992 byte|=foreground;
5993 else
5994 byte|=background;
5995 bit++;
5996 if (bit == 8)
5997 {
5998 *q++=byte;
5999 bit=0;
6000 byte=0;
6001 }
cristyed231572011-07-14 02:18:59 +00006002 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006003 }
6004 if (bit != 0)
6005 *q=byte >> (8-bit);
6006 q+=scanline_pad;
6007 }
6008 }
6009 else
6010 if (window->pixel_info->colors != 0)
6011 switch (ximage->bits_per_pixel)
6012 {
6013 case 2:
6014 {
6015 register unsigned int
6016 nibble;
6017
6018 /*
6019 Convert to 2 bit color-mapped X canvas.
6020 */
6021 for (y=0; y < (int) canvas->rows; y++)
6022 {
cristyc57f6942010-11-12 01:47:39 +00006023 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006024 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006025 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006026 break;
cristy3ed852e2009-09-05 21:47:34 +00006027 nibble=0;
6028 for (x=0; x < (int) canvas->columns; x++)
6029 {
cristy4c08aed2011-07-01 19:47:50 +00006030 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006031 switch (nibble)
6032 {
6033 case 0:
6034 {
6035 *q=(unsigned char) pixel;
6036 nibble++;
6037 break;
6038 }
6039 case 1:
6040 {
6041 *q|=(unsigned char) (pixel << 2);
6042 nibble++;
6043 break;
6044 }
6045 case 2:
6046 {
6047 *q|=(unsigned char) (pixel << 4);
6048 nibble++;
6049 break;
6050 }
6051 case 3:
6052 {
6053 *q|=(unsigned char) (pixel << 6);
6054 q++;
6055 nibble=0;
6056 break;
6057 }
6058 }
cristyed231572011-07-14 02:18:59 +00006059 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006060 }
6061 q+=scanline_pad;
6062 }
6063 break;
6064 }
6065 case 4:
6066 {
6067 register unsigned int
6068 nibble;
6069
6070 /*
6071 Convert to 4 bit color-mapped X canvas.
6072 */
6073 for (y=0; y < (int) canvas->rows; y++)
6074 {
cristyc57f6942010-11-12 01:47:39 +00006075 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006076 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006077 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006078 break;
cristy3ed852e2009-09-05 21:47:34 +00006079 nibble=0;
6080 for (x=0; x < (int) canvas->columns; x++)
6081 {
cristy4c08aed2011-07-01 19:47:50 +00006082 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006083 switch (nibble)
6084 {
6085 case 0:
6086 {
6087 *q=(unsigned char) pixel;
6088 nibble++;
6089 break;
6090 }
6091 case 1:
6092 {
6093 *q|=(unsigned char) (pixel << 4);
6094 q++;
6095 nibble=0;
6096 break;
6097 }
6098 }
cristyed231572011-07-14 02:18:59 +00006099 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006100 }
6101 q+=scanline_pad;
6102 }
6103 break;
6104 }
6105 case 6:
6106 case 8:
6107 {
6108 /*
6109 Convert to 8 bit color-mapped X canvas.
6110 */
6111 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006112 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006113 {
cristy6710d842011-10-20 23:23:00 +00006114 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006115 break;
6116 }
6117 for (y=0; y < (int) canvas->rows; y++)
6118 {
cristyc57f6942010-11-12 01:47:39 +00006119 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006120 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006121 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006122 break;
cristy3ed852e2009-09-05 21:47:34 +00006123 for (x=0; x < (int) canvas->columns; x++)
6124 {
cristy4c08aed2011-07-01 19:47:50 +00006125 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006126 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006127 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006128 }
6129 q+=scanline_pad;
6130 }
6131 break;
6132 }
6133 default:
6134 {
6135 register int
6136 k;
6137
6138 register unsigned int
6139 bytes_per_pixel;
6140
cristy3ed852e2009-09-05 21:47:34 +00006141 /*
6142 Convert to multi-byte color-mapped X canvas.
6143 */
6144 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6145 for (y=0; y < (int) canvas->rows; y++)
6146 {
cristyc57f6942010-11-12 01:47:39 +00006147 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006148 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006149 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006150 break;
cristy3ed852e2009-09-05 21:47:34 +00006151 for (x=0; x < (int) canvas->columns; x++)
6152 {
cristy4c08aed2011-07-01 19:47:50 +00006153 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006154 for (k=0; k < (int) bytes_per_pixel; k++)
6155 {
cristy42daae12013-04-07 22:36:07 +00006156 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006157 pixel>>=8;
6158 }
cristyed231572011-07-14 02:18:59 +00006159 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006160 }
6161 q+=scanline_pad;
6162 }
6163 break;
6164 }
6165 }
6166 else
6167 switch (ximage->bits_per_pixel)
6168 {
6169 case 2:
6170 {
6171 register unsigned int
6172 nibble;
6173
6174 /*
6175 Convert to contiguous 2 bit continuous-tone X canvas.
6176 */
6177 for (y=0; y < (int) canvas->rows; y++)
6178 {
6179 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006180 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006181 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006182 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006183 break;
6184 for (x=0; x < (int) canvas->columns; x++)
6185 {
cristy4c08aed2011-07-01 19:47:50 +00006186 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006187 pixel&=0xf;
6188 switch (nibble)
6189 {
6190 case 0:
6191 {
6192 *q=(unsigned char) pixel;
6193 nibble++;
6194 break;
6195 }
6196 case 1:
6197 {
6198 *q|=(unsigned char) (pixel << 2);
6199 nibble++;
6200 break;
6201 }
6202 case 2:
6203 {
6204 *q|=(unsigned char) (pixel << 4);
6205 nibble++;
6206 break;
6207 }
6208 case 3:
6209 {
6210 *q|=(unsigned char) (pixel << 6);
6211 q++;
6212 nibble=0;
6213 break;
6214 }
6215 }
cristyed231572011-07-14 02:18:59 +00006216 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006217 }
6218 q+=scanline_pad;
6219 }
6220 break;
6221 }
6222 case 4:
6223 {
6224 register unsigned int
6225 nibble;
6226
6227 /*
6228 Convert to contiguous 4 bit continuous-tone X canvas.
6229 */
6230 for (y=0; y < (int) canvas->rows; y++)
6231 {
cristyc57f6942010-11-12 01:47:39 +00006232 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006233 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006234 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006235 break;
6236 nibble=0;
6237 for (x=0; x < (int) canvas->columns; x++)
6238 {
cristy4c08aed2011-07-01 19:47:50 +00006239 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006240 pixel&=0xf;
6241 switch (nibble)
6242 {
6243 case 0:
6244 {
6245 *q=(unsigned char) pixel;
6246 nibble++;
6247 break;
6248 }
6249 case 1:
6250 {
6251 *q|=(unsigned char) (pixel << 4);
6252 q++;
6253 nibble=0;
6254 break;
6255 }
6256 }
cristyed231572011-07-14 02:18:59 +00006257 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006258 }
6259 q+=scanline_pad;
6260 }
6261 break;
6262 }
6263 case 6:
6264 case 8:
6265 {
6266 /*
6267 Convert to contiguous 8 bit continuous-tone X canvas.
6268 */
6269 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006270 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006271 {
cristy6710d842011-10-20 23:23:00 +00006272 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006273 break;
6274 }
6275 for (y=0; y < (int) canvas->rows; y++)
6276 {
cristyc57f6942010-11-12 01:47:39 +00006277 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006278 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006279 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006280 break;
6281 for (x=0; x < (int) canvas->columns; x++)
6282 {
cristy4c08aed2011-07-01 19:47:50 +00006283 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006284 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006285 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006286 }
6287 q+=scanline_pad;
6288 }
6289 break;
6290 }
6291 default:
6292 {
6293 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6294 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6295 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6296 (map_info->blue_mult == 1))
6297 {
6298 /*
6299 Convert to 32 bit continuous-tone X canvas.
6300 */
6301 for (y=0; y < (int) canvas->rows; y++)
6302 {
cristyc57f6942010-11-12 01:47:39 +00006303 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006304 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006305 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006306 break;
6307 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6308 (blue_gamma != 1.0))
6309 {
6310 /*
6311 Gamma correct canvas.
6312 */
6313 for (x=(int) canvas->columns-1; x >= 0; x--)
6314 {
cristyccf844f2010-02-03 23:28:16 +00006315 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006316 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006317 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006318 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006319 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006320 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006321 *q++=0;
cristyed231572011-07-14 02:18:59 +00006322 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006323 }
6324 continue;
6325 }
6326 for (x=(int) canvas->columns-1; x >= 0; x--)
6327 {
cristy8bc259b2012-06-21 23:53:15 +00006328 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6329 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6330 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006331 *q++=0;
cristyed231572011-07-14 02:18:59 +00006332 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006333 }
6334 }
6335 }
6336 else
6337 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6338 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6339 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6340 (map_info->blue_mult == 65536L))
6341 {
6342 /*
6343 Convert to 32 bit continuous-tone X canvas.
6344 */
6345 for (y=0; y < (int) canvas->rows; y++)
6346 {
cristyc57f6942010-11-12 01:47:39 +00006347 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006348 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006349 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006350 break;
6351 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6352 (blue_gamma != 1.0))
6353 {
6354 /*
6355 Gamma correct canvas.
6356 */
6357 for (x=(int) canvas->columns-1; x >= 0; x--)
6358 {
cristyccf844f2010-02-03 23:28:16 +00006359 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006360 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006361 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006362 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006363 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006364 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006365 *q++=0;
cristyed231572011-07-14 02:18:59 +00006366 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006367 }
6368 continue;
6369 }
6370 for (x=(int) canvas->columns-1; x >= 0; x--)
6371 {
cristy8bc259b2012-06-21 23:53:15 +00006372 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6373 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6374 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006375 *q++=0;
cristyed231572011-07-14 02:18:59 +00006376 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006377 }
6378 }
6379 }
6380 else
6381 {
6382 register int
6383 k;
6384
6385 register unsigned int
6386 bytes_per_pixel;
6387
cristy3ed852e2009-09-05 21:47:34 +00006388 /*
6389 Convert to multi-byte continuous-tone X canvas.
6390 */
6391 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6392 for (y=0; y < (int) canvas->rows; y++)
6393 {
cristyc57f6942010-11-12 01:47:39 +00006394 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006395 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006396 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006397 break;
cristyc57f6942010-11-12 01:47:39 +00006398 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006399 {
cristy4c08aed2011-07-01 19:47:50 +00006400 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006401 for (k=0; k < (int) bytes_per_pixel; k++)
6402 {
cristy42daae12013-04-07 22:36:07 +00006403 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006404 pixel>>=8;
6405 }
cristyed231572011-07-14 02:18:59 +00006406 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006407 }
6408 q+=scanline_pad;
6409 }
6410 }
6411 break;
6412 }
6413 }
6414 if (matte_image != (XImage *) NULL)
6415 {
6416 /*
6417 Initialize matte canvas.
6418 */
6419 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6420 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6421 q=(unsigned char *) matte_image->data;
6422 for (y=0; y < (int) canvas->rows; y++)
6423 {
cristyc57f6942010-11-12 01:47:39 +00006424 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006425 exception);
cristy4c08aed2011-07-01 19:47:50 +00006426 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006427 break;
6428 bit=0;
6429 byte=0;
6430 for (x=(int) canvas->columns-1; x >= 0; x--)
6431 {
6432 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006433 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006434 byte|=0x80;
6435 bit++;
6436 if (bit == 8)
6437 {
6438 *q++=byte;
6439 bit=0;
6440 byte=0;
6441 }
cristyed231572011-07-14 02:18:59 +00006442 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006443 }
6444 if (bit != 0)
6445 *q=byte >> (8-bit);
6446 q+=scanline_pad;
6447 }
6448 }
cristyc57f6942010-11-12 01:47:39 +00006449 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006450 if (canvas != image)
6451 canvas=DestroyImage(canvas);
6452}
6453
6454/*
6455%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6456% %
6457% %
6458% %
6459+ X M a k e I m a g e M S B F i r s t %
6460% %
6461% %
6462% %
6463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6464%
6465% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6466% image pixels are copied in most-significant bit and byte first order. The
6467% server's scanline pad is also respected. Rather than using one or two
6468% general cases, many special cases are found here to help speed up the image
6469% conversion.
6470%
6471% The format of the XMakeImageMSBFirst method is:
6472%
cristye941a752011-10-15 01:52:48 +00006473% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6474% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006475%
6476% A description of each parameter follows:
6477%
6478% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6479%
6480% o window: Specifies a pointer to a XWindowInfo structure.
6481%
6482% o image: the image.
6483%
6484% o ximage: Specifies a pointer to a XImage structure; returned from
6485% XCreateImage.
6486%
6487% o matte_image: Specifies a pointer to a XImage structure; returned from
6488% XCreateImage.
6489%
cristye941a752011-10-15 01:52:48 +00006490% o exception: return any errors or warnings in this structure.
6491%
cristy3ed852e2009-09-05 21:47:34 +00006492*/
6493static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006494 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6495 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006496{
cristyc57f6942010-11-12 01:47:39 +00006497 CacheView
6498 *canvas_view;
6499
cristy3ed852e2009-09-05 21:47:34 +00006500 Image
6501 *canvas;
6502
6503 int
6504 y;
6505
6506 register int
6507 x;
6508
cristy4c08aed2011-07-01 19:47:50 +00006509 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006510 *p;
6511
6512 register unsigned char
6513 *q;
6514
6515 unsigned char
6516 bit,
6517 byte;
6518
6519 unsigned int
6520 scanline_pad;
6521
cristyf2faecf2010-05-28 19:19:36 +00006522 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006523 pixel,
6524 *pixels;
6525
6526 XStandardColormap
6527 *map_info;
6528
6529 assert(resource_info != (XResourceInfo *) NULL);
6530 assert(window != (XWindowInfo *) NULL);
6531 assert(image != (Image *) NULL);
6532 if (image->debug != MagickFalse)
6533 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6534 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006535 if ((window->immutable != MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00006536 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00006537 {
6538 char
6539 size[MaxTextExtent];
6540
6541 Image
6542 *pattern;
6543
6544 ImageInfo
6545 *image_info;
6546
6547 image_info=AcquireImageInfo();
6548 (void) CopyMagickString(image_info->filename,
6549 resource_info->image_info->texture != (char *) NULL ?
6550 resource_info->image_info->texture : "pattern:checkerboard",
6551 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006552 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006553 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006554 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006555 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006556 image_info=DestroyImageInfo(image_info);
6557 if (pattern != (Image *) NULL)
6558 {
cristy6710d842011-10-20 23:23:00 +00006559 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006560 if (canvas != (Image *) NULL)
cristyfeb3e962012-03-29 17:25:55 +00006561 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6562 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00006563 pattern=DestroyImage(pattern);
6564 }
6565 }
cristy4c08aed2011-07-01 19:47:50 +00006566 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6567 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006568 map_info=window->map_info;
6569 pixels=window->pixel_info->pixels;
6570 q=(unsigned char *) ximage->data;
6571 x=0;
cristy46ff2672012-12-14 15:32:26 +00006572 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00006573 if (ximage->format == XYBitmap)
6574 {
6575 register unsigned short
6576 polarity;
6577
6578 unsigned char
6579 background,
6580 foreground;
6581
6582 /*
6583 Convert canvas to big-endian bitmap.
6584 */
6585 background=(unsigned char)
6586 (XPixelIntensity(&window->pixel_info->foreground_color) <
6587 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6588 foreground=(unsigned char)
6589 (XPixelIntensity(&window->pixel_info->background_color) <
6590 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006591 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00006592 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00006593 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006594 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6595 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006596 for (y=0; y < (int) canvas->rows; y++)
6597 {
cristyc57f6942010-11-12 01:47:39 +00006598 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006599 exception);
cristy4c08aed2011-07-01 19:47:50 +00006600 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006601 break;
cristy3ed852e2009-09-05 21:47:34 +00006602 bit=0;
6603 byte=0;
6604 for (x=(int) canvas->columns-1; x >= 0; x--)
6605 {
6606 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006607 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006608 byte|=foreground;
6609 else
6610 byte|=background;
6611 bit++;
6612 if (bit == 8)
6613 {
6614 *q++=byte;
6615 bit=0;
6616 byte=0;
6617 }
cristyed231572011-07-14 02:18:59 +00006618 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006619 }
6620 if (bit != 0)
6621 *q=byte << (8-bit);
6622 q+=scanline_pad;
6623 }
6624 }
6625 else
6626 if (window->pixel_info->colors != 0)
6627 switch (ximage->bits_per_pixel)
6628 {
6629 case 2:
6630 {
6631 register unsigned int
6632 nibble;
6633
6634 /*
6635 Convert to 2 bit color-mapped X canvas.
6636 */
6637 for (y=0; y < (int) canvas->rows; y++)
6638 {
cristyc57f6942010-11-12 01:47:39 +00006639 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006640 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006641 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006642 break;
cristy3ed852e2009-09-05 21:47:34 +00006643 nibble=0;
6644 for (x=0; x < (int) canvas->columns; x++)
6645 {
cristy4c08aed2011-07-01 19:47:50 +00006646 pixel=pixels[(ssize_t)
6647 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006648 switch (nibble)
6649 {
6650 case 0:
6651 {
6652 *q=(unsigned char) (pixel << 6);
6653 nibble++;
6654 break;
6655 }
6656 case 1:
6657 {
6658 *q|=(unsigned char) (pixel << 4);
6659 nibble++;
6660 break;
6661 }
6662 case 2:
6663 {
6664 *q|=(unsigned char) (pixel << 2);
6665 nibble++;
6666 break;
6667 }
6668 case 3:
6669 {
6670 *q|=(unsigned char) pixel;
6671 q++;
6672 nibble=0;
6673 break;
6674 }
6675 }
cristyed231572011-07-14 02:18:59 +00006676 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006677 }
6678 q+=scanline_pad;
6679 }
6680 break;
6681 }
6682 case 4:
6683 {
6684 register unsigned int
6685 nibble;
6686
6687 /*
6688 Convert to 4 bit color-mapped X canvas.
6689 */
6690 for (y=0; y < (int) canvas->rows; y++)
6691 {
cristyc57f6942010-11-12 01:47:39 +00006692 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006693 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006694 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006695 break;
cristy3ed852e2009-09-05 21:47:34 +00006696 nibble=0;
6697 for (x=0; x < (int) canvas->columns; x++)
6698 {
cristy4c08aed2011-07-01 19:47:50 +00006699 pixel=pixels[(ssize_t)
6700 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006701 switch (nibble)
6702 {
6703 case 0:
6704 {
6705 *q=(unsigned char) (pixel << 4);
6706 nibble++;
6707 break;
6708 }
6709 case 1:
6710 {
6711 *q|=(unsigned char) pixel;
6712 q++;
6713 nibble=0;
6714 break;
6715 }
6716 }
cristyed231572011-07-14 02:18:59 +00006717 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006718 }
6719 q+=scanline_pad;
6720 }
6721 break;
6722 }
6723 case 6:
6724 case 8:
6725 {
6726 /*
6727 Convert to 8 bit color-mapped X canvas.
6728 */
6729 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006730 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006731 {
cristy6710d842011-10-20 23:23:00 +00006732 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006733 break;
6734 }
6735 for (y=0; y < (int) canvas->rows; y++)
6736 {
cristyc57f6942010-11-12 01:47:39 +00006737 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006738 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006739 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006740 break;
cristy3ed852e2009-09-05 21:47:34 +00006741 for (x=0; x < (int) canvas->columns; x++)
6742 {
cristy6710d842011-10-20 23:23:00 +00006743 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006744 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006745 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006746 }
6747 q+=scanline_pad;
6748 }
6749 break;
6750 }
6751 default:
6752 {
6753 register int
6754 k;
6755
6756 register unsigned int
6757 bytes_per_pixel;
6758
6759 unsigned char
cristybb503372010-05-27 20:51:26 +00006760 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006761
6762 /*
6763 Convert to 8 bit color-mapped X canvas.
6764 */
6765 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6766 for (y=0; y < (int) canvas->rows; y++)
6767 {
cristyc57f6942010-11-12 01:47:39 +00006768 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006769 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006770 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006771 break;
cristy3ed852e2009-09-05 21:47:34 +00006772 for (x=0; x < (int) canvas->columns; x++)
6773 {
cristy4c08aed2011-07-01 19:47:50 +00006774 pixel=pixels[(ssize_t)
6775 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006776 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6777 {
6778 channel[k]=(unsigned char) pixel;
6779 pixel>>=8;
6780 }
6781 for (k=0; k < (int) bytes_per_pixel; k++)
6782 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006783 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006784 }
6785 q+=scanline_pad;
6786 }
6787 break;
6788 }
6789 }
6790 else
6791 switch (ximage->bits_per_pixel)
6792 {
6793 case 2:
6794 {
6795 register unsigned int
6796 nibble;
6797
6798 /*
6799 Convert to 4 bit continuous-tone X canvas.
6800 */
6801 for (y=0; y < (int) canvas->rows; y++)
6802 {
cristyc57f6942010-11-12 01:47:39 +00006803 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006804 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006805 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006806 break;
6807 nibble=0;
6808 for (x=(int) canvas->columns-1; x >= 0; x--)
6809 {
cristy4c08aed2011-07-01 19:47:50 +00006810 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006811 pixel&=0xf;
6812 switch (nibble)
6813 {
6814 case 0:
6815 {
6816 *q=(unsigned char) (pixel << 6);
6817 nibble++;
6818 break;
6819 }
6820 case 1:
6821 {
6822 *q|=(unsigned char) (pixel << 4);
6823 nibble++;
6824 break;
6825 }
6826 case 2:
6827 {
6828 *q|=(unsigned char) (pixel << 2);
6829 nibble++;
6830 break;
6831 }
6832 case 3:
6833 {
6834 *q|=(unsigned char) pixel;
6835 q++;
6836 nibble=0;
6837 break;
6838 }
6839 }
cristyed231572011-07-14 02:18:59 +00006840 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006841 }
6842 q+=scanline_pad;
6843 }
6844 break;
6845 }
6846 case 4:
6847 {
6848 register unsigned int
6849 nibble;
6850
6851 /*
6852 Convert to 4 bit continuous-tone X canvas.
6853 */
6854 for (y=0; y < (int) canvas->rows; y++)
6855 {
cristyc57f6942010-11-12 01:47:39 +00006856 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006857 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006858 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006859 break;
6860 nibble=0;
6861 for (x=(int) canvas->columns-1; x >= 0; x--)
6862 {
cristy4c08aed2011-07-01 19:47:50 +00006863 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006864 pixel&=0xf;
6865 switch (nibble)
6866 {
6867 case 0:
6868 {
6869 *q=(unsigned char) (pixel << 4);
6870 nibble++;
6871 break;
6872 }
6873 case 1:
6874 {
6875 *q|=(unsigned char) pixel;
6876 q++;
6877 nibble=0;
6878 break;
6879 }
6880 }
cristyed231572011-07-14 02:18:59 +00006881 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006882 }
6883 q+=scanline_pad;
6884 }
6885 break;
6886 }
6887 case 6:
6888 case 8:
6889 {
6890 /*
6891 Convert to 8 bit continuous-tone X canvas.
6892 */
6893 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006894 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006895 {
cristy6710d842011-10-20 23:23:00 +00006896 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006897 break;
6898 }
6899 for (y=0; y < (int) canvas->rows; y++)
6900 {
cristyc57f6942010-11-12 01:47:39 +00006901 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006902 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006903 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006904 break;
6905 for (x=(int) canvas->columns-1; x >= 0; x--)
6906 {
cristy4c08aed2011-07-01 19:47:50 +00006907 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006908 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006909 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006910 }
6911 q+=scanline_pad;
6912 }
6913 break;
6914 }
6915 default:
6916 {
6917 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6918 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6919 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6920 (map_info->blue_mult == 1))
6921 {
6922 /*
6923 Convert to 32 bit continuous-tone X canvas.
6924 */
6925 for (y=0; y < (int) canvas->rows; y++)
6926 {
cristyc57f6942010-11-12 01:47:39 +00006927 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006928 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006929 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006930 break;
6931 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6932 (blue_gamma != 1.0))
6933 {
6934 /*
6935 Gamma correct canvas.
6936 */
6937 for (x=(int) canvas->columns-1; x >= 0; x--)
6938 {
6939 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006940 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006941 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006942 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006943 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006944 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006945 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006946 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006947 }
6948 continue;
6949 }
6950 for (x=(int) canvas->columns-1; x >= 0; x--)
6951 {
6952 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006953 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6954 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6955 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006956 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006957 }
6958 }
6959 }
6960 else
6961 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6962 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6963 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6964 (map_info->blue_mult == 65536L))
6965 {
6966 /*
6967 Convert to 32 bit continuous-tone X canvas.
6968 */
6969 for (y=0; y < (int) canvas->rows; y++)
6970 {
cristyc57f6942010-11-12 01:47:39 +00006971 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006972 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006973 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006974 break;
6975 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6976 (blue_gamma != 1.0))
6977 {
6978 /*
6979 Gamma correct canvas.
6980 */
6981 for (x=(int) canvas->columns-1; x >= 0; x--)
6982 {
6983 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006984 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006985 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006986 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006987 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006988 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006989 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006990 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006991 }
6992 continue;
6993 }
6994 for (x=(int) canvas->columns-1; x >= 0; x--)
6995 {
6996 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006997 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6998 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6999 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00007000 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007001 }
7002 }
7003 }
7004 else
7005 {
7006 register int
7007 k;
7008
7009 register unsigned int
7010 bytes_per_pixel;
7011
7012 unsigned char
cristybb503372010-05-27 20:51:26 +00007013 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007014
7015 /*
7016 Convert to multi-byte continuous-tone X canvas.
7017 */
7018 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7019 for (y=0; y < (int) canvas->rows; y++)
7020 {
cristyc57f6942010-11-12 01:47:39 +00007021 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007022 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007023 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007024 break;
7025 for (x=(int) canvas->columns-1; x >= 0; x--)
7026 {
cristy4c08aed2011-07-01 19:47:50 +00007027 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007028 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7029 {
7030 channel[k]=(unsigned char) pixel;
7031 pixel>>=8;
7032 }
7033 for (k=0; k < (int) bytes_per_pixel; k++)
7034 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007035 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007036 }
7037 q+=scanline_pad;
7038 }
7039 }
7040 break;
7041 }
7042 }
7043 if (matte_image != (XImage *) NULL)
7044 {
7045 /*
7046 Initialize matte canvas.
7047 */
7048 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7049 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7050 q=(unsigned char *) matte_image->data;
7051 for (y=0; y < (int) canvas->rows; y++)
7052 {
cristyc57f6942010-11-12 01:47:39 +00007053 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007054 exception);
cristy4c08aed2011-07-01 19:47:50 +00007055 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007056 break;
7057 bit=0;
7058 byte=0;
7059 for (x=(int) canvas->columns-1; x >= 0; x--)
7060 {
7061 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007062 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007063 byte|=0x01;
7064 bit++;
7065 if (bit == 8)
7066 {
7067 *q++=byte;
7068 bit=0;
7069 byte=0;
7070 }
cristyed231572011-07-14 02:18:59 +00007071 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007072 }
7073 if (bit != 0)
7074 *q=byte << (8-bit);
7075 q+=scanline_pad;
7076 }
7077 }
cristyc57f6942010-11-12 01:47:39 +00007078 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007079 if (canvas != image)
7080 canvas=DestroyImage(canvas);
7081}
7082
7083/*
7084%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7085% %
7086% %
7087% %
7088% X M a k e M a g n i f y I m a g e %
7089% %
7090% %
7091% %
7092%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7093%
7094% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7095%
7096% The format of the XMakeMagnifyImage method is:
7097%
cristy6710d842011-10-20 23:23:00 +00007098% void XMakeMagnifyImage(Display *display,XWindows *windows,
7099% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007100%
7101% A description of each parameter follows:
7102%
7103% o display: Specifies a connection to an X server; returned from
7104% XOpenDisplay.
7105%
7106% o windows: Specifies a pointer to a XWindows structure.
7107%
cristy6710d842011-10-20 23:23:00 +00007108% o exception: return any errors or warnings in this structure.
7109%
cristy3ed852e2009-09-05 21:47:34 +00007110*/
cristy6710d842011-10-20 23:23:00 +00007111MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7112 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007113{
7114 char
7115 tuple[MaxTextExtent];
7116
7117 int
7118 y;
7119
cristy4c08aed2011-07-01 19:47:50 +00007120 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007121 pixel;
7122
7123 register int
7124 x;
7125
cristybb503372010-05-27 20:51:26 +00007126 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007127 i;
7128
7129 register unsigned char
7130 *p,
7131 *q;
7132
cristy9d314ff2011-03-09 01:30:28 +00007133 ssize_t
7134 n;
7135
cristy3ed852e2009-09-05 21:47:34 +00007136 static unsigned int
7137 previous_magnify = 0;
7138
7139 static XWindowInfo
7140 magnify_window;
7141
7142 unsigned int
7143 height,
7144 j,
7145 k,
7146 l,
7147 magnify,
7148 scanline_pad,
7149 width;
7150
7151 XImage
7152 *ximage;
7153
7154 /*
7155 Check boundary conditions.
7156 */
7157 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7158 assert(display != (Display *) NULL);
7159 assert(windows != (XWindows *) NULL);
7160 magnify=1;
cristybb503372010-05-27 20:51:26 +00007161 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007162 magnify<<=1;
7163 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7164 magnify<<=1;
7165 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7166 magnify<<=1;
7167 while (magnify > windows->magnify.width)
7168 magnify>>=1;
7169 while (magnify > windows->magnify.height)
7170 magnify>>=1;
7171 if (magnify != previous_magnify)
7172 {
7173 Status
7174 status;
7175
7176 XTextProperty
7177 window_name;
7178
7179 /*
7180 New magnify factor: update magnify window name.
7181 */
7182 i=0;
7183 while ((1 << i) <= (int) magnify)
7184 i++;
cristyb51dff52011-05-19 16:55:47 +00007185 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007186 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007187 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7188 if (status != False)
7189 {
7190 XSetWMName(display,windows->magnify.id,&window_name);
7191 XSetWMIconName(display,windows->magnify.id,&window_name);
7192 (void) XFree((void *) window_name.value);
7193 }
7194 }
7195 previous_magnify=magnify;
7196 ximage=windows->image.ximage;
7197 width=(unsigned int) windows->magnify.ximage->width;
7198 height=(unsigned int) windows->magnify.ximage->height;
7199 if ((windows->magnify.x < 0) ||
7200 (windows->magnify.x >= windows->image.ximage->width))
7201 windows->magnify.x=windows->image.ximage->width >> 1;
7202 x=windows->magnify.x-((width/magnify) >> 1);
7203 if (x < 0)
7204 x=0;
7205 else
7206 if (x > (int) (ximage->width-(width/magnify)))
7207 x=ximage->width-width/magnify;
7208 if ((windows->magnify.y < 0) ||
7209 (windows->magnify.y >= windows->image.ximage->height))
7210 windows->magnify.y=windows->image.ximage->height >> 1;
7211 y=windows->magnify.y-((height/magnify) >> 1);
7212 if (y < 0)
7213 y=0;
7214 else
7215 if (y > (int) (ximage->height-(height/magnify)))
7216 y=ximage->height-height/magnify;
7217 q=(unsigned char *) windows->magnify.ximage->data;
7218 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7219 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7220 if (ximage->bits_per_pixel < 8)
7221 {
7222 register unsigned char
7223 background,
7224 byte,
7225 foreground,
7226 p_bit,
7227 q_bit;
7228
7229 register unsigned int
7230 plane;
7231
7232 XPixelInfo
7233 *pixel_info;
7234
7235 pixel_info=windows->magnify.pixel_info;
7236 switch (ximage->bitmap_bit_order)
7237 {
7238 case LSBFirst:
7239 {
7240 /*
7241 Magnify little-endian bitmap.
7242 */
7243 background=0x00;
7244 foreground=0x80;
7245 if (ximage->format == XYBitmap)
7246 {
7247 background=(unsigned char)
7248 (XPixelIntensity(&pixel_info->foreground_color) <
7249 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7250 foreground=(unsigned char)
7251 (XPixelIntensity(&pixel_info->background_color) <
7252 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7253 if (windows->magnify.depth > 1)
7254 Swap(background,foreground);
7255 }
cristybb503372010-05-27 20:51:26 +00007256 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007257 {
7258 /*
7259 Propogate pixel magnify rows.
7260 */
7261 for (j=0; j < magnify; j++)
7262 {
7263 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7264 ((x*ximage->bits_per_pixel) >> 3);
7265 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7266 q_bit=0;
7267 byte=0;
7268 for (k=0; k < width; k+=magnify)
7269 {
7270 /*
7271 Propogate pixel magnify columns.
7272 */
7273 for (l=0; l < magnify; l++)
7274 {
7275 /*
7276 Propogate each bit plane.
7277 */
7278 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7279 {
7280 byte>>=1;
7281 if (*p & (0x01 << (p_bit+plane)))
7282 byte|=foreground;
7283 else
7284 byte|=background;
7285 q_bit++;
7286 if (q_bit == 8)
7287 {
7288 *q++=byte;
7289 q_bit=0;
7290 byte=0;
7291 }
7292 }
7293 }
7294 p_bit+=ximage->bits_per_pixel;
7295 if (p_bit == 8)
7296 {
7297 p++;
7298 p_bit=0;
7299 }
7300 if (q_bit != 0)
7301 *q=byte >> (8-q_bit);
7302 q+=scanline_pad;
7303 }
7304 }
7305 y++;
7306 }
7307 break;
7308 }
7309 case MSBFirst:
7310 default:
7311 {
7312 /*
7313 Magnify big-endian bitmap.
7314 */
7315 background=0x00;
7316 foreground=0x01;
7317 if (ximage->format == XYBitmap)
7318 {
7319 background=(unsigned char)
7320 (XPixelIntensity(&pixel_info->foreground_color) <
7321 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7322 foreground=(unsigned char)
7323 (XPixelIntensity(&pixel_info->background_color) <
7324 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7325 if (windows->magnify.depth > 1)
7326 Swap(background,foreground);
7327 }
cristybb503372010-05-27 20:51:26 +00007328 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007329 {
7330 /*
7331 Propogate pixel magnify rows.
7332 */
7333 for (j=0; j < magnify; j++)
7334 {
7335 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7336 ((x*ximage->bits_per_pixel) >> 3);
7337 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7338 q_bit=0;
7339 byte=0;
7340 for (k=0; k < width; k+=magnify)
7341 {
7342 /*
7343 Propogate pixel magnify columns.
7344 */
7345 for (l=0; l < magnify; l++)
7346 {
7347 /*
7348 Propogate each bit plane.
7349 */
7350 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7351 {
7352 byte<<=1;
7353 if (*p & (0x80 >> (p_bit+plane)))
7354 byte|=foreground;
7355 else
7356 byte|=background;
7357 q_bit++;
7358 if (q_bit == 8)
7359 {
7360 *q++=byte;
7361 q_bit=0;
7362 byte=0;
7363 }
7364 }
7365 }
7366 p_bit+=ximage->bits_per_pixel;
7367 if (p_bit == 8)
7368 {
7369 p++;
7370 p_bit=0;
7371 }
7372 if (q_bit != 0)
7373 *q=byte << (8-q_bit);
7374 q+=scanline_pad;
7375 }
7376 }
7377 y++;
7378 }
7379 break;
7380 }
7381 }
7382 }
7383 else
7384 switch (ximage->bits_per_pixel)
7385 {
7386 case 6:
7387 case 8:
7388 {
7389 /*
7390 Magnify 8 bit X image.
7391 */
cristybb503372010-05-27 20:51:26 +00007392 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007393 {
7394 /*
7395 Propogate pixel magnify rows.
7396 */
7397 for (j=0; j < magnify; j++)
7398 {
7399 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7400 ((x*ximage->bits_per_pixel) >> 3);
7401 for (k=0; k < width; k+=magnify)
7402 {
7403 /*
7404 Propogate pixel magnify columns.
7405 */
7406 for (l=0; l < magnify; l++)
7407 *q++=(*p);
7408 p++;
7409 }
7410 q+=scanline_pad;
7411 }
7412 y++;
7413 }
7414 break;
7415 }
7416 default:
7417 {
7418 register unsigned int
7419 bytes_per_pixel,
7420 m;
7421
7422 /*
7423 Magnify multi-byte X image.
7424 */
7425 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007426 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007427 {
7428 /*
7429 Propogate pixel magnify rows.
7430 */
7431 for (j=0; j < magnify; j++)
7432 {
7433 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7434 ((x*ximage->bits_per_pixel) >> 3);
7435 for (k=0; k < width; k+=magnify)
7436 {
7437 /*
7438 Propogate pixel magnify columns.
7439 */
7440 for (l=0; l < magnify; l++)
7441 for (m=0; m < bytes_per_pixel; m++)
7442 *q++=(*(p+m));
7443 p+=bytes_per_pixel;
7444 }
7445 q+=scanline_pad;
7446 }
7447 y++;
7448 }
7449 break;
7450 }
7451 }
7452 /*
7453 Copy X image to magnify pixmap.
7454 */
7455 x=windows->magnify.x-((width/magnify) >> 1);
7456 if (x < 0)
7457 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7458 else
7459 if (x > (int) (ximage->width-(width/magnify)))
7460 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7461 else
7462 x=0;
7463 y=windows->magnify.y-((height/magnify) >> 1);
7464 if (y < 0)
7465 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7466 else
7467 if (y > (int) (ximage->height-(height/magnify)))
7468 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7469 else
7470 y=0;
7471 if ((x != 0) || (y != 0))
7472 (void) XFillRectangle(display,windows->magnify.pixmap,
7473 windows->magnify.annotate_context,0,0,width,height);
7474 (void) XPutImage(display,windows->magnify.pixmap,
7475 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7476 height-y);
7477 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7478 (magnify <= (height >> 1))))
7479 {
7480 RectangleInfo
7481 highlight_info;
7482
7483 /*
7484 Highlight center pixel.
7485 */
cristybb503372010-05-27 20:51:26 +00007486 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7487 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007488 highlight_info.width=magnify;
7489 highlight_info.height=magnify;
7490 (void) XDrawRectangle(display,windows->magnify.pixmap,
7491 windows->magnify.highlight_context,(int) highlight_info.x,
7492 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7493 (unsigned int) highlight_info.height-1);
7494 if (magnify > 2)
7495 (void) XDrawRectangle(display,windows->magnify.pixmap,
7496 windows->magnify.annotate_context,(int) highlight_info.x+1,
7497 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7498 (unsigned int) highlight_info.height-3);
7499 }
7500 /*
7501 Show center pixel color.
7502 */
cristy3aa93752011-12-18 15:54:24 +00007503 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007504 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007505 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007506 windows->magnify.x,windows->magnify.y);
7507 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007508 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007509 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007510 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007511 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007512 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007513 if (pixel.colorspace == CMYKColorspace)
7514 {
7515 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007516 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007517 }
cristy8a46d822012-08-28 23:32:39 +00007518 if (pixel.alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00007519 {
7520 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007521 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007522 }
7523 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7524 height=(unsigned int) windows->magnify.font_info->ascent+
7525 windows->magnify.font_info->descent;
7526 x=windows->magnify.font_info->max_bounds.width >> 1;
7527 y=windows->magnify.font_info->ascent+(height >> 2);
7528 (void) XDrawImageString(display,windows->magnify.pixmap,
7529 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7530 GetColorTuple(&pixel,MagickTrue,tuple);
7531 y+=height;
7532 (void) XDrawImageString(display,windows->magnify.pixmap,
7533 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007534 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007535 exception);
cristy3ed852e2009-09-05 21:47:34 +00007536 y+=height;
7537 (void) XDrawImageString(display,windows->magnify.pixmap,
7538 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7539 /*
7540 Refresh magnify window.
7541 */
7542 magnify_window=windows->magnify;
7543 magnify_window.x=0;
7544 magnify_window.y=0;
7545 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7546}
7547
7548/*
7549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7550% %
7551% %
7552% %
7553% X M a k e P i x m a p %
7554% %
7555% %
7556% %
7557%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7558%
7559% XMakePixmap() creates an X11 pixmap.
7560%
7561% The format of the XMakePixmap method is:
7562%
7563% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7564% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7565% XPixelInfo *pixel)
7566%
7567% A description of each parameter follows:
7568%
7569% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7570%
7571% o display: Specifies a connection to an X server; returned from
7572% XOpenDisplay.
7573%
7574% o window: Specifies a pointer to a XWindowInfo structure.
7575%
cristy3ed852e2009-09-05 21:47:34 +00007576*/
7577static MagickBooleanType XMakePixmap(Display *display,
7578 const XResourceInfo *resource_info,XWindowInfo *window)
7579{
7580 unsigned int
7581 height,
7582 width;
7583
7584 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7585 assert(display != (Display *) NULL);
7586 assert(resource_info != (XResourceInfo *) NULL);
7587 assert(window != (XWindowInfo *) NULL);
7588 if (window->pixmap != (Pixmap) NULL)
7589 {
7590 /*
7591 Destroy previous X pixmap.
7592 */
7593 (void) XFreePixmap(display,window->pixmap);
7594 window->pixmap=(Pixmap) NULL;
7595 }
7596 if (window->use_pixmap == MagickFalse)
7597 return(MagickFalse);
7598 if (window->ximage == (XImage *) NULL)
7599 return(MagickFalse);
7600 /*
7601 Display busy cursor.
7602 */
7603 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7604 (void) XFlush(display);
7605 /*
7606 Create pixmap.
7607 */
7608 width=(unsigned int) window->ximage->width;
7609 height=(unsigned int) window->ximage->height;
7610 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7611 if (window->pixmap == (Pixmap) NULL)
7612 {
7613 /*
7614 Unable to allocate pixmap.
7615 */
7616 (void) XCheckDefineCursor(display,window->id,window->cursor);
7617 return(MagickFalse);
7618 }
7619 /*
7620 Copy X image to pixmap.
7621 */
7622#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7623 if (window->shared_memory)
7624 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7625 window->ximage,0,0,0,0,width,height,MagickTrue);
7626#endif
7627 if (window->shared_memory == MagickFalse)
7628 (void) XPutImage(display,window->pixmap,window->annotate_context,
7629 window->ximage,0,0,0,0,width,height);
7630 if (IsEventLogging())
7631 {
7632 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7633 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7634 width,height);
7635 }
7636 /*
7637 Restore cursor.
7638 */
7639 (void) XCheckDefineCursor(display,window->id,window->cursor);
7640 return(MagickTrue);
7641}
7642
7643/*
7644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7645% %
7646% %
7647% %
7648% X M a k e S t a n d a r d C o l o r m a p %
7649% %
7650% %
7651% %
7652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7653%
7654% XMakeStandardColormap() creates an X11 Standard Colormap.
7655%
7656% The format of the XMakeStandardColormap method is:
7657%
cristy6710d842011-10-20 23:23:00 +00007658% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7659% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7660% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007661%
7662% A description of each parameter follows:
7663%
7664% o display: Specifies a connection to an X server; returned from
7665% XOpenDisplay.
7666%
7667% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7668% returned from XGetVisualInfo.
7669%
7670% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7671%
7672% o image: the image.
7673%
7674% o map_info: If a Standard Colormap type is specified, this structure is
7675% initialized with info from the Standard Colormap.
7676%
7677% o pixel: Specifies a pointer to a XPixelInfo structure.
7678%
cristy6710d842011-10-20 23:23:00 +00007679% o exception: return any errors or warnings in this structure.
7680%
cristy3ed852e2009-09-05 21:47:34 +00007681*/
7682
7683#if defined(__cplusplus) || defined(c_plusplus)
7684extern "C" {
7685#endif
7686
cristya19f1d72012-08-07 18:24:38 +00007687static inline double DiversityPixelIntensity(
cristy3ed852e2009-09-05 21:47:34 +00007688 const DiversityPacket *pixel)
7689{
cristya19f1d72012-08-07 18:24:38 +00007690 double
cristy3ed852e2009-09-05 21:47:34 +00007691 intensity;
7692
cristyd3d2a272013-06-24 16:09:41 +00007693 intensity=0.212656*pixel->red+0.715158*pixel->green+0.072186*pixel->blue;
cristy3ed852e2009-09-05 21:47:34 +00007694 return(intensity);
7695}
7696
7697static int IntensityCompare(const void *x,const void *y)
7698{
7699 DiversityPacket
7700 *color_1,
7701 *color_2;
7702
7703 int
7704 diversity;
7705
7706 color_1=(DiversityPacket *) x;
7707 color_2=(DiversityPacket *) y;
7708 diversity=(int) (DiversityPixelIntensity(color_2)-
7709 DiversityPixelIntensity(color_1));
7710 return(diversity);
7711}
7712
7713static int PopularityCompare(const void *x,const void *y)
7714{
7715 DiversityPacket
7716 *color_1,
7717 *color_2;
7718
7719 color_1=(DiversityPacket *) x;
7720 color_2=(DiversityPacket *) y;
7721 return((int) color_2->count-(int) color_1->count);
7722}
7723
7724#if defined(__cplusplus) || defined(c_plusplus)
7725}
7726#endif
7727
cristybb503372010-05-27 20:51:26 +00007728static inline Quantum ScaleXToQuantum(const size_t x,
7729 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007730{
cristya19f1d72012-08-07 18:24:38 +00007731 return((Quantum) (((double) QuantumRange*x)/scale+0.5));
cristy3ed852e2009-09-05 21:47:34 +00007732}
7733
cristybcbda3f2011-09-03 13:01:22 +00007734MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007735 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007736 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007737{
7738 Colormap
7739 colormap;
7740
cristybb503372010-05-27 20:51:26 +00007741 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007742 i;
7743
7744 Status
7745 status;
7746
cristybb503372010-05-27 20:51:26 +00007747 size_t
cristy3ed852e2009-09-05 21:47:34 +00007748 number_colors,
7749 retain_colors;
7750
7751 unsigned short
7752 gray_value;
7753
7754 XColor
7755 color,
7756 *colors,
7757 *p;
7758
7759 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7760 assert(display != (Display *) NULL);
7761 assert(visual_info != (XVisualInfo *) NULL);
7762 assert(map_info != (XStandardColormap *) NULL);
7763 assert(resource_info != (XResourceInfo *) NULL);
7764 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007765 if (resource_info->map_type != (char *) NULL)
7766 {
7767 /*
7768 Standard Colormap is already defined (i.e. xstdcmap).
7769 */
cristy4c08aed2011-07-01 19:47:50 +00007770 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007771 pixel);
7772 number_colors=(unsigned int) (map_info->base_pixel+
7773 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7774 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
cristy8a46d822012-08-28 23:32:39 +00007775 if ((image->alpha_trait != BlendPixelTrait) &&
cristy3ed852e2009-09-05 21:47:34 +00007776 (resource_info->color_recovery == MagickFalse) &&
cristycbda6112012-05-27 20:57:16 +00007777 (resource_info->quantize_info->dither_method != NoDitherMethod) &&
cristy3ed852e2009-09-05 21:47:34 +00007778 (number_colors < MaxColormapSize))
7779 {
7780 Image
7781 *affinity_image;
7782
cristy4c08aed2011-07-01 19:47:50 +00007783 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007784 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007785
7786 /*
7787 Improve image appearance with error diffusion.
7788 */
cristy6710d842011-10-20 23:23:00 +00007789 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007790 if (affinity_image == (Image *) NULL)
7791 ThrowXWindowFatalException(ResourceLimitFatalError,
7792 "UnableToDitherImage",image->filename);
7793 affinity_image->columns=number_colors;
7794 affinity_image->rows=1;
7795 /*
7796 Initialize colormap image.
7797 */
7798 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7799 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007800 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007801 {
cristybb503372010-05-27 20:51:26 +00007802 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007803 {
cristy4c08aed2011-07-01 19:47:50 +00007804 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007805 if (map_info->red_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007806 SetPixelRed(affinity_image,ScaleXToQuantum((size_t)
7807 (i/map_info->red_mult),map_info->red_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007808 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007809 if (map_info->green_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007810 SetPixelGreen(affinity_image,ScaleXToQuantum((size_t)
7811 ((i/map_info->green_mult) % (map_info->green_max+1)),
7812 map_info->green_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007813 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007814 if (map_info->blue_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007815 SetPixelBlue(affinity_image,ScaleXToQuantum((size_t)
7816 (i % map_info->green_mult),map_info->blue_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007817 SetPixelAlpha(affinity_image,
7818 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007819 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007820 }
7821 (void) SyncAuthenticPixels(affinity_image,exception);
7822 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007823 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007824 }
cristy4c08aed2011-07-01 19:47:50 +00007825 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007826 pixel);
cristy574cc262011-08-05 01:23:58 +00007827 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007828 affinity_image=DestroyImage(affinity_image);
7829 }
7830 if (IsEventLogging())
7831 {
7832 (void) LogMagickEvent(X11Event,GetMagickModule(),
7833 "Standard Colormap:");
7834 (void) LogMagickEvent(X11Event,GetMagickModule(),
7835 " colormap id: 0x%lx",map_info->colormap);
7836 (void) LogMagickEvent(X11Event,GetMagickModule(),
7837 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7838 map_info->green_max,map_info->blue_max);
7839 (void) LogMagickEvent(X11Event,GetMagickModule(),
7840 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7841 map_info->green_mult,map_info->blue_mult);
7842 }
7843 return;
7844 }
7845 if ((visual_info->klass != DirectColor) &&
7846 (visual_info->klass != TrueColor))
7847 if ((image->storage_class == DirectClass) ||
7848 ((int) image->colors > visual_info->colormap_size))
7849 {
7850 QuantizeInfo
7851 quantize_info;
7852
7853 /*
7854 Image has more colors than the visual supports.
7855 */
7856 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007857 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007858 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007859 }
7860 /*
7861 Free previous and create new colormap.
7862 */
7863 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7864 colormap=XDefaultColormap(display,visual_info->screen);
7865 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7866 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7867 visual_info->visual,visual_info->klass == DirectColor ?
7868 AllocAll : AllocNone);
7869 if (colormap == (Colormap) NULL)
7870 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7871 image->filename);
7872 /*
7873 Initialize the map and pixel info structures.
7874 */
7875 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007876 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007877 /*
7878 Allocating colors in server colormap is based on visual class.
7879 */
7880 switch (visual_info->klass)
7881 {
7882 case StaticGray:
7883 case StaticColor:
7884 {
7885 /*
7886 Define Standard Colormap for StaticGray or StaticColor visual.
7887 */
7888 number_colors=image->colors;
7889 colors=(XColor *) AcquireQuantumMemory((size_t)
7890 visual_info->colormap_size,sizeof(*colors));
7891 if (colors == (XColor *) NULL)
7892 ThrowXWindowFatalException(ResourceLimitFatalError,
7893 "UnableToCreateColormap",image->filename);
7894 p=colors;
7895 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007896 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007897 {
7898 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7899 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7900 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7901 if (visual_info->klass != StaticColor)
7902 {
7903 gray_value=(unsigned short) XPixelIntensity(&color);
7904 color.red=gray_value;
7905 color.green=gray_value;
7906 color.blue=gray_value;
7907 }
7908 status=XAllocColor(display,colormap,&color);
7909 if (status == False)
7910 {
7911 colormap=XCopyColormapAndFree(display,colormap);
7912 (void) XAllocColor(display,colormap,&color);
7913 }
7914 pixel->pixels[i]=color.pixel;
7915 *p++=color;
7916 }
7917 break;
7918 }
7919 case GrayScale:
7920 case PseudoColor:
7921 {
7922 unsigned int
7923 colormap_type;
7924
7925 /*
7926 Define Standard Colormap for GrayScale or PseudoColor visual.
7927 */
7928 number_colors=image->colors;
7929 colors=(XColor *) AcquireQuantumMemory((size_t)
7930 visual_info->colormap_size,sizeof(*colors));
7931 if (colors == (XColor *) NULL)
7932 ThrowXWindowFatalException(ResourceLimitFatalError,
7933 "UnableToCreateColormap",image->filename);
7934 /*
7935 Preallocate our GUI colors.
7936 */
7937 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7938 (void) XAllocColor(display,colormap,&pixel->background_color);
7939 (void) XAllocColor(display,colormap,&pixel->border_color);
7940 (void) XAllocColor(display,colormap,&pixel->matte_color);
7941 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7942 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7943 (void) XAllocColor(display,colormap,&pixel->depth_color);
7944 (void) XAllocColor(display,colormap,&pixel->trough_color);
7945 for (i=0; i < MaxNumberPens; i++)
7946 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7947 /*
7948 Determine if image colors will "fit" into X server colormap.
7949 */
7950 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007951 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007952 NULL,0,pixel->pixels,(unsigned int) image->colors);
7953 if (status != False)
7954 colormap_type=PrivateColormap;
7955 if (colormap_type == SharedColormap)
7956 {
cristyc57f6942010-11-12 01:47:39 +00007957 CacheView
7958 *image_view;
7959
cristy3ed852e2009-09-05 21:47:34 +00007960 DiversityPacket
7961 *diversity;
7962
7963 int
7964 y;
7965
7966 register int
7967 x;
7968
7969 unsigned short
7970 index;
7971
7972 XColor
7973 *server_colors;
7974
7975 /*
7976 Define Standard colormap for shared GrayScale or PseudoColor visual.
7977 */
7978 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7979 sizeof(*diversity));
7980 if (diversity == (DiversityPacket *) NULL)
7981 ThrowXWindowFatalException(ResourceLimitFatalError,
7982 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007983 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007984 {
cristye42f6582012-02-11 17:59:50 +00007985 diversity[i].red=ClampToQuantum(image->colormap[i].red);
7986 diversity[i].green=ClampToQuantum(image->colormap[i].green);
7987 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00007988 diversity[i].index=(unsigned short) i;
7989 diversity[i].count=0;
7990 }
cristy46ff2672012-12-14 15:32:26 +00007991 image_view=AcquireAuthenticCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007992 for (y=0; y < (int) image->rows; y++)
7993 {
cristyc57f6942010-11-12 01:47:39 +00007994 register int
cristy3ed852e2009-09-05 21:47:34 +00007995 x;
7996
cristy4c08aed2011-07-01 19:47:50 +00007997 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007998 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007999
cristyc57f6942010-11-12 01:47:39 +00008000 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8001 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008002 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008003 break;
cristyc57f6942010-11-12 01:47:39 +00008004 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008005 {
8006 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008007 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008008 }
cristy3ed852e2009-09-05 21:47:34 +00008009 }
cristyc57f6942010-11-12 01:47:39 +00008010 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008011 /*
8012 Sort colors by decreasing intensity.
8013 */
8014 qsort((void *) diversity,image->colors,sizeof(*diversity),
8015 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008016 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008017 {
8018 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008019 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008020 }
8021 diversity[image->colors-1].count<<=4;
8022 qsort((void *) diversity,image->colors,sizeof(*diversity),
8023 PopularityCompare);
8024 /*
8025 Allocate colors.
8026 */
8027 p=colors;
8028 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008029 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008030 {
8031 index=diversity[i].index;
8032 color.red=
8033 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8034 color.green=
8035 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8036 color.blue=
8037 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8038 if (visual_info->klass != PseudoColor)
8039 {
8040 gray_value=(unsigned short) XPixelIntensity(&color);
8041 color.red=gray_value;
8042 color.green=gray_value;
8043 color.blue=gray_value;
8044 }
8045 status=XAllocColor(display,colormap,&color);
8046 if (status == False)
8047 break;
8048 pixel->pixels[index]=color.pixel;
8049 *p++=color;
8050 }
8051 /*
8052 Read X server colormap.
8053 */
8054 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8055 visual_info->colormap_size,sizeof(*server_colors));
8056 if (server_colors == (XColor *) NULL)
8057 ThrowXWindowFatalException(ResourceLimitFatalError,
8058 "UnableToCreateColormap",image->filename);
8059 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008060 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008061 (void) XQueryColors(display,colormap,server_colors,
8062 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8063 /*
8064 Select remaining colors from X server colormap.
8065 */
cristybb503372010-05-27 20:51:26 +00008066 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008067 {
8068 index=diversity[i].index;
cristy534d0a32013-04-13 16:27:24 +00008069 color.red=ScaleQuantumToShort(
8070 XRedGamma(image->colormap[index].red));
8071 color.green=ScaleQuantumToShort(
8072 XGreenGamma(image->colormap[index].green));
8073 color.blue=ScaleQuantumToShort(
8074 XBlueGamma(image->colormap[index].blue));
cristy3ed852e2009-09-05 21:47:34 +00008075 if (visual_info->klass != PseudoColor)
8076 {
8077 gray_value=(unsigned short) XPixelIntensity(&color);
8078 color.red=gray_value;
8079 color.green=gray_value;
8080 color.blue=gray_value;
8081 }
8082 XBestPixel(display,colormap,server_colors,(unsigned int)
8083 visual_info->colormap_size,&color);
8084 pixel->pixels[index]=color.pixel;
8085 *p++=color;
8086 }
8087 if ((int) image->colors < visual_info->colormap_size)
8088 {
8089 /*
8090 Fill up colors array-- more choices for pen colors.
8091 */
8092 retain_colors=MagickMin((unsigned int)
8093 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008094 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008095 *p++=server_colors[i];
8096 number_colors+=retain_colors;
8097 }
8098 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8099 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8100 break;
8101 }
8102 /*
8103 Define Standard colormap for private GrayScale or PseudoColor visual.
8104 */
8105 if (status == False)
8106 {
8107 /*
8108 Not enough colormap entries in the colormap-- Create a new colormap.
8109 */
8110 colormap=XCreateColormap(display,
8111 XRootWindow(display,visual_info->screen),visual_info->visual,
8112 AllocNone);
8113 if (colormap == (Colormap) NULL)
8114 ThrowXWindowFatalException(ResourceLimitFatalError,
8115 "UnableToCreateColormap",image->filename);
8116 map_info->colormap=colormap;
8117 if ((int) image->colors < visual_info->colormap_size)
8118 {
8119 /*
8120 Retain colors from the default colormap to help lessens the
8121 effects of colormap flashing.
8122 */
8123 retain_colors=MagickMin((unsigned int)
8124 (visual_info->colormap_size-image->colors),256);
8125 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008126 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008127 {
cristyc57f6942010-11-12 01:47:39 +00008128 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008129 p++;
8130 }
8131 (void) XQueryColors(display,
8132 XDefaultColormap(display,visual_info->screen),
8133 colors+image->colors,(int) retain_colors);
8134 /*
8135 Transfer colors from default to private colormap.
8136 */
8137 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008138 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008139 retain_colors);
8140 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008141 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008142 {
8143 p->pixel=pixel->pixels[i];
8144 p++;
8145 }
8146 (void) XStoreColors(display,colormap,colors+image->colors,
8147 (int) retain_colors);
8148 number_colors+=retain_colors;
8149 }
8150 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008151 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008152 image->colors);
8153 }
8154 /*
8155 Store the image colormap.
8156 */
8157 p=colors;
8158 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008159 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008160 {
8161 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8162 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8163 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8164 if (visual_info->klass != PseudoColor)
8165 {
8166 gray_value=(unsigned short) XPixelIntensity(&color);
8167 color.red=gray_value;
8168 color.green=gray_value;
8169 color.blue=gray_value;
8170 }
8171 color.pixel=pixel->pixels[i];
8172 *p++=color;
8173 }
8174 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8175 break;
8176 }
8177 case TrueColor:
8178 case DirectColor:
8179 default:
8180 {
8181 MagickBooleanType
8182 linear_colormap;
8183
8184 /*
8185 Define Standard Colormap for TrueColor or DirectColor visual.
8186 */
8187 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8188 (map_info->green_max*map_info->green_mult)+
8189 (map_info->blue_max*map_info->blue_mult)+1);
8190 linear_colormap=(number_colors > 4096) ||
8191 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8192 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8193 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8194 MagickTrue : MagickFalse;
8195 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008196 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008197 /*
8198 Allocate color array.
8199 */
8200 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8201 if (colors == (XColor *) NULL)
8202 ThrowXWindowFatalException(ResourceLimitFatalError,
8203 "UnableToCreateColormap",image->filename);
8204 /*
8205 Initialize linear color ramp.
8206 */
8207 p=colors;
8208 color.flags=(char) (DoRed | DoGreen | DoBlue);
8209 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008210 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008211 {
8212 color.blue=(unsigned short) 0;
8213 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008214 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008215 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8216 color.green=color.blue;
8217 color.red=color.blue;
8218 color.pixel=XStandardPixel(map_info,&color);
8219 *p++=color;
8220 }
8221 else
cristybb503372010-05-27 20:51:26 +00008222 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008223 {
8224 color.red=(unsigned short) 0;
8225 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008226 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008227 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8228 color.green=(unsigned int) 0;
8229 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008230 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008231 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8232 map_info->green_max));
8233 color.blue=(unsigned short) 0;
8234 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008235 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008236 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8237 color.pixel=XStandardPixel(map_info,&color);
8238 *p++=color;
8239 }
8240 if ((visual_info->klass == DirectColor) &&
8241 (colormap != XDefaultColormap(display,visual_info->screen)))
8242 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8243 else
cristybb503372010-05-27 20:51:26 +00008244 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008245 (void) XAllocColor(display,colormap,&colors[i]);
8246 break;
8247 }
8248 }
8249 if ((visual_info->klass != DirectColor) &&
8250 (visual_info->klass != TrueColor))
8251 {
8252 /*
8253 Set foreground, background, border, etc. pixels.
8254 */
8255 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8256 &pixel->foreground_color);
8257 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8258 &pixel->background_color);
8259 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8260 {
8261 /*
8262 Foreground and background colors must differ.
8263 */
8264 pixel->background_color.red=(~pixel->foreground_color.red);
8265 pixel->background_color.green=
8266 (~pixel->foreground_color.green);
8267 pixel->background_color.blue=
8268 (~pixel->foreground_color.blue);
8269 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8270 &pixel->background_color);
8271 }
8272 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8273 &pixel->border_color);
8274 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8275 &pixel->matte_color);
8276 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8277 &pixel->highlight_color);
8278 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8279 &pixel->shadow_color);
8280 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8281 &pixel->depth_color);
8282 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8283 &pixel->trough_color);
8284 for (i=0; i < MaxNumberPens; i++)
8285 {
8286 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8287 &pixel->pen_colors[i]);
8288 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8289 }
cristyc57f6942010-11-12 01:47:39 +00008290 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008291 }
8292 colors=(XColor *) RelinquishMagickMemory(colors);
8293 if (IsEventLogging())
8294 {
8295 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8296 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8297 map_info->colormap);
8298 (void) LogMagickEvent(X11Event,GetMagickModule(),
8299 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8300 map_info->green_max,map_info->blue_max);
8301 (void) LogMagickEvent(X11Event,GetMagickModule(),
8302 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8303 map_info->green_mult,map_info->blue_mult);
8304 }
8305}
8306
8307/*
8308%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8309% %
8310% %
8311% %
8312% X M a k e W i n d o w %
8313% %
8314% %
8315% %
8316%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8317%
8318% XMakeWindow() creates an X11 window.
8319%
8320% The format of the XMakeWindow method is:
8321%
8322% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8323% XClassHint *class_hint,XWMHints *manager_hints,
8324% XWindowInfo *window_info)
8325%
8326% A description of each parameter follows:
8327%
8328% o display: Specifies a connection to an X server; returned from
8329% XOpenDisplay.
8330%
8331% o parent: Specifies the parent window_info.
8332%
8333% o argv: Specifies the application's argument list.
8334%
8335% o argc: Specifies the number of arguments.
8336%
8337% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8338%
8339% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8340%
8341% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8342%
8343*/
cristybcbda3f2011-09-03 13:01:22 +00008344MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008345 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8346 XWindowInfo *window_info)
8347{
8348#define MinWindowSize 64
8349
8350 Atom
8351 atom_list[2];
8352
8353 int
8354 gravity;
8355
8356 static XTextProperty
8357 icon_name,
8358 window_name;
8359
8360 Status
8361 status;
8362
8363 XSizeHints
8364 *size_hints;
8365
8366 /*
8367 Set window info hints.
8368 */
8369 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8370 assert(display != (Display *) NULL);
8371 assert(window_info != (XWindowInfo *) NULL);
8372 size_hints=XAllocSizeHints();
8373 if (size_hints == (XSizeHints *) NULL)
8374 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008375 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008376 size_hints->x=window_info->x;
8377 size_hints->y=window_info->y;
8378 size_hints->width=(int) window_info->width;
8379 size_hints->height=(int) window_info->height;
8380 if (window_info->immutable != MagickFalse)
8381 {
8382 /*
8383 Window size cannot be changed.
8384 */
8385 size_hints->min_width=size_hints->width;
8386 size_hints->min_height=size_hints->height;
8387 size_hints->max_width=size_hints->width;
8388 size_hints->max_height=size_hints->height;
8389 size_hints->flags|=PMinSize;
8390 size_hints->flags|=PMaxSize;
8391 }
8392 else
8393 {
8394 /*
8395 Window size can be changed.
8396 */
8397 size_hints->min_width=(int) window_info->min_width;
8398 size_hints->min_height=(int) window_info->min_height;
8399 size_hints->flags|=PResizeInc;
8400 size_hints->width_inc=(int) window_info->width_inc;
8401 size_hints->height_inc=(int) window_info->height_inc;
8402#if !defined(PRE_R4_ICCCM)
8403 size_hints->flags|=PBaseSize;
8404 size_hints->base_width=size_hints->width_inc;
8405 size_hints->base_height=size_hints->height_inc;
8406#endif
8407 }
8408 gravity=NorthWestGravity;
8409 if (window_info->geometry != (char *) NULL)
8410 {
8411 char
8412 default_geometry[MaxTextExtent],
8413 geometry[MaxTextExtent];
8414
8415 int
8416 flags;
8417
8418 register char
8419 *p;
8420
8421 /*
8422 User specified geometry.
8423 */
cristyb51dff52011-05-19 16:55:47 +00008424 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008425 size_hints->width,size_hints->height);
8426 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8427 p=geometry;
8428 while (strlen(p) != 0)
8429 {
8430 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8431 p++;
8432 else
8433 (void) CopyMagickString(p,p+1,MaxTextExtent);
8434 }
8435 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8436 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8437 &size_hints->width,&size_hints->height,&gravity);
8438 if ((flags & WidthValue) && (flags & HeightValue))
8439 size_hints->flags|=USSize;
8440 if ((flags & XValue) && (flags & YValue))
8441 {
8442 size_hints->flags|=USPosition;
8443 window_info->x=size_hints->x;
8444 window_info->y=size_hints->y;
8445 }
8446 }
8447#if !defined(PRE_R4_ICCCM)
8448 size_hints->win_gravity=gravity;
8449 size_hints->flags|=PWinGravity;
8450#endif
8451 if (window_info->id == (Window) NULL)
8452 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8453 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8454 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008455 window_info->visual,(unsigned long) window_info->mask,
8456 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008457 else
8458 {
8459 MagickStatusType
8460 mask;
8461
8462 XEvent
8463 sans_event;
8464
8465 XWindowChanges
8466 window_changes;
8467
8468 /*
8469 Window already exists; change relevant attributes.
8470 */
cristyc57f6942010-11-12 01:47:39 +00008471 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8472 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008473 mask=ConfigureNotify;
8474 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8475 window_changes.x=window_info->x;
8476 window_changes.y=window_info->y;
8477 window_changes.width=(int) window_info->width;
8478 window_changes.height=(int) window_info->height;
8479 mask=(MagickStatusType) (CWWidth | CWHeight);
8480 if (window_info->flags & USPosition)
8481 mask|=CWX | CWY;
8482 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8483 mask,&window_changes);
8484 }
8485 if (window_info->id == (Window) NULL)
8486 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8487 window_info->name);
8488 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8489 if (status == False)
8490 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8491 window_info->name);
8492 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8493 if (status == False)
8494 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8495 window_info->icon_name);
8496 if (window_info->icon_geometry != (char *) NULL)
8497 {
8498 int
8499 flags,
8500 height,
8501 width;
8502
8503 /*
8504 User specified icon geometry.
8505 */
8506 size_hints->flags|=USPosition;
8507 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8508 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8509 &manager_hints->icon_y,&width,&height,&gravity);
8510 if ((flags & XValue) && (flags & YValue))
8511 manager_hints->flags|=IconPositionHint;
8512 }
8513 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8514 size_hints,manager_hints,class_hint);
8515 if (window_name.value != (void *) NULL)
8516 {
8517 (void) XFree((void *) window_name.value);
8518 window_name.value=(unsigned char *) NULL;
8519 window_name.nitems=0;
8520 }
8521 if (icon_name.value != (void *) NULL)
8522 {
8523 (void) XFree((void *) icon_name.value);
8524 icon_name.value=(unsigned char *) NULL;
8525 icon_name.nitems=0;
8526 }
8527 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8528 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8529 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8530 (void) XFree((void *) size_hints);
8531 if (window_info->shape != MagickFalse)
8532 {
8533#if defined(MAGICKCORE_HAVE_SHAPE)
8534 int
8535 error_base,
8536 event_base;
8537
8538 /*
8539 Can we apply a non-rectangular shaping mask?
8540 */
8541 error_base=0;
8542 event_base=0;
8543 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8544 window_info->shape=MagickFalse;
8545#else
8546 window_info->shape=MagickFalse;
8547#endif
8548 }
8549 if (window_info->shared_memory)
8550 {
8551#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8552 /*
8553 Can we use shared memory with this window?
8554 */
8555 if (XShmQueryExtension(display) == 0)
8556 window_info->shared_memory=MagickFalse;
8557#else
8558 window_info->shared_memory=MagickFalse;
8559#endif
8560 }
8561 window_info->image=NewImageList();
8562 window_info->destroy=MagickFalse;
8563}
8564
8565/*
8566%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8567% %
8568% %
8569% %
8570% X M a g i c k P r o g r e s s M o n i t o r %
8571% %
8572% %
8573% %
8574%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8575%
8576% XMagickProgressMonitor() displays the progress a task is making in
8577% completing a task.
8578%
8579% The format of the XMagickProgressMonitor method is:
8580%
8581% void XMagickProgressMonitor(const char *task,
8582% const MagickOffsetType quantum,const MagickSizeType span,
8583% void *client_data)
8584%
8585% A description of each parameter follows:
8586%
8587% o task: Identifies the task in progress.
8588%
8589% o quantum: Specifies the quantum position within the span which represents
8590% how much progress has been made in completing a task.
8591%
8592% o span: Specifies the span relative to completing a task.
8593%
8594% o client_data: Pointer to any client data.
8595%
8596*/
8597
8598static const char *GetLocaleMonitorMessage(const char *text)
8599{
8600 char
8601 message[MaxTextExtent],
8602 tag[MaxTextExtent];
8603
8604 const char
8605 *locale_message;
8606
8607 register char
8608 *p;
8609
8610 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8611 p=strrchr(tag,'/');
8612 if (p != (char *) NULL)
8613 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008614 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008615 locale_message=GetLocaleMessage(message);
8616 if (locale_message == message)
8617 return(text);
8618 return(locale_message);
8619}
8620
cristybcbda3f2011-09-03 13:01:22 +00008621MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008622 const MagickOffsetType quantum,const MagickSizeType span,
8623 void *magick_unused(client_data))
8624{
8625 XWindows
8626 *windows;
8627
8628 windows=XSetWindows((XWindows *) ~0);
8629 if (windows == (XWindows *) NULL)
8630 return(MagickTrue);
8631 if (windows->info.mapped != MagickFalse)
8632 XProgressMonitorWidget(windows->display,windows,
8633 GetLocaleMonitorMessage(tag),quantum,span);
8634 return(MagickTrue);
8635}
8636
8637/*
8638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8639% %
8640% %
8641% %
8642% X Q u e r y C o l o r D a t a b a s e %
8643% %
8644% %
8645% %
8646%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8647%
cristy9950d572011-10-01 18:22:35 +00008648% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008649% string.
8650%
8651% The format of the XQueryColorDatabase method is:
8652%
cristy9950d572011-10-01 18:22:35 +00008653% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008654%
8655% A description of each parameter follows:
8656%
8657% o target: Specifies the color to lookup in the X color database.
8658%
cristy101ab702011-10-13 13:06:32 +00008659% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008660% color is returned as this value.
8661%
8662*/
cristy9950d572011-10-01 18:22:35 +00008663MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008664 XColor *color)
8665{
8666 Colormap
8667 colormap;
8668
8669 static Display
8670 *display = (Display *) NULL;
8671
8672 Status
8673 status;
8674
8675 XColor
8676 xcolor;
8677
8678 /*
8679 Initialize color return value.
8680 */
8681 assert(color != (XColor *) NULL);
8682 color->red=0;
8683 color->green=0;
8684 color->blue=0;
8685 color->flags=(char) (DoRed | DoGreen | DoBlue);
8686 if ((target == (char *) NULL) || (*target == '\0'))
8687 target="#ffffffffffff";
8688 /*
8689 Let the X server define the color for us.
8690 */
8691 if (display == (Display *) NULL)
8692 display=XOpenDisplay((char *) NULL);
8693 if (display == (Display *) NULL)
8694 {
cristyc38fbf52013-11-03 13:55:54 +00008695 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target);
cristy3ed852e2009-09-05 21:47:34 +00008696 return(MagickFalse);
8697 }
8698 colormap=XDefaultColormap(display,XDefaultScreen(display));
8699 status=XParseColor(display,colormap,(char *) target,&xcolor);
8700 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00008701 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target)
cristy3ed852e2009-09-05 21:47:34 +00008702 else
8703 {
8704 color->red=xcolor.red;
8705 color->green=xcolor.green;
8706 color->blue=xcolor.blue;
8707 color->flags=xcolor.flags;
8708 }
8709 return(status != False ? MagickTrue : MagickFalse);
8710}
8711
8712/*
8713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8714% %
8715% %
8716% %
8717% X Q u e r y P o s i t i o n %
8718% %
8719% %
8720% %
8721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8722%
8723% XQueryPosition() gets the pointer coordinates relative to a window.
8724%
8725% The format of the XQueryPosition method is:
8726%
8727% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8728%
8729% A description of each parameter follows:
8730%
8731% o display: Specifies a connection to an X server; returned from
8732% XOpenDisplay.
8733%
8734% o window: Specifies a pointer to a Window.
8735%
8736% o x: Return the x coordinate of the pointer relative to the origin of the
8737% window.
8738%
8739% o y: Return the y coordinate of the pointer relative to the origin of the
8740% window.
8741%
8742*/
cristy534d0a32013-04-13 16:27:24 +00008743MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,
8744 int *y)
cristy3ed852e2009-09-05 21:47:34 +00008745{
8746 int
8747 x_root,
8748 y_root;
8749
8750 unsigned int
8751 mask;
8752
8753 Window
8754 root_window;
8755
8756 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8757 assert(display != (Display *) NULL);
8758 assert(window != (Window) NULL);
8759 assert(x != (int *) NULL);
8760 assert(y != (int *) NULL);
8761 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8762 x,y,&mask);
8763}
8764
8765/*
8766%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8767% %
8768% %
8769% %
8770% X R e f r e s h W i n d o w %
8771% %
8772% %
8773% %
8774%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8775%
8776% XRefreshWindow() refreshes an image in a X window.
8777%
8778% The format of the XRefreshWindow method is:
8779%
8780% void XRefreshWindow(Display *display,const XWindowInfo *window,
8781% const XEvent *event)
8782%
8783% A description of each parameter follows:
8784%
8785% o display: Specifies a connection to an X server; returned from
8786% XOpenDisplay.
8787%
8788% o window: Specifies a pointer to a XWindowInfo structure.
8789%
8790% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8791% the entire image is refreshed.
8792%
8793*/
cristybcbda3f2011-09-03 13:01:22 +00008794MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008795 const XEvent *event)
8796{
8797 int
8798 x,
8799 y;
8800
8801 unsigned int
8802 height,
8803 width;
8804
8805 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8806 assert(display != (Display *) NULL);
8807 assert(window != (XWindowInfo *) NULL);
8808 if (window->ximage == (XImage *) NULL)
8809 return;
8810 if (event != (XEvent *) NULL)
8811 {
8812 /*
8813 Determine geometry from expose event.
8814 */
8815 x=event->xexpose.x;
8816 y=event->xexpose.y;
8817 width=(unsigned int) event->xexpose.width;
8818 height=(unsigned int) event->xexpose.height;
8819 }
8820 else
8821 {
8822 XEvent
8823 sans_event;
8824
8825 /*
8826 Refresh entire window; discard outstanding expose events.
8827 */
8828 x=0;
8829 y=0;
8830 width=window->width;
8831 height=window->height;
8832 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008833 if (window->matte_pixmap != (Pixmap) NULL)
8834 {
8835#if defined(MAGICKCORE_HAVE_SHAPE)
8836 if (window->shape != MagickFalse)
8837 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8838 window->matte_pixmap,ShapeSet);
8839#endif
8840 }
cristy3ed852e2009-09-05 21:47:34 +00008841 }
8842 /*
8843 Check boundary conditions.
8844 */
8845 if ((window->ximage->width-(x+window->x)) < (int) width)
8846 width=(unsigned int) (window->ximage->width-(x+window->x));
8847 if ((window->ximage->height-(y+window->y)) < (int) height)
8848 height=(unsigned int) (window->ximage->height-(y+window->y));
8849 /*
8850 Refresh image.
8851 */
8852 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008853 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008854 if (window->pixmap != (Pixmap) NULL)
8855 {
8856 if (window->depth > 1)
8857 (void) XCopyArea(display,window->pixmap,window->id,
8858 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8859 else
8860 (void) XCopyPlane(display,window->pixmap,window->id,
8861 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8862 1L);
8863 }
8864 else
8865 {
8866#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8867 if (window->shared_memory)
8868 (void) XShmPutImage(display,window->id,window->annotate_context,
8869 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8870#endif
8871 if (window->shared_memory == MagickFalse)
8872 (void) XPutImage(display,window->id,window->annotate_context,
8873 window->ximage,x+window->x,y+window->y,x,y,width,height);
8874 }
8875 if (window->matte_pixmap != (Pixmap) NULL)
8876 (void) XSetClipMask(display,window->annotate_context,None);
8877 (void) XFlush(display);
8878}
8879
8880/*
8881%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8882% %
8883% %
8884% %
8885% X R e m o t e C o m m a n d %
8886% %
8887% %
8888% %
8889%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8890%
8891% XRemoteCommand() forces a remote display(1) to display the specified
8892% image filename.
8893%
8894% The format of the XRemoteCommand method is:
8895%
8896% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8897% const char *filename)
8898%
8899% A description of each parameter follows:
8900%
8901% o display: Specifies a connection to an X server; returned from
8902% XOpenDisplay.
8903%
8904% o window: Specifies the name or id of an X window.
8905%
8906% o filename: the name of the image filename to display.
8907%
8908*/
8909MagickExport MagickBooleanType XRemoteCommand(Display *display,
8910 const char *window,const char *filename)
8911{
8912 Atom
8913 remote_atom;
8914
8915 Window
8916 remote_window,
8917 root_window;
8918
8919 assert(filename != (char *) NULL);
8920 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8921 if (display == (Display *) NULL)
8922 display=XOpenDisplay((char *) NULL);
8923 if (display == (Display *) NULL)
8924 {
8925 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8926 return(MagickFalse);
8927 }
8928 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8929 remote_window=(Window) NULL;
8930 root_window=XRootWindow(display,XDefaultScreen(display));
8931 if (window != (char *) NULL)
8932 {
8933 /*
8934 Search window hierarchy and identify any clients by name or ID.
8935 */
cristy02e64f82013-11-14 16:20:04 +00008936 if (isdigit((int) ((unsigned char) *window)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00008937 remote_window=XWindowByID(display,root_window,(Window)
8938 strtol((char *) window,(char **) NULL,0));
8939 if (remote_window == (Window) NULL)
8940 remote_window=XWindowByName(display,root_window,window);
8941 }
8942 if (remote_window == (Window) NULL)
8943 remote_window=XWindowByProperty(display,root_window,remote_atom);
8944 if (remote_window == (Window) NULL)
8945 {
8946 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8947 filename);
8948 return(MagickFalse);
8949 }
8950 /*
8951 Send remote command.
8952 */
8953 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8954 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8955 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8956 (void) XSync(display,MagickFalse);
8957 return(MagickTrue);
8958}
8959
8960/*
8961%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8962% %
8963% %
8964% %
cristy534d0a32013-04-13 16:27:24 +00008965% X R e n d e r I m a g e %
8966% %
8967% %
8968% %
8969%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8970%
8971% XRenderImage() renders text on the image with an X11 font. It also returns
8972% the bounding box of the text relative to the image.
8973%
8974% The format of the XRenderImage method is:
8975%
8976% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
8977% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
8978%
8979% A description of each parameter follows:
8980%
8981% o image: the image.
8982%
8983% o draw_info: the draw info.
8984%
8985% o offset: (x,y) location of text relative to image.
8986%
8987% o metrics: bounding box of text.
8988%
8989% o exception: return any errors or warnings in this structure.
8990%
8991*/
8992MagickPrivate MagickBooleanType XRenderImage(Image *image,
8993 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
8994 ExceptionInfo *exception)
8995{
8996 const char
8997 *client_name;
8998
8999 DrawInfo
9000 cache_info;
9001
9002 Display
9003 *display;
9004
9005 ImageInfo
9006 *image_info;
9007
9008 MagickBooleanType
9009 status;
9010
9011 size_t
9012 height,
9013 width;
9014
9015 XAnnotateInfo
9016 annotate_info;
9017
9018 XFontStruct
9019 *font_info;
9020
9021 XPixelInfo
9022 pixel;
9023
9024 XResourceInfo
9025 resource_info;
9026
9027 XrmDatabase
9028 resource_database;
9029
9030 XStandardColormap
9031 *map_info;
9032
9033 XVisualInfo
9034 *visual_info;
9035
9036 /*
9037 Open X server connection.
9038 */
9039 display=XOpenDisplay(draw_info->server_name);
9040 if (display == (Display *) NULL)
9041 {
9042 ThrowXWindowException(XServerError,"UnableToOpenXServer",
9043 draw_info->server_name);
9044 return(MagickFalse);
9045 }
9046 /*
9047 Get user defaults from X resource database.
9048 */
9049 (void) XSetErrorHandler(XError);
9050 image_info=AcquireImageInfo();
9051 client_name=GetClientName();
9052 resource_database=XGetResourceDatabase(display,client_name);
9053 XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
9054 resource_info.close_server=MagickFalse;
9055 resource_info.colormap=PrivateColormap;
9056 resource_info.font=AcquireString(draw_info->font);
9057 resource_info.background_color=AcquireString("#ffffffffffff");
9058 resource_info.foreground_color=AcquireString("#000000000000");
9059 map_info=XAllocStandardColormap();
9060 if (map_info == (XStandardColormap *) NULL)
9061 {
9062 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9063 image->filename);
9064 return(MagickFalse);
9065 }
9066 /*
9067 Initialize visual info.
9068 */
9069 visual_info=XBestVisualInfo(display,map_info,&resource_info);
9070 if (visual_info == (XVisualInfo *) NULL)
9071 {
cristyc38fbf52013-11-03 13:55:54 +00009072 ThrowXWindowException(XServerError,"UnableToGetVisual",image->filename);
cristy534d0a32013-04-13 16:27:24 +00009073 return(MagickFalse);
9074 }
9075 map_info->colormap=(Colormap) NULL;
9076 pixel.pixels=(unsigned long *) NULL;
9077 /*
9078 Initialize Standard Colormap info.
9079 */
9080 XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
9081 map_info);
9082 XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
9083 &pixel);
9084 pixel.annotate_context=XDefaultGC(display,visual_info->screen);
9085 /*
9086 Initialize font info.
9087 */
9088 font_info=XBestFont(display,&resource_info,MagickFalse);
9089 if (font_info == (XFontStruct *) NULL)
9090 {
9091 ThrowXWindowException(XServerError,"UnableToLoadFont",draw_info->font);
9092 return(MagickFalse);
9093 }
9094 if ((map_info == (XStandardColormap *) NULL) ||
9095 (visual_info == (XVisualInfo *) NULL) ||
9096 (font_info == (XFontStruct *) NULL))
9097 {
9098 XFreeResources(display,visual_info,map_info,&pixel,font_info,
9099 &resource_info,(XWindowInfo *) NULL);
9100 ThrowXWindowException(XServerError,"UnableToLoadFont",image->filename);
9101 return(MagickFalse);
9102 }
9103 cache_info=(*draw_info);
9104 /*
9105 Initialize annotate info.
9106 */
9107 XGetAnnotateInfo(&annotate_info);
9108 annotate_info.stencil=ForegroundStencil;
9109 if (cache_info.font != draw_info->font)
9110 {
9111 /*
9112 Type name has changed.
9113 */
9114 (void) XFreeFont(display,font_info);
9115 (void) CloneString(&resource_info.font,draw_info->font);
9116 font_info=XBestFont(display,&resource_info,MagickFalse);
9117 if (font_info == (XFontStruct *) NULL)
9118 {
9119 ThrowXWindowException(XServerError,"UnableToLoadFont",
9120 draw_info->font);
9121 return(MagickFalse);
9122 }
9123 }
9124 if (image->debug != MagickFalse)
9125 (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
9126 "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
9127 draw_info->font : "none",draw_info->pointsize);
9128 cache_info=(*draw_info);
9129 annotate_info.font_info=font_info;
9130 annotate_info.text=(char *) draw_info->text;
9131 annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
9132 strlen(draw_info->text));
9133 annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
9134 metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
9135 metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
9136 metrics->ascent=(double) font_info->ascent+4;
9137 metrics->descent=(double) (-font_info->descent);
9138 metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
9139 metrics->height=font_info->ascent+font_info->descent;
9140 metrics->max_advance=(double) font_info->max_bounds.width;
9141 metrics->bounds.x1=0.0;
9142 metrics->bounds.y1=metrics->descent;
9143 metrics->bounds.x2=metrics->ascent+metrics->descent;
9144 metrics->bounds.y2=metrics->ascent+metrics->descent;
9145 metrics->underline_position=(-2.0);
9146 metrics->underline_thickness=1.0;
9147 if (draw_info->render == MagickFalse)
9148 return(MagickTrue);
9149 if (draw_info->fill.alpha == TransparentAlpha)
9150 return(MagickTrue);
9151 /*
9152 Render fill color.
9153 */
9154 width=annotate_info.width;
9155 height=annotate_info.height;
9156 if ((fabs(draw_info->affine.rx) >= MagickEpsilon) ||
9157 (fabs(draw_info->affine.ry) >= MagickEpsilon))
9158 {
9159 if ((fabs(draw_info->affine.sx-draw_info->affine.sy) < MagickEpsilon) &&
9160 (fabs(draw_info->affine.rx+draw_info->affine.ry) < MagickEpsilon))
9161 annotate_info.degrees=(double) (180.0/MagickPI)*
9162 atan2(draw_info->affine.rx,draw_info->affine.sx);
9163 }
9164 (void) FormatLocaleString(annotate_info.geometry,MaxTextExtent,
9165 "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
9166 ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
9167 draw_info->interline_spacing-0.5));
9168 pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
9169 pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
9170 pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);
9171 status=XAnnotateImage(display,&pixel,&annotate_info,image,exception);
9172 if (status == 0)
9173 {
9174 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9175 image->filename);
9176 return(MagickFalse);
9177 }
9178 return(MagickTrue);
9179}
9180
9181/*
9182%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9183% %
9184% %
9185% %
cristy3ed852e2009-09-05 21:47:34 +00009186% X R e t a i n W i n d o w C o l o r s %
9187% %
9188% %
9189% %
9190%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9191%
9192% XRetainWindowColors() sets X11 color resources on a window. This preserves
9193% the colors associated with an image displayed on the window.
9194%
9195% The format of the XRetainWindowColors method is:
9196%
9197% void XRetainWindowColors(Display *display,const Window window)
9198%
9199% A description of each parameter follows:
9200%
9201% o display: Specifies a connection to an X server; returned from
9202% XOpenDisplay.
9203%
9204% o window: Specifies a pointer to a XWindowInfo structure.
9205%
9206*/
9207MagickExport void XRetainWindowColors(Display *display,const Window window)
9208{
9209 Atom
9210 property;
9211
9212 Pixmap
9213 pixmap;
9214
9215 /*
9216 Put property on the window.
9217 */
9218 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9219 assert(display != (Display *) NULL);
9220 assert(window != (Window) NULL);
9221 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9222 if (property == (Atom) NULL)
9223 {
cristyc38fbf52013-11-03 13:55:54 +00009224 ThrowXWindowException(XServerError,"UnableToCreateProperty",
cristy3ed852e2009-09-05 21:47:34 +00009225 "_XSETROOT_ID");
9226 return;
9227 }
9228 pixmap=XCreatePixmap(display,window,1,1,1);
9229 if (pixmap == (Pixmap) NULL)
9230 {
cristyc38fbf52013-11-03 13:55:54 +00009231 ThrowXWindowException(XServerError,"UnableToCreateBitmap","");
cristy3ed852e2009-09-05 21:47:34 +00009232 return;
9233 }
9234 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9235 (unsigned char *) &pixmap,1);
9236 (void) XSetCloseDownMode(display,RetainPermanent);
9237}
9238
9239/*
9240%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9241% %
9242% %
9243% %
9244% X S e l e c t W i n d o w %
9245% %
9246% %
9247% %
9248%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9249%
9250% XSelectWindow() allows a user to select a window using the mouse. If the
9251% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9252% is returned in the crop_info structure.
9253%
9254% The format of the XSelectWindow function is:
9255%
9256% target_window=XSelectWindow(display,crop_info)
9257%
9258% A description of each parameter follows:
9259%
9260% o window: XSelectWindow returns the window id.
9261%
9262% o display: Specifies a pointer to the Display structure; returned from
9263% XOpenDisplay.
9264%
9265% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9266% contains the extents of any cropping rectangle.
9267%
cristy3ed852e2009-09-05 21:47:34 +00009268*/
9269static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9270{
9271#define MinimumCropArea (unsigned int) 9
9272
9273 Cursor
9274 target_cursor;
9275
9276 GC
9277 annotate_context;
9278
9279 int
9280 presses,
9281 x_offset,
9282 y_offset;
9283
9284 Status
9285 status;
9286
9287 Window
9288 root_window,
9289 target_window;
9290
9291 XEvent
9292 event;
9293
9294 XGCValues
9295 context_values;
9296
9297 /*
9298 Initialize graphic context.
9299 */
9300 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9301 assert(display != (Display *) NULL);
9302 assert(crop_info != (RectangleInfo *) NULL);
9303 root_window=XRootWindow(display,XDefaultScreen(display));
9304 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9305 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9306 context_values.function=GXinvert;
9307 context_values.plane_mask=
9308 context_values.background ^ context_values.foreground;
9309 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009310 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009311 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9312 if (annotate_context == (GC) NULL)
9313 return(MagickFalse);
9314 /*
9315 Grab the pointer using target cursor.
9316 */
9317 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9318 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9319 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9320 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9321 GrabModeAsync,root_window,target_cursor,CurrentTime);
9322 if (status != GrabSuccess)
9323 {
cristyc38fbf52013-11-03 13:55:54 +00009324 ThrowXWindowException(XServerError,"UnableToGrabMouse","");
cristy3ed852e2009-09-05 21:47:34 +00009325 return((Window) NULL);
9326 }
9327 /*
9328 Select a window.
9329 */
9330 crop_info->width=0;
9331 crop_info->height=0;
9332 presses=0;
9333 target_window=(Window) NULL;
9334 x_offset=0;
9335 y_offset=0;
9336 do
9337 {
9338 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9339 (void) XDrawRectangle(display,root_window,annotate_context,
9340 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9341 (unsigned int) crop_info->height-1);
9342 /*
9343 Allow another event.
9344 */
9345 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9346 (void) XWindowEvent(display,root_window,ButtonPressMask |
9347 ButtonReleaseMask | ButtonMotionMask,&event);
9348 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9349 (void) XDrawRectangle(display,root_window,annotate_context,
9350 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9351 (unsigned int) crop_info->height-1);
9352 switch (event.type)
9353 {
9354 case ButtonPress:
9355 {
9356 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9357 event.xbutton.x,event.xbutton.y);
9358 if (target_window == (Window) NULL)
9359 target_window=root_window;
9360 x_offset=event.xbutton.x_root;
9361 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009362 crop_info->x=(ssize_t) x_offset;
9363 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009364 crop_info->width=0;
9365 crop_info->height=0;
9366 presses++;
9367 break;
9368 }
9369 case ButtonRelease:
9370 {
9371 presses--;
9372 break;
9373 }
9374 case MotionNotify:
9375 {
9376 /*
9377 Discard pending button motion events.
9378 */
9379 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009380 crop_info->x=(ssize_t) event.xmotion.x;
9381 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009382 /*
9383 Check boundary conditions.
9384 */
9385 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009386 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009387 else
9388 {
cristyecd0ab52010-05-30 14:59:20 +00009389 crop_info->width=(size_t) (crop_info->x-x_offset);
9390 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009391 }
9392 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009393 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009394 else
9395 {
cristyecd0ab52010-05-30 14:59:20 +00009396 crop_info->height=(size_t) (crop_info->y-y_offset);
9397 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009398 }
9399 }
9400 default:
9401 break;
9402 }
9403 } while ((target_window == (Window) NULL) || (presses > 0));
9404 (void) XUngrabPointer(display,CurrentTime);
9405 (void) XFreeCursor(display,target_cursor);
9406 (void) XFreeGC(display,annotate_context);
9407 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9408 {
9409 crop_info->width=0;
9410 crop_info->height=0;
9411 }
9412 if ((crop_info->width != 0) && (crop_info->height != 0))
9413 target_window=root_window;
9414 return(target_window);
9415}
9416
9417/*
9418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9419% %
9420% %
9421% %
9422% X S e t C u r s o r S t a t e %
9423% %
9424% %
9425% %
9426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9427%
9428% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9429% reset to their default.
9430%
9431% The format of the XXSetCursorState method is:
9432%
9433% XSetCursorState(display,windows,const MagickStatusType state)
9434%
9435% A description of each parameter follows:
9436%
9437% o display: Specifies a connection to an X server; returned from
9438% XOpenDisplay.
9439%
9440% o windows: Specifies a pointer to a XWindows structure.
9441%
9442% o state: An unsigned integer greater than 0 sets the cursor state
9443% to busy, otherwise the cursor are reset to their default.
9444%
9445*/
cristybcbda3f2011-09-03 13:01:22 +00009446MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009447 const MagickStatusType state)
9448{
9449 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9450 assert(display != (Display *) NULL);
9451 assert(windows != (XWindows *) NULL);
9452 if (state)
9453 {
9454 (void) XCheckDefineCursor(display,windows->image.id,
9455 windows->image.busy_cursor);
9456 (void) XCheckDefineCursor(display,windows->pan.id,
9457 windows->pan.busy_cursor);
9458 (void) XCheckDefineCursor(display,windows->magnify.id,
9459 windows->magnify.busy_cursor);
9460 (void) XCheckDefineCursor(display,windows->command.id,
9461 windows->command.busy_cursor);
9462 }
9463 else
9464 {
9465 (void) XCheckDefineCursor(display,windows->image.id,
9466 windows->image.cursor);
9467 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9468 (void) XCheckDefineCursor(display,windows->magnify.id,
9469 windows->magnify.cursor);
9470 (void) XCheckDefineCursor(display,windows->command.id,
9471 windows->command.cursor);
9472 (void) XCheckDefineCursor(display,windows->command.id,
9473 windows->widget.cursor);
9474 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9475 }
9476 windows->info.mapped=MagickFalse;
9477}
9478
9479/*
9480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9481% %
9482% %
9483% %
9484% X S e t W i n d o w s %
9485% %
9486% %
9487% %
9488%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9489%
9490% XSetWindows() sets the X windows structure if the windows info is specified.
9491% Otherwise the current windows structure is returned.
9492%
9493% The format of the XSetWindows method is:
9494%
9495% XWindows *XSetWindows(XWindows *windows_info)
9496%
9497% A description of each parameter follows:
9498%
9499% o windows_info: Initialize the Windows structure with this information.
9500%
9501*/
cristybcbda3f2011-09-03 13:01:22 +00009502MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009503{
9504 static XWindows
9505 *windows = (XWindows *) NULL;
9506
9507 if (windows_info != (XWindows *) ~0)
9508 {
9509 windows=(XWindows *) RelinquishMagickMemory(windows);
9510 windows=windows_info;
9511 }
9512 return(windows);
9513}
9514/*
9515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9516% %
9517% %
9518% %
9519% X U s e r P r e f e r e n c e s %
9520% %
9521% %
9522% %
9523%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9524%
9525% XUserPreferences() saves the preferences in a configuration file in the
9526% users' home directory.
9527%
9528% The format of the XUserPreferences method is:
9529%
9530% void XUserPreferences(XResourceInfo *resource_info)
9531%
9532% A description of each parameter follows:
9533%
9534% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9535%
9536*/
cristybcbda3f2011-09-03 13:01:22 +00009537MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009538{
9539#if defined(X11_PREFERENCES_PATH)
9540 char
9541 cache[MaxTextExtent],
9542 filename[MaxTextExtent],
9543 specifier[MaxTextExtent];
9544
9545 const char
cristy104cea82009-10-25 02:26:51 +00009546 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009547 *value;
9548
9549 XrmDatabase
9550 preferences_database;
9551
9552 /*
9553 Save user preferences to the client configuration file.
9554 */
9555 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009556 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009557 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009558 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009559 value=resource_info->backdrop ? "True" : "False";
9560 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009561 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009562 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9563 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009564 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009565 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009566 value=resource_info->confirm_exit ? "True" : "False";
9567 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009568 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009569 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009570 value=resource_info->confirm_edit ? "True" : "False";
9571 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009572 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009573 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009574 value=resource_info->display_warnings ? "True" : "False";
9575 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009576 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristycbda6112012-05-27 20:57:16 +00009577 value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9578 "True" : "False";
cristy3ed852e2009-09-05 21:47:34 +00009579 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009580 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009581 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009582 value=resource_info->gamma_correct ? "True" : "False";
9583 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009584 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9585 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009586 resource_info->undo_cache);
9587 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009588 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009589 value=resource_info->use_pixmap ? "True" : "False";
9590 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009591 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009592 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009593 ExpandFilename(filename);
9594 XrmPutFileDatabase(preferences_database,filename);
9595#endif
9596}
9597
9598/*
9599%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9600% %
9601% %
9602% %
9603% X V i s u a l C l a s s N a m e %
9604% %
9605% %
9606% %
9607%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9608%
9609% XVisualClassName() returns the visual class name as a character string.
9610%
9611% The format of the XVisualClassName method is:
9612%
9613% char *XVisualClassName(const int visual_class)
9614%
9615% A description of each parameter follows:
9616%
9617% o visual_type: XVisualClassName returns the visual class as a character
9618% string.
9619%
9620% o class: Specifies the visual class.
9621%
cristy3ed852e2009-09-05 21:47:34 +00009622*/
9623static const char *XVisualClassName(const int visual_class)
9624{
9625 switch (visual_class)
9626 {
9627 case StaticGray: return("StaticGray");
9628 case GrayScale: return("GrayScale");
9629 case StaticColor: return("StaticColor");
9630 case PseudoColor: return("PseudoColor");
9631 case TrueColor: return("TrueColor");
9632 case DirectColor: return("DirectColor");
9633 }
9634 return("unknown visual class");
9635}
9636
9637/*
9638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9639% %
9640% %
9641% %
9642% X W a r n i n g %
9643% %
9644% %
9645% %
9646%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9647%
9648% XWarning() displays a warning reason in a Notice widget.
9649%
9650% The format of the XWarning method is:
9651%
9652% void XWarning(const unsigned int warning,const char *reason,
9653% const char *description)
9654%
9655% A description of each parameter follows:
9656%
9657% o warning: Specifies the numeric warning category.
9658%
9659% o reason: Specifies the reason to display before terminating the
9660% program.
9661%
9662% o description: Specifies any description to the reason.
9663%
9664*/
cristybcbda3f2011-09-03 13:01:22 +00009665MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009666 const char *reason,const char *description)
9667{
9668 char
9669 text[MaxTextExtent];
9670
9671 XWindows
9672 *windows;
9673
9674 if (reason == (char *) NULL)
9675 return;
9676 (void) CopyMagickString(text,reason,MaxTextExtent);
9677 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9678 windows=XSetWindows((XWindows *) ~0);
9679 XNoticeWidget(windows->display,windows,text,(char *) description);
9680}
9681
9682/*
9683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9684% %
9685% %
9686% %
9687% X W i n d o w B y I D %
9688% %
9689% %
9690% %
9691%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9692%
9693% XWindowByID() locates a child window with a given ID. If not window with
9694% the given name is found, 0 is returned. Only the window specified and its
9695% subwindows are searched.
9696%
9697% The format of the XWindowByID function is:
9698%
9699% child=XWindowByID(display,window,id)
9700%
9701% A description of each parameter follows:
9702%
9703% o child: XWindowByID returns the window with the specified
9704% id. If no windows are found, XWindowByID returns 0.
9705%
9706% o display: Specifies a pointer to the Display structure; returned from
9707% XOpenDisplay.
9708%
9709% o id: Specifies the id of the window to locate.
9710%
9711*/
cristybcbda3f2011-09-03 13:01:22 +00009712MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009713 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009714{
9715 RectangleInfo
9716 rectangle_info;
9717
9718 register int
9719 i;
9720
9721 Status
9722 status;
9723
9724 unsigned int
9725 number_children;
9726
9727 Window
9728 child,
9729 *children,
9730 window;
9731
9732 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9733 assert(display != (Display *) NULL);
9734 assert(root_window != (Window) NULL);
9735 if (id == 0)
9736 return(XSelectWindow(display,&rectangle_info));
9737 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009738 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009739 status=XQueryTree(display,root_window,&child,&child,&children,
9740 &number_children);
9741 if (status == False)
9742 return((Window) NULL);
9743 window=(Window) NULL;
9744 for (i=0; i < (int) number_children; i++)
9745 {
9746 /*
9747 Search each child and their children.
9748 */
9749 window=XWindowByID(display,children[i],id);
9750 if (window != (Window) NULL)
9751 break;
9752 }
9753 if (children != (Window *) NULL)
9754 (void) XFree((void *) children);
9755 return(window);
9756}
9757
9758/*
9759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9760% %
9761% %
9762% %
9763% X W i n d o w B y N a m e %
9764% %
9765% %
9766% %
9767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9768%
9769% XWindowByName() locates a window with a given name on a display. If no
9770% window with the given name is found, 0 is returned. If more than one window
9771% has the given name, the first one is returned. Only root and its children
9772% are searched.
9773%
9774% The format of the XWindowByName function is:
9775%
9776% window=XWindowByName(display,root_window,name)
9777%
9778% A description of each parameter follows:
9779%
9780% o window: XWindowByName returns the window id.
9781%
9782% o display: Specifies a pointer to the Display structure; returned from
9783% XOpenDisplay.
9784%
9785% o root_window: Specifies the id of the root window.
9786%
9787% o name: Specifies the name of the window to locate.
9788%
9789*/
cristybcbda3f2011-09-03 13:01:22 +00009790MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009791 const char *name)
9792{
9793 register int
9794 i;
9795
9796 Status
9797 status;
9798
9799 unsigned int
9800 number_children;
9801
9802 Window
9803 *children,
9804 child,
9805 window;
9806
9807 XTextProperty
9808 window_name;
9809
9810 assert(display != (Display *) NULL);
9811 assert(root_window != (Window) NULL);
9812 assert(name != (char *) NULL);
9813 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9814 if (XGetWMName(display,root_window,&window_name) != 0)
9815 if (LocaleCompare((char *) window_name.value,name) == 0)
9816 return(root_window);
9817 status=XQueryTree(display,root_window,&child,&child,&children,
9818 &number_children);
9819 if (status == False)
9820 return((Window) NULL);
9821 window=(Window) NULL;
9822 for (i=0; i < (int) number_children; i++)
9823 {
9824 /*
9825 Search each child and their children.
9826 */
9827 window=XWindowByName(display,children[i],name);
9828 if (window != (Window) NULL)
9829 break;
9830 }
9831 if (children != (Window *) NULL)
9832 (void) XFree((void *) children);
9833 return(window);
9834}
9835
9836/*
9837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9838% %
9839% %
9840% %
9841% X W i n d o w B y P r o p e r y %
9842% %
9843% %
9844% %
9845%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9846%
9847% XWindowByProperty() locates a child window with a given property. If not
9848% window with the given name is found, 0 is returned. If more than one window
9849% has the given property, the first one is returned. Only the window
9850% specified and its subwindows are searched.
9851%
9852% The format of the XWindowByProperty function is:
9853%
9854% child=XWindowByProperty(display,window,property)
9855%
9856% A description of each parameter follows:
9857%
9858% o child: XWindowByProperty returns the window id with the specified
9859% property. If no windows are found, XWindowByProperty returns 0.
9860%
9861% o display: Specifies a pointer to the Display structure; returned from
9862% XOpenDisplay.
9863%
9864% o property: Specifies the property of the window to locate.
9865%
9866*/
cristybcbda3f2011-09-03 13:01:22 +00009867MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009868 const Atom property)
9869{
9870 Atom
9871 type;
9872
9873 int
9874 format;
9875
9876 Status
9877 status;
9878
9879 unsigned char
9880 *data;
9881
9882 unsigned int
9883 i,
9884 number_children;
9885
cristyf2faecf2010-05-28 19:19:36 +00009886 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009887 after,
9888 number_items;
9889
9890 Window
9891 child,
9892 *children,
9893 parent,
9894 root;
9895
9896 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9897 assert(display != (Display *) NULL);
9898 assert(window != (Window) NULL);
9899 assert(property != (Atom) NULL);
9900 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9901 if (status == False)
9902 return((Window) NULL);
9903 type=(Atom) NULL;
9904 child=(Window) NULL;
9905 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9906 {
9907 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9908 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9909 if (data != NULL)
9910 (void) XFree((void *) data);
9911 if ((status == Success) && (type != (Atom) NULL))
9912 child=children[i];
9913 }
9914 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9915 child=XWindowByProperty(display,children[i],property);
9916 if (children != (Window *) NULL)
9917 (void) XFree((void *) children);
9918 return(child);
9919}
9920#else
9921
9922/*
9923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9924% %
9925% %
9926% %
9927% X I m p o r t I m a g e %
9928% %
9929% %
9930% %
9931%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9932%
9933% XImportImage() reads an image from an X window.
9934%
9935% The format of the XImportImage method is:
9936%
cristya0dc96a2011-12-19 23:58:54 +00009937% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9938% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009939%
9940% A description of each parameter follows:
9941%
9942% o image_info: the image info..
9943%
9944% o ximage_info: Specifies a pointer to an XImportInfo structure.
9945%
cristya0dc96a2011-12-19 23:58:54 +00009946% o exception: return any errors or warnings in this structure.
9947%
cristy3ed852e2009-09-05 21:47:34 +00009948*/
cristy4bc52022012-12-13 14:15:41 +00009949MagickExport Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009950 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009951{
9952 assert(image_info != (const ImageInfo *) NULL);
9953 assert(image_info->signature == MagickSignature);
9954 if (image_info->debug != MagickFalse)
9955 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9956 image_info->filename);
9957 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009958 assert(exception != (ExceptionInfo *) NULL);
9959 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009960 return((Image *) NULL);
9961}
cristy534d0a32013-04-13 16:27:24 +00009962
9963/*
9964%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9965% %
9966% %
9967% %
9968% X R e n d e r X 1 1 %
9969% %
9970% %
9971% %
9972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9973%
9974% XRenderImage() renders text on the image with an X11 font. It also returns
9975% the bounding box of the text relative to the image.
9976%
9977% The format of the XRenderImage method is:
9978%
9979% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
9980% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
9981%
9982% A description of each parameter follows:
9983%
9984% o image: the image.
9985%
9986% o draw_info: the draw info.
9987%
9988% o offset: (x,y) location of text relative to image.
9989%
9990% o metrics: bounding box of text.
9991%
9992% o exception: return any errors or warnings in this structure.
9993%
9994*/
9995MagickPrivate MagickBooleanType XRenderImage(Image *image,
9996 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
9997 ExceptionInfo *exception)
9998{
9999 (void) draw_info;
10000 (void) offset;
10001 (void) metrics;
10002 (void) ThrowMagickException(exception,GetMagickModule(),
10003 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","'%s' (X11)",
10004 image->filename);
10005 return(MagickFalse);
10006}
cristy3ed852e2009-09-05 21:47:34 +000010007#endif
10008
10009/*
10010%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10011% %
10012% %
10013% %
cristy576974e2009-10-25 20:45:31 +000010014+ X C o m p o n e n t G e n e s i s %
10015% %
10016% %
10017% %
10018%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10019%
10020% XComponentGenesis() instantiates the X component.
10021%
10022% The format of the XComponentGenesis method is:
10023%
10024% MagickBooleanType XComponentGenesis(void)
10025%
10026*/
cristy5ff4eaf2011-09-03 01:38:02 +000010027MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +000010028{
10029 return(MagickTrue);
10030}
10031
10032/*
10033%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10034% %
10035% %
10036% %
cristy3ed852e2009-09-05 21:47:34 +000010037% X G e t I m p o r t I n f o %
10038% %
10039% %
10040% %
10041%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10042%
10043% XGetImportInfo() initializes the XImportInfo structure.
10044%
10045% The format of the XGetImportInfo method is:
10046%
10047% void XGetImportInfo(XImportInfo *ximage_info)
10048%
10049% A description of each parameter follows:
10050%
10051% o ximage_info: Specifies a pointer to an ImageInfo structure.
10052%
10053*/
10054MagickExport void XGetImportInfo(XImportInfo *ximage_info)
10055{
10056 assert(ximage_info != (XImportInfo *) NULL);
10057 ximage_info->frame=MagickFalse;
10058 ximage_info->borders=MagickFalse;
10059 ximage_info->screen=MagickFalse;
10060 ximage_info->descend=MagickTrue;
10061 ximage_info->silent=MagickFalse;
10062}