blob: 4f2f6ff062358356cdfde5156b308eaa46ea21ed [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 {
767 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
768 font);
769 return((char **) NULL);
770 }
771 p=font;
772 for (i=0; i < (int) fonts; i++)
773 {
774 for (q=p; *q != '\0'; q++)
775 if ((*q == ':') || (*q == ';') || (*q == ','))
776 break;
777 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
778 sizeof(*fontlist[i]));
779 if (fontlist[i] == (char *) NULL)
780 {
781 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
782 font);
783 return((char **) NULL);
784 }
785 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
786 p=q+1;
787 }
788 fontlist[i]=(char *) NULL;
789 return(fontlist);
790}
791
cristybcbda3f2011-09-03 13:01:22 +0000792MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000793 const XResourceInfo *resource_info,const MagickBooleanType text_font)
794{
795 static const char
796 *Fonts[]=
797 {
798 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
799 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
800 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
801 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
802 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
803 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
804 "variable",
805 "fixed",
806 (char *) NULL
807 },
808 *TextFonts[]=
809 {
810 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
811 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
812 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
813 "fixed",
814 (char *) NULL
815 };
816
817 char
818 *font_name;
819
820 register const char
821 **p;
822
823 XFontStruct
824 *font_info;
825
826 font_info=(XFontStruct *) NULL;
827 font_name=resource_info->font;
828 if (text_font != MagickFalse)
829 font_name=resource_info->text_font;
830 if ((font_name != (char *) NULL) && (*font_name != '\0'))
831 {
832 char
833 **fontlist;
834
835 register int
836 i;
837
838 /*
839 Load preferred font specified in the X resource database.
840 */
841 fontlist=FontToList(font_name);
842 if (fontlist != (char **) NULL)
843 {
844 for (i=0; fontlist[i] != (char *) NULL; i++)
845 {
846 if (font_info == (XFontStruct *) NULL)
847 font_info=XLoadQueryFont(display,fontlist[i]);
848 fontlist[i]=DestroyString(fontlist[i]);
849 }
850 fontlist=(char **) RelinquishMagickMemory(fontlist);
851 }
852 if (font_info == (XFontStruct *) NULL)
853 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
854 }
855 /*
856 Load fonts from list of fonts until one is found.
857 */
858 p=Fonts;
859 if (text_font != MagickFalse)
860 p=TextFonts;
861 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
862 p++;
863 while (*p != (char *) NULL)
864 {
865 if (font_info != (XFontStruct *) NULL)
866 break;
867 font_info=XLoadQueryFont(display,(char *) *p);
868 p++;
869 }
870 return(font_info);
871}
872
873/*
874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875% %
876% %
877% %
878% X B e s t I c o n S i z e %
879% %
880% %
881% %
882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883%
884% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
885% size that maintains the aspect ratio of the image. If the window manager
886% has preferred icon sizes, one of the preferred sizes is used.
887%
888% The format of the XBestIconSize method is:
889%
890% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
891%
892% A description of each parameter follows:
893%
894% o display: Specifies a connection to an X server; returned from
895% XOpenDisplay.
896%
897% o image: the image.
898%
899*/
cristybcbda3f2011-09-03 13:01:22 +0000900MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000901 Image *image)
902{
903 int
904 i,
905 number_sizes;
906
cristya19f1d72012-08-07 18:24:38 +0000907 double
cristy3ed852e2009-09-05 21:47:34 +0000908 scale_factor;
909
910 unsigned int
911 height,
912 icon_height,
913 icon_width,
914 width;
915
916 Window
917 root_window;
918
919 XIconSize
920 *icon_size,
921 *size_list;
922
923 /*
924 Determine if the window manager has specified preferred icon sizes.
925 */
926 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
927 assert(display != (Display *) NULL);
928 assert(window != (XWindowInfo *) NULL);
929 assert(image != (Image *) NULL);
930 window->width=MaxIconSize;
931 window->height=MaxIconSize;
932 icon_size=(XIconSize *) NULL;
933 number_sizes=0;
934 root_window=XRootWindow(display,window->screen);
935 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
936 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
937 icon_size=size_list;
938 if (icon_size == (XIconSize *) NULL)
939 {
940 /*
941 Window manager does not restrict icon size.
942 */
943 icon_size=XAllocIconSize();
944 if (icon_size == (XIconSize *) NULL)
945 {
946 ThrowXWindowFatalException(ResourceLimitError,
947 "MemoryAllocationFailed",image->filename);
948 return;
949 }
950 icon_size->min_width=1;
951 icon_size->max_width=MaxIconSize;
952 icon_size->min_height=1;
953 icon_size->max_height=MaxIconSize;
954 icon_size->width_inc=1;
955 icon_size->height_inc=1;
956 }
957 /*
958 Determine aspect ratio of image.
959 */
960 width=(unsigned int) image->columns;
961 height=(unsigned int) image->rows;
962 i=0;
963 if (window->crop_geometry)
964 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
965 /*
966 Look for an icon size that maintains the aspect ratio of image.
967 */
cristya19f1d72012-08-07 18:24:38 +0000968 scale_factor=(double) icon_size->max_width/width;
969 if (scale_factor > ((double) icon_size->max_height/height))
970 scale_factor=(double) icon_size->max_height/height;
cristy3ed852e2009-09-05 21:47:34 +0000971 icon_width=(unsigned int) icon_size->min_width;
972 while ((int) icon_width < icon_size->max_width)
973 {
974 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
975 break;
976 icon_width+=icon_size->width_inc;
977 }
978 icon_height=(unsigned int) icon_size->min_height;
979 while ((int) icon_height < icon_size->max_height)
980 {
981 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
982 break;
983 icon_height+=icon_size->height_inc;
984 }
985 (void) XFree((void *) icon_size);
986 window->width=icon_width;
987 window->height=icon_height;
988}
989
990/*
991%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992% %
993% %
994% %
995% X B e s t P i x e l %
996% %
997% %
998% %
999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000%
1001% XBestPixel() returns a pixel from an array of pixels that is closest to the
1002% requested color. If the color array is NULL, the colors are obtained from
1003% the X server.
1004%
1005% The format of the XBestPixel method is:
1006%
1007% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1008% unsigned int number_colors,XColor *color)
1009%
1010% A description of each parameter follows:
1011%
1012% o pixel: XBestPixel returns the pixel value closest to the requested
1013% color.
1014%
1015% o display: Specifies a connection to an X server; returned from
1016% XOpenDisplay.
1017%
1018% o colormap: Specifies the ID of the X server colormap.
1019%
1020% o colors: Specifies an array of XColor structures.
1021%
1022% o number_colors: Specifies the number of XColor structures in the
1023% color definition array.
1024%
1025% o color: Specifies the desired RGB value to find in the colors array.
1026%
1027*/
cristybcbda3f2011-09-03 13:01:22 +00001028MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001029 XColor *colors,unsigned int number_colors,XColor *color)
1030{
1031 MagickBooleanType
1032 query_server;
1033
cristy4c08aed2011-07-01 19:47:50 +00001034 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001035 pixel;
1036
cristya19f1d72012-08-07 18:24:38 +00001037 double
cristy3ed852e2009-09-05 21:47:34 +00001038 min_distance;
1039
cristya19f1d72012-08-07 18:24:38 +00001040 register double
cristy3ed852e2009-09-05 21:47:34 +00001041 distance;
1042
1043 register int
1044 i,
1045 j;
1046
1047 Status
1048 status;
1049
1050 /*
1051 Find closest representation for the requested RGB color.
1052 */
1053 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1054 assert(display != (Display *) NULL);
1055 assert(color != (XColor *) NULL);
1056 status=XAllocColor(display,colormap,color);
1057 if (status != False)
1058 return;
1059 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1060 if (query_server != MagickFalse)
1061 {
1062 /*
1063 Read X server colormap.
1064 */
1065 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1066 if (colors == (XColor *) NULL)
1067 {
1068 ThrowXWindowFatalException(ResourceLimitError,
1069 "MemoryAllocationFailed","...");
1070 return;
1071 }
1072 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001073 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001074 if (number_colors > 256)
1075 number_colors=256;
1076 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1077 }
cristya19f1d72012-08-07 18:24:38 +00001078 min_distance=3.0*((double) QuantumRange+1.0)*((double)
cristy3ed852e2009-09-05 21:47:34 +00001079 QuantumRange+1.0);
1080 j=0;
1081 for (i=0; i < (int) number_colors; i++)
1082 {
cristya19f1d72012-08-07 18:24:38 +00001083 pixel.red=colors[i].red-(double) color->red;
cristy3ed852e2009-09-05 21:47:34 +00001084 distance=pixel.red*pixel.red;
1085 if (distance > min_distance)
1086 continue;
cristya19f1d72012-08-07 18:24:38 +00001087 pixel.green=colors[i].green-(double) color->green;
cristy3ed852e2009-09-05 21:47:34 +00001088 distance+=pixel.green*pixel.green;
1089 if (distance > min_distance)
1090 continue;
cristya19f1d72012-08-07 18:24:38 +00001091 pixel.blue=colors[i].blue-(double) color->blue;
cristy3ed852e2009-09-05 21:47:34 +00001092 distance+=pixel.blue*pixel.blue;
1093 if (distance > min_distance)
1094 continue;
1095 min_distance=distance;
1096 color->pixel=colors[i].pixel;
1097 j=i;
1098 }
1099 (void) XAllocColor(display,colormap,&colors[j]);
1100 if (query_server != MagickFalse)
1101 colors=(XColor *) RelinquishMagickMemory(colors);
1102}
1103
1104/*
1105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1106% %
1107% %
1108% %
1109% X B e s t V i s u a l I n f o %
1110% %
1111% %
1112% %
1113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114%
1115% XBestVisualInfo() returns visual information for a visual that is the "best"
1116% the server supports. "Best" is defined as:
1117%
1118% 1. Restrict the visual list to those supported by the default screen.
1119%
1120% 2. If a visual type is specified, restrict the visual list to those of
1121% that type.
1122%
1123% 3. If a map type is specified, choose the visual that matches the id
1124% specified by the Standard Colormap.
1125%
1126% 4 From the list of visuals, choose one that can display the most
1127% simultaneous colors. If more than one visual can display the same
1128% number of simultaneous colors, one is chosen based on a rank.
1129%
1130% The format of the XBestVisualInfo method is:
1131%
1132% XVisualInfo *XBestVisualInfo(Display *display,
1133% XStandardColormap *map_info,XResourceInfo *resource_info)
1134%
1135% A description of each parameter follows:
1136%
1137% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1138% structure.
1139%
1140% o display: Specifies a connection to an X server; returned from
1141% XOpenDisplay.
1142%
1143% o map_info: If map_type is specified, this structure is initialized
1144% with info from the Standard Colormap.
1145%
1146% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1147%
1148*/
1149
1150static inline int MagickMax(const int x,const int y)
1151{
1152 if (x > y)
1153 return(x);
1154 return(y);
1155}
1156
cristybb503372010-05-27 20:51:26 +00001157static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001158 const unsigned int y)
1159{
1160 if (x < y)
1161 return(x);
1162 return(y);
1163}
1164
cristybcbda3f2011-09-03 13:01:22 +00001165MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001166 XStandardColormap *map_info,XResourceInfo *resource_info)
1167{
1168#define MaxStandardColormaps 7
1169#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1170 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1171 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1172 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1173
1174 char
1175 *map_type,
1176 *visual_type;
1177
cristyc57f6942010-11-12 01:47:39 +00001178 int
1179 visual_mask;
1180
cristy3ed852e2009-09-05 21:47:34 +00001181 register int
1182 i;
1183
cristy8891f9c2010-06-04 23:32:17 +00001184 size_t
1185 one;
1186
cristy3ed852e2009-09-05 21:47:34 +00001187 static int
1188 number_visuals;
1189
1190 static XVisualInfo
1191 visual_template;
1192
1193 XVisualInfo
1194 *visual_info,
1195 *visual_list;
1196
1197 /*
1198 Restrict visual search by screen number.
1199 */
1200 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1201 assert(display != (Display *) NULL);
1202 assert(map_info != (XStandardColormap *) NULL);
1203 assert(resource_info != (XResourceInfo *) NULL);
1204 map_type=resource_info->map_type;
1205 visual_type=resource_info->visual_type;
1206 visual_mask=VisualScreenMask;
1207 visual_template.screen=XDefaultScreen(display);
1208 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001209 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001210 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001211 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001212 visual_mask|=VisualDepthMask;
1213 if (visual_type != (char *) NULL)
1214 {
1215 /*
1216 Restrict visual search by class or visual id.
1217 */
1218 if (LocaleCompare("staticgray",visual_type) == 0)
1219 {
1220 visual_mask|=VisualClassMask;
1221 visual_template.klass=StaticGray;
1222 }
1223 else
1224 if (LocaleCompare("grayscale",visual_type) == 0)
1225 {
1226 visual_mask|=VisualClassMask;
1227 visual_template.klass=GrayScale;
1228 }
1229 else
1230 if (LocaleCompare("staticcolor",visual_type) == 0)
1231 {
1232 visual_mask|=VisualClassMask;
1233 visual_template.klass=StaticColor;
1234 }
1235 else
1236 if (LocaleCompare("pseudocolor",visual_type) == 0)
1237 {
1238 visual_mask|=VisualClassMask;
1239 visual_template.klass=PseudoColor;
1240 }
1241 else
1242 if (LocaleCompare("truecolor",visual_type) == 0)
1243 {
1244 visual_mask|=VisualClassMask;
1245 visual_template.klass=TrueColor;
1246 }
1247 else
1248 if (LocaleCompare("directcolor",visual_type) == 0)
1249 {
1250 visual_mask|=VisualClassMask;
1251 visual_template.klass=DirectColor;
1252 }
1253 else
1254 if (LocaleCompare("default",visual_type) == 0)
1255 {
1256 visual_mask|=VisualIDMask;
1257 visual_template.visualid=XVisualIDFromVisual(
1258 XDefaultVisual(display,XDefaultScreen(display)));
1259 }
1260 else
1261 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1262 {
1263 visual_mask|=VisualIDMask;
1264 visual_template.visualid=
1265 strtol(visual_type,(char **) NULL,0);
1266 }
1267 else
1268 ThrowXWindowFatalException(XServerError,
1269 "UnrecognizedVisualSpecifier",visual_type);
1270 }
1271 /*
1272 Get all visuals that meet our criteria so far.
1273 */
1274 number_visuals=0;
1275 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1276 &number_visuals);
1277 visual_mask=VisualScreenMask | VisualIDMask;
1278 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1279 {
1280 /*
1281 Failed to get visual; try using the default visual.
1282 */
1283 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1284 visual_type);
1285 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1286 XDefaultScreen(display)));
1287 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1288 &number_visuals);
1289 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1290 return((XVisualInfo *) NULL);
1291 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1292 XVisualClassName(visual_list->klass));
1293 }
1294 resource_info->color_recovery=MagickFalse;
1295 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1296 {
1297 Atom
1298 map_property;
1299
1300 char
1301 map_name[MaxTextExtent];
1302
1303 int
1304 j,
1305 number_maps;
1306
1307 Status
1308 status;
1309
1310 Window
1311 root_window;
1312
1313 XStandardColormap
1314 *map_list;
1315
1316 /*
1317 Choose a visual associated with a standard colormap.
1318 */
1319 root_window=XRootWindow(display,XDefaultScreen(display));
1320 status=False;
1321 if (LocaleCompare(map_type,"list") != 0)
1322 {
1323 /*
1324 User specified Standard Colormap.
1325 */
cristyb51dff52011-05-19 16:55:47 +00001326 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001327 "RGB_%s_MAP",map_type);
1328 LocaleUpper(map_name);
1329 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1330 if (map_property != (Atom) NULL)
1331 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1332 map_property);
1333 }
1334 else
1335 {
1336 static const char
1337 *colormap[MaxStandardColormaps]=
1338 {
1339 "_HP_RGB_SMOOTH_MAP_LIST",
1340 "RGB_BEST_MAP",
1341 "RGB_DEFAULT_MAP",
1342 "RGB_GRAY_MAP",
1343 "RGB_RED_MAP",
1344 "RGB_GREEN_MAP",
1345 "RGB_BLUE_MAP",
1346 };
1347
1348 /*
1349 Choose a standard colormap from a list.
1350 */
1351 for (i=0; i < MaxStandardColormaps; i++)
1352 {
1353 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1354 if (map_property == (Atom) NULL)
1355 continue;
1356 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1357 map_property);
1358 if (status != False)
1359 break;
1360 }
1361 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1362 }
1363 if (status == False)
1364 {
1365 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1366 map_type);
1367 return((XVisualInfo *) NULL);
1368 }
1369 /*
1370 Search all Standard Colormaps and visuals for ids that match.
1371 */
1372 *map_info=map_list[0];
1373#if !defined(PRE_R4_ICCCM)
1374 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1375 for (i=0; i < number_maps; i++)
1376 for (j=0; j < number_visuals; j++)
1377 if (map_list[i].visualid ==
1378 XVisualIDFromVisual(visual_list[j].visual))
1379 {
1380 *map_info=map_list[i];
1381 visual_template.visualid=XVisualIDFromVisual(
1382 visual_list[j].visual);
1383 break;
1384 }
1385 if (map_info->visualid != visual_template.visualid)
1386 {
1387 ThrowXWindowFatalException(XServerError,
1388 "UnableToMatchVisualToStandardColormap",map_type);
1389 return((XVisualInfo *) NULL);
1390 }
1391#endif
1392 if (map_info->colormap == (Colormap) NULL)
1393 {
1394 ThrowXWindowFatalException(XServerError,
1395 "StandardColormapIsNotInitialized",map_type);
1396 return((XVisualInfo *) NULL);
1397 }
1398 (void) XFree((void *) map_list);
1399 }
1400 else
1401 {
1402 static const unsigned int
1403 rank[]=
1404 {
1405 StaticGray,
1406 GrayScale,
1407 StaticColor,
1408 DirectColor,
1409 TrueColor,
1410 PseudoColor
1411 };
1412
1413 XVisualInfo
1414 *p;
1415
1416 /*
1417 Pick one visual that displays the most simultaneous colors.
1418 */
1419 visual_info=visual_list;
1420 p=visual_list;
1421 for (i=1; i < number_visuals; i++)
1422 {
1423 p++;
1424 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1425 visual_info=p;
1426 else
1427 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1428 if (rank[p->klass] > rank[visual_info->klass])
1429 visual_info=p;
1430 }
1431 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1432 }
1433 (void) XFree((void *) visual_list);
1434 /*
1435 Retrieve only one visual by its screen & id number.
1436 */
1437 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1438 &number_visuals);
1439 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1440 return((XVisualInfo *) NULL);
1441 return(visual_info);
1442}
1443
1444/*
1445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1446% %
1447% %
1448% %
1449% X C h e c k D e f i n e C u r s o r %
1450% %
1451% %
1452% %
1453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1454%
1455% XCheckDefineCursor() prevents cursor changes on the root window.
1456%
1457% The format of the XXCheckDefineCursor method is:
1458%
1459% XCheckDefineCursor(display,window,cursor)
1460%
1461% A description of each parameter follows:
1462%
1463% o display: Specifies a connection to an X server; returned from
1464% XOpenDisplay.
1465%
1466% o window: the window.
1467%
1468% o cursor: the cursor.
1469%
1470*/
cristybcbda3f2011-09-03 13:01:22 +00001471MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001472 Cursor cursor)
1473{
1474 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1475 assert(display != (Display *) NULL);
1476 if (window == XRootWindow(display,XDefaultScreen(display)))
1477 return(0);
1478 return(XDefineCursor(display,window,cursor));
1479}
1480
1481/*
1482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1483% %
1484% %
1485% %
1486% X C h e c k R e f r e s h W i n d o w s %
1487% %
1488% %
1489% %
1490%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1491%
1492% XCheckRefreshWindows() checks the X server for exposure events for a
1493% particular window and updates the areassociated with the exposure event.
1494%
1495% The format of the XCheckRefreshWindows method is:
1496%
1497% void XCheckRefreshWindows(Display *display,XWindows *windows)
1498%
1499% A description of each parameter follows:
1500%
1501% o display: Specifies a connection to an X server; returned from
1502% XOpenDisplay.
1503%
1504% o windows: Specifies a pointer to a XWindows structure.
1505%
1506*/
cristybcbda3f2011-09-03 13:01:22 +00001507MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001508{
1509 Window
1510 id;
1511
1512 XEvent
1513 event;
1514
1515 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1516 assert(display != (Display *) NULL);
1517 assert(windows != (XWindows *) NULL);
1518 XDelay(display,SuspendTime);
1519 id=windows->command.id;
1520 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1521 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1522 id=windows->image.id;
1523 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1524 XRefreshWindow(display,&windows->image,&event);
1525 XDelay(display,SuspendTime << 1);
1526 id=windows->command.id;
1527 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1528 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1529 id=windows->image.id;
1530 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1531 XRefreshWindow(display,&windows->image,&event);
1532}
1533
1534/*
1535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1536% %
1537% %
1538% %
1539% X C l i e n t M e s s a g e %
1540% %
1541% %
1542% %
1543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1544%
1545% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1546% initialized with a particular protocol type and atom.
1547%
1548% The format of the XClientMessage function is:
1549%
1550% XClientMessage(display,window,protocol,reason,timestamp)
1551%
1552% A description of each parameter follows:
1553%
1554% o display: Specifies a pointer to the Display structure; returned from
1555% XOpenDisplay.
1556%
1557% o window: Specifies a pointer to a Window structure.
1558%
1559% o protocol: Specifies an atom value.
1560%
1561% o reason: Specifies an atom value which is the reason to send.
1562%
1563% o timestamp: Specifies a value of type Time.
1564%
1565*/
cristybcbda3f2011-09-03 13:01:22 +00001566MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001567 const Atom protocol,const Atom reason,const Time timestamp)
1568{
1569 XClientMessageEvent
1570 client_event;
1571
1572 assert(display != (Display *) NULL);
1573 client_event.type=ClientMessage;
1574 client_event.window=window;
1575 client_event.message_type=protocol;
1576 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001577 client_event.data.l[0]=(long) reason;
1578 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001579 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1580}
1581
1582/*
1583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1584% %
1585% %
1586% %
1587+ X C l i e n t W i n d o w %
1588% %
1589% %
1590% %
1591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1592%
1593% XClientWindow() finds a window, at or below the specified window, which has
1594% a WM_STATE property. If such a window is found, it is returned, otherwise
1595% the argument window is returned.
1596%
1597% The format of the XClientWindow function is:
1598%
1599% client_window=XClientWindow(display,target_window)
1600%
1601% A description of each parameter follows:
1602%
1603% o client_window: XClientWindow returns a window, at or below the specified
1604% window, which has a WM_STATE property otherwise the argument
1605% target_window is returned.
1606%
1607% o display: Specifies a pointer to the Display structure; returned from
1608% XOpenDisplay.
1609%
1610% o target_window: Specifies the window to find a WM_STATE property.
1611%
cristy3ed852e2009-09-05 21:47:34 +00001612*/
1613static Window XClientWindow(Display *display,Window target_window)
1614{
1615 Atom
1616 state,
1617 type;
1618
1619 int
1620 format;
1621
1622 Status
1623 status;
1624
1625 unsigned char
1626 *data;
1627
cristyf2faecf2010-05-28 19:19:36 +00001628 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001629 after,
1630 number_items;
1631
1632 Window
1633 client_window;
1634
1635 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1636 assert(display != (Display *) NULL);
1637 state=XInternAtom(display,"WM_STATE",MagickTrue);
1638 if (state == (Atom) NULL)
1639 return(target_window);
1640 type=(Atom) NULL;
1641 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1642 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1643 if ((status == Success) && (type != (Atom) NULL))
1644 return(target_window);
1645 client_window=XWindowByProperty(display,target_window,state);
1646 if (client_window == (Window) NULL)
1647 return(target_window);
1648 return(client_window);
1649}
1650
1651/*
1652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1653% %
1654% %
1655% %
cristyf34a1452009-10-24 22:29:27 +00001656+ X C o m p o n e n t T e r m i n u s %
1657% %
1658% %
1659% %
1660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1661%
1662% XComponentTerminus() destroys the module component.
1663%
1664% The format of the XComponentTerminus method is:
1665%
1666% XComponentTerminus(void)
1667%
1668*/
cristy5ff4eaf2011-09-03 01:38:02 +00001669MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001670{
1671 DestroyXResources();
1672}
1673
1674/*
1675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1676% %
1677% %
1678% %
cristy3ed852e2009-09-05 21:47:34 +00001679% X C o n f i g u r e I m a g e C o l o r m a p %
1680% %
1681% %
1682% %
1683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1684%
1685% XConfigureImageColormap() creates a new X colormap.
1686%
1687% The format of the XConfigureImageColormap method is:
1688%
1689% void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001690% XResourceInfo *resource_info,XWindows *windows,Image *image,
1691% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001692%
1693% A description of each parameter follows:
1694%
1695% o display: Specifies a connection to an X server; returned from
1696% XOpenDisplay.
1697%
1698% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1699%
1700% o windows: Specifies a pointer to a XWindows structure.
1701%
1702% o image: the image.
1703%
cristy6710d842011-10-20 23:23:00 +00001704% o exception: return any errors or warnings in this structure.
1705%
cristy3ed852e2009-09-05 21:47:34 +00001706*/
cristybcbda3f2011-09-03 13:01:22 +00001707MagickPrivate void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001708 XResourceInfo *resource_info,XWindows *windows,Image *image,
1709 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001710{
1711 Colormap
1712 colormap;
1713
1714 /*
1715 Make standard colormap.
1716 */
1717 XSetCursorState(display,windows,MagickTrue);
1718 XCheckRefreshWindows(display,windows);
1719 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
cristy6710d842011-10-20 23:23:00 +00001720 windows->map_info,windows->pixel_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00001721 colormap=windows->map_info->colormap;
1722 (void) XSetWindowColormap(display,windows->image.id,colormap);
1723 (void) XSetWindowColormap(display,windows->command.id,colormap);
1724 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1725 if (windows->magnify.mapped != MagickFalse)
1726 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1727 if (windows->pan.mapped != MagickFalse)
1728 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1729 XSetCursorState(display,windows,MagickFalse);
1730 XClientMessage(display,windows->image.id,windows->im_protocols,
1731 windows->im_update_colormap,CurrentTime);
1732}
1733
1734/*
1735%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1736% %
1737% %
1738% %
1739% X C o n s t r a i n W i n d o w P o s i t i o n %
1740% %
1741% %
1742% %
1743%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1744%
1745% XConstrainWindowPosition() assures a window is positioned within the X
1746% server boundaries.
1747%
1748% The format of the XConstrainWindowPosition method is:
1749%
1750% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1751%
1752% A description of each parameter follows:
1753%
1754% o display: Specifies a pointer to the Display structure; returned from
1755% XOpenDisplay.
1756%
1757% o window_info: Specifies a pointer to a XWindowInfo structure.
1758%
1759*/
cristybcbda3f2011-09-03 13:01:22 +00001760MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001761 XWindowInfo *window_info)
1762{
1763 int
1764 limit;
1765
1766 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1767 assert(display != (Display *) NULL);
1768 assert(window_info != (XWindowInfo *) NULL);
1769 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1770 if (window_info->x < 0)
1771 window_info->x=0;
1772 else
1773 if (window_info->x > (int) limit)
1774 window_info->x=(int) limit;
1775 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1776 if (window_info->y < 0)
1777 window_info->y=0;
1778 else
1779 if (window_info->y > limit)
1780 window_info->y=limit;
1781}
1782
1783/*
1784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1785% %
1786% %
1787% %
1788% X D e l a y %
1789% %
1790% %
1791% %
1792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1793%
1794% XDelay() suspends program execution for the number of milliseconds
1795% specified.
1796%
1797% The format of the Delay method is:
1798%
cristybb503372010-05-27 20:51:26 +00001799% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001800%
1801% A description of each parameter follows:
1802%
1803% o display: Specifies a pointer to the Display structure; returned from
1804% XOpenDisplay.
1805%
1806% o milliseconds: Specifies the number of milliseconds to delay before
1807% returning.
1808%
1809*/
cristybcbda3f2011-09-03 13:01:22 +00001810MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001811{
1812 assert(display != (Display *) NULL);
1813 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001814 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001815}
1816
1817/*
1818%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1819% %
1820% %
1821% %
1822% X D e s t r o y R e s o u r c e I n f o %
1823% %
1824% %
1825% %
1826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1827%
1828% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1829% structure.
1830%
1831% The format of the XDestroyResourceInfo method is:
1832%
1833% void XDestroyResourceInfo(XResourceInfo *resource_info)
1834%
1835% A description of each parameter follows:
1836%
1837% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1838%
1839*/
1840MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1841{
1842 if (resource_info->image_geometry != (char *) NULL)
1843 resource_info->image_geometry=(char *)
1844 RelinquishMagickMemory(resource_info->image_geometry);
1845 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1846 resource_info->quantize_info=DestroyQuantizeInfo(
1847 resource_info->quantize_info);
1848 if (resource_info->client_name != (char *) NULL)
1849 resource_info->client_name=(char *)
1850 RelinquishMagickMemory(resource_info->client_name);
1851 if (resource_info->name != (char *) NULL)
1852 resource_info->name=DestroyString(resource_info->name);
1853 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1854}
1855
1856/*
1857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1858% %
1859% %
1860% %
1861% X D e s t r o y W i n d o w C o l o r s %
1862% %
1863% %
1864% %
1865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1866%
1867% XDestroyWindowColors() frees X11 color resources previously saved on a
1868% window by XRetainWindowColors or programs like xsetroot.
1869%
1870% The format of the XDestroyWindowColors method is:
1871%
1872% void XDestroyWindowColors(Display *display,Window window)
1873%
1874% A description of each parameter follows:
1875%
1876% o display: Specifies a connection to an X server; returned from
1877% XOpenDisplay.
1878%
1879% o window: Specifies a pointer to a Window structure.
1880%
1881*/
cristybcbda3f2011-09-03 13:01:22 +00001882MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001883{
1884 Atom
1885 property,
1886 type;
1887
1888 int
1889 format;
1890
1891 Status
1892 status;
1893
1894 unsigned char
1895 *data;
1896
cristyf2faecf2010-05-28 19:19:36 +00001897 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001898 after,
1899 length;
1900
1901 /*
1902 If there are previous resources on the root window, destroy them.
1903 */
1904 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1905 assert(display != (Display *) NULL);
1906 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1907 if (property == (Atom) NULL)
1908 {
1909 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1910 "_XSETROOT_ID");
1911 return;
1912 }
1913 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1914 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1915 if (status != Success)
1916 return;
1917 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1918 {
1919 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1920 (void) XDeleteProperty(display,window,property);
1921 }
1922 if (type != None)
1923 (void) XFree((void *) data);
1924}
1925
1926/*
1927%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1928% %
1929% %
1930% %
1931% X D i s p l a y I m a g e I n f o %
1932% %
1933% %
1934% %
1935%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1936%
1937% XDisplayImageInfo() displays information about an X image.
1938%
1939% The format of the XDisplayImageInfo method is:
1940%
1941% void XDisplayImageInfo(Display *display,
1942% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001943% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001944%
1945% A description of each parameter follows:
1946%
1947% o display: Specifies a connection to an X server; returned from
1948% XOpenDisplay.
1949%
1950% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1951%
1952% o windows: Specifies a pointer to a XWindows structure.
1953%
1954% o undo_image: the undo image.
1955%
1956% o image: the image.
1957%
cristy6710d842011-10-20 23:23:00 +00001958% o exception: return any errors or warnings in this structure.
1959%
cristy3ed852e2009-09-05 21:47:34 +00001960*/
cristybcbda3f2011-09-03 13:01:22 +00001961MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001962 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001963 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001964{
1965 char
1966 filename[MaxTextExtent],
1967 *text,
1968 **textlist;
1969
1970 FILE
1971 *file;
1972
1973 int
1974 unique_file;
1975
cristybb503372010-05-27 20:51:26 +00001976 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001977 i;
1978
cristybb503372010-05-27 20:51:26 +00001979 size_t
cristy3ed852e2009-09-05 21:47:34 +00001980 number_pixels;
1981
cristy9d314ff2011-03-09 01:30:28 +00001982 ssize_t
1983 bytes;
1984
1985 unsigned int
1986 levels;
1987
cristy3ed852e2009-09-05 21:47:34 +00001988 /*
1989 Write info about the X server to a file.
1990 */
1991 assert(display != (Display *) NULL);
1992 assert(resource_info != (XResourceInfo *) NULL);
1993 assert(windows != (XWindows *) NULL);
1994 assert(image != (Image *) NULL);
1995 if (image->debug)
1996 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1997 file=(FILE *) NULL;
1998 unique_file=AcquireUniqueFileResource(filename);
1999 if (unique_file != -1)
2000 file=fdopen(unique_file,"w");
2001 if ((unique_file == -1) || (file == (FILE *) NULL))
2002 {
2003 XNoticeWidget(display,windows,"Unable to display image info",filename);
2004 return;
2005 }
2006 if (resource_info->gamma_correct != MagickFalse)
2007 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002008 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002009 resource_info->display_gamma);
2010 /*
2011 Write info about the X image to a file.
2012 */
cristyb51dff52011-05-19 16:55:47 +00002013 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002014 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002015 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002016 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002017 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002018 windows->visual_info->colormap_size);
2019 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002020 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002021 else
cristyb51dff52011-05-19 16:55:47 +00002022 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002023 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2024 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002025 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002026 (void) FormatLocaleFile(file," crop geometry: %s\n",
2027 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002028 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002029 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002030 else
cristyb51dff52011-05-19 16:55:47 +00002031 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002032 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002033 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002034 else
cristyb51dff52011-05-19 16:55:47 +00002035 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002036 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002037 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002038 else
cristyb51dff52011-05-19 16:55:47 +00002039 (void) FormatLocaleFile(file," shared memory: False\n");
2040 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002041 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002042 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002043 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002044 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002045 /*
2046 Write info about the undo cache to a file.
2047 */
2048 bytes=0;
2049 for (levels=0; undo_image != (Image *) NULL; levels++)
2050 {
2051 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002052 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002053 undo_image=GetPreviousImageInList(undo_image);
2054 }
cristyb51dff52011-05-19 16:55:47 +00002055 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002056 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2057 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002058 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002059 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002060 /*
2061 Write info about the image to a file.
2062 */
cristy6710d842011-10-20 23:23:00 +00002063 (void) IdentifyImage(image,file,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00002064 (void) fclose(file);
cristy6710d842011-10-20 23:23:00 +00002065 text=FileToString(filename,~0,exception);
cristy3ed852e2009-09-05 21:47:34 +00002066 (void) RelinquishUniqueFileResource(filename);
2067 if (text == (char *) NULL)
2068 {
2069 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2070 "UnableToDisplayImageInfo");
2071 return;
2072 }
2073 textlist=StringToList(text);
2074 if (textlist != (char **) NULL)
2075 {
2076 char
2077 title[MaxTextExtent];
2078
2079 /*
2080 Display information about the image in the Text View widget.
2081 */
2082 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002083 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002084 image->filename);
2085 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2086 (char const **) textlist);
2087 for (i=0; textlist[i] != (char *) NULL; i++)
2088 textlist[i]=DestroyString(textlist[i]);
2089 textlist=(char **) RelinquishMagickMemory(textlist);
2090 }
2091 text=DestroyString(text);
2092}
2093
2094/*
2095%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2096% %
2097% %
2098% %
2099+ X D i t h e r I m a g e %
2100% %
2101% %
2102% %
2103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2104%
2105% XDitherImage() dithers the reference image as required by the HP Color
2106% Recovery algorithm. The color values are quantized to 3 bits of red and
2107% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2108% standard colormap.
2109%
2110% The format of the XDitherImage method is:
2111%
cristy6710d842011-10-20 23:23:00 +00002112% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002113%
2114% A description of each parameter follows:
2115%
2116% o image: the image.
2117%
2118% o ximage: Specifies a pointer to a XImage structure; returned from
2119% XCreateImage.
2120%
cristy6710d842011-10-20 23:23:00 +00002121% o exception: return any errors or warnings in this structure.
2122%
cristy3ed852e2009-09-05 21:47:34 +00002123*/
cristy6710d842011-10-20 23:23:00 +00002124static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002125{
2126 static const short int
2127 dither_red[2][16]=
2128 {
2129 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2130 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2131 },
2132 dither_green[2][16]=
2133 {
2134 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2135 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2136 },
2137 dither_blue[2][16]=
2138 {
2139 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2140 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2141 };
2142
cristyc57f6942010-11-12 01:47:39 +00002143 CacheView
2144 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002145
2146 int
cristyc57f6942010-11-12 01:47:39 +00002147 value,
cristy3ed852e2009-09-05 21:47:34 +00002148 y;
2149
cristy101ab702011-10-13 13:06:32 +00002150 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002151 color;
cristy3ed852e2009-09-05 21:47:34 +00002152
2153 register char
2154 *q;
2155
cristy4c08aed2011-07-01 19:47:50 +00002156 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002157 *p;
2158
2159 register int
2160 i,
2161 j,
2162 x;
2163
2164 unsigned int
2165 scanline_pad;
2166
cristybb503372010-05-27 20:51:26 +00002167 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002168 pixel;
2169
2170 unsigned char
2171 *blue_map[2][16],
2172 *green_map[2][16],
2173 *red_map[2][16];
2174
2175 /*
2176 Allocate and initialize dither maps.
2177 */
2178 for (i=0; i < 2; i++)
2179 for (j=0; j < 16; j++)
2180 {
2181 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2182 sizeof(*red_map));
2183 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2184 sizeof(*green_map));
2185 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2186 sizeof(*blue_map));
2187 if ((red_map[i][j] == (unsigned char *) NULL) ||
2188 (green_map[i][j] == (unsigned char *) NULL) ||
2189 (blue_map[i][j] == (unsigned char *) NULL))
2190 {
2191 ThrowXWindowFatalException(ResourceLimitError,
2192 "MemoryAllocationFailed",image->filename);
2193 return;
2194 }
2195 }
2196 /*
2197 Initialize dither tables.
2198 */
2199 for (i=0; i < 2; i++)
2200 for (j=0; j < 16; j++)
2201 for (x=0; x < 256; x++)
2202 {
2203 value=x-16;
2204 if (x < 48)
2205 value=x/2+8;
2206 value+=dither_red[i][j];
2207 red_map[i][j][x]=(unsigned char)
2208 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2209 value=x-16;
2210 if (x < 48)
2211 value=x/2+8;
2212 value+=dither_green[i][j];
2213 green_map[i][j][x]=(unsigned char)
2214 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2215 value=x-32;
2216 if (x < 112)
2217 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002218 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002219 blue_map[i][j][x]=(unsigned char)
2220 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2221 }
2222 /*
2223 Dither image.
2224 */
2225 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002226 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002227 i=0;
2228 j=0;
2229 q=ximage->data;
cristy46ff2672012-12-14 15:32:26 +00002230 image_view=AcquireVirtualCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002231 for (y=0; y < (int) image->rows; y++)
2232 {
cristyc57f6942010-11-12 01:47:39 +00002233 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
cristy6710d842011-10-20 23:23:00 +00002234 exception);
cristy4c08aed2011-07-01 19:47:50 +00002235 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002236 break;
2237 for (x=0; x < (int) image->columns; x++)
2238 {
cristyada285b2012-07-07 19:00:46 +00002239 color.red=(double) ClampToQuantum((double) (red_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002240 (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002241 color.green=(double) ClampToQuantum((double) (green_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002242 (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002243 color.blue=(double) ClampToQuantum((double) (blue_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002244 (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002245 pixel=(size_t) (((size_t) color.red & 0xe0) |
2246 (((size_t) color.green & 0xe0) >> 3) |
2247 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002248 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002249 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002250 j++;
2251 if (j == 16)
2252 j=0;
2253 }
2254 q+=scanline_pad;
2255 i++;
2256 if (i == 2)
2257 i=0;
2258 }
cristyc57f6942010-11-12 01:47:39 +00002259 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002260 /*
2261 Free allocated memory.
2262 */
2263 for (i=0; i < 2; i++)
2264 for (j=0; j < 16; j++)
2265 {
2266 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2267 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2268 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2269 }
2270}
2271
2272/*
2273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2274% %
2275% %
2276% %
2277% X D r a w I m a g e %
2278% %
2279% %
2280% %
2281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2282%
2283% XDrawImage() draws a line on the image.
2284%
2285% The format of the XDrawImage method is:
2286%
cristy6710d842011-10-20 23:23:00 +00002287% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2288% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002289%
2290% A description of each parameter follows:
2291%
2292% o display: Specifies a connection to an X server; returned from
2293% XOpenDisplay.
2294%
2295% o pixel: Specifies a pointer to a XPixelInfo structure.
2296%
2297% o draw_info: Specifies a pointer to a XDrawInfo structure.
2298%
2299% o image: the image.
2300%
cristy6710d842011-10-20 23:23:00 +00002301% o exception: return any errors or warnings in this structure.
2302%
cristy3ed852e2009-09-05 21:47:34 +00002303*/
cristybcbda3f2011-09-03 13:01:22 +00002304MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy6710d842011-10-20 23:23:00 +00002305 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2306 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002307{
cristyc57f6942010-11-12 01:47:39 +00002308 CacheView
2309 *draw_view;
2310
cristy3ed852e2009-09-05 21:47:34 +00002311 GC
2312 draw_context;
2313
2314 Image
2315 *draw_image;
2316
2317 int
2318 x,
2319 y;
2320
cristyb0a657e2012-08-29 00:45:37 +00002321 PixelTrait
2322 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002323
2324 Pixmap
2325 draw_pixmap;
2326
2327 unsigned int
2328 depth,
2329 height,
2330 width;
2331
2332 Window
2333 root_window;
2334
2335 XGCValues
2336 context_values;
2337
2338 XImage
2339 *draw_ximage;
2340
2341 /*
2342 Initialize drawd image.
2343 */
2344 assert(display != (Display *) NULL);
2345 assert(pixel != (XPixelInfo *) NULL);
2346 assert(draw_info != (XDrawInfo *) NULL);
2347 assert(image != (Image *) NULL);
2348 if (image->debug != MagickFalse)
2349 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2350 /*
2351 Initialize drawd pixmap.
2352 */
2353 root_window=XRootWindow(display,XDefaultScreen(display));
2354 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2355 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2356 draw_info->height,depth);
2357 if (draw_pixmap == (Pixmap) NULL)
2358 return(MagickFalse);
2359 /*
2360 Initialize graphics info.
2361 */
cristybb503372010-05-27 20:51:26 +00002362 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002363 context_values.foreground=0;
2364 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002365 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002366 (GCBackground | GCForeground | GCLineWidth),&context_values);
2367 if (draw_context == (GC) NULL)
2368 return(MagickFalse);
2369 /*
2370 Clear pixmap.
2371 */
2372 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2373 draw_info->height);
2374 /*
2375 Draw line to pixmap.
2376 */
2377 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002378 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002379 if (draw_info->stipple != (Pixmap) NULL)
2380 {
2381 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2382 (void) XSetStipple(display,draw_context,draw_info->stipple);
2383 }
cristy3ed852e2009-09-05 21:47:34 +00002384 switch (draw_info->element)
2385 {
2386 case PointElement:
2387 default:
2388 {
2389 (void) XDrawLines(display,draw_pixmap,draw_context,
2390 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2391 CoordModeOrigin);
2392 break;
2393 }
2394 case LineElement:
2395 {
2396 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2397 draw_info->line_info.y1,draw_info->line_info.x2,
2398 draw_info->line_info.y2);
2399 break;
2400 }
2401 case RectangleElement:
2402 {
2403 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2404 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2405 (unsigned int) draw_info->rectangle_info.width,
2406 (unsigned int) draw_info->rectangle_info.height);
2407 break;
2408 }
2409 case FillRectangleElement:
2410 {
2411 (void) XFillRectangle(display,draw_pixmap,draw_context,
2412 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2413 (unsigned int) draw_info->rectangle_info.width,
2414 (unsigned int) draw_info->rectangle_info.height);
2415 break;
2416 }
2417 case CircleElement:
2418 case EllipseElement:
2419 {
2420 (void) XDrawArc(display,draw_pixmap,draw_context,
2421 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2422 (unsigned int) draw_info->rectangle_info.width,
2423 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2424 break;
2425 }
2426 case FillCircleElement:
2427 case FillEllipseElement:
2428 {
2429 (void) XFillArc(display,draw_pixmap,draw_context,
2430 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2431 (unsigned int) draw_info->rectangle_info.width,
2432 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2433 break;
2434 }
2435 case PolygonElement:
2436 {
2437 XPoint
2438 *coordinate_info;
2439
2440 coordinate_info=draw_info->coordinate_info;
2441 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2442 (int) draw_info->number_coordinates,CoordModeOrigin);
2443 (void) XDrawLine(display,draw_pixmap,draw_context,
2444 coordinate_info[draw_info->number_coordinates-1].x,
2445 coordinate_info[draw_info->number_coordinates-1].y,
2446 coordinate_info[0].x,coordinate_info[0].y);
2447 break;
2448 }
2449 case FillPolygonElement:
2450 {
2451 (void) XFillPolygon(display,draw_pixmap,draw_context,
2452 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2453 CoordModeOrigin);
2454 break;
2455 }
2456 }
2457 (void) XFreeGC(display,draw_context);
2458 /*
2459 Initialize X image.
2460 */
2461 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2462 draw_info->height,AllPlanes,ZPixmap);
2463 if (draw_ximage == (XImage *) NULL)
2464 return(MagickFalse);
2465 (void) XFreePixmap(display,draw_pixmap);
2466 /*
2467 Initialize draw image.
2468 */
cristy6710d842011-10-20 23:23:00 +00002469 draw_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002470 if (draw_image == (Image *) NULL)
2471 return(MagickFalse);
2472 draw_image->columns=draw_info->width;
2473 draw_image->rows=draw_info->height;
2474 /*
2475 Transfer drawn X image to image.
2476 */
2477 width=(unsigned int) image->columns;
2478 height=(unsigned int) image->rows;
2479 x=0;
2480 y=0;
2481 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +00002482 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
2483 (ssize_t) y,&draw_image->background_color,exception);
cristy6710d842011-10-20 23:23:00 +00002484 if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002485 return(MagickFalse);
cristy8a46d822012-08-28 23:32:39 +00002486 draw_image->alpha_trait=BlendPixelTrait;
cristy6f5395d2012-12-14 18:30:30 +00002487 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002488 for (y=0; y < (int) draw_image->rows; y++)
2489 {
cristyc57f6942010-11-12 01:47:39 +00002490 register int
cristy3ed852e2009-09-05 21:47:34 +00002491 x;
2492
cristy4c08aed2011-07-01 19:47:50 +00002493 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002494 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002495
cristyc57f6942010-11-12 01:47:39 +00002496 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2497 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002498 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002499 break;
cristyc57f6942010-11-12 01:47:39 +00002500 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002501 {
2502 if (XGetPixel(draw_ximage,x,y) == 0)
2503 {
2504 /*
2505 Set this pixel to the background color.
2506 */
cristy803640d2011-11-17 02:11:32 +00002507 SetPixelInfoPixel(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002508 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002509 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002510 }
2511 else
2512 {
2513 /*
2514 Set this pixel to the pen color.
2515 */
cristy4c08aed2011-07-01 19:47:50 +00002516 SetPixelRed(draw_image,ScaleShortToQuantum(
2517 pixel->pen_color.red),q);
2518 SetPixelGreen(draw_image,ScaleShortToQuantum(
2519 pixel->pen_color.green),q);
2520 SetPixelBlue(draw_image,ScaleShortToQuantum(
2521 pixel->pen_color.blue),q);
2522 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2523 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002524 }
cristyed231572011-07-14 02:18:59 +00002525 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002526 }
cristyc57f6942010-11-12 01:47:39 +00002527 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002528 break;
2529 }
cristyc57f6942010-11-12 01:47:39 +00002530 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002531 XDestroyImage(draw_ximage);
2532 /*
2533 Determine draw geometry.
2534 */
2535 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2536 if ((width != (unsigned int) draw_image->columns) ||
2537 (height != (unsigned int) draw_image->rows))
2538 {
2539 char
2540 image_geometry[MaxTextExtent];
2541
2542 /*
2543 Scale image.
2544 */
cristyb51dff52011-05-19 16:55:47 +00002545 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002546 width,height);
cristye941a752011-10-15 01:52:48 +00002547 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2548 exception);
cristy3ed852e2009-09-05 21:47:34 +00002549 }
2550 if (draw_info->degrees != 0.0)
2551 {
2552 Image
2553 *rotate_image;
2554
2555 int
2556 rotations;
2557
cristya19f1d72012-08-07 18:24:38 +00002558 double
cristy3ed852e2009-09-05 21:47:34 +00002559 normalized_degrees;
2560
2561 /*
2562 Rotate image.
2563 */
cristy6710d842011-10-20 23:23:00 +00002564 rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +00002565 if (rotate_image == (Image *) NULL)
2566 return(MagickFalse);
2567 draw_image=DestroyImage(draw_image);
2568 draw_image=rotate_image;
2569 /*
2570 Annotation is relative to the degree of rotation.
2571 */
2572 normalized_degrees=draw_info->degrees;
2573 while (normalized_degrees < -45.0)
2574 normalized_degrees+=360.0;
2575 for (rotations=0; normalized_degrees > 45.0; rotations++)
2576 normalized_degrees-=90.0;
2577 switch (rotations % 4)
2578 {
2579 default:
2580 case 0:
2581 break;
2582 case 1:
2583 {
2584 /*
2585 Rotate 90 degrees.
2586 */
2587 x=x-(int) draw_image->columns/2;
2588 y=y+(int) draw_image->columns/2;
2589 break;
2590 }
2591 case 2:
2592 {
2593 /*
2594 Rotate 180 degrees.
2595 */
2596 x=x-(int) draw_image->columns;
2597 break;
2598 }
2599 case 3:
2600 {
2601 /*
2602 Rotate 270 degrees.
2603 */
2604 x=x-(int) draw_image->columns/2;
2605 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2606 break;
2607 }
2608 }
2609 }
2610 /*
2611 Composite text onto the image.
2612 */
cristy6f5395d2012-12-14 18:30:30 +00002613 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002614 for (y=0; y < (int) draw_image->rows; y++)
2615 {
cristyc57f6942010-11-12 01:47:39 +00002616 register int
cristy3ed852e2009-09-05 21:47:34 +00002617 x;
2618
cristy4c08aed2011-07-01 19:47:50 +00002619 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002620 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002621
cristyc57f6942010-11-12 01:47:39 +00002622 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2623 exception);
cristyacd2ed22011-08-30 01:44:23 +00002624 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002625 break;
cristyc57f6942010-11-12 01:47:39 +00002626 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002627 {
cristy4c08aed2011-07-01 19:47:50 +00002628 if (GetPixelAlpha(image,q) != TransparentAlpha)
2629 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002630 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002631 }
cristyc57f6942010-11-12 01:47:39 +00002632 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002633 break;
2634 }
cristyc57f6942010-11-12 01:47:39 +00002635 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002636 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2637 if (draw_info->stencil == TransparentStencil)
cristy39172402012-03-30 13:04:39 +00002638 (void) CompositeImage(image,draw_image,CopyAlphaCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002639 (ssize_t) x,(ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002640 else
2641 {
cristyb0a657e2012-08-29 00:45:37 +00002642 alpha_trait=image->alpha_trait;
cristy39172402012-03-30 13:04:39 +00002643 (void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002644 (ssize_t) x,(ssize_t) y,exception);
cristyb0a657e2012-08-29 00:45:37 +00002645 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002646 }
2647 draw_image=DestroyImage(draw_image);
2648 return(MagickTrue);
2649}
2650
2651/*
2652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2653% %
2654% %
2655% %
2656% X E r r o r %
2657% %
2658% %
2659% %
2660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2661%
2662% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2663% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002664% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2665% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002666%
2667% The format of the XError function is:
2668%
cristybcbda3f2011-09-03 13:01:22 +00002669% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002670%
2671% A description of each parameter follows:
2672%
2673% o display: Specifies a pointer to the Display structure; returned from
2674% XOpenDisplay.
2675%
2676% o error: Specifies the error event.
2677%
2678*/
2679
2680#if defined(__cplusplus) || defined(c_plusplus)
2681extern "C" {
2682#endif
2683
2684MagickExport int XError(Display *display,XErrorEvent *error)
2685{
2686 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2687 assert(display != (Display *) NULL);
2688 assert(error != (XErrorEvent *) NULL);
2689 xerror_alert=MagickTrue;
2690 switch (error->request_code)
2691 {
2692 case X_GetGeometry:
2693 {
2694 if ((int) error->error_code == BadDrawable)
2695 return(MagickFalse);
2696 break;
2697 }
2698 case X_GetWindowAttributes:
2699 case X_QueryTree:
2700 {
2701 if ((int) error->error_code == BadWindow)
2702 return(MagickFalse);
2703 break;
2704 }
2705 case X_QueryColors:
2706 {
2707 if ((int) error->error_code == BadValue)
2708 return(MagickFalse);
2709 break;
2710 }
2711 }
2712 return(MagickTrue);
2713}
2714
2715#if defined(__cplusplus) || defined(c_plusplus)
2716}
2717#endif
2718
2719/*
2720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2721% %
2722% %
2723% %
2724% X F r e e R e s o u r c e s %
2725% %
2726% %
2727% %
2728%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2729%
2730% XFreeResources() frees X11 resources.
2731%
2732% The format of the XFreeResources method is:
2733%
2734% void XFreeResources(Display *display,XVisualInfo *visual_info,
2735% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2736% XResourceInfo *resource_info,XWindowInfo *window_info)
2737% resource_info,window_info)
2738%
2739% A description of each parameter follows:
2740%
2741% o display: Specifies a connection to an X server; returned from
2742% XOpenDisplay.
2743%
2744% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2745% returned from XGetVisualInfo.
2746%
2747% o map_info: If map_type is specified, this structure is initialized
2748% with info from the Standard Colormap.
2749%
2750% o pixel: Specifies a pointer to a XPixelInfo structure.
2751%
2752% o font_info: Specifies a pointer to a XFontStruct structure.
2753%
2754% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2755%
2756% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2757%
2758*/
cristybcbda3f2011-09-03 13:01:22 +00002759MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002760 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2761 XResourceInfo *resource_info,XWindowInfo *window_info)
2762{
2763 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2764 assert(display != (Display *) NULL);
2765 assert(resource_info != (XResourceInfo *) NULL);
2766 if (window_info != (XWindowInfo *) NULL)
2767 {
2768 /*
2769 Free X image.
2770 */
2771 if (window_info->ximage != (XImage *) NULL)
2772 XDestroyImage(window_info->ximage);
2773 if (window_info->id != (Window) NULL)
2774 {
2775 /*
2776 Free destroy window and free cursors.
2777 */
2778 if (window_info->id != XRootWindow(display,visual_info->screen))
2779 (void) XDestroyWindow(display,window_info->id);
2780 if (window_info->annotate_context != (GC) NULL)
2781 (void) XFreeGC(display,window_info->annotate_context);
2782 if (window_info->highlight_context != (GC) NULL)
2783 (void) XFreeGC(display,window_info->highlight_context);
2784 if (window_info->widget_context != (GC) NULL)
2785 (void) XFreeGC(display,window_info->widget_context);
2786 if (window_info->cursor != (Cursor) NULL)
2787 (void) XFreeCursor(display,window_info->cursor);
2788 window_info->cursor=(Cursor) NULL;
2789 if (window_info->busy_cursor != (Cursor) NULL)
2790 (void) XFreeCursor(display,window_info->busy_cursor);
2791 window_info->busy_cursor=(Cursor) NULL;
2792 }
2793 }
2794 /*
2795 Free font.
2796 */
2797 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002798 {
2799 (void) XFreeFont(display,font_info);
2800 font_info=(XFontStruct *) NULL;
2801 }
cristy3ed852e2009-09-05 21:47:34 +00002802 if (map_info != (XStandardColormap *) NULL)
2803 {
2804 /*
2805 Free X Standard Colormap.
2806 */
2807 if (resource_info->map_type == (char *) NULL)
2808 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2809 (void) XFree((void *) map_info);
2810 }
2811 /*
2812 Free X visual info.
2813 */
2814 if (visual_info != (XVisualInfo *) NULL)
2815 (void) XFree((void *) visual_info);
2816 if (resource_info->close_server != MagickFalse)
2817 (void) XCloseDisplay(display);
2818}
2819
2820/*
2821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2822% %
2823% %
2824% %
2825% X F r e e S t a n d a r d C o l o r m a p %
2826% %
2827% %
2828% %
2829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2830%
2831% XFreeStandardColormap() frees an X11 colormap.
2832%
2833% The format of the XFreeStandardColormap method is:
2834%
2835% void XFreeStandardColormap(Display *display,
2836% const XVisualInfo *visual_info,XStandardColormap *map_info,
2837% XPixelInfo *pixel)
2838%
2839% A description of each parameter follows:
2840%
2841% o display: Specifies a connection to an X server; returned from
2842% XOpenDisplay.
2843%
2844% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2845% returned from XGetVisualInfo.
2846%
2847% o map_info: If map_type is specified, this structure is initialized
2848% with info from the Standard Colormap.
2849%
2850% o pixel: Specifies a pointer to a XPixelInfo structure.
2851%
2852*/
cristybcbda3f2011-09-03 13:01:22 +00002853MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002854 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2855{
2856 /*
2857 Free colormap.
2858 */
2859 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2860 assert(display != (Display *) NULL);
2861 assert(visual_info != (XVisualInfo *) NULL);
2862 assert(map_info != (XStandardColormap *) NULL);
2863 (void) XFlush(display);
2864 if (map_info->colormap != (Colormap) NULL)
2865 {
2866 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2867 (void) XFreeColormap(display,map_info->colormap);
2868 else
2869 if (pixel != (XPixelInfo *) NULL)
2870 if ((visual_info->klass != TrueColor) &&
2871 (visual_info->klass != DirectColor))
2872 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2873 (int) pixel->colors,0);
2874 }
2875 map_info->colormap=(Colormap) NULL;
2876 if (pixel != (XPixelInfo *) NULL)
2877 {
cristyf2faecf2010-05-28 19:19:36 +00002878 if (pixel->pixels != (unsigned long *) NULL)
2879 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2880 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002881 }
2882}
2883
2884/*
2885%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2886% %
2887% %
2888% %
2889% X G e t A n n o t a t e I n f o %
2890% %
2891% %
2892% %
2893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2894%
2895% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2896%
2897% The format of the XGetAnnotateInfo method is:
2898%
2899% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2900%
2901% A description of each parameter follows:
2902%
2903% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2904%
2905*/
cristybcbda3f2011-09-03 13:01:22 +00002906MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002907{
2908 /*
2909 Initialize annotate structure.
2910 */
2911 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2912 assert(annotate_info != (XAnnotateInfo *) NULL);
2913 annotate_info->x=0;
2914 annotate_info->y=0;
2915 annotate_info->width=0;
2916 annotate_info->height=0;
2917 annotate_info->stencil=ForegroundStencil;
2918 annotate_info->degrees=0.0;
2919 annotate_info->font_info=(XFontStruct *) NULL;
2920 annotate_info->text=(char *) NULL;
2921 *annotate_info->geometry='\0';
2922 annotate_info->previous=(XAnnotateInfo *) NULL;
2923 annotate_info->next=(XAnnotateInfo *) NULL;
2924 (void) XSupportsLocale();
2925 (void) XSetLocaleModifiers("");
2926}
2927
2928/*
2929%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2930% %
2931% %
2932% %
2933% X G e t M a p I n f o %
2934% %
2935% %
2936% %
2937%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2938%
2939% XGetMapInfo() initializes the XStandardColormap structure.
2940%
2941% The format of the XStandardColormap method is:
2942%
2943% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2944% XStandardColormap *map_info)
2945%
2946% A description of each parameter follows:
2947%
2948% o colormap: Specifies the ID of the X server colormap.
2949%
2950% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2951% returned from XGetVisualInfo.
2952%
2953% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2954%
2955*/
cristybcbda3f2011-09-03 13:01:22 +00002956MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002957 const Colormap colormap,XStandardColormap *map_info)
2958{
2959 /*
2960 Initialize map info.
2961 */
2962 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2963 assert(visual_info != (XVisualInfo *) NULL);
2964 assert(map_info != (XStandardColormap *) NULL);
2965 map_info->colormap=colormap;
2966 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002967 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002968 if (map_info->red_max != 0)
2969 while ((map_info->red_max & 0x01) == 0)
2970 {
2971 map_info->red_max>>=1;
2972 map_info->red_mult<<=1;
2973 }
2974 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002975 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002976 if (map_info->green_max != 0)
2977 while ((map_info->green_max & 0x01) == 0)
2978 {
2979 map_info->green_max>>=1;
2980 map_info->green_mult<<=1;
2981 }
2982 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002983 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002984 if (map_info->blue_max != 0)
2985 while ((map_info->blue_max & 0x01) == 0)
2986 {
2987 map_info->blue_max>>=1;
2988 map_info->blue_mult<<=1;
2989 }
2990 map_info->base_pixel=0;
2991}
2992
2993/*
2994%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2995% %
2996% %
2997% %
2998% X G e t P i x e l I n f o %
2999% %
3000% %
3001% %
3002%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3003%
cristy101ab702011-10-13 13:06:32 +00003004% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00003005%
cristy4c08aed2011-07-01 19:47:50 +00003006% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00003007%
cristy4c08aed2011-07-01 19:47:50 +00003008% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00003009% const XStandardColormap *map_info,const XResourceInfo *resource_info,
3010% Image *image,XPixelInfo *pixel)
3011% pixel)
3012%
3013% A description of each parameter follows:
3014%
3015% o display: Specifies a connection to an X server; returned from
3016% XOpenDisplay.
3017%
3018% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3019% returned from XGetVisualInfo.
3020%
3021% o map_info: If map_type is specified, this structure is initialized
3022% with info from the Standard Colormap.
3023%
3024% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3025%
3026% o image: the image.
3027%
3028% o pixel: Specifies a pointer to a XPixelInfo structure.
3029%
3030*/
cristybcbda3f2011-09-03 13:01:22 +00003031MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003032 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3033 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3034{
3035 static const char
3036 *PenColors[MaxNumberPens]=
3037 {
3038 "#000000000000", /* black */
3039 "#00000000ffff", /* blue */
3040 "#0000ffffffff", /* cyan */
3041 "#0000ffff0000", /* green */
3042 "#bdbdbdbdbdbd", /* gray */
3043 "#ffff00000000", /* red */
3044 "#ffff0000ffff", /* magenta */
3045 "#ffffffff0000", /* yellow */
3046 "#ffffffffffff", /* white */
3047 "#bdbdbdbdbdbd", /* gray */
3048 "#bdbdbdbdbdbd" /* gray */
3049 };
3050
3051 Colormap
3052 colormap;
3053
cristybcdf5672012-05-24 22:58:54 +00003054 extern const char
3055 BorderColor[],
3056 ForegroundColor[];
3057
cristybb503372010-05-27 20:51:26 +00003058 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003059 i;
3060
3061 Status
3062 status;
3063
3064 unsigned int
3065 packets;
3066
3067 /*
3068 Initialize pixel info.
3069 */
3070 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3071 assert(display != (Display *) NULL);
3072 assert(visual_info != (XVisualInfo *) NULL);
3073 assert(map_info != (XStandardColormap *) NULL);
3074 assert(resource_info != (XResourceInfo *) NULL);
3075 assert(pixel != (XPixelInfo *) NULL);
3076 pixel->colors=0;
3077 if (image != (Image *) NULL)
3078 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003079 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003080 packets=(unsigned int)
3081 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003082 if (pixel->pixels != (unsigned long *) NULL)
3083 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3084 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003085 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003086 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003087 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3088 image->filename);
3089 /*
3090 Set foreground color.
3091 */
3092 colormap=map_info->colormap;
3093 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3094 &pixel->foreground_color);
3095 status=XParseColor(display,colormap,resource_info->foreground_color,
3096 &pixel->foreground_color);
3097 if (status == False)
3098 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3099 resource_info->foreground_color);
3100 pixel->foreground_color.pixel=
3101 XStandardPixel(map_info,&pixel->foreground_color);
3102 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3103 /*
3104 Set background color.
3105 */
3106 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3107 status=XParseColor(display,colormap,resource_info->background_color,
3108 &pixel->background_color);
3109 if (status == False)
3110 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3111 resource_info->background_color);
3112 pixel->background_color.pixel=
3113 XStandardPixel(map_info,&pixel->background_color);
3114 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3115 /*
3116 Set border color.
3117 */
3118 (void) XParseColor(display,colormap,(char *) BorderColor,
3119 &pixel->border_color);
3120 status=XParseColor(display,colormap,resource_info->border_color,
3121 &pixel->border_color);
3122 if (status == False)
3123 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3124 resource_info->border_color);
3125 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3126 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3127 /*
3128 Set matte color.
3129 */
3130 pixel->matte_color=pixel->background_color;
3131 if (resource_info->matte_color != (char *) NULL)
3132 {
3133 /*
3134 Matte color is specified as a X resource or command line argument.
3135 */
3136 status=XParseColor(display,colormap,resource_info->matte_color,
3137 &pixel->matte_color);
3138 if (status == False)
3139 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3140 resource_info->matte_color);
3141 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3142 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3143 }
3144 /*
3145 Set highlight color.
3146 */
3147 pixel->highlight_color.red=(unsigned short) ((
3148 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3149 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3150 pixel->highlight_color.green=(unsigned short) ((
3151 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3152 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3153 pixel->highlight_color.blue=(unsigned short) ((
3154 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3155 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3156 pixel->highlight_color.pixel=
3157 XStandardPixel(map_info,&pixel->highlight_color);
3158 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3159 /*
3160 Set shadow color.
3161 */
cristya19f1d72012-08-07 18:24:38 +00003162 pixel->shadow_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003163 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003164 pixel->shadow_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003165 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003166 pixel->shadow_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003167 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3168 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3169 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3170 /*
3171 Set depth color.
3172 */
cristya19f1d72012-08-07 18:24:38 +00003173 pixel->depth_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003174 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003175 pixel->depth_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003176 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003177 pixel->depth_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003178 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3179 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3180 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3181 /*
3182 Set trough color.
3183 */
cristya19f1d72012-08-07 18:24:38 +00003184 pixel->trough_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003185 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003186 pixel->trough_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003187 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003188 pixel->trough_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003189 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3190 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3191 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3192 /*
3193 Set pen color.
3194 */
3195 for (i=0; i < MaxNumberPens; i++)
3196 {
3197 (void) XParseColor(display,colormap,(char *) PenColors[i],
3198 &pixel->pen_colors[i]);
3199 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3200 &pixel->pen_colors[i]);
3201 if (status == False)
3202 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3203 resource_info->pen_colors[i]);
3204 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3205 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3206 }
3207 pixel->box_color=pixel->background_color;
3208 pixel->pen_color=pixel->foreground_color;
3209 pixel->box_index=0;
3210 pixel->pen_index=1;
3211 if (image != (Image *) NULL)
3212 {
3213 if ((resource_info->gamma_correct != MagickFalse) &&
3214 (image->gamma != 0.0))
3215 {
3216 GeometryInfo
3217 geometry_info;
3218
3219 MagickStatusType
3220 flags;
3221
3222 /*
3223 Initialize map relative to display and image gamma.
3224 */
3225 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3226 red_gamma=geometry_info.rho;
3227 green_gamma=geometry_info.sigma;
3228 if ((flags & SigmaValue) == 0)
3229 green_gamma=red_gamma;
3230 blue_gamma=geometry_info.xi;
3231 if ((flags & XiValue) == 0)
3232 blue_gamma=red_gamma;
3233 red_gamma*=image->gamma;
3234 green_gamma*=image->gamma;
3235 blue_gamma*=image->gamma;
3236 }
3237 if (image->storage_class == PseudoClass)
3238 {
3239 /*
3240 Initialize pixel array for images of type PseudoClass.
3241 */
cristybb503372010-05-27 20:51:26 +00003242 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003243 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003244 for (i=0; i < MaxNumberPens; i++)
3245 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3246 pixel->colors+=MaxNumberPens;
3247 }
3248 }
3249}
3250
3251/*
3252%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3253% %
3254% %
3255% %
3256% X G e t R e s o u r c e C l a s s %
3257% %
3258% %
3259% %
3260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3261%
3262% XGetResourceClass() queries the X server for the specified resource name or
3263% class. If the resource name or class is not defined in the database, the
3264% supplied default value is returned.
3265%
3266% The format of the XGetResourceClass method is:
3267%
3268% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3269% const char *keyword,char *resource_default)
3270%
3271% A description of each parameter follows:
3272%
3273% o database: Specifies a resource database; returned from
3274% XrmGetStringDatabase.
3275%
3276% o client_name: Specifies the application name used to retrieve resource
3277% info from the X server database.
3278%
3279% o keyword: Specifies the keyword of the value being retrieved.
3280%
3281% o resource_default: Specifies the default value to return if the query
3282% fails to find the specified keyword/class.
3283%
3284*/
3285MagickExport char *XGetResourceClass(XrmDatabase database,
3286 const char *client_name,const char *keyword,char *resource_default)
3287{
3288 char
3289 resource_class[MaxTextExtent],
3290 resource_name[MaxTextExtent];
3291
3292 static char
3293 *resource_type;
3294
3295 Status
3296 status;
3297
3298 XrmValue
3299 resource_value;
3300
3301 if (database == (XrmDatabase) NULL)
3302 return(resource_default);
3303 *resource_name='\0';
3304 *resource_class='\0';
3305 if (keyword != (char *) NULL)
3306 {
3307 int
3308 c,
3309 k;
3310
3311 /*
3312 Initialize resource keyword and class.
3313 */
cristyb51dff52011-05-19 16:55:47 +00003314 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003315 client_name,keyword);
3316 c=(int) (*client_name);
3317 if ((c >= XK_a) && (c <= XK_z))
3318 c-=(XK_a-XK_A);
3319 else
3320 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3321 c-=(XK_agrave-XK_Agrave);
3322 else
3323 if ((c >= XK_oslash) && (c <= XK_thorn))
3324 c-=(XK_oslash-XK_Ooblique);
3325 k=(int) (*keyword);
3326 if ((k >= XK_a) && (k <= XK_z))
3327 k-=(XK_a-XK_A);
3328 else
3329 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3330 k-=(XK_agrave-XK_Agrave);
3331 else
3332 if ((k >= XK_oslash) && (k <= XK_thorn))
3333 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003334 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003335 client_name+1,k,keyword+1);
3336 }
3337 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3338 &resource_value);
3339 if (status == False)
3340 return(resource_default);
3341 return(resource_value.addr);
3342}
3343
3344/*
3345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3346% %
3347% %
3348% %
3349% X G e t R e s o u r c e D a t a b a s e %
3350% %
3351% %
3352% %
3353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3354%
3355% XGetResourceDatabase() creates a new resource database and initializes it.
3356%
3357% The format of the XGetResourceDatabase method is:
3358%
3359% XrmDatabase XGetResourceDatabase(Display *display,
3360% const char *client_name)
3361%
3362% A description of each parameter follows:
3363%
3364% o database: XGetResourceDatabase() returns the database after it is
3365% initialized.
3366%
3367% o display: Specifies a connection to an X server; returned from
3368% XOpenDisplay.
3369%
3370% o client_name: Specifies the application name used to retrieve resource
3371% info from the X server database.
3372%
3373*/
3374MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3375 const char *client_name)
3376{
3377 char
3378 filename[MaxTextExtent];
3379
3380 int
3381 c;
3382
3383 register const char
3384 *p;
3385
3386 XrmDatabase
3387 resource_database,
3388 server_database;
3389
3390 if (display == (Display *) NULL)
3391 return((XrmDatabase) NULL);
3392 assert(client_name != (char *) NULL);
3393 /*
3394 Initialize resource database.
3395 */
3396 XrmInitialize();
3397 (void) XGetDefault(display,(char *) client_name,"dummy");
3398 resource_database=XrmGetDatabase(display);
3399 /*
3400 Combine application database.
3401 */
3402 if (client_name != (char *) NULL)
3403 {
3404 /*
3405 Get basename of client.
3406 */
3407 p=client_name+(strlen(client_name)-1);
3408 while ((p > client_name) && (*p != '/'))
3409 p--;
3410 if (*p == '/')
3411 client_name=p+1;
3412 }
3413 c=(int) (*client_name);
3414 if ((c >= XK_a) && (c <= XK_z))
3415 c-=(XK_a-XK_A);
3416 else
3417 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3418 c-=(XK_agrave-XK_Agrave);
3419 else
3420 if ((c >= XK_oslash) && (c <= XK_thorn))
3421 c-=(XK_oslash-XK_Ooblique);
3422#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003423 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003424 X11_APPLICATION_PATH,c,client_name+1);
3425 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3426#endif
3427 if (XResourceManagerString(display) != (char *) NULL)
3428 {
3429 /*
3430 Combine server database.
3431 */
3432 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3433 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3434 }
3435 /*
3436 Merge user preferences database.
3437 */
3438#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003439 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003440 X11_PREFERENCES_PATH,client_name);
3441 ExpandFilename(filename);
3442 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3443#endif
3444 return(resource_database);
3445}
3446
3447/*
3448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3449% %
3450% %
3451% %
3452% X G e t R e s o u r c e I n f o %
3453% %
3454% %
3455% %
3456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3457%
3458% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3459%
3460% The format of the XGetResourceInfo method is:
3461%
3462% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3463% const char *client_name,XResourceInfo *resource_info)
3464%
3465% A description of each parameter follows:
3466%
3467% o image_info: the image info.
3468%
3469% o database: Specifies a resource database; returned from
3470% XrmGetStringDatabase.
3471%
3472% o client_name: Specifies the application name used to retrieve
3473% resource info from the X server database.
3474%
3475% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3476%
3477*/
3478MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3479 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3480{
3481 char
cristy00976d82011-02-20 20:31:28 +00003482 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003483 *resource_value;
3484
cristybcdf5672012-05-24 22:58:54 +00003485 extern const char
3486 BorderColor[],
3487 ForegroundColor[];
3488
cristy3ed852e2009-09-05 21:47:34 +00003489 /*
3490 Initialize resource info fields.
3491 */
3492 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3493 assert(resource_info != (XResourceInfo *) NULL);
3494 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3495 resource_info->resource_database=database;
3496 resource_info->image_info=(ImageInfo *) image_info;
3497 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3498 XMagickProgressMonitor,(void *) NULL);
3499 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3500 resource_info->close_server=MagickTrue;
3501 resource_info->client_name=AcquireString(client_name);
3502 resource_value=XGetResourceClass(database,client_name,"backdrop",
3503 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003504 resource_info->backdrop=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003505 resource_info->background_color=XGetResourceInstance(database,client_name,
3506 "background",(char *) "#d6d6d6d6d6d6");
3507 resource_info->border_color=XGetResourceInstance(database,client_name,
3508 "borderColor",BorderColor);
3509 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3510 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003511 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3512 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003513 resource_value=XGetResourceClass(database,client_name,"colormap",
3514 (char *) "shared");
3515 resource_info->colormap=UndefinedColormap;
3516 if (LocaleCompare("private",resource_value) == 0)
3517 resource_info->colormap=PrivateColormap;
3518 if (LocaleCompare("shared",resource_value) == 0)
3519 resource_info->colormap=SharedColormap;
3520 if (resource_info->colormap == UndefinedColormap)
3521 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3522 resource_value);
3523 resource_value=XGetResourceClass(database,client_name,
3524 "colorRecovery",(char *) "False");
anthony6f201312012-03-30 04:08:15 +00003525 resource_info->color_recovery=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003526 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3527 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003528 resource_info->confirm_exit=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003529 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3530 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003531 resource_info->confirm_edit=IsStringTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003532 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003533 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003534 resource_info->display_gamma=XGetResourceClass(database,client_name,
3535 "displayGamma",(char *) "2.2");
3536 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3537 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003538 resource_info->display_warnings=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003539 resource_info->font=XGetResourceClass(database,client_name,"font",
3540 (char *) NULL);
3541 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3542 resource_info->font);
3543 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3544 (char *) "fixed");
3545 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3546 (char *) "variable");
3547 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3548 (char *) "5x8");
3549 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3550 (char *) "6x10");
3551 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3552 (char *) "7x13bold");
3553 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3554 (char *) "8x13bold");
3555 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3556 (char *) "9x15bold");
3557 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3558 (char *) "10x20");
3559 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3560 (char *) "12x24");
3561 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3562 (char *) "fixed");
3563 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3564 (char *) "fixed");
3565 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3566 "foreground",ForegroundColor);
3567 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
cristy8bc259b2012-06-21 23:53:15 +00003568 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003569 resource_info->gamma_correct=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003570 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3571 client_name,"geometry",(char *) NULL));
3572 resource_value=XGetResourceClass(database,client_name,"gravity",
3573 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003574 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003575 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003576 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3577 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003578 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3579 "iconGeometry",(char *) NULL);
3580 resource_value=XGetResourceClass(database,client_name,"iconic",
3581 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003582 resource_info->iconic=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003583 resource_value=XGetResourceClass(database,client_name,"immutable",
3584 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3585 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003586 resource_info->immutable=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003587 resource_value=XGetResourceClass(database,client_name,"magnify",
3588 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003589 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003590 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3591 (char *) NULL);
3592 resource_info->matte_color=XGetResourceInstance(database,client_name,
3593 "mattecolor",(char *) NULL);
3594 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3595 "name",(char *) NULL));
3596 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3597 (char *) "black");
3598 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3599 (char *) "blue");
3600 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3601 (char *) "cyan");
3602 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3603 (char *) "green");
3604 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3605 (char *) "gray");
3606 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3607 (char *) "red");
3608 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3609 (char *) "magenta");
3610 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3611 (char *) "yellow");
3612 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3613 (char *) "white");
3614 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3615 (char *) "gray");
3616 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3617 (char *) "gray");
3618 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003619 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003620 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003621 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003622 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3623 "font",(char *) "fixed");
3624 resource_info->text_font=XGetResourceClass(database,client_name,
3625 "textFontList",resource_info->text_font);
3626 resource_info->title=XGetResourceClass(database,client_name,"title",
3627 (char *) NULL);
3628 resource_value=XGetResourceClass(database,client_name,"undoCache",
cristy92befbd2012-09-16 14:08:12 +00003629 (char *) "256");
cristye27293e2009-12-18 02:53:20 +00003630 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003631 resource_value=XGetResourceClass(database,client_name,"update",
3632 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003633 resource_info->update=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003634 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3635 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003636 resource_info->use_pixmap=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003637 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3638 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003639 resource_info->use_shared_memory=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003640 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3641 (char *) NULL);
3642 resource_info->window_group=XGetResourceClass(database,client_name,
3643 "windowGroup",(char *) NULL);
3644 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3645 (char *) NULL);
3646 resource_info->write_filename=XGetResourceClass(database,client_name,
3647 "writeFilename",(char *) NULL);
3648}
3649
3650/*
3651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3652% %
3653% %
3654% %
3655% X G e t R e s o u r c e I n s t a n c e %
3656% %
3657% %
3658% %
3659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3660%
3661% XGetResourceInstance() queries the X server for the specified resource name.
3662% If the resource name is not defined in the database, the supplied default
3663% value is returned.
3664%
3665% The format of the XGetResourceInstance method is:
3666%
3667% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3668% const char *keyword,const char *resource_default)
3669%
3670% A description of each parameter follows:
3671%
3672% o database: Specifies a resource database; returned from
3673% XrmGetStringDatabase.
3674%
3675% o client_name: Specifies the application name used to retrieve
3676% resource info from the X server database.
3677%
3678% o keyword: Specifies the keyword of the value being retrieved.
3679%
3680% o resource_default: Specifies the default value to return if the query
3681% fails to find the specified keyword/class.
3682%
3683*/
3684MagickExport char *XGetResourceInstance(XrmDatabase database,
3685 const char *client_name,const char *keyword,const char *resource_default)
3686{
3687 char
3688 *resource_type,
3689 resource_name[MaxTextExtent];
3690
3691 Status
3692 status;
3693
3694 XrmValue
3695 resource_value;
3696
3697 if (database == (XrmDatabase) NULL)
3698 return((char *) resource_default);
3699 *resource_name='\0';
3700 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003701 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003702 keyword);
3703 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3704 &resource_value);
3705 if (status == False)
3706 return((char *) resource_default);
3707 return(resource_value.addr);
3708}
3709
3710/*
3711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3712% %
3713% %
3714% %
3715% X G e t S c r e e n D e n s i t y %
3716% %
3717% %
3718% %
3719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3720%
3721% XGetScreenDensity() returns the density of the X server screen in
3722% dots-per-inch.
3723%
3724% The format of the XGetScreenDensity method is:
3725%
3726% char *XGetScreenDensity(Display *display)
3727%
3728% A description of each parameter follows:
3729%
3730% o density: XGetScreenDensity() returns the density of the X screen in
3731% dots-per-inch.
3732%
3733% o display: Specifies a connection to an X server; returned from
3734% XOpenDisplay.
3735%
3736*/
3737MagickExport char *XGetScreenDensity(Display *display)
3738{
3739 char
3740 density[MaxTextExtent];
3741
3742 double
3743 x_density,
3744 y_density;
3745
3746 /*
3747 Set density as determined by screen size.
3748 */
3749 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3750 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3751 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3752 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003753 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003754 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003755 return(GetPageGeometry(density));
3756}
3757
3758/*
3759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3760% %
3761% %
3762% %
3763+ X G e t S u b w i n d o w %
3764% %
3765% %
3766% %
3767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3768%
3769% XGetSubwindow() returns the subwindow of a window chosen the user with the
3770% pointer and a button press.
3771%
3772% The format of the XGetSubwindow method is:
3773%
3774% Window XGetSubwindow(Display *display,Window window,int x,int y)
3775%
3776% A description of each parameter follows:
3777%
3778% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3779% otherwise the subwindow is returned.
3780%
3781% o display: Specifies a connection to an X server; returned from
3782% XOpenDisplay.
3783%
3784% o window: Specifies a pointer to a Window.
3785%
3786% o x: the x coordinate of the pointer relative to the origin of the
3787% window.
3788%
3789% o y: the y coordinate of the pointer relative to the origin of the
3790% window.
3791%
cristy3ed852e2009-09-05 21:47:34 +00003792*/
3793static Window XGetSubwindow(Display *display,Window window,int x,int y)
3794{
3795 int
3796 x_offset,
3797 y_offset;
3798
3799 Status
3800 status;
3801
3802 Window
3803 source_window,
3804 target_window;
3805
3806 assert(display != (Display *) NULL);
3807 source_window=XRootWindow(display,XDefaultScreen(display));
3808 if (window == (Window) NULL)
3809 return(source_window);
3810 target_window=window;
3811 for ( ; ; )
3812 {
3813 status=XTranslateCoordinates(display,source_window,window,x,y,
3814 &x_offset,&y_offset,&target_window);
3815 if (status != True)
3816 break;
3817 if (target_window == (Window) NULL)
3818 break;
3819 source_window=window;
3820 window=target_window;
3821 x=x_offset;
3822 y=y_offset;
3823 }
3824 if (target_window == (Window) NULL)
3825 target_window=window;
3826 return(target_window);
3827}
3828
3829/*
3830%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3831% %
3832% %
3833% %
3834% X G e t W i n d o w C o l o r %
3835% %
3836% %
3837% %
3838%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3839%
3840% XGetWindowColor() returns the color of a pixel interactively chosen from the
3841% X server.
3842%
3843% The format of the XGetWindowColor method is:
3844%
3845% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003846% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003847%
3848% A description of each parameter follows:
3849%
3850% o display: Specifies a connection to an X server; returned from
3851% XOpenDisplay.
3852%
3853% o windows: Specifies a pointer to a XWindows structure.
3854%
3855% o name: the name of the color if found in the X Color Database is
3856% returned in this character string.
3857%
cristy6710d842011-10-20 23:23:00 +00003858% o exception: return any errors or warnings in this structure.
3859%
cristy3ed852e2009-09-05 21:47:34 +00003860*/
cristybcbda3f2011-09-03 13:01:22 +00003861MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003862 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003863{
3864 int
3865 x,
3866 y;
3867
cristy101ab702011-10-13 13:06:32 +00003868 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003869 pixel;
3870
3871 RectangleInfo
3872 crop_info;
3873
3874 Status
3875 status;
3876
3877 Window
3878 child,
3879 client_window,
3880 root_window,
3881 target_window;
3882
3883 XColor
3884 color;
3885
3886 XImage
3887 *ximage;
3888
3889 XWindowAttributes
3890 window_attributes;
3891
3892 /*
3893 Choose a pixel from the X server.
3894 */
3895 assert(display != (Display *) NULL);
3896 assert(name != (char *) NULL);
3897 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3898 *name='\0';
3899 target_window=XSelectWindow(display,&crop_info);
3900 if (target_window == (Window) NULL)
3901 return(MagickFalse);
3902 root_window=XRootWindow(display,XDefaultScreen(display));
3903 client_window=target_window;
3904 if (target_window != root_window)
3905 {
3906 unsigned int
3907 d;
3908
3909 /*
3910 Get client window.
3911 */
3912 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3913 if (status != False)
3914 {
3915 client_window=XClientWindow(display,target_window);
3916 target_window=client_window;
3917 }
3918 }
3919 /*
3920 Verify window is viewable.
3921 */
3922 status=XGetWindowAttributes(display,target_window,&window_attributes);
3923 if ((status == False) || (window_attributes.map_state != IsViewable))
3924 return(MagickFalse);
3925 /*
3926 Get window X image.
3927 */
3928 (void) XTranslateCoordinates(display,root_window,target_window,
3929 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3930 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3931 if (ximage == (XImage *) NULL)
3932 return(MagickFalse);
3933 color.pixel=XGetPixel(ximage,0,0);
3934 XDestroyImage(ximage);
3935 /*
3936 Match color against the color database.
3937 */
3938 (void) XQueryColor(display,window_attributes.colormap,&color);
cristye42f6582012-02-11 17:59:50 +00003939 pixel.red=(double) ScaleShortToQuantum(color.red);
3940 pixel.green=(double) ScaleShortToQuantum(color.green);
3941 pixel.blue=(double) ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003942 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003943 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003944 exception);
cristy3ed852e2009-09-05 21:47:34 +00003945 return(MagickTrue);
3946}
3947
3948/*
3949%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3950% %
3951% %
3952% %
3953+ X G e t W i n d o w I m a g e %
3954% %
3955% %
3956% %
3957%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3958%
3959% XGetWindowImage() reads an image from the target X window and returns it.
3960% XGetWindowImage() optionally descends the window hierarchy and overlays the
3961% target image with each child image in an optimized fashion. Any child
3962% window that have the same visual, colormap, and are contained by its parent
3963% are exempted.
3964%
3965% The format of the XGetWindowImage method is:
3966%
3967% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003968% const unsigned int borders,const unsigned int level,
3969% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003970%
3971% A description of each parameter follows:
3972%
3973% o display: Specifies a connection to an X server; returned from
3974% XOpenDisplay.
3975%
3976% o window: Specifies the window to obtain the image from.
3977%
3978% o borders: Specifies whether borders pixels are to be saved with
3979% the image.
3980%
3981% o level: Specifies an unsigned integer representing the level of
3982% decent in the window hierarchy. This value must be zero or one on
3983% the initial call to XGetWindowImage. A value of zero returns after
3984% one call. A value of one causes the function to descend the window
3985% hierarchy and overlay the target image with each subwindow image.
3986%
cristy6710d842011-10-20 23:23:00 +00003987% o exception: return any errors or warnings in this structure.
3988%
cristy3ed852e2009-09-05 21:47:34 +00003989*/
3990static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003991 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003992{
3993 typedef struct _ColormapInfo
3994 {
3995 Colormap
3996 colormap;
3997
3998 XColor
3999 *colors;
4000
4001 struct _ColormapInfo
4002 *next;
4003 } ColormapInfo;
4004
4005 typedef struct _WindowInfo
4006 {
4007 Window
4008 window,
4009 parent;
4010
4011 Visual
4012 *visual;
4013
4014 Colormap
4015 colormap;
4016
4017 XSegment
4018 bounds;
4019
4020 RectangleInfo
4021 crop_info;
4022 } WindowInfo;
4023
cristy3ed852e2009-09-05 21:47:34 +00004024 int
4025 display_height,
4026 display_width,
4027 id,
4028 x_offset,
4029 y_offset;
4030
cristy4c08aed2011-07-01 19:47:50 +00004031 Quantum
4032 index;
4033
cristy3ed852e2009-09-05 21:47:34 +00004034 RectangleInfo
4035 crop_info;
4036
cristy3ed852e2009-09-05 21:47:34 +00004037 register int
4038 i;
4039
4040 static ColormapInfo
4041 *colormap_info = (ColormapInfo *) NULL;
4042
4043 static int
4044 max_windows = 0,
4045 number_windows = 0;
4046
4047 static WindowInfo
4048 *window_info;
4049
4050 Status
4051 status;
4052
4053 Window
4054 child,
4055 root_window;
4056
4057 XWindowAttributes
4058 window_attributes;
4059
4060 /*
4061 Verify window is viewable.
4062 */
4063 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4064 assert(display != (Display *) NULL);
4065 status=XGetWindowAttributes(display,window,&window_attributes);
4066 if ((status == False) || (window_attributes.map_state != IsViewable))
4067 return((Image *) NULL);
4068 /*
4069 Cropping rectangle is relative to root window.
4070 */
4071 root_window=XRootWindow(display,XDefaultScreen(display));
4072 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4073 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004074 crop_info.x=(ssize_t) x_offset;
4075 crop_info.y=(ssize_t) y_offset;
4076 crop_info.width=(size_t) window_attributes.width;
4077 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004078 if (borders != MagickFalse)
4079 {
4080 /*
4081 Include border in image.
4082 */
cristybb503372010-05-27 20:51:26 +00004083 crop_info.x-=(ssize_t) window_attributes.border_width;
4084 crop_info.y-=(ssize_t) window_attributes.border_width;
4085 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4086 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004087 }
4088 /*
4089 Crop to root window.
4090 */
4091 if (crop_info.x < 0)
4092 {
4093 crop_info.width+=crop_info.x;
4094 crop_info.x=0;
4095 }
4096 if (crop_info.y < 0)
4097 {
4098 crop_info.height+=crop_info.y;
4099 crop_info.y=0;
4100 }
4101 display_width=XDisplayWidth(display,XDefaultScreen(display));
4102 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004103 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004104 display_height=XDisplayHeight(display,XDefaultScreen(display));
4105 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004106 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004107 /*
4108 Initialize window info attributes.
4109 */
4110 if (number_windows >= max_windows)
4111 {
4112 /*
4113 Allocate or resize window info buffer.
4114 */
4115 max_windows+=1024;
4116 if (window_info == (WindowInfo *) NULL)
4117 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4118 sizeof(*window_info));
4119 else
4120 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4121 max_windows,sizeof(*window_info));
4122 }
4123 if (window_info == (WindowInfo *) NULL)
4124 {
4125 ThrowXWindowFatalException(ResourceLimitError,
4126 "MemoryAllocationFailed","...");
4127 return((Image *) NULL);
4128 }
4129 id=number_windows++;
4130 window_info[id].window=window;
4131 window_info[id].visual=window_attributes.visual;
4132 window_info[id].colormap=window_attributes.colormap;
4133 window_info[id].bounds.x1=(short) crop_info.x;
4134 window_info[id].bounds.y1=(short) crop_info.y;
4135 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4136 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4137 crop_info.x-=x_offset;
4138 crop_info.y-=y_offset;
4139 window_info[id].crop_info=crop_info;
4140 if (level != 0)
4141 {
4142 unsigned int
4143 number_children;
4144
4145 Window
4146 *children;
4147
4148 /*
4149 Descend the window hierarchy.
4150 */
4151 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4152 &children,&number_children);
4153 for (i=0; i < id; i++)
4154 if ((window_info[i].window == window_info[id].parent) &&
4155 (window_info[i].visual == window_info[id].visual) &&
4156 (window_info[i].colormap == window_info[id].colormap))
4157 {
cristy64057b02013-01-11 00:09:58 +00004158 if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
4159 (window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
4160 (window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
4161 (window_info[id].bounds.y2 > window_info[i].bounds.y2))
cristy3ed852e2009-09-05 21:47:34 +00004162 {
4163 /*
4164 Eliminate windows not circumscribed by their parent.
4165 */
4166 number_windows--;
4167 break;
4168 }
4169 }
4170 if ((status == True) && (number_children != 0))
4171 {
4172 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004173 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4174 exception);
cristy3ed852e2009-09-05 21:47:34 +00004175 (void) XFree((void *) children);
4176 }
4177 }
4178 if (level <= 1)
4179 {
cristyc57f6942010-11-12 01:47:39 +00004180 CacheView
4181 *composite_view;
4182
cristy3ed852e2009-09-05 21:47:34 +00004183 ColormapInfo
4184 *next;
4185
cristy3ed852e2009-09-05 21:47:34 +00004186 Image
4187 *composite_image,
4188 *image;
4189
4190 int
4191 y;
4192
4193 MagickBooleanType
4194 import;
4195
4196 register int
4197 j,
4198 x;
4199
cristy4c08aed2011-07-01 19:47:50 +00004200 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004201 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004202
cristybb503372010-05-27 20:51:26 +00004203 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004204 pixel;
4205
4206 unsigned int
4207 number_colors;
4208
4209 XColor
4210 *colors;
4211
4212 XImage
4213 *ximage;
4214
4215 /*
4216 Get X image for each window in the list.
4217 */
4218 image=NewImageList();
4219 for (id=0; id < number_windows; id++)
4220 {
4221 /*
4222 Does target window intersect top level window?
4223 */
cristy088af952013-08-19 18:34:20 +00004224 import=((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
cristy3ed852e2009-09-05 21:47:34 +00004225 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4226 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4227 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4228 MagickTrue : MagickFalse;
4229 /*
4230 Is target window contained by another window with the same colormap?
4231 */
4232 for (j=0; j < id; j++)
4233 if ((window_info[id].visual == window_info[j].visual) &&
4234 (window_info[id].colormap == window_info[j].colormap))
4235 {
cristy64057b02013-01-11 00:09:58 +00004236 if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
4237 (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
4238 (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
4239 (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
cristy088af952013-08-19 18:34:20 +00004240 import=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00004241 }
cristy3ed852e2009-09-05 21:47:34 +00004242 if (import == MagickFalse)
4243 continue;
4244 /*
4245 Get X image.
4246 */
4247 ximage=XGetImage(display,window_info[id].window,(int)
4248 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4249 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4250 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4251 if (ximage == (XImage *) NULL)
4252 continue;
4253 /*
4254 Initialize window colormap.
4255 */
4256 number_colors=0;
4257 colors=(XColor *) NULL;
4258 if (window_info[id].colormap != (Colormap) NULL)
4259 {
4260 ColormapInfo
4261 *p;
4262
4263 /*
4264 Search colormap list for window colormap.
4265 */
4266 number_colors=(unsigned int) window_info[id].visual->map_entries;
4267 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4268 if (p->colormap == window_info[id].colormap)
4269 break;
4270 if (p == (ColormapInfo *) NULL)
4271 {
4272 /*
4273 Get the window colormap.
4274 */
4275 colors=(XColor *) AcquireQuantumMemory(number_colors,
4276 sizeof(*colors));
4277 if (colors == (XColor *) NULL)
4278 {
4279 XDestroyImage(ximage);
4280 return((Image *) NULL);
4281 }
4282 if ((window_info[id].visual->klass != DirectColor) &&
4283 (window_info[id].visual->klass != TrueColor))
4284 for (i=0; i < (int) number_colors; i++)
4285 {
cristybb503372010-05-27 20:51:26 +00004286 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004287 colors[i].pad='\0';
4288 }
4289 else
4290 {
cristybb503372010-05-27 20:51:26 +00004291 size_t
cristy3ed852e2009-09-05 21:47:34 +00004292 blue,
4293 blue_bit,
4294 green,
4295 green_bit,
4296 red,
4297 red_bit;
4298
4299 /*
4300 DirectColor or TrueColor visual.
4301 */
4302 red=0;
4303 green=0;
4304 blue=0;
4305 red_bit=window_info[id].visual->red_mask &
4306 (~(window_info[id].visual->red_mask)+1);
4307 green_bit=window_info[id].visual->green_mask &
4308 (~(window_info[id].visual->green_mask)+1);
4309 blue_bit=window_info[id].visual->blue_mask &
4310 (~(window_info[id].visual->blue_mask)+1);
4311 for (i=0; i < (int) number_colors; i++)
4312 {
cristy8891f9c2010-06-04 23:32:17 +00004313 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004314 colors[i].pad='\0';
4315 red+=red_bit;
4316 if (red > window_info[id].visual->red_mask)
4317 red=0;
4318 green+=green_bit;
4319 if (green > window_info[id].visual->green_mask)
4320 green=0;
4321 blue+=blue_bit;
4322 if (blue > window_info[id].visual->blue_mask)
4323 blue=0;
4324 }
4325 }
4326 (void) XQueryColors(display,window_info[id].colormap,colors,
4327 (int) number_colors);
4328 /*
4329 Append colormap to colormap list.
4330 */
cristy73bd4a52010-10-05 11:24:23 +00004331 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004332 if (p == (ColormapInfo *) NULL)
4333 return((Image *) NULL);
4334 p->colormap=window_info[id].colormap;
4335 p->colors=colors;
4336 p->next=colormap_info;
4337 colormap_info=p;
4338 }
4339 colors=p->colors;
4340 }
4341 /*
4342 Allocate image structure.
4343 */
cristy6710d842011-10-20 23:23:00 +00004344 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004345 if (composite_image == (Image *) NULL)
4346 {
4347 XDestroyImage(ximage);
4348 return((Image *) NULL);
4349 }
4350 /*
4351 Convert X image to MIFF format.
4352 */
4353 if ((window_info[id].visual->klass != TrueColor) &&
4354 (window_info[id].visual->klass != DirectColor))
4355 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004356 composite_image->columns=(size_t) ximage->width;
4357 composite_image->rows=(size_t) ximage->height;
cristy46ff2672012-12-14 15:32:26 +00004358 composite_view=AcquireAuthenticCacheView(composite_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00004359 switch (composite_image->storage_class)
4360 {
4361 case DirectClass:
4362 default:
4363 {
cristybb503372010-05-27 20:51:26 +00004364 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004365 color,
4366 index;
4367
cristybb503372010-05-27 20:51:26 +00004368 size_t
cristy3ed852e2009-09-05 21:47:34 +00004369 blue_mask,
4370 blue_shift,
4371 green_mask,
4372 green_shift,
4373 red_mask,
4374 red_shift;
4375
4376 /*
4377 Determine shift and mask for red, green, and blue.
4378 */
4379 red_mask=window_info[id].visual->red_mask;
4380 red_shift=0;
4381 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4382 {
4383 red_mask>>=1;
4384 red_shift++;
4385 }
4386 green_mask=window_info[id].visual->green_mask;
4387 green_shift=0;
4388 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4389 {
4390 green_mask>>=1;
4391 green_shift++;
4392 }
4393 blue_mask=window_info[id].visual->blue_mask;
4394 blue_shift=0;
4395 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4396 {
4397 blue_mask>>=1;
4398 blue_shift++;
4399 }
4400 /*
4401 Convert X image to DirectClass packets.
4402 */
4403 if ((number_colors != 0) &&
4404 (window_info[id].visual->klass == DirectColor))
4405 for (y=0; y < (int) composite_image->rows; y++)
4406 {
cristyc57f6942010-11-12 01:47:39 +00004407 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004408 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004409 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004410 break;
4411 for (x=0; x < (int) composite_image->columns; x++)
4412 {
4413 pixel=XGetPixel(ximage,x,y);
4414 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004415 SetPixelRed(composite_image,
4416 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004417 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004418 SetPixelGreen(composite_image,
4419 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004420 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004421 SetPixelBlue(composite_image,
4422 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004423 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004424 }
cristy0b1a7972011-10-22 22:17:02 +00004425 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4426 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004427 break;
4428 }
4429 else
4430 for (y=0; y < (int) composite_image->rows; y++)
4431 {
cristyc57f6942010-11-12 01:47:39 +00004432 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004433 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004434 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004435 break;
4436 for (x=0; x < (int) composite_image->columns; x++)
4437 {
4438 pixel=XGetPixel(ximage,x,y);
4439 color=(pixel >> red_shift) & red_mask;
4440 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004441 SetPixelRed(composite_image,
4442 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004443 color=(pixel >> green_shift) & green_mask;
4444 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004445 SetPixelGreen(composite_image,
4446 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004447 color=(pixel >> blue_shift) & blue_mask;
4448 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004449 SetPixelBlue(composite_image,
4450 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004451 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004452 }
cristy0b1a7972011-10-22 22:17:02 +00004453 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4454 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004455 break;
4456 }
4457 break;
4458 }
4459 case PseudoClass:
4460 {
4461 /*
4462 Create colormap.
4463 */
cristy0b1a7972011-10-22 22:17:02 +00004464 status=AcquireImageColormap(composite_image,number_colors,
4465 exception);
4466 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004467 {
4468 XDestroyImage(ximage);
4469 composite_image=DestroyImage(composite_image);
4470 return((Image *) NULL);
4471 }
4472 for (i=0; i < (int) composite_image->colors; i++)
4473 {
cristye42f6582012-02-11 17:59:50 +00004474 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004475 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004476 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004477 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004478 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004479 ScaleShortToQuantum(colors[i].blue);
4480 }
4481 /*
4482 Convert X image to PseudoClass packets.
4483 */
4484 for (y=0; y < (int) composite_image->rows; y++)
4485 {
cristyc57f6942010-11-12 01:47:39 +00004486 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4487 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004488 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004489 break;
cristy3ed852e2009-09-05 21:47:34 +00004490 for (x=0; x < (int) composite_image->columns; x++)
4491 {
cristy4c08aed2011-07-01 19:47:50 +00004492 index=(Quantum) XGetPixel(ximage,x,y);
4493 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004494 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004495 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004496 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004497 }
cristy0b1a7972011-10-22 22:17:02 +00004498 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4499 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004500 break;
4501 }
4502 break;
4503 }
4504 }
cristyc57f6942010-11-12 01:47:39 +00004505 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004506 XDestroyImage(ximage);
4507 if (image == (Image *) NULL)
4508 {
4509 image=composite_image;
4510 continue;
4511 }
4512 /*
4513 Composite any children in back-to-front order.
4514 */
4515 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4516 &x_offset,&y_offset,&child);
4517 x_offset-=(int) crop_info.x;
4518 if (x_offset < 0)
4519 x_offset=0;
4520 y_offset-=(int) crop_info.y;
4521 if (y_offset < 0)
4522 y_offset=0;
cristy39172402012-03-30 13:04:39 +00004523 (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00004524 (ssize_t) x_offset,(ssize_t) y_offset,exception);
cristy5f257b22012-03-07 00:27:29 +00004525 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004526 }
4527 /*
4528 Relinquish resources.
4529 */
4530 while (colormap_info != (ColormapInfo *) NULL)
4531 {
4532 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004533 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4534 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004535 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4536 colormap_info=next;
4537 }
4538 /*
4539 Relinquish resources and restore initial state.
4540 */
4541 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4542 max_windows=0;
4543 number_windows=0;
4544 colormap_info=(ColormapInfo *) NULL;
4545 return(image);
4546 }
4547 return((Image *) NULL);
4548}
4549
4550/*
4551%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4552% %
4553% %
4554% %
4555% X G e t W i n d o w I n f o %
4556% %
4557% %
4558% %
4559%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4560%
4561% XGetWindowInfo() initializes the XWindowInfo structure.
4562%
4563% The format of the XGetWindowInfo method is:
4564%
4565% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4566% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4567% XResourceInfo *resource_info,XWindowInfo *window)
4568% resource_info,window)
4569%
4570% A description of each parameter follows:
4571%
4572% o display: Specifies a connection to an X server; returned from
4573% XOpenDisplay.
4574%
4575% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4576% returned from XGetVisualInfo.
4577%
4578% o map_info: If map_type is specified, this structure is initialized
4579% with info from the Standard Colormap.
4580%
4581% o pixel: Specifies a pointer to a XPixelInfo structure.
4582%
4583% o font_info: Specifies a pointer to a XFontStruct structure.
4584%
4585% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4586%
4587*/
cristybcbda3f2011-09-03 13:01:22 +00004588MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004589 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4590 XResourceInfo *resource_info,XWindowInfo *window)
4591{
4592 /*
4593 Initialize window info.
4594 */
4595 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4596 assert(display != (Display *) NULL);
4597 assert(visual_info != (XVisualInfo *) NULL);
4598 assert(map_info != (XStandardColormap *) NULL);
4599 assert(pixel != (XPixelInfo *) NULL);
4600 assert(resource_info != (XResourceInfo *) NULL);
4601 assert(window != (XWindowInfo *) NULL);
4602 if (window->id != (Window) NULL)
4603 {
4604 if (window->cursor != (Cursor) NULL)
4605 (void) XFreeCursor(display,window->cursor);
4606 if (window->busy_cursor != (Cursor) NULL)
4607 (void) XFreeCursor(display,window->busy_cursor);
4608 if (window->highlight_stipple != (Pixmap) NULL)
4609 (void) XFreePixmap(display,window->highlight_stipple);
4610 if (window->shadow_stipple != (Pixmap) NULL)
4611 (void) XFreePixmap(display,window->shadow_stipple);
4612 if (window->name == (char *) NULL)
4613 window->name=AcquireString("");
4614 if (window->icon_name == (char *) NULL)
4615 window->icon_name=AcquireString("");
4616 }
4617 else
4618 {
4619 /*
4620 Initialize these attributes just once.
4621 */
4622 window->id=(Window) NULL;
4623 if (window->name == (char *) NULL)
4624 window->name=AcquireString("");
4625 if (window->icon_name == (char *) NULL)
4626 window->icon_name=AcquireString("");
4627 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4628 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4629 window->ximage=(XImage *) NULL;
4630 window->matte_image=(XImage *) NULL;
4631 window->pixmap=(Pixmap) NULL;
4632 window->matte_pixmap=(Pixmap) NULL;
4633 window->mapped=MagickFalse;
4634 window->stasis=MagickFalse;
4635 window->shared_memory=MagickTrue;
4636 window->segment_info=(void *) NULL;
4637#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4638 {
4639 XShmSegmentInfo
4640 *segment_info;
4641
4642 if (window->segment_info == (void *) NULL)
4643 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4644 segment_info=(XShmSegmentInfo *) window->segment_info;
4645 segment_info[0].shmid=(-1);
4646 segment_info[0].shmaddr=(char *) NULL;
4647 segment_info[1].shmid=(-1);
4648 segment_info[1].shmaddr=(char *) NULL;
4649 }
4650#endif
4651 }
4652 /*
4653 Initialize these attributes every time function is called.
4654 */
4655 window->screen=visual_info->screen;
4656 window->root=XRootWindow(display,visual_info->screen);
4657 window->visual=visual_info->visual;
4658 window->storage_class=(unsigned int) visual_info->klass;
4659 window->depth=(unsigned int) visual_info->depth;
4660 window->visual_info=visual_info;
4661 window->map_info=map_info;
4662 window->pixel_info=pixel;
4663 window->font_info=font_info;
4664 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4665 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4666 window->geometry=(char *) NULL;
4667 window->icon_geometry=(char *) NULL;
4668 if (resource_info->icon_geometry != (char *) NULL)
4669 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4670 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004671 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004672 window->width=1;
4673 window->height=1;
4674 window->min_width=1;
4675 window->min_height=1;
4676 window->width_inc=1;
4677 window->height_inc=1;
4678 window->border_width=resource_info->border_width;
4679 window->annotate_context=pixel->annotate_context;
4680 window->highlight_context=pixel->highlight_context;
4681 window->widget_context=pixel->widget_context;
4682 window->shadow_stipple=(Pixmap) NULL;
4683 window->highlight_stipple=(Pixmap) NULL;
4684 window->use_pixmap=MagickTrue;
4685 window->immutable=MagickFalse;
4686 window->shape=MagickFalse;
4687 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004688 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004689 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4690 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4691 window->attributes.background_pixel=pixel->background_color.pixel;
4692 window->attributes.background_pixmap=(Pixmap) NULL;
4693 window->attributes.bit_gravity=ForgetGravity;
4694 window->attributes.backing_store=WhenMapped;
4695 window->attributes.save_under=MagickTrue;
4696 window->attributes.border_pixel=pixel->border_color.pixel;
4697 window->attributes.colormap=map_info->colormap;
4698 window->attributes.cursor=window->cursor;
4699 window->attributes.do_not_propagate_mask=NoEventMask;
4700 window->attributes.event_mask=NoEventMask;
4701 window->attributes.override_redirect=MagickFalse;
4702 window->attributes.win_gravity=NorthWestGravity;
4703 window->orphan=MagickFalse;
4704}
4705
4706/*
4707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4708% %
4709% %
4710% %
4711% X H i g h l i g h t E l l i p s e %
4712% %
4713% %
4714% %
4715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4716%
4717% XHighlightEllipse() puts a border on the X server around a region defined by
4718% highlight_info.
4719%
4720% The format of the XHighlightEllipse method is:
4721%
4722% void XHighlightEllipse(Display *display,Window window,
4723% GC annotate_context,const RectangleInfo *highlight_info)
4724%
4725% A description of each parameter follows:
4726%
4727% o display: Specifies a connection to an X server; returned from
4728% XOpenDisplay.
4729%
4730% o window: Specifies a pointer to a Window structure.
4731%
4732% o annotate_context: Specifies a pointer to a GC structure.
4733%
4734% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4735% contains the extents of any highlighting rectangle.
4736%
4737*/
cristybcbda3f2011-09-03 13:01:22 +00004738MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004739 GC annotate_context,const RectangleInfo *highlight_info)
4740{
4741 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4742 assert(display != (Display *) NULL);
4743 assert(window != (Window) NULL);
4744 assert(annotate_context != (GC) NULL);
4745 assert(highlight_info != (RectangleInfo *) NULL);
4746 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4747 return;
4748 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4749 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4750 (unsigned int) highlight_info->height-1,0,360*64);
4751 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4752 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4753 (unsigned int) highlight_info->height-3,0,360*64);
4754}
4755
4756/*
4757%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4758% %
4759% %
4760% %
4761% X H i g h l i g h t L i n e %
4762% %
4763% %
4764% %
4765%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4766%
4767% XHighlightLine() puts a border on the X server around a region defined by
4768% highlight_info.
4769%
4770% The format of the XHighlightLine method is:
4771%
4772% void XHighlightLine(Display *display,Window window,GC annotate_context,
4773% const XSegment *highlight_info)
4774%
4775% A description of each parameter follows:
4776%
4777% o display: Specifies a connection to an X server; returned from
4778% XOpenDisplay.
4779%
4780% o window: Specifies a pointer to a Window structure.
4781%
4782% o annotate_context: Specifies a pointer to a GC structure.
4783%
4784% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4785% contains the extents of any highlighting rectangle.
4786%
4787*/
cristybcbda3f2011-09-03 13:01:22 +00004788MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004789 GC annotate_context,const XSegment *highlight_info)
4790{
4791 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4792 assert(display != (Display *) NULL);
4793 assert(window != (Window) NULL);
4794 assert(annotate_context != (GC) NULL);
4795 assert(highlight_info != (XSegment *) NULL);
4796 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4797 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4798}
4799
4800/*
4801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4802% %
4803% %
4804% %
4805% X H i g h l i g h t R e c t a n g l e %
4806% %
4807% %
4808% %
4809%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4810%
4811% XHighlightRectangle() puts a border on the X server around a region defined
4812% by highlight_info.
4813%
4814% The format of the XHighlightRectangle method is:
4815%
4816% void XHighlightRectangle(Display *display,Window window,
4817% GC annotate_context,const RectangleInfo *highlight_info)
4818%
4819% A description of each parameter follows:
4820%
4821% o display: Specifies a connection to an X server; returned from
4822% XOpenDisplay.
4823%
4824% o window: Specifies a pointer to a Window structure.
4825%
4826% o annotate_context: Specifies a pointer to a GC structure.
4827%
4828% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4829% contains the extents of any highlighting rectangle.
4830%
4831*/
cristybcbda3f2011-09-03 13:01:22 +00004832MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004833 GC annotate_context,const RectangleInfo *highlight_info)
4834{
4835 assert(display != (Display *) NULL);
4836 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4837 assert(window != (Window) NULL);
4838 assert(annotate_context != (GC) NULL);
4839 assert(highlight_info != (RectangleInfo *) NULL);
4840 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4841 return;
4842 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4843 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4844 (unsigned int) highlight_info->height-1);
4845 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4846 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4847 (unsigned int) highlight_info->height-3);
4848}
4849
4850/*
4851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4852% %
4853% %
4854% %
4855% X I m p o r t I m a g e %
4856% %
4857% %
4858% %
4859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4860%
4861% XImportImage() reads an image from an X window.
4862%
4863% The format of the XImportImage method is:
4864%
cristy6710d842011-10-20 23:23:00 +00004865% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4866% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004867%
4868% A description of each parameter follows:
4869%
4870% o image_info: the image info.
4871%
4872% o ximage_info: Specifies a pointer to an XImportInfo structure.
4873%
cristy6710d842011-10-20 23:23:00 +00004874% o exception: return any errors or warnings in this structure.
4875%
cristy3ed852e2009-09-05 21:47:34 +00004876*/
4877MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004878 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004879{
4880 Colormap
4881 *colormaps;
4882
4883 Display
4884 *display;
4885
4886 Image
4887 *image;
4888
4889 int
4890 number_colormaps,
4891 number_windows,
4892 x;
4893
4894 RectangleInfo
4895 crop_info;
4896
4897 Status
4898 status;
4899
4900 Window
4901 *children,
4902 client,
4903 prior_target,
4904 root,
4905 target;
4906
4907 XTextProperty
4908 window_name;
4909
4910 /*
4911 Open X server connection.
4912 */
4913 assert(image_info != (const ImageInfo *) NULL);
4914 assert(image_info->signature == MagickSignature);
4915 if (image_info->debug != MagickFalse)
4916 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4917 image_info->filename);
4918 assert(ximage_info != (XImportInfo *) NULL);
4919 display=XOpenDisplay(image_info->server_name);
4920 if (display == (Display *) NULL)
4921 {
4922 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4923 XDisplayName(image_info->server_name));
4924 return((Image *) NULL);
4925 }
4926 /*
4927 Set our forgiving exception handler.
4928 */
4929 (void) XSetErrorHandler(XError);
4930 /*
4931 Select target window.
4932 */
4933 crop_info.x=0;
4934 crop_info.y=0;
4935 crop_info.width=0;
4936 crop_info.height=0;
4937 root=XRootWindow(display,XDefaultScreen(display));
4938 target=(Window) NULL;
4939 if ((image_info->filename != (char *) NULL) &&
4940 (*image_info->filename != '\0'))
4941 {
4942 if (LocaleCompare(image_info->filename,"root") == 0)
4943 target=root;
4944 else
4945 {
4946 /*
4947 Select window by ID or name.
4948 */
4949 if (isdigit((unsigned char) *image_info->filename) != 0)
4950 target=XWindowByID(display,root,(Window)
4951 strtol(image_info->filename,(char **) NULL,0));
4952 if (target == (Window) NULL)
4953 target=XWindowByName(display,root,image_info->filename);
4954 if (target == (Window) NULL)
4955 ThrowXWindowFatalException(XServerError,
4956 "NoWindowWithSpecifiedIDExists",image_info->filename);
4957 }
4958 }
4959 /*
4960 If target window is not defined, interactively select one.
4961 */
4962 prior_target=target;
4963 if (target == (Window) NULL)
4964 target=XSelectWindow(display,&crop_info);
4965 if (target == (Window) NULL)
4966 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4967 image_info->filename);
4968 client=target; /* obsolete */
4969 if (target != root)
4970 {
4971 unsigned int
4972 d;
4973
4974 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4975 if (status != False)
4976 {
4977 for ( ; ; )
4978 {
4979 Window
4980 parent;
4981
4982 /*
4983 Find window manager frame.
4984 */
4985 status=XQueryTree(display,target,&root,&parent,&children,&d);
4986 if ((status != False) && (children != (Window *) NULL))
4987 (void) XFree((char *) children);
4988 if ((status == False) || (parent == (Window) NULL) ||
4989 (parent == root))
4990 break;
4991 target=parent;
4992 }
4993 /*
4994 Get client window.
4995 */
4996 client=XClientWindow(display,target);
4997 if (ximage_info->frame == MagickFalse)
4998 target=client;
4999 if ((ximage_info->frame == MagickFalse) &&
5000 (prior_target != MagickFalse))
5001 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00005002 }
5003 }
5004 if (ximage_info->screen)
5005 {
5006 int
5007 y;
5008
5009 Window
5010 child;
5011
5012 XWindowAttributes
5013 window_attributes;
5014
5015 /*
5016 Obtain window image directly from screen.
5017 */
5018 status=XGetWindowAttributes(display,target,&window_attributes);
5019 if (status == False)
5020 {
5021 ThrowXWindowFatalException(XServerError,
5022 "UnableToReadXWindowAttributes",image_info->filename);
5023 (void) XCloseDisplay(display);
5024 return((Image *) NULL);
5025 }
5026 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005027 crop_info.x=(ssize_t) x;
5028 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005029 crop_info.width=(size_t) window_attributes.width;
5030 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005031 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005032 {
5033 /*
5034 Include border in image.
5035 */
5036 crop_info.x-=window_attributes.border_width;
5037 crop_info.y-=window_attributes.border_width;
5038 crop_info.width+=window_attributes.border_width << 1;
5039 crop_info.height+=window_attributes.border_width << 1;
5040 }
5041 target=root;
5042 }
5043 /*
5044 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5045 */
5046 number_windows=0;
5047 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5048 if ((status == True) && (number_windows > 0))
5049 {
5050 ximage_info->descend=MagickTrue;
5051 (void) XFree ((char *) children);
5052 }
5053 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5054 if (number_colormaps > 0)
5055 {
5056 if (number_colormaps > 1)
5057 ximage_info->descend=MagickTrue;
5058 (void) XFree((char *) colormaps);
5059 }
5060 /*
5061 Alert the user not to alter the screen.
5062 */
5063 if (ximage_info->silent == MagickFalse)
5064 (void) XBell(display,0);
5065 /*
5066 Get image by window id.
5067 */
5068 (void) XGrabServer(display);
5069 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005070 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005071 (void) XUngrabServer(display);
5072 if (image == (Image *) NULL)
5073 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5074 image_info->filename)
5075 else
5076 {
5077 (void) CopyMagickString(image->filename,image_info->filename,
5078 MaxTextExtent);
5079 if ((crop_info.width != 0) && (crop_info.height != 0))
5080 {
5081 Image
5082 *clone_image,
5083 *crop_image;
5084
5085 /*
5086 Crop image as defined by the cropping rectangle.
5087 */
cristy6710d842011-10-20 23:23:00 +00005088 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005089 if (clone_image != (Image *) NULL)
5090 {
cristy6710d842011-10-20 23:23:00 +00005091 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005092 if (crop_image != (Image *) NULL)
5093 {
5094 image=DestroyImage(image);
5095 image=crop_image;
5096 }
5097 }
5098 }
5099 status=XGetWMName(display,target,&window_name);
5100 if (status == True)
5101 {
5102 if ((image_info->filename != (char *) NULL) &&
5103 (*image_info->filename == '\0'))
5104 (void) CopyMagickString(image->filename,(char *) window_name.value,
5105 (size_t) window_name.nitems+1);
5106 (void) XFree((void *) window_name.value);
5107 }
5108 }
5109 if (ximage_info->silent == MagickFalse)
5110 {
5111 /*
5112 Alert the user we're done.
5113 */
5114 (void) XBell(display,0);
5115 (void) XBell(display,0);
5116 }
5117 (void) XCloseDisplay(display);
5118 return(image);
5119}
5120
5121/*
5122%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5123% %
5124% %
5125% %
5126% X I n i t i a l i z e W i n d o w s %
5127% %
5128% %
5129% %
5130%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5131%
5132% XInitializeWindows() initializes the XWindows structure.
5133%
5134% The format of the XInitializeWindows method is:
5135%
5136% XWindows *XInitializeWindows(Display *display,
5137% XResourceInfo *resource_info)
5138%
5139% A description of each parameter follows:
5140%
5141% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5142%
5143% o display: Specifies a connection to an X server; returned from
5144% XOpenDisplay.
5145%
5146% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5147%
5148*/
cristybcbda3f2011-09-03 13:01:22 +00005149MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005150 XResourceInfo *resource_info)
5151{
5152 Window
5153 root_window;
5154
5155 XWindows
5156 *windows;
5157
5158 /*
5159 Allocate windows structure.
5160 */
cristy73bd4a52010-10-05 11:24:23 +00005161 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005162 if (windows == (XWindows *) NULL)
5163 {
5164 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5165 "...");
5166 return((XWindows *) NULL);
5167 }
5168 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5169 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5170 sizeof(*windows->pixel_info));
5171 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5172 sizeof(*windows->icon_pixel));
5173 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5174 sizeof(*windows->icon_resources));
5175 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5176 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5177 (windows->icon_resources == (XResourceInfo *) NULL))
5178 {
5179 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5180 "...");
5181 return((XWindows *) NULL);
5182 }
5183 /*
5184 Initialize windows structure.
5185 */
5186 windows->display=display;
5187 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5188 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5189 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5190 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5191 windows->im_remote_command=
5192 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5193 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5194 windows->im_update_colormap=
5195 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5196 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5197 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5198 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5199 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5200 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005201#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005202 (void) XSynchronize(display,IsWindows95());
5203#endif
5204 if (IsEventLogging())
5205 {
5206 (void) XSynchronize(display,MagickTrue);
5207 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005208 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005209 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5210 (void) LogMagickEvent(X11Event,GetMagickModule(),
5211 " Window Manager: 0x%lx",windows->wm_protocols);
5212 (void) LogMagickEvent(X11Event,GetMagickModule(),
5213 " delete window: 0x%lx",windows->wm_delete_window);
5214 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5215 windows->wm_take_focus);
5216 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5217 windows->im_protocols);
5218 (void) LogMagickEvent(X11Event,GetMagickModule(),
5219 " remote command: 0x%lx",windows->im_remote_command);
5220 (void) LogMagickEvent(X11Event,GetMagickModule(),
5221 " update widget: 0x%lx",windows->im_update_widget);
5222 (void) LogMagickEvent(X11Event,GetMagickModule(),
5223 " update colormap: 0x%lx",windows->im_update_colormap);
5224 (void) LogMagickEvent(X11Event,GetMagickModule(),
5225 " former image: 0x%lx",windows->im_former_image);
5226 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5227 windows->im_next_image);
5228 (void) LogMagickEvent(X11Event,GetMagickModule(),
5229 " retain colors: 0x%lx",windows->im_retain_colors);
5230 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5231 windows->im_exit);
5232 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5233 windows->dnd_protocols);
5234 }
5235 /*
5236 Allocate standard colormap.
5237 */
5238 windows->map_info=XAllocStandardColormap();
5239 windows->icon_map=XAllocStandardColormap();
5240 if ((windows->map_info == (XStandardColormap *) NULL) ||
5241 (windows->icon_map == (XStandardColormap *) NULL))
5242 ThrowXWindowFatalException(ResourceLimitFatalError,
5243 "MemoryAllocationFailed","...");
5244 windows->map_info->colormap=(Colormap) NULL;
5245 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005246 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005247 windows->pixel_info->annotate_context=(GC) NULL;
5248 windows->pixel_info->highlight_context=(GC) NULL;
5249 windows->pixel_info->widget_context=(GC) NULL;
5250 windows->font_info=(XFontStruct *) NULL;
5251 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005252 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005253 /*
5254 Allocate visual.
5255 */
5256 *windows->icon_resources=(*resource_info);
5257 windows->icon_resources->visual_type=(char *) "default";
5258 windows->icon_resources->colormap=SharedColormap;
5259 windows->visual_info=
5260 XBestVisualInfo(display,windows->map_info,resource_info);
5261 windows->icon_visual=
5262 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5263 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5264 (windows->icon_visual == (XVisualInfo *) NULL))
5265 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5266 resource_info->visual_type);
5267 if (IsEventLogging())
5268 {
5269 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5270 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5271 windows->visual_info->visualid);
5272 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5273 XVisualClassName(windows->visual_info->klass));
5274 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5275 windows->visual_info->depth);
5276 (void) LogMagickEvent(X11Event,GetMagickModule(),
5277 " size of colormap: %d entries",windows->visual_info->colormap_size);
5278 (void) LogMagickEvent(X11Event,GetMagickModule(),
5279 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5280 windows->visual_info->red_mask,windows->visual_info->green_mask,
5281 windows->visual_info->blue_mask);
5282 (void) LogMagickEvent(X11Event,GetMagickModule(),
5283 " significant bits in color: %d bits",
5284 windows->visual_info->bits_per_rgb);
5285 }
5286 /*
5287 Allocate class and manager hints.
5288 */
5289 windows->class_hints=XAllocClassHint();
5290 windows->manager_hints=XAllocWMHints();
5291 if ((windows->class_hints == (XClassHint *) NULL) ||
5292 (windows->manager_hints == (XWMHints *) NULL))
5293 ThrowXWindowFatalException(ResourceLimitFatalError,
5294 "MemoryAllocationFailed","...");
5295 /*
5296 Determine group leader if we have one.
5297 */
5298 root_window=XRootWindow(display,windows->visual_info->screen);
5299 windows->group_leader.id=(Window) NULL;
5300 if (resource_info->window_group != (char *) NULL)
5301 {
5302 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5303 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5304 strtol((char *) resource_info->window_group,(char **) NULL,0));
5305 if (windows->group_leader.id == (Window) NULL)
5306 windows->group_leader.id=
5307 XWindowByName(display,root_window,resource_info->window_group);
5308 }
5309 return(windows);
5310}
5311
5312/*
5313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5314% %
5315% %
5316% %
5317% X M a k e C u r s o r %
5318% %
5319% %
5320% %
5321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5322%
5323% XMakeCursor() creates a crosshairs X11 cursor.
5324%
5325% The format of the XMakeCursor method is:
5326%
5327% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5328% char *background_color,char *foreground_color)
5329%
5330% A description of each parameter follows:
5331%
5332% o display: Specifies a connection to an X server; returned from
5333% XOpenDisplay.
5334%
5335% o window: Specifies the ID of the window for which the cursor is
5336% assigned.
5337%
5338% o colormap: Specifies the ID of the colormap from which the background
5339% and foreground color will be retrieved.
5340%
5341% o background_color: Specifies the color to use for the cursor background.
5342%
5343% o foreground_color: Specifies the color to use for the cursor foreground.
5344%
5345*/
cristybcbda3f2011-09-03 13:01:22 +00005346MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005347 Colormap colormap,char *background_color,char *foreground_color)
5348{
5349#define scope_height 17
5350#define scope_x_hot 8
5351#define scope_y_hot 8
5352#define scope_width 17
5353
5354 static const unsigned char
5355 scope_bits[] =
5356 {
5357 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5358 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5359 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5360 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5361 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5362 },
5363 scope_mask_bits[] =
5364 {
5365 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5366 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5367 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5368 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5369 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5370 };
5371
5372 Cursor
5373 cursor;
5374
5375 Pixmap
5376 mask,
5377 source;
5378
5379 XColor
5380 background,
5381 foreground;
5382
5383 assert(display != (Display *) NULL);
5384 assert(window != (Window) NULL);
5385 assert(colormap != (Colormap) NULL);
5386 assert(background_color != (char *) NULL);
5387 assert(foreground_color != (char *) NULL);
5388 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5389 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5390 scope_height);
5391 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5392 scope_width,scope_height);
5393 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5394 {
5395 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5396 return((Cursor) NULL);
5397 }
5398 (void) XParseColor(display,colormap,background_color,&background);
5399 (void) XParseColor(display,colormap,foreground_color,&foreground);
5400 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5401 scope_x_hot,scope_y_hot);
5402 (void) XFreePixmap(display,source);
5403 (void) XFreePixmap(display,mask);
5404 return(cursor);
5405}
5406
5407/*
5408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5409% %
5410% %
5411% %
5412% X M a k e I m a g e %
5413% %
5414% %
5415% %
5416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5417%
5418% XMakeImage() creates an X11 image. If the image size differs from the X11
5419% image size, the image is first resized.
5420%
5421% The format of the XMakeImage method is:
5422%
5423% MagickBooleanType XMakeImage(Display *display,
5424% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005425% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005426%
5427% A description of each parameter follows:
5428%
5429% o display: Specifies a connection to an X server; returned from
5430% XOpenDisplay.
5431%
5432% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5433%
5434% o window: Specifies a pointer to a XWindowInfo structure.
5435%
5436% o image: the image.
5437%
5438% o width: Specifies the width in pixels of the rectangular area to
5439% display.
5440%
5441% o height: Specifies the height in pixels of the rectangular area to
5442% display.
5443%
cristy051718b2011-08-28 22:49:25 +00005444% o exception: return any errors or warnings in this structure.
5445%
cristy3ed852e2009-09-05 21:47:34 +00005446*/
cristybcbda3f2011-09-03 13:01:22 +00005447MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005448 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005449 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005450{
5451#define CheckOverflowException(length,width,height) \
5452 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5453
5454 int
5455 depth,
5456 format;
5457
5458 size_t
5459 length;
5460
5461 XImage
5462 *matte_image,
5463 *ximage;
5464
5465 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5466 assert(display != (Display *) NULL);
5467 assert(resource_info != (XResourceInfo *) NULL);
5468 assert(window != (XWindowInfo *) NULL);
5469 assert(width != 0);
5470 assert(height != 0);
5471 if ((window->width == 0) || (window->height == 0))
5472 return(MagickFalse);
5473 /*
5474 Apply user transforms to the image.
5475 */
5476 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5477 (void) XFlush(display);
5478 depth=(int) window->depth;
5479 if (window->destroy)
5480 window->image=DestroyImage(window->image);
5481 window->image=image;
5482 window->destroy=MagickFalse;
5483 if (window->image != (Image *) NULL)
5484 {
5485 if (window->crop_geometry != (char *) NULL)
5486 {
5487 Image
5488 *crop_image;
5489
5490 RectangleInfo
5491 crop_info;
5492
5493 /*
5494 Crop image.
5495 */
5496 window->image->page.x=0;
5497 window->image->page.y=0;
5498 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005499 &crop_info,exception);
5500 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005501 if (crop_image != (Image *) NULL)
5502 {
5503 if (window->image != image)
5504 window->image=DestroyImage(window->image);
5505 window->image=crop_image;
5506 window->destroy=MagickTrue;
5507 }
5508 }
5509 if ((width != (unsigned int) window->image->columns) ||
5510 (height != (unsigned int) window->image->rows))
5511 {
5512 Image
5513 *resize_image;
5514
5515 /*
5516 Resize image.
5517 */
5518 resize_image=NewImageList();
5519 if (window->pixel_info->colors != 0)
cristy6710d842011-10-20 23:23:00 +00005520 resize_image=SampleImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005521 else
cristy6710d842011-10-20 23:23:00 +00005522 resize_image=ThumbnailImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005523 if (resize_image != (Image *) NULL)
5524 {
5525 if (window->image != image)
5526 window->image=DestroyImage(window->image);
5527 window->image=resize_image;
5528 window->destroy=MagickTrue;
5529 }
5530 }
5531 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005532 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005533 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005534 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005535 }
5536 /*
5537 Create X image.
5538 */
5539 ximage=(XImage *) NULL;
5540 format=(depth == 1) ? XYBitmap : ZPixmap;
5541#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5542 if (window->shared_memory != MagickFalse)
5543 {
5544 XShmSegmentInfo
5545 *segment_info;
5546
5547 segment_info=(XShmSegmentInfo *) window->segment_info;
5548 segment_info[1].shmid=(-1);
5549 segment_info[1].shmaddr=(char *) NULL;
5550 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5551 (char *) NULL,&segment_info[1],width,height);
5552 if (ximage == (XImage *) NULL)
5553 window->shared_memory=MagickFalse;
5554 length=(size_t) ximage->bytes_per_line*ximage->height;
5555 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5556 window->shared_memory=MagickFalse;
5557 if (window->shared_memory != MagickFalse)
5558 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5559 if (window->shared_memory != MagickFalse)
5560 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5561 if (segment_info[1].shmid < 0)
5562 window->shared_memory=MagickFalse;
5563 if (window->shared_memory != MagickFalse)
5564 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5565 else
5566 {
5567 if (ximage != (XImage *) NULL)
5568 XDestroyImage(ximage);
5569 ximage=(XImage *) NULL;
5570 if (segment_info[1].shmaddr)
5571 {
5572 (void) shmdt(segment_info[1].shmaddr);
5573 segment_info[1].shmaddr=(char *) NULL;
5574 }
5575 if (segment_info[1].shmid >= 0)
5576 {
5577 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5578 segment_info[1].shmid=(-1);
5579 }
5580 }
5581 }
5582#endif
5583 /*
5584 Allocate X image pixel data.
5585 */
5586#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5587 if (window->shared_memory)
5588 {
5589 Status
5590 status;
5591
5592 XShmSegmentInfo
5593 *segment_info;
5594
5595 (void) XSync(display,MagickFalse);
5596 xerror_alert=MagickFalse;
5597 segment_info=(XShmSegmentInfo *) window->segment_info;
5598 ximage->data=segment_info[1].shmaddr;
5599 segment_info[1].readOnly=MagickFalse;
5600 status=XShmAttach(display,&segment_info[1]);
5601 if (status != False)
5602 (void) XSync(display,MagickFalse);
5603 if ((status == False) || (xerror_alert != MagickFalse))
5604 {
5605 window->shared_memory=MagickFalse;
5606 if (status != False)
5607 XShmDetach(display,&segment_info[1]);
5608 if (ximage != (XImage *) NULL)
5609 {
5610 ximage->data=NULL;
5611 XDestroyImage(ximage);
5612 ximage=(XImage *) NULL;
5613 }
5614 if (segment_info[1].shmid >= 0)
5615 {
5616 if (segment_info[1].shmaddr != NULL)
5617 (void) shmdt(segment_info[1].shmaddr);
5618 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5619 segment_info[1].shmid=(-1);
5620 segment_info[1].shmaddr=(char *) NULL;
5621 }
5622 }
5623 }
5624#endif
5625 if (window->shared_memory == MagickFalse)
5626 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5627 (char *) NULL,width,height,XBitmapPad(display),0);
5628 if (ximage == (XImage *) NULL)
5629 {
5630 /*
5631 Unable to create X image.
5632 */
5633 (void) XCheckDefineCursor(display,window->id,window->cursor);
5634 return(MagickFalse);
5635 }
5636 length=(size_t) ximage->bytes_per_line*ximage->height;
5637 if (IsEventLogging())
5638 {
5639 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5640 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5641 ximage->width,ximage->height);
5642 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5643 ximage->format);
5644 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5645 ximage->byte_order);
5646 (void) LogMagickEvent(X11Event,GetMagickModule(),
5647 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5648 ximage->bitmap_bit_order,ximage->bitmap_pad);
5649 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5650 ximage->depth);
5651 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5652 ximage->bytes_per_line);
5653 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5654 ximage->bits_per_pixel);
5655 (void) LogMagickEvent(X11Event,GetMagickModule(),
5656 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5657 ximage->green_mask,ximage->blue_mask);
5658 }
5659 if (window->shared_memory == MagickFalse)
5660 {
5661 if (ximage->format != XYBitmap)
cristy9aecad62013-04-18 10:37:47 +00005662 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5663 ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005664 else
cristy9aecad62013-04-18 10:37:47 +00005665 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5666 ximage->depth*ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005667 }
5668 if (ximage->data == (char *) NULL)
5669 {
5670 /*
5671 Unable to allocate pixel data.
5672 */
5673 XDestroyImage(ximage);
5674 ximage=(XImage *) NULL;
5675 (void) XCheckDefineCursor(display,window->id,window->cursor);
5676 return(MagickFalse);
5677 }
5678 if (window->ximage != (XImage *) NULL)
5679 {
5680 /*
5681 Destroy previous X image.
5682 */
5683 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5684#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5685 if (window->segment_info != (XShmSegmentInfo *) NULL)
5686 {
5687 XShmSegmentInfo
5688 *segment_info;
5689
5690 segment_info=(XShmSegmentInfo *) window->segment_info;
5691 if (segment_info[0].shmid >= 0)
5692 {
5693 (void) XSync(display,MagickFalse);
5694 (void) XShmDetach(display,&segment_info[0]);
5695 (void) XSync(display,MagickFalse);
5696 if (segment_info[0].shmaddr != (char *) NULL)
5697 (void) shmdt(segment_info[0].shmaddr);
5698 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5699 segment_info[0].shmid=(-1);
5700 segment_info[0].shmaddr=(char *) NULL;
5701 window->ximage->data=(char *) NULL;
5702 }
5703 }
5704#endif
5705 if (window->ximage->data != (char *) NULL)
5706 free(window->ximage->data);
5707 window->ximage->data=(char *) NULL;
5708 XDestroyImage(window->ximage);
5709 window->ximage=(XImage *) NULL;
5710 }
5711#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5712 if (window->segment_info != (XShmSegmentInfo *) NULL)
5713 {
5714 XShmSegmentInfo
5715 *segment_info;
5716
5717 segment_info=(XShmSegmentInfo *) window->segment_info;
5718 segment_info[0]=segment_info[1];
5719 }
5720#endif
5721 window->ximage=ximage;
5722 matte_image=(XImage *) NULL;
5723 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
cristy8a46d822012-08-28 23:32:39 +00005724 if ((window->image->alpha_trait == BlendPixelTrait) &&
cristyc57f6942010-11-12 01:47:39 +00005725 ((int) width <= XDisplayWidth(display,window->screen)) &&
5726 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005727 {
5728 /*
5729 Create matte image.
5730 */
5731 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5732 (char *) NULL,width,height,XBitmapPad(display),0);
5733 if (IsEventLogging())
5734 {
5735 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5736 (void) LogMagickEvent(X11Event,GetMagickModule(),
5737 " width, height: %dx%d",matte_image->width,matte_image->height);
5738 }
5739 if (matte_image != (XImage *) NULL)
5740 {
5741 /*
5742 Allocate matte image pixel data.
5743 */
cristy9aecad62013-04-18 10:37:47 +00005744 matte_image->data=(char *) malloc((size_t)
5745 matte_image->bytes_per_line*matte_image->depth*
5746 matte_image->height);
cristy3ed852e2009-09-05 21:47:34 +00005747 if (matte_image->data == (char *) NULL)
5748 {
5749 XDestroyImage(matte_image);
5750 matte_image=(XImage *) NULL;
5751 }
5752 }
5753 }
5754 if (window->matte_image != (XImage *) NULL)
5755 {
5756 /*
5757 Free matte image.
5758 */
5759 if (window->matte_image->data != (char *) NULL)
5760 free(window->matte_image->data);
5761 window->matte_image->data=(char *) NULL;
5762 XDestroyImage(window->matte_image);
5763 window->matte_image=(XImage *) NULL;
5764 }
5765 window->matte_image=matte_image;
5766 if (window->matte_pixmap != (Pixmap) NULL)
5767 {
5768 (void) XFreePixmap(display,window->matte_pixmap);
5769 window->matte_pixmap=(Pixmap) NULL;
5770#if defined(MAGICKCORE_HAVE_SHAPE)
5771 if (window->shape != MagickFalse)
5772 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5773#endif
5774 }
5775 window->stasis=MagickFalse;
5776 /*
5777 Convert pixels to X image data.
5778 */
5779 if (window->image != (Image *) NULL)
5780 {
5781 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5782 (ximage->bitmap_bit_order == LSBFirst)))
5783 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005784 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005785 else
5786 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005787 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005788 }
5789 if (window->matte_image != (XImage *) NULL)
5790 {
5791 /*
5792 Create matte pixmap.
5793 */
5794 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5795 if (window->matte_pixmap != (Pixmap) NULL)
5796 {
5797 GC
5798 graphics_context;
5799
5800 XGCValues
5801 context_values;
5802
5803 /*
5804 Copy matte image to matte pixmap.
5805 */
cristy4c08aed2011-07-01 19:47:50 +00005806 context_values.background=0;
5807 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005808 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005809 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005810 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5811 window->matte_image,0,0,0,0,width,height);
5812 (void) XFreeGC(display,graphics_context);
5813#if defined(MAGICKCORE_HAVE_SHAPE)
5814 if (window->shape != MagickFalse)
5815 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5816 window->matte_pixmap,ShapeSet);
5817#endif
5818 }
5819 }
5820 (void) XMakePixmap(display,resource_info,window);
5821 /*
5822 Restore cursor.
5823 */
5824 (void) XCheckDefineCursor(display,window->id,window->cursor);
5825 return(MagickTrue);
5826}
5827
5828/*
5829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5830% %
5831% %
5832% %
5833+ X M a k e I m a g e L S B F i r s t %
5834% %
5835% %
5836% %
5837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5838%
5839% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5840% pixels are copied in least-significant bit and byte first order. The
5841% server's scanline pad is respected. Rather than using one or two general
5842% cases, many special cases are found here to help speed up the image
5843% conversion.
5844%
5845% The format of the XMakeImageLSBFirst method is:
5846%
cristye941a752011-10-15 01:52:48 +00005847% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5848% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005849%
5850% A description of each parameter follows:
5851%
5852% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5853%
5854% o window: Specifies a pointer to a XWindowInfo structure.
5855%
5856% o image: the image.
5857%
5858% o ximage: Specifies a pointer to a XImage structure; returned from
5859% XCreateImage.
5860%
5861% o matte_image: Specifies a pointer to a XImage structure; returned from
5862% XCreateImage.
5863%
cristye941a752011-10-15 01:52:48 +00005864% o exception: return any errors or warnings in this structure.
5865%
cristy3ed852e2009-09-05 21:47:34 +00005866*/
5867static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005868 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5869 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005870{
cristyc57f6942010-11-12 01:47:39 +00005871 CacheView
5872 *canvas_view;
5873
cristy3ed852e2009-09-05 21:47:34 +00005874 Image
5875 *canvas;
5876
5877 int
5878 y;
5879
cristy4c08aed2011-07-01 19:47:50 +00005880 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005881 *p;
5882
5883 register int
5884 x;
5885
5886 register unsigned char
5887 *q;
5888
5889 unsigned char
5890 bit,
5891 byte;
5892
5893 unsigned int
5894 scanline_pad;
5895
cristyf2faecf2010-05-28 19:19:36 +00005896 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005897 pixel,
5898 *pixels;
5899
5900 XStandardColormap
5901 *map_info;
5902
5903 assert(resource_info != (XResourceInfo *) NULL);
5904 assert(window != (XWindowInfo *) NULL);
5905 assert(image != (Image *) NULL);
5906 if (image->debug != MagickFalse)
5907 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5908 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005909 if ((window->immutable == MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00005910 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00005911 {
5912 char
5913 size[MaxTextExtent];
5914
5915 Image
5916 *pattern;
5917
5918 ImageInfo
5919 *image_info;
5920
5921 image_info=AcquireImageInfo();
5922 (void) CopyMagickString(image_info->filename,
5923 resource_info->image_info->texture != (char *) NULL ?
5924 resource_info->image_info->texture : "pattern:checkerboard",
5925 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005926 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005927 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005928 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005929 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005930 image_info=DestroyImageInfo(image_info);
5931 if (pattern != (Image *) NULL)
5932 {
cristy6710d842011-10-20 23:23:00 +00005933 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005934 if (canvas != (Image *) NULL)
cristy39172402012-03-30 13:04:39 +00005935 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00005936 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00005937 pattern=DestroyImage(pattern);
5938 }
5939 }
5940 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5941 ximage->bits_per_pixel) >> 3));
5942 map_info=window->map_info;
5943 pixels=window->pixel_info->pixels;
5944 q=(unsigned char *) ximage->data;
5945 x=0;
cristy46ff2672012-12-14 15:32:26 +00005946 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00005947 if (ximage->format == XYBitmap)
5948 {
5949 register unsigned short
5950 polarity;
5951
5952 unsigned char
5953 background,
5954 foreground;
5955
5956 /*
5957 Convert canvas to big-endian bitmap.
5958 */
5959 background=(unsigned char)
5960 (XPixelIntensity(&window->pixel_info->foreground_color) <
5961 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5962 foreground=(unsigned char)
5963 (XPixelIntensity(&window->pixel_info->background_color) <
5964 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005965 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00005966 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00005967 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005968 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5969 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005970 for (y=0; y < (int) canvas->rows; y++)
5971 {
cristyc57f6942010-11-12 01:47:39 +00005972 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005973 exception);
cristy4c08aed2011-07-01 19:47:50 +00005974 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005975 break;
cristy3ed852e2009-09-05 21:47:34 +00005976 bit=0;
5977 byte=0;
5978 for (x=0; x < (int) canvas->columns; x++)
5979 {
5980 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005981 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005982 byte|=foreground;
5983 else
5984 byte|=background;
5985 bit++;
5986 if (bit == 8)
5987 {
5988 *q++=byte;
5989 bit=0;
5990 byte=0;
5991 }
cristyed231572011-07-14 02:18:59 +00005992 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005993 }
5994 if (bit != 0)
5995 *q=byte >> (8-bit);
5996 q+=scanline_pad;
5997 }
5998 }
5999 else
6000 if (window->pixel_info->colors != 0)
6001 switch (ximage->bits_per_pixel)
6002 {
6003 case 2:
6004 {
6005 register unsigned int
6006 nibble;
6007
6008 /*
6009 Convert to 2 bit color-mapped X canvas.
6010 */
6011 for (y=0; y < (int) canvas->rows; y++)
6012 {
cristyc57f6942010-11-12 01:47:39 +00006013 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006014 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006015 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006016 break;
cristy3ed852e2009-09-05 21:47:34 +00006017 nibble=0;
6018 for (x=0; x < (int) canvas->columns; x++)
6019 {
cristy4c08aed2011-07-01 19:47:50 +00006020 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006021 switch (nibble)
6022 {
6023 case 0:
6024 {
6025 *q=(unsigned char) pixel;
6026 nibble++;
6027 break;
6028 }
6029 case 1:
6030 {
6031 *q|=(unsigned char) (pixel << 2);
6032 nibble++;
6033 break;
6034 }
6035 case 2:
6036 {
6037 *q|=(unsigned char) (pixel << 4);
6038 nibble++;
6039 break;
6040 }
6041 case 3:
6042 {
6043 *q|=(unsigned char) (pixel << 6);
6044 q++;
6045 nibble=0;
6046 break;
6047 }
6048 }
cristyed231572011-07-14 02:18:59 +00006049 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006050 }
6051 q+=scanline_pad;
6052 }
6053 break;
6054 }
6055 case 4:
6056 {
6057 register unsigned int
6058 nibble;
6059
6060 /*
6061 Convert to 4 bit color-mapped X canvas.
6062 */
6063 for (y=0; y < (int) canvas->rows; y++)
6064 {
cristyc57f6942010-11-12 01:47:39 +00006065 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006066 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006067 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006068 break;
cristy3ed852e2009-09-05 21:47:34 +00006069 nibble=0;
6070 for (x=0; x < (int) canvas->columns; x++)
6071 {
cristy4c08aed2011-07-01 19:47:50 +00006072 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006073 switch (nibble)
6074 {
6075 case 0:
6076 {
6077 *q=(unsigned char) pixel;
6078 nibble++;
6079 break;
6080 }
6081 case 1:
6082 {
6083 *q|=(unsigned char) (pixel << 4);
6084 q++;
6085 nibble=0;
6086 break;
6087 }
6088 }
cristyed231572011-07-14 02:18:59 +00006089 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006090 }
6091 q+=scanline_pad;
6092 }
6093 break;
6094 }
6095 case 6:
6096 case 8:
6097 {
6098 /*
6099 Convert to 8 bit color-mapped X canvas.
6100 */
6101 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006102 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006103 {
cristy6710d842011-10-20 23:23:00 +00006104 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006105 break;
6106 }
6107 for (y=0; y < (int) canvas->rows; y++)
6108 {
cristyc57f6942010-11-12 01:47:39 +00006109 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006110 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006111 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006112 break;
cristy3ed852e2009-09-05 21:47:34 +00006113 for (x=0; x < (int) canvas->columns; x++)
6114 {
cristy4c08aed2011-07-01 19:47:50 +00006115 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006116 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006117 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006118 }
6119 q+=scanline_pad;
6120 }
6121 break;
6122 }
6123 default:
6124 {
6125 register int
6126 k;
6127
6128 register unsigned int
6129 bytes_per_pixel;
6130
cristy3ed852e2009-09-05 21:47:34 +00006131 /*
6132 Convert to multi-byte color-mapped X canvas.
6133 */
6134 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6135 for (y=0; y < (int) canvas->rows; y++)
6136 {
cristyc57f6942010-11-12 01:47:39 +00006137 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006138 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006139 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006140 break;
cristy3ed852e2009-09-05 21:47:34 +00006141 for (x=0; x < (int) canvas->columns; x++)
6142 {
cristy4c08aed2011-07-01 19:47:50 +00006143 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006144 for (k=0; k < (int) bytes_per_pixel; k++)
6145 {
cristy42daae12013-04-07 22:36:07 +00006146 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006147 pixel>>=8;
6148 }
cristyed231572011-07-14 02:18:59 +00006149 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006150 }
6151 q+=scanline_pad;
6152 }
6153 break;
6154 }
6155 }
6156 else
6157 switch (ximage->bits_per_pixel)
6158 {
6159 case 2:
6160 {
6161 register unsigned int
6162 nibble;
6163
6164 /*
6165 Convert to contiguous 2 bit continuous-tone X canvas.
6166 */
6167 for (y=0; y < (int) canvas->rows; y++)
6168 {
6169 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006170 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006171 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006172 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006173 break;
6174 for (x=0; x < (int) canvas->columns; x++)
6175 {
cristy4c08aed2011-07-01 19:47:50 +00006176 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006177 pixel&=0xf;
6178 switch (nibble)
6179 {
6180 case 0:
6181 {
6182 *q=(unsigned char) pixel;
6183 nibble++;
6184 break;
6185 }
6186 case 1:
6187 {
6188 *q|=(unsigned char) (pixel << 2);
6189 nibble++;
6190 break;
6191 }
6192 case 2:
6193 {
6194 *q|=(unsigned char) (pixel << 4);
6195 nibble++;
6196 break;
6197 }
6198 case 3:
6199 {
6200 *q|=(unsigned char) (pixel << 6);
6201 q++;
6202 nibble=0;
6203 break;
6204 }
6205 }
cristyed231572011-07-14 02:18:59 +00006206 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006207 }
6208 q+=scanline_pad;
6209 }
6210 break;
6211 }
6212 case 4:
6213 {
6214 register unsigned int
6215 nibble;
6216
6217 /*
6218 Convert to contiguous 4 bit continuous-tone X canvas.
6219 */
6220 for (y=0; y < (int) canvas->rows; y++)
6221 {
cristyc57f6942010-11-12 01:47:39 +00006222 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006223 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006224 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006225 break;
6226 nibble=0;
6227 for (x=0; x < (int) canvas->columns; x++)
6228 {
cristy4c08aed2011-07-01 19:47:50 +00006229 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006230 pixel&=0xf;
6231 switch (nibble)
6232 {
6233 case 0:
6234 {
6235 *q=(unsigned char) pixel;
6236 nibble++;
6237 break;
6238 }
6239 case 1:
6240 {
6241 *q|=(unsigned char) (pixel << 4);
6242 q++;
6243 nibble=0;
6244 break;
6245 }
6246 }
cristyed231572011-07-14 02:18:59 +00006247 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006248 }
6249 q+=scanline_pad;
6250 }
6251 break;
6252 }
6253 case 6:
6254 case 8:
6255 {
6256 /*
6257 Convert to contiguous 8 bit continuous-tone X canvas.
6258 */
6259 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006260 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006261 {
cristy6710d842011-10-20 23:23:00 +00006262 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006263 break;
6264 }
6265 for (y=0; y < (int) canvas->rows; y++)
6266 {
cristyc57f6942010-11-12 01:47:39 +00006267 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006268 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006269 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006270 break;
6271 for (x=0; x < (int) canvas->columns; x++)
6272 {
cristy4c08aed2011-07-01 19:47:50 +00006273 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006274 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006275 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006276 }
6277 q+=scanline_pad;
6278 }
6279 break;
6280 }
6281 default:
6282 {
6283 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6284 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6285 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6286 (map_info->blue_mult == 1))
6287 {
6288 /*
6289 Convert to 32 bit continuous-tone X canvas.
6290 */
6291 for (y=0; y < (int) canvas->rows; y++)
6292 {
cristyc57f6942010-11-12 01:47:39 +00006293 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006294 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006295 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006296 break;
6297 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6298 (blue_gamma != 1.0))
6299 {
6300 /*
6301 Gamma correct canvas.
6302 */
6303 for (x=(int) canvas->columns-1; x >= 0; x--)
6304 {
cristyccf844f2010-02-03 23:28:16 +00006305 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006306 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006307 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006308 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006309 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006310 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006311 *q++=0;
cristyed231572011-07-14 02:18:59 +00006312 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006313 }
6314 continue;
6315 }
6316 for (x=(int) canvas->columns-1; x >= 0; x--)
6317 {
cristy8bc259b2012-06-21 23:53:15 +00006318 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6319 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6320 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006321 *q++=0;
cristyed231572011-07-14 02:18:59 +00006322 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006323 }
6324 }
6325 }
6326 else
6327 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6328 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6329 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6330 (map_info->blue_mult == 65536L))
6331 {
6332 /*
6333 Convert to 32 bit continuous-tone X canvas.
6334 */
6335 for (y=0; y < (int) canvas->rows; y++)
6336 {
cristyc57f6942010-11-12 01:47:39 +00006337 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006338 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006339 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006340 break;
6341 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6342 (blue_gamma != 1.0))
6343 {
6344 /*
6345 Gamma correct canvas.
6346 */
6347 for (x=(int) canvas->columns-1; x >= 0; x--)
6348 {
cristyccf844f2010-02-03 23:28:16 +00006349 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006350 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006351 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006352 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006353 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006354 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006355 *q++=0;
cristyed231572011-07-14 02:18:59 +00006356 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006357 }
6358 continue;
6359 }
6360 for (x=(int) canvas->columns-1; x >= 0; x--)
6361 {
cristy8bc259b2012-06-21 23:53:15 +00006362 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6363 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6364 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006365 *q++=0;
cristyed231572011-07-14 02:18:59 +00006366 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006367 }
6368 }
6369 }
6370 else
6371 {
6372 register int
6373 k;
6374
6375 register unsigned int
6376 bytes_per_pixel;
6377
cristy3ed852e2009-09-05 21:47:34 +00006378 /*
6379 Convert to multi-byte continuous-tone X canvas.
6380 */
6381 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6382 for (y=0; y < (int) canvas->rows; y++)
6383 {
cristyc57f6942010-11-12 01:47:39 +00006384 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006385 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006386 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006387 break;
cristyc57f6942010-11-12 01:47:39 +00006388 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006389 {
cristy4c08aed2011-07-01 19:47:50 +00006390 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006391 for (k=0; k < (int) bytes_per_pixel; k++)
6392 {
cristy42daae12013-04-07 22:36:07 +00006393 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006394 pixel>>=8;
6395 }
cristyed231572011-07-14 02:18:59 +00006396 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006397 }
6398 q+=scanline_pad;
6399 }
6400 }
6401 break;
6402 }
6403 }
6404 if (matte_image != (XImage *) NULL)
6405 {
6406 /*
6407 Initialize matte canvas.
6408 */
6409 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6410 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6411 q=(unsigned char *) matte_image->data;
6412 for (y=0; y < (int) canvas->rows; y++)
6413 {
cristyc57f6942010-11-12 01:47:39 +00006414 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006415 exception);
cristy4c08aed2011-07-01 19:47:50 +00006416 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006417 break;
6418 bit=0;
6419 byte=0;
6420 for (x=(int) canvas->columns-1; x >= 0; x--)
6421 {
6422 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006423 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006424 byte|=0x80;
6425 bit++;
6426 if (bit == 8)
6427 {
6428 *q++=byte;
6429 bit=0;
6430 byte=0;
6431 }
cristyed231572011-07-14 02:18:59 +00006432 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006433 }
6434 if (bit != 0)
6435 *q=byte >> (8-bit);
6436 q+=scanline_pad;
6437 }
6438 }
cristyc57f6942010-11-12 01:47:39 +00006439 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006440 if (canvas != image)
6441 canvas=DestroyImage(canvas);
6442}
6443
6444/*
6445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6446% %
6447% %
6448% %
6449+ X M a k e I m a g e M S B F i r s t %
6450% %
6451% %
6452% %
6453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6454%
6455% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6456% image pixels are copied in most-significant bit and byte first order. The
6457% server's scanline pad is also respected. Rather than using one or two
6458% general cases, many special cases are found here to help speed up the image
6459% conversion.
6460%
6461% The format of the XMakeImageMSBFirst method is:
6462%
cristye941a752011-10-15 01:52:48 +00006463% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6464% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006465%
6466% A description of each parameter follows:
6467%
6468% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6469%
6470% o window: Specifies a pointer to a XWindowInfo structure.
6471%
6472% o image: the image.
6473%
6474% o ximage: Specifies a pointer to a XImage structure; returned from
6475% XCreateImage.
6476%
6477% o matte_image: Specifies a pointer to a XImage structure; returned from
6478% XCreateImage.
6479%
cristye941a752011-10-15 01:52:48 +00006480% o exception: return any errors or warnings in this structure.
6481%
cristy3ed852e2009-09-05 21:47:34 +00006482*/
6483static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006484 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6485 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006486{
cristyc57f6942010-11-12 01:47:39 +00006487 CacheView
6488 *canvas_view;
6489
cristy3ed852e2009-09-05 21:47:34 +00006490 Image
6491 *canvas;
6492
6493 int
6494 y;
6495
6496 register int
6497 x;
6498
cristy4c08aed2011-07-01 19:47:50 +00006499 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006500 *p;
6501
6502 register unsigned char
6503 *q;
6504
6505 unsigned char
6506 bit,
6507 byte;
6508
6509 unsigned int
6510 scanline_pad;
6511
cristyf2faecf2010-05-28 19:19:36 +00006512 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006513 pixel,
6514 *pixels;
6515
6516 XStandardColormap
6517 *map_info;
6518
6519 assert(resource_info != (XResourceInfo *) NULL);
6520 assert(window != (XWindowInfo *) NULL);
6521 assert(image != (Image *) NULL);
6522 if (image->debug != MagickFalse)
6523 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6524 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006525 if ((window->immutable != MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00006526 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00006527 {
6528 char
6529 size[MaxTextExtent];
6530
6531 Image
6532 *pattern;
6533
6534 ImageInfo
6535 *image_info;
6536
6537 image_info=AcquireImageInfo();
6538 (void) CopyMagickString(image_info->filename,
6539 resource_info->image_info->texture != (char *) NULL ?
6540 resource_info->image_info->texture : "pattern:checkerboard",
6541 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006542 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006543 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006544 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006545 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006546 image_info=DestroyImageInfo(image_info);
6547 if (pattern != (Image *) NULL)
6548 {
cristy6710d842011-10-20 23:23:00 +00006549 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006550 if (canvas != (Image *) NULL)
cristyfeb3e962012-03-29 17:25:55 +00006551 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6552 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00006553 pattern=DestroyImage(pattern);
6554 }
6555 }
cristy4c08aed2011-07-01 19:47:50 +00006556 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6557 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006558 map_info=window->map_info;
6559 pixels=window->pixel_info->pixels;
6560 q=(unsigned char *) ximage->data;
6561 x=0;
cristy46ff2672012-12-14 15:32:26 +00006562 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00006563 if (ximage->format == XYBitmap)
6564 {
6565 register unsigned short
6566 polarity;
6567
6568 unsigned char
6569 background,
6570 foreground;
6571
6572 /*
6573 Convert canvas to big-endian bitmap.
6574 */
6575 background=(unsigned char)
6576 (XPixelIntensity(&window->pixel_info->foreground_color) <
6577 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6578 foreground=(unsigned char)
6579 (XPixelIntensity(&window->pixel_info->background_color) <
6580 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006581 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00006582 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00006583 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006584 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6585 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006586 for (y=0; y < (int) canvas->rows; y++)
6587 {
cristyc57f6942010-11-12 01:47:39 +00006588 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006589 exception);
cristy4c08aed2011-07-01 19:47:50 +00006590 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006591 break;
cristy3ed852e2009-09-05 21:47:34 +00006592 bit=0;
6593 byte=0;
6594 for (x=(int) canvas->columns-1; x >= 0; x--)
6595 {
6596 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006597 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006598 byte|=foreground;
6599 else
6600 byte|=background;
6601 bit++;
6602 if (bit == 8)
6603 {
6604 *q++=byte;
6605 bit=0;
6606 byte=0;
6607 }
cristyed231572011-07-14 02:18:59 +00006608 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006609 }
6610 if (bit != 0)
6611 *q=byte << (8-bit);
6612 q+=scanline_pad;
6613 }
6614 }
6615 else
6616 if (window->pixel_info->colors != 0)
6617 switch (ximage->bits_per_pixel)
6618 {
6619 case 2:
6620 {
6621 register unsigned int
6622 nibble;
6623
6624 /*
6625 Convert to 2 bit color-mapped X canvas.
6626 */
6627 for (y=0; y < (int) canvas->rows; y++)
6628 {
cristyc57f6942010-11-12 01:47:39 +00006629 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006630 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006631 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006632 break;
cristy3ed852e2009-09-05 21:47:34 +00006633 nibble=0;
6634 for (x=0; x < (int) canvas->columns; x++)
6635 {
cristy4c08aed2011-07-01 19:47:50 +00006636 pixel=pixels[(ssize_t)
6637 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006638 switch (nibble)
6639 {
6640 case 0:
6641 {
6642 *q=(unsigned char) (pixel << 6);
6643 nibble++;
6644 break;
6645 }
6646 case 1:
6647 {
6648 *q|=(unsigned char) (pixel << 4);
6649 nibble++;
6650 break;
6651 }
6652 case 2:
6653 {
6654 *q|=(unsigned char) (pixel << 2);
6655 nibble++;
6656 break;
6657 }
6658 case 3:
6659 {
6660 *q|=(unsigned char) pixel;
6661 q++;
6662 nibble=0;
6663 break;
6664 }
6665 }
cristyed231572011-07-14 02:18:59 +00006666 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006667 }
6668 q+=scanline_pad;
6669 }
6670 break;
6671 }
6672 case 4:
6673 {
6674 register unsigned int
6675 nibble;
6676
6677 /*
6678 Convert to 4 bit color-mapped X canvas.
6679 */
6680 for (y=0; y < (int) canvas->rows; y++)
6681 {
cristyc57f6942010-11-12 01:47:39 +00006682 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006683 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006684 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006685 break;
cristy3ed852e2009-09-05 21:47:34 +00006686 nibble=0;
6687 for (x=0; x < (int) canvas->columns; x++)
6688 {
cristy4c08aed2011-07-01 19:47:50 +00006689 pixel=pixels[(ssize_t)
6690 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006691 switch (nibble)
6692 {
6693 case 0:
6694 {
6695 *q=(unsigned char) (pixel << 4);
6696 nibble++;
6697 break;
6698 }
6699 case 1:
6700 {
6701 *q|=(unsigned char) pixel;
6702 q++;
6703 nibble=0;
6704 break;
6705 }
6706 }
cristyed231572011-07-14 02:18:59 +00006707 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006708 }
6709 q+=scanline_pad;
6710 }
6711 break;
6712 }
6713 case 6:
6714 case 8:
6715 {
6716 /*
6717 Convert to 8 bit color-mapped X canvas.
6718 */
6719 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006720 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006721 {
cristy6710d842011-10-20 23:23:00 +00006722 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006723 break;
6724 }
6725 for (y=0; y < (int) canvas->rows; y++)
6726 {
cristyc57f6942010-11-12 01:47:39 +00006727 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006728 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006729 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006730 break;
cristy3ed852e2009-09-05 21:47:34 +00006731 for (x=0; x < (int) canvas->columns; x++)
6732 {
cristy6710d842011-10-20 23:23:00 +00006733 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006734 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006735 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006736 }
6737 q+=scanline_pad;
6738 }
6739 break;
6740 }
6741 default:
6742 {
6743 register int
6744 k;
6745
6746 register unsigned int
6747 bytes_per_pixel;
6748
6749 unsigned char
cristybb503372010-05-27 20:51:26 +00006750 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006751
6752 /*
6753 Convert to 8 bit color-mapped X canvas.
6754 */
6755 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6756 for (y=0; y < (int) canvas->rows; y++)
6757 {
cristyc57f6942010-11-12 01:47:39 +00006758 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006759 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006760 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006761 break;
cristy3ed852e2009-09-05 21:47:34 +00006762 for (x=0; x < (int) canvas->columns; x++)
6763 {
cristy4c08aed2011-07-01 19:47:50 +00006764 pixel=pixels[(ssize_t)
6765 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006766 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6767 {
6768 channel[k]=(unsigned char) pixel;
6769 pixel>>=8;
6770 }
6771 for (k=0; k < (int) bytes_per_pixel; k++)
6772 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006773 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006774 }
6775 q+=scanline_pad;
6776 }
6777 break;
6778 }
6779 }
6780 else
6781 switch (ximage->bits_per_pixel)
6782 {
6783 case 2:
6784 {
6785 register unsigned int
6786 nibble;
6787
6788 /*
6789 Convert to 4 bit continuous-tone X canvas.
6790 */
6791 for (y=0; y < (int) canvas->rows; y++)
6792 {
cristyc57f6942010-11-12 01:47:39 +00006793 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006794 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006795 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006796 break;
6797 nibble=0;
6798 for (x=(int) canvas->columns-1; x >= 0; x--)
6799 {
cristy4c08aed2011-07-01 19:47:50 +00006800 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006801 pixel&=0xf;
6802 switch (nibble)
6803 {
6804 case 0:
6805 {
6806 *q=(unsigned char) (pixel << 6);
6807 nibble++;
6808 break;
6809 }
6810 case 1:
6811 {
6812 *q|=(unsigned char) (pixel << 4);
6813 nibble++;
6814 break;
6815 }
6816 case 2:
6817 {
6818 *q|=(unsigned char) (pixel << 2);
6819 nibble++;
6820 break;
6821 }
6822 case 3:
6823 {
6824 *q|=(unsigned char) pixel;
6825 q++;
6826 nibble=0;
6827 break;
6828 }
6829 }
cristyed231572011-07-14 02:18:59 +00006830 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006831 }
6832 q+=scanline_pad;
6833 }
6834 break;
6835 }
6836 case 4:
6837 {
6838 register unsigned int
6839 nibble;
6840
6841 /*
6842 Convert to 4 bit continuous-tone X canvas.
6843 */
6844 for (y=0; y < (int) canvas->rows; y++)
6845 {
cristyc57f6942010-11-12 01:47:39 +00006846 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006847 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006848 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006849 break;
6850 nibble=0;
6851 for (x=(int) canvas->columns-1; x >= 0; x--)
6852 {
cristy4c08aed2011-07-01 19:47:50 +00006853 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006854 pixel&=0xf;
6855 switch (nibble)
6856 {
6857 case 0:
6858 {
6859 *q=(unsigned char) (pixel << 4);
6860 nibble++;
6861 break;
6862 }
6863 case 1:
6864 {
6865 *q|=(unsigned char) pixel;
6866 q++;
6867 nibble=0;
6868 break;
6869 }
6870 }
cristyed231572011-07-14 02:18:59 +00006871 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006872 }
6873 q+=scanline_pad;
6874 }
6875 break;
6876 }
6877 case 6:
6878 case 8:
6879 {
6880 /*
6881 Convert to 8 bit continuous-tone X canvas.
6882 */
6883 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006884 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006885 {
cristy6710d842011-10-20 23:23:00 +00006886 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006887 break;
6888 }
6889 for (y=0; y < (int) canvas->rows; y++)
6890 {
cristyc57f6942010-11-12 01:47:39 +00006891 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006892 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006893 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006894 break;
6895 for (x=(int) canvas->columns-1; x >= 0; x--)
6896 {
cristy4c08aed2011-07-01 19:47:50 +00006897 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006898 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006899 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006900 }
6901 q+=scanline_pad;
6902 }
6903 break;
6904 }
6905 default:
6906 {
6907 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6908 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6909 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6910 (map_info->blue_mult == 1))
6911 {
6912 /*
6913 Convert to 32 bit continuous-tone X canvas.
6914 */
6915 for (y=0; y < (int) canvas->rows; y++)
6916 {
cristyc57f6942010-11-12 01:47:39 +00006917 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006918 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006919 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006920 break;
6921 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6922 (blue_gamma != 1.0))
6923 {
6924 /*
6925 Gamma correct canvas.
6926 */
6927 for (x=(int) canvas->columns-1; x >= 0; x--)
6928 {
6929 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006930 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006931 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006932 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006933 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006934 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006935 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006936 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006937 }
6938 continue;
6939 }
6940 for (x=(int) canvas->columns-1; x >= 0; x--)
6941 {
6942 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006943 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6944 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6945 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006946 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006947 }
6948 }
6949 }
6950 else
6951 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6952 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6953 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6954 (map_info->blue_mult == 65536L))
6955 {
6956 /*
6957 Convert to 32 bit continuous-tone X canvas.
6958 */
6959 for (y=0; y < (int) canvas->rows; y++)
6960 {
cristyc57f6942010-11-12 01:47:39 +00006961 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006962 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006963 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006964 break;
6965 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6966 (blue_gamma != 1.0))
6967 {
6968 /*
6969 Gamma correct canvas.
6970 */
6971 for (x=(int) canvas->columns-1; x >= 0; x--)
6972 {
6973 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006974 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006975 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006976 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006977 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006978 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006979 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006980 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006981 }
6982 continue;
6983 }
6984 for (x=(int) canvas->columns-1; x >= 0; x--)
6985 {
6986 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006987 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6988 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6989 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006990 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006991 }
6992 }
6993 }
6994 else
6995 {
6996 register int
6997 k;
6998
6999 register unsigned int
7000 bytes_per_pixel;
7001
7002 unsigned char
cristybb503372010-05-27 20:51:26 +00007003 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007004
7005 /*
7006 Convert to multi-byte continuous-tone X canvas.
7007 */
7008 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7009 for (y=0; y < (int) canvas->rows; y++)
7010 {
cristyc57f6942010-11-12 01:47:39 +00007011 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007012 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007013 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007014 break;
7015 for (x=(int) canvas->columns-1; x >= 0; x--)
7016 {
cristy4c08aed2011-07-01 19:47:50 +00007017 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007018 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7019 {
7020 channel[k]=(unsigned char) pixel;
7021 pixel>>=8;
7022 }
7023 for (k=0; k < (int) bytes_per_pixel; k++)
7024 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007025 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007026 }
7027 q+=scanline_pad;
7028 }
7029 }
7030 break;
7031 }
7032 }
7033 if (matte_image != (XImage *) NULL)
7034 {
7035 /*
7036 Initialize matte canvas.
7037 */
7038 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7039 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7040 q=(unsigned char *) matte_image->data;
7041 for (y=0; y < (int) canvas->rows; y++)
7042 {
cristyc57f6942010-11-12 01:47:39 +00007043 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007044 exception);
cristy4c08aed2011-07-01 19:47:50 +00007045 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007046 break;
7047 bit=0;
7048 byte=0;
7049 for (x=(int) canvas->columns-1; x >= 0; x--)
7050 {
7051 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007052 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007053 byte|=0x01;
7054 bit++;
7055 if (bit == 8)
7056 {
7057 *q++=byte;
7058 bit=0;
7059 byte=0;
7060 }
cristyed231572011-07-14 02:18:59 +00007061 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007062 }
7063 if (bit != 0)
7064 *q=byte << (8-bit);
7065 q+=scanline_pad;
7066 }
7067 }
cristyc57f6942010-11-12 01:47:39 +00007068 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007069 if (canvas != image)
7070 canvas=DestroyImage(canvas);
7071}
7072
7073/*
7074%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7075% %
7076% %
7077% %
7078% X M a k e M a g n i f y I m a g e %
7079% %
7080% %
7081% %
7082%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7083%
7084% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7085%
7086% The format of the XMakeMagnifyImage method is:
7087%
cristy6710d842011-10-20 23:23:00 +00007088% void XMakeMagnifyImage(Display *display,XWindows *windows,
7089% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007090%
7091% A description of each parameter follows:
7092%
7093% o display: Specifies a connection to an X server; returned from
7094% XOpenDisplay.
7095%
7096% o windows: Specifies a pointer to a XWindows structure.
7097%
cristy6710d842011-10-20 23:23:00 +00007098% o exception: return any errors or warnings in this structure.
7099%
cristy3ed852e2009-09-05 21:47:34 +00007100*/
cristy6710d842011-10-20 23:23:00 +00007101MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7102 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007103{
7104 char
7105 tuple[MaxTextExtent];
7106
7107 int
7108 y;
7109
cristy4c08aed2011-07-01 19:47:50 +00007110 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007111 pixel;
7112
7113 register int
7114 x;
7115
cristybb503372010-05-27 20:51:26 +00007116 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007117 i;
7118
7119 register unsigned char
7120 *p,
7121 *q;
7122
cristy9d314ff2011-03-09 01:30:28 +00007123 ssize_t
7124 n;
7125
cristy3ed852e2009-09-05 21:47:34 +00007126 static unsigned int
7127 previous_magnify = 0;
7128
7129 static XWindowInfo
7130 magnify_window;
7131
7132 unsigned int
7133 height,
7134 j,
7135 k,
7136 l,
7137 magnify,
7138 scanline_pad,
7139 width;
7140
7141 XImage
7142 *ximage;
7143
7144 /*
7145 Check boundary conditions.
7146 */
7147 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7148 assert(display != (Display *) NULL);
7149 assert(windows != (XWindows *) NULL);
7150 magnify=1;
cristybb503372010-05-27 20:51:26 +00007151 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007152 magnify<<=1;
7153 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7154 magnify<<=1;
7155 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7156 magnify<<=1;
7157 while (magnify > windows->magnify.width)
7158 magnify>>=1;
7159 while (magnify > windows->magnify.height)
7160 magnify>>=1;
7161 if (magnify != previous_magnify)
7162 {
7163 Status
7164 status;
7165
7166 XTextProperty
7167 window_name;
7168
7169 /*
7170 New magnify factor: update magnify window name.
7171 */
7172 i=0;
7173 while ((1 << i) <= (int) magnify)
7174 i++;
cristyb51dff52011-05-19 16:55:47 +00007175 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007176 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007177 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7178 if (status != False)
7179 {
7180 XSetWMName(display,windows->magnify.id,&window_name);
7181 XSetWMIconName(display,windows->magnify.id,&window_name);
7182 (void) XFree((void *) window_name.value);
7183 }
7184 }
7185 previous_magnify=magnify;
7186 ximage=windows->image.ximage;
7187 width=(unsigned int) windows->magnify.ximage->width;
7188 height=(unsigned int) windows->magnify.ximage->height;
7189 if ((windows->magnify.x < 0) ||
7190 (windows->magnify.x >= windows->image.ximage->width))
7191 windows->magnify.x=windows->image.ximage->width >> 1;
7192 x=windows->magnify.x-((width/magnify) >> 1);
7193 if (x < 0)
7194 x=0;
7195 else
7196 if (x > (int) (ximage->width-(width/magnify)))
7197 x=ximage->width-width/magnify;
7198 if ((windows->magnify.y < 0) ||
7199 (windows->magnify.y >= windows->image.ximage->height))
7200 windows->magnify.y=windows->image.ximage->height >> 1;
7201 y=windows->magnify.y-((height/magnify) >> 1);
7202 if (y < 0)
7203 y=0;
7204 else
7205 if (y > (int) (ximage->height-(height/magnify)))
7206 y=ximage->height-height/magnify;
7207 q=(unsigned char *) windows->magnify.ximage->data;
7208 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7209 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7210 if (ximage->bits_per_pixel < 8)
7211 {
7212 register unsigned char
7213 background,
7214 byte,
7215 foreground,
7216 p_bit,
7217 q_bit;
7218
7219 register unsigned int
7220 plane;
7221
7222 XPixelInfo
7223 *pixel_info;
7224
7225 pixel_info=windows->magnify.pixel_info;
7226 switch (ximage->bitmap_bit_order)
7227 {
7228 case LSBFirst:
7229 {
7230 /*
7231 Magnify little-endian bitmap.
7232 */
7233 background=0x00;
7234 foreground=0x80;
7235 if (ximage->format == XYBitmap)
7236 {
7237 background=(unsigned char)
7238 (XPixelIntensity(&pixel_info->foreground_color) <
7239 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7240 foreground=(unsigned char)
7241 (XPixelIntensity(&pixel_info->background_color) <
7242 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7243 if (windows->magnify.depth > 1)
7244 Swap(background,foreground);
7245 }
cristybb503372010-05-27 20:51:26 +00007246 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007247 {
7248 /*
7249 Propogate pixel magnify rows.
7250 */
7251 for (j=0; j < magnify; j++)
7252 {
7253 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7254 ((x*ximage->bits_per_pixel) >> 3);
7255 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7256 q_bit=0;
7257 byte=0;
7258 for (k=0; k < width; k+=magnify)
7259 {
7260 /*
7261 Propogate pixel magnify columns.
7262 */
7263 for (l=0; l < magnify; l++)
7264 {
7265 /*
7266 Propogate each bit plane.
7267 */
7268 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7269 {
7270 byte>>=1;
7271 if (*p & (0x01 << (p_bit+plane)))
7272 byte|=foreground;
7273 else
7274 byte|=background;
7275 q_bit++;
7276 if (q_bit == 8)
7277 {
7278 *q++=byte;
7279 q_bit=0;
7280 byte=0;
7281 }
7282 }
7283 }
7284 p_bit+=ximage->bits_per_pixel;
7285 if (p_bit == 8)
7286 {
7287 p++;
7288 p_bit=0;
7289 }
7290 if (q_bit != 0)
7291 *q=byte >> (8-q_bit);
7292 q+=scanline_pad;
7293 }
7294 }
7295 y++;
7296 }
7297 break;
7298 }
7299 case MSBFirst:
7300 default:
7301 {
7302 /*
7303 Magnify big-endian bitmap.
7304 */
7305 background=0x00;
7306 foreground=0x01;
7307 if (ximage->format == XYBitmap)
7308 {
7309 background=(unsigned char)
7310 (XPixelIntensity(&pixel_info->foreground_color) <
7311 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7312 foreground=(unsigned char)
7313 (XPixelIntensity(&pixel_info->background_color) <
7314 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7315 if (windows->magnify.depth > 1)
7316 Swap(background,foreground);
7317 }
cristybb503372010-05-27 20:51:26 +00007318 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007319 {
7320 /*
7321 Propogate pixel magnify rows.
7322 */
7323 for (j=0; j < magnify; j++)
7324 {
7325 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7326 ((x*ximage->bits_per_pixel) >> 3);
7327 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7328 q_bit=0;
7329 byte=0;
7330 for (k=0; k < width; k+=magnify)
7331 {
7332 /*
7333 Propogate pixel magnify columns.
7334 */
7335 for (l=0; l < magnify; l++)
7336 {
7337 /*
7338 Propogate each bit plane.
7339 */
7340 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7341 {
7342 byte<<=1;
7343 if (*p & (0x80 >> (p_bit+plane)))
7344 byte|=foreground;
7345 else
7346 byte|=background;
7347 q_bit++;
7348 if (q_bit == 8)
7349 {
7350 *q++=byte;
7351 q_bit=0;
7352 byte=0;
7353 }
7354 }
7355 }
7356 p_bit+=ximage->bits_per_pixel;
7357 if (p_bit == 8)
7358 {
7359 p++;
7360 p_bit=0;
7361 }
7362 if (q_bit != 0)
7363 *q=byte << (8-q_bit);
7364 q+=scanline_pad;
7365 }
7366 }
7367 y++;
7368 }
7369 break;
7370 }
7371 }
7372 }
7373 else
7374 switch (ximage->bits_per_pixel)
7375 {
7376 case 6:
7377 case 8:
7378 {
7379 /*
7380 Magnify 8 bit X image.
7381 */
cristybb503372010-05-27 20:51:26 +00007382 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007383 {
7384 /*
7385 Propogate pixel magnify rows.
7386 */
7387 for (j=0; j < magnify; j++)
7388 {
7389 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7390 ((x*ximage->bits_per_pixel) >> 3);
7391 for (k=0; k < width; k+=magnify)
7392 {
7393 /*
7394 Propogate pixel magnify columns.
7395 */
7396 for (l=0; l < magnify; l++)
7397 *q++=(*p);
7398 p++;
7399 }
7400 q+=scanline_pad;
7401 }
7402 y++;
7403 }
7404 break;
7405 }
7406 default:
7407 {
7408 register unsigned int
7409 bytes_per_pixel,
7410 m;
7411
7412 /*
7413 Magnify multi-byte X image.
7414 */
7415 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007416 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007417 {
7418 /*
7419 Propogate pixel magnify rows.
7420 */
7421 for (j=0; j < magnify; j++)
7422 {
7423 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7424 ((x*ximage->bits_per_pixel) >> 3);
7425 for (k=0; k < width; k+=magnify)
7426 {
7427 /*
7428 Propogate pixel magnify columns.
7429 */
7430 for (l=0; l < magnify; l++)
7431 for (m=0; m < bytes_per_pixel; m++)
7432 *q++=(*(p+m));
7433 p+=bytes_per_pixel;
7434 }
7435 q+=scanline_pad;
7436 }
7437 y++;
7438 }
7439 break;
7440 }
7441 }
7442 /*
7443 Copy X image to magnify pixmap.
7444 */
7445 x=windows->magnify.x-((width/magnify) >> 1);
7446 if (x < 0)
7447 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7448 else
7449 if (x > (int) (ximage->width-(width/magnify)))
7450 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7451 else
7452 x=0;
7453 y=windows->magnify.y-((height/magnify) >> 1);
7454 if (y < 0)
7455 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7456 else
7457 if (y > (int) (ximage->height-(height/magnify)))
7458 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7459 else
7460 y=0;
7461 if ((x != 0) || (y != 0))
7462 (void) XFillRectangle(display,windows->magnify.pixmap,
7463 windows->magnify.annotate_context,0,0,width,height);
7464 (void) XPutImage(display,windows->magnify.pixmap,
7465 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7466 height-y);
7467 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7468 (magnify <= (height >> 1))))
7469 {
7470 RectangleInfo
7471 highlight_info;
7472
7473 /*
7474 Highlight center pixel.
7475 */
cristybb503372010-05-27 20:51:26 +00007476 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7477 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007478 highlight_info.width=magnify;
7479 highlight_info.height=magnify;
7480 (void) XDrawRectangle(display,windows->magnify.pixmap,
7481 windows->magnify.highlight_context,(int) highlight_info.x,
7482 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7483 (unsigned int) highlight_info.height-1);
7484 if (magnify > 2)
7485 (void) XDrawRectangle(display,windows->magnify.pixmap,
7486 windows->magnify.annotate_context,(int) highlight_info.x+1,
7487 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7488 (unsigned int) highlight_info.height-3);
7489 }
7490 /*
7491 Show center pixel color.
7492 */
cristy3aa93752011-12-18 15:54:24 +00007493 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007494 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007495 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007496 windows->magnify.x,windows->magnify.y);
7497 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007498 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007499 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007500 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007501 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007502 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007503 if (pixel.colorspace == CMYKColorspace)
7504 {
7505 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007506 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007507 }
cristy8a46d822012-08-28 23:32:39 +00007508 if (pixel.alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00007509 {
7510 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007511 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007512 }
7513 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7514 height=(unsigned int) windows->magnify.font_info->ascent+
7515 windows->magnify.font_info->descent;
7516 x=windows->magnify.font_info->max_bounds.width >> 1;
7517 y=windows->magnify.font_info->ascent+(height >> 2);
7518 (void) XDrawImageString(display,windows->magnify.pixmap,
7519 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7520 GetColorTuple(&pixel,MagickTrue,tuple);
7521 y+=height;
7522 (void) XDrawImageString(display,windows->magnify.pixmap,
7523 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007524 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007525 exception);
cristy3ed852e2009-09-05 21:47:34 +00007526 y+=height;
7527 (void) XDrawImageString(display,windows->magnify.pixmap,
7528 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7529 /*
7530 Refresh magnify window.
7531 */
7532 magnify_window=windows->magnify;
7533 magnify_window.x=0;
7534 magnify_window.y=0;
7535 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7536}
7537
7538/*
7539%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7540% %
7541% %
7542% %
7543% X M a k e P i x m a p %
7544% %
7545% %
7546% %
7547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7548%
7549% XMakePixmap() creates an X11 pixmap.
7550%
7551% The format of the XMakePixmap method is:
7552%
7553% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7554% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7555% XPixelInfo *pixel)
7556%
7557% A description of each parameter follows:
7558%
7559% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7560%
7561% o display: Specifies a connection to an X server; returned from
7562% XOpenDisplay.
7563%
7564% o window: Specifies a pointer to a XWindowInfo structure.
7565%
cristy3ed852e2009-09-05 21:47:34 +00007566*/
7567static MagickBooleanType XMakePixmap(Display *display,
7568 const XResourceInfo *resource_info,XWindowInfo *window)
7569{
7570 unsigned int
7571 height,
7572 width;
7573
7574 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7575 assert(display != (Display *) NULL);
7576 assert(resource_info != (XResourceInfo *) NULL);
7577 assert(window != (XWindowInfo *) NULL);
7578 if (window->pixmap != (Pixmap) NULL)
7579 {
7580 /*
7581 Destroy previous X pixmap.
7582 */
7583 (void) XFreePixmap(display,window->pixmap);
7584 window->pixmap=(Pixmap) NULL;
7585 }
7586 if (window->use_pixmap == MagickFalse)
7587 return(MagickFalse);
7588 if (window->ximage == (XImage *) NULL)
7589 return(MagickFalse);
7590 /*
7591 Display busy cursor.
7592 */
7593 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7594 (void) XFlush(display);
7595 /*
7596 Create pixmap.
7597 */
7598 width=(unsigned int) window->ximage->width;
7599 height=(unsigned int) window->ximage->height;
7600 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7601 if (window->pixmap == (Pixmap) NULL)
7602 {
7603 /*
7604 Unable to allocate pixmap.
7605 */
7606 (void) XCheckDefineCursor(display,window->id,window->cursor);
7607 return(MagickFalse);
7608 }
7609 /*
7610 Copy X image to pixmap.
7611 */
7612#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7613 if (window->shared_memory)
7614 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7615 window->ximage,0,0,0,0,width,height,MagickTrue);
7616#endif
7617 if (window->shared_memory == MagickFalse)
7618 (void) XPutImage(display,window->pixmap,window->annotate_context,
7619 window->ximage,0,0,0,0,width,height);
7620 if (IsEventLogging())
7621 {
7622 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7623 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7624 width,height);
7625 }
7626 /*
7627 Restore cursor.
7628 */
7629 (void) XCheckDefineCursor(display,window->id,window->cursor);
7630 return(MagickTrue);
7631}
7632
7633/*
7634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7635% %
7636% %
7637% %
7638% X M a k e S t a n d a r d C o l o r m a p %
7639% %
7640% %
7641% %
7642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7643%
7644% XMakeStandardColormap() creates an X11 Standard Colormap.
7645%
7646% The format of the XMakeStandardColormap method is:
7647%
cristy6710d842011-10-20 23:23:00 +00007648% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7649% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7650% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007651%
7652% A description of each parameter follows:
7653%
7654% o display: Specifies a connection to an X server; returned from
7655% XOpenDisplay.
7656%
7657% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7658% returned from XGetVisualInfo.
7659%
7660% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7661%
7662% o image: the image.
7663%
7664% o map_info: If a Standard Colormap type is specified, this structure is
7665% initialized with info from the Standard Colormap.
7666%
7667% o pixel: Specifies a pointer to a XPixelInfo structure.
7668%
cristy6710d842011-10-20 23:23:00 +00007669% o exception: return any errors or warnings in this structure.
7670%
cristy3ed852e2009-09-05 21:47:34 +00007671*/
7672
7673#if defined(__cplusplus) || defined(c_plusplus)
7674extern "C" {
7675#endif
7676
cristya19f1d72012-08-07 18:24:38 +00007677static inline double DiversityPixelIntensity(
cristy3ed852e2009-09-05 21:47:34 +00007678 const DiversityPacket *pixel)
7679{
cristya19f1d72012-08-07 18:24:38 +00007680 double
cristy3ed852e2009-09-05 21:47:34 +00007681 intensity;
7682
cristyd3d2a272013-06-24 16:09:41 +00007683 intensity=0.212656*pixel->red+0.715158*pixel->green+0.072186*pixel->blue;
cristy3ed852e2009-09-05 21:47:34 +00007684 return(intensity);
7685}
7686
7687static int IntensityCompare(const void *x,const void *y)
7688{
7689 DiversityPacket
7690 *color_1,
7691 *color_2;
7692
7693 int
7694 diversity;
7695
7696 color_1=(DiversityPacket *) x;
7697 color_2=(DiversityPacket *) y;
7698 diversity=(int) (DiversityPixelIntensity(color_2)-
7699 DiversityPixelIntensity(color_1));
7700 return(diversity);
7701}
7702
7703static int PopularityCompare(const void *x,const void *y)
7704{
7705 DiversityPacket
7706 *color_1,
7707 *color_2;
7708
7709 color_1=(DiversityPacket *) x;
7710 color_2=(DiversityPacket *) y;
7711 return((int) color_2->count-(int) color_1->count);
7712}
7713
7714#if defined(__cplusplus) || defined(c_plusplus)
7715}
7716#endif
7717
cristybb503372010-05-27 20:51:26 +00007718static inline Quantum ScaleXToQuantum(const size_t x,
7719 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007720{
cristya19f1d72012-08-07 18:24:38 +00007721 return((Quantum) (((double) QuantumRange*x)/scale+0.5));
cristy3ed852e2009-09-05 21:47:34 +00007722}
7723
cristybcbda3f2011-09-03 13:01:22 +00007724MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007725 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007726 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007727{
7728 Colormap
7729 colormap;
7730
cristybb503372010-05-27 20:51:26 +00007731 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007732 i;
7733
7734 Status
7735 status;
7736
cristybb503372010-05-27 20:51:26 +00007737 size_t
cristy3ed852e2009-09-05 21:47:34 +00007738 number_colors,
7739 retain_colors;
7740
7741 unsigned short
7742 gray_value;
7743
7744 XColor
7745 color,
7746 *colors,
7747 *p;
7748
7749 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7750 assert(display != (Display *) NULL);
7751 assert(visual_info != (XVisualInfo *) NULL);
7752 assert(map_info != (XStandardColormap *) NULL);
7753 assert(resource_info != (XResourceInfo *) NULL);
7754 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007755 if (resource_info->map_type != (char *) NULL)
7756 {
7757 /*
7758 Standard Colormap is already defined (i.e. xstdcmap).
7759 */
cristy4c08aed2011-07-01 19:47:50 +00007760 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007761 pixel);
7762 number_colors=(unsigned int) (map_info->base_pixel+
7763 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7764 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
cristy8a46d822012-08-28 23:32:39 +00007765 if ((image->alpha_trait != BlendPixelTrait) &&
cristy3ed852e2009-09-05 21:47:34 +00007766 (resource_info->color_recovery == MagickFalse) &&
cristycbda6112012-05-27 20:57:16 +00007767 (resource_info->quantize_info->dither_method != NoDitherMethod) &&
cristy3ed852e2009-09-05 21:47:34 +00007768 (number_colors < MaxColormapSize))
7769 {
7770 Image
7771 *affinity_image;
7772
cristy4c08aed2011-07-01 19:47:50 +00007773 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007774 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007775
7776 /*
7777 Improve image appearance with error diffusion.
7778 */
cristy6710d842011-10-20 23:23:00 +00007779 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007780 if (affinity_image == (Image *) NULL)
7781 ThrowXWindowFatalException(ResourceLimitFatalError,
7782 "UnableToDitherImage",image->filename);
7783 affinity_image->columns=number_colors;
7784 affinity_image->rows=1;
7785 /*
7786 Initialize colormap image.
7787 */
7788 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7789 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007790 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007791 {
cristybb503372010-05-27 20:51:26 +00007792 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007793 {
cristy4c08aed2011-07-01 19:47:50 +00007794 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007795 if (map_info->red_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007796 SetPixelRed(affinity_image,ScaleXToQuantum((size_t)
7797 (i/map_info->red_mult),map_info->red_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007798 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007799 if (map_info->green_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007800 SetPixelGreen(affinity_image,ScaleXToQuantum((size_t)
7801 ((i/map_info->green_mult) % (map_info->green_max+1)),
7802 map_info->green_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007803 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007804 if (map_info->blue_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007805 SetPixelBlue(affinity_image,ScaleXToQuantum((size_t)
7806 (i % map_info->green_mult),map_info->blue_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007807 SetPixelAlpha(affinity_image,
7808 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007809 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007810 }
7811 (void) SyncAuthenticPixels(affinity_image,exception);
7812 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007813 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007814 }
cristy4c08aed2011-07-01 19:47:50 +00007815 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007816 pixel);
cristy574cc262011-08-05 01:23:58 +00007817 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007818 affinity_image=DestroyImage(affinity_image);
7819 }
7820 if (IsEventLogging())
7821 {
7822 (void) LogMagickEvent(X11Event,GetMagickModule(),
7823 "Standard Colormap:");
7824 (void) LogMagickEvent(X11Event,GetMagickModule(),
7825 " colormap id: 0x%lx",map_info->colormap);
7826 (void) LogMagickEvent(X11Event,GetMagickModule(),
7827 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7828 map_info->green_max,map_info->blue_max);
7829 (void) LogMagickEvent(X11Event,GetMagickModule(),
7830 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7831 map_info->green_mult,map_info->blue_mult);
7832 }
7833 return;
7834 }
7835 if ((visual_info->klass != DirectColor) &&
7836 (visual_info->klass != TrueColor))
7837 if ((image->storage_class == DirectClass) ||
7838 ((int) image->colors > visual_info->colormap_size))
7839 {
7840 QuantizeInfo
7841 quantize_info;
7842
7843 /*
7844 Image has more colors than the visual supports.
7845 */
7846 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007847 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007848 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007849 }
7850 /*
7851 Free previous and create new colormap.
7852 */
7853 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7854 colormap=XDefaultColormap(display,visual_info->screen);
7855 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7856 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7857 visual_info->visual,visual_info->klass == DirectColor ?
7858 AllocAll : AllocNone);
7859 if (colormap == (Colormap) NULL)
7860 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7861 image->filename);
7862 /*
7863 Initialize the map and pixel info structures.
7864 */
7865 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007866 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007867 /*
7868 Allocating colors in server colormap is based on visual class.
7869 */
7870 switch (visual_info->klass)
7871 {
7872 case StaticGray:
7873 case StaticColor:
7874 {
7875 /*
7876 Define Standard Colormap for StaticGray or StaticColor visual.
7877 */
7878 number_colors=image->colors;
7879 colors=(XColor *) AcquireQuantumMemory((size_t)
7880 visual_info->colormap_size,sizeof(*colors));
7881 if (colors == (XColor *) NULL)
7882 ThrowXWindowFatalException(ResourceLimitFatalError,
7883 "UnableToCreateColormap",image->filename);
7884 p=colors;
7885 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007886 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007887 {
7888 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7889 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7890 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7891 if (visual_info->klass != StaticColor)
7892 {
7893 gray_value=(unsigned short) XPixelIntensity(&color);
7894 color.red=gray_value;
7895 color.green=gray_value;
7896 color.blue=gray_value;
7897 }
7898 status=XAllocColor(display,colormap,&color);
7899 if (status == False)
7900 {
7901 colormap=XCopyColormapAndFree(display,colormap);
7902 (void) XAllocColor(display,colormap,&color);
7903 }
7904 pixel->pixels[i]=color.pixel;
7905 *p++=color;
7906 }
7907 break;
7908 }
7909 case GrayScale:
7910 case PseudoColor:
7911 {
7912 unsigned int
7913 colormap_type;
7914
7915 /*
7916 Define Standard Colormap for GrayScale or PseudoColor visual.
7917 */
7918 number_colors=image->colors;
7919 colors=(XColor *) AcquireQuantumMemory((size_t)
7920 visual_info->colormap_size,sizeof(*colors));
7921 if (colors == (XColor *) NULL)
7922 ThrowXWindowFatalException(ResourceLimitFatalError,
7923 "UnableToCreateColormap",image->filename);
7924 /*
7925 Preallocate our GUI colors.
7926 */
7927 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7928 (void) XAllocColor(display,colormap,&pixel->background_color);
7929 (void) XAllocColor(display,colormap,&pixel->border_color);
7930 (void) XAllocColor(display,colormap,&pixel->matte_color);
7931 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7932 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7933 (void) XAllocColor(display,colormap,&pixel->depth_color);
7934 (void) XAllocColor(display,colormap,&pixel->trough_color);
7935 for (i=0; i < MaxNumberPens; i++)
7936 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7937 /*
7938 Determine if image colors will "fit" into X server colormap.
7939 */
7940 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007941 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007942 NULL,0,pixel->pixels,(unsigned int) image->colors);
7943 if (status != False)
7944 colormap_type=PrivateColormap;
7945 if (colormap_type == SharedColormap)
7946 {
cristyc57f6942010-11-12 01:47:39 +00007947 CacheView
7948 *image_view;
7949
cristy3ed852e2009-09-05 21:47:34 +00007950 DiversityPacket
7951 *diversity;
7952
7953 int
7954 y;
7955
7956 register int
7957 x;
7958
7959 unsigned short
7960 index;
7961
7962 XColor
7963 *server_colors;
7964
7965 /*
7966 Define Standard colormap for shared GrayScale or PseudoColor visual.
7967 */
7968 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7969 sizeof(*diversity));
7970 if (diversity == (DiversityPacket *) NULL)
7971 ThrowXWindowFatalException(ResourceLimitFatalError,
7972 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007973 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007974 {
cristye42f6582012-02-11 17:59:50 +00007975 diversity[i].red=ClampToQuantum(image->colormap[i].red);
7976 diversity[i].green=ClampToQuantum(image->colormap[i].green);
7977 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00007978 diversity[i].index=(unsigned short) i;
7979 diversity[i].count=0;
7980 }
cristy46ff2672012-12-14 15:32:26 +00007981 image_view=AcquireAuthenticCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007982 for (y=0; y < (int) image->rows; y++)
7983 {
cristyc57f6942010-11-12 01:47:39 +00007984 register int
cristy3ed852e2009-09-05 21:47:34 +00007985 x;
7986
cristy4c08aed2011-07-01 19:47:50 +00007987 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007988 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007989
cristyc57f6942010-11-12 01:47:39 +00007990 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7991 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007992 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007993 break;
cristyc57f6942010-11-12 01:47:39 +00007994 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00007995 {
7996 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00007997 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00007998 }
cristy3ed852e2009-09-05 21:47:34 +00007999 }
cristyc57f6942010-11-12 01:47:39 +00008000 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008001 /*
8002 Sort colors by decreasing intensity.
8003 */
8004 qsort((void *) diversity,image->colors,sizeof(*diversity),
8005 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008006 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008007 {
8008 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008009 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008010 }
8011 diversity[image->colors-1].count<<=4;
8012 qsort((void *) diversity,image->colors,sizeof(*diversity),
8013 PopularityCompare);
8014 /*
8015 Allocate colors.
8016 */
8017 p=colors;
8018 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008019 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008020 {
8021 index=diversity[i].index;
8022 color.red=
8023 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8024 color.green=
8025 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8026 color.blue=
8027 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8028 if (visual_info->klass != PseudoColor)
8029 {
8030 gray_value=(unsigned short) XPixelIntensity(&color);
8031 color.red=gray_value;
8032 color.green=gray_value;
8033 color.blue=gray_value;
8034 }
8035 status=XAllocColor(display,colormap,&color);
8036 if (status == False)
8037 break;
8038 pixel->pixels[index]=color.pixel;
8039 *p++=color;
8040 }
8041 /*
8042 Read X server colormap.
8043 */
8044 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8045 visual_info->colormap_size,sizeof(*server_colors));
8046 if (server_colors == (XColor *) NULL)
8047 ThrowXWindowFatalException(ResourceLimitFatalError,
8048 "UnableToCreateColormap",image->filename);
8049 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008050 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008051 (void) XQueryColors(display,colormap,server_colors,
8052 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8053 /*
8054 Select remaining colors from X server colormap.
8055 */
cristybb503372010-05-27 20:51:26 +00008056 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008057 {
8058 index=diversity[i].index;
cristy534d0a32013-04-13 16:27:24 +00008059 color.red=ScaleQuantumToShort(
8060 XRedGamma(image->colormap[index].red));
8061 color.green=ScaleQuantumToShort(
8062 XGreenGamma(image->colormap[index].green));
8063 color.blue=ScaleQuantumToShort(
8064 XBlueGamma(image->colormap[index].blue));
cristy3ed852e2009-09-05 21:47:34 +00008065 if (visual_info->klass != PseudoColor)
8066 {
8067 gray_value=(unsigned short) XPixelIntensity(&color);
8068 color.red=gray_value;
8069 color.green=gray_value;
8070 color.blue=gray_value;
8071 }
8072 XBestPixel(display,colormap,server_colors,(unsigned int)
8073 visual_info->colormap_size,&color);
8074 pixel->pixels[index]=color.pixel;
8075 *p++=color;
8076 }
8077 if ((int) image->colors < visual_info->colormap_size)
8078 {
8079 /*
8080 Fill up colors array-- more choices for pen colors.
8081 */
8082 retain_colors=MagickMin((unsigned int)
8083 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008084 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008085 *p++=server_colors[i];
8086 number_colors+=retain_colors;
8087 }
8088 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8089 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8090 break;
8091 }
8092 /*
8093 Define Standard colormap for private GrayScale or PseudoColor visual.
8094 */
8095 if (status == False)
8096 {
8097 /*
8098 Not enough colormap entries in the colormap-- Create a new colormap.
8099 */
8100 colormap=XCreateColormap(display,
8101 XRootWindow(display,visual_info->screen),visual_info->visual,
8102 AllocNone);
8103 if (colormap == (Colormap) NULL)
8104 ThrowXWindowFatalException(ResourceLimitFatalError,
8105 "UnableToCreateColormap",image->filename);
8106 map_info->colormap=colormap;
8107 if ((int) image->colors < visual_info->colormap_size)
8108 {
8109 /*
8110 Retain colors from the default colormap to help lessens the
8111 effects of colormap flashing.
8112 */
8113 retain_colors=MagickMin((unsigned int)
8114 (visual_info->colormap_size-image->colors),256);
8115 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008116 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008117 {
cristyc57f6942010-11-12 01:47:39 +00008118 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008119 p++;
8120 }
8121 (void) XQueryColors(display,
8122 XDefaultColormap(display,visual_info->screen),
8123 colors+image->colors,(int) retain_colors);
8124 /*
8125 Transfer colors from default to private colormap.
8126 */
8127 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008128 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008129 retain_colors);
8130 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008131 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008132 {
8133 p->pixel=pixel->pixels[i];
8134 p++;
8135 }
8136 (void) XStoreColors(display,colormap,colors+image->colors,
8137 (int) retain_colors);
8138 number_colors+=retain_colors;
8139 }
8140 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008141 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008142 image->colors);
8143 }
8144 /*
8145 Store the image colormap.
8146 */
8147 p=colors;
8148 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008149 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008150 {
8151 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8152 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8153 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8154 if (visual_info->klass != PseudoColor)
8155 {
8156 gray_value=(unsigned short) XPixelIntensity(&color);
8157 color.red=gray_value;
8158 color.green=gray_value;
8159 color.blue=gray_value;
8160 }
8161 color.pixel=pixel->pixels[i];
8162 *p++=color;
8163 }
8164 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8165 break;
8166 }
8167 case TrueColor:
8168 case DirectColor:
8169 default:
8170 {
8171 MagickBooleanType
8172 linear_colormap;
8173
8174 /*
8175 Define Standard Colormap for TrueColor or DirectColor visual.
8176 */
8177 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8178 (map_info->green_max*map_info->green_mult)+
8179 (map_info->blue_max*map_info->blue_mult)+1);
8180 linear_colormap=(number_colors > 4096) ||
8181 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8182 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8183 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8184 MagickTrue : MagickFalse;
8185 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008186 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008187 /*
8188 Allocate color array.
8189 */
8190 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8191 if (colors == (XColor *) NULL)
8192 ThrowXWindowFatalException(ResourceLimitFatalError,
8193 "UnableToCreateColormap",image->filename);
8194 /*
8195 Initialize linear color ramp.
8196 */
8197 p=colors;
8198 color.flags=(char) (DoRed | DoGreen | DoBlue);
8199 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008200 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008201 {
8202 color.blue=(unsigned short) 0;
8203 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008204 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008205 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8206 color.green=color.blue;
8207 color.red=color.blue;
8208 color.pixel=XStandardPixel(map_info,&color);
8209 *p++=color;
8210 }
8211 else
cristybb503372010-05-27 20:51:26 +00008212 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008213 {
8214 color.red=(unsigned short) 0;
8215 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008216 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008217 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8218 color.green=(unsigned int) 0;
8219 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008220 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008221 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8222 map_info->green_max));
8223 color.blue=(unsigned short) 0;
8224 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008225 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008226 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8227 color.pixel=XStandardPixel(map_info,&color);
8228 *p++=color;
8229 }
8230 if ((visual_info->klass == DirectColor) &&
8231 (colormap != XDefaultColormap(display,visual_info->screen)))
8232 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8233 else
cristybb503372010-05-27 20:51:26 +00008234 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008235 (void) XAllocColor(display,colormap,&colors[i]);
8236 break;
8237 }
8238 }
8239 if ((visual_info->klass != DirectColor) &&
8240 (visual_info->klass != TrueColor))
8241 {
8242 /*
8243 Set foreground, background, border, etc. pixels.
8244 */
8245 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8246 &pixel->foreground_color);
8247 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8248 &pixel->background_color);
8249 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8250 {
8251 /*
8252 Foreground and background colors must differ.
8253 */
8254 pixel->background_color.red=(~pixel->foreground_color.red);
8255 pixel->background_color.green=
8256 (~pixel->foreground_color.green);
8257 pixel->background_color.blue=
8258 (~pixel->foreground_color.blue);
8259 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8260 &pixel->background_color);
8261 }
8262 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8263 &pixel->border_color);
8264 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8265 &pixel->matte_color);
8266 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8267 &pixel->highlight_color);
8268 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8269 &pixel->shadow_color);
8270 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8271 &pixel->depth_color);
8272 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8273 &pixel->trough_color);
8274 for (i=0; i < MaxNumberPens; i++)
8275 {
8276 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8277 &pixel->pen_colors[i]);
8278 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8279 }
cristyc57f6942010-11-12 01:47:39 +00008280 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008281 }
8282 colors=(XColor *) RelinquishMagickMemory(colors);
8283 if (IsEventLogging())
8284 {
8285 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8286 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8287 map_info->colormap);
8288 (void) LogMagickEvent(X11Event,GetMagickModule(),
8289 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8290 map_info->green_max,map_info->blue_max);
8291 (void) LogMagickEvent(X11Event,GetMagickModule(),
8292 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8293 map_info->green_mult,map_info->blue_mult);
8294 }
8295}
8296
8297/*
8298%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8299% %
8300% %
8301% %
8302% X M a k e W i n d o w %
8303% %
8304% %
8305% %
8306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8307%
8308% XMakeWindow() creates an X11 window.
8309%
8310% The format of the XMakeWindow method is:
8311%
8312% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8313% XClassHint *class_hint,XWMHints *manager_hints,
8314% XWindowInfo *window_info)
8315%
8316% A description of each parameter follows:
8317%
8318% o display: Specifies a connection to an X server; returned from
8319% XOpenDisplay.
8320%
8321% o parent: Specifies the parent window_info.
8322%
8323% o argv: Specifies the application's argument list.
8324%
8325% o argc: Specifies the number of arguments.
8326%
8327% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8328%
8329% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8330%
8331% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8332%
8333*/
cristybcbda3f2011-09-03 13:01:22 +00008334MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008335 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8336 XWindowInfo *window_info)
8337{
8338#define MinWindowSize 64
8339
8340 Atom
8341 atom_list[2];
8342
8343 int
8344 gravity;
8345
8346 static XTextProperty
8347 icon_name,
8348 window_name;
8349
8350 Status
8351 status;
8352
8353 XSizeHints
8354 *size_hints;
8355
8356 /*
8357 Set window info hints.
8358 */
8359 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8360 assert(display != (Display *) NULL);
8361 assert(window_info != (XWindowInfo *) NULL);
8362 size_hints=XAllocSizeHints();
8363 if (size_hints == (XSizeHints *) NULL)
8364 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008365 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008366 size_hints->x=window_info->x;
8367 size_hints->y=window_info->y;
8368 size_hints->width=(int) window_info->width;
8369 size_hints->height=(int) window_info->height;
8370 if (window_info->immutable != MagickFalse)
8371 {
8372 /*
8373 Window size cannot be changed.
8374 */
8375 size_hints->min_width=size_hints->width;
8376 size_hints->min_height=size_hints->height;
8377 size_hints->max_width=size_hints->width;
8378 size_hints->max_height=size_hints->height;
8379 size_hints->flags|=PMinSize;
8380 size_hints->flags|=PMaxSize;
8381 }
8382 else
8383 {
8384 /*
8385 Window size can be changed.
8386 */
8387 size_hints->min_width=(int) window_info->min_width;
8388 size_hints->min_height=(int) window_info->min_height;
8389 size_hints->flags|=PResizeInc;
8390 size_hints->width_inc=(int) window_info->width_inc;
8391 size_hints->height_inc=(int) window_info->height_inc;
8392#if !defined(PRE_R4_ICCCM)
8393 size_hints->flags|=PBaseSize;
8394 size_hints->base_width=size_hints->width_inc;
8395 size_hints->base_height=size_hints->height_inc;
8396#endif
8397 }
8398 gravity=NorthWestGravity;
8399 if (window_info->geometry != (char *) NULL)
8400 {
8401 char
8402 default_geometry[MaxTextExtent],
8403 geometry[MaxTextExtent];
8404
8405 int
8406 flags;
8407
8408 register char
8409 *p;
8410
8411 /*
8412 User specified geometry.
8413 */
cristyb51dff52011-05-19 16:55:47 +00008414 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008415 size_hints->width,size_hints->height);
8416 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8417 p=geometry;
8418 while (strlen(p) != 0)
8419 {
8420 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8421 p++;
8422 else
8423 (void) CopyMagickString(p,p+1,MaxTextExtent);
8424 }
8425 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8426 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8427 &size_hints->width,&size_hints->height,&gravity);
8428 if ((flags & WidthValue) && (flags & HeightValue))
8429 size_hints->flags|=USSize;
8430 if ((flags & XValue) && (flags & YValue))
8431 {
8432 size_hints->flags|=USPosition;
8433 window_info->x=size_hints->x;
8434 window_info->y=size_hints->y;
8435 }
8436 }
8437#if !defined(PRE_R4_ICCCM)
8438 size_hints->win_gravity=gravity;
8439 size_hints->flags|=PWinGravity;
8440#endif
8441 if (window_info->id == (Window) NULL)
8442 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8443 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8444 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008445 window_info->visual,(unsigned long) window_info->mask,
8446 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008447 else
8448 {
8449 MagickStatusType
8450 mask;
8451
8452 XEvent
8453 sans_event;
8454
8455 XWindowChanges
8456 window_changes;
8457
8458 /*
8459 Window already exists; change relevant attributes.
8460 */
cristyc57f6942010-11-12 01:47:39 +00008461 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8462 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008463 mask=ConfigureNotify;
8464 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8465 window_changes.x=window_info->x;
8466 window_changes.y=window_info->y;
8467 window_changes.width=(int) window_info->width;
8468 window_changes.height=(int) window_info->height;
8469 mask=(MagickStatusType) (CWWidth | CWHeight);
8470 if (window_info->flags & USPosition)
8471 mask|=CWX | CWY;
8472 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8473 mask,&window_changes);
8474 }
8475 if (window_info->id == (Window) NULL)
8476 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8477 window_info->name);
8478 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8479 if (status == False)
8480 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8481 window_info->name);
8482 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8483 if (status == False)
8484 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8485 window_info->icon_name);
8486 if (window_info->icon_geometry != (char *) NULL)
8487 {
8488 int
8489 flags,
8490 height,
8491 width;
8492
8493 /*
8494 User specified icon geometry.
8495 */
8496 size_hints->flags|=USPosition;
8497 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8498 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8499 &manager_hints->icon_y,&width,&height,&gravity);
8500 if ((flags & XValue) && (flags & YValue))
8501 manager_hints->flags|=IconPositionHint;
8502 }
8503 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8504 size_hints,manager_hints,class_hint);
8505 if (window_name.value != (void *) NULL)
8506 {
8507 (void) XFree((void *) window_name.value);
8508 window_name.value=(unsigned char *) NULL;
8509 window_name.nitems=0;
8510 }
8511 if (icon_name.value != (void *) NULL)
8512 {
8513 (void) XFree((void *) icon_name.value);
8514 icon_name.value=(unsigned char *) NULL;
8515 icon_name.nitems=0;
8516 }
8517 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8518 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8519 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8520 (void) XFree((void *) size_hints);
8521 if (window_info->shape != MagickFalse)
8522 {
8523#if defined(MAGICKCORE_HAVE_SHAPE)
8524 int
8525 error_base,
8526 event_base;
8527
8528 /*
8529 Can we apply a non-rectangular shaping mask?
8530 */
8531 error_base=0;
8532 event_base=0;
8533 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8534 window_info->shape=MagickFalse;
8535#else
8536 window_info->shape=MagickFalse;
8537#endif
8538 }
8539 if (window_info->shared_memory)
8540 {
8541#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8542 /*
8543 Can we use shared memory with this window?
8544 */
8545 if (XShmQueryExtension(display) == 0)
8546 window_info->shared_memory=MagickFalse;
8547#else
8548 window_info->shared_memory=MagickFalse;
8549#endif
8550 }
8551 window_info->image=NewImageList();
8552 window_info->destroy=MagickFalse;
8553}
8554
8555/*
8556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8557% %
8558% %
8559% %
8560% X M a g i c k P r o g r e s s M o n i t o r %
8561% %
8562% %
8563% %
8564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8565%
8566% XMagickProgressMonitor() displays the progress a task is making in
8567% completing a task.
8568%
8569% The format of the XMagickProgressMonitor method is:
8570%
8571% void XMagickProgressMonitor(const char *task,
8572% const MagickOffsetType quantum,const MagickSizeType span,
8573% void *client_data)
8574%
8575% A description of each parameter follows:
8576%
8577% o task: Identifies the task in progress.
8578%
8579% o quantum: Specifies the quantum position within the span which represents
8580% how much progress has been made in completing a task.
8581%
8582% o span: Specifies the span relative to completing a task.
8583%
8584% o client_data: Pointer to any client data.
8585%
8586*/
8587
8588static const char *GetLocaleMonitorMessage(const char *text)
8589{
8590 char
8591 message[MaxTextExtent],
8592 tag[MaxTextExtent];
8593
8594 const char
8595 *locale_message;
8596
8597 register char
8598 *p;
8599
8600 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8601 p=strrchr(tag,'/');
8602 if (p != (char *) NULL)
8603 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008604 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008605 locale_message=GetLocaleMessage(message);
8606 if (locale_message == message)
8607 return(text);
8608 return(locale_message);
8609}
8610
cristybcbda3f2011-09-03 13:01:22 +00008611MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008612 const MagickOffsetType quantum,const MagickSizeType span,
8613 void *magick_unused(client_data))
8614{
8615 XWindows
8616 *windows;
8617
8618 windows=XSetWindows((XWindows *) ~0);
8619 if (windows == (XWindows *) NULL)
8620 return(MagickTrue);
8621 if (windows->info.mapped != MagickFalse)
8622 XProgressMonitorWidget(windows->display,windows,
8623 GetLocaleMonitorMessage(tag),quantum,span);
8624 return(MagickTrue);
8625}
8626
8627/*
8628%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8629% %
8630% %
8631% %
8632% X Q u e r y C o l o r D a t a b a s e %
8633% %
8634% %
8635% %
8636%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8637%
cristy9950d572011-10-01 18:22:35 +00008638% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008639% string.
8640%
8641% The format of the XQueryColorDatabase method is:
8642%
cristy9950d572011-10-01 18:22:35 +00008643% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008644%
8645% A description of each parameter follows:
8646%
8647% o target: Specifies the color to lookup in the X color database.
8648%
cristy101ab702011-10-13 13:06:32 +00008649% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008650% color is returned as this value.
8651%
8652*/
cristy9950d572011-10-01 18:22:35 +00008653MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008654 XColor *color)
8655{
8656 Colormap
8657 colormap;
8658
8659 static Display
8660 *display = (Display *) NULL;
8661
8662 Status
8663 status;
8664
8665 XColor
8666 xcolor;
8667
8668 /*
8669 Initialize color return value.
8670 */
8671 assert(color != (XColor *) NULL);
8672 color->red=0;
8673 color->green=0;
8674 color->blue=0;
8675 color->flags=(char) (DoRed | DoGreen | DoBlue);
8676 if ((target == (char *) NULL) || (*target == '\0'))
8677 target="#ffffffffffff";
8678 /*
8679 Let the X server define the color for us.
8680 */
8681 if (display == (Display *) NULL)
8682 display=XOpenDisplay((char *) NULL);
8683 if (display == (Display *) NULL)
8684 {
8685 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8686 return(MagickFalse);
8687 }
8688 colormap=XDefaultColormap(display,XDefaultScreen(display));
8689 status=XParseColor(display,colormap,(char *) target,&xcolor);
8690 if (status == False)
8691 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8692 else
8693 {
8694 color->red=xcolor.red;
8695 color->green=xcolor.green;
8696 color->blue=xcolor.blue;
8697 color->flags=xcolor.flags;
8698 }
8699 return(status != False ? MagickTrue : MagickFalse);
8700}
8701
8702/*
8703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8704% %
8705% %
8706% %
8707% X Q u e r y P o s i t i o n %
8708% %
8709% %
8710% %
8711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8712%
8713% XQueryPosition() gets the pointer coordinates relative to a window.
8714%
8715% The format of the XQueryPosition method is:
8716%
8717% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8718%
8719% A description of each parameter follows:
8720%
8721% o display: Specifies a connection to an X server; returned from
8722% XOpenDisplay.
8723%
8724% o window: Specifies a pointer to a Window.
8725%
8726% o x: Return the x coordinate of the pointer relative to the origin of the
8727% window.
8728%
8729% o y: Return the y coordinate of the pointer relative to the origin of the
8730% window.
8731%
8732*/
cristy534d0a32013-04-13 16:27:24 +00008733MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,
8734 int *y)
cristy3ed852e2009-09-05 21:47:34 +00008735{
8736 int
8737 x_root,
8738 y_root;
8739
8740 unsigned int
8741 mask;
8742
8743 Window
8744 root_window;
8745
8746 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8747 assert(display != (Display *) NULL);
8748 assert(window != (Window) NULL);
8749 assert(x != (int *) NULL);
8750 assert(y != (int *) NULL);
8751 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8752 x,y,&mask);
8753}
8754
8755/*
8756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8757% %
8758% %
8759% %
8760% X R e f r e s h W i n d o w %
8761% %
8762% %
8763% %
8764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8765%
8766% XRefreshWindow() refreshes an image in a X window.
8767%
8768% The format of the XRefreshWindow method is:
8769%
8770% void XRefreshWindow(Display *display,const XWindowInfo *window,
8771% const XEvent *event)
8772%
8773% A description of each parameter follows:
8774%
8775% o display: Specifies a connection to an X server; returned from
8776% XOpenDisplay.
8777%
8778% o window: Specifies a pointer to a XWindowInfo structure.
8779%
8780% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8781% the entire image is refreshed.
8782%
8783*/
cristybcbda3f2011-09-03 13:01:22 +00008784MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008785 const XEvent *event)
8786{
8787 int
8788 x,
8789 y;
8790
8791 unsigned int
8792 height,
8793 width;
8794
8795 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8796 assert(display != (Display *) NULL);
8797 assert(window != (XWindowInfo *) NULL);
8798 if (window->ximage == (XImage *) NULL)
8799 return;
8800 if (event != (XEvent *) NULL)
8801 {
8802 /*
8803 Determine geometry from expose event.
8804 */
8805 x=event->xexpose.x;
8806 y=event->xexpose.y;
8807 width=(unsigned int) event->xexpose.width;
8808 height=(unsigned int) event->xexpose.height;
8809 }
8810 else
8811 {
8812 XEvent
8813 sans_event;
8814
8815 /*
8816 Refresh entire window; discard outstanding expose events.
8817 */
8818 x=0;
8819 y=0;
8820 width=window->width;
8821 height=window->height;
8822 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008823 if (window->matte_pixmap != (Pixmap) NULL)
8824 {
8825#if defined(MAGICKCORE_HAVE_SHAPE)
8826 if (window->shape != MagickFalse)
8827 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8828 window->matte_pixmap,ShapeSet);
8829#endif
8830 }
cristy3ed852e2009-09-05 21:47:34 +00008831 }
8832 /*
8833 Check boundary conditions.
8834 */
8835 if ((window->ximage->width-(x+window->x)) < (int) width)
8836 width=(unsigned int) (window->ximage->width-(x+window->x));
8837 if ((window->ximage->height-(y+window->y)) < (int) height)
8838 height=(unsigned int) (window->ximage->height-(y+window->y));
8839 /*
8840 Refresh image.
8841 */
8842 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008843 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008844 if (window->pixmap != (Pixmap) NULL)
8845 {
8846 if (window->depth > 1)
8847 (void) XCopyArea(display,window->pixmap,window->id,
8848 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8849 else
8850 (void) XCopyPlane(display,window->pixmap,window->id,
8851 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8852 1L);
8853 }
8854 else
8855 {
8856#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8857 if (window->shared_memory)
8858 (void) XShmPutImage(display,window->id,window->annotate_context,
8859 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8860#endif
8861 if (window->shared_memory == MagickFalse)
8862 (void) XPutImage(display,window->id,window->annotate_context,
8863 window->ximage,x+window->x,y+window->y,x,y,width,height);
8864 }
8865 if (window->matte_pixmap != (Pixmap) NULL)
8866 (void) XSetClipMask(display,window->annotate_context,None);
8867 (void) XFlush(display);
8868}
8869
8870/*
8871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8872% %
8873% %
8874% %
8875% X R e m o t e C o m m a n d %
8876% %
8877% %
8878% %
8879%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8880%
8881% XRemoteCommand() forces a remote display(1) to display the specified
8882% image filename.
8883%
8884% The format of the XRemoteCommand method is:
8885%
8886% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8887% const char *filename)
8888%
8889% A description of each parameter follows:
8890%
8891% o display: Specifies a connection to an X server; returned from
8892% XOpenDisplay.
8893%
8894% o window: Specifies the name or id of an X window.
8895%
8896% o filename: the name of the image filename to display.
8897%
8898*/
8899MagickExport MagickBooleanType XRemoteCommand(Display *display,
8900 const char *window,const char *filename)
8901{
8902 Atom
8903 remote_atom;
8904
8905 Window
8906 remote_window,
8907 root_window;
8908
8909 assert(filename != (char *) NULL);
8910 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8911 if (display == (Display *) NULL)
8912 display=XOpenDisplay((char *) NULL);
8913 if (display == (Display *) NULL)
8914 {
8915 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8916 return(MagickFalse);
8917 }
8918 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8919 remote_window=(Window) NULL;
8920 root_window=XRootWindow(display,XDefaultScreen(display));
8921 if (window != (char *) NULL)
8922 {
8923 /*
8924 Search window hierarchy and identify any clients by name or ID.
8925 */
8926 if (isdigit((unsigned char) *window) != 0)
8927 remote_window=XWindowByID(display,root_window,(Window)
8928 strtol((char *) window,(char **) NULL,0));
8929 if (remote_window == (Window) NULL)
8930 remote_window=XWindowByName(display,root_window,window);
8931 }
8932 if (remote_window == (Window) NULL)
8933 remote_window=XWindowByProperty(display,root_window,remote_atom);
8934 if (remote_window == (Window) NULL)
8935 {
8936 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8937 filename);
8938 return(MagickFalse);
8939 }
8940 /*
8941 Send remote command.
8942 */
8943 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8944 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8945 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8946 (void) XSync(display,MagickFalse);
8947 return(MagickTrue);
8948}
8949
8950/*
8951%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8952% %
8953% %
8954% %
cristy534d0a32013-04-13 16:27:24 +00008955% X R e n d e r I m a g e %
8956% %
8957% %
8958% %
8959%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8960%
8961% XRenderImage() renders text on the image with an X11 font. It also returns
8962% the bounding box of the text relative to the image.
8963%
8964% The format of the XRenderImage method is:
8965%
8966% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
8967% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
8968%
8969% A description of each parameter follows:
8970%
8971% o image: the image.
8972%
8973% o draw_info: the draw info.
8974%
8975% o offset: (x,y) location of text relative to image.
8976%
8977% o metrics: bounding box of text.
8978%
8979% o exception: return any errors or warnings in this structure.
8980%
8981*/
8982MagickPrivate MagickBooleanType XRenderImage(Image *image,
8983 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
8984 ExceptionInfo *exception)
8985{
8986 const char
8987 *client_name;
8988
8989 DrawInfo
8990 cache_info;
8991
8992 Display
8993 *display;
8994
8995 ImageInfo
8996 *image_info;
8997
8998 MagickBooleanType
8999 status;
9000
9001 size_t
9002 height,
9003 width;
9004
9005 XAnnotateInfo
9006 annotate_info;
9007
9008 XFontStruct
9009 *font_info;
9010
9011 XPixelInfo
9012 pixel;
9013
9014 XResourceInfo
9015 resource_info;
9016
9017 XrmDatabase
9018 resource_database;
9019
9020 XStandardColormap
9021 *map_info;
9022
9023 XVisualInfo
9024 *visual_info;
9025
9026 /*
9027 Open X server connection.
9028 */
9029 display=XOpenDisplay(draw_info->server_name);
9030 if (display == (Display *) NULL)
9031 {
9032 ThrowXWindowException(XServerError,"UnableToOpenXServer",
9033 draw_info->server_name);
9034 return(MagickFalse);
9035 }
9036 /*
9037 Get user defaults from X resource database.
9038 */
9039 (void) XSetErrorHandler(XError);
9040 image_info=AcquireImageInfo();
9041 client_name=GetClientName();
9042 resource_database=XGetResourceDatabase(display,client_name);
9043 XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
9044 resource_info.close_server=MagickFalse;
9045 resource_info.colormap=PrivateColormap;
9046 resource_info.font=AcquireString(draw_info->font);
9047 resource_info.background_color=AcquireString("#ffffffffffff");
9048 resource_info.foreground_color=AcquireString("#000000000000");
9049 map_info=XAllocStandardColormap();
9050 if (map_info == (XStandardColormap *) NULL)
9051 {
9052 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9053 image->filename);
9054 return(MagickFalse);
9055 }
9056 /*
9057 Initialize visual info.
9058 */
9059 visual_info=XBestVisualInfo(display,map_info,&resource_info);
9060 if (visual_info == (XVisualInfo *) NULL)
9061 {
9062 ThrowXWindowException(XServerError,"UnableToGetVisual",
9063 image->filename);
9064 return(MagickFalse);
9065 }
9066 map_info->colormap=(Colormap) NULL;
9067 pixel.pixels=(unsigned long *) NULL;
9068 /*
9069 Initialize Standard Colormap info.
9070 */
9071 XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
9072 map_info);
9073 XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
9074 &pixel);
9075 pixel.annotate_context=XDefaultGC(display,visual_info->screen);
9076 /*
9077 Initialize font info.
9078 */
9079 font_info=XBestFont(display,&resource_info,MagickFalse);
9080 if (font_info == (XFontStruct *) NULL)
9081 {
9082 ThrowXWindowException(XServerError,"UnableToLoadFont",draw_info->font);
9083 return(MagickFalse);
9084 }
9085 if ((map_info == (XStandardColormap *) NULL) ||
9086 (visual_info == (XVisualInfo *) NULL) ||
9087 (font_info == (XFontStruct *) NULL))
9088 {
9089 XFreeResources(display,visual_info,map_info,&pixel,font_info,
9090 &resource_info,(XWindowInfo *) NULL);
9091 ThrowXWindowException(XServerError,"UnableToLoadFont",image->filename);
9092 return(MagickFalse);
9093 }
9094 cache_info=(*draw_info);
9095 /*
9096 Initialize annotate info.
9097 */
9098 XGetAnnotateInfo(&annotate_info);
9099 annotate_info.stencil=ForegroundStencil;
9100 if (cache_info.font != draw_info->font)
9101 {
9102 /*
9103 Type name has changed.
9104 */
9105 (void) XFreeFont(display,font_info);
9106 (void) CloneString(&resource_info.font,draw_info->font);
9107 font_info=XBestFont(display,&resource_info,MagickFalse);
9108 if (font_info == (XFontStruct *) NULL)
9109 {
9110 ThrowXWindowException(XServerError,"UnableToLoadFont",
9111 draw_info->font);
9112 return(MagickFalse);
9113 }
9114 }
9115 if (image->debug != MagickFalse)
9116 (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
9117 "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
9118 draw_info->font : "none",draw_info->pointsize);
9119 cache_info=(*draw_info);
9120 annotate_info.font_info=font_info;
9121 annotate_info.text=(char *) draw_info->text;
9122 annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
9123 strlen(draw_info->text));
9124 annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
9125 metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
9126 metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
9127 metrics->ascent=(double) font_info->ascent+4;
9128 metrics->descent=(double) (-font_info->descent);
9129 metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
9130 metrics->height=font_info->ascent+font_info->descent;
9131 metrics->max_advance=(double) font_info->max_bounds.width;
9132 metrics->bounds.x1=0.0;
9133 metrics->bounds.y1=metrics->descent;
9134 metrics->bounds.x2=metrics->ascent+metrics->descent;
9135 metrics->bounds.y2=metrics->ascent+metrics->descent;
9136 metrics->underline_position=(-2.0);
9137 metrics->underline_thickness=1.0;
9138 if (draw_info->render == MagickFalse)
9139 return(MagickTrue);
9140 if (draw_info->fill.alpha == TransparentAlpha)
9141 return(MagickTrue);
9142 /*
9143 Render fill color.
9144 */
9145 width=annotate_info.width;
9146 height=annotate_info.height;
9147 if ((fabs(draw_info->affine.rx) >= MagickEpsilon) ||
9148 (fabs(draw_info->affine.ry) >= MagickEpsilon))
9149 {
9150 if ((fabs(draw_info->affine.sx-draw_info->affine.sy) < MagickEpsilon) &&
9151 (fabs(draw_info->affine.rx+draw_info->affine.ry) < MagickEpsilon))
9152 annotate_info.degrees=(double) (180.0/MagickPI)*
9153 atan2(draw_info->affine.rx,draw_info->affine.sx);
9154 }
9155 (void) FormatLocaleString(annotate_info.geometry,MaxTextExtent,
9156 "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
9157 ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
9158 draw_info->interline_spacing-0.5));
9159 pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
9160 pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
9161 pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);
9162 status=XAnnotateImage(display,&pixel,&annotate_info,image,exception);
9163 if (status == 0)
9164 {
9165 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9166 image->filename);
9167 return(MagickFalse);
9168 }
9169 return(MagickTrue);
9170}
9171
9172/*
9173%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9174% %
9175% %
9176% %
cristy3ed852e2009-09-05 21:47:34 +00009177% X R e t a i n W i n d o w C o l o r s %
9178% %
9179% %
9180% %
9181%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9182%
9183% XRetainWindowColors() sets X11 color resources on a window. This preserves
9184% the colors associated with an image displayed on the window.
9185%
9186% The format of the XRetainWindowColors method is:
9187%
9188% void XRetainWindowColors(Display *display,const Window window)
9189%
9190% A description of each parameter follows:
9191%
9192% o display: Specifies a connection to an X server; returned from
9193% XOpenDisplay.
9194%
9195% o window: Specifies a pointer to a XWindowInfo structure.
9196%
9197*/
9198MagickExport void XRetainWindowColors(Display *display,const Window window)
9199{
9200 Atom
9201 property;
9202
9203 Pixmap
9204 pixmap;
9205
9206 /*
9207 Put property on the window.
9208 */
9209 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9210 assert(display != (Display *) NULL);
9211 assert(window != (Window) NULL);
9212 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9213 if (property == (Atom) NULL)
9214 {
9215 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9216 "_XSETROOT_ID");
9217 return;
9218 }
9219 pixmap=XCreatePixmap(display,window,1,1,1);
9220 if (pixmap == (Pixmap) NULL)
9221 {
9222 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9223 return;
9224 }
9225 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9226 (unsigned char *) &pixmap,1);
9227 (void) XSetCloseDownMode(display,RetainPermanent);
9228}
9229
9230/*
9231%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9232% %
9233% %
9234% %
9235% X S e l e c t W i n d o w %
9236% %
9237% %
9238% %
9239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9240%
9241% XSelectWindow() allows a user to select a window using the mouse. If the
9242% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9243% is returned in the crop_info structure.
9244%
9245% The format of the XSelectWindow function is:
9246%
9247% target_window=XSelectWindow(display,crop_info)
9248%
9249% A description of each parameter follows:
9250%
9251% o window: XSelectWindow returns the window id.
9252%
9253% o display: Specifies a pointer to the Display structure; returned from
9254% XOpenDisplay.
9255%
9256% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9257% contains the extents of any cropping rectangle.
9258%
cristy3ed852e2009-09-05 21:47:34 +00009259*/
9260static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9261{
9262#define MinimumCropArea (unsigned int) 9
9263
9264 Cursor
9265 target_cursor;
9266
9267 GC
9268 annotate_context;
9269
9270 int
9271 presses,
9272 x_offset,
9273 y_offset;
9274
9275 Status
9276 status;
9277
9278 Window
9279 root_window,
9280 target_window;
9281
9282 XEvent
9283 event;
9284
9285 XGCValues
9286 context_values;
9287
9288 /*
9289 Initialize graphic context.
9290 */
9291 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9292 assert(display != (Display *) NULL);
9293 assert(crop_info != (RectangleInfo *) NULL);
9294 root_window=XRootWindow(display,XDefaultScreen(display));
9295 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9296 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9297 context_values.function=GXinvert;
9298 context_values.plane_mask=
9299 context_values.background ^ context_values.foreground;
9300 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009301 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009302 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9303 if (annotate_context == (GC) NULL)
9304 return(MagickFalse);
9305 /*
9306 Grab the pointer using target cursor.
9307 */
9308 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9309 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9310 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9311 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9312 GrabModeAsync,root_window,target_cursor,CurrentTime);
9313 if (status != GrabSuccess)
9314 {
9315 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9316 return((Window) NULL);
9317 }
9318 /*
9319 Select a window.
9320 */
9321 crop_info->width=0;
9322 crop_info->height=0;
9323 presses=0;
9324 target_window=(Window) NULL;
9325 x_offset=0;
9326 y_offset=0;
9327 do
9328 {
9329 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9330 (void) XDrawRectangle(display,root_window,annotate_context,
9331 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9332 (unsigned int) crop_info->height-1);
9333 /*
9334 Allow another event.
9335 */
9336 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9337 (void) XWindowEvent(display,root_window,ButtonPressMask |
9338 ButtonReleaseMask | ButtonMotionMask,&event);
9339 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9340 (void) XDrawRectangle(display,root_window,annotate_context,
9341 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9342 (unsigned int) crop_info->height-1);
9343 switch (event.type)
9344 {
9345 case ButtonPress:
9346 {
9347 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9348 event.xbutton.x,event.xbutton.y);
9349 if (target_window == (Window) NULL)
9350 target_window=root_window;
9351 x_offset=event.xbutton.x_root;
9352 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009353 crop_info->x=(ssize_t) x_offset;
9354 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009355 crop_info->width=0;
9356 crop_info->height=0;
9357 presses++;
9358 break;
9359 }
9360 case ButtonRelease:
9361 {
9362 presses--;
9363 break;
9364 }
9365 case MotionNotify:
9366 {
9367 /*
9368 Discard pending button motion events.
9369 */
9370 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009371 crop_info->x=(ssize_t) event.xmotion.x;
9372 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009373 /*
9374 Check boundary conditions.
9375 */
9376 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009377 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009378 else
9379 {
cristyecd0ab52010-05-30 14:59:20 +00009380 crop_info->width=(size_t) (crop_info->x-x_offset);
9381 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009382 }
9383 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009384 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009385 else
9386 {
cristyecd0ab52010-05-30 14:59:20 +00009387 crop_info->height=(size_t) (crop_info->y-y_offset);
9388 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009389 }
9390 }
9391 default:
9392 break;
9393 }
9394 } while ((target_window == (Window) NULL) || (presses > 0));
9395 (void) XUngrabPointer(display,CurrentTime);
9396 (void) XFreeCursor(display,target_cursor);
9397 (void) XFreeGC(display,annotate_context);
9398 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9399 {
9400 crop_info->width=0;
9401 crop_info->height=0;
9402 }
9403 if ((crop_info->width != 0) && (crop_info->height != 0))
9404 target_window=root_window;
9405 return(target_window);
9406}
9407
9408/*
9409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9410% %
9411% %
9412% %
9413% X S e t C u r s o r S t a t e %
9414% %
9415% %
9416% %
9417%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9418%
9419% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9420% reset to their default.
9421%
9422% The format of the XXSetCursorState method is:
9423%
9424% XSetCursorState(display,windows,const MagickStatusType state)
9425%
9426% A description of each parameter follows:
9427%
9428% o display: Specifies a connection to an X server; returned from
9429% XOpenDisplay.
9430%
9431% o windows: Specifies a pointer to a XWindows structure.
9432%
9433% o state: An unsigned integer greater than 0 sets the cursor state
9434% to busy, otherwise the cursor are reset to their default.
9435%
9436*/
cristybcbda3f2011-09-03 13:01:22 +00009437MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009438 const MagickStatusType state)
9439{
9440 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9441 assert(display != (Display *) NULL);
9442 assert(windows != (XWindows *) NULL);
9443 if (state)
9444 {
9445 (void) XCheckDefineCursor(display,windows->image.id,
9446 windows->image.busy_cursor);
9447 (void) XCheckDefineCursor(display,windows->pan.id,
9448 windows->pan.busy_cursor);
9449 (void) XCheckDefineCursor(display,windows->magnify.id,
9450 windows->magnify.busy_cursor);
9451 (void) XCheckDefineCursor(display,windows->command.id,
9452 windows->command.busy_cursor);
9453 }
9454 else
9455 {
9456 (void) XCheckDefineCursor(display,windows->image.id,
9457 windows->image.cursor);
9458 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9459 (void) XCheckDefineCursor(display,windows->magnify.id,
9460 windows->magnify.cursor);
9461 (void) XCheckDefineCursor(display,windows->command.id,
9462 windows->command.cursor);
9463 (void) XCheckDefineCursor(display,windows->command.id,
9464 windows->widget.cursor);
9465 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9466 }
9467 windows->info.mapped=MagickFalse;
9468}
9469
9470/*
9471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9472% %
9473% %
9474% %
9475% X S e t W i n d o w s %
9476% %
9477% %
9478% %
9479%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9480%
9481% XSetWindows() sets the X windows structure if the windows info is specified.
9482% Otherwise the current windows structure is returned.
9483%
9484% The format of the XSetWindows method is:
9485%
9486% XWindows *XSetWindows(XWindows *windows_info)
9487%
9488% A description of each parameter follows:
9489%
9490% o windows_info: Initialize the Windows structure with this information.
9491%
9492*/
cristybcbda3f2011-09-03 13:01:22 +00009493MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009494{
9495 static XWindows
9496 *windows = (XWindows *) NULL;
9497
9498 if (windows_info != (XWindows *) ~0)
9499 {
9500 windows=(XWindows *) RelinquishMagickMemory(windows);
9501 windows=windows_info;
9502 }
9503 return(windows);
9504}
9505/*
9506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9507% %
9508% %
9509% %
9510% X U s e r P r e f e r e n c e s %
9511% %
9512% %
9513% %
9514%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9515%
9516% XUserPreferences() saves the preferences in a configuration file in the
9517% users' home directory.
9518%
9519% The format of the XUserPreferences method is:
9520%
9521% void XUserPreferences(XResourceInfo *resource_info)
9522%
9523% A description of each parameter follows:
9524%
9525% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9526%
9527*/
cristybcbda3f2011-09-03 13:01:22 +00009528MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009529{
9530#if defined(X11_PREFERENCES_PATH)
9531 char
9532 cache[MaxTextExtent],
9533 filename[MaxTextExtent],
9534 specifier[MaxTextExtent];
9535
9536 const char
cristy104cea82009-10-25 02:26:51 +00009537 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009538 *value;
9539
9540 XrmDatabase
9541 preferences_database;
9542
9543 /*
9544 Save user preferences to the client configuration file.
9545 */
9546 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009547 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009548 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009549 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009550 value=resource_info->backdrop ? "True" : "False";
9551 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009552 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009553 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9554 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009555 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009556 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009557 value=resource_info->confirm_exit ? "True" : "False";
9558 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009559 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009560 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009561 value=resource_info->confirm_edit ? "True" : "False";
9562 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009563 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009564 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009565 value=resource_info->display_warnings ? "True" : "False";
9566 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009567 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristycbda6112012-05-27 20:57:16 +00009568 value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9569 "True" : "False";
cristy3ed852e2009-09-05 21:47:34 +00009570 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009571 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009572 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009573 value=resource_info->gamma_correct ? "True" : "False";
9574 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009575 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9576 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009577 resource_info->undo_cache);
9578 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009579 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009580 value=resource_info->use_pixmap ? "True" : "False";
9581 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009582 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009583 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009584 ExpandFilename(filename);
9585 XrmPutFileDatabase(preferences_database,filename);
9586#endif
9587}
9588
9589/*
9590%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9591% %
9592% %
9593% %
9594% X V i s u a l C l a s s N a m e %
9595% %
9596% %
9597% %
9598%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9599%
9600% XVisualClassName() returns the visual class name as a character string.
9601%
9602% The format of the XVisualClassName method is:
9603%
9604% char *XVisualClassName(const int visual_class)
9605%
9606% A description of each parameter follows:
9607%
9608% o visual_type: XVisualClassName returns the visual class as a character
9609% string.
9610%
9611% o class: Specifies the visual class.
9612%
cristy3ed852e2009-09-05 21:47:34 +00009613*/
9614static const char *XVisualClassName(const int visual_class)
9615{
9616 switch (visual_class)
9617 {
9618 case StaticGray: return("StaticGray");
9619 case GrayScale: return("GrayScale");
9620 case StaticColor: return("StaticColor");
9621 case PseudoColor: return("PseudoColor");
9622 case TrueColor: return("TrueColor");
9623 case DirectColor: return("DirectColor");
9624 }
9625 return("unknown visual class");
9626}
9627
9628/*
9629%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9630% %
9631% %
9632% %
9633% X W a r n i n g %
9634% %
9635% %
9636% %
9637%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9638%
9639% XWarning() displays a warning reason in a Notice widget.
9640%
9641% The format of the XWarning method is:
9642%
9643% void XWarning(const unsigned int warning,const char *reason,
9644% const char *description)
9645%
9646% A description of each parameter follows:
9647%
9648% o warning: Specifies the numeric warning category.
9649%
9650% o reason: Specifies the reason to display before terminating the
9651% program.
9652%
9653% o description: Specifies any description to the reason.
9654%
9655*/
cristybcbda3f2011-09-03 13:01:22 +00009656MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009657 const char *reason,const char *description)
9658{
9659 char
9660 text[MaxTextExtent];
9661
9662 XWindows
9663 *windows;
9664
9665 if (reason == (char *) NULL)
9666 return;
9667 (void) CopyMagickString(text,reason,MaxTextExtent);
9668 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9669 windows=XSetWindows((XWindows *) ~0);
9670 XNoticeWidget(windows->display,windows,text,(char *) description);
9671}
9672
9673/*
9674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9675% %
9676% %
9677% %
9678% X W i n d o w B y I D %
9679% %
9680% %
9681% %
9682%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9683%
9684% XWindowByID() locates a child window with a given ID. If not window with
9685% the given name is found, 0 is returned. Only the window specified and its
9686% subwindows are searched.
9687%
9688% The format of the XWindowByID function is:
9689%
9690% child=XWindowByID(display,window,id)
9691%
9692% A description of each parameter follows:
9693%
9694% o child: XWindowByID returns the window with the specified
9695% id. If no windows are found, XWindowByID returns 0.
9696%
9697% o display: Specifies a pointer to the Display structure; returned from
9698% XOpenDisplay.
9699%
9700% o id: Specifies the id of the window to locate.
9701%
9702*/
cristybcbda3f2011-09-03 13:01:22 +00009703MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009704 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009705{
9706 RectangleInfo
9707 rectangle_info;
9708
9709 register int
9710 i;
9711
9712 Status
9713 status;
9714
9715 unsigned int
9716 number_children;
9717
9718 Window
9719 child,
9720 *children,
9721 window;
9722
9723 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9724 assert(display != (Display *) NULL);
9725 assert(root_window != (Window) NULL);
9726 if (id == 0)
9727 return(XSelectWindow(display,&rectangle_info));
9728 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009729 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009730 status=XQueryTree(display,root_window,&child,&child,&children,
9731 &number_children);
9732 if (status == False)
9733 return((Window) NULL);
9734 window=(Window) NULL;
9735 for (i=0; i < (int) number_children; i++)
9736 {
9737 /*
9738 Search each child and their children.
9739 */
9740 window=XWindowByID(display,children[i],id);
9741 if (window != (Window) NULL)
9742 break;
9743 }
9744 if (children != (Window *) NULL)
9745 (void) XFree((void *) children);
9746 return(window);
9747}
9748
9749/*
9750%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9751% %
9752% %
9753% %
9754% X W i n d o w B y N a m e %
9755% %
9756% %
9757% %
9758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9759%
9760% XWindowByName() locates a window with a given name on a display. If no
9761% window with the given name is found, 0 is returned. If more than one window
9762% has the given name, the first one is returned. Only root and its children
9763% are searched.
9764%
9765% The format of the XWindowByName function is:
9766%
9767% window=XWindowByName(display,root_window,name)
9768%
9769% A description of each parameter follows:
9770%
9771% o window: XWindowByName returns the window id.
9772%
9773% o display: Specifies a pointer to the Display structure; returned from
9774% XOpenDisplay.
9775%
9776% o root_window: Specifies the id of the root window.
9777%
9778% o name: Specifies the name of the window to locate.
9779%
9780*/
cristybcbda3f2011-09-03 13:01:22 +00009781MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009782 const char *name)
9783{
9784 register int
9785 i;
9786
9787 Status
9788 status;
9789
9790 unsigned int
9791 number_children;
9792
9793 Window
9794 *children,
9795 child,
9796 window;
9797
9798 XTextProperty
9799 window_name;
9800
9801 assert(display != (Display *) NULL);
9802 assert(root_window != (Window) NULL);
9803 assert(name != (char *) NULL);
9804 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9805 if (XGetWMName(display,root_window,&window_name) != 0)
9806 if (LocaleCompare((char *) window_name.value,name) == 0)
9807 return(root_window);
9808 status=XQueryTree(display,root_window,&child,&child,&children,
9809 &number_children);
9810 if (status == False)
9811 return((Window) NULL);
9812 window=(Window) NULL;
9813 for (i=0; i < (int) number_children; i++)
9814 {
9815 /*
9816 Search each child and their children.
9817 */
9818 window=XWindowByName(display,children[i],name);
9819 if (window != (Window) NULL)
9820 break;
9821 }
9822 if (children != (Window *) NULL)
9823 (void) XFree((void *) children);
9824 return(window);
9825}
9826
9827/*
9828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9829% %
9830% %
9831% %
9832% X W i n d o w B y P r o p e r y %
9833% %
9834% %
9835% %
9836%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9837%
9838% XWindowByProperty() locates a child window with a given property. If not
9839% window with the given name is found, 0 is returned. If more than one window
9840% has the given property, the first one is returned. Only the window
9841% specified and its subwindows are searched.
9842%
9843% The format of the XWindowByProperty function is:
9844%
9845% child=XWindowByProperty(display,window,property)
9846%
9847% A description of each parameter follows:
9848%
9849% o child: XWindowByProperty returns the window id with the specified
9850% property. If no windows are found, XWindowByProperty returns 0.
9851%
9852% o display: Specifies a pointer to the Display structure; returned from
9853% XOpenDisplay.
9854%
9855% o property: Specifies the property of the window to locate.
9856%
9857*/
cristybcbda3f2011-09-03 13:01:22 +00009858MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009859 const Atom property)
9860{
9861 Atom
9862 type;
9863
9864 int
9865 format;
9866
9867 Status
9868 status;
9869
9870 unsigned char
9871 *data;
9872
9873 unsigned int
9874 i,
9875 number_children;
9876
cristyf2faecf2010-05-28 19:19:36 +00009877 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009878 after,
9879 number_items;
9880
9881 Window
9882 child,
9883 *children,
9884 parent,
9885 root;
9886
9887 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9888 assert(display != (Display *) NULL);
9889 assert(window != (Window) NULL);
9890 assert(property != (Atom) NULL);
9891 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9892 if (status == False)
9893 return((Window) NULL);
9894 type=(Atom) NULL;
9895 child=(Window) NULL;
9896 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9897 {
9898 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9899 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9900 if (data != NULL)
9901 (void) XFree((void *) data);
9902 if ((status == Success) && (type != (Atom) NULL))
9903 child=children[i];
9904 }
9905 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9906 child=XWindowByProperty(display,children[i],property);
9907 if (children != (Window *) NULL)
9908 (void) XFree((void *) children);
9909 return(child);
9910}
9911#else
9912
9913/*
9914%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9915% %
9916% %
9917% %
9918% X I m p o r t I m a g e %
9919% %
9920% %
9921% %
9922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9923%
9924% XImportImage() reads an image from an X window.
9925%
9926% The format of the XImportImage method is:
9927%
cristya0dc96a2011-12-19 23:58:54 +00009928% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9929% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009930%
9931% A description of each parameter follows:
9932%
9933% o image_info: the image info..
9934%
9935% o ximage_info: Specifies a pointer to an XImportInfo structure.
9936%
cristya0dc96a2011-12-19 23:58:54 +00009937% o exception: return any errors or warnings in this structure.
9938%
cristy3ed852e2009-09-05 21:47:34 +00009939*/
cristy4bc52022012-12-13 14:15:41 +00009940MagickExport Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009941 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009942{
9943 assert(image_info != (const ImageInfo *) NULL);
9944 assert(image_info->signature == MagickSignature);
9945 if (image_info->debug != MagickFalse)
9946 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9947 image_info->filename);
9948 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009949 assert(exception != (ExceptionInfo *) NULL);
9950 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009951 return((Image *) NULL);
9952}
cristy534d0a32013-04-13 16:27:24 +00009953
9954/*
9955%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9956% %
9957% %
9958% %
9959% X R e n d e r X 1 1 %
9960% %
9961% %
9962% %
9963%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9964%
9965% XRenderImage() renders text on the image with an X11 font. It also returns
9966% the bounding box of the text relative to the image.
9967%
9968% The format of the XRenderImage method is:
9969%
9970% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
9971% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
9972%
9973% A description of each parameter follows:
9974%
9975% o image: the image.
9976%
9977% o draw_info: the draw info.
9978%
9979% o offset: (x,y) location of text relative to image.
9980%
9981% o metrics: bounding box of text.
9982%
9983% o exception: return any errors or warnings in this structure.
9984%
9985*/
9986MagickPrivate MagickBooleanType XRenderImage(Image *image,
9987 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
9988 ExceptionInfo *exception)
9989{
9990 (void) draw_info;
9991 (void) offset;
9992 (void) metrics;
9993 (void) ThrowMagickException(exception,GetMagickModule(),
9994 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","'%s' (X11)",
9995 image->filename);
9996 return(MagickFalse);
9997}
cristy3ed852e2009-09-05 21:47:34 +00009998#endif
9999
10000/*
10001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10002% %
10003% %
10004% %
cristy576974e2009-10-25 20:45:31 +000010005+ X C o m p o n e n t G e n e s i s %
10006% %
10007% %
10008% %
10009%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10010%
10011% XComponentGenesis() instantiates the X component.
10012%
10013% The format of the XComponentGenesis method is:
10014%
10015% MagickBooleanType XComponentGenesis(void)
10016%
10017*/
cristy5ff4eaf2011-09-03 01:38:02 +000010018MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +000010019{
10020 return(MagickTrue);
10021}
10022
10023/*
10024%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10025% %
10026% %
10027% %
cristy3ed852e2009-09-05 21:47:34 +000010028% X G e t I m p o r t I n f o %
10029% %
10030% %
10031% %
10032%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10033%
10034% XGetImportInfo() initializes the XImportInfo structure.
10035%
10036% The format of the XGetImportInfo method is:
10037%
10038% void XGetImportInfo(XImportInfo *ximage_info)
10039%
10040% A description of each parameter follows:
10041%
10042% o ximage_info: Specifies a pointer to an ImageInfo structure.
10043%
10044*/
10045MagickExport void XGetImportInfo(XImportInfo *ximage_info)
10046{
10047 assert(ximage_info != (XImportInfo *) NULL);
10048 ximage_info->frame=MagickFalse;
10049 ximage_info->borders=MagickFalse;
10050 ximage_info->screen=MagickFalse;
10051 ximage_info->descend=MagickTrue;
10052 ximage_info->silent=MagickFalse;
10053}