blob: 248e497576f43b307504bcbda759cf3ee6627bd5 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% X X W W IIIII N N DDDD OOO W W %
7% X X W W I NN N D D O O W W %
8% X W W I N N N D D O O W W %
9% X X W W W I N NN D D O O W W W %
10% X X W W IIIII N N DDDD OOO W W %
11% %
12% %
13% MagickCore X11 Utility Methods %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy45ef08f2012-12-07 13:13:34 +000020% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/animate.h"
44#include "MagickCore/artifact.h"
45#include "MagickCore/blob.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/client.h"
48#include "MagickCore/color.h"
49#include "MagickCore/color-private.h"
50#include "MagickCore/colormap.h"
51#include "MagickCore/composite.h"
cristy030436f2012-01-06 21:56:17 +000052#include "MagickCore/constitute.h"
cristy4c08aed2011-07-01 19:47:50 +000053#include "MagickCore/display.h"
cristyc53413d2011-11-17 13:04:26 +000054#include "MagickCore/distort.h"
cristy4c08aed2011-07-01 19:47:50 +000055#include "MagickCore/exception.h"
56#include "MagickCore/exception-private.h"
57#include "MagickCore/geometry.h"
58#include "MagickCore/identify.h"
59#include "MagickCore/image.h"
60#include "MagickCore/image-private.h"
61#include "MagickCore/list.h"
62#include "MagickCore/locale_.h"
63#include "MagickCore/log.h"
64#include "MagickCore/magick.h"
65#include "MagickCore/memory_.h"
66#include "MagickCore/monitor.h"
cristy2c5fc272012-02-22 01:27:46 +000067#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000068#include "MagickCore/option.h"
69#include "MagickCore/pixel-accessor.h"
70#include "MagickCore/PreRvIcccm.h"
71#include "MagickCore/quantize.h"
72#include "MagickCore/quantum.h"
73#include "MagickCore/quantum-private.h"
74#include "MagickCore/resource_.h"
75#include "MagickCore/resize.h"
cristy4c08aed2011-07-01 19:47:50 +000076#include "MagickCore/statistic.h"
77#include "MagickCore/string_.h"
78#include "MagickCore/string-private.h"
79#include "MagickCore/transform.h"
cristy63a81872012-03-22 15:52:52 +000080#include "MagickCore/token.h"
cristy4c08aed2011-07-01 19:47:50 +000081#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000082#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000083#include "MagickCore/widget.h"
cristybcbda3f2011-09-03 13:01:22 +000084#include "MagickCore/widget-private.h"
cristy4c08aed2011-07-01 19:47:50 +000085#include "MagickCore/xwindow.h"
86#include "MagickCore/xwindow-private.h"
87#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000088#if defined(__BEOS__)
89#include <OS.h>
90#endif
91#if defined(MAGICKCORE_X11_DELEGATE)
92#include <X11/Xproto.h>
93#include <X11/Xlocale.h>
94#if defined(MAGICK_HAVE_POLL)
95# include <sys/poll.h>
96#endif
97#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
98#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
99# include <machine/param.h>
100#endif
101#include <sys/ipc.h>
102#include <sys/shm.h>
103#include <X11/extensions/XShm.h>
104#endif
105#if defined(MAGICKCORE_HAVE_SHAPE)
106#include <X11/extensions/shape.h>
107#endif
108
109/*
110 X defines.
111*/
cristyce70c172010-01-07 17:15:30 +0000112#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000113 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
114 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000115#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000116 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
117 map->red_mult)+ \
118 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
119 map->green_mult)+ \
120 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
121 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000122#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
123 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
124 map->red_mult)+ \
125 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
126 map->green_mult)+ \
127 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
128 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000129#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000130 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
131 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000132#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000133 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
134 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000135#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000136 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
137 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
138 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000139
140#define AccentuateModulate ScaleCharToQuantum(80)
141#define HighlightModulate ScaleCharToQuantum(125)
142#define ShadowModulate ScaleCharToQuantum(135)
143#define DepthModulate ScaleCharToQuantum(185)
144#define TroughModulate ScaleCharToQuantum(110)
145
146#define XLIB_ILLEGAL_ACCESS 1
147#undef ForgetGravity
148#undef NorthWestGravity
149#undef NorthGravity
150#undef NorthEastGravity
151#undef WestGravity
152#undef CenterGravity
153#undef EastGravity
154#undef SouthWestGravity
155#undef SouthGravity
156#undef SouthEastGravity
157#undef StaticGravity
158
159#undef index
160#if defined(hpux9)
161#define XFD_SET int
162#else
163#define XFD_SET fd_set
164#endif
165
166/*
167 Enumeration declarations.
168*/
169typedef enum
170{
171#undef DoRed
172 DoRed = 0x0001,
173#undef DoGreen
174 DoGreen = 0x0002,
175#undef DoBlue
176 DoBlue = 0x0004,
177 DoMatte = 0x0008
178} XColorFlags;
179
180/*
181 Typedef declarations.
182*/
183typedef struct _DiversityPacket
184{
185 Quantum
186 red,
187 green,
188 blue;
189
190 unsigned short
191 index;
192
cristybb503372010-05-27 20:51:26 +0000193 size_t
cristy3ed852e2009-09-05 21:47:34 +0000194 count;
195} DiversityPacket;
196
197/*
198 Constant declaractions.
199*/
200static MagickBooleanType
201 xerror_alert = MagickFalse;
202
203/*
204 Method prototypes.
205*/
206static const char
207 *XVisualClassName(const int);
208
cristya19f1d72012-08-07 18:24:38 +0000209static double
cristy3ed852e2009-09-05 21:47:34 +0000210 blue_gamma = 1.0,
211 green_gamma = 1.0,
212 red_gamma = 1.0;
213
214static MagickBooleanType
215 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
216
217static void
218 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000219 XImage *,XImage *,ExceptionInfo *),
cristy3ed852e2009-09-05 21:47:34 +0000220 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000221 XImage *,XImage *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +0000222
223static Window
224 XSelectWindow(Display *,RectangleInfo *);
225
226/*
227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228% %
229% %
230% %
231% D e s t r o y X R e s o u r c e s %
232% %
233% %
234% %
235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236%
237% DestroyXResources() destroys any X resources.
238%
239% The format of the DestroyXResources method is:
240%
241% void DestroyXResources()
242%
243% A description of each parameter follows:
244%
245*/
246MagickExport void DestroyXResources(void)
247{
248 register int
249 i;
250
251 unsigned int
252 number_windows;
253
254 XWindowInfo
255 *magick_windows[MaxXWindows];
256
257 XWindows
258 *windows;
259
260 DestroyXWidget();
261 windows=XSetWindows((XWindows *) ~0);
262 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
263 return;
264 number_windows=0;
265 magick_windows[number_windows++]=(&windows->context);
266 magick_windows[number_windows++]=(&windows->group_leader);
267 magick_windows[number_windows++]=(&windows->backdrop);
268 magick_windows[number_windows++]=(&windows->icon);
269 magick_windows[number_windows++]=(&windows->image);
270 magick_windows[number_windows++]=(&windows->info);
271 magick_windows[number_windows++]=(&windows->magnify);
272 magick_windows[number_windows++]=(&windows->pan);
273 magick_windows[number_windows++]=(&windows->command);
274 magick_windows[number_windows++]=(&windows->widget);
275 magick_windows[number_windows++]=(&windows->popup);
276 magick_windows[number_windows++]=(&windows->context);
277 for (i=0; i < (int) number_windows; i++)
278 {
279 if (magick_windows[i]->mapped != MagickFalse)
280 {
281 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
282 magick_windows[i]->screen);
283 magick_windows[i]->mapped=MagickFalse;
284 }
285 if (magick_windows[i]->name != (char *) NULL)
286 magick_windows[i]->name=(char *)
287 RelinquishMagickMemory(magick_windows[i]->name);
288 if (magick_windows[i]->icon_name != (char *) NULL)
289 magick_windows[i]->icon_name=(char *)
290 RelinquishMagickMemory(magick_windows[i]->icon_name);
291 if (magick_windows[i]->cursor != (Cursor) NULL)
292 {
293 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
294 magick_windows[i]->cursor=(Cursor) NULL;
295 }
296 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
297 {
298 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
299 magick_windows[i]->busy_cursor=(Cursor) NULL;
300 }
301 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
302 {
303 (void) XFreePixmap(windows->display,
304 magick_windows[i]->highlight_stipple);
305 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
306 }
307 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
308 {
309 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
310 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
311 }
312 if (magick_windows[i]->ximage != (XImage *) NULL)
313 {
314 XDestroyImage(magick_windows[i]->ximage);
315 magick_windows[i]->ximage=(XImage *) NULL;
316 }
317 if (magick_windows[i]->pixmap != (Pixmap) NULL)
318 {
319 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
320 magick_windows[i]->pixmap=(Pixmap) NULL;
321 }
322 if (magick_windows[i]->id != (Window) NULL)
323 {
324 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
325 magick_windows[i]->id=(Window) NULL;
326 }
327 if (magick_windows[i]->destroy != MagickFalse)
328 {
329 if (magick_windows[i]->image != (Image *) NULL)
330 {
331 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
332 magick_windows[i]->image=NewImageList();
333 }
334 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
335 {
336 (void) XFreePixmap(windows->display,
337 magick_windows[i]->matte_pixmap);
338 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
339 }
340 }
341 if (magick_windows[i]->segment_info != (void *) NULL)
342 {
343#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
344 XShmSegmentInfo
345 *segment_info;
346
347 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
348 if (segment_info != (XShmSegmentInfo *) NULL)
349 if (segment_info[0].shmid >= 0)
350 {
351 if (segment_info[0].shmaddr != NULL)
352 (void) shmdt(segment_info[0].shmaddr);
353 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
354 segment_info[0].shmaddr=NULL;
355 segment_info[0].shmid=(-1);
356 }
357#endif
358 magick_windows[i]->segment_info=(void *)
359 RelinquishMagickMemory(magick_windows[i]->segment_info);
360 }
361 }
362 windows->icon_resources=(XResourceInfo *)
363 RelinquishMagickMemory(windows->icon_resources);
364 if (windows->icon_pixel != (XPixelInfo *) NULL)
365 {
cristyf2faecf2010-05-28 19:19:36 +0000366 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
367 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000368 RelinquishMagickMemory(windows->icon_pixel->pixels);
369 if (windows->icon_pixel->annotate_context != (GC) NULL)
370 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
371 windows->icon_pixel=(XPixelInfo *)
372 RelinquishMagickMemory(windows->icon_pixel);
373 }
374 if (windows->pixel_info != (XPixelInfo *) NULL)
375 {
cristyf2faecf2010-05-28 19:19:36 +0000376 if (windows->pixel_info->pixels != (unsigned long *) NULL)
377 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000378 RelinquishMagickMemory(windows->pixel_info->pixels);
379 if (windows->pixel_info->annotate_context != (GC) NULL)
380 XFreeGC(windows->display,windows->pixel_info->annotate_context);
381 if (windows->pixel_info->widget_context != (GC) NULL)
382 XFreeGC(windows->display,windows->pixel_info->widget_context);
383 if (windows->pixel_info->highlight_context != (GC) NULL)
384 XFreeGC(windows->display,windows->pixel_info->highlight_context);
385 windows->pixel_info=(XPixelInfo *)
386 RelinquishMagickMemory(windows->pixel_info);
387 }
388 if (windows->font_info != (XFontStruct *) NULL)
389 {
390 XFreeFont(windows->display,windows->font_info);
391 windows->font_info=(XFontStruct *) NULL;
392 }
393 if (windows->class_hints != (XClassHint *) NULL)
394 {
cristyc9cc4a72011-09-18 02:12:41 +0000395 if (windows->class_hints->res_name != (char *) NULL)
396 windows->class_hints->res_name=DestroyString(
397 windows->class_hints->res_name);
398 if (windows->class_hints->res_class != (char *) NULL)
399 windows->class_hints->res_class=DestroyString(
400 windows->class_hints->res_class);
cristy3ed852e2009-09-05 21:47:34 +0000401 XFree(windows->class_hints);
402 windows->class_hints=(XClassHint *) NULL;
403 }
404 if (windows->manager_hints != (XWMHints *) NULL)
405 {
406 XFree(windows->manager_hints);
407 windows->manager_hints=(XWMHints *) NULL;
408 }
409 if (windows->map_info != (XStandardColormap *) NULL)
410 {
411 XFree(windows->map_info);
412 windows->map_info=(XStandardColormap *) NULL;
413 }
414 if (windows->icon_map != (XStandardColormap *) NULL)
415 {
416 XFree(windows->icon_map);
417 windows->icon_map=(XStandardColormap *) NULL;
418 }
419 if (windows->visual_info != (XVisualInfo *) NULL)
420 {
421 XFree(windows->visual_info);
422 windows->visual_info=(XVisualInfo *) NULL;
423 }
424 if (windows->icon_visual != (XVisualInfo *) NULL)
425 {
426 XFree(windows->icon_visual);
427 windows->icon_visual=(XVisualInfo *) NULL;
428 }
429 (void) XSetWindows((XWindows *) NULL);
430}
431
432/*
433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434% %
435% %
436% %
437% X A n n o t a t e I m a g e %
438% %
439% %
440% %
441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
442%
443% XAnnotateImage() annotates the image with text.
444%
445% The format of the XAnnotateImage method is:
446%
447% MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000448% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
449% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000450%
451% A description of each parameter follows:
452%
453% o display: Specifies a connection to an X server; returned from
454% XOpenDisplay.
455%
456% o pixel: Specifies a pointer to a XPixelInfo structure.
457%
458% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
459%
460% o image: the image.
461%
cristy7c3af952011-10-20 16:04:16 +0000462% o exception: return any errors or warnings in this structure.
463%
cristy3ed852e2009-09-05 21:47:34 +0000464*/
cristybcbda3f2011-09-03 13:01:22 +0000465MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000466 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
467 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000468{
cristyc57f6942010-11-12 01:47:39 +0000469 CacheView
470 *annotate_view;
471
cristy3ed852e2009-09-05 21:47:34 +0000472 GC
473 annotate_context;
474
cristy3ed852e2009-09-05 21:47:34 +0000475 Image
476 *annotate_image;
477
478 int
479 x,
480 y;
481
cristyb0a657e2012-08-29 00:45:37 +0000482 PixelTrait
483 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +0000484
485 Pixmap
486 annotate_pixmap;
487
488 unsigned int
489 depth,
490 height,
491 width;
492
493 Window
494 root_window;
495
496 XGCValues
497 context_values;
498
499 XImage
500 *annotate_ximage;
501
502 /*
503 Initialize annotated image.
504 */
505 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
506 assert(display != (Display *) NULL);
507 assert(pixel != (XPixelInfo *) NULL);
508 assert(annotate_info != (XAnnotateInfo *) NULL);
509 assert(image != (Image *) NULL);
510 /*
511 Initialize annotated pixmap.
512 */
513 root_window=XRootWindow(display,XDefaultScreen(display));
514 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
515 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
516 annotate_info->height,depth);
517 if (annotate_pixmap == (Pixmap) NULL)
518 return(MagickFalse);
519 /*
520 Initialize graphics info.
521 */
522 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000523 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000524 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000525 annotate_context=XCreateGC(display,root_window,(unsigned long)
526 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000527 if (annotate_context == (GC) NULL)
528 return(MagickFalse);
529 /*
530 Draw text to pixmap.
531 */
532 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
533 (int) annotate_info->font_info->ascent,annotate_info->text,
534 (int) strlen(annotate_info->text));
535 (void) XFreeGC(display,annotate_context);
536 /*
537 Initialize annotated X image.
538 */
539 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
540 annotate_info->height,AllPlanes,ZPixmap);
541 if (annotate_ximage == (XImage *) NULL)
542 return(MagickFalse);
543 (void) XFreePixmap(display,annotate_pixmap);
544 /*
545 Initialize annotated image.
546 */
cristy6710d842011-10-20 23:23:00 +0000547 annotate_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +0000548 if (annotate_image == (Image *) NULL)
549 return(MagickFalse);
550 annotate_image->columns=annotate_info->width;
551 annotate_image->rows=annotate_info->height;
552 /*
553 Transfer annotated X image to image.
554 */
555 width=(unsigned int) image->columns;
556 height=(unsigned int) image->rows;
557 x=0;
558 y=0;
559 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +0000560 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
561 (ssize_t) y,&annotate_image->background_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000562 if (annotate_info->stencil == ForegroundStencil)
cristy8a46d822012-08-28 23:32:39 +0000563 annotate_image->alpha_trait=BlendPixelTrait;
cristy6f5395d2012-12-14 18:30:30 +0000564 annotate_view=AcquireAuthenticCacheView(annotate_image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000565 for (y=0; y < (int) annotate_image->rows; y++)
566 {
cristyc57f6942010-11-12 01:47:39 +0000567 register int
cristy3ed852e2009-09-05 21:47:34 +0000568 x;
569
cristy4c08aed2011-07-01 19:47:50 +0000570 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000571 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000572
cristyc57f6942010-11-12 01:47:39 +0000573 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
574 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000575 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000576 break;
cristyc57f6942010-11-12 01:47:39 +0000577 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000578 {
cristy4c08aed2011-07-01 19:47:50 +0000579 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000580 if (XGetPixel(annotate_ximage,x,y) == 0)
581 {
582 /*
583 Set this pixel to the background color.
584 */
cristy4c08aed2011-07-01 19:47:50 +0000585 SetPixelRed(annotate_image,ScaleShortToQuantum(
586 pixel->box_color.red),q);
587 SetPixelGreen(annotate_image,ScaleShortToQuantum(
588 pixel->box_color.green),q);
589 SetPixelBlue(annotate_image,ScaleShortToQuantum(
590 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000591 if ((annotate_info->stencil == ForegroundStencil) ||
592 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000593 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000594 }
595 else
596 {
597 /*
598 Set this pixel to the pen color.
599 */
cristy4c08aed2011-07-01 19:47:50 +0000600 SetPixelRed(annotate_image,ScaleShortToQuantum(
601 pixel->pen_color.red),q);
602 SetPixelGreen(annotate_image,ScaleShortToQuantum(
603 pixel->pen_color.green),q);
604 SetPixelBlue(annotate_image,ScaleShortToQuantum(
605 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000606 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000607 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000608 }
cristyed231572011-07-14 02:18:59 +0000609 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000610 }
cristyc57f6942010-11-12 01:47:39 +0000611 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000612 break;
613 }
cristyc57f6942010-11-12 01:47:39 +0000614 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000615 XDestroyImage(annotate_ximage);
616 /*
617 Determine annotate geometry.
618 */
619 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
620 if ((width != (unsigned int) annotate_image->columns) ||
621 (height != (unsigned int) annotate_image->rows))
622 {
623 char
624 image_geometry[MaxTextExtent];
625
626 /*
627 Scale image.
628 */
cristyb51dff52011-05-19 16:55:47 +0000629 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000630 width,height);
cristye941a752011-10-15 01:52:48 +0000631 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
632 exception);
cristy3ed852e2009-09-05 21:47:34 +0000633 }
634 if (annotate_info->degrees != 0.0)
635 {
636 Image
637 *rotate_image;
638
639 int
640 rotations;
641
cristya19f1d72012-08-07 18:24:38 +0000642 double
cristy3ed852e2009-09-05 21:47:34 +0000643 normalized_degrees;
644
645 /*
646 Rotate image.
647 */
cristy6710d842011-10-20 23:23:00 +0000648 rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +0000649 if (rotate_image == (Image *) NULL)
650 return(MagickFalse);
651 annotate_image=DestroyImage(annotate_image);
652 annotate_image=rotate_image;
653 /*
654 Annotation is relative to the degree of rotation.
655 */
656 normalized_degrees=annotate_info->degrees;
657 while (normalized_degrees < -45.0)
658 normalized_degrees+=360.0;
659 for (rotations=0; normalized_degrees > 45.0; rotations++)
660 normalized_degrees-=90.0;
661 switch (rotations % 4)
662 {
663 default:
664 case 0:
665 break;
666 case 1:
667 {
668 /*
669 Rotate 90 degrees.
670 */
671 x-=(int) annotate_image->columns/2;
672 y+=(int) annotate_image->columns/2;
673 break;
674 }
675 case 2:
676 {
677 /*
678 Rotate 180 degrees.
679 */
680 x=x-(int) annotate_image->columns;
681 break;
682 }
683 case 3:
684 {
685 /*
686 Rotate 270 degrees.
687 */
688 x=x-(int) annotate_image->columns/2;
689 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
690 break;
691 }
692 }
693 }
694 /*
695 Composite text onto the image.
696 */
697 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyb0a657e2012-08-29 00:45:37 +0000698 alpha_trait=image->alpha_trait;
cristyfeb3e962012-03-29 17:25:55 +0000699 (void) CompositeImage(image,annotate_image,
cristyb0a657e2012-08-29 00:45:37 +0000700 annotate_image->alpha_trait == BlendPixelTrait ? OverCompositeOp :
701 CopyCompositeOp,MagickTrue,(ssize_t) x,(ssize_t) y,exception);
702 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +0000703 annotate_image=DestroyImage(annotate_image);
704 return(MagickTrue);
705}
706
707/*
708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
709% %
710% %
711% %
712% X B e s t F o n t %
713% %
714% %
715% %
716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
717%
718% XBestFont() returns the "best" font. "Best" is defined as a font specified
719% in the X resource database or a font such that the text width displayed
720% with the font does not exceed the specified maximum width.
721%
722% The format of the XBestFont method is:
723%
724% XFontStruct *XBestFont(Display *display,
725% const XResourceInfo *resource_info,const MagickBooleanType text_font)
726%
727% A description of each parameter follows:
728%
729% o font: XBestFont returns a pointer to a XFontStruct structure.
730%
731% o display: Specifies a connection to an X server; returned from
732% XOpenDisplay.
733%
734% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
735%
736% o text_font: True is font should be mono-spaced (typewriter style).
737%
cristy3ed852e2009-09-05 21:47:34 +0000738*/
739
740static char **FontToList(char *font)
741{
742 char
743 **fontlist;
744
745 register char
746 *p,
747 *q;
748
749 register int
750 i;
751
752 unsigned int
753 fonts;
754
755 if (font == (char *) NULL)
756 return((char **) NULL);
757 /*
758 Convert string to an ASCII list.
759 */
760 fonts=1U;
761 for (p=font; *p != '\0'; p++)
762 if ((*p == ':') || (*p == ';') || (*p == ','))
763 fonts++;
764 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
765 if (fontlist == (char **) NULL)
766 {
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;
1318 if (LocaleCompare(map_type,"list") != 0)
1319 {
1320 /*
1321 User specified Standard Colormap.
1322 */
cristyb51dff52011-05-19 16:55:47 +00001323 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001324 "RGB_%s_MAP",map_type);
1325 LocaleUpper(map_name);
1326 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1327 if (map_property != (Atom) NULL)
1328 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1329 map_property);
1330 }
1331 else
1332 {
1333 static const char
1334 *colormap[MaxStandardColormaps]=
1335 {
1336 "_HP_RGB_SMOOTH_MAP_LIST",
1337 "RGB_BEST_MAP",
1338 "RGB_DEFAULT_MAP",
1339 "RGB_GRAY_MAP",
1340 "RGB_RED_MAP",
1341 "RGB_GREEN_MAP",
1342 "RGB_BLUE_MAP",
1343 };
1344
1345 /*
1346 Choose a standard colormap from a list.
1347 */
1348 for (i=0; i < MaxStandardColormaps; i++)
1349 {
1350 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1351 if (map_property == (Atom) NULL)
1352 continue;
1353 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1354 map_property);
1355 if (status != False)
1356 break;
1357 }
1358 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1359 }
1360 if (status == False)
1361 {
cristyc38fbf52013-11-03 13:55:54 +00001362 ThrowXWindowException(XServerError,"UnableToGetStandardColormap",
cristy3ed852e2009-09-05 21:47:34 +00001363 map_type);
1364 return((XVisualInfo *) NULL);
1365 }
1366 /*
1367 Search all Standard Colormaps and visuals for ids that match.
1368 */
1369 *map_info=map_list[0];
1370#if !defined(PRE_R4_ICCCM)
1371 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1372 for (i=0; i < number_maps; i++)
1373 for (j=0; j < number_visuals; j++)
1374 if (map_list[i].visualid ==
1375 XVisualIDFromVisual(visual_list[j].visual))
1376 {
1377 *map_info=map_list[i];
1378 visual_template.visualid=XVisualIDFromVisual(
1379 visual_list[j].visual);
1380 break;
1381 }
1382 if (map_info->visualid != visual_template.visualid)
1383 {
cristyc38fbf52013-11-03 13:55:54 +00001384 ThrowXWindowException(XServerError,
cristy3ed852e2009-09-05 21:47:34 +00001385 "UnableToMatchVisualToStandardColormap",map_type);
1386 return((XVisualInfo *) NULL);
1387 }
1388#endif
1389 if (map_info->colormap == (Colormap) NULL)
1390 {
cristyc38fbf52013-11-03 13:55:54 +00001391 ThrowXWindowException(XServerError,"StandardColormapIsNotInitialized",
1392 map_type);
cristy3ed852e2009-09-05 21:47:34 +00001393 return((XVisualInfo *) NULL);
1394 }
1395 (void) XFree((void *) map_list);
1396 }
1397 else
1398 {
1399 static const unsigned int
1400 rank[]=
1401 {
1402 StaticGray,
1403 GrayScale,
1404 StaticColor,
1405 DirectColor,
1406 TrueColor,
1407 PseudoColor
1408 };
1409
1410 XVisualInfo
1411 *p;
1412
1413 /*
1414 Pick one visual that displays the most simultaneous colors.
1415 */
1416 visual_info=visual_list;
1417 p=visual_list;
1418 for (i=1; i < number_visuals; i++)
1419 {
1420 p++;
1421 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1422 visual_info=p;
1423 else
1424 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1425 if (rank[p->klass] > rank[visual_info->klass])
1426 visual_info=p;
1427 }
1428 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1429 }
1430 (void) XFree((void *) visual_list);
1431 /*
1432 Retrieve only one visual by its screen & id number.
1433 */
1434 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1435 &number_visuals);
1436 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1437 return((XVisualInfo *) NULL);
1438 return(visual_info);
1439}
1440
1441/*
1442%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1443% %
1444% %
1445% %
1446% X C h e c k D e f i n e C u r s o r %
1447% %
1448% %
1449% %
1450%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1451%
1452% XCheckDefineCursor() prevents cursor changes on the root window.
1453%
1454% The format of the XXCheckDefineCursor method is:
1455%
1456% XCheckDefineCursor(display,window,cursor)
1457%
1458% A description of each parameter follows:
1459%
1460% o display: Specifies a connection to an X server; returned from
1461% XOpenDisplay.
1462%
1463% o window: the window.
1464%
1465% o cursor: the cursor.
1466%
1467*/
cristybcbda3f2011-09-03 13:01:22 +00001468MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001469 Cursor cursor)
1470{
1471 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1472 assert(display != (Display *) NULL);
1473 if (window == XRootWindow(display,XDefaultScreen(display)))
1474 return(0);
1475 return(XDefineCursor(display,window,cursor));
1476}
1477
1478/*
1479%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1480% %
1481% %
1482% %
1483% X C h e c k R e f r e s h W i n d o w s %
1484% %
1485% %
1486% %
1487%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1488%
1489% XCheckRefreshWindows() checks the X server for exposure events for a
1490% particular window and updates the areassociated with the exposure event.
1491%
1492% The format of the XCheckRefreshWindows method is:
1493%
1494% void XCheckRefreshWindows(Display *display,XWindows *windows)
1495%
1496% A description of each parameter follows:
1497%
1498% o display: Specifies a connection to an X server; returned from
1499% XOpenDisplay.
1500%
1501% o windows: Specifies a pointer to a XWindows structure.
1502%
1503*/
cristybcbda3f2011-09-03 13:01:22 +00001504MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001505{
1506 Window
1507 id;
1508
1509 XEvent
1510 event;
1511
1512 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1513 assert(display != (Display *) NULL);
1514 assert(windows != (XWindows *) NULL);
1515 XDelay(display,SuspendTime);
1516 id=windows->command.id;
1517 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1518 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1519 id=windows->image.id;
1520 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1521 XRefreshWindow(display,&windows->image,&event);
1522 XDelay(display,SuspendTime << 1);
1523 id=windows->command.id;
1524 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1525 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1526 id=windows->image.id;
1527 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1528 XRefreshWindow(display,&windows->image,&event);
1529}
1530
1531/*
1532%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1533% %
1534% %
1535% %
1536% X C l i e n t M e s s a g e %
1537% %
1538% %
1539% %
1540%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1541%
1542% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1543% initialized with a particular protocol type and atom.
1544%
1545% The format of the XClientMessage function is:
1546%
1547% XClientMessage(display,window,protocol,reason,timestamp)
1548%
1549% A description of each parameter follows:
1550%
1551% o display: Specifies a pointer to the Display structure; returned from
1552% XOpenDisplay.
1553%
1554% o window: Specifies a pointer to a Window structure.
1555%
1556% o protocol: Specifies an atom value.
1557%
1558% o reason: Specifies an atom value which is the reason to send.
1559%
1560% o timestamp: Specifies a value of type Time.
1561%
1562*/
cristybcbda3f2011-09-03 13:01:22 +00001563MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001564 const Atom protocol,const Atom reason,const Time timestamp)
1565{
1566 XClientMessageEvent
1567 client_event;
1568
1569 assert(display != (Display *) NULL);
1570 client_event.type=ClientMessage;
1571 client_event.window=window;
1572 client_event.message_type=protocol;
1573 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001574 client_event.data.l[0]=(long) reason;
1575 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001576 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1577}
1578
1579/*
1580%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1581% %
1582% %
1583% %
1584+ X C l i e n t W i n d o w %
1585% %
1586% %
1587% %
1588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1589%
1590% XClientWindow() finds a window, at or below the specified window, which has
1591% a WM_STATE property. If such a window is found, it is returned, otherwise
1592% the argument window is returned.
1593%
1594% The format of the XClientWindow function is:
1595%
1596% client_window=XClientWindow(display,target_window)
1597%
1598% A description of each parameter follows:
1599%
1600% o client_window: XClientWindow returns a window, at or below the specified
1601% window, which has a WM_STATE property otherwise the argument
1602% target_window is returned.
1603%
1604% o display: Specifies a pointer to the Display structure; returned from
1605% XOpenDisplay.
1606%
1607% o target_window: Specifies the window to find a WM_STATE property.
1608%
cristy3ed852e2009-09-05 21:47:34 +00001609*/
1610static Window XClientWindow(Display *display,Window target_window)
1611{
1612 Atom
1613 state,
1614 type;
1615
1616 int
1617 format;
1618
1619 Status
1620 status;
1621
1622 unsigned char
1623 *data;
1624
cristyf2faecf2010-05-28 19:19:36 +00001625 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001626 after,
1627 number_items;
1628
1629 Window
1630 client_window;
1631
1632 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1633 assert(display != (Display *) NULL);
1634 state=XInternAtom(display,"WM_STATE",MagickTrue);
1635 if (state == (Atom) NULL)
1636 return(target_window);
1637 type=(Atom) NULL;
1638 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1639 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1640 if ((status == Success) && (type != (Atom) NULL))
1641 return(target_window);
1642 client_window=XWindowByProperty(display,target_window,state);
1643 if (client_window == (Window) NULL)
1644 return(target_window);
1645 return(client_window);
1646}
1647
1648/*
1649%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1650% %
1651% %
1652% %
cristyf34a1452009-10-24 22:29:27 +00001653+ X C o m p o n e n t T e r m i n u s %
1654% %
1655% %
1656% %
1657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1658%
1659% XComponentTerminus() destroys the module component.
1660%
1661% The format of the XComponentTerminus method is:
1662%
1663% XComponentTerminus(void)
1664%
1665*/
cristy5ff4eaf2011-09-03 01:38:02 +00001666MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001667{
1668 DestroyXResources();
1669}
1670
1671/*
1672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1673% %
1674% %
1675% %
cristy3ed852e2009-09-05 21:47:34 +00001676% X C o n f i g u r e I m a g e C o l o r m a p %
1677% %
1678% %
1679% %
1680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1681%
1682% XConfigureImageColormap() creates a new X colormap.
1683%
1684% The format of the XConfigureImageColormap method is:
1685%
1686% void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001687% XResourceInfo *resource_info,XWindows *windows,Image *image,
1688% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001689%
1690% A description of each parameter follows:
1691%
1692% o display: Specifies a connection to an X server; returned from
1693% XOpenDisplay.
1694%
1695% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1696%
1697% o windows: Specifies a pointer to a XWindows structure.
1698%
1699% o image: the image.
1700%
cristy6710d842011-10-20 23:23:00 +00001701% o exception: return any errors or warnings in this structure.
1702%
cristy3ed852e2009-09-05 21:47:34 +00001703*/
cristybcbda3f2011-09-03 13:01:22 +00001704MagickPrivate void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001705 XResourceInfo *resource_info,XWindows *windows,Image *image,
1706 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001707{
1708 Colormap
1709 colormap;
1710
1711 /*
1712 Make standard colormap.
1713 */
1714 XSetCursorState(display,windows,MagickTrue);
1715 XCheckRefreshWindows(display,windows);
1716 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
cristy6710d842011-10-20 23:23:00 +00001717 windows->map_info,windows->pixel_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00001718 colormap=windows->map_info->colormap;
1719 (void) XSetWindowColormap(display,windows->image.id,colormap);
1720 (void) XSetWindowColormap(display,windows->command.id,colormap);
1721 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1722 if (windows->magnify.mapped != MagickFalse)
1723 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1724 if (windows->pan.mapped != MagickFalse)
1725 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1726 XSetCursorState(display,windows,MagickFalse);
1727 XClientMessage(display,windows->image.id,windows->im_protocols,
1728 windows->im_update_colormap,CurrentTime);
1729}
1730
1731/*
1732%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1733% %
1734% %
1735% %
1736% X C o n s t r a i n W i n d o w P o s i t i o n %
1737% %
1738% %
1739% %
1740%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1741%
1742% XConstrainWindowPosition() assures a window is positioned within the X
1743% server boundaries.
1744%
1745% The format of the XConstrainWindowPosition method is:
1746%
1747% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1748%
1749% A description of each parameter follows:
1750%
1751% o display: Specifies a pointer to the Display structure; returned from
1752% XOpenDisplay.
1753%
1754% o window_info: Specifies a pointer to a XWindowInfo structure.
1755%
1756*/
cristybcbda3f2011-09-03 13:01:22 +00001757MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001758 XWindowInfo *window_info)
1759{
1760 int
1761 limit;
1762
1763 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1764 assert(display != (Display *) NULL);
1765 assert(window_info != (XWindowInfo *) NULL);
1766 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1767 if (window_info->x < 0)
1768 window_info->x=0;
1769 else
1770 if (window_info->x > (int) limit)
1771 window_info->x=(int) limit;
1772 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1773 if (window_info->y < 0)
1774 window_info->y=0;
1775 else
1776 if (window_info->y > limit)
1777 window_info->y=limit;
1778}
1779
1780/*
1781%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1782% %
1783% %
1784% %
1785% X D e l a y %
1786% %
1787% %
1788% %
1789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1790%
1791% XDelay() suspends program execution for the number of milliseconds
1792% specified.
1793%
1794% The format of the Delay method is:
1795%
cristybb503372010-05-27 20:51:26 +00001796% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001797%
1798% A description of each parameter follows:
1799%
1800% o display: Specifies a pointer to the Display structure; returned from
1801% XOpenDisplay.
1802%
1803% o milliseconds: Specifies the number of milliseconds to delay before
1804% returning.
1805%
1806*/
cristybcbda3f2011-09-03 13:01:22 +00001807MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001808{
1809 assert(display != (Display *) NULL);
1810 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001811 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001812}
1813
1814/*
1815%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1816% %
1817% %
1818% %
1819% X D e s t r o y R e s o u r c e I n f o %
1820% %
1821% %
1822% %
1823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1824%
1825% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1826% structure.
1827%
1828% The format of the XDestroyResourceInfo method is:
1829%
1830% void XDestroyResourceInfo(XResourceInfo *resource_info)
1831%
1832% A description of each parameter follows:
1833%
1834% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1835%
1836*/
1837MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1838{
1839 if (resource_info->image_geometry != (char *) NULL)
1840 resource_info->image_geometry=(char *)
1841 RelinquishMagickMemory(resource_info->image_geometry);
1842 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1843 resource_info->quantize_info=DestroyQuantizeInfo(
1844 resource_info->quantize_info);
1845 if (resource_info->client_name != (char *) NULL)
1846 resource_info->client_name=(char *)
1847 RelinquishMagickMemory(resource_info->client_name);
1848 if (resource_info->name != (char *) NULL)
1849 resource_info->name=DestroyString(resource_info->name);
1850 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1851}
1852
1853/*
1854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1855% %
1856% %
1857% %
1858% X D e s t r o y W i n d o w C o l o r s %
1859% %
1860% %
1861% %
1862%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1863%
1864% XDestroyWindowColors() frees X11 color resources previously saved on a
1865% window by XRetainWindowColors or programs like xsetroot.
1866%
1867% The format of the XDestroyWindowColors method is:
1868%
1869% void XDestroyWindowColors(Display *display,Window window)
1870%
1871% A description of each parameter follows:
1872%
1873% o display: Specifies a connection to an X server; returned from
1874% XOpenDisplay.
1875%
1876% o window: Specifies a pointer to a Window structure.
1877%
1878*/
cristybcbda3f2011-09-03 13:01:22 +00001879MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001880{
1881 Atom
1882 property,
1883 type;
1884
1885 int
1886 format;
1887
1888 Status
1889 status;
1890
1891 unsigned char
1892 *data;
1893
cristyf2faecf2010-05-28 19:19:36 +00001894 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001895 after,
1896 length;
1897
1898 /*
1899 If there are previous resources on the root window, destroy them.
1900 */
1901 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1902 assert(display != (Display *) NULL);
1903 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1904 if (property == (Atom) NULL)
1905 {
cristyc38fbf52013-11-03 13:55:54 +00001906 ThrowXWindowException(XServerError,"UnableToCreateProperty",
cristy3ed852e2009-09-05 21:47:34 +00001907 "_XSETROOT_ID");
1908 return;
1909 }
1910 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1911 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1912 if (status != Success)
1913 return;
1914 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1915 {
1916 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1917 (void) XDeleteProperty(display,window,property);
1918 }
1919 if (type != None)
1920 (void) XFree((void *) data);
1921}
1922
1923/*
1924%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1925% %
1926% %
1927% %
1928% X D i s p l a y I m a g e I n f o %
1929% %
1930% %
1931% %
1932%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1933%
1934% XDisplayImageInfo() displays information about an X image.
1935%
1936% The format of the XDisplayImageInfo method is:
1937%
1938% void XDisplayImageInfo(Display *display,
1939% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001940% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001941%
1942% A description of each parameter follows:
1943%
1944% o display: Specifies a connection to an X server; returned from
1945% XOpenDisplay.
1946%
1947% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1948%
1949% o windows: Specifies a pointer to a XWindows structure.
1950%
1951% o undo_image: the undo image.
1952%
1953% o image: the image.
1954%
cristy6710d842011-10-20 23:23:00 +00001955% o exception: return any errors or warnings in this structure.
1956%
cristy3ed852e2009-09-05 21:47:34 +00001957*/
cristybcbda3f2011-09-03 13:01:22 +00001958MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001959 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001960 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001961{
1962 char
1963 filename[MaxTextExtent],
1964 *text,
1965 **textlist;
1966
1967 FILE
1968 *file;
1969
1970 int
1971 unique_file;
1972
cristybb503372010-05-27 20:51:26 +00001973 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001974 i;
1975
cristybb503372010-05-27 20:51:26 +00001976 size_t
cristy3ed852e2009-09-05 21:47:34 +00001977 number_pixels;
1978
cristy9d314ff2011-03-09 01:30:28 +00001979 ssize_t
1980 bytes;
1981
1982 unsigned int
1983 levels;
1984
cristy3ed852e2009-09-05 21:47:34 +00001985 /*
1986 Write info about the X server to a file.
1987 */
1988 assert(display != (Display *) NULL);
1989 assert(resource_info != (XResourceInfo *) NULL);
1990 assert(windows != (XWindows *) NULL);
1991 assert(image != (Image *) NULL);
1992 if (image->debug)
1993 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1994 file=(FILE *) NULL;
1995 unique_file=AcquireUniqueFileResource(filename);
1996 if (unique_file != -1)
1997 file=fdopen(unique_file,"w");
1998 if ((unique_file == -1) || (file == (FILE *) NULL))
1999 {
2000 XNoticeWidget(display,windows,"Unable to display image info",filename);
2001 return;
2002 }
2003 if (resource_info->gamma_correct != MagickFalse)
2004 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002005 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002006 resource_info->display_gamma);
2007 /*
2008 Write info about the X image to a file.
2009 */
cristyb51dff52011-05-19 16:55:47 +00002010 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002011 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002012 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002013 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002014 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002015 windows->visual_info->colormap_size);
2016 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002017 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002018 else
cristyb51dff52011-05-19 16:55:47 +00002019 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002020 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2021 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002022 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002023 (void) FormatLocaleFile(file," crop geometry: %s\n",
2024 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002025 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002026 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002027 else
cristyb51dff52011-05-19 16:55:47 +00002028 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002029 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002030 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002031 else
cristyb51dff52011-05-19 16:55:47 +00002032 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002033 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002034 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002035 else
cristyb51dff52011-05-19 16:55:47 +00002036 (void) FormatLocaleFile(file," shared memory: False\n");
2037 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002038 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002039 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002040 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002041 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002042 /*
2043 Write info about the undo cache to a file.
2044 */
2045 bytes=0;
2046 for (levels=0; undo_image != (Image *) NULL; levels++)
2047 {
2048 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002049 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002050 undo_image=GetPreviousImageInList(undo_image);
2051 }
cristyb51dff52011-05-19 16:55:47 +00002052 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002053 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2054 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002055 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002056 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002057 /*
2058 Write info about the image to a file.
2059 */
cristy6710d842011-10-20 23:23:00 +00002060 (void) IdentifyImage(image,file,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00002061 (void) fclose(file);
cristy6710d842011-10-20 23:23:00 +00002062 text=FileToString(filename,~0,exception);
cristy3ed852e2009-09-05 21:47:34 +00002063 (void) RelinquishUniqueFileResource(filename);
2064 if (text == (char *) NULL)
2065 {
2066 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2067 "UnableToDisplayImageInfo");
2068 return;
2069 }
2070 textlist=StringToList(text);
2071 if (textlist != (char **) NULL)
2072 {
2073 char
2074 title[MaxTextExtent];
2075
2076 /*
2077 Display information about the image in the Text View widget.
2078 */
2079 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002080 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002081 image->filename);
2082 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2083 (char const **) textlist);
2084 for (i=0; textlist[i] != (char *) NULL; i++)
2085 textlist[i]=DestroyString(textlist[i]);
2086 textlist=(char **) RelinquishMagickMemory(textlist);
2087 }
2088 text=DestroyString(text);
2089}
2090
2091/*
2092%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2093% %
2094% %
2095% %
2096+ X D i t h e r I m a g e %
2097% %
2098% %
2099% %
2100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2101%
2102% XDitherImage() dithers the reference image as required by the HP Color
2103% Recovery algorithm. The color values are quantized to 3 bits of red and
2104% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2105% standard colormap.
2106%
2107% The format of the XDitherImage method is:
2108%
cristy6710d842011-10-20 23:23:00 +00002109% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002110%
2111% A description of each parameter follows:
2112%
2113% o image: the image.
2114%
2115% o ximage: Specifies a pointer to a XImage structure; returned from
2116% XCreateImage.
2117%
cristy6710d842011-10-20 23:23:00 +00002118% o exception: return any errors or warnings in this structure.
2119%
cristy3ed852e2009-09-05 21:47:34 +00002120*/
cristy6710d842011-10-20 23:23:00 +00002121static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002122{
2123 static const short int
2124 dither_red[2][16]=
2125 {
2126 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2127 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2128 },
2129 dither_green[2][16]=
2130 {
2131 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2132 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2133 },
2134 dither_blue[2][16]=
2135 {
2136 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2137 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2138 };
2139
cristyc57f6942010-11-12 01:47:39 +00002140 CacheView
2141 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002142
2143 int
cristyc57f6942010-11-12 01:47:39 +00002144 value,
cristy3ed852e2009-09-05 21:47:34 +00002145 y;
2146
cristy101ab702011-10-13 13:06:32 +00002147 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002148 color;
cristy3ed852e2009-09-05 21:47:34 +00002149
2150 register char
2151 *q;
2152
cristy4c08aed2011-07-01 19:47:50 +00002153 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002154 *p;
2155
2156 register int
2157 i,
2158 j,
2159 x;
2160
2161 unsigned int
2162 scanline_pad;
2163
cristybb503372010-05-27 20:51:26 +00002164 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002165 pixel;
2166
2167 unsigned char
2168 *blue_map[2][16],
2169 *green_map[2][16],
2170 *red_map[2][16];
2171
2172 /*
2173 Allocate and initialize dither maps.
2174 */
2175 for (i=0; i < 2; i++)
2176 for (j=0; j < 16; j++)
2177 {
2178 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2179 sizeof(*red_map));
2180 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2181 sizeof(*green_map));
2182 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2183 sizeof(*blue_map));
2184 if ((red_map[i][j] == (unsigned char *) NULL) ||
2185 (green_map[i][j] == (unsigned char *) NULL) ||
2186 (blue_map[i][j] == (unsigned char *) NULL))
2187 {
cristyc38fbf52013-11-03 13:55:54 +00002188 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
2189 image->filename);
cristy3ed852e2009-09-05 21:47:34 +00002190 return;
2191 }
2192 }
2193 /*
2194 Initialize dither tables.
2195 */
2196 for (i=0; i < 2; i++)
2197 for (j=0; j < 16; j++)
2198 for (x=0; x < 256; x++)
2199 {
2200 value=x-16;
2201 if (x < 48)
2202 value=x/2+8;
2203 value+=dither_red[i][j];
2204 red_map[i][j][x]=(unsigned char)
2205 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2206 value=x-16;
2207 if (x < 48)
2208 value=x/2+8;
2209 value+=dither_green[i][j];
2210 green_map[i][j][x]=(unsigned char)
2211 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2212 value=x-32;
2213 if (x < 112)
2214 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002215 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002216 blue_map[i][j][x]=(unsigned char)
2217 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2218 }
2219 /*
2220 Dither image.
2221 */
2222 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002223 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002224 i=0;
2225 j=0;
2226 q=ximage->data;
cristy46ff2672012-12-14 15:32:26 +00002227 image_view=AcquireVirtualCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002228 for (y=0; y < (int) image->rows; y++)
2229 {
cristyc57f6942010-11-12 01:47:39 +00002230 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
cristy6710d842011-10-20 23:23:00 +00002231 exception);
cristy4c08aed2011-07-01 19:47:50 +00002232 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002233 break;
2234 for (x=0; x < (int) image->columns; x++)
2235 {
cristyada285b2012-07-07 19:00:46 +00002236 color.red=(double) ClampToQuantum((double) (red_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002237 (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002238 color.green=(double) ClampToQuantum((double) (green_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002239 (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002240 color.blue=(double) ClampToQuantum((double) (blue_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002241 (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002242 pixel=(size_t) (((size_t) color.red & 0xe0) |
2243 (((size_t) color.green & 0xe0) >> 3) |
2244 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002245 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002246 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002247 j++;
2248 if (j == 16)
2249 j=0;
2250 }
2251 q+=scanline_pad;
2252 i++;
2253 if (i == 2)
2254 i=0;
2255 }
cristyc57f6942010-11-12 01:47:39 +00002256 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002257 /*
2258 Free allocated memory.
2259 */
2260 for (i=0; i < 2; i++)
2261 for (j=0; j < 16; j++)
2262 {
2263 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2264 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2265 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2266 }
2267}
2268
2269/*
2270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2271% %
2272% %
2273% %
2274% X D r a w I m a g e %
2275% %
2276% %
2277% %
2278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2279%
2280% XDrawImage() draws a line on the image.
2281%
2282% The format of the XDrawImage method is:
2283%
cristy6710d842011-10-20 23:23:00 +00002284% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2285% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002286%
2287% A description of each parameter follows:
2288%
2289% o display: Specifies a connection to an X server; returned from
2290% XOpenDisplay.
2291%
2292% o pixel: Specifies a pointer to a XPixelInfo structure.
2293%
2294% o draw_info: Specifies a pointer to a XDrawInfo structure.
2295%
2296% o image: the image.
2297%
cristy6710d842011-10-20 23:23:00 +00002298% o exception: return any errors or warnings in this structure.
2299%
cristy3ed852e2009-09-05 21:47:34 +00002300*/
cristybcbda3f2011-09-03 13:01:22 +00002301MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy6710d842011-10-20 23:23:00 +00002302 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2303 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002304{
cristyc57f6942010-11-12 01:47:39 +00002305 CacheView
2306 *draw_view;
2307
cristy3ed852e2009-09-05 21:47:34 +00002308 GC
2309 draw_context;
2310
2311 Image
2312 *draw_image;
2313
2314 int
2315 x,
2316 y;
2317
cristyb0a657e2012-08-29 00:45:37 +00002318 PixelTrait
2319 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002320
2321 Pixmap
2322 draw_pixmap;
2323
2324 unsigned int
2325 depth,
2326 height,
2327 width;
2328
2329 Window
2330 root_window;
2331
2332 XGCValues
2333 context_values;
2334
2335 XImage
2336 *draw_ximage;
2337
2338 /*
2339 Initialize drawd image.
2340 */
2341 assert(display != (Display *) NULL);
2342 assert(pixel != (XPixelInfo *) NULL);
2343 assert(draw_info != (XDrawInfo *) NULL);
2344 assert(image != (Image *) NULL);
2345 if (image->debug != MagickFalse)
2346 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2347 /*
2348 Initialize drawd pixmap.
2349 */
2350 root_window=XRootWindow(display,XDefaultScreen(display));
2351 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2352 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2353 draw_info->height,depth);
2354 if (draw_pixmap == (Pixmap) NULL)
2355 return(MagickFalse);
2356 /*
2357 Initialize graphics info.
2358 */
cristybb503372010-05-27 20:51:26 +00002359 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002360 context_values.foreground=0;
2361 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002362 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002363 (GCBackground | GCForeground | GCLineWidth),&context_values);
2364 if (draw_context == (GC) NULL)
2365 return(MagickFalse);
2366 /*
2367 Clear pixmap.
2368 */
2369 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2370 draw_info->height);
2371 /*
2372 Draw line to pixmap.
2373 */
2374 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002375 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002376 if (draw_info->stipple != (Pixmap) NULL)
2377 {
2378 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2379 (void) XSetStipple(display,draw_context,draw_info->stipple);
2380 }
cristy3ed852e2009-09-05 21:47:34 +00002381 switch (draw_info->element)
2382 {
2383 case PointElement:
2384 default:
2385 {
2386 (void) XDrawLines(display,draw_pixmap,draw_context,
2387 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2388 CoordModeOrigin);
2389 break;
2390 }
2391 case LineElement:
2392 {
2393 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2394 draw_info->line_info.y1,draw_info->line_info.x2,
2395 draw_info->line_info.y2);
2396 break;
2397 }
2398 case RectangleElement:
2399 {
2400 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2401 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2402 (unsigned int) draw_info->rectangle_info.width,
2403 (unsigned int) draw_info->rectangle_info.height);
2404 break;
2405 }
2406 case FillRectangleElement:
2407 {
2408 (void) XFillRectangle(display,draw_pixmap,draw_context,
2409 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2410 (unsigned int) draw_info->rectangle_info.width,
2411 (unsigned int) draw_info->rectangle_info.height);
2412 break;
2413 }
2414 case CircleElement:
2415 case EllipseElement:
2416 {
2417 (void) XDrawArc(display,draw_pixmap,draw_context,
2418 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2419 (unsigned int) draw_info->rectangle_info.width,
2420 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2421 break;
2422 }
2423 case FillCircleElement:
2424 case FillEllipseElement:
2425 {
2426 (void) XFillArc(display,draw_pixmap,draw_context,
2427 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2428 (unsigned int) draw_info->rectangle_info.width,
2429 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2430 break;
2431 }
2432 case PolygonElement:
2433 {
2434 XPoint
2435 *coordinate_info;
2436
2437 coordinate_info=draw_info->coordinate_info;
2438 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2439 (int) draw_info->number_coordinates,CoordModeOrigin);
2440 (void) XDrawLine(display,draw_pixmap,draw_context,
2441 coordinate_info[draw_info->number_coordinates-1].x,
2442 coordinate_info[draw_info->number_coordinates-1].y,
2443 coordinate_info[0].x,coordinate_info[0].y);
2444 break;
2445 }
2446 case FillPolygonElement:
2447 {
2448 (void) XFillPolygon(display,draw_pixmap,draw_context,
2449 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2450 CoordModeOrigin);
2451 break;
2452 }
2453 }
2454 (void) XFreeGC(display,draw_context);
2455 /*
2456 Initialize X image.
2457 */
2458 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2459 draw_info->height,AllPlanes,ZPixmap);
2460 if (draw_ximage == (XImage *) NULL)
2461 return(MagickFalse);
2462 (void) XFreePixmap(display,draw_pixmap);
2463 /*
2464 Initialize draw image.
2465 */
cristy6710d842011-10-20 23:23:00 +00002466 draw_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002467 if (draw_image == (Image *) NULL)
2468 return(MagickFalse);
2469 draw_image->columns=draw_info->width;
2470 draw_image->rows=draw_info->height;
2471 /*
2472 Transfer drawn X image to image.
2473 */
2474 width=(unsigned int) image->columns;
2475 height=(unsigned int) image->rows;
2476 x=0;
2477 y=0;
2478 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +00002479 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
2480 (ssize_t) y,&draw_image->background_color,exception);
cristy6710d842011-10-20 23:23:00 +00002481 if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002482 return(MagickFalse);
cristy8a46d822012-08-28 23:32:39 +00002483 draw_image->alpha_trait=BlendPixelTrait;
cristy6f5395d2012-12-14 18:30:30 +00002484 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002485 for (y=0; y < (int) draw_image->rows; y++)
2486 {
cristyc57f6942010-11-12 01:47:39 +00002487 register int
cristy3ed852e2009-09-05 21:47:34 +00002488 x;
2489
cristy4c08aed2011-07-01 19:47:50 +00002490 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002491 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002492
cristyc57f6942010-11-12 01:47:39 +00002493 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2494 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002495 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002496 break;
cristyc57f6942010-11-12 01:47:39 +00002497 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002498 {
2499 if (XGetPixel(draw_ximage,x,y) == 0)
2500 {
2501 /*
2502 Set this pixel to the background color.
2503 */
cristy803640d2011-11-17 02:11:32 +00002504 SetPixelInfoPixel(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002505 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002506 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002507 }
2508 else
2509 {
2510 /*
2511 Set this pixel to the pen color.
2512 */
cristy4c08aed2011-07-01 19:47:50 +00002513 SetPixelRed(draw_image,ScaleShortToQuantum(
2514 pixel->pen_color.red),q);
2515 SetPixelGreen(draw_image,ScaleShortToQuantum(
2516 pixel->pen_color.green),q);
2517 SetPixelBlue(draw_image,ScaleShortToQuantum(
2518 pixel->pen_color.blue),q);
2519 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2520 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002521 }
cristyed231572011-07-14 02:18:59 +00002522 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002523 }
cristyc57f6942010-11-12 01:47:39 +00002524 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002525 break;
2526 }
cristyc57f6942010-11-12 01:47:39 +00002527 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002528 XDestroyImage(draw_ximage);
2529 /*
2530 Determine draw geometry.
2531 */
2532 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2533 if ((width != (unsigned int) draw_image->columns) ||
2534 (height != (unsigned int) draw_image->rows))
2535 {
2536 char
2537 image_geometry[MaxTextExtent];
2538
2539 /*
2540 Scale image.
2541 */
cristyb51dff52011-05-19 16:55:47 +00002542 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002543 width,height);
cristye941a752011-10-15 01:52:48 +00002544 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2545 exception);
cristy3ed852e2009-09-05 21:47:34 +00002546 }
2547 if (draw_info->degrees != 0.0)
2548 {
2549 Image
2550 *rotate_image;
2551
2552 int
2553 rotations;
2554
cristya19f1d72012-08-07 18:24:38 +00002555 double
cristy3ed852e2009-09-05 21:47:34 +00002556 normalized_degrees;
2557
2558 /*
2559 Rotate image.
2560 */
cristy6710d842011-10-20 23:23:00 +00002561 rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +00002562 if (rotate_image == (Image *) NULL)
2563 return(MagickFalse);
2564 draw_image=DestroyImage(draw_image);
2565 draw_image=rotate_image;
2566 /*
2567 Annotation is relative to the degree of rotation.
2568 */
2569 normalized_degrees=draw_info->degrees;
2570 while (normalized_degrees < -45.0)
2571 normalized_degrees+=360.0;
2572 for (rotations=0; normalized_degrees > 45.0; rotations++)
2573 normalized_degrees-=90.0;
2574 switch (rotations % 4)
2575 {
2576 default:
2577 case 0:
2578 break;
2579 case 1:
2580 {
2581 /*
2582 Rotate 90 degrees.
2583 */
2584 x=x-(int) draw_image->columns/2;
2585 y=y+(int) draw_image->columns/2;
2586 break;
2587 }
2588 case 2:
2589 {
2590 /*
2591 Rotate 180 degrees.
2592 */
2593 x=x-(int) draw_image->columns;
2594 break;
2595 }
2596 case 3:
2597 {
2598 /*
2599 Rotate 270 degrees.
2600 */
2601 x=x-(int) draw_image->columns/2;
2602 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2603 break;
2604 }
2605 }
2606 }
2607 /*
2608 Composite text onto the image.
2609 */
cristy6f5395d2012-12-14 18:30:30 +00002610 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002611 for (y=0; y < (int) draw_image->rows; y++)
2612 {
cristyc57f6942010-11-12 01:47:39 +00002613 register int
cristy3ed852e2009-09-05 21:47:34 +00002614 x;
2615
cristy4c08aed2011-07-01 19:47:50 +00002616 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002617 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002618
cristyc57f6942010-11-12 01:47:39 +00002619 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2620 exception);
cristyacd2ed22011-08-30 01:44:23 +00002621 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002622 break;
cristyc57f6942010-11-12 01:47:39 +00002623 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002624 {
cristy4c08aed2011-07-01 19:47:50 +00002625 if (GetPixelAlpha(image,q) != TransparentAlpha)
2626 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002627 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002628 }
cristyc57f6942010-11-12 01:47:39 +00002629 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002630 break;
2631 }
cristyc57f6942010-11-12 01:47:39 +00002632 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002633 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2634 if (draw_info->stencil == TransparentStencil)
cristy39172402012-03-30 13:04:39 +00002635 (void) CompositeImage(image,draw_image,CopyAlphaCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002636 (ssize_t) x,(ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002637 else
2638 {
cristyb0a657e2012-08-29 00:45:37 +00002639 alpha_trait=image->alpha_trait;
cristy39172402012-03-30 13:04:39 +00002640 (void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002641 (ssize_t) x,(ssize_t) y,exception);
cristyb0a657e2012-08-29 00:45:37 +00002642 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002643 }
2644 draw_image=DestroyImage(draw_image);
2645 return(MagickTrue);
2646}
2647
2648/*
2649%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2650% %
2651% %
2652% %
2653% X E r r o r %
2654% %
2655% %
2656% %
2657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2658%
2659% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2660% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002661% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2662% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002663%
2664% The format of the XError function is:
2665%
cristybcbda3f2011-09-03 13:01:22 +00002666% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002667%
2668% A description of each parameter follows:
2669%
2670% o display: Specifies a pointer to the Display structure; returned from
2671% XOpenDisplay.
2672%
2673% o error: Specifies the error event.
2674%
2675*/
2676
2677#if defined(__cplusplus) || defined(c_plusplus)
2678extern "C" {
2679#endif
2680
2681MagickExport int XError(Display *display,XErrorEvent *error)
2682{
2683 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2684 assert(display != (Display *) NULL);
2685 assert(error != (XErrorEvent *) NULL);
2686 xerror_alert=MagickTrue;
2687 switch (error->request_code)
2688 {
2689 case X_GetGeometry:
2690 {
2691 if ((int) error->error_code == BadDrawable)
2692 return(MagickFalse);
2693 break;
2694 }
2695 case X_GetWindowAttributes:
2696 case X_QueryTree:
2697 {
2698 if ((int) error->error_code == BadWindow)
2699 return(MagickFalse);
2700 break;
2701 }
2702 case X_QueryColors:
2703 {
2704 if ((int) error->error_code == BadValue)
2705 return(MagickFalse);
2706 break;
2707 }
2708 }
2709 return(MagickTrue);
2710}
2711
2712#if defined(__cplusplus) || defined(c_plusplus)
2713}
2714#endif
2715
2716/*
2717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2718% %
2719% %
2720% %
2721% X F r e e R e s o u r c e s %
2722% %
2723% %
2724% %
2725%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2726%
2727% XFreeResources() frees X11 resources.
2728%
2729% The format of the XFreeResources method is:
2730%
2731% void XFreeResources(Display *display,XVisualInfo *visual_info,
2732% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2733% XResourceInfo *resource_info,XWindowInfo *window_info)
2734% resource_info,window_info)
2735%
2736% A description of each parameter follows:
2737%
2738% o display: Specifies a connection to an X server; returned from
2739% XOpenDisplay.
2740%
2741% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2742% returned from XGetVisualInfo.
2743%
2744% o map_info: If map_type is specified, this structure is initialized
2745% with info from the Standard Colormap.
2746%
2747% o pixel: Specifies a pointer to a XPixelInfo structure.
2748%
2749% o font_info: Specifies a pointer to a XFontStruct structure.
2750%
2751% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2752%
2753% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2754%
2755*/
cristybcbda3f2011-09-03 13:01:22 +00002756MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002757 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2758 XResourceInfo *resource_info,XWindowInfo *window_info)
2759{
2760 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2761 assert(display != (Display *) NULL);
2762 assert(resource_info != (XResourceInfo *) NULL);
2763 if (window_info != (XWindowInfo *) NULL)
2764 {
2765 /*
2766 Free X image.
2767 */
2768 if (window_info->ximage != (XImage *) NULL)
2769 XDestroyImage(window_info->ximage);
2770 if (window_info->id != (Window) NULL)
2771 {
2772 /*
2773 Free destroy window and free cursors.
2774 */
2775 if (window_info->id != XRootWindow(display,visual_info->screen))
2776 (void) XDestroyWindow(display,window_info->id);
2777 if (window_info->annotate_context != (GC) NULL)
2778 (void) XFreeGC(display,window_info->annotate_context);
2779 if (window_info->highlight_context != (GC) NULL)
2780 (void) XFreeGC(display,window_info->highlight_context);
2781 if (window_info->widget_context != (GC) NULL)
2782 (void) XFreeGC(display,window_info->widget_context);
2783 if (window_info->cursor != (Cursor) NULL)
2784 (void) XFreeCursor(display,window_info->cursor);
2785 window_info->cursor=(Cursor) NULL;
2786 if (window_info->busy_cursor != (Cursor) NULL)
2787 (void) XFreeCursor(display,window_info->busy_cursor);
2788 window_info->busy_cursor=(Cursor) NULL;
2789 }
2790 }
2791 /*
2792 Free font.
2793 */
2794 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002795 {
2796 (void) XFreeFont(display,font_info);
2797 font_info=(XFontStruct *) NULL;
2798 }
cristy3ed852e2009-09-05 21:47:34 +00002799 if (map_info != (XStandardColormap *) NULL)
2800 {
2801 /*
2802 Free X Standard Colormap.
2803 */
2804 if (resource_info->map_type == (char *) NULL)
2805 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2806 (void) XFree((void *) map_info);
2807 }
2808 /*
2809 Free X visual info.
2810 */
2811 if (visual_info != (XVisualInfo *) NULL)
2812 (void) XFree((void *) visual_info);
2813 if (resource_info->close_server != MagickFalse)
2814 (void) XCloseDisplay(display);
2815}
2816
2817/*
2818%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2819% %
2820% %
2821% %
2822% X F r e e S t a n d a r d C o l o r m a p %
2823% %
2824% %
2825% %
2826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2827%
2828% XFreeStandardColormap() frees an X11 colormap.
2829%
2830% The format of the XFreeStandardColormap method is:
2831%
2832% void XFreeStandardColormap(Display *display,
2833% const XVisualInfo *visual_info,XStandardColormap *map_info,
2834% XPixelInfo *pixel)
2835%
2836% A description of each parameter follows:
2837%
2838% o display: Specifies a connection to an X server; returned from
2839% XOpenDisplay.
2840%
2841% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2842% returned from XGetVisualInfo.
2843%
2844% o map_info: If map_type is specified, this structure is initialized
2845% with info from the Standard Colormap.
2846%
2847% o pixel: Specifies a pointer to a XPixelInfo structure.
2848%
2849*/
cristybcbda3f2011-09-03 13:01:22 +00002850MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002851 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2852{
2853 /*
2854 Free colormap.
2855 */
2856 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2857 assert(display != (Display *) NULL);
2858 assert(visual_info != (XVisualInfo *) NULL);
2859 assert(map_info != (XStandardColormap *) NULL);
2860 (void) XFlush(display);
2861 if (map_info->colormap != (Colormap) NULL)
2862 {
2863 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2864 (void) XFreeColormap(display,map_info->colormap);
2865 else
2866 if (pixel != (XPixelInfo *) NULL)
2867 if ((visual_info->klass != TrueColor) &&
2868 (visual_info->klass != DirectColor))
2869 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2870 (int) pixel->colors,0);
2871 }
2872 map_info->colormap=(Colormap) NULL;
2873 if (pixel != (XPixelInfo *) NULL)
2874 {
cristyf2faecf2010-05-28 19:19:36 +00002875 if (pixel->pixels != (unsigned long *) NULL)
2876 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2877 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002878 }
2879}
2880
2881/*
2882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2883% %
2884% %
2885% %
2886% X G e t A n n o t a t e I n f o %
2887% %
2888% %
2889% %
2890%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2891%
2892% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2893%
2894% The format of the XGetAnnotateInfo method is:
2895%
2896% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2897%
2898% A description of each parameter follows:
2899%
2900% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2901%
2902*/
cristybcbda3f2011-09-03 13:01:22 +00002903MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002904{
2905 /*
2906 Initialize annotate structure.
2907 */
2908 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2909 assert(annotate_info != (XAnnotateInfo *) NULL);
2910 annotate_info->x=0;
2911 annotate_info->y=0;
2912 annotate_info->width=0;
2913 annotate_info->height=0;
2914 annotate_info->stencil=ForegroundStencil;
2915 annotate_info->degrees=0.0;
2916 annotate_info->font_info=(XFontStruct *) NULL;
2917 annotate_info->text=(char *) NULL;
2918 *annotate_info->geometry='\0';
2919 annotate_info->previous=(XAnnotateInfo *) NULL;
2920 annotate_info->next=(XAnnotateInfo *) NULL;
2921 (void) XSupportsLocale();
2922 (void) XSetLocaleModifiers("");
2923}
2924
2925/*
2926%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2927% %
2928% %
2929% %
2930% X G e t M a p I n f o %
2931% %
2932% %
2933% %
2934%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2935%
2936% XGetMapInfo() initializes the XStandardColormap structure.
2937%
2938% The format of the XStandardColormap method is:
2939%
2940% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2941% XStandardColormap *map_info)
2942%
2943% A description of each parameter follows:
2944%
2945% o colormap: Specifies the ID of the X server colormap.
2946%
2947% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2948% returned from XGetVisualInfo.
2949%
2950% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2951%
2952*/
cristybcbda3f2011-09-03 13:01:22 +00002953MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002954 const Colormap colormap,XStandardColormap *map_info)
2955{
2956 /*
2957 Initialize map info.
2958 */
2959 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2960 assert(visual_info != (XVisualInfo *) NULL);
2961 assert(map_info != (XStandardColormap *) NULL);
2962 map_info->colormap=colormap;
2963 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002964 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002965 if (map_info->red_max != 0)
2966 while ((map_info->red_max & 0x01) == 0)
2967 {
2968 map_info->red_max>>=1;
2969 map_info->red_mult<<=1;
2970 }
2971 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002972 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002973 if (map_info->green_max != 0)
2974 while ((map_info->green_max & 0x01) == 0)
2975 {
2976 map_info->green_max>>=1;
2977 map_info->green_mult<<=1;
2978 }
2979 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002980 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002981 if (map_info->blue_max != 0)
2982 while ((map_info->blue_max & 0x01) == 0)
2983 {
2984 map_info->blue_max>>=1;
2985 map_info->blue_mult<<=1;
2986 }
2987 map_info->base_pixel=0;
2988}
2989
2990/*
2991%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2992% %
2993% %
2994% %
2995% X G e t P i x e l I n f o %
2996% %
2997% %
2998% %
2999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3000%
cristy101ab702011-10-13 13:06:32 +00003001% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00003002%
cristy4c08aed2011-07-01 19:47:50 +00003003% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00003004%
cristy4c08aed2011-07-01 19:47:50 +00003005% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00003006% const XStandardColormap *map_info,const XResourceInfo *resource_info,
3007% Image *image,XPixelInfo *pixel)
3008% pixel)
3009%
3010% A description of each parameter follows:
3011%
3012% o display: Specifies a connection to an X server; returned from
3013% XOpenDisplay.
3014%
3015% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3016% returned from XGetVisualInfo.
3017%
3018% o map_info: If map_type is specified, this structure is initialized
3019% with info from the Standard Colormap.
3020%
3021% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3022%
3023% o image: the image.
3024%
3025% o pixel: Specifies a pointer to a XPixelInfo structure.
3026%
3027*/
cristybcbda3f2011-09-03 13:01:22 +00003028MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003029 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3030 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3031{
3032 static const char
3033 *PenColors[MaxNumberPens]=
3034 {
3035 "#000000000000", /* black */
3036 "#00000000ffff", /* blue */
3037 "#0000ffffffff", /* cyan */
3038 "#0000ffff0000", /* green */
3039 "#bdbdbdbdbdbd", /* gray */
3040 "#ffff00000000", /* red */
3041 "#ffff0000ffff", /* magenta */
3042 "#ffffffff0000", /* yellow */
3043 "#ffffffffffff", /* white */
3044 "#bdbdbdbdbdbd", /* gray */
3045 "#bdbdbdbdbdbd" /* gray */
3046 };
3047
3048 Colormap
3049 colormap;
3050
cristybcdf5672012-05-24 22:58:54 +00003051 extern const char
3052 BorderColor[],
3053 ForegroundColor[];
3054
cristybb503372010-05-27 20:51:26 +00003055 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003056 i;
3057
3058 Status
3059 status;
3060
3061 unsigned int
3062 packets;
3063
3064 /*
3065 Initialize pixel info.
3066 */
3067 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3068 assert(display != (Display *) NULL);
3069 assert(visual_info != (XVisualInfo *) NULL);
3070 assert(map_info != (XStandardColormap *) NULL);
3071 assert(resource_info != (XResourceInfo *) NULL);
3072 assert(pixel != (XPixelInfo *) NULL);
3073 pixel->colors=0;
3074 if (image != (Image *) NULL)
3075 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003076 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003077 packets=(unsigned int)
3078 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003079 if (pixel->pixels != (unsigned long *) NULL)
3080 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3081 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003082 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003083 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003084 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3085 image->filename);
3086 /*
3087 Set foreground color.
3088 */
3089 colormap=map_info->colormap;
3090 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3091 &pixel->foreground_color);
3092 status=XParseColor(display,colormap,resource_info->foreground_color,
3093 &pixel->foreground_color);
3094 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003095 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003096 resource_info->foreground_color);
3097 pixel->foreground_color.pixel=
3098 XStandardPixel(map_info,&pixel->foreground_color);
3099 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3100 /*
3101 Set background color.
3102 */
3103 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3104 status=XParseColor(display,colormap,resource_info->background_color,
3105 &pixel->background_color);
3106 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003107 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003108 resource_info->background_color);
3109 pixel->background_color.pixel=
3110 XStandardPixel(map_info,&pixel->background_color);
3111 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3112 /*
3113 Set border color.
3114 */
3115 (void) XParseColor(display,colormap,(char *) BorderColor,
3116 &pixel->border_color);
3117 status=XParseColor(display,colormap,resource_info->border_color,
3118 &pixel->border_color);
3119 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003120 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003121 resource_info->border_color);
3122 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3123 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3124 /*
3125 Set matte color.
3126 */
3127 pixel->matte_color=pixel->background_color;
3128 if (resource_info->matte_color != (char *) NULL)
3129 {
3130 /*
3131 Matte color is specified as a X resource or command line argument.
3132 */
3133 status=XParseColor(display,colormap,resource_info->matte_color,
3134 &pixel->matte_color);
3135 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003136 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003137 resource_info->matte_color);
3138 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3139 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3140 }
3141 /*
3142 Set highlight color.
3143 */
3144 pixel->highlight_color.red=(unsigned short) ((
3145 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3146 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3147 pixel->highlight_color.green=(unsigned short) ((
3148 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3149 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3150 pixel->highlight_color.blue=(unsigned short) ((
3151 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3152 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3153 pixel->highlight_color.pixel=
3154 XStandardPixel(map_info,&pixel->highlight_color);
3155 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3156 /*
3157 Set shadow color.
3158 */
cristya19f1d72012-08-07 18:24:38 +00003159 pixel->shadow_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003160 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003161 pixel->shadow_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003162 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003163 pixel->shadow_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003164 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3165 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3166 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3167 /*
3168 Set depth color.
3169 */
cristya19f1d72012-08-07 18:24:38 +00003170 pixel->depth_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003171 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003172 pixel->depth_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003173 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003174 pixel->depth_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003175 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3176 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3177 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3178 /*
3179 Set trough color.
3180 */
cristya19f1d72012-08-07 18:24:38 +00003181 pixel->trough_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003182 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003183 pixel->trough_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003184 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003185 pixel->trough_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003186 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3187 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3188 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3189 /*
3190 Set pen color.
3191 */
3192 for (i=0; i < MaxNumberPens; i++)
3193 {
3194 (void) XParseColor(display,colormap,(char *) PenColors[i],
3195 &pixel->pen_colors[i]);
3196 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3197 &pixel->pen_colors[i]);
3198 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003199 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003200 resource_info->pen_colors[i]);
3201 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3202 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3203 }
3204 pixel->box_color=pixel->background_color;
3205 pixel->pen_color=pixel->foreground_color;
3206 pixel->box_index=0;
3207 pixel->pen_index=1;
3208 if (image != (Image *) NULL)
3209 {
3210 if ((resource_info->gamma_correct != MagickFalse) &&
3211 (image->gamma != 0.0))
3212 {
3213 GeometryInfo
3214 geometry_info;
3215
3216 MagickStatusType
3217 flags;
3218
3219 /*
3220 Initialize map relative to display and image gamma.
3221 */
3222 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3223 red_gamma=geometry_info.rho;
3224 green_gamma=geometry_info.sigma;
3225 if ((flags & SigmaValue) == 0)
3226 green_gamma=red_gamma;
3227 blue_gamma=geometry_info.xi;
3228 if ((flags & XiValue) == 0)
3229 blue_gamma=red_gamma;
3230 red_gamma*=image->gamma;
3231 green_gamma*=image->gamma;
3232 blue_gamma*=image->gamma;
3233 }
3234 if (image->storage_class == PseudoClass)
3235 {
3236 /*
3237 Initialize pixel array for images of type PseudoClass.
3238 */
cristybb503372010-05-27 20:51:26 +00003239 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003240 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003241 for (i=0; i < MaxNumberPens; i++)
3242 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3243 pixel->colors+=MaxNumberPens;
3244 }
3245 }
3246}
3247
3248/*
3249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3250% %
3251% %
3252% %
3253% X G e t R e s o u r c e C l a s s %
3254% %
3255% %
3256% %
3257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3258%
3259% XGetResourceClass() queries the X server for the specified resource name or
3260% class. If the resource name or class is not defined in the database, the
3261% supplied default value is returned.
3262%
3263% The format of the XGetResourceClass method is:
3264%
3265% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3266% const char *keyword,char *resource_default)
3267%
3268% A description of each parameter follows:
3269%
3270% o database: Specifies a resource database; returned from
3271% XrmGetStringDatabase.
3272%
3273% o client_name: Specifies the application name used to retrieve resource
3274% info from the X server database.
3275%
3276% o keyword: Specifies the keyword of the value being retrieved.
3277%
3278% o resource_default: Specifies the default value to return if the query
3279% fails to find the specified keyword/class.
3280%
3281*/
3282MagickExport char *XGetResourceClass(XrmDatabase database,
3283 const char *client_name,const char *keyword,char *resource_default)
3284{
3285 char
3286 resource_class[MaxTextExtent],
3287 resource_name[MaxTextExtent];
3288
3289 static char
3290 *resource_type;
3291
3292 Status
3293 status;
3294
3295 XrmValue
3296 resource_value;
3297
3298 if (database == (XrmDatabase) NULL)
3299 return(resource_default);
3300 *resource_name='\0';
3301 *resource_class='\0';
3302 if (keyword != (char *) NULL)
3303 {
3304 int
3305 c,
3306 k;
3307
3308 /*
3309 Initialize resource keyword and class.
3310 */
cristyb51dff52011-05-19 16:55:47 +00003311 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003312 client_name,keyword);
3313 c=(int) (*client_name);
3314 if ((c >= XK_a) && (c <= XK_z))
3315 c-=(XK_a-XK_A);
3316 else
3317 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3318 c-=(XK_agrave-XK_Agrave);
3319 else
3320 if ((c >= XK_oslash) && (c <= XK_thorn))
3321 c-=(XK_oslash-XK_Ooblique);
3322 k=(int) (*keyword);
3323 if ((k >= XK_a) && (k <= XK_z))
3324 k-=(XK_a-XK_A);
3325 else
3326 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3327 k-=(XK_agrave-XK_Agrave);
3328 else
3329 if ((k >= XK_oslash) && (k <= XK_thorn))
3330 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003331 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003332 client_name+1,k,keyword+1);
3333 }
3334 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3335 &resource_value);
3336 if (status == False)
3337 return(resource_default);
3338 return(resource_value.addr);
3339}
3340
3341/*
3342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3343% %
3344% %
3345% %
3346% X G e t R e s o u r c e D a t a b a s e %
3347% %
3348% %
3349% %
3350%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3351%
3352% XGetResourceDatabase() creates a new resource database and initializes it.
3353%
3354% The format of the XGetResourceDatabase method is:
3355%
3356% XrmDatabase XGetResourceDatabase(Display *display,
3357% const char *client_name)
3358%
3359% A description of each parameter follows:
3360%
3361% o database: XGetResourceDatabase() returns the database after it is
3362% initialized.
3363%
3364% o display: Specifies a connection to an X server; returned from
3365% XOpenDisplay.
3366%
3367% o client_name: Specifies the application name used to retrieve resource
3368% info from the X server database.
3369%
3370*/
3371MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3372 const char *client_name)
3373{
3374 char
3375 filename[MaxTextExtent];
3376
3377 int
3378 c;
3379
3380 register const char
3381 *p;
3382
3383 XrmDatabase
3384 resource_database,
3385 server_database;
3386
3387 if (display == (Display *) NULL)
3388 return((XrmDatabase) NULL);
3389 assert(client_name != (char *) NULL);
3390 /*
3391 Initialize resource database.
3392 */
3393 XrmInitialize();
3394 (void) XGetDefault(display,(char *) client_name,"dummy");
3395 resource_database=XrmGetDatabase(display);
3396 /*
3397 Combine application database.
3398 */
3399 if (client_name != (char *) NULL)
3400 {
3401 /*
3402 Get basename of client.
3403 */
3404 p=client_name+(strlen(client_name)-1);
3405 while ((p > client_name) && (*p != '/'))
3406 p--;
3407 if (*p == '/')
3408 client_name=p+1;
3409 }
3410 c=(int) (*client_name);
3411 if ((c >= XK_a) && (c <= XK_z))
3412 c-=(XK_a-XK_A);
3413 else
3414 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3415 c-=(XK_agrave-XK_Agrave);
3416 else
3417 if ((c >= XK_oslash) && (c <= XK_thorn))
3418 c-=(XK_oslash-XK_Ooblique);
3419#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003420 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003421 X11_APPLICATION_PATH,c,client_name+1);
3422 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3423#endif
3424 if (XResourceManagerString(display) != (char *) NULL)
3425 {
3426 /*
3427 Combine server database.
3428 */
3429 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3430 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3431 }
3432 /*
3433 Merge user preferences database.
3434 */
3435#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003436 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003437 X11_PREFERENCES_PATH,client_name);
3438 ExpandFilename(filename);
3439 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3440#endif
3441 return(resource_database);
3442}
3443
3444/*
3445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3446% %
3447% %
3448% %
3449% X G e t R e s o u r c e I n f o %
3450% %
3451% %
3452% %
3453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3454%
3455% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3456%
3457% The format of the XGetResourceInfo method is:
3458%
3459% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3460% const char *client_name,XResourceInfo *resource_info)
3461%
3462% A description of each parameter follows:
3463%
3464% o image_info: the image info.
3465%
3466% o database: Specifies a resource database; returned from
3467% XrmGetStringDatabase.
3468%
3469% o client_name: Specifies the application name used to retrieve
3470% resource info from the X server database.
3471%
3472% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3473%
3474*/
3475MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3476 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3477{
3478 char
cristy00976d82011-02-20 20:31:28 +00003479 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003480 *resource_value;
3481
cristybcdf5672012-05-24 22:58:54 +00003482 extern const char
3483 BorderColor[],
3484 ForegroundColor[];
3485
cristy3ed852e2009-09-05 21:47:34 +00003486 /*
3487 Initialize resource info fields.
3488 */
3489 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3490 assert(resource_info != (XResourceInfo *) NULL);
3491 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3492 resource_info->resource_database=database;
3493 resource_info->image_info=(ImageInfo *) image_info;
3494 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3495 XMagickProgressMonitor,(void *) NULL);
3496 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3497 resource_info->close_server=MagickTrue;
3498 resource_info->client_name=AcquireString(client_name);
3499 resource_value=XGetResourceClass(database,client_name,"backdrop",
3500 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003501 resource_info->backdrop=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003502 resource_info->background_color=XGetResourceInstance(database,client_name,
3503 "background",(char *) "#d6d6d6d6d6d6");
3504 resource_info->border_color=XGetResourceInstance(database,client_name,
3505 "borderColor",BorderColor);
3506 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3507 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003508 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3509 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003510 resource_value=XGetResourceClass(database,client_name,"colormap",
3511 (char *) "shared");
3512 resource_info->colormap=UndefinedColormap;
3513 if (LocaleCompare("private",resource_value) == 0)
3514 resource_info->colormap=PrivateColormap;
3515 if (LocaleCompare("shared",resource_value) == 0)
3516 resource_info->colormap=SharedColormap;
3517 if (resource_info->colormap == UndefinedColormap)
cristyc38fbf52013-11-03 13:55:54 +00003518 ThrowXWindowException(OptionError,"UnrecognizedColormapType",
cristy3ed852e2009-09-05 21:47:34 +00003519 resource_value);
3520 resource_value=XGetResourceClass(database,client_name,
3521 "colorRecovery",(char *) "False");
anthony6f201312012-03-30 04:08:15 +00003522 resource_info->color_recovery=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003523 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3524 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003525 resource_info->confirm_exit=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003526 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3527 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003528 resource_info->confirm_edit=IsStringTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003529 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003530 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003531 resource_info->display_gamma=XGetResourceClass(database,client_name,
3532 "displayGamma",(char *) "2.2");
3533 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3534 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003535 resource_info->display_warnings=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003536 resource_info->font=XGetResourceClass(database,client_name,"font",
3537 (char *) NULL);
3538 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3539 resource_info->font);
3540 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3541 (char *) "fixed");
3542 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3543 (char *) "variable");
3544 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3545 (char *) "5x8");
3546 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3547 (char *) "6x10");
3548 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3549 (char *) "7x13bold");
3550 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3551 (char *) "8x13bold");
3552 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3553 (char *) "9x15bold");
3554 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3555 (char *) "10x20");
3556 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3557 (char *) "12x24");
3558 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3559 (char *) "fixed");
3560 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3561 (char *) "fixed");
3562 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3563 "foreground",ForegroundColor);
3564 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
cristy8bc259b2012-06-21 23:53:15 +00003565 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003566 resource_info->gamma_correct=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003567 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3568 client_name,"geometry",(char *) NULL));
3569 resource_value=XGetResourceClass(database,client_name,"gravity",
3570 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003571 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003572 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003573 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3574 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003575 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3576 "iconGeometry",(char *) NULL);
3577 resource_value=XGetResourceClass(database,client_name,"iconic",
3578 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003579 resource_info->iconic=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003580 resource_value=XGetResourceClass(database,client_name,"immutable",
3581 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3582 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003583 resource_info->immutable=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003584 resource_value=XGetResourceClass(database,client_name,"magnify",
3585 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003586 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003587 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3588 (char *) NULL);
3589 resource_info->matte_color=XGetResourceInstance(database,client_name,
3590 "mattecolor",(char *) NULL);
3591 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3592 "name",(char *) NULL));
3593 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3594 (char *) "black");
3595 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3596 (char *) "blue");
3597 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3598 (char *) "cyan");
3599 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3600 (char *) "green");
3601 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3602 (char *) "gray");
3603 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3604 (char *) "red");
3605 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3606 (char *) "magenta");
3607 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3608 (char *) "yellow");
3609 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3610 (char *) "white");
3611 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3612 (char *) "gray");
3613 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3614 (char *) "gray");
3615 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003616 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003617 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003618 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003619 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3620 "font",(char *) "fixed");
3621 resource_info->text_font=XGetResourceClass(database,client_name,
3622 "textFontList",resource_info->text_font);
3623 resource_info->title=XGetResourceClass(database,client_name,"title",
3624 (char *) NULL);
3625 resource_value=XGetResourceClass(database,client_name,"undoCache",
cristy92befbd2012-09-16 14:08:12 +00003626 (char *) "256");
cristye27293e2009-12-18 02:53:20 +00003627 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003628 resource_value=XGetResourceClass(database,client_name,"update",
3629 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003630 resource_info->update=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003631 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3632 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003633 resource_info->use_pixmap=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003634 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3635 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003636 resource_info->use_shared_memory=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003637 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3638 (char *) NULL);
3639 resource_info->window_group=XGetResourceClass(database,client_name,
3640 "windowGroup",(char *) NULL);
3641 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3642 (char *) NULL);
3643 resource_info->write_filename=XGetResourceClass(database,client_name,
3644 "writeFilename",(char *) NULL);
3645}
3646
3647/*
3648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3649% %
3650% %
3651% %
3652% X G e t R e s o u r c e I n s t a n c e %
3653% %
3654% %
3655% %
3656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3657%
3658% XGetResourceInstance() queries the X server for the specified resource name.
3659% If the resource name is not defined in the database, the supplied default
3660% value is returned.
3661%
3662% The format of the XGetResourceInstance method is:
3663%
3664% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3665% const char *keyword,const char *resource_default)
3666%
3667% A description of each parameter follows:
3668%
3669% o database: Specifies a resource database; returned from
3670% XrmGetStringDatabase.
3671%
3672% o client_name: Specifies the application name used to retrieve
3673% resource info from the X server database.
3674%
3675% o keyword: Specifies the keyword of the value being retrieved.
3676%
3677% o resource_default: Specifies the default value to return if the query
3678% fails to find the specified keyword/class.
3679%
3680*/
3681MagickExport char *XGetResourceInstance(XrmDatabase database,
3682 const char *client_name,const char *keyword,const char *resource_default)
3683{
3684 char
3685 *resource_type,
3686 resource_name[MaxTextExtent];
3687
3688 Status
3689 status;
3690
3691 XrmValue
3692 resource_value;
3693
3694 if (database == (XrmDatabase) NULL)
3695 return((char *) resource_default);
3696 *resource_name='\0';
3697 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003698 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003699 keyword);
3700 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3701 &resource_value);
3702 if (status == False)
3703 return((char *) resource_default);
3704 return(resource_value.addr);
3705}
3706
3707/*
3708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3709% %
3710% %
3711% %
3712% X G e t S c r e e n D e n s i t y %
3713% %
3714% %
3715% %
3716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3717%
3718% XGetScreenDensity() returns the density of the X server screen in
3719% dots-per-inch.
3720%
3721% The format of the XGetScreenDensity method is:
3722%
3723% char *XGetScreenDensity(Display *display)
3724%
3725% A description of each parameter follows:
3726%
3727% o density: XGetScreenDensity() returns the density of the X screen in
3728% dots-per-inch.
3729%
3730% o display: Specifies a connection to an X server; returned from
3731% XOpenDisplay.
3732%
3733*/
3734MagickExport char *XGetScreenDensity(Display *display)
3735{
3736 char
3737 density[MaxTextExtent];
3738
3739 double
3740 x_density,
3741 y_density;
3742
3743 /*
3744 Set density as determined by screen size.
3745 */
3746 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3747 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3748 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3749 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003750 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003751 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003752 return(GetPageGeometry(density));
3753}
3754
3755/*
3756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3757% %
3758% %
3759% %
3760+ X G e t S u b w i n d o w %
3761% %
3762% %
3763% %
3764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3765%
3766% XGetSubwindow() returns the subwindow of a window chosen the user with the
3767% pointer and a button press.
3768%
3769% The format of the XGetSubwindow method is:
3770%
3771% Window XGetSubwindow(Display *display,Window window,int x,int y)
3772%
3773% A description of each parameter follows:
3774%
3775% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3776% otherwise the subwindow is returned.
3777%
3778% o display: Specifies a connection to an X server; returned from
3779% XOpenDisplay.
3780%
3781% o window: Specifies a pointer to a Window.
3782%
3783% o x: the x coordinate of the pointer relative to the origin of the
3784% window.
3785%
3786% o y: the y coordinate of the pointer relative to the origin of the
3787% window.
3788%
cristy3ed852e2009-09-05 21:47:34 +00003789*/
3790static Window XGetSubwindow(Display *display,Window window,int x,int y)
3791{
3792 int
3793 x_offset,
3794 y_offset;
3795
3796 Status
3797 status;
3798
3799 Window
3800 source_window,
3801 target_window;
3802
3803 assert(display != (Display *) NULL);
3804 source_window=XRootWindow(display,XDefaultScreen(display));
3805 if (window == (Window) NULL)
3806 return(source_window);
3807 target_window=window;
3808 for ( ; ; )
3809 {
3810 status=XTranslateCoordinates(display,source_window,window,x,y,
3811 &x_offset,&y_offset,&target_window);
3812 if (status != True)
3813 break;
3814 if (target_window == (Window) NULL)
3815 break;
3816 source_window=window;
3817 window=target_window;
3818 x=x_offset;
3819 y=y_offset;
3820 }
3821 if (target_window == (Window) NULL)
3822 target_window=window;
3823 return(target_window);
3824}
3825
3826/*
3827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3828% %
3829% %
3830% %
3831% X G e t W i n d o w C o l o r %
3832% %
3833% %
3834% %
3835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3836%
3837% XGetWindowColor() returns the color of a pixel interactively chosen from the
3838% X server.
3839%
3840% The format of the XGetWindowColor method is:
3841%
3842% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003843% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003844%
3845% A description of each parameter follows:
3846%
3847% o display: Specifies a connection to an X server; returned from
3848% XOpenDisplay.
3849%
3850% o windows: Specifies a pointer to a XWindows structure.
3851%
3852% o name: the name of the color if found in the X Color Database is
3853% returned in this character string.
3854%
cristy6710d842011-10-20 23:23:00 +00003855% o exception: return any errors or warnings in this structure.
3856%
cristy3ed852e2009-09-05 21:47:34 +00003857*/
cristybcbda3f2011-09-03 13:01:22 +00003858MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003859 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003860{
3861 int
3862 x,
3863 y;
3864
cristy101ab702011-10-13 13:06:32 +00003865 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003866 pixel;
3867
3868 RectangleInfo
3869 crop_info;
3870
3871 Status
3872 status;
3873
3874 Window
3875 child,
3876 client_window,
3877 root_window,
3878 target_window;
3879
3880 XColor
3881 color;
3882
3883 XImage
3884 *ximage;
3885
3886 XWindowAttributes
3887 window_attributes;
3888
3889 /*
3890 Choose a pixel from the X server.
3891 */
3892 assert(display != (Display *) NULL);
3893 assert(name != (char *) NULL);
3894 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3895 *name='\0';
3896 target_window=XSelectWindow(display,&crop_info);
3897 if (target_window == (Window) NULL)
3898 return(MagickFalse);
3899 root_window=XRootWindow(display,XDefaultScreen(display));
3900 client_window=target_window;
3901 if (target_window != root_window)
3902 {
3903 unsigned int
3904 d;
3905
3906 /*
3907 Get client window.
3908 */
3909 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3910 if (status != False)
3911 {
3912 client_window=XClientWindow(display,target_window);
3913 target_window=client_window;
3914 }
3915 }
3916 /*
3917 Verify window is viewable.
3918 */
3919 status=XGetWindowAttributes(display,target_window,&window_attributes);
3920 if ((status == False) || (window_attributes.map_state != IsViewable))
3921 return(MagickFalse);
3922 /*
3923 Get window X image.
3924 */
3925 (void) XTranslateCoordinates(display,root_window,target_window,
3926 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3927 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3928 if (ximage == (XImage *) NULL)
3929 return(MagickFalse);
3930 color.pixel=XGetPixel(ximage,0,0);
3931 XDestroyImage(ximage);
3932 /*
3933 Match color against the color database.
3934 */
3935 (void) XQueryColor(display,window_attributes.colormap,&color);
cristye42f6582012-02-11 17:59:50 +00003936 pixel.red=(double) ScaleShortToQuantum(color.red);
3937 pixel.green=(double) ScaleShortToQuantum(color.green);
3938 pixel.blue=(double) ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003939 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003940 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003941 exception);
cristy3ed852e2009-09-05 21:47:34 +00003942 return(MagickTrue);
3943}
3944
3945/*
3946%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3947% %
3948% %
3949% %
3950+ X G e t W i n d o w I m a g e %
3951% %
3952% %
3953% %
3954%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3955%
3956% XGetWindowImage() reads an image from the target X window and returns it.
3957% XGetWindowImage() optionally descends the window hierarchy and overlays the
3958% target image with each child image in an optimized fashion. Any child
3959% window that have the same visual, colormap, and are contained by its parent
3960% are exempted.
3961%
3962% The format of the XGetWindowImage method is:
3963%
3964% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003965% const unsigned int borders,const unsigned int level,
3966% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003967%
3968% A description of each parameter follows:
3969%
3970% o display: Specifies a connection to an X server; returned from
3971% XOpenDisplay.
3972%
3973% o window: Specifies the window to obtain the image from.
3974%
3975% o borders: Specifies whether borders pixels are to be saved with
3976% the image.
3977%
3978% o level: Specifies an unsigned integer representing the level of
3979% decent in the window hierarchy. This value must be zero or one on
3980% the initial call to XGetWindowImage. A value of zero returns after
3981% one call. A value of one causes the function to descend the window
3982% hierarchy and overlay the target image with each subwindow image.
3983%
cristy6710d842011-10-20 23:23:00 +00003984% o exception: return any errors or warnings in this structure.
3985%
cristy3ed852e2009-09-05 21:47:34 +00003986*/
3987static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003988 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003989{
3990 typedef struct _ColormapInfo
3991 {
3992 Colormap
3993 colormap;
3994
3995 XColor
3996 *colors;
3997
3998 struct _ColormapInfo
3999 *next;
4000 } ColormapInfo;
4001
4002 typedef struct _WindowInfo
4003 {
4004 Window
4005 window,
4006 parent;
4007
4008 Visual
4009 *visual;
4010
4011 Colormap
4012 colormap;
4013
4014 XSegment
4015 bounds;
4016
4017 RectangleInfo
4018 crop_info;
4019 } WindowInfo;
4020
cristy3ed852e2009-09-05 21:47:34 +00004021 int
4022 display_height,
4023 display_width,
4024 id,
4025 x_offset,
4026 y_offset;
4027
cristy4c08aed2011-07-01 19:47:50 +00004028 Quantum
4029 index;
4030
cristy3ed852e2009-09-05 21:47:34 +00004031 RectangleInfo
4032 crop_info;
4033
cristy3ed852e2009-09-05 21:47:34 +00004034 register int
4035 i;
4036
4037 static ColormapInfo
4038 *colormap_info = (ColormapInfo *) NULL;
4039
4040 static int
4041 max_windows = 0,
4042 number_windows = 0;
4043
4044 static WindowInfo
4045 *window_info;
4046
4047 Status
4048 status;
4049
4050 Window
4051 child,
4052 root_window;
4053
4054 XWindowAttributes
4055 window_attributes;
4056
4057 /*
4058 Verify window is viewable.
4059 */
4060 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4061 assert(display != (Display *) NULL);
4062 status=XGetWindowAttributes(display,window,&window_attributes);
4063 if ((status == False) || (window_attributes.map_state != IsViewable))
4064 return((Image *) NULL);
4065 /*
4066 Cropping rectangle is relative to root window.
4067 */
4068 root_window=XRootWindow(display,XDefaultScreen(display));
4069 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4070 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004071 crop_info.x=(ssize_t) x_offset;
4072 crop_info.y=(ssize_t) y_offset;
4073 crop_info.width=(size_t) window_attributes.width;
4074 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004075 if (borders != MagickFalse)
4076 {
4077 /*
4078 Include border in image.
4079 */
cristybb503372010-05-27 20:51:26 +00004080 crop_info.x-=(ssize_t) window_attributes.border_width;
4081 crop_info.y-=(ssize_t) window_attributes.border_width;
4082 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4083 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004084 }
4085 /*
4086 Crop to root window.
4087 */
4088 if (crop_info.x < 0)
4089 {
4090 crop_info.width+=crop_info.x;
4091 crop_info.x=0;
4092 }
4093 if (crop_info.y < 0)
4094 {
4095 crop_info.height+=crop_info.y;
4096 crop_info.y=0;
4097 }
4098 display_width=XDisplayWidth(display,XDefaultScreen(display));
4099 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004100 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004101 display_height=XDisplayHeight(display,XDefaultScreen(display));
4102 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004103 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004104 /*
4105 Initialize window info attributes.
4106 */
4107 if (number_windows >= max_windows)
4108 {
4109 /*
4110 Allocate or resize window info buffer.
4111 */
4112 max_windows+=1024;
4113 if (window_info == (WindowInfo *) NULL)
4114 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4115 sizeof(*window_info));
4116 else
4117 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4118 max_windows,sizeof(*window_info));
4119 }
4120 if (window_info == (WindowInfo *) NULL)
4121 {
cristyc38fbf52013-11-03 13:55:54 +00004122 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed","...");
cristy3ed852e2009-09-05 21:47:34 +00004123 return((Image *) NULL);
4124 }
4125 id=number_windows++;
4126 window_info[id].window=window;
4127 window_info[id].visual=window_attributes.visual;
4128 window_info[id].colormap=window_attributes.colormap;
4129 window_info[id].bounds.x1=(short) crop_info.x;
4130 window_info[id].bounds.y1=(short) crop_info.y;
4131 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4132 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4133 crop_info.x-=x_offset;
4134 crop_info.y-=y_offset;
4135 window_info[id].crop_info=crop_info;
4136 if (level != 0)
4137 {
4138 unsigned int
4139 number_children;
4140
4141 Window
4142 *children;
4143
4144 /*
4145 Descend the window hierarchy.
4146 */
4147 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4148 &children,&number_children);
4149 for (i=0; i < id; i++)
4150 if ((window_info[i].window == window_info[id].parent) &&
4151 (window_info[i].visual == window_info[id].visual) &&
4152 (window_info[i].colormap == window_info[id].colormap))
4153 {
cristy64057b02013-01-11 00:09:58 +00004154 if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
4155 (window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
4156 (window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
4157 (window_info[id].bounds.y2 > window_info[i].bounds.y2))
cristy3ed852e2009-09-05 21:47:34 +00004158 {
4159 /*
4160 Eliminate windows not circumscribed by their parent.
4161 */
4162 number_windows--;
4163 break;
4164 }
4165 }
4166 if ((status == True) && (number_children != 0))
4167 {
4168 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004169 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4170 exception);
cristy3ed852e2009-09-05 21:47:34 +00004171 (void) XFree((void *) children);
4172 }
4173 }
4174 if (level <= 1)
4175 {
cristyc57f6942010-11-12 01:47:39 +00004176 CacheView
4177 *composite_view;
4178
cristy3ed852e2009-09-05 21:47:34 +00004179 ColormapInfo
4180 *next;
4181
cristy3ed852e2009-09-05 21:47:34 +00004182 Image
4183 *composite_image,
4184 *image;
4185
4186 int
4187 y;
4188
4189 MagickBooleanType
4190 import;
4191
4192 register int
4193 j,
4194 x;
4195
cristy4c08aed2011-07-01 19:47:50 +00004196 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004197 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004198
cristybb503372010-05-27 20:51:26 +00004199 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004200 pixel;
4201
4202 unsigned int
4203 number_colors;
4204
4205 XColor
4206 *colors;
4207
4208 XImage
4209 *ximage;
4210
4211 /*
4212 Get X image for each window in the list.
4213 */
4214 image=NewImageList();
4215 for (id=0; id < number_windows; id++)
4216 {
4217 /*
4218 Does target window intersect top level window?
4219 */
cristy088af952013-08-19 18:34:20 +00004220 import=((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
cristy3ed852e2009-09-05 21:47:34 +00004221 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4222 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4223 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4224 MagickTrue : MagickFalse;
4225 /*
4226 Is target window contained by another window with the same colormap?
4227 */
4228 for (j=0; j < id; j++)
4229 if ((window_info[id].visual == window_info[j].visual) &&
4230 (window_info[id].colormap == window_info[j].colormap))
4231 {
cristy64057b02013-01-11 00:09:58 +00004232 if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
4233 (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
4234 (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
4235 (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
cristy088af952013-08-19 18:34:20 +00004236 import=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00004237 }
cristy3ed852e2009-09-05 21:47:34 +00004238 if (import == MagickFalse)
4239 continue;
4240 /*
4241 Get X image.
4242 */
4243 ximage=XGetImage(display,window_info[id].window,(int)
4244 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4245 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4246 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4247 if (ximage == (XImage *) NULL)
4248 continue;
4249 /*
4250 Initialize window colormap.
4251 */
4252 number_colors=0;
4253 colors=(XColor *) NULL;
4254 if (window_info[id].colormap != (Colormap) NULL)
4255 {
4256 ColormapInfo
4257 *p;
4258
4259 /*
4260 Search colormap list for window colormap.
4261 */
4262 number_colors=(unsigned int) window_info[id].visual->map_entries;
4263 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4264 if (p->colormap == window_info[id].colormap)
4265 break;
4266 if (p == (ColormapInfo *) NULL)
4267 {
4268 /*
4269 Get the window colormap.
4270 */
4271 colors=(XColor *) AcquireQuantumMemory(number_colors,
4272 sizeof(*colors));
4273 if (colors == (XColor *) NULL)
4274 {
4275 XDestroyImage(ximage);
4276 return((Image *) NULL);
4277 }
4278 if ((window_info[id].visual->klass != DirectColor) &&
4279 (window_info[id].visual->klass != TrueColor))
4280 for (i=0; i < (int) number_colors; i++)
4281 {
cristybb503372010-05-27 20:51:26 +00004282 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004283 colors[i].pad='\0';
4284 }
4285 else
4286 {
cristybb503372010-05-27 20:51:26 +00004287 size_t
cristy3ed852e2009-09-05 21:47:34 +00004288 blue,
4289 blue_bit,
4290 green,
4291 green_bit,
4292 red,
4293 red_bit;
4294
4295 /*
4296 DirectColor or TrueColor visual.
4297 */
4298 red=0;
4299 green=0;
4300 blue=0;
4301 red_bit=window_info[id].visual->red_mask &
4302 (~(window_info[id].visual->red_mask)+1);
4303 green_bit=window_info[id].visual->green_mask &
4304 (~(window_info[id].visual->green_mask)+1);
4305 blue_bit=window_info[id].visual->blue_mask &
4306 (~(window_info[id].visual->blue_mask)+1);
4307 for (i=0; i < (int) number_colors; i++)
4308 {
cristy8891f9c2010-06-04 23:32:17 +00004309 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004310 colors[i].pad='\0';
4311 red+=red_bit;
4312 if (red > window_info[id].visual->red_mask)
4313 red=0;
4314 green+=green_bit;
4315 if (green > window_info[id].visual->green_mask)
4316 green=0;
4317 blue+=blue_bit;
4318 if (blue > window_info[id].visual->blue_mask)
4319 blue=0;
4320 }
4321 }
4322 (void) XQueryColors(display,window_info[id].colormap,colors,
4323 (int) number_colors);
4324 /*
4325 Append colormap to colormap list.
4326 */
cristy73bd4a52010-10-05 11:24:23 +00004327 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004328 if (p == (ColormapInfo *) NULL)
4329 return((Image *) NULL);
4330 p->colormap=window_info[id].colormap;
4331 p->colors=colors;
4332 p->next=colormap_info;
4333 colormap_info=p;
4334 }
4335 colors=p->colors;
4336 }
4337 /*
4338 Allocate image structure.
4339 */
cristy6710d842011-10-20 23:23:00 +00004340 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004341 if (composite_image == (Image *) NULL)
4342 {
4343 XDestroyImage(ximage);
4344 return((Image *) NULL);
4345 }
4346 /*
4347 Convert X image to MIFF format.
4348 */
4349 if ((window_info[id].visual->klass != TrueColor) &&
4350 (window_info[id].visual->klass != DirectColor))
4351 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004352 composite_image->columns=(size_t) ximage->width;
4353 composite_image->rows=(size_t) ximage->height;
cristy46ff2672012-12-14 15:32:26 +00004354 composite_view=AcquireAuthenticCacheView(composite_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00004355 switch (composite_image->storage_class)
4356 {
4357 case DirectClass:
4358 default:
4359 {
cristybb503372010-05-27 20:51:26 +00004360 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004361 color,
4362 index;
4363
cristybb503372010-05-27 20:51:26 +00004364 size_t
cristy3ed852e2009-09-05 21:47:34 +00004365 blue_mask,
4366 blue_shift,
4367 green_mask,
4368 green_shift,
4369 red_mask,
4370 red_shift;
4371
4372 /*
4373 Determine shift and mask for red, green, and blue.
4374 */
4375 red_mask=window_info[id].visual->red_mask;
4376 red_shift=0;
4377 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4378 {
4379 red_mask>>=1;
4380 red_shift++;
4381 }
4382 green_mask=window_info[id].visual->green_mask;
4383 green_shift=0;
4384 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4385 {
4386 green_mask>>=1;
4387 green_shift++;
4388 }
4389 blue_mask=window_info[id].visual->blue_mask;
4390 blue_shift=0;
4391 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4392 {
4393 blue_mask>>=1;
4394 blue_shift++;
4395 }
4396 /*
4397 Convert X image to DirectClass packets.
4398 */
4399 if ((number_colors != 0) &&
4400 (window_info[id].visual->klass == DirectColor))
4401 for (y=0; y < (int) composite_image->rows; y++)
4402 {
cristyc57f6942010-11-12 01:47:39 +00004403 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004404 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004405 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004406 break;
4407 for (x=0; x < (int) composite_image->columns; x++)
4408 {
4409 pixel=XGetPixel(ximage,x,y);
4410 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004411 SetPixelRed(composite_image,
4412 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004413 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004414 SetPixelGreen(composite_image,
4415 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004416 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004417 SetPixelBlue(composite_image,
4418 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004419 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004420 }
cristy0b1a7972011-10-22 22:17:02 +00004421 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4422 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004423 break;
4424 }
4425 else
4426 for (y=0; y < (int) composite_image->rows; y++)
4427 {
cristyc57f6942010-11-12 01:47:39 +00004428 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004429 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004430 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004431 break;
4432 for (x=0; x < (int) composite_image->columns; x++)
4433 {
4434 pixel=XGetPixel(ximage,x,y);
4435 color=(pixel >> red_shift) & red_mask;
4436 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004437 SetPixelRed(composite_image,
4438 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004439 color=(pixel >> green_shift) & green_mask;
4440 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004441 SetPixelGreen(composite_image,
4442 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004443 color=(pixel >> blue_shift) & blue_mask;
4444 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004445 SetPixelBlue(composite_image,
4446 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004447 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004448 }
cristy0b1a7972011-10-22 22:17:02 +00004449 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4450 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004451 break;
4452 }
4453 break;
4454 }
4455 case PseudoClass:
4456 {
4457 /*
4458 Create colormap.
4459 */
cristy0b1a7972011-10-22 22:17:02 +00004460 status=AcquireImageColormap(composite_image,number_colors,
4461 exception);
4462 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004463 {
4464 XDestroyImage(ximage);
4465 composite_image=DestroyImage(composite_image);
4466 return((Image *) NULL);
4467 }
4468 for (i=0; i < (int) composite_image->colors; i++)
4469 {
cristye42f6582012-02-11 17:59:50 +00004470 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004471 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004472 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004473 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004474 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004475 ScaleShortToQuantum(colors[i].blue);
4476 }
4477 /*
4478 Convert X image to PseudoClass packets.
4479 */
4480 for (y=0; y < (int) composite_image->rows; y++)
4481 {
cristyc57f6942010-11-12 01:47:39 +00004482 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4483 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004484 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004485 break;
cristy3ed852e2009-09-05 21:47:34 +00004486 for (x=0; x < (int) composite_image->columns; x++)
4487 {
cristy4c08aed2011-07-01 19:47:50 +00004488 index=(Quantum) XGetPixel(ximage,x,y);
4489 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004490 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004491 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004492 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004493 }
cristy0b1a7972011-10-22 22:17:02 +00004494 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4495 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004496 break;
4497 }
4498 break;
4499 }
4500 }
cristyc57f6942010-11-12 01:47:39 +00004501 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004502 XDestroyImage(ximage);
4503 if (image == (Image *) NULL)
4504 {
4505 image=composite_image;
4506 continue;
4507 }
4508 /*
4509 Composite any children in back-to-front order.
4510 */
4511 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4512 &x_offset,&y_offset,&child);
4513 x_offset-=(int) crop_info.x;
4514 if (x_offset < 0)
4515 x_offset=0;
4516 y_offset-=(int) crop_info.y;
4517 if (y_offset < 0)
4518 y_offset=0;
cristy39172402012-03-30 13:04:39 +00004519 (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00004520 (ssize_t) x_offset,(ssize_t) y_offset,exception);
cristy5f257b22012-03-07 00:27:29 +00004521 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004522 }
4523 /*
4524 Relinquish resources.
4525 */
4526 while (colormap_info != (ColormapInfo *) NULL)
4527 {
4528 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004529 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4530 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004531 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4532 colormap_info=next;
4533 }
4534 /*
4535 Relinquish resources and restore initial state.
4536 */
4537 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4538 max_windows=0;
4539 number_windows=0;
4540 colormap_info=(ColormapInfo *) NULL;
4541 return(image);
4542 }
4543 return((Image *) NULL);
4544}
4545
4546/*
4547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4548% %
4549% %
4550% %
4551% X G e t W i n d o w I n f o %
4552% %
4553% %
4554% %
4555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4556%
4557% XGetWindowInfo() initializes the XWindowInfo structure.
4558%
4559% The format of the XGetWindowInfo method is:
4560%
4561% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4562% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4563% XResourceInfo *resource_info,XWindowInfo *window)
4564% resource_info,window)
4565%
4566% A description of each parameter follows:
4567%
4568% o display: Specifies a connection to an X server; returned from
4569% XOpenDisplay.
4570%
4571% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4572% returned from XGetVisualInfo.
4573%
4574% o map_info: If map_type is specified, this structure is initialized
4575% with info from the Standard Colormap.
4576%
4577% o pixel: Specifies a pointer to a XPixelInfo structure.
4578%
4579% o font_info: Specifies a pointer to a XFontStruct structure.
4580%
4581% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4582%
4583*/
cristybcbda3f2011-09-03 13:01:22 +00004584MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004585 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4586 XResourceInfo *resource_info,XWindowInfo *window)
4587{
4588 /*
4589 Initialize window info.
4590 */
4591 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4592 assert(display != (Display *) NULL);
4593 assert(visual_info != (XVisualInfo *) NULL);
4594 assert(map_info != (XStandardColormap *) NULL);
4595 assert(pixel != (XPixelInfo *) NULL);
4596 assert(resource_info != (XResourceInfo *) NULL);
4597 assert(window != (XWindowInfo *) NULL);
4598 if (window->id != (Window) NULL)
4599 {
4600 if (window->cursor != (Cursor) NULL)
4601 (void) XFreeCursor(display,window->cursor);
4602 if (window->busy_cursor != (Cursor) NULL)
4603 (void) XFreeCursor(display,window->busy_cursor);
4604 if (window->highlight_stipple != (Pixmap) NULL)
4605 (void) XFreePixmap(display,window->highlight_stipple);
4606 if (window->shadow_stipple != (Pixmap) NULL)
4607 (void) XFreePixmap(display,window->shadow_stipple);
4608 if (window->name == (char *) NULL)
4609 window->name=AcquireString("");
4610 if (window->icon_name == (char *) NULL)
4611 window->icon_name=AcquireString("");
4612 }
4613 else
4614 {
4615 /*
4616 Initialize these attributes just once.
4617 */
4618 window->id=(Window) NULL;
4619 if (window->name == (char *) NULL)
4620 window->name=AcquireString("");
4621 if (window->icon_name == (char *) NULL)
4622 window->icon_name=AcquireString("");
4623 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4624 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4625 window->ximage=(XImage *) NULL;
4626 window->matte_image=(XImage *) NULL;
4627 window->pixmap=(Pixmap) NULL;
4628 window->matte_pixmap=(Pixmap) NULL;
4629 window->mapped=MagickFalse;
4630 window->stasis=MagickFalse;
4631 window->shared_memory=MagickTrue;
4632 window->segment_info=(void *) NULL;
4633#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4634 {
4635 XShmSegmentInfo
4636 *segment_info;
4637
4638 if (window->segment_info == (void *) NULL)
4639 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4640 segment_info=(XShmSegmentInfo *) window->segment_info;
4641 segment_info[0].shmid=(-1);
4642 segment_info[0].shmaddr=(char *) NULL;
4643 segment_info[1].shmid=(-1);
4644 segment_info[1].shmaddr=(char *) NULL;
4645 }
4646#endif
4647 }
4648 /*
4649 Initialize these attributes every time function is called.
4650 */
4651 window->screen=visual_info->screen;
4652 window->root=XRootWindow(display,visual_info->screen);
4653 window->visual=visual_info->visual;
4654 window->storage_class=(unsigned int) visual_info->klass;
4655 window->depth=(unsigned int) visual_info->depth;
4656 window->visual_info=visual_info;
4657 window->map_info=map_info;
4658 window->pixel_info=pixel;
4659 window->font_info=font_info;
4660 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4661 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4662 window->geometry=(char *) NULL;
4663 window->icon_geometry=(char *) NULL;
4664 if (resource_info->icon_geometry != (char *) NULL)
4665 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4666 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004667 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004668 window->width=1;
4669 window->height=1;
4670 window->min_width=1;
4671 window->min_height=1;
4672 window->width_inc=1;
4673 window->height_inc=1;
4674 window->border_width=resource_info->border_width;
4675 window->annotate_context=pixel->annotate_context;
4676 window->highlight_context=pixel->highlight_context;
4677 window->widget_context=pixel->widget_context;
4678 window->shadow_stipple=(Pixmap) NULL;
4679 window->highlight_stipple=(Pixmap) NULL;
4680 window->use_pixmap=MagickTrue;
4681 window->immutable=MagickFalse;
4682 window->shape=MagickFalse;
4683 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004684 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004685 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4686 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4687 window->attributes.background_pixel=pixel->background_color.pixel;
4688 window->attributes.background_pixmap=(Pixmap) NULL;
4689 window->attributes.bit_gravity=ForgetGravity;
4690 window->attributes.backing_store=WhenMapped;
4691 window->attributes.save_under=MagickTrue;
4692 window->attributes.border_pixel=pixel->border_color.pixel;
4693 window->attributes.colormap=map_info->colormap;
4694 window->attributes.cursor=window->cursor;
4695 window->attributes.do_not_propagate_mask=NoEventMask;
4696 window->attributes.event_mask=NoEventMask;
4697 window->attributes.override_redirect=MagickFalse;
4698 window->attributes.win_gravity=NorthWestGravity;
4699 window->orphan=MagickFalse;
4700}
4701
4702/*
4703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4704% %
4705% %
4706% %
4707% X H i g h l i g h t E l l i p s e %
4708% %
4709% %
4710% %
4711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4712%
4713% XHighlightEllipse() puts a border on the X server around a region defined by
4714% highlight_info.
4715%
4716% The format of the XHighlightEllipse method is:
4717%
4718% void XHighlightEllipse(Display *display,Window window,
4719% GC annotate_context,const RectangleInfo *highlight_info)
4720%
4721% A description of each parameter follows:
4722%
4723% o display: Specifies a connection to an X server; returned from
4724% XOpenDisplay.
4725%
4726% o window: Specifies a pointer to a Window structure.
4727%
4728% o annotate_context: Specifies a pointer to a GC structure.
4729%
4730% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4731% contains the extents of any highlighting rectangle.
4732%
4733*/
cristybcbda3f2011-09-03 13:01:22 +00004734MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004735 GC annotate_context,const RectangleInfo *highlight_info)
4736{
4737 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4738 assert(display != (Display *) NULL);
4739 assert(window != (Window) NULL);
4740 assert(annotate_context != (GC) NULL);
4741 assert(highlight_info != (RectangleInfo *) NULL);
4742 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4743 return;
4744 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4745 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4746 (unsigned int) highlight_info->height-1,0,360*64);
4747 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4748 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4749 (unsigned int) highlight_info->height-3,0,360*64);
4750}
4751
4752/*
4753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4754% %
4755% %
4756% %
4757% X H i g h l i g h t L i n e %
4758% %
4759% %
4760% %
4761%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4762%
4763% XHighlightLine() puts a border on the X server around a region defined by
4764% highlight_info.
4765%
4766% The format of the XHighlightLine method is:
4767%
4768% void XHighlightLine(Display *display,Window window,GC annotate_context,
4769% const XSegment *highlight_info)
4770%
4771% A description of each parameter follows:
4772%
4773% o display: Specifies a connection to an X server; returned from
4774% XOpenDisplay.
4775%
4776% o window: Specifies a pointer to a Window structure.
4777%
4778% o annotate_context: Specifies a pointer to a GC structure.
4779%
4780% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4781% contains the extents of any highlighting rectangle.
4782%
4783*/
cristybcbda3f2011-09-03 13:01:22 +00004784MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004785 GC annotate_context,const XSegment *highlight_info)
4786{
4787 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4788 assert(display != (Display *) NULL);
4789 assert(window != (Window) NULL);
4790 assert(annotate_context != (GC) NULL);
4791 assert(highlight_info != (XSegment *) NULL);
4792 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4793 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4794}
4795
4796/*
4797%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4798% %
4799% %
4800% %
4801% X H i g h l i g h t R e c t a n g l e %
4802% %
4803% %
4804% %
4805%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4806%
4807% XHighlightRectangle() puts a border on the X server around a region defined
4808% by highlight_info.
4809%
4810% The format of the XHighlightRectangle method is:
4811%
4812% void XHighlightRectangle(Display *display,Window window,
4813% GC annotate_context,const RectangleInfo *highlight_info)
4814%
4815% A description of each parameter follows:
4816%
4817% o display: Specifies a connection to an X server; returned from
4818% XOpenDisplay.
4819%
4820% o window: Specifies a pointer to a Window structure.
4821%
4822% o annotate_context: Specifies a pointer to a GC structure.
4823%
4824% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4825% contains the extents of any highlighting rectangle.
4826%
4827*/
cristybcbda3f2011-09-03 13:01:22 +00004828MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004829 GC annotate_context,const RectangleInfo *highlight_info)
4830{
4831 assert(display != (Display *) NULL);
4832 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4833 assert(window != (Window) NULL);
4834 assert(annotate_context != (GC) NULL);
4835 assert(highlight_info != (RectangleInfo *) NULL);
4836 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4837 return;
4838 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4839 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4840 (unsigned int) highlight_info->height-1);
4841 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4842 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4843 (unsigned int) highlight_info->height-3);
4844}
4845
4846/*
4847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4848% %
4849% %
4850% %
4851% X I m p o r t I m a g e %
4852% %
4853% %
4854% %
4855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4856%
4857% XImportImage() reads an image from an X window.
4858%
4859% The format of the XImportImage method is:
4860%
cristy6710d842011-10-20 23:23:00 +00004861% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4862% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004863%
4864% A description of each parameter follows:
4865%
4866% o image_info: the image info.
4867%
4868% o ximage_info: Specifies a pointer to an XImportInfo structure.
4869%
cristy6710d842011-10-20 23:23:00 +00004870% o exception: return any errors or warnings in this structure.
4871%
cristy3ed852e2009-09-05 21:47:34 +00004872*/
4873MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004874 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004875{
4876 Colormap
4877 *colormaps;
4878
4879 Display
4880 *display;
4881
4882 Image
4883 *image;
4884
4885 int
4886 number_colormaps,
4887 number_windows,
4888 x;
4889
4890 RectangleInfo
4891 crop_info;
4892
4893 Status
4894 status;
4895
4896 Window
4897 *children,
4898 client,
4899 prior_target,
4900 root,
4901 target;
4902
4903 XTextProperty
4904 window_name;
4905
4906 /*
4907 Open X server connection.
4908 */
4909 assert(image_info != (const ImageInfo *) NULL);
4910 assert(image_info->signature == MagickSignature);
4911 if (image_info->debug != MagickFalse)
4912 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4913 image_info->filename);
4914 assert(ximage_info != (XImportInfo *) NULL);
4915 display=XOpenDisplay(image_info->server_name);
4916 if (display == (Display *) NULL)
4917 {
cristyc38fbf52013-11-03 13:55:54 +00004918 ThrowXWindowException(XServerError,"UnableToOpenXServer",
cristy3ed852e2009-09-05 21:47:34 +00004919 XDisplayName(image_info->server_name));
4920 return((Image *) NULL);
4921 }
4922 /*
4923 Set our forgiving exception handler.
4924 */
4925 (void) XSetErrorHandler(XError);
4926 /*
4927 Select target window.
4928 */
4929 crop_info.x=0;
4930 crop_info.y=0;
4931 crop_info.width=0;
4932 crop_info.height=0;
4933 root=XRootWindow(display,XDefaultScreen(display));
4934 target=(Window) NULL;
4935 if ((image_info->filename != (char *) NULL) &&
4936 (*image_info->filename != '\0'))
4937 {
4938 if (LocaleCompare(image_info->filename,"root") == 0)
4939 target=root;
4940 else
4941 {
4942 /*
4943 Select window by ID or name.
4944 */
4945 if (isdigit((unsigned char) *image_info->filename) != 0)
4946 target=XWindowByID(display,root,(Window)
4947 strtol(image_info->filename,(char **) NULL,0));
4948 if (target == (Window) NULL)
4949 target=XWindowByName(display,root,image_info->filename);
4950 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004951 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
4952 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00004953 }
4954 }
4955 /*
4956 If target window is not defined, interactively select one.
4957 */
4958 prior_target=target;
4959 if (target == (Window) NULL)
4960 target=XSelectWindow(display,&crop_info);
4961 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004962 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00004963 image_info->filename);
4964 client=target; /* obsolete */
4965 if (target != root)
4966 {
4967 unsigned int
4968 d;
4969
4970 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4971 if (status != False)
4972 {
4973 for ( ; ; )
4974 {
4975 Window
4976 parent;
4977
4978 /*
4979 Find window manager frame.
4980 */
4981 status=XQueryTree(display,target,&root,&parent,&children,&d);
4982 if ((status != False) && (children != (Window *) NULL))
4983 (void) XFree((char *) children);
4984 if ((status == False) || (parent == (Window) NULL) ||
4985 (parent == root))
4986 break;
4987 target=parent;
4988 }
4989 /*
4990 Get client window.
4991 */
4992 client=XClientWindow(display,target);
4993 if (ximage_info->frame == MagickFalse)
4994 target=client;
4995 if ((ximage_info->frame == MagickFalse) &&
4996 (prior_target != MagickFalse))
4997 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00004998 }
4999 }
5000 if (ximage_info->screen)
5001 {
5002 int
5003 y;
5004
5005 Window
5006 child;
5007
5008 XWindowAttributes
5009 window_attributes;
5010
5011 /*
5012 Obtain window image directly from screen.
5013 */
5014 status=XGetWindowAttributes(display,target,&window_attributes);
5015 if (status == False)
5016 {
cristyc38fbf52013-11-03 13:55:54 +00005017 ThrowXWindowException(XServerError,"UnableToReadXWindowAttributes",
5018 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00005019 (void) XCloseDisplay(display);
5020 return((Image *) NULL);
5021 }
5022 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005023 crop_info.x=(ssize_t) x;
5024 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005025 crop_info.width=(size_t) window_attributes.width;
5026 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005027 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005028 {
5029 /*
5030 Include border in image.
5031 */
5032 crop_info.x-=window_attributes.border_width;
5033 crop_info.y-=window_attributes.border_width;
5034 crop_info.width+=window_attributes.border_width << 1;
5035 crop_info.height+=window_attributes.border_width << 1;
5036 }
5037 target=root;
5038 }
5039 /*
5040 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5041 */
5042 number_windows=0;
5043 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5044 if ((status == True) && (number_windows > 0))
5045 {
5046 ximage_info->descend=MagickTrue;
5047 (void) XFree ((char *) children);
5048 }
5049 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5050 if (number_colormaps > 0)
5051 {
5052 if (number_colormaps > 1)
5053 ximage_info->descend=MagickTrue;
5054 (void) XFree((char *) colormaps);
5055 }
5056 /*
5057 Alert the user not to alter the screen.
5058 */
5059 if (ximage_info->silent == MagickFalse)
5060 (void) XBell(display,0);
5061 /*
5062 Get image by window id.
5063 */
5064 (void) XGrabServer(display);
5065 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005066 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005067 (void) XUngrabServer(display);
5068 if (image == (Image *) NULL)
cristyc38fbf52013-11-03 13:55:54 +00005069 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00005070 image_info->filename)
5071 else
5072 {
5073 (void) CopyMagickString(image->filename,image_info->filename,
5074 MaxTextExtent);
5075 if ((crop_info.width != 0) && (crop_info.height != 0))
5076 {
5077 Image
5078 *clone_image,
5079 *crop_image;
5080
5081 /*
5082 Crop image as defined by the cropping rectangle.
5083 */
cristy6710d842011-10-20 23:23:00 +00005084 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005085 if (clone_image != (Image *) NULL)
5086 {
cristy6710d842011-10-20 23:23:00 +00005087 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005088 if (crop_image != (Image *) NULL)
5089 {
5090 image=DestroyImage(image);
5091 image=crop_image;
5092 }
5093 }
5094 }
5095 status=XGetWMName(display,target,&window_name);
5096 if (status == True)
5097 {
5098 if ((image_info->filename != (char *) NULL) &&
5099 (*image_info->filename == '\0'))
5100 (void) CopyMagickString(image->filename,(char *) window_name.value,
5101 (size_t) window_name.nitems+1);
5102 (void) XFree((void *) window_name.value);
5103 }
5104 }
5105 if (ximage_info->silent == MagickFalse)
5106 {
5107 /*
5108 Alert the user we're done.
5109 */
5110 (void) XBell(display,0);
5111 (void) XBell(display,0);
5112 }
5113 (void) XCloseDisplay(display);
5114 return(image);
5115}
5116
5117/*
5118%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5119% %
5120% %
5121% %
5122% X I n i t i a l i z e W i n d o w s %
5123% %
5124% %
5125% %
5126%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5127%
5128% XInitializeWindows() initializes the XWindows structure.
5129%
5130% The format of the XInitializeWindows method is:
5131%
5132% XWindows *XInitializeWindows(Display *display,
5133% XResourceInfo *resource_info)
5134%
5135% A description of each parameter follows:
5136%
5137% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5138%
5139% o display: Specifies a connection to an X server; returned from
5140% XOpenDisplay.
5141%
5142% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5143%
5144*/
cristybcbda3f2011-09-03 13:01:22 +00005145MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005146 XResourceInfo *resource_info)
5147{
5148 Window
5149 root_window;
5150
5151 XWindows
5152 *windows;
5153
5154 /*
5155 Allocate windows structure.
5156 */
cristy73bd4a52010-10-05 11:24:23 +00005157 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005158 if (windows == (XWindows *) NULL)
5159 {
5160 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5161 "...");
5162 return((XWindows *) NULL);
5163 }
5164 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5165 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5166 sizeof(*windows->pixel_info));
5167 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5168 sizeof(*windows->icon_pixel));
5169 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5170 sizeof(*windows->icon_resources));
5171 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5172 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5173 (windows->icon_resources == (XResourceInfo *) NULL))
5174 {
5175 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5176 "...");
5177 return((XWindows *) NULL);
5178 }
5179 /*
5180 Initialize windows structure.
5181 */
5182 windows->display=display;
5183 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5184 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5185 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5186 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5187 windows->im_remote_command=
5188 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5189 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5190 windows->im_update_colormap=
5191 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5192 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5193 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5194 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5195 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5196 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005197#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005198 (void) XSynchronize(display,IsWindows95());
5199#endif
5200 if (IsEventLogging())
5201 {
5202 (void) XSynchronize(display,MagickTrue);
5203 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005204 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005205 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5206 (void) LogMagickEvent(X11Event,GetMagickModule(),
5207 " Window Manager: 0x%lx",windows->wm_protocols);
5208 (void) LogMagickEvent(X11Event,GetMagickModule(),
5209 " delete window: 0x%lx",windows->wm_delete_window);
5210 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5211 windows->wm_take_focus);
5212 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5213 windows->im_protocols);
5214 (void) LogMagickEvent(X11Event,GetMagickModule(),
5215 " remote command: 0x%lx",windows->im_remote_command);
5216 (void) LogMagickEvent(X11Event,GetMagickModule(),
5217 " update widget: 0x%lx",windows->im_update_widget);
5218 (void) LogMagickEvent(X11Event,GetMagickModule(),
5219 " update colormap: 0x%lx",windows->im_update_colormap);
5220 (void) LogMagickEvent(X11Event,GetMagickModule(),
5221 " former image: 0x%lx",windows->im_former_image);
5222 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5223 windows->im_next_image);
5224 (void) LogMagickEvent(X11Event,GetMagickModule(),
5225 " retain colors: 0x%lx",windows->im_retain_colors);
5226 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5227 windows->im_exit);
5228 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5229 windows->dnd_protocols);
5230 }
5231 /*
5232 Allocate standard colormap.
5233 */
5234 windows->map_info=XAllocStandardColormap();
5235 windows->icon_map=XAllocStandardColormap();
5236 if ((windows->map_info == (XStandardColormap *) NULL) ||
5237 (windows->icon_map == (XStandardColormap *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005238 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5239 "...");
cristy3ed852e2009-09-05 21:47:34 +00005240 windows->map_info->colormap=(Colormap) NULL;
5241 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005242 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005243 windows->pixel_info->annotate_context=(GC) NULL;
5244 windows->pixel_info->highlight_context=(GC) NULL;
5245 windows->pixel_info->widget_context=(GC) NULL;
5246 windows->font_info=(XFontStruct *) NULL;
5247 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005248 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005249 /*
5250 Allocate visual.
5251 */
5252 *windows->icon_resources=(*resource_info);
5253 windows->icon_resources->visual_type=(char *) "default";
5254 windows->icon_resources->colormap=SharedColormap;
5255 windows->visual_info=
5256 XBestVisualInfo(display,windows->map_info,resource_info);
5257 windows->icon_visual=
5258 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5259 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5260 (windows->icon_visual == (XVisualInfo *) NULL))
5261 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5262 resource_info->visual_type);
5263 if (IsEventLogging())
5264 {
5265 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5266 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5267 windows->visual_info->visualid);
5268 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5269 XVisualClassName(windows->visual_info->klass));
5270 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5271 windows->visual_info->depth);
5272 (void) LogMagickEvent(X11Event,GetMagickModule(),
5273 " size of colormap: %d entries",windows->visual_info->colormap_size);
5274 (void) LogMagickEvent(X11Event,GetMagickModule(),
5275 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5276 windows->visual_info->red_mask,windows->visual_info->green_mask,
5277 windows->visual_info->blue_mask);
5278 (void) LogMagickEvent(X11Event,GetMagickModule(),
5279 " significant bits in color: %d bits",
5280 windows->visual_info->bits_per_rgb);
5281 }
5282 /*
5283 Allocate class and manager hints.
5284 */
5285 windows->class_hints=XAllocClassHint();
5286 windows->manager_hints=XAllocWMHints();
5287 if ((windows->class_hints == (XClassHint *) NULL) ||
5288 (windows->manager_hints == (XWMHints *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005289 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5290 "...");
cristy3ed852e2009-09-05 21:47:34 +00005291 /*
5292 Determine group leader if we have one.
5293 */
5294 root_window=XRootWindow(display,windows->visual_info->screen);
5295 windows->group_leader.id=(Window) NULL;
5296 if (resource_info->window_group != (char *) NULL)
5297 {
5298 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5299 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5300 strtol((char *) resource_info->window_group,(char **) NULL,0));
5301 if (windows->group_leader.id == (Window) NULL)
5302 windows->group_leader.id=
5303 XWindowByName(display,root_window,resource_info->window_group);
5304 }
5305 return(windows);
5306}
5307
5308/*
5309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5310% %
5311% %
5312% %
5313% X M a k e C u r s o r %
5314% %
5315% %
5316% %
5317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5318%
5319% XMakeCursor() creates a crosshairs X11 cursor.
5320%
5321% The format of the XMakeCursor method is:
5322%
5323% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5324% char *background_color,char *foreground_color)
5325%
5326% A description of each parameter follows:
5327%
5328% o display: Specifies a connection to an X server; returned from
5329% XOpenDisplay.
5330%
5331% o window: Specifies the ID of the window for which the cursor is
5332% assigned.
5333%
5334% o colormap: Specifies the ID of the colormap from which the background
5335% and foreground color will be retrieved.
5336%
5337% o background_color: Specifies the color to use for the cursor background.
5338%
5339% o foreground_color: Specifies the color to use for the cursor foreground.
5340%
5341*/
cristybcbda3f2011-09-03 13:01:22 +00005342MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005343 Colormap colormap,char *background_color,char *foreground_color)
5344{
5345#define scope_height 17
5346#define scope_x_hot 8
5347#define scope_y_hot 8
5348#define scope_width 17
5349
5350 static const unsigned char
5351 scope_bits[] =
5352 {
5353 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5354 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5355 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5356 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5357 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5358 },
5359 scope_mask_bits[] =
5360 {
5361 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5362 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5363 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5364 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5365 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5366 };
5367
5368 Cursor
5369 cursor;
5370
5371 Pixmap
5372 mask,
5373 source;
5374
5375 XColor
5376 background,
5377 foreground;
5378
5379 assert(display != (Display *) NULL);
5380 assert(window != (Window) NULL);
5381 assert(colormap != (Colormap) NULL);
5382 assert(background_color != (char *) NULL);
5383 assert(foreground_color != (char *) NULL);
5384 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5385 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5386 scope_height);
5387 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5388 scope_width,scope_height);
5389 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5390 {
cristyc38fbf52013-11-03 13:55:54 +00005391 ThrowXWindowException(XServerError,"UnableToCreatePixmap","...");
cristy3ed852e2009-09-05 21:47:34 +00005392 return((Cursor) NULL);
5393 }
5394 (void) XParseColor(display,colormap,background_color,&background);
5395 (void) XParseColor(display,colormap,foreground_color,&foreground);
5396 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5397 scope_x_hot,scope_y_hot);
5398 (void) XFreePixmap(display,source);
5399 (void) XFreePixmap(display,mask);
5400 return(cursor);
5401}
5402
5403/*
5404%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5405% %
5406% %
5407% %
5408% X M a k e I m a g e %
5409% %
5410% %
5411% %
5412%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5413%
5414% XMakeImage() creates an X11 image. If the image size differs from the X11
5415% image size, the image is first resized.
5416%
5417% The format of the XMakeImage method is:
5418%
5419% MagickBooleanType XMakeImage(Display *display,
5420% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005421% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005422%
5423% A description of each parameter follows:
5424%
5425% o display: Specifies a connection to an X server; returned from
5426% XOpenDisplay.
5427%
5428% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5429%
5430% o window: Specifies a pointer to a XWindowInfo structure.
5431%
5432% o image: the image.
5433%
5434% o width: Specifies the width in pixels of the rectangular area to
5435% display.
5436%
5437% o height: Specifies the height in pixels of the rectangular area to
5438% display.
5439%
cristy051718b2011-08-28 22:49:25 +00005440% o exception: return any errors or warnings in this structure.
5441%
cristy3ed852e2009-09-05 21:47:34 +00005442*/
cristybcbda3f2011-09-03 13:01:22 +00005443MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005444 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005445 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005446{
5447#define CheckOverflowException(length,width,height) \
5448 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5449
5450 int
5451 depth,
5452 format;
5453
5454 size_t
5455 length;
5456
5457 XImage
5458 *matte_image,
5459 *ximage;
5460
5461 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5462 assert(display != (Display *) NULL);
5463 assert(resource_info != (XResourceInfo *) NULL);
5464 assert(window != (XWindowInfo *) NULL);
5465 assert(width != 0);
5466 assert(height != 0);
5467 if ((window->width == 0) || (window->height == 0))
5468 return(MagickFalse);
5469 /*
5470 Apply user transforms to the image.
5471 */
5472 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5473 (void) XFlush(display);
5474 depth=(int) window->depth;
5475 if (window->destroy)
5476 window->image=DestroyImage(window->image);
5477 window->image=image;
5478 window->destroy=MagickFalse;
5479 if (window->image != (Image *) NULL)
5480 {
5481 if (window->crop_geometry != (char *) NULL)
5482 {
5483 Image
5484 *crop_image;
5485
5486 RectangleInfo
5487 crop_info;
5488
5489 /*
5490 Crop image.
5491 */
5492 window->image->page.x=0;
5493 window->image->page.y=0;
5494 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005495 &crop_info,exception);
5496 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005497 if (crop_image != (Image *) NULL)
5498 {
5499 if (window->image != image)
5500 window->image=DestroyImage(window->image);
5501 window->image=crop_image;
5502 window->destroy=MagickTrue;
5503 }
5504 }
5505 if ((width != (unsigned int) window->image->columns) ||
5506 (height != (unsigned int) window->image->rows))
5507 {
5508 Image
5509 *resize_image;
5510
5511 /*
5512 Resize image.
5513 */
5514 resize_image=NewImageList();
cristy865489b2013-10-12 01:03:29 +00005515 if ((window->pixel_info->colors == 0) &&
5516 (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5517 (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5518 resize_image=ResizeImage(window->image,width,height,
5519 image->filter,exception);
cristy3ed852e2009-09-05 21:47:34 +00005520 else
cristy865489b2013-10-12 01:03:29 +00005521 {
5522 if (window->image->storage_class == PseudoClass)
5523 resize_image=SampleImage(window->image,width,height,
5524 exception);
5525 else
5526 resize_image=ThumbnailImage(window->image,width,height,
5527 exception);
5528 }
cristy3ed852e2009-09-05 21:47:34 +00005529 if (resize_image != (Image *) NULL)
5530 {
5531 if (window->image != image)
5532 window->image=DestroyImage(window->image);
5533 window->image=resize_image;
5534 window->destroy=MagickTrue;
5535 }
5536 }
5537 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005538 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005539 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005540 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005541 }
5542 /*
5543 Create X image.
5544 */
5545 ximage=(XImage *) NULL;
5546 format=(depth == 1) ? XYBitmap : ZPixmap;
5547#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5548 if (window->shared_memory != MagickFalse)
5549 {
5550 XShmSegmentInfo
5551 *segment_info;
5552
5553 segment_info=(XShmSegmentInfo *) window->segment_info;
5554 segment_info[1].shmid=(-1);
5555 segment_info[1].shmaddr=(char *) NULL;
5556 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5557 (char *) NULL,&segment_info[1],width,height);
5558 if (ximage == (XImage *) NULL)
5559 window->shared_memory=MagickFalse;
5560 length=(size_t) ximage->bytes_per_line*ximage->height;
5561 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5562 window->shared_memory=MagickFalse;
5563 if (window->shared_memory != MagickFalse)
5564 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5565 if (window->shared_memory != MagickFalse)
5566 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5567 if (segment_info[1].shmid < 0)
5568 window->shared_memory=MagickFalse;
5569 if (window->shared_memory != MagickFalse)
5570 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5571 else
5572 {
5573 if (ximage != (XImage *) NULL)
5574 XDestroyImage(ximage);
5575 ximage=(XImage *) NULL;
5576 if (segment_info[1].shmaddr)
5577 {
5578 (void) shmdt(segment_info[1].shmaddr);
5579 segment_info[1].shmaddr=(char *) NULL;
5580 }
5581 if (segment_info[1].shmid >= 0)
5582 {
5583 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5584 segment_info[1].shmid=(-1);
5585 }
5586 }
5587 }
5588#endif
5589 /*
5590 Allocate X image pixel data.
5591 */
5592#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5593 if (window->shared_memory)
5594 {
5595 Status
5596 status;
5597
5598 XShmSegmentInfo
5599 *segment_info;
5600
5601 (void) XSync(display,MagickFalse);
5602 xerror_alert=MagickFalse;
5603 segment_info=(XShmSegmentInfo *) window->segment_info;
5604 ximage->data=segment_info[1].shmaddr;
5605 segment_info[1].readOnly=MagickFalse;
5606 status=XShmAttach(display,&segment_info[1]);
5607 if (status != False)
5608 (void) XSync(display,MagickFalse);
5609 if ((status == False) || (xerror_alert != MagickFalse))
5610 {
5611 window->shared_memory=MagickFalse;
5612 if (status != False)
5613 XShmDetach(display,&segment_info[1]);
5614 if (ximage != (XImage *) NULL)
5615 {
5616 ximage->data=NULL;
5617 XDestroyImage(ximage);
5618 ximage=(XImage *) NULL;
5619 }
5620 if (segment_info[1].shmid >= 0)
5621 {
5622 if (segment_info[1].shmaddr != NULL)
5623 (void) shmdt(segment_info[1].shmaddr);
5624 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5625 segment_info[1].shmid=(-1);
5626 segment_info[1].shmaddr=(char *) NULL;
5627 }
5628 }
5629 }
5630#endif
5631 if (window->shared_memory == MagickFalse)
5632 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5633 (char *) NULL,width,height,XBitmapPad(display),0);
5634 if (ximage == (XImage *) NULL)
5635 {
5636 /*
5637 Unable to create X image.
5638 */
5639 (void) XCheckDefineCursor(display,window->id,window->cursor);
5640 return(MagickFalse);
5641 }
5642 length=(size_t) ximage->bytes_per_line*ximage->height;
5643 if (IsEventLogging())
5644 {
5645 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5646 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5647 ximage->width,ximage->height);
5648 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5649 ximage->format);
5650 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5651 ximage->byte_order);
5652 (void) LogMagickEvent(X11Event,GetMagickModule(),
5653 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5654 ximage->bitmap_bit_order,ximage->bitmap_pad);
5655 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5656 ximage->depth);
5657 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5658 ximage->bytes_per_line);
5659 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5660 ximage->bits_per_pixel);
5661 (void) LogMagickEvent(X11Event,GetMagickModule(),
5662 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5663 ximage->green_mask,ximage->blue_mask);
5664 }
5665 if (window->shared_memory == MagickFalse)
5666 {
5667 if (ximage->format != XYBitmap)
cristy9aecad62013-04-18 10:37:47 +00005668 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5669 ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005670 else
cristy9aecad62013-04-18 10:37:47 +00005671 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5672 ximage->depth*ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005673 }
5674 if (ximage->data == (char *) NULL)
5675 {
5676 /*
5677 Unable to allocate pixel data.
5678 */
5679 XDestroyImage(ximage);
5680 ximage=(XImage *) NULL;
5681 (void) XCheckDefineCursor(display,window->id,window->cursor);
5682 return(MagickFalse);
5683 }
5684 if (window->ximage != (XImage *) NULL)
5685 {
5686 /*
5687 Destroy previous X image.
5688 */
5689 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5690#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5691 if (window->segment_info != (XShmSegmentInfo *) NULL)
5692 {
5693 XShmSegmentInfo
5694 *segment_info;
5695
5696 segment_info=(XShmSegmentInfo *) window->segment_info;
5697 if (segment_info[0].shmid >= 0)
5698 {
5699 (void) XSync(display,MagickFalse);
5700 (void) XShmDetach(display,&segment_info[0]);
5701 (void) XSync(display,MagickFalse);
5702 if (segment_info[0].shmaddr != (char *) NULL)
5703 (void) shmdt(segment_info[0].shmaddr);
5704 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5705 segment_info[0].shmid=(-1);
5706 segment_info[0].shmaddr=(char *) NULL;
5707 window->ximage->data=(char *) NULL;
5708 }
5709 }
5710#endif
5711 if (window->ximage->data != (char *) NULL)
5712 free(window->ximage->data);
5713 window->ximage->data=(char *) NULL;
5714 XDestroyImage(window->ximage);
5715 window->ximage=(XImage *) NULL;
5716 }
5717#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5718 if (window->segment_info != (XShmSegmentInfo *) NULL)
5719 {
5720 XShmSegmentInfo
5721 *segment_info;
5722
5723 segment_info=(XShmSegmentInfo *) window->segment_info;
5724 segment_info[0]=segment_info[1];
5725 }
5726#endif
5727 window->ximage=ximage;
5728 matte_image=(XImage *) NULL;
5729 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
cristy8a46d822012-08-28 23:32:39 +00005730 if ((window->image->alpha_trait == BlendPixelTrait) &&
cristyc57f6942010-11-12 01:47:39 +00005731 ((int) width <= XDisplayWidth(display,window->screen)) &&
5732 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005733 {
5734 /*
5735 Create matte image.
5736 */
5737 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5738 (char *) NULL,width,height,XBitmapPad(display),0);
5739 if (IsEventLogging())
5740 {
5741 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5742 (void) LogMagickEvent(X11Event,GetMagickModule(),
5743 " width, height: %dx%d",matte_image->width,matte_image->height);
5744 }
5745 if (matte_image != (XImage *) NULL)
5746 {
5747 /*
5748 Allocate matte image pixel data.
5749 */
cristy9aecad62013-04-18 10:37:47 +00005750 matte_image->data=(char *) malloc((size_t)
5751 matte_image->bytes_per_line*matte_image->depth*
5752 matte_image->height);
cristy3ed852e2009-09-05 21:47:34 +00005753 if (matte_image->data == (char *) NULL)
5754 {
5755 XDestroyImage(matte_image);
5756 matte_image=(XImage *) NULL;
5757 }
5758 }
5759 }
5760 if (window->matte_image != (XImage *) NULL)
5761 {
5762 /*
5763 Free matte image.
5764 */
5765 if (window->matte_image->data != (char *) NULL)
5766 free(window->matte_image->data);
5767 window->matte_image->data=(char *) NULL;
5768 XDestroyImage(window->matte_image);
5769 window->matte_image=(XImage *) NULL;
5770 }
5771 window->matte_image=matte_image;
5772 if (window->matte_pixmap != (Pixmap) NULL)
5773 {
5774 (void) XFreePixmap(display,window->matte_pixmap);
5775 window->matte_pixmap=(Pixmap) NULL;
5776#if defined(MAGICKCORE_HAVE_SHAPE)
5777 if (window->shape != MagickFalse)
5778 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5779#endif
5780 }
5781 window->stasis=MagickFalse;
5782 /*
5783 Convert pixels to X image data.
5784 */
5785 if (window->image != (Image *) NULL)
5786 {
5787 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5788 (ximage->bitmap_bit_order == LSBFirst)))
5789 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005790 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005791 else
5792 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005793 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005794 }
5795 if (window->matte_image != (XImage *) NULL)
5796 {
5797 /*
5798 Create matte pixmap.
5799 */
5800 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5801 if (window->matte_pixmap != (Pixmap) NULL)
5802 {
5803 GC
5804 graphics_context;
5805
5806 XGCValues
5807 context_values;
5808
5809 /*
5810 Copy matte image to matte pixmap.
5811 */
cristy4c08aed2011-07-01 19:47:50 +00005812 context_values.background=0;
5813 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005814 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005815 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005816 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5817 window->matte_image,0,0,0,0,width,height);
5818 (void) XFreeGC(display,graphics_context);
5819#if defined(MAGICKCORE_HAVE_SHAPE)
5820 if (window->shape != MagickFalse)
5821 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5822 window->matte_pixmap,ShapeSet);
5823#endif
5824 }
5825 }
5826 (void) XMakePixmap(display,resource_info,window);
5827 /*
5828 Restore cursor.
5829 */
5830 (void) XCheckDefineCursor(display,window->id,window->cursor);
5831 return(MagickTrue);
5832}
5833
5834/*
5835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5836% %
5837% %
5838% %
5839+ X M a k e I m a g e L S B F i r s t %
5840% %
5841% %
5842% %
5843%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5844%
5845% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5846% pixels are copied in least-significant bit and byte first order. The
5847% server's scanline pad is respected. Rather than using one or two general
5848% cases, many special cases are found here to help speed up the image
5849% conversion.
5850%
5851% The format of the XMakeImageLSBFirst method is:
5852%
cristye941a752011-10-15 01:52:48 +00005853% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5854% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005855%
5856% A description of each parameter follows:
5857%
5858% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5859%
5860% o window: Specifies a pointer to a XWindowInfo structure.
5861%
5862% o image: the image.
5863%
5864% o ximage: Specifies a pointer to a XImage structure; returned from
5865% XCreateImage.
5866%
5867% o matte_image: Specifies a pointer to a XImage structure; returned from
5868% XCreateImage.
5869%
cristye941a752011-10-15 01:52:48 +00005870% o exception: return any errors or warnings in this structure.
5871%
cristy3ed852e2009-09-05 21:47:34 +00005872*/
5873static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005874 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5875 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005876{
cristyc57f6942010-11-12 01:47:39 +00005877 CacheView
5878 *canvas_view;
5879
cristy3ed852e2009-09-05 21:47:34 +00005880 Image
5881 *canvas;
5882
5883 int
5884 y;
5885
cristy4c08aed2011-07-01 19:47:50 +00005886 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005887 *p;
5888
5889 register int
5890 x;
5891
5892 register unsigned char
5893 *q;
5894
5895 unsigned char
5896 bit,
5897 byte;
5898
5899 unsigned int
5900 scanline_pad;
5901
cristyf2faecf2010-05-28 19:19:36 +00005902 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005903 pixel,
5904 *pixels;
5905
5906 XStandardColormap
5907 *map_info;
5908
5909 assert(resource_info != (XResourceInfo *) NULL);
5910 assert(window != (XWindowInfo *) NULL);
5911 assert(image != (Image *) NULL);
5912 if (image->debug != MagickFalse)
5913 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5914 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005915 if ((window->immutable == MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00005916 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00005917 {
5918 char
5919 size[MaxTextExtent];
5920
5921 Image
5922 *pattern;
5923
5924 ImageInfo
5925 *image_info;
5926
5927 image_info=AcquireImageInfo();
5928 (void) CopyMagickString(image_info->filename,
5929 resource_info->image_info->texture != (char *) NULL ?
5930 resource_info->image_info->texture : "pattern:checkerboard",
5931 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005932 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005933 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005934 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005935 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005936 image_info=DestroyImageInfo(image_info);
5937 if (pattern != (Image *) NULL)
5938 {
cristy6710d842011-10-20 23:23:00 +00005939 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005940 if (canvas != (Image *) NULL)
cristy39172402012-03-30 13:04:39 +00005941 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00005942 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00005943 pattern=DestroyImage(pattern);
5944 }
5945 }
5946 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5947 ximage->bits_per_pixel) >> 3));
5948 map_info=window->map_info;
5949 pixels=window->pixel_info->pixels;
5950 q=(unsigned char *) ximage->data;
5951 x=0;
cristy46ff2672012-12-14 15:32:26 +00005952 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00005953 if (ximage->format == XYBitmap)
5954 {
5955 register unsigned short
5956 polarity;
5957
5958 unsigned char
5959 background,
5960 foreground;
5961
5962 /*
5963 Convert canvas to big-endian bitmap.
5964 */
5965 background=(unsigned char)
5966 (XPixelIntensity(&window->pixel_info->foreground_color) <
5967 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5968 foreground=(unsigned char)
5969 (XPixelIntensity(&window->pixel_info->background_color) <
5970 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005971 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00005972 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00005973 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005974 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5975 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005976 for (y=0; y < (int) canvas->rows; y++)
5977 {
cristyc57f6942010-11-12 01:47:39 +00005978 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005979 exception);
cristy4c08aed2011-07-01 19:47:50 +00005980 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005981 break;
cristy3ed852e2009-09-05 21:47:34 +00005982 bit=0;
5983 byte=0;
5984 for (x=0; x < (int) canvas->columns; x++)
5985 {
5986 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005987 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005988 byte|=foreground;
5989 else
5990 byte|=background;
5991 bit++;
5992 if (bit == 8)
5993 {
5994 *q++=byte;
5995 bit=0;
5996 byte=0;
5997 }
cristyed231572011-07-14 02:18:59 +00005998 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005999 }
6000 if (bit != 0)
6001 *q=byte >> (8-bit);
6002 q+=scanline_pad;
6003 }
6004 }
6005 else
6006 if (window->pixel_info->colors != 0)
6007 switch (ximage->bits_per_pixel)
6008 {
6009 case 2:
6010 {
6011 register unsigned int
6012 nibble;
6013
6014 /*
6015 Convert to 2 bit color-mapped X canvas.
6016 */
6017 for (y=0; y < (int) canvas->rows; y++)
6018 {
cristyc57f6942010-11-12 01:47:39 +00006019 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006020 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006021 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006022 break;
cristy3ed852e2009-09-05 21:47:34 +00006023 nibble=0;
6024 for (x=0; x < (int) canvas->columns; x++)
6025 {
cristy4c08aed2011-07-01 19:47:50 +00006026 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006027 switch (nibble)
6028 {
6029 case 0:
6030 {
6031 *q=(unsigned char) pixel;
6032 nibble++;
6033 break;
6034 }
6035 case 1:
6036 {
6037 *q|=(unsigned char) (pixel << 2);
6038 nibble++;
6039 break;
6040 }
6041 case 2:
6042 {
6043 *q|=(unsigned char) (pixel << 4);
6044 nibble++;
6045 break;
6046 }
6047 case 3:
6048 {
6049 *q|=(unsigned char) (pixel << 6);
6050 q++;
6051 nibble=0;
6052 break;
6053 }
6054 }
cristyed231572011-07-14 02:18:59 +00006055 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006056 }
6057 q+=scanline_pad;
6058 }
6059 break;
6060 }
6061 case 4:
6062 {
6063 register unsigned int
6064 nibble;
6065
6066 /*
6067 Convert to 4 bit color-mapped X canvas.
6068 */
6069 for (y=0; y < (int) canvas->rows; y++)
6070 {
cristyc57f6942010-11-12 01:47:39 +00006071 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006072 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006073 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006074 break;
cristy3ed852e2009-09-05 21:47:34 +00006075 nibble=0;
6076 for (x=0; x < (int) canvas->columns; x++)
6077 {
cristy4c08aed2011-07-01 19:47:50 +00006078 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006079 switch (nibble)
6080 {
6081 case 0:
6082 {
6083 *q=(unsigned char) pixel;
6084 nibble++;
6085 break;
6086 }
6087 case 1:
6088 {
6089 *q|=(unsigned char) (pixel << 4);
6090 q++;
6091 nibble=0;
6092 break;
6093 }
6094 }
cristyed231572011-07-14 02:18:59 +00006095 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006096 }
6097 q+=scanline_pad;
6098 }
6099 break;
6100 }
6101 case 6:
6102 case 8:
6103 {
6104 /*
6105 Convert to 8 bit color-mapped X canvas.
6106 */
6107 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006108 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006109 {
cristy6710d842011-10-20 23:23:00 +00006110 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006111 break;
6112 }
6113 for (y=0; y < (int) canvas->rows; y++)
6114 {
cristyc57f6942010-11-12 01:47:39 +00006115 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006116 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006117 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006118 break;
cristy3ed852e2009-09-05 21:47:34 +00006119 for (x=0; x < (int) canvas->columns; x++)
6120 {
cristy4c08aed2011-07-01 19:47:50 +00006121 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006122 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006123 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006124 }
6125 q+=scanline_pad;
6126 }
6127 break;
6128 }
6129 default:
6130 {
6131 register int
6132 k;
6133
6134 register unsigned int
6135 bytes_per_pixel;
6136
cristy3ed852e2009-09-05 21:47:34 +00006137 /*
6138 Convert to multi-byte color-mapped X canvas.
6139 */
6140 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6141 for (y=0; y < (int) canvas->rows; y++)
6142 {
cristyc57f6942010-11-12 01:47:39 +00006143 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006144 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006145 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006146 break;
cristy3ed852e2009-09-05 21:47:34 +00006147 for (x=0; x < (int) canvas->columns; x++)
6148 {
cristy4c08aed2011-07-01 19:47:50 +00006149 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006150 for (k=0; k < (int) bytes_per_pixel; k++)
6151 {
cristy42daae12013-04-07 22:36:07 +00006152 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006153 pixel>>=8;
6154 }
cristyed231572011-07-14 02:18:59 +00006155 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006156 }
6157 q+=scanline_pad;
6158 }
6159 break;
6160 }
6161 }
6162 else
6163 switch (ximage->bits_per_pixel)
6164 {
6165 case 2:
6166 {
6167 register unsigned int
6168 nibble;
6169
6170 /*
6171 Convert to contiguous 2 bit continuous-tone X canvas.
6172 */
6173 for (y=0; y < (int) canvas->rows; y++)
6174 {
6175 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006176 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006177 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006178 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006179 break;
6180 for (x=0; x < (int) canvas->columns; x++)
6181 {
cristy4c08aed2011-07-01 19:47:50 +00006182 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006183 pixel&=0xf;
6184 switch (nibble)
6185 {
6186 case 0:
6187 {
6188 *q=(unsigned char) pixel;
6189 nibble++;
6190 break;
6191 }
6192 case 1:
6193 {
6194 *q|=(unsigned char) (pixel << 2);
6195 nibble++;
6196 break;
6197 }
6198 case 2:
6199 {
6200 *q|=(unsigned char) (pixel << 4);
6201 nibble++;
6202 break;
6203 }
6204 case 3:
6205 {
6206 *q|=(unsigned char) (pixel << 6);
6207 q++;
6208 nibble=0;
6209 break;
6210 }
6211 }
cristyed231572011-07-14 02:18:59 +00006212 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006213 }
6214 q+=scanline_pad;
6215 }
6216 break;
6217 }
6218 case 4:
6219 {
6220 register unsigned int
6221 nibble;
6222
6223 /*
6224 Convert to contiguous 4 bit continuous-tone X canvas.
6225 */
6226 for (y=0; y < (int) canvas->rows; y++)
6227 {
cristyc57f6942010-11-12 01:47:39 +00006228 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006229 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006230 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006231 break;
6232 nibble=0;
6233 for (x=0; x < (int) canvas->columns; x++)
6234 {
cristy4c08aed2011-07-01 19:47:50 +00006235 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006236 pixel&=0xf;
6237 switch (nibble)
6238 {
6239 case 0:
6240 {
6241 *q=(unsigned char) pixel;
6242 nibble++;
6243 break;
6244 }
6245 case 1:
6246 {
6247 *q|=(unsigned char) (pixel << 4);
6248 q++;
6249 nibble=0;
6250 break;
6251 }
6252 }
cristyed231572011-07-14 02:18:59 +00006253 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006254 }
6255 q+=scanline_pad;
6256 }
6257 break;
6258 }
6259 case 6:
6260 case 8:
6261 {
6262 /*
6263 Convert to contiguous 8 bit continuous-tone X canvas.
6264 */
6265 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006266 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006267 {
cristy6710d842011-10-20 23:23:00 +00006268 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006269 break;
6270 }
6271 for (y=0; y < (int) canvas->rows; y++)
6272 {
cristyc57f6942010-11-12 01:47:39 +00006273 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006274 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006275 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006276 break;
6277 for (x=0; x < (int) canvas->columns; x++)
6278 {
cristy4c08aed2011-07-01 19:47:50 +00006279 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006280 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006281 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006282 }
6283 q+=scanline_pad;
6284 }
6285 break;
6286 }
6287 default:
6288 {
6289 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6290 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6291 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6292 (map_info->blue_mult == 1))
6293 {
6294 /*
6295 Convert to 32 bit continuous-tone X canvas.
6296 */
6297 for (y=0; y < (int) canvas->rows; y++)
6298 {
cristyc57f6942010-11-12 01:47:39 +00006299 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006300 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006301 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006302 break;
6303 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6304 (blue_gamma != 1.0))
6305 {
6306 /*
6307 Gamma correct canvas.
6308 */
6309 for (x=(int) canvas->columns-1; x >= 0; x--)
6310 {
cristyccf844f2010-02-03 23:28:16 +00006311 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006312 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006313 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006314 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006315 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006316 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006317 *q++=0;
cristyed231572011-07-14 02:18:59 +00006318 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006319 }
6320 continue;
6321 }
6322 for (x=(int) canvas->columns-1; x >= 0; x--)
6323 {
cristy8bc259b2012-06-21 23:53:15 +00006324 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6325 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6326 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006327 *q++=0;
cristyed231572011-07-14 02:18:59 +00006328 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006329 }
6330 }
6331 }
6332 else
6333 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6334 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6335 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6336 (map_info->blue_mult == 65536L))
6337 {
6338 /*
6339 Convert to 32 bit continuous-tone X canvas.
6340 */
6341 for (y=0; y < (int) canvas->rows; y++)
6342 {
cristyc57f6942010-11-12 01:47:39 +00006343 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006344 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006345 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006346 break;
6347 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6348 (blue_gamma != 1.0))
6349 {
6350 /*
6351 Gamma correct canvas.
6352 */
6353 for (x=(int) canvas->columns-1; x >= 0; x--)
6354 {
cristyccf844f2010-02-03 23:28:16 +00006355 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006356 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006357 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006358 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006359 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006360 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006361 *q++=0;
cristyed231572011-07-14 02:18:59 +00006362 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006363 }
6364 continue;
6365 }
6366 for (x=(int) canvas->columns-1; x >= 0; x--)
6367 {
cristy8bc259b2012-06-21 23:53:15 +00006368 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6369 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6370 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006371 *q++=0;
cristyed231572011-07-14 02:18:59 +00006372 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006373 }
6374 }
6375 }
6376 else
6377 {
6378 register int
6379 k;
6380
6381 register unsigned int
6382 bytes_per_pixel;
6383
cristy3ed852e2009-09-05 21:47:34 +00006384 /*
6385 Convert to multi-byte continuous-tone X canvas.
6386 */
6387 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6388 for (y=0; y < (int) canvas->rows; y++)
6389 {
cristyc57f6942010-11-12 01:47:39 +00006390 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006391 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006392 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006393 break;
cristyc57f6942010-11-12 01:47:39 +00006394 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006395 {
cristy4c08aed2011-07-01 19:47:50 +00006396 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006397 for (k=0; k < (int) bytes_per_pixel; k++)
6398 {
cristy42daae12013-04-07 22:36:07 +00006399 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006400 pixel>>=8;
6401 }
cristyed231572011-07-14 02:18:59 +00006402 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006403 }
6404 q+=scanline_pad;
6405 }
6406 }
6407 break;
6408 }
6409 }
6410 if (matte_image != (XImage *) NULL)
6411 {
6412 /*
6413 Initialize matte canvas.
6414 */
6415 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6416 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6417 q=(unsigned char *) matte_image->data;
6418 for (y=0; y < (int) canvas->rows; y++)
6419 {
cristyc57f6942010-11-12 01:47:39 +00006420 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006421 exception);
cristy4c08aed2011-07-01 19:47:50 +00006422 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006423 break;
6424 bit=0;
6425 byte=0;
6426 for (x=(int) canvas->columns-1; x >= 0; x--)
6427 {
6428 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006429 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006430 byte|=0x80;
6431 bit++;
6432 if (bit == 8)
6433 {
6434 *q++=byte;
6435 bit=0;
6436 byte=0;
6437 }
cristyed231572011-07-14 02:18:59 +00006438 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006439 }
6440 if (bit != 0)
6441 *q=byte >> (8-bit);
6442 q+=scanline_pad;
6443 }
6444 }
cristyc57f6942010-11-12 01:47:39 +00006445 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006446 if (canvas != image)
6447 canvas=DestroyImage(canvas);
6448}
6449
6450/*
6451%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6452% %
6453% %
6454% %
6455+ X M a k e I m a g e M S B F i r s t %
6456% %
6457% %
6458% %
6459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6460%
6461% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6462% image pixels are copied in most-significant bit and byte first order. The
6463% server's scanline pad is also respected. Rather than using one or two
6464% general cases, many special cases are found here to help speed up the image
6465% conversion.
6466%
6467% The format of the XMakeImageMSBFirst method is:
6468%
cristye941a752011-10-15 01:52:48 +00006469% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6470% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006471%
6472% A description of each parameter follows:
6473%
6474% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6475%
6476% o window: Specifies a pointer to a XWindowInfo structure.
6477%
6478% o image: the image.
6479%
6480% o ximage: Specifies a pointer to a XImage structure; returned from
6481% XCreateImage.
6482%
6483% o matte_image: Specifies a pointer to a XImage structure; returned from
6484% XCreateImage.
6485%
cristye941a752011-10-15 01:52:48 +00006486% o exception: return any errors or warnings in this structure.
6487%
cristy3ed852e2009-09-05 21:47:34 +00006488*/
6489static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006490 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6491 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006492{
cristyc57f6942010-11-12 01:47:39 +00006493 CacheView
6494 *canvas_view;
6495
cristy3ed852e2009-09-05 21:47:34 +00006496 Image
6497 *canvas;
6498
6499 int
6500 y;
6501
6502 register int
6503 x;
6504
cristy4c08aed2011-07-01 19:47:50 +00006505 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006506 *p;
6507
6508 register unsigned char
6509 *q;
6510
6511 unsigned char
6512 bit,
6513 byte;
6514
6515 unsigned int
6516 scanline_pad;
6517
cristyf2faecf2010-05-28 19:19:36 +00006518 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006519 pixel,
6520 *pixels;
6521
6522 XStandardColormap
6523 *map_info;
6524
6525 assert(resource_info != (XResourceInfo *) NULL);
6526 assert(window != (XWindowInfo *) NULL);
6527 assert(image != (Image *) NULL);
6528 if (image->debug != MagickFalse)
6529 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6530 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006531 if ((window->immutable != MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00006532 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00006533 {
6534 char
6535 size[MaxTextExtent];
6536
6537 Image
6538 *pattern;
6539
6540 ImageInfo
6541 *image_info;
6542
6543 image_info=AcquireImageInfo();
6544 (void) CopyMagickString(image_info->filename,
6545 resource_info->image_info->texture != (char *) NULL ?
6546 resource_info->image_info->texture : "pattern:checkerboard",
6547 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006548 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006549 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006550 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006551 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006552 image_info=DestroyImageInfo(image_info);
6553 if (pattern != (Image *) NULL)
6554 {
cristy6710d842011-10-20 23:23:00 +00006555 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006556 if (canvas != (Image *) NULL)
cristyfeb3e962012-03-29 17:25:55 +00006557 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6558 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00006559 pattern=DestroyImage(pattern);
6560 }
6561 }
cristy4c08aed2011-07-01 19:47:50 +00006562 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6563 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006564 map_info=window->map_info;
6565 pixels=window->pixel_info->pixels;
6566 q=(unsigned char *) ximage->data;
6567 x=0;
cristy46ff2672012-12-14 15:32:26 +00006568 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00006569 if (ximage->format == XYBitmap)
6570 {
6571 register unsigned short
6572 polarity;
6573
6574 unsigned char
6575 background,
6576 foreground;
6577
6578 /*
6579 Convert canvas to big-endian bitmap.
6580 */
6581 background=(unsigned char)
6582 (XPixelIntensity(&window->pixel_info->foreground_color) <
6583 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6584 foreground=(unsigned char)
6585 (XPixelIntensity(&window->pixel_info->background_color) <
6586 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006587 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00006588 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00006589 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006590 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6591 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006592 for (y=0; y < (int) canvas->rows; y++)
6593 {
cristyc57f6942010-11-12 01:47:39 +00006594 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006595 exception);
cristy4c08aed2011-07-01 19:47:50 +00006596 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006597 break;
cristy3ed852e2009-09-05 21:47:34 +00006598 bit=0;
6599 byte=0;
6600 for (x=(int) canvas->columns-1; x >= 0; x--)
6601 {
6602 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006603 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006604 byte|=foreground;
6605 else
6606 byte|=background;
6607 bit++;
6608 if (bit == 8)
6609 {
6610 *q++=byte;
6611 bit=0;
6612 byte=0;
6613 }
cristyed231572011-07-14 02:18:59 +00006614 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006615 }
6616 if (bit != 0)
6617 *q=byte << (8-bit);
6618 q+=scanline_pad;
6619 }
6620 }
6621 else
6622 if (window->pixel_info->colors != 0)
6623 switch (ximage->bits_per_pixel)
6624 {
6625 case 2:
6626 {
6627 register unsigned int
6628 nibble;
6629
6630 /*
6631 Convert to 2 bit color-mapped X canvas.
6632 */
6633 for (y=0; y < (int) canvas->rows; y++)
6634 {
cristyc57f6942010-11-12 01:47:39 +00006635 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006636 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006637 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006638 break;
cristy3ed852e2009-09-05 21:47:34 +00006639 nibble=0;
6640 for (x=0; x < (int) canvas->columns; x++)
6641 {
cristy4c08aed2011-07-01 19:47:50 +00006642 pixel=pixels[(ssize_t)
6643 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006644 switch (nibble)
6645 {
6646 case 0:
6647 {
6648 *q=(unsigned char) (pixel << 6);
6649 nibble++;
6650 break;
6651 }
6652 case 1:
6653 {
6654 *q|=(unsigned char) (pixel << 4);
6655 nibble++;
6656 break;
6657 }
6658 case 2:
6659 {
6660 *q|=(unsigned char) (pixel << 2);
6661 nibble++;
6662 break;
6663 }
6664 case 3:
6665 {
6666 *q|=(unsigned char) pixel;
6667 q++;
6668 nibble=0;
6669 break;
6670 }
6671 }
cristyed231572011-07-14 02:18:59 +00006672 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006673 }
6674 q+=scanline_pad;
6675 }
6676 break;
6677 }
6678 case 4:
6679 {
6680 register unsigned int
6681 nibble;
6682
6683 /*
6684 Convert to 4 bit color-mapped X canvas.
6685 */
6686 for (y=0; y < (int) canvas->rows; y++)
6687 {
cristyc57f6942010-11-12 01:47:39 +00006688 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006689 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006690 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006691 break;
cristy3ed852e2009-09-05 21:47:34 +00006692 nibble=0;
6693 for (x=0; x < (int) canvas->columns; x++)
6694 {
cristy4c08aed2011-07-01 19:47:50 +00006695 pixel=pixels[(ssize_t)
6696 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006697 switch (nibble)
6698 {
6699 case 0:
6700 {
6701 *q=(unsigned char) (pixel << 4);
6702 nibble++;
6703 break;
6704 }
6705 case 1:
6706 {
6707 *q|=(unsigned char) pixel;
6708 q++;
6709 nibble=0;
6710 break;
6711 }
6712 }
cristyed231572011-07-14 02:18:59 +00006713 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006714 }
6715 q+=scanline_pad;
6716 }
6717 break;
6718 }
6719 case 6:
6720 case 8:
6721 {
6722 /*
6723 Convert to 8 bit color-mapped X canvas.
6724 */
6725 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006726 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006727 {
cristy6710d842011-10-20 23:23:00 +00006728 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006729 break;
6730 }
6731 for (y=0; y < (int) canvas->rows; y++)
6732 {
cristyc57f6942010-11-12 01:47:39 +00006733 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006734 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006735 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006736 break;
cristy3ed852e2009-09-05 21:47:34 +00006737 for (x=0; x < (int) canvas->columns; x++)
6738 {
cristy6710d842011-10-20 23:23:00 +00006739 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006740 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006741 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006742 }
6743 q+=scanline_pad;
6744 }
6745 break;
6746 }
6747 default:
6748 {
6749 register int
6750 k;
6751
6752 register unsigned int
6753 bytes_per_pixel;
6754
6755 unsigned char
cristybb503372010-05-27 20:51:26 +00006756 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006757
6758 /*
6759 Convert to 8 bit color-mapped X canvas.
6760 */
6761 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6762 for (y=0; y < (int) canvas->rows; y++)
6763 {
cristyc57f6942010-11-12 01:47:39 +00006764 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006765 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006766 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006767 break;
cristy3ed852e2009-09-05 21:47:34 +00006768 for (x=0; x < (int) canvas->columns; x++)
6769 {
cristy4c08aed2011-07-01 19:47:50 +00006770 pixel=pixels[(ssize_t)
6771 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006772 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6773 {
6774 channel[k]=(unsigned char) pixel;
6775 pixel>>=8;
6776 }
6777 for (k=0; k < (int) bytes_per_pixel; k++)
6778 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006779 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006780 }
6781 q+=scanline_pad;
6782 }
6783 break;
6784 }
6785 }
6786 else
6787 switch (ximage->bits_per_pixel)
6788 {
6789 case 2:
6790 {
6791 register unsigned int
6792 nibble;
6793
6794 /*
6795 Convert to 4 bit continuous-tone X canvas.
6796 */
6797 for (y=0; y < (int) canvas->rows; y++)
6798 {
cristyc57f6942010-11-12 01:47:39 +00006799 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006800 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006801 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006802 break;
6803 nibble=0;
6804 for (x=(int) canvas->columns-1; x >= 0; x--)
6805 {
cristy4c08aed2011-07-01 19:47:50 +00006806 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006807 pixel&=0xf;
6808 switch (nibble)
6809 {
6810 case 0:
6811 {
6812 *q=(unsigned char) (pixel << 6);
6813 nibble++;
6814 break;
6815 }
6816 case 1:
6817 {
6818 *q|=(unsigned char) (pixel << 4);
6819 nibble++;
6820 break;
6821 }
6822 case 2:
6823 {
6824 *q|=(unsigned char) (pixel << 2);
6825 nibble++;
6826 break;
6827 }
6828 case 3:
6829 {
6830 *q|=(unsigned char) pixel;
6831 q++;
6832 nibble=0;
6833 break;
6834 }
6835 }
cristyed231572011-07-14 02:18:59 +00006836 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006837 }
6838 q+=scanline_pad;
6839 }
6840 break;
6841 }
6842 case 4:
6843 {
6844 register unsigned int
6845 nibble;
6846
6847 /*
6848 Convert to 4 bit continuous-tone X canvas.
6849 */
6850 for (y=0; y < (int) canvas->rows; y++)
6851 {
cristyc57f6942010-11-12 01:47:39 +00006852 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006853 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006854 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006855 break;
6856 nibble=0;
6857 for (x=(int) canvas->columns-1; x >= 0; x--)
6858 {
cristy4c08aed2011-07-01 19:47:50 +00006859 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006860 pixel&=0xf;
6861 switch (nibble)
6862 {
6863 case 0:
6864 {
6865 *q=(unsigned char) (pixel << 4);
6866 nibble++;
6867 break;
6868 }
6869 case 1:
6870 {
6871 *q|=(unsigned char) pixel;
6872 q++;
6873 nibble=0;
6874 break;
6875 }
6876 }
cristyed231572011-07-14 02:18:59 +00006877 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006878 }
6879 q+=scanline_pad;
6880 }
6881 break;
6882 }
6883 case 6:
6884 case 8:
6885 {
6886 /*
6887 Convert to 8 bit continuous-tone X canvas.
6888 */
6889 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006890 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006891 {
cristy6710d842011-10-20 23:23:00 +00006892 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006893 break;
6894 }
6895 for (y=0; y < (int) canvas->rows; y++)
6896 {
cristyc57f6942010-11-12 01:47:39 +00006897 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006898 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006899 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006900 break;
6901 for (x=(int) canvas->columns-1; x >= 0; x--)
6902 {
cristy4c08aed2011-07-01 19:47:50 +00006903 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006904 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006905 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006906 }
6907 q+=scanline_pad;
6908 }
6909 break;
6910 }
6911 default:
6912 {
6913 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6914 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6915 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6916 (map_info->blue_mult == 1))
6917 {
6918 /*
6919 Convert to 32 bit continuous-tone X canvas.
6920 */
6921 for (y=0; y < (int) canvas->rows; y++)
6922 {
cristyc57f6942010-11-12 01:47:39 +00006923 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006924 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006925 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006926 break;
6927 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6928 (blue_gamma != 1.0))
6929 {
6930 /*
6931 Gamma correct canvas.
6932 */
6933 for (x=(int) canvas->columns-1; x >= 0; x--)
6934 {
6935 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006936 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006937 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006938 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006939 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006940 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006941 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006942 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006943 }
6944 continue;
6945 }
6946 for (x=(int) canvas->columns-1; x >= 0; x--)
6947 {
6948 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006949 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6950 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6951 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006952 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006953 }
6954 }
6955 }
6956 else
6957 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6958 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6959 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6960 (map_info->blue_mult == 65536L))
6961 {
6962 /*
6963 Convert to 32 bit continuous-tone X canvas.
6964 */
6965 for (y=0; y < (int) canvas->rows; y++)
6966 {
cristyc57f6942010-11-12 01:47:39 +00006967 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006968 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006969 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006970 break;
6971 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6972 (blue_gamma != 1.0))
6973 {
6974 /*
6975 Gamma correct canvas.
6976 */
6977 for (x=(int) canvas->columns-1; x >= 0; x--)
6978 {
6979 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006980 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006981 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006982 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006983 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006984 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006985 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006986 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006987 }
6988 continue;
6989 }
6990 for (x=(int) canvas->columns-1; x >= 0; x--)
6991 {
6992 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006993 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6994 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6995 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006996 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006997 }
6998 }
6999 }
7000 else
7001 {
7002 register int
7003 k;
7004
7005 register unsigned int
7006 bytes_per_pixel;
7007
7008 unsigned char
cristybb503372010-05-27 20:51:26 +00007009 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007010
7011 /*
7012 Convert to multi-byte continuous-tone X canvas.
7013 */
7014 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7015 for (y=0; y < (int) canvas->rows; y++)
7016 {
cristyc57f6942010-11-12 01:47:39 +00007017 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007018 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007019 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007020 break;
7021 for (x=(int) canvas->columns-1; x >= 0; x--)
7022 {
cristy4c08aed2011-07-01 19:47:50 +00007023 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007024 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7025 {
7026 channel[k]=(unsigned char) pixel;
7027 pixel>>=8;
7028 }
7029 for (k=0; k < (int) bytes_per_pixel; k++)
7030 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007031 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007032 }
7033 q+=scanline_pad;
7034 }
7035 }
7036 break;
7037 }
7038 }
7039 if (matte_image != (XImage *) NULL)
7040 {
7041 /*
7042 Initialize matte canvas.
7043 */
7044 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7045 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7046 q=(unsigned char *) matte_image->data;
7047 for (y=0; y < (int) canvas->rows; y++)
7048 {
cristyc57f6942010-11-12 01:47:39 +00007049 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007050 exception);
cristy4c08aed2011-07-01 19:47:50 +00007051 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007052 break;
7053 bit=0;
7054 byte=0;
7055 for (x=(int) canvas->columns-1; x >= 0; x--)
7056 {
7057 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007058 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007059 byte|=0x01;
7060 bit++;
7061 if (bit == 8)
7062 {
7063 *q++=byte;
7064 bit=0;
7065 byte=0;
7066 }
cristyed231572011-07-14 02:18:59 +00007067 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007068 }
7069 if (bit != 0)
7070 *q=byte << (8-bit);
7071 q+=scanline_pad;
7072 }
7073 }
cristyc57f6942010-11-12 01:47:39 +00007074 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007075 if (canvas != image)
7076 canvas=DestroyImage(canvas);
7077}
7078
7079/*
7080%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7081% %
7082% %
7083% %
7084% X M a k e M a g n i f y I m a g e %
7085% %
7086% %
7087% %
7088%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7089%
7090% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7091%
7092% The format of the XMakeMagnifyImage method is:
7093%
cristy6710d842011-10-20 23:23:00 +00007094% void XMakeMagnifyImage(Display *display,XWindows *windows,
7095% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007096%
7097% A description of each parameter follows:
7098%
7099% o display: Specifies a connection to an X server; returned from
7100% XOpenDisplay.
7101%
7102% o windows: Specifies a pointer to a XWindows structure.
7103%
cristy6710d842011-10-20 23:23:00 +00007104% o exception: return any errors or warnings in this structure.
7105%
cristy3ed852e2009-09-05 21:47:34 +00007106*/
cristy6710d842011-10-20 23:23:00 +00007107MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7108 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007109{
7110 char
7111 tuple[MaxTextExtent];
7112
7113 int
7114 y;
7115
cristy4c08aed2011-07-01 19:47:50 +00007116 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007117 pixel;
7118
7119 register int
7120 x;
7121
cristybb503372010-05-27 20:51:26 +00007122 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007123 i;
7124
7125 register unsigned char
7126 *p,
7127 *q;
7128
cristy9d314ff2011-03-09 01:30:28 +00007129 ssize_t
7130 n;
7131
cristy3ed852e2009-09-05 21:47:34 +00007132 static unsigned int
7133 previous_magnify = 0;
7134
7135 static XWindowInfo
7136 magnify_window;
7137
7138 unsigned int
7139 height,
7140 j,
7141 k,
7142 l,
7143 magnify,
7144 scanline_pad,
7145 width;
7146
7147 XImage
7148 *ximage;
7149
7150 /*
7151 Check boundary conditions.
7152 */
7153 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7154 assert(display != (Display *) NULL);
7155 assert(windows != (XWindows *) NULL);
7156 magnify=1;
cristybb503372010-05-27 20:51:26 +00007157 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007158 magnify<<=1;
7159 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7160 magnify<<=1;
7161 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7162 magnify<<=1;
7163 while (magnify > windows->magnify.width)
7164 magnify>>=1;
7165 while (magnify > windows->magnify.height)
7166 magnify>>=1;
7167 if (magnify != previous_magnify)
7168 {
7169 Status
7170 status;
7171
7172 XTextProperty
7173 window_name;
7174
7175 /*
7176 New magnify factor: update magnify window name.
7177 */
7178 i=0;
7179 while ((1 << i) <= (int) magnify)
7180 i++;
cristyb51dff52011-05-19 16:55:47 +00007181 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007182 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007183 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7184 if (status != False)
7185 {
7186 XSetWMName(display,windows->magnify.id,&window_name);
7187 XSetWMIconName(display,windows->magnify.id,&window_name);
7188 (void) XFree((void *) window_name.value);
7189 }
7190 }
7191 previous_magnify=magnify;
7192 ximage=windows->image.ximage;
7193 width=(unsigned int) windows->magnify.ximage->width;
7194 height=(unsigned int) windows->magnify.ximage->height;
7195 if ((windows->magnify.x < 0) ||
7196 (windows->magnify.x >= windows->image.ximage->width))
7197 windows->magnify.x=windows->image.ximage->width >> 1;
7198 x=windows->magnify.x-((width/magnify) >> 1);
7199 if (x < 0)
7200 x=0;
7201 else
7202 if (x > (int) (ximage->width-(width/magnify)))
7203 x=ximage->width-width/magnify;
7204 if ((windows->magnify.y < 0) ||
7205 (windows->magnify.y >= windows->image.ximage->height))
7206 windows->magnify.y=windows->image.ximage->height >> 1;
7207 y=windows->magnify.y-((height/magnify) >> 1);
7208 if (y < 0)
7209 y=0;
7210 else
7211 if (y > (int) (ximage->height-(height/magnify)))
7212 y=ximage->height-height/magnify;
7213 q=(unsigned char *) windows->magnify.ximage->data;
7214 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7215 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7216 if (ximage->bits_per_pixel < 8)
7217 {
7218 register unsigned char
7219 background,
7220 byte,
7221 foreground,
7222 p_bit,
7223 q_bit;
7224
7225 register unsigned int
7226 plane;
7227
7228 XPixelInfo
7229 *pixel_info;
7230
7231 pixel_info=windows->magnify.pixel_info;
7232 switch (ximage->bitmap_bit_order)
7233 {
7234 case LSBFirst:
7235 {
7236 /*
7237 Magnify little-endian bitmap.
7238 */
7239 background=0x00;
7240 foreground=0x80;
7241 if (ximage->format == XYBitmap)
7242 {
7243 background=(unsigned char)
7244 (XPixelIntensity(&pixel_info->foreground_color) <
7245 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7246 foreground=(unsigned char)
7247 (XPixelIntensity(&pixel_info->background_color) <
7248 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7249 if (windows->magnify.depth > 1)
7250 Swap(background,foreground);
7251 }
cristybb503372010-05-27 20:51:26 +00007252 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007253 {
7254 /*
7255 Propogate pixel magnify rows.
7256 */
7257 for (j=0; j < magnify; j++)
7258 {
7259 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7260 ((x*ximage->bits_per_pixel) >> 3);
7261 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7262 q_bit=0;
7263 byte=0;
7264 for (k=0; k < width; k+=magnify)
7265 {
7266 /*
7267 Propogate pixel magnify columns.
7268 */
7269 for (l=0; l < magnify; l++)
7270 {
7271 /*
7272 Propogate each bit plane.
7273 */
7274 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7275 {
7276 byte>>=1;
7277 if (*p & (0x01 << (p_bit+plane)))
7278 byte|=foreground;
7279 else
7280 byte|=background;
7281 q_bit++;
7282 if (q_bit == 8)
7283 {
7284 *q++=byte;
7285 q_bit=0;
7286 byte=0;
7287 }
7288 }
7289 }
7290 p_bit+=ximage->bits_per_pixel;
7291 if (p_bit == 8)
7292 {
7293 p++;
7294 p_bit=0;
7295 }
7296 if (q_bit != 0)
7297 *q=byte >> (8-q_bit);
7298 q+=scanline_pad;
7299 }
7300 }
7301 y++;
7302 }
7303 break;
7304 }
7305 case MSBFirst:
7306 default:
7307 {
7308 /*
7309 Magnify big-endian bitmap.
7310 */
7311 background=0x00;
7312 foreground=0x01;
7313 if (ximage->format == XYBitmap)
7314 {
7315 background=(unsigned char)
7316 (XPixelIntensity(&pixel_info->foreground_color) <
7317 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7318 foreground=(unsigned char)
7319 (XPixelIntensity(&pixel_info->background_color) <
7320 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7321 if (windows->magnify.depth > 1)
7322 Swap(background,foreground);
7323 }
cristybb503372010-05-27 20:51:26 +00007324 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007325 {
7326 /*
7327 Propogate pixel magnify rows.
7328 */
7329 for (j=0; j < magnify; j++)
7330 {
7331 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7332 ((x*ximage->bits_per_pixel) >> 3);
7333 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7334 q_bit=0;
7335 byte=0;
7336 for (k=0; k < width; k+=magnify)
7337 {
7338 /*
7339 Propogate pixel magnify columns.
7340 */
7341 for (l=0; l < magnify; l++)
7342 {
7343 /*
7344 Propogate each bit plane.
7345 */
7346 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7347 {
7348 byte<<=1;
7349 if (*p & (0x80 >> (p_bit+plane)))
7350 byte|=foreground;
7351 else
7352 byte|=background;
7353 q_bit++;
7354 if (q_bit == 8)
7355 {
7356 *q++=byte;
7357 q_bit=0;
7358 byte=0;
7359 }
7360 }
7361 }
7362 p_bit+=ximage->bits_per_pixel;
7363 if (p_bit == 8)
7364 {
7365 p++;
7366 p_bit=0;
7367 }
7368 if (q_bit != 0)
7369 *q=byte << (8-q_bit);
7370 q+=scanline_pad;
7371 }
7372 }
7373 y++;
7374 }
7375 break;
7376 }
7377 }
7378 }
7379 else
7380 switch (ximage->bits_per_pixel)
7381 {
7382 case 6:
7383 case 8:
7384 {
7385 /*
7386 Magnify 8 bit X image.
7387 */
cristybb503372010-05-27 20:51:26 +00007388 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007389 {
7390 /*
7391 Propogate pixel magnify rows.
7392 */
7393 for (j=0; j < magnify; j++)
7394 {
7395 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7396 ((x*ximage->bits_per_pixel) >> 3);
7397 for (k=0; k < width; k+=magnify)
7398 {
7399 /*
7400 Propogate pixel magnify columns.
7401 */
7402 for (l=0; l < magnify; l++)
7403 *q++=(*p);
7404 p++;
7405 }
7406 q+=scanline_pad;
7407 }
7408 y++;
7409 }
7410 break;
7411 }
7412 default:
7413 {
7414 register unsigned int
7415 bytes_per_pixel,
7416 m;
7417
7418 /*
7419 Magnify multi-byte X image.
7420 */
7421 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007422 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007423 {
7424 /*
7425 Propogate pixel magnify rows.
7426 */
7427 for (j=0; j < magnify; j++)
7428 {
7429 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7430 ((x*ximage->bits_per_pixel) >> 3);
7431 for (k=0; k < width; k+=magnify)
7432 {
7433 /*
7434 Propogate pixel magnify columns.
7435 */
7436 for (l=0; l < magnify; l++)
7437 for (m=0; m < bytes_per_pixel; m++)
7438 *q++=(*(p+m));
7439 p+=bytes_per_pixel;
7440 }
7441 q+=scanline_pad;
7442 }
7443 y++;
7444 }
7445 break;
7446 }
7447 }
7448 /*
7449 Copy X image to magnify pixmap.
7450 */
7451 x=windows->magnify.x-((width/magnify) >> 1);
7452 if (x < 0)
7453 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7454 else
7455 if (x > (int) (ximage->width-(width/magnify)))
7456 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7457 else
7458 x=0;
7459 y=windows->magnify.y-((height/magnify) >> 1);
7460 if (y < 0)
7461 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7462 else
7463 if (y > (int) (ximage->height-(height/magnify)))
7464 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7465 else
7466 y=0;
7467 if ((x != 0) || (y != 0))
7468 (void) XFillRectangle(display,windows->magnify.pixmap,
7469 windows->magnify.annotate_context,0,0,width,height);
7470 (void) XPutImage(display,windows->magnify.pixmap,
7471 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7472 height-y);
7473 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7474 (magnify <= (height >> 1))))
7475 {
7476 RectangleInfo
7477 highlight_info;
7478
7479 /*
7480 Highlight center pixel.
7481 */
cristybb503372010-05-27 20:51:26 +00007482 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7483 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007484 highlight_info.width=magnify;
7485 highlight_info.height=magnify;
7486 (void) XDrawRectangle(display,windows->magnify.pixmap,
7487 windows->magnify.highlight_context,(int) highlight_info.x,
7488 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7489 (unsigned int) highlight_info.height-1);
7490 if (magnify > 2)
7491 (void) XDrawRectangle(display,windows->magnify.pixmap,
7492 windows->magnify.annotate_context,(int) highlight_info.x+1,
7493 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7494 (unsigned int) highlight_info.height-3);
7495 }
7496 /*
7497 Show center pixel color.
7498 */
cristy3aa93752011-12-18 15:54:24 +00007499 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007500 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007501 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007502 windows->magnify.x,windows->magnify.y);
7503 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007504 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007505 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007506 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007507 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007508 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007509 if (pixel.colorspace == CMYKColorspace)
7510 {
7511 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007512 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007513 }
cristy8a46d822012-08-28 23:32:39 +00007514 if (pixel.alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00007515 {
7516 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007517 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007518 }
7519 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7520 height=(unsigned int) windows->magnify.font_info->ascent+
7521 windows->magnify.font_info->descent;
7522 x=windows->magnify.font_info->max_bounds.width >> 1;
7523 y=windows->magnify.font_info->ascent+(height >> 2);
7524 (void) XDrawImageString(display,windows->magnify.pixmap,
7525 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7526 GetColorTuple(&pixel,MagickTrue,tuple);
7527 y+=height;
7528 (void) XDrawImageString(display,windows->magnify.pixmap,
7529 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007530 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007531 exception);
cristy3ed852e2009-09-05 21:47:34 +00007532 y+=height;
7533 (void) XDrawImageString(display,windows->magnify.pixmap,
7534 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7535 /*
7536 Refresh magnify window.
7537 */
7538 magnify_window=windows->magnify;
7539 magnify_window.x=0;
7540 magnify_window.y=0;
7541 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7542}
7543
7544/*
7545%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7546% %
7547% %
7548% %
7549% X M a k e P i x m a p %
7550% %
7551% %
7552% %
7553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7554%
7555% XMakePixmap() creates an X11 pixmap.
7556%
7557% The format of the XMakePixmap method is:
7558%
7559% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7560% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7561% XPixelInfo *pixel)
7562%
7563% A description of each parameter follows:
7564%
7565% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7566%
7567% o display: Specifies a connection to an X server; returned from
7568% XOpenDisplay.
7569%
7570% o window: Specifies a pointer to a XWindowInfo structure.
7571%
cristy3ed852e2009-09-05 21:47:34 +00007572*/
7573static MagickBooleanType XMakePixmap(Display *display,
7574 const XResourceInfo *resource_info,XWindowInfo *window)
7575{
7576 unsigned int
7577 height,
7578 width;
7579
7580 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7581 assert(display != (Display *) NULL);
7582 assert(resource_info != (XResourceInfo *) NULL);
7583 assert(window != (XWindowInfo *) NULL);
7584 if (window->pixmap != (Pixmap) NULL)
7585 {
7586 /*
7587 Destroy previous X pixmap.
7588 */
7589 (void) XFreePixmap(display,window->pixmap);
7590 window->pixmap=(Pixmap) NULL;
7591 }
7592 if (window->use_pixmap == MagickFalse)
7593 return(MagickFalse);
7594 if (window->ximage == (XImage *) NULL)
7595 return(MagickFalse);
7596 /*
7597 Display busy cursor.
7598 */
7599 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7600 (void) XFlush(display);
7601 /*
7602 Create pixmap.
7603 */
7604 width=(unsigned int) window->ximage->width;
7605 height=(unsigned int) window->ximage->height;
7606 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7607 if (window->pixmap == (Pixmap) NULL)
7608 {
7609 /*
7610 Unable to allocate pixmap.
7611 */
7612 (void) XCheckDefineCursor(display,window->id,window->cursor);
7613 return(MagickFalse);
7614 }
7615 /*
7616 Copy X image to pixmap.
7617 */
7618#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7619 if (window->shared_memory)
7620 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7621 window->ximage,0,0,0,0,width,height,MagickTrue);
7622#endif
7623 if (window->shared_memory == MagickFalse)
7624 (void) XPutImage(display,window->pixmap,window->annotate_context,
7625 window->ximage,0,0,0,0,width,height);
7626 if (IsEventLogging())
7627 {
7628 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7629 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7630 width,height);
7631 }
7632 /*
7633 Restore cursor.
7634 */
7635 (void) XCheckDefineCursor(display,window->id,window->cursor);
7636 return(MagickTrue);
7637}
7638
7639/*
7640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7641% %
7642% %
7643% %
7644% X M a k e S t a n d a r d C o l o r m a p %
7645% %
7646% %
7647% %
7648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7649%
7650% XMakeStandardColormap() creates an X11 Standard Colormap.
7651%
7652% The format of the XMakeStandardColormap method is:
7653%
cristy6710d842011-10-20 23:23:00 +00007654% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7655% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7656% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007657%
7658% A description of each parameter follows:
7659%
7660% o display: Specifies a connection to an X server; returned from
7661% XOpenDisplay.
7662%
7663% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7664% returned from XGetVisualInfo.
7665%
7666% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7667%
7668% o image: the image.
7669%
7670% o map_info: If a Standard Colormap type is specified, this structure is
7671% initialized with info from the Standard Colormap.
7672%
7673% o pixel: Specifies a pointer to a XPixelInfo structure.
7674%
cristy6710d842011-10-20 23:23:00 +00007675% o exception: return any errors or warnings in this structure.
7676%
cristy3ed852e2009-09-05 21:47:34 +00007677*/
7678
7679#if defined(__cplusplus) || defined(c_plusplus)
7680extern "C" {
7681#endif
7682
cristya19f1d72012-08-07 18:24:38 +00007683static inline double DiversityPixelIntensity(
cristy3ed852e2009-09-05 21:47:34 +00007684 const DiversityPacket *pixel)
7685{
cristya19f1d72012-08-07 18:24:38 +00007686 double
cristy3ed852e2009-09-05 21:47:34 +00007687 intensity;
7688
cristyd3d2a272013-06-24 16:09:41 +00007689 intensity=0.212656*pixel->red+0.715158*pixel->green+0.072186*pixel->blue;
cristy3ed852e2009-09-05 21:47:34 +00007690 return(intensity);
7691}
7692
7693static int IntensityCompare(const void *x,const void *y)
7694{
7695 DiversityPacket
7696 *color_1,
7697 *color_2;
7698
7699 int
7700 diversity;
7701
7702 color_1=(DiversityPacket *) x;
7703 color_2=(DiversityPacket *) y;
7704 diversity=(int) (DiversityPixelIntensity(color_2)-
7705 DiversityPixelIntensity(color_1));
7706 return(diversity);
7707}
7708
7709static int PopularityCompare(const void *x,const void *y)
7710{
7711 DiversityPacket
7712 *color_1,
7713 *color_2;
7714
7715 color_1=(DiversityPacket *) x;
7716 color_2=(DiversityPacket *) y;
7717 return((int) color_2->count-(int) color_1->count);
7718}
7719
7720#if defined(__cplusplus) || defined(c_plusplus)
7721}
7722#endif
7723
cristybb503372010-05-27 20:51:26 +00007724static inline Quantum ScaleXToQuantum(const size_t x,
7725 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007726{
cristya19f1d72012-08-07 18:24:38 +00007727 return((Quantum) (((double) QuantumRange*x)/scale+0.5));
cristy3ed852e2009-09-05 21:47:34 +00007728}
7729
cristybcbda3f2011-09-03 13:01:22 +00007730MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007731 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007732 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007733{
7734 Colormap
7735 colormap;
7736
cristybb503372010-05-27 20:51:26 +00007737 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007738 i;
7739
7740 Status
7741 status;
7742
cristybb503372010-05-27 20:51:26 +00007743 size_t
cristy3ed852e2009-09-05 21:47:34 +00007744 number_colors,
7745 retain_colors;
7746
7747 unsigned short
7748 gray_value;
7749
7750 XColor
7751 color,
7752 *colors,
7753 *p;
7754
7755 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7756 assert(display != (Display *) NULL);
7757 assert(visual_info != (XVisualInfo *) NULL);
7758 assert(map_info != (XStandardColormap *) NULL);
7759 assert(resource_info != (XResourceInfo *) NULL);
7760 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007761 if (resource_info->map_type != (char *) NULL)
7762 {
7763 /*
7764 Standard Colormap is already defined (i.e. xstdcmap).
7765 */
cristy4c08aed2011-07-01 19:47:50 +00007766 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007767 pixel);
7768 number_colors=(unsigned int) (map_info->base_pixel+
7769 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7770 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
cristy8a46d822012-08-28 23:32:39 +00007771 if ((image->alpha_trait != BlendPixelTrait) &&
cristy3ed852e2009-09-05 21:47:34 +00007772 (resource_info->color_recovery == MagickFalse) &&
cristycbda6112012-05-27 20:57:16 +00007773 (resource_info->quantize_info->dither_method != NoDitherMethod) &&
cristy3ed852e2009-09-05 21:47:34 +00007774 (number_colors < MaxColormapSize))
7775 {
7776 Image
7777 *affinity_image;
7778
cristy4c08aed2011-07-01 19:47:50 +00007779 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007780 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007781
7782 /*
7783 Improve image appearance with error diffusion.
7784 */
cristy6710d842011-10-20 23:23:00 +00007785 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007786 if (affinity_image == (Image *) NULL)
7787 ThrowXWindowFatalException(ResourceLimitFatalError,
7788 "UnableToDitherImage",image->filename);
7789 affinity_image->columns=number_colors;
7790 affinity_image->rows=1;
7791 /*
7792 Initialize colormap image.
7793 */
7794 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7795 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007796 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007797 {
cristybb503372010-05-27 20:51:26 +00007798 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007799 {
cristy4c08aed2011-07-01 19:47:50 +00007800 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007801 if (map_info->red_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007802 SetPixelRed(affinity_image,ScaleXToQuantum((size_t)
7803 (i/map_info->red_mult),map_info->red_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007804 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007805 if (map_info->green_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007806 SetPixelGreen(affinity_image,ScaleXToQuantum((size_t)
7807 ((i/map_info->green_mult) % (map_info->green_max+1)),
7808 map_info->green_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007809 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007810 if (map_info->blue_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007811 SetPixelBlue(affinity_image,ScaleXToQuantum((size_t)
7812 (i % map_info->green_mult),map_info->blue_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007813 SetPixelAlpha(affinity_image,
7814 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007815 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007816 }
7817 (void) SyncAuthenticPixels(affinity_image,exception);
7818 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007819 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007820 }
cristy4c08aed2011-07-01 19:47:50 +00007821 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007822 pixel);
cristy574cc262011-08-05 01:23:58 +00007823 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007824 affinity_image=DestroyImage(affinity_image);
7825 }
7826 if (IsEventLogging())
7827 {
7828 (void) LogMagickEvent(X11Event,GetMagickModule(),
7829 "Standard Colormap:");
7830 (void) LogMagickEvent(X11Event,GetMagickModule(),
7831 " colormap id: 0x%lx",map_info->colormap);
7832 (void) LogMagickEvent(X11Event,GetMagickModule(),
7833 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7834 map_info->green_max,map_info->blue_max);
7835 (void) LogMagickEvent(X11Event,GetMagickModule(),
7836 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7837 map_info->green_mult,map_info->blue_mult);
7838 }
7839 return;
7840 }
7841 if ((visual_info->klass != DirectColor) &&
7842 (visual_info->klass != TrueColor))
7843 if ((image->storage_class == DirectClass) ||
7844 ((int) image->colors > visual_info->colormap_size))
7845 {
7846 QuantizeInfo
7847 quantize_info;
7848
7849 /*
7850 Image has more colors than the visual supports.
7851 */
7852 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007853 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007854 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007855 }
7856 /*
7857 Free previous and create new colormap.
7858 */
7859 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7860 colormap=XDefaultColormap(display,visual_info->screen);
7861 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7862 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7863 visual_info->visual,visual_info->klass == DirectColor ?
7864 AllocAll : AllocNone);
7865 if (colormap == (Colormap) NULL)
7866 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7867 image->filename);
7868 /*
7869 Initialize the map and pixel info structures.
7870 */
7871 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007872 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007873 /*
7874 Allocating colors in server colormap is based on visual class.
7875 */
7876 switch (visual_info->klass)
7877 {
7878 case StaticGray:
7879 case StaticColor:
7880 {
7881 /*
7882 Define Standard Colormap for StaticGray or StaticColor visual.
7883 */
7884 number_colors=image->colors;
7885 colors=(XColor *) AcquireQuantumMemory((size_t)
7886 visual_info->colormap_size,sizeof(*colors));
7887 if (colors == (XColor *) NULL)
7888 ThrowXWindowFatalException(ResourceLimitFatalError,
7889 "UnableToCreateColormap",image->filename);
7890 p=colors;
7891 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007892 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007893 {
7894 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7895 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7896 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7897 if (visual_info->klass != StaticColor)
7898 {
7899 gray_value=(unsigned short) XPixelIntensity(&color);
7900 color.red=gray_value;
7901 color.green=gray_value;
7902 color.blue=gray_value;
7903 }
7904 status=XAllocColor(display,colormap,&color);
7905 if (status == False)
7906 {
7907 colormap=XCopyColormapAndFree(display,colormap);
7908 (void) XAllocColor(display,colormap,&color);
7909 }
7910 pixel->pixels[i]=color.pixel;
7911 *p++=color;
7912 }
7913 break;
7914 }
7915 case GrayScale:
7916 case PseudoColor:
7917 {
7918 unsigned int
7919 colormap_type;
7920
7921 /*
7922 Define Standard Colormap for GrayScale or PseudoColor visual.
7923 */
7924 number_colors=image->colors;
7925 colors=(XColor *) AcquireQuantumMemory((size_t)
7926 visual_info->colormap_size,sizeof(*colors));
7927 if (colors == (XColor *) NULL)
7928 ThrowXWindowFatalException(ResourceLimitFatalError,
7929 "UnableToCreateColormap",image->filename);
7930 /*
7931 Preallocate our GUI colors.
7932 */
7933 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7934 (void) XAllocColor(display,colormap,&pixel->background_color);
7935 (void) XAllocColor(display,colormap,&pixel->border_color);
7936 (void) XAllocColor(display,colormap,&pixel->matte_color);
7937 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7938 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7939 (void) XAllocColor(display,colormap,&pixel->depth_color);
7940 (void) XAllocColor(display,colormap,&pixel->trough_color);
7941 for (i=0; i < MaxNumberPens; i++)
7942 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7943 /*
7944 Determine if image colors will "fit" into X server colormap.
7945 */
7946 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007947 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007948 NULL,0,pixel->pixels,(unsigned int) image->colors);
7949 if (status != False)
7950 colormap_type=PrivateColormap;
7951 if (colormap_type == SharedColormap)
7952 {
cristyc57f6942010-11-12 01:47:39 +00007953 CacheView
7954 *image_view;
7955
cristy3ed852e2009-09-05 21:47:34 +00007956 DiversityPacket
7957 *diversity;
7958
7959 int
7960 y;
7961
7962 register int
7963 x;
7964
7965 unsigned short
7966 index;
7967
7968 XColor
7969 *server_colors;
7970
7971 /*
7972 Define Standard colormap for shared GrayScale or PseudoColor visual.
7973 */
7974 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7975 sizeof(*diversity));
7976 if (diversity == (DiversityPacket *) NULL)
7977 ThrowXWindowFatalException(ResourceLimitFatalError,
7978 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007979 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007980 {
cristye42f6582012-02-11 17:59:50 +00007981 diversity[i].red=ClampToQuantum(image->colormap[i].red);
7982 diversity[i].green=ClampToQuantum(image->colormap[i].green);
7983 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00007984 diversity[i].index=(unsigned short) i;
7985 diversity[i].count=0;
7986 }
cristy46ff2672012-12-14 15:32:26 +00007987 image_view=AcquireAuthenticCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007988 for (y=0; y < (int) image->rows; y++)
7989 {
cristyc57f6942010-11-12 01:47:39 +00007990 register int
cristy3ed852e2009-09-05 21:47:34 +00007991 x;
7992
cristy4c08aed2011-07-01 19:47:50 +00007993 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007994 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007995
cristyc57f6942010-11-12 01:47:39 +00007996 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7997 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007998 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007999 break;
cristyc57f6942010-11-12 01:47:39 +00008000 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008001 {
8002 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008003 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008004 }
cristy3ed852e2009-09-05 21:47:34 +00008005 }
cristyc57f6942010-11-12 01:47:39 +00008006 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008007 /*
8008 Sort colors by decreasing intensity.
8009 */
8010 qsort((void *) diversity,image->colors,sizeof(*diversity),
8011 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008012 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008013 {
8014 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008015 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008016 }
8017 diversity[image->colors-1].count<<=4;
8018 qsort((void *) diversity,image->colors,sizeof(*diversity),
8019 PopularityCompare);
8020 /*
8021 Allocate colors.
8022 */
8023 p=colors;
8024 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008025 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008026 {
8027 index=diversity[i].index;
8028 color.red=
8029 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8030 color.green=
8031 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8032 color.blue=
8033 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8034 if (visual_info->klass != PseudoColor)
8035 {
8036 gray_value=(unsigned short) XPixelIntensity(&color);
8037 color.red=gray_value;
8038 color.green=gray_value;
8039 color.blue=gray_value;
8040 }
8041 status=XAllocColor(display,colormap,&color);
8042 if (status == False)
8043 break;
8044 pixel->pixels[index]=color.pixel;
8045 *p++=color;
8046 }
8047 /*
8048 Read X server colormap.
8049 */
8050 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8051 visual_info->colormap_size,sizeof(*server_colors));
8052 if (server_colors == (XColor *) NULL)
8053 ThrowXWindowFatalException(ResourceLimitFatalError,
8054 "UnableToCreateColormap",image->filename);
8055 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008056 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008057 (void) XQueryColors(display,colormap,server_colors,
8058 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8059 /*
8060 Select remaining colors from X server colormap.
8061 */
cristybb503372010-05-27 20:51:26 +00008062 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008063 {
8064 index=diversity[i].index;
cristy534d0a32013-04-13 16:27:24 +00008065 color.red=ScaleQuantumToShort(
8066 XRedGamma(image->colormap[index].red));
8067 color.green=ScaleQuantumToShort(
8068 XGreenGamma(image->colormap[index].green));
8069 color.blue=ScaleQuantumToShort(
8070 XBlueGamma(image->colormap[index].blue));
cristy3ed852e2009-09-05 21:47:34 +00008071 if (visual_info->klass != PseudoColor)
8072 {
8073 gray_value=(unsigned short) XPixelIntensity(&color);
8074 color.red=gray_value;
8075 color.green=gray_value;
8076 color.blue=gray_value;
8077 }
8078 XBestPixel(display,colormap,server_colors,(unsigned int)
8079 visual_info->colormap_size,&color);
8080 pixel->pixels[index]=color.pixel;
8081 *p++=color;
8082 }
8083 if ((int) image->colors < visual_info->colormap_size)
8084 {
8085 /*
8086 Fill up colors array-- more choices for pen colors.
8087 */
8088 retain_colors=MagickMin((unsigned int)
8089 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008090 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008091 *p++=server_colors[i];
8092 number_colors+=retain_colors;
8093 }
8094 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8095 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8096 break;
8097 }
8098 /*
8099 Define Standard colormap for private GrayScale or PseudoColor visual.
8100 */
8101 if (status == False)
8102 {
8103 /*
8104 Not enough colormap entries in the colormap-- Create a new colormap.
8105 */
8106 colormap=XCreateColormap(display,
8107 XRootWindow(display,visual_info->screen),visual_info->visual,
8108 AllocNone);
8109 if (colormap == (Colormap) NULL)
8110 ThrowXWindowFatalException(ResourceLimitFatalError,
8111 "UnableToCreateColormap",image->filename);
8112 map_info->colormap=colormap;
8113 if ((int) image->colors < visual_info->colormap_size)
8114 {
8115 /*
8116 Retain colors from the default colormap to help lessens the
8117 effects of colormap flashing.
8118 */
8119 retain_colors=MagickMin((unsigned int)
8120 (visual_info->colormap_size-image->colors),256);
8121 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008122 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008123 {
cristyc57f6942010-11-12 01:47:39 +00008124 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008125 p++;
8126 }
8127 (void) XQueryColors(display,
8128 XDefaultColormap(display,visual_info->screen),
8129 colors+image->colors,(int) retain_colors);
8130 /*
8131 Transfer colors from default to private colormap.
8132 */
8133 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008134 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008135 retain_colors);
8136 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008137 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008138 {
8139 p->pixel=pixel->pixels[i];
8140 p++;
8141 }
8142 (void) XStoreColors(display,colormap,colors+image->colors,
8143 (int) retain_colors);
8144 number_colors+=retain_colors;
8145 }
8146 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008147 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008148 image->colors);
8149 }
8150 /*
8151 Store the image colormap.
8152 */
8153 p=colors;
8154 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008155 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008156 {
8157 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8158 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8159 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8160 if (visual_info->klass != PseudoColor)
8161 {
8162 gray_value=(unsigned short) XPixelIntensity(&color);
8163 color.red=gray_value;
8164 color.green=gray_value;
8165 color.blue=gray_value;
8166 }
8167 color.pixel=pixel->pixels[i];
8168 *p++=color;
8169 }
8170 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8171 break;
8172 }
8173 case TrueColor:
8174 case DirectColor:
8175 default:
8176 {
8177 MagickBooleanType
8178 linear_colormap;
8179
8180 /*
8181 Define Standard Colormap for TrueColor or DirectColor visual.
8182 */
8183 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8184 (map_info->green_max*map_info->green_mult)+
8185 (map_info->blue_max*map_info->blue_mult)+1);
8186 linear_colormap=(number_colors > 4096) ||
8187 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8188 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8189 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8190 MagickTrue : MagickFalse;
8191 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008192 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008193 /*
8194 Allocate color array.
8195 */
8196 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8197 if (colors == (XColor *) NULL)
8198 ThrowXWindowFatalException(ResourceLimitFatalError,
8199 "UnableToCreateColormap",image->filename);
8200 /*
8201 Initialize linear color ramp.
8202 */
8203 p=colors;
8204 color.flags=(char) (DoRed | DoGreen | DoBlue);
8205 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008206 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008207 {
8208 color.blue=(unsigned short) 0;
8209 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008210 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008211 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8212 color.green=color.blue;
8213 color.red=color.blue;
8214 color.pixel=XStandardPixel(map_info,&color);
8215 *p++=color;
8216 }
8217 else
cristybb503372010-05-27 20:51:26 +00008218 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008219 {
8220 color.red=(unsigned short) 0;
8221 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008222 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008223 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8224 color.green=(unsigned int) 0;
8225 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008226 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008227 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8228 map_info->green_max));
8229 color.blue=(unsigned short) 0;
8230 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008231 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008232 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8233 color.pixel=XStandardPixel(map_info,&color);
8234 *p++=color;
8235 }
8236 if ((visual_info->klass == DirectColor) &&
8237 (colormap != XDefaultColormap(display,visual_info->screen)))
8238 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8239 else
cristybb503372010-05-27 20:51:26 +00008240 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008241 (void) XAllocColor(display,colormap,&colors[i]);
8242 break;
8243 }
8244 }
8245 if ((visual_info->klass != DirectColor) &&
8246 (visual_info->klass != TrueColor))
8247 {
8248 /*
8249 Set foreground, background, border, etc. pixels.
8250 */
8251 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8252 &pixel->foreground_color);
8253 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8254 &pixel->background_color);
8255 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8256 {
8257 /*
8258 Foreground and background colors must differ.
8259 */
8260 pixel->background_color.red=(~pixel->foreground_color.red);
8261 pixel->background_color.green=
8262 (~pixel->foreground_color.green);
8263 pixel->background_color.blue=
8264 (~pixel->foreground_color.blue);
8265 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8266 &pixel->background_color);
8267 }
8268 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8269 &pixel->border_color);
8270 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8271 &pixel->matte_color);
8272 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8273 &pixel->highlight_color);
8274 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8275 &pixel->shadow_color);
8276 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8277 &pixel->depth_color);
8278 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8279 &pixel->trough_color);
8280 for (i=0; i < MaxNumberPens; i++)
8281 {
8282 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8283 &pixel->pen_colors[i]);
8284 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8285 }
cristyc57f6942010-11-12 01:47:39 +00008286 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008287 }
8288 colors=(XColor *) RelinquishMagickMemory(colors);
8289 if (IsEventLogging())
8290 {
8291 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8292 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8293 map_info->colormap);
8294 (void) LogMagickEvent(X11Event,GetMagickModule(),
8295 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8296 map_info->green_max,map_info->blue_max);
8297 (void) LogMagickEvent(X11Event,GetMagickModule(),
8298 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8299 map_info->green_mult,map_info->blue_mult);
8300 }
8301}
8302
8303/*
8304%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8305% %
8306% %
8307% %
8308% X M a k e W i n d o w %
8309% %
8310% %
8311% %
8312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8313%
8314% XMakeWindow() creates an X11 window.
8315%
8316% The format of the XMakeWindow method is:
8317%
8318% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8319% XClassHint *class_hint,XWMHints *manager_hints,
8320% XWindowInfo *window_info)
8321%
8322% A description of each parameter follows:
8323%
8324% o display: Specifies a connection to an X server; returned from
8325% XOpenDisplay.
8326%
8327% o parent: Specifies the parent window_info.
8328%
8329% o argv: Specifies the application's argument list.
8330%
8331% o argc: Specifies the number of arguments.
8332%
8333% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8334%
8335% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8336%
8337% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8338%
8339*/
cristybcbda3f2011-09-03 13:01:22 +00008340MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008341 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8342 XWindowInfo *window_info)
8343{
8344#define MinWindowSize 64
8345
8346 Atom
8347 atom_list[2];
8348
8349 int
8350 gravity;
8351
8352 static XTextProperty
8353 icon_name,
8354 window_name;
8355
8356 Status
8357 status;
8358
8359 XSizeHints
8360 *size_hints;
8361
8362 /*
8363 Set window info hints.
8364 */
8365 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8366 assert(display != (Display *) NULL);
8367 assert(window_info != (XWindowInfo *) NULL);
8368 size_hints=XAllocSizeHints();
8369 if (size_hints == (XSizeHints *) NULL)
8370 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008371 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008372 size_hints->x=window_info->x;
8373 size_hints->y=window_info->y;
8374 size_hints->width=(int) window_info->width;
8375 size_hints->height=(int) window_info->height;
8376 if (window_info->immutable != MagickFalse)
8377 {
8378 /*
8379 Window size cannot be changed.
8380 */
8381 size_hints->min_width=size_hints->width;
8382 size_hints->min_height=size_hints->height;
8383 size_hints->max_width=size_hints->width;
8384 size_hints->max_height=size_hints->height;
8385 size_hints->flags|=PMinSize;
8386 size_hints->flags|=PMaxSize;
8387 }
8388 else
8389 {
8390 /*
8391 Window size can be changed.
8392 */
8393 size_hints->min_width=(int) window_info->min_width;
8394 size_hints->min_height=(int) window_info->min_height;
8395 size_hints->flags|=PResizeInc;
8396 size_hints->width_inc=(int) window_info->width_inc;
8397 size_hints->height_inc=(int) window_info->height_inc;
8398#if !defined(PRE_R4_ICCCM)
8399 size_hints->flags|=PBaseSize;
8400 size_hints->base_width=size_hints->width_inc;
8401 size_hints->base_height=size_hints->height_inc;
8402#endif
8403 }
8404 gravity=NorthWestGravity;
8405 if (window_info->geometry != (char *) NULL)
8406 {
8407 char
8408 default_geometry[MaxTextExtent],
8409 geometry[MaxTextExtent];
8410
8411 int
8412 flags;
8413
8414 register char
8415 *p;
8416
8417 /*
8418 User specified geometry.
8419 */
cristyb51dff52011-05-19 16:55:47 +00008420 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008421 size_hints->width,size_hints->height);
8422 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8423 p=geometry;
8424 while (strlen(p) != 0)
8425 {
8426 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8427 p++;
8428 else
8429 (void) CopyMagickString(p,p+1,MaxTextExtent);
8430 }
8431 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8432 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8433 &size_hints->width,&size_hints->height,&gravity);
8434 if ((flags & WidthValue) && (flags & HeightValue))
8435 size_hints->flags|=USSize;
8436 if ((flags & XValue) && (flags & YValue))
8437 {
8438 size_hints->flags|=USPosition;
8439 window_info->x=size_hints->x;
8440 window_info->y=size_hints->y;
8441 }
8442 }
8443#if !defined(PRE_R4_ICCCM)
8444 size_hints->win_gravity=gravity;
8445 size_hints->flags|=PWinGravity;
8446#endif
8447 if (window_info->id == (Window) NULL)
8448 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8449 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8450 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008451 window_info->visual,(unsigned long) window_info->mask,
8452 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008453 else
8454 {
8455 MagickStatusType
8456 mask;
8457
8458 XEvent
8459 sans_event;
8460
8461 XWindowChanges
8462 window_changes;
8463
8464 /*
8465 Window already exists; change relevant attributes.
8466 */
cristyc57f6942010-11-12 01:47:39 +00008467 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8468 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008469 mask=ConfigureNotify;
8470 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8471 window_changes.x=window_info->x;
8472 window_changes.y=window_info->y;
8473 window_changes.width=(int) window_info->width;
8474 window_changes.height=(int) window_info->height;
8475 mask=(MagickStatusType) (CWWidth | CWHeight);
8476 if (window_info->flags & USPosition)
8477 mask|=CWX | CWY;
8478 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8479 mask,&window_changes);
8480 }
8481 if (window_info->id == (Window) NULL)
8482 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8483 window_info->name);
8484 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8485 if (status == False)
8486 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8487 window_info->name);
8488 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8489 if (status == False)
8490 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8491 window_info->icon_name);
8492 if (window_info->icon_geometry != (char *) NULL)
8493 {
8494 int
8495 flags,
8496 height,
8497 width;
8498
8499 /*
8500 User specified icon geometry.
8501 */
8502 size_hints->flags|=USPosition;
8503 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8504 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8505 &manager_hints->icon_y,&width,&height,&gravity);
8506 if ((flags & XValue) && (flags & YValue))
8507 manager_hints->flags|=IconPositionHint;
8508 }
8509 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8510 size_hints,manager_hints,class_hint);
8511 if (window_name.value != (void *) NULL)
8512 {
8513 (void) XFree((void *) window_name.value);
8514 window_name.value=(unsigned char *) NULL;
8515 window_name.nitems=0;
8516 }
8517 if (icon_name.value != (void *) NULL)
8518 {
8519 (void) XFree((void *) icon_name.value);
8520 icon_name.value=(unsigned char *) NULL;
8521 icon_name.nitems=0;
8522 }
8523 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8524 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8525 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8526 (void) XFree((void *) size_hints);
8527 if (window_info->shape != MagickFalse)
8528 {
8529#if defined(MAGICKCORE_HAVE_SHAPE)
8530 int
8531 error_base,
8532 event_base;
8533
8534 /*
8535 Can we apply a non-rectangular shaping mask?
8536 */
8537 error_base=0;
8538 event_base=0;
8539 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8540 window_info->shape=MagickFalse;
8541#else
8542 window_info->shape=MagickFalse;
8543#endif
8544 }
8545 if (window_info->shared_memory)
8546 {
8547#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8548 /*
8549 Can we use shared memory with this window?
8550 */
8551 if (XShmQueryExtension(display) == 0)
8552 window_info->shared_memory=MagickFalse;
8553#else
8554 window_info->shared_memory=MagickFalse;
8555#endif
8556 }
8557 window_info->image=NewImageList();
8558 window_info->destroy=MagickFalse;
8559}
8560
8561/*
8562%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8563% %
8564% %
8565% %
8566% X M a g i c k P r o g r e s s M o n i t o r %
8567% %
8568% %
8569% %
8570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8571%
8572% XMagickProgressMonitor() displays the progress a task is making in
8573% completing a task.
8574%
8575% The format of the XMagickProgressMonitor method is:
8576%
8577% void XMagickProgressMonitor(const char *task,
8578% const MagickOffsetType quantum,const MagickSizeType span,
8579% void *client_data)
8580%
8581% A description of each parameter follows:
8582%
8583% o task: Identifies the task in progress.
8584%
8585% o quantum: Specifies the quantum position within the span which represents
8586% how much progress has been made in completing a task.
8587%
8588% o span: Specifies the span relative to completing a task.
8589%
8590% o client_data: Pointer to any client data.
8591%
8592*/
8593
8594static const char *GetLocaleMonitorMessage(const char *text)
8595{
8596 char
8597 message[MaxTextExtent],
8598 tag[MaxTextExtent];
8599
8600 const char
8601 *locale_message;
8602
8603 register char
8604 *p;
8605
8606 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8607 p=strrchr(tag,'/');
8608 if (p != (char *) NULL)
8609 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008610 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008611 locale_message=GetLocaleMessage(message);
8612 if (locale_message == message)
8613 return(text);
8614 return(locale_message);
8615}
8616
cristybcbda3f2011-09-03 13:01:22 +00008617MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008618 const MagickOffsetType quantum,const MagickSizeType span,
8619 void *magick_unused(client_data))
8620{
8621 XWindows
8622 *windows;
8623
8624 windows=XSetWindows((XWindows *) ~0);
8625 if (windows == (XWindows *) NULL)
8626 return(MagickTrue);
8627 if (windows->info.mapped != MagickFalse)
8628 XProgressMonitorWidget(windows->display,windows,
8629 GetLocaleMonitorMessage(tag),quantum,span);
8630 return(MagickTrue);
8631}
8632
8633/*
8634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8635% %
8636% %
8637% %
8638% X Q u e r y C o l o r D a t a b a s e %
8639% %
8640% %
8641% %
8642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8643%
cristy9950d572011-10-01 18:22:35 +00008644% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008645% string.
8646%
8647% The format of the XQueryColorDatabase method is:
8648%
cristy9950d572011-10-01 18:22:35 +00008649% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008650%
8651% A description of each parameter follows:
8652%
8653% o target: Specifies the color to lookup in the X color database.
8654%
cristy101ab702011-10-13 13:06:32 +00008655% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008656% color is returned as this value.
8657%
8658*/
cristy9950d572011-10-01 18:22:35 +00008659MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008660 XColor *color)
8661{
8662 Colormap
8663 colormap;
8664
8665 static Display
8666 *display = (Display *) NULL;
8667
8668 Status
8669 status;
8670
8671 XColor
8672 xcolor;
8673
8674 /*
8675 Initialize color return value.
8676 */
8677 assert(color != (XColor *) NULL);
8678 color->red=0;
8679 color->green=0;
8680 color->blue=0;
8681 color->flags=(char) (DoRed | DoGreen | DoBlue);
8682 if ((target == (char *) NULL) || (*target == '\0'))
8683 target="#ffffffffffff";
8684 /*
8685 Let the X server define the color for us.
8686 */
8687 if (display == (Display *) NULL)
8688 display=XOpenDisplay((char *) NULL);
8689 if (display == (Display *) NULL)
8690 {
cristyc38fbf52013-11-03 13:55:54 +00008691 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target);
cristy3ed852e2009-09-05 21:47:34 +00008692 return(MagickFalse);
8693 }
8694 colormap=XDefaultColormap(display,XDefaultScreen(display));
8695 status=XParseColor(display,colormap,(char *) target,&xcolor);
8696 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00008697 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target)
cristy3ed852e2009-09-05 21:47:34 +00008698 else
8699 {
8700 color->red=xcolor.red;
8701 color->green=xcolor.green;
8702 color->blue=xcolor.blue;
8703 color->flags=xcolor.flags;
8704 }
8705 return(status != False ? MagickTrue : MagickFalse);
8706}
8707
8708/*
8709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8710% %
8711% %
8712% %
8713% X Q u e r y P o s i t i o n %
8714% %
8715% %
8716% %
8717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8718%
8719% XQueryPosition() gets the pointer coordinates relative to a window.
8720%
8721% The format of the XQueryPosition method is:
8722%
8723% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8724%
8725% A description of each parameter follows:
8726%
8727% o display: Specifies a connection to an X server; returned from
8728% XOpenDisplay.
8729%
8730% o window: Specifies a pointer to a Window.
8731%
8732% o x: Return the x coordinate of the pointer relative to the origin of the
8733% window.
8734%
8735% o y: Return the y coordinate of the pointer relative to the origin of the
8736% window.
8737%
8738*/
cristy534d0a32013-04-13 16:27:24 +00008739MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,
8740 int *y)
cristy3ed852e2009-09-05 21:47:34 +00008741{
8742 int
8743 x_root,
8744 y_root;
8745
8746 unsigned int
8747 mask;
8748
8749 Window
8750 root_window;
8751
8752 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8753 assert(display != (Display *) NULL);
8754 assert(window != (Window) NULL);
8755 assert(x != (int *) NULL);
8756 assert(y != (int *) NULL);
8757 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8758 x,y,&mask);
8759}
8760
8761/*
8762%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8763% %
8764% %
8765% %
8766% X R e f r e s h W i n d o w %
8767% %
8768% %
8769% %
8770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8771%
8772% XRefreshWindow() refreshes an image in a X window.
8773%
8774% The format of the XRefreshWindow method is:
8775%
8776% void XRefreshWindow(Display *display,const XWindowInfo *window,
8777% const XEvent *event)
8778%
8779% A description of each parameter follows:
8780%
8781% o display: Specifies a connection to an X server; returned from
8782% XOpenDisplay.
8783%
8784% o window: Specifies a pointer to a XWindowInfo structure.
8785%
8786% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8787% the entire image is refreshed.
8788%
8789*/
cristybcbda3f2011-09-03 13:01:22 +00008790MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008791 const XEvent *event)
8792{
8793 int
8794 x,
8795 y;
8796
8797 unsigned int
8798 height,
8799 width;
8800
8801 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8802 assert(display != (Display *) NULL);
8803 assert(window != (XWindowInfo *) NULL);
8804 if (window->ximage == (XImage *) NULL)
8805 return;
8806 if (event != (XEvent *) NULL)
8807 {
8808 /*
8809 Determine geometry from expose event.
8810 */
8811 x=event->xexpose.x;
8812 y=event->xexpose.y;
8813 width=(unsigned int) event->xexpose.width;
8814 height=(unsigned int) event->xexpose.height;
8815 }
8816 else
8817 {
8818 XEvent
8819 sans_event;
8820
8821 /*
8822 Refresh entire window; discard outstanding expose events.
8823 */
8824 x=0;
8825 y=0;
8826 width=window->width;
8827 height=window->height;
8828 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008829 if (window->matte_pixmap != (Pixmap) NULL)
8830 {
8831#if defined(MAGICKCORE_HAVE_SHAPE)
8832 if (window->shape != MagickFalse)
8833 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8834 window->matte_pixmap,ShapeSet);
8835#endif
8836 }
cristy3ed852e2009-09-05 21:47:34 +00008837 }
8838 /*
8839 Check boundary conditions.
8840 */
8841 if ((window->ximage->width-(x+window->x)) < (int) width)
8842 width=(unsigned int) (window->ximage->width-(x+window->x));
8843 if ((window->ximage->height-(y+window->y)) < (int) height)
8844 height=(unsigned int) (window->ximage->height-(y+window->y));
8845 /*
8846 Refresh image.
8847 */
8848 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008849 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008850 if (window->pixmap != (Pixmap) NULL)
8851 {
8852 if (window->depth > 1)
8853 (void) XCopyArea(display,window->pixmap,window->id,
8854 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8855 else
8856 (void) XCopyPlane(display,window->pixmap,window->id,
8857 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8858 1L);
8859 }
8860 else
8861 {
8862#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8863 if (window->shared_memory)
8864 (void) XShmPutImage(display,window->id,window->annotate_context,
8865 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8866#endif
8867 if (window->shared_memory == MagickFalse)
8868 (void) XPutImage(display,window->id,window->annotate_context,
8869 window->ximage,x+window->x,y+window->y,x,y,width,height);
8870 }
8871 if (window->matte_pixmap != (Pixmap) NULL)
8872 (void) XSetClipMask(display,window->annotate_context,None);
8873 (void) XFlush(display);
8874}
8875
8876/*
8877%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8878% %
8879% %
8880% %
8881% X R e m o t e C o m m a n d %
8882% %
8883% %
8884% %
8885%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8886%
8887% XRemoteCommand() forces a remote display(1) to display the specified
8888% image filename.
8889%
8890% The format of the XRemoteCommand method is:
8891%
8892% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8893% const char *filename)
8894%
8895% A description of each parameter follows:
8896%
8897% o display: Specifies a connection to an X server; returned from
8898% XOpenDisplay.
8899%
8900% o window: Specifies the name or id of an X window.
8901%
8902% o filename: the name of the image filename to display.
8903%
8904*/
8905MagickExport MagickBooleanType XRemoteCommand(Display *display,
8906 const char *window,const char *filename)
8907{
8908 Atom
8909 remote_atom;
8910
8911 Window
8912 remote_window,
8913 root_window;
8914
8915 assert(filename != (char *) NULL);
8916 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8917 if (display == (Display *) NULL)
8918 display=XOpenDisplay((char *) NULL);
8919 if (display == (Display *) NULL)
8920 {
8921 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8922 return(MagickFalse);
8923 }
8924 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8925 remote_window=(Window) NULL;
8926 root_window=XRootWindow(display,XDefaultScreen(display));
8927 if (window != (char *) NULL)
8928 {
8929 /*
8930 Search window hierarchy and identify any clients by name or ID.
8931 */
8932 if (isdigit((unsigned char) *window) != 0)
8933 remote_window=XWindowByID(display,root_window,(Window)
8934 strtol((char *) window,(char **) NULL,0));
8935 if (remote_window == (Window) NULL)
8936 remote_window=XWindowByName(display,root_window,window);
8937 }
8938 if (remote_window == (Window) NULL)
8939 remote_window=XWindowByProperty(display,root_window,remote_atom);
8940 if (remote_window == (Window) NULL)
8941 {
8942 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8943 filename);
8944 return(MagickFalse);
8945 }
8946 /*
8947 Send remote command.
8948 */
8949 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8950 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8951 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8952 (void) XSync(display,MagickFalse);
8953 return(MagickTrue);
8954}
8955
8956/*
8957%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8958% %
8959% %
8960% %
cristy534d0a32013-04-13 16:27:24 +00008961% X R e n d e r I m a g e %
8962% %
8963% %
8964% %
8965%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8966%
8967% XRenderImage() renders text on the image with an X11 font. It also returns
8968% the bounding box of the text relative to the image.
8969%
8970% The format of the XRenderImage method is:
8971%
8972% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
8973% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
8974%
8975% A description of each parameter follows:
8976%
8977% o image: the image.
8978%
8979% o draw_info: the draw info.
8980%
8981% o offset: (x,y) location of text relative to image.
8982%
8983% o metrics: bounding box of text.
8984%
8985% o exception: return any errors or warnings in this structure.
8986%
8987*/
8988MagickPrivate MagickBooleanType XRenderImage(Image *image,
8989 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
8990 ExceptionInfo *exception)
8991{
8992 const char
8993 *client_name;
8994
8995 DrawInfo
8996 cache_info;
8997
8998 Display
8999 *display;
9000
9001 ImageInfo
9002 *image_info;
9003
9004 MagickBooleanType
9005 status;
9006
9007 size_t
9008 height,
9009 width;
9010
9011 XAnnotateInfo
9012 annotate_info;
9013
9014 XFontStruct
9015 *font_info;
9016
9017 XPixelInfo
9018 pixel;
9019
9020 XResourceInfo
9021 resource_info;
9022
9023 XrmDatabase
9024 resource_database;
9025
9026 XStandardColormap
9027 *map_info;
9028
9029 XVisualInfo
9030 *visual_info;
9031
9032 /*
9033 Open X server connection.
9034 */
9035 display=XOpenDisplay(draw_info->server_name);
9036 if (display == (Display *) NULL)
9037 {
9038 ThrowXWindowException(XServerError,"UnableToOpenXServer",
9039 draw_info->server_name);
9040 return(MagickFalse);
9041 }
9042 /*
9043 Get user defaults from X resource database.
9044 */
9045 (void) XSetErrorHandler(XError);
9046 image_info=AcquireImageInfo();
9047 client_name=GetClientName();
9048 resource_database=XGetResourceDatabase(display,client_name);
9049 XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
9050 resource_info.close_server=MagickFalse;
9051 resource_info.colormap=PrivateColormap;
9052 resource_info.font=AcquireString(draw_info->font);
9053 resource_info.background_color=AcquireString("#ffffffffffff");
9054 resource_info.foreground_color=AcquireString("#000000000000");
9055 map_info=XAllocStandardColormap();
9056 if (map_info == (XStandardColormap *) NULL)
9057 {
9058 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9059 image->filename);
9060 return(MagickFalse);
9061 }
9062 /*
9063 Initialize visual info.
9064 */
9065 visual_info=XBestVisualInfo(display,map_info,&resource_info);
9066 if (visual_info == (XVisualInfo *) NULL)
9067 {
cristyc38fbf52013-11-03 13:55:54 +00009068 ThrowXWindowException(XServerError,"UnableToGetVisual",image->filename);
cristy534d0a32013-04-13 16:27:24 +00009069 return(MagickFalse);
9070 }
9071 map_info->colormap=(Colormap) NULL;
9072 pixel.pixels=(unsigned long *) NULL;
9073 /*
9074 Initialize Standard Colormap info.
9075 */
9076 XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
9077 map_info);
9078 XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
9079 &pixel);
9080 pixel.annotate_context=XDefaultGC(display,visual_info->screen);
9081 /*
9082 Initialize font info.
9083 */
9084 font_info=XBestFont(display,&resource_info,MagickFalse);
9085 if (font_info == (XFontStruct *) NULL)
9086 {
9087 ThrowXWindowException(XServerError,"UnableToLoadFont",draw_info->font);
9088 return(MagickFalse);
9089 }
9090 if ((map_info == (XStandardColormap *) NULL) ||
9091 (visual_info == (XVisualInfo *) NULL) ||
9092 (font_info == (XFontStruct *) NULL))
9093 {
9094 XFreeResources(display,visual_info,map_info,&pixel,font_info,
9095 &resource_info,(XWindowInfo *) NULL);
9096 ThrowXWindowException(XServerError,"UnableToLoadFont",image->filename);
9097 return(MagickFalse);
9098 }
9099 cache_info=(*draw_info);
9100 /*
9101 Initialize annotate info.
9102 */
9103 XGetAnnotateInfo(&annotate_info);
9104 annotate_info.stencil=ForegroundStencil;
9105 if (cache_info.font != draw_info->font)
9106 {
9107 /*
9108 Type name has changed.
9109 */
9110 (void) XFreeFont(display,font_info);
9111 (void) CloneString(&resource_info.font,draw_info->font);
9112 font_info=XBestFont(display,&resource_info,MagickFalse);
9113 if (font_info == (XFontStruct *) NULL)
9114 {
9115 ThrowXWindowException(XServerError,"UnableToLoadFont",
9116 draw_info->font);
9117 return(MagickFalse);
9118 }
9119 }
9120 if (image->debug != MagickFalse)
9121 (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
9122 "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
9123 draw_info->font : "none",draw_info->pointsize);
9124 cache_info=(*draw_info);
9125 annotate_info.font_info=font_info;
9126 annotate_info.text=(char *) draw_info->text;
9127 annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
9128 strlen(draw_info->text));
9129 annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
9130 metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
9131 metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
9132 metrics->ascent=(double) font_info->ascent+4;
9133 metrics->descent=(double) (-font_info->descent);
9134 metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
9135 metrics->height=font_info->ascent+font_info->descent;
9136 metrics->max_advance=(double) font_info->max_bounds.width;
9137 metrics->bounds.x1=0.0;
9138 metrics->bounds.y1=metrics->descent;
9139 metrics->bounds.x2=metrics->ascent+metrics->descent;
9140 metrics->bounds.y2=metrics->ascent+metrics->descent;
9141 metrics->underline_position=(-2.0);
9142 metrics->underline_thickness=1.0;
9143 if (draw_info->render == MagickFalse)
9144 return(MagickTrue);
9145 if (draw_info->fill.alpha == TransparentAlpha)
9146 return(MagickTrue);
9147 /*
9148 Render fill color.
9149 */
9150 width=annotate_info.width;
9151 height=annotate_info.height;
9152 if ((fabs(draw_info->affine.rx) >= MagickEpsilon) ||
9153 (fabs(draw_info->affine.ry) >= MagickEpsilon))
9154 {
9155 if ((fabs(draw_info->affine.sx-draw_info->affine.sy) < MagickEpsilon) &&
9156 (fabs(draw_info->affine.rx+draw_info->affine.ry) < MagickEpsilon))
9157 annotate_info.degrees=(double) (180.0/MagickPI)*
9158 atan2(draw_info->affine.rx,draw_info->affine.sx);
9159 }
9160 (void) FormatLocaleString(annotate_info.geometry,MaxTextExtent,
9161 "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
9162 ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
9163 draw_info->interline_spacing-0.5));
9164 pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
9165 pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
9166 pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);
9167 status=XAnnotateImage(display,&pixel,&annotate_info,image,exception);
9168 if (status == 0)
9169 {
9170 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9171 image->filename);
9172 return(MagickFalse);
9173 }
9174 return(MagickTrue);
9175}
9176
9177/*
9178%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9179% %
9180% %
9181% %
cristy3ed852e2009-09-05 21:47:34 +00009182% X R e t a i n W i n d o w C o l o r s %
9183% %
9184% %
9185% %
9186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9187%
9188% XRetainWindowColors() sets X11 color resources on a window. This preserves
9189% the colors associated with an image displayed on the window.
9190%
9191% The format of the XRetainWindowColors method is:
9192%
9193% void XRetainWindowColors(Display *display,const Window window)
9194%
9195% A description of each parameter follows:
9196%
9197% o display: Specifies a connection to an X server; returned from
9198% XOpenDisplay.
9199%
9200% o window: Specifies a pointer to a XWindowInfo structure.
9201%
9202*/
9203MagickExport void XRetainWindowColors(Display *display,const Window window)
9204{
9205 Atom
9206 property;
9207
9208 Pixmap
9209 pixmap;
9210
9211 /*
9212 Put property on the window.
9213 */
9214 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9215 assert(display != (Display *) NULL);
9216 assert(window != (Window) NULL);
9217 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9218 if (property == (Atom) NULL)
9219 {
cristyc38fbf52013-11-03 13:55:54 +00009220 ThrowXWindowException(XServerError,"UnableToCreateProperty",
cristy3ed852e2009-09-05 21:47:34 +00009221 "_XSETROOT_ID");
9222 return;
9223 }
9224 pixmap=XCreatePixmap(display,window,1,1,1);
9225 if (pixmap == (Pixmap) NULL)
9226 {
cristyc38fbf52013-11-03 13:55:54 +00009227 ThrowXWindowException(XServerError,"UnableToCreateBitmap","");
cristy3ed852e2009-09-05 21:47:34 +00009228 return;
9229 }
9230 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9231 (unsigned char *) &pixmap,1);
9232 (void) XSetCloseDownMode(display,RetainPermanent);
9233}
9234
9235/*
9236%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9237% %
9238% %
9239% %
9240% X S e l e c t W i n d o w %
9241% %
9242% %
9243% %
9244%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9245%
9246% XSelectWindow() allows a user to select a window using the mouse. If the
9247% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9248% is returned in the crop_info structure.
9249%
9250% The format of the XSelectWindow function is:
9251%
9252% target_window=XSelectWindow(display,crop_info)
9253%
9254% A description of each parameter follows:
9255%
9256% o window: XSelectWindow returns the window id.
9257%
9258% o display: Specifies a pointer to the Display structure; returned from
9259% XOpenDisplay.
9260%
9261% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9262% contains the extents of any cropping rectangle.
9263%
cristy3ed852e2009-09-05 21:47:34 +00009264*/
9265static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9266{
9267#define MinimumCropArea (unsigned int) 9
9268
9269 Cursor
9270 target_cursor;
9271
9272 GC
9273 annotate_context;
9274
9275 int
9276 presses,
9277 x_offset,
9278 y_offset;
9279
9280 Status
9281 status;
9282
9283 Window
9284 root_window,
9285 target_window;
9286
9287 XEvent
9288 event;
9289
9290 XGCValues
9291 context_values;
9292
9293 /*
9294 Initialize graphic context.
9295 */
9296 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9297 assert(display != (Display *) NULL);
9298 assert(crop_info != (RectangleInfo *) NULL);
9299 root_window=XRootWindow(display,XDefaultScreen(display));
9300 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9301 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9302 context_values.function=GXinvert;
9303 context_values.plane_mask=
9304 context_values.background ^ context_values.foreground;
9305 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009306 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009307 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9308 if (annotate_context == (GC) NULL)
9309 return(MagickFalse);
9310 /*
9311 Grab the pointer using target cursor.
9312 */
9313 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9314 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9315 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9316 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9317 GrabModeAsync,root_window,target_cursor,CurrentTime);
9318 if (status != GrabSuccess)
9319 {
cristyc38fbf52013-11-03 13:55:54 +00009320 ThrowXWindowException(XServerError,"UnableToGrabMouse","");
cristy3ed852e2009-09-05 21:47:34 +00009321 return((Window) NULL);
9322 }
9323 /*
9324 Select a window.
9325 */
9326 crop_info->width=0;
9327 crop_info->height=0;
9328 presses=0;
9329 target_window=(Window) NULL;
9330 x_offset=0;
9331 y_offset=0;
9332 do
9333 {
9334 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9335 (void) XDrawRectangle(display,root_window,annotate_context,
9336 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9337 (unsigned int) crop_info->height-1);
9338 /*
9339 Allow another event.
9340 */
9341 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9342 (void) XWindowEvent(display,root_window,ButtonPressMask |
9343 ButtonReleaseMask | ButtonMotionMask,&event);
9344 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9345 (void) XDrawRectangle(display,root_window,annotate_context,
9346 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9347 (unsigned int) crop_info->height-1);
9348 switch (event.type)
9349 {
9350 case ButtonPress:
9351 {
9352 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9353 event.xbutton.x,event.xbutton.y);
9354 if (target_window == (Window) NULL)
9355 target_window=root_window;
9356 x_offset=event.xbutton.x_root;
9357 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009358 crop_info->x=(ssize_t) x_offset;
9359 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009360 crop_info->width=0;
9361 crop_info->height=0;
9362 presses++;
9363 break;
9364 }
9365 case ButtonRelease:
9366 {
9367 presses--;
9368 break;
9369 }
9370 case MotionNotify:
9371 {
9372 /*
9373 Discard pending button motion events.
9374 */
9375 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009376 crop_info->x=(ssize_t) event.xmotion.x;
9377 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009378 /*
9379 Check boundary conditions.
9380 */
9381 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009382 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009383 else
9384 {
cristyecd0ab52010-05-30 14:59:20 +00009385 crop_info->width=(size_t) (crop_info->x-x_offset);
9386 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009387 }
9388 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009389 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009390 else
9391 {
cristyecd0ab52010-05-30 14:59:20 +00009392 crop_info->height=(size_t) (crop_info->y-y_offset);
9393 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009394 }
9395 }
9396 default:
9397 break;
9398 }
9399 } while ((target_window == (Window) NULL) || (presses > 0));
9400 (void) XUngrabPointer(display,CurrentTime);
9401 (void) XFreeCursor(display,target_cursor);
9402 (void) XFreeGC(display,annotate_context);
9403 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9404 {
9405 crop_info->width=0;
9406 crop_info->height=0;
9407 }
9408 if ((crop_info->width != 0) && (crop_info->height != 0))
9409 target_window=root_window;
9410 return(target_window);
9411}
9412
9413/*
9414%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9415% %
9416% %
9417% %
9418% X S e t C u r s o r S t a t e %
9419% %
9420% %
9421% %
9422%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9423%
9424% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9425% reset to their default.
9426%
9427% The format of the XXSetCursorState method is:
9428%
9429% XSetCursorState(display,windows,const MagickStatusType state)
9430%
9431% A description of each parameter follows:
9432%
9433% o display: Specifies a connection to an X server; returned from
9434% XOpenDisplay.
9435%
9436% o windows: Specifies a pointer to a XWindows structure.
9437%
9438% o state: An unsigned integer greater than 0 sets the cursor state
9439% to busy, otherwise the cursor are reset to their default.
9440%
9441*/
cristybcbda3f2011-09-03 13:01:22 +00009442MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009443 const MagickStatusType state)
9444{
9445 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9446 assert(display != (Display *) NULL);
9447 assert(windows != (XWindows *) NULL);
9448 if (state)
9449 {
9450 (void) XCheckDefineCursor(display,windows->image.id,
9451 windows->image.busy_cursor);
9452 (void) XCheckDefineCursor(display,windows->pan.id,
9453 windows->pan.busy_cursor);
9454 (void) XCheckDefineCursor(display,windows->magnify.id,
9455 windows->magnify.busy_cursor);
9456 (void) XCheckDefineCursor(display,windows->command.id,
9457 windows->command.busy_cursor);
9458 }
9459 else
9460 {
9461 (void) XCheckDefineCursor(display,windows->image.id,
9462 windows->image.cursor);
9463 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9464 (void) XCheckDefineCursor(display,windows->magnify.id,
9465 windows->magnify.cursor);
9466 (void) XCheckDefineCursor(display,windows->command.id,
9467 windows->command.cursor);
9468 (void) XCheckDefineCursor(display,windows->command.id,
9469 windows->widget.cursor);
9470 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9471 }
9472 windows->info.mapped=MagickFalse;
9473}
9474
9475/*
9476%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9477% %
9478% %
9479% %
9480% X S e t W i n d o w s %
9481% %
9482% %
9483% %
9484%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9485%
9486% XSetWindows() sets the X windows structure if the windows info is specified.
9487% Otherwise the current windows structure is returned.
9488%
9489% The format of the XSetWindows method is:
9490%
9491% XWindows *XSetWindows(XWindows *windows_info)
9492%
9493% A description of each parameter follows:
9494%
9495% o windows_info: Initialize the Windows structure with this information.
9496%
9497*/
cristybcbda3f2011-09-03 13:01:22 +00009498MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009499{
9500 static XWindows
9501 *windows = (XWindows *) NULL;
9502
9503 if (windows_info != (XWindows *) ~0)
9504 {
9505 windows=(XWindows *) RelinquishMagickMemory(windows);
9506 windows=windows_info;
9507 }
9508 return(windows);
9509}
9510/*
9511%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9512% %
9513% %
9514% %
9515% X U s e r P r e f e r e n c e s %
9516% %
9517% %
9518% %
9519%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9520%
9521% XUserPreferences() saves the preferences in a configuration file in the
9522% users' home directory.
9523%
9524% The format of the XUserPreferences method is:
9525%
9526% void XUserPreferences(XResourceInfo *resource_info)
9527%
9528% A description of each parameter follows:
9529%
9530% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9531%
9532*/
cristybcbda3f2011-09-03 13:01:22 +00009533MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009534{
9535#if defined(X11_PREFERENCES_PATH)
9536 char
9537 cache[MaxTextExtent],
9538 filename[MaxTextExtent],
9539 specifier[MaxTextExtent];
9540
9541 const char
cristy104cea82009-10-25 02:26:51 +00009542 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009543 *value;
9544
9545 XrmDatabase
9546 preferences_database;
9547
9548 /*
9549 Save user preferences to the client configuration file.
9550 */
9551 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009552 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009553 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009554 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009555 value=resource_info->backdrop ? "True" : "False";
9556 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009557 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009558 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9559 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009560 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009561 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009562 value=resource_info->confirm_exit ? "True" : "False";
9563 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009564 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009565 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009566 value=resource_info->confirm_edit ? "True" : "False";
9567 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009568 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009569 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009570 value=resource_info->display_warnings ? "True" : "False";
9571 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009572 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristycbda6112012-05-27 20:57:16 +00009573 value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9574 "True" : "False";
cristy3ed852e2009-09-05 21:47:34 +00009575 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009576 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009577 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009578 value=resource_info->gamma_correct ? "True" : "False";
9579 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009580 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9581 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009582 resource_info->undo_cache);
9583 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009584 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009585 value=resource_info->use_pixmap ? "True" : "False";
9586 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009587 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009588 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009589 ExpandFilename(filename);
9590 XrmPutFileDatabase(preferences_database,filename);
9591#endif
9592}
9593
9594/*
9595%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9596% %
9597% %
9598% %
9599% X V i s u a l C l a s s N a m e %
9600% %
9601% %
9602% %
9603%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9604%
9605% XVisualClassName() returns the visual class name as a character string.
9606%
9607% The format of the XVisualClassName method is:
9608%
9609% char *XVisualClassName(const int visual_class)
9610%
9611% A description of each parameter follows:
9612%
9613% o visual_type: XVisualClassName returns the visual class as a character
9614% string.
9615%
9616% o class: Specifies the visual class.
9617%
cristy3ed852e2009-09-05 21:47:34 +00009618*/
9619static const char *XVisualClassName(const int visual_class)
9620{
9621 switch (visual_class)
9622 {
9623 case StaticGray: return("StaticGray");
9624 case GrayScale: return("GrayScale");
9625 case StaticColor: return("StaticColor");
9626 case PseudoColor: return("PseudoColor");
9627 case TrueColor: return("TrueColor");
9628 case DirectColor: return("DirectColor");
9629 }
9630 return("unknown visual class");
9631}
9632
9633/*
9634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9635% %
9636% %
9637% %
9638% X W a r n i n g %
9639% %
9640% %
9641% %
9642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9643%
9644% XWarning() displays a warning reason in a Notice widget.
9645%
9646% The format of the XWarning method is:
9647%
9648% void XWarning(const unsigned int warning,const char *reason,
9649% const char *description)
9650%
9651% A description of each parameter follows:
9652%
9653% o warning: Specifies the numeric warning category.
9654%
9655% o reason: Specifies the reason to display before terminating the
9656% program.
9657%
9658% o description: Specifies any description to the reason.
9659%
9660*/
cristybcbda3f2011-09-03 13:01:22 +00009661MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009662 const char *reason,const char *description)
9663{
9664 char
9665 text[MaxTextExtent];
9666
9667 XWindows
9668 *windows;
9669
9670 if (reason == (char *) NULL)
9671 return;
9672 (void) CopyMagickString(text,reason,MaxTextExtent);
9673 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9674 windows=XSetWindows((XWindows *) ~0);
9675 XNoticeWidget(windows->display,windows,text,(char *) description);
9676}
9677
9678/*
9679%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9680% %
9681% %
9682% %
9683% X W i n d o w B y I D %
9684% %
9685% %
9686% %
9687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9688%
9689% XWindowByID() locates a child window with a given ID. If not window with
9690% the given name is found, 0 is returned. Only the window specified and its
9691% subwindows are searched.
9692%
9693% The format of the XWindowByID function is:
9694%
9695% child=XWindowByID(display,window,id)
9696%
9697% A description of each parameter follows:
9698%
9699% o child: XWindowByID returns the window with the specified
9700% id. If no windows are found, XWindowByID returns 0.
9701%
9702% o display: Specifies a pointer to the Display structure; returned from
9703% XOpenDisplay.
9704%
9705% o id: Specifies the id of the window to locate.
9706%
9707*/
cristybcbda3f2011-09-03 13:01:22 +00009708MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009709 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009710{
9711 RectangleInfo
9712 rectangle_info;
9713
9714 register int
9715 i;
9716
9717 Status
9718 status;
9719
9720 unsigned int
9721 number_children;
9722
9723 Window
9724 child,
9725 *children,
9726 window;
9727
9728 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9729 assert(display != (Display *) NULL);
9730 assert(root_window != (Window) NULL);
9731 if (id == 0)
9732 return(XSelectWindow(display,&rectangle_info));
9733 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009734 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009735 status=XQueryTree(display,root_window,&child,&child,&children,
9736 &number_children);
9737 if (status == False)
9738 return((Window) NULL);
9739 window=(Window) NULL;
9740 for (i=0; i < (int) number_children; i++)
9741 {
9742 /*
9743 Search each child and their children.
9744 */
9745 window=XWindowByID(display,children[i],id);
9746 if (window != (Window) NULL)
9747 break;
9748 }
9749 if (children != (Window *) NULL)
9750 (void) XFree((void *) children);
9751 return(window);
9752}
9753
9754/*
9755%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9756% %
9757% %
9758% %
9759% X W i n d o w B y N a m e %
9760% %
9761% %
9762% %
9763%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9764%
9765% XWindowByName() locates a window with a given name on a display. If no
9766% window with the given name is found, 0 is returned. If more than one window
9767% has the given name, the first one is returned. Only root and its children
9768% are searched.
9769%
9770% The format of the XWindowByName function is:
9771%
9772% window=XWindowByName(display,root_window,name)
9773%
9774% A description of each parameter follows:
9775%
9776% o window: XWindowByName returns the window id.
9777%
9778% o display: Specifies a pointer to the Display structure; returned from
9779% XOpenDisplay.
9780%
9781% o root_window: Specifies the id of the root window.
9782%
9783% o name: Specifies the name of the window to locate.
9784%
9785*/
cristybcbda3f2011-09-03 13:01:22 +00009786MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009787 const char *name)
9788{
9789 register int
9790 i;
9791
9792 Status
9793 status;
9794
9795 unsigned int
9796 number_children;
9797
9798 Window
9799 *children,
9800 child,
9801 window;
9802
9803 XTextProperty
9804 window_name;
9805
9806 assert(display != (Display *) NULL);
9807 assert(root_window != (Window) NULL);
9808 assert(name != (char *) NULL);
9809 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9810 if (XGetWMName(display,root_window,&window_name) != 0)
9811 if (LocaleCompare((char *) window_name.value,name) == 0)
9812 return(root_window);
9813 status=XQueryTree(display,root_window,&child,&child,&children,
9814 &number_children);
9815 if (status == False)
9816 return((Window) NULL);
9817 window=(Window) NULL;
9818 for (i=0; i < (int) number_children; i++)
9819 {
9820 /*
9821 Search each child and their children.
9822 */
9823 window=XWindowByName(display,children[i],name);
9824 if (window != (Window) NULL)
9825 break;
9826 }
9827 if (children != (Window *) NULL)
9828 (void) XFree((void *) children);
9829 return(window);
9830}
9831
9832/*
9833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9834% %
9835% %
9836% %
9837% X W i n d o w B y P r o p e r y %
9838% %
9839% %
9840% %
9841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9842%
9843% XWindowByProperty() locates a child window with a given property. If not
9844% window with the given name is found, 0 is returned. If more than one window
9845% has the given property, the first one is returned. Only the window
9846% specified and its subwindows are searched.
9847%
9848% The format of the XWindowByProperty function is:
9849%
9850% child=XWindowByProperty(display,window,property)
9851%
9852% A description of each parameter follows:
9853%
9854% o child: XWindowByProperty returns the window id with the specified
9855% property. If no windows are found, XWindowByProperty returns 0.
9856%
9857% o display: Specifies a pointer to the Display structure; returned from
9858% XOpenDisplay.
9859%
9860% o property: Specifies the property of the window to locate.
9861%
9862*/
cristybcbda3f2011-09-03 13:01:22 +00009863MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009864 const Atom property)
9865{
9866 Atom
9867 type;
9868
9869 int
9870 format;
9871
9872 Status
9873 status;
9874
9875 unsigned char
9876 *data;
9877
9878 unsigned int
9879 i,
9880 number_children;
9881
cristyf2faecf2010-05-28 19:19:36 +00009882 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009883 after,
9884 number_items;
9885
9886 Window
9887 child,
9888 *children,
9889 parent,
9890 root;
9891
9892 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9893 assert(display != (Display *) NULL);
9894 assert(window != (Window) NULL);
9895 assert(property != (Atom) NULL);
9896 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9897 if (status == False)
9898 return((Window) NULL);
9899 type=(Atom) NULL;
9900 child=(Window) NULL;
9901 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9902 {
9903 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9904 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9905 if (data != NULL)
9906 (void) XFree((void *) data);
9907 if ((status == Success) && (type != (Atom) NULL))
9908 child=children[i];
9909 }
9910 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9911 child=XWindowByProperty(display,children[i],property);
9912 if (children != (Window *) NULL)
9913 (void) XFree((void *) children);
9914 return(child);
9915}
9916#else
9917
9918/*
9919%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9920% %
9921% %
9922% %
9923% X I m p o r t I m a g e %
9924% %
9925% %
9926% %
9927%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9928%
9929% XImportImage() reads an image from an X window.
9930%
9931% The format of the XImportImage method is:
9932%
cristya0dc96a2011-12-19 23:58:54 +00009933% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9934% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009935%
9936% A description of each parameter follows:
9937%
9938% o image_info: the image info..
9939%
9940% o ximage_info: Specifies a pointer to an XImportInfo structure.
9941%
cristya0dc96a2011-12-19 23:58:54 +00009942% o exception: return any errors or warnings in this structure.
9943%
cristy3ed852e2009-09-05 21:47:34 +00009944*/
cristy4bc52022012-12-13 14:15:41 +00009945MagickExport Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009946 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009947{
9948 assert(image_info != (const ImageInfo *) NULL);
9949 assert(image_info->signature == MagickSignature);
9950 if (image_info->debug != MagickFalse)
9951 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9952 image_info->filename);
9953 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009954 assert(exception != (ExceptionInfo *) NULL);
9955 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009956 return((Image *) NULL);
9957}
cristy534d0a32013-04-13 16:27:24 +00009958
9959/*
9960%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9961% %
9962% %
9963% %
9964% X R e n d e r X 1 1 %
9965% %
9966% %
9967% %
9968%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9969%
9970% XRenderImage() renders text on the image with an X11 font. It also returns
9971% the bounding box of the text relative to the image.
9972%
9973% The format of the XRenderImage method is:
9974%
9975% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
9976% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
9977%
9978% A description of each parameter follows:
9979%
9980% o image: the image.
9981%
9982% o draw_info: the draw info.
9983%
9984% o offset: (x,y) location of text relative to image.
9985%
9986% o metrics: bounding box of text.
9987%
9988% o exception: return any errors or warnings in this structure.
9989%
9990*/
9991MagickPrivate MagickBooleanType XRenderImage(Image *image,
9992 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
9993 ExceptionInfo *exception)
9994{
9995 (void) draw_info;
9996 (void) offset;
9997 (void) metrics;
9998 (void) ThrowMagickException(exception,GetMagickModule(),
9999 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","'%s' (X11)",
10000 image->filename);
10001 return(MagickFalse);
10002}
cristy3ed852e2009-09-05 21:47:34 +000010003#endif
10004
10005/*
10006%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10007% %
10008% %
10009% %
cristy576974e2009-10-25 20:45:31 +000010010+ X C o m p o n e n t G e n e s i s %
10011% %
10012% %
10013% %
10014%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10015%
10016% XComponentGenesis() instantiates the X component.
10017%
10018% The format of the XComponentGenesis method is:
10019%
10020% MagickBooleanType XComponentGenesis(void)
10021%
10022*/
cristy5ff4eaf2011-09-03 01:38:02 +000010023MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +000010024{
10025 return(MagickTrue);
10026}
10027
10028/*
10029%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10030% %
10031% %
10032% %
cristy3ed852e2009-09-05 21:47:34 +000010033% X G e t I m p o r t I n f o %
10034% %
10035% %
10036% %
10037%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10038%
10039% XGetImportInfo() initializes the XImportInfo structure.
10040%
10041% The format of the XGetImportInfo method is:
10042%
10043% void XGetImportInfo(XImportInfo *ximage_info)
10044%
10045% A description of each parameter follows:
10046%
10047% o ximage_info: Specifies a pointer to an ImageInfo structure.
10048%
10049*/
10050MagickExport void XGetImportInfo(XImportInfo *ximage_info)
10051{
10052 assert(ximage_info != (XImportInfo *) NULL);
10053 ximage_info->frame=MagickFalse;
10054 ximage_info->borders=MagickFalse;
10055 ximage_info->screen=MagickFalse;
10056 ximage_info->descend=MagickTrue;
10057 ximage_info->silent=MagickFalse;
10058}