blob: 8f2574284e8366733cde8a7a5459721153684fcc [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% X X W W IIIII N N DDDD OOO W W %
7% X X W W I NN N D D O O W W %
8% X W W I N N N D D O O W W %
9% X X W W W I N NN D D O O W W W %
10% X X W W IIIII N N DDDD OOO W W %
11% %
12% %
13% MagickCore X11 Utility Methods %
14% %
15% Software Design %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 1992 %
18% %
19% %
cristyb56bb242014-11-25 17:12:48 +000020% Copyright 1999-2015 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"
cristy4c08aed2011-07-01 19:47:50 +000070#include "MagickCore/quantize.h"
71#include "MagickCore/quantum.h"
72#include "MagickCore/quantum-private.h"
73#include "MagickCore/resource_.h"
74#include "MagickCore/resize.h"
cristy4c08aed2011-07-01 19:47:50 +000075#include "MagickCore/statistic.h"
76#include "MagickCore/string_.h"
77#include "MagickCore/string-private.h"
78#include "MagickCore/transform.h"
cristy63a81872012-03-22 15:52:52 +000079#include "MagickCore/token.h"
cristy4c08aed2011-07-01 19:47:50 +000080#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000081#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000082#include "MagickCore/widget.h"
cristybcbda3f2011-09-03 13:01:22 +000083#include "MagickCore/widget-private.h"
cristy4c08aed2011-07-01 19:47:50 +000084#include "MagickCore/xwindow.h"
85#include "MagickCore/xwindow-private.h"
86#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000087#if defined(__BEOS__)
88#include <OS.h>
89#endif
90#if defined(MAGICKCORE_X11_DELEGATE)
91#include <X11/Xproto.h>
92#include <X11/Xlocale.h>
93#if defined(MAGICK_HAVE_POLL)
94# include <sys/poll.h>
95#endif
96#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
97#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
98# include <machine/param.h>
99#endif
100#include <sys/ipc.h>
101#include <sys/shm.h>
102#include <X11/extensions/XShm.h>
103#endif
104#if defined(MAGICKCORE_HAVE_SHAPE)
105#include <X11/extensions/shape.h>
106#endif
107
108/*
109 X defines.
110*/
cristyce70c172010-01-07 17:15:30 +0000111#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000112 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
113 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000114#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000115 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
116 map->red_mult)+ \
117 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
118 map->green_mult)+ \
119 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
120 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000121#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
122 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
123 map->red_mult)+ \
124 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
125 map->green_mult)+ \
126 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
127 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000128#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000129 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
130 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000131#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000132 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
133 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000134#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000135 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
136 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
137 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000138
139#define AccentuateModulate ScaleCharToQuantum(80)
140#define HighlightModulate ScaleCharToQuantum(125)
141#define ShadowModulate ScaleCharToQuantum(135)
142#define DepthModulate ScaleCharToQuantum(185)
143#define TroughModulate ScaleCharToQuantum(110)
144
145#define XLIB_ILLEGAL_ACCESS 1
146#undef ForgetGravity
147#undef NorthWestGravity
148#undef NorthGravity
149#undef NorthEastGravity
150#undef WestGravity
151#undef CenterGravity
152#undef EastGravity
153#undef SouthWestGravity
154#undef SouthGravity
155#undef SouthEastGravity
156#undef StaticGravity
157
158#undef index
159#if defined(hpux9)
160#define XFD_SET int
161#else
162#define XFD_SET fd_set
163#endif
164
165/*
166 Enumeration declarations.
167*/
168typedef enum
169{
170#undef DoRed
171 DoRed = 0x0001,
172#undef DoGreen
173 DoGreen = 0x0002,
174#undef DoBlue
175 DoBlue = 0x0004,
176 DoMatte = 0x0008
177} XColorFlags;
178
179/*
180 Typedef declarations.
181*/
182typedef struct _DiversityPacket
183{
184 Quantum
185 red,
186 green,
187 blue;
188
189 unsigned short
190 index;
191
cristybb503372010-05-27 20:51:26 +0000192 size_t
cristy3ed852e2009-09-05 21:47:34 +0000193 count;
194} DiversityPacket;
195
196/*
197 Constant declaractions.
198*/
199static MagickBooleanType
200 xerror_alert = MagickFalse;
201
202/*
203 Method prototypes.
204*/
205static const char
206 *XVisualClassName(const int);
207
cristya19f1d72012-08-07 18:24:38 +0000208static double
cristy3ed852e2009-09-05 21:47:34 +0000209 blue_gamma = 1.0,
210 green_gamma = 1.0,
211 red_gamma = 1.0;
212
213static MagickBooleanType
214 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
215
216static void
217 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000218 XImage *,XImage *,ExceptionInfo *),
cristy3ed852e2009-09-05 21:47:34 +0000219 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000220 XImage *,XImage *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +0000221
222static Window
223 XSelectWindow(Display *,RectangleInfo *);
224
225/*
226%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227% %
228% %
229% %
230% D e s t r o y X R e s o u r c e s %
231% %
232% %
233% %
234%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235%
236% DestroyXResources() destroys any X resources.
237%
238% The format of the DestroyXResources method is:
239%
240% void DestroyXResources()
241%
242% A description of each parameter follows:
243%
244*/
245MagickExport void DestroyXResources(void)
246{
247 register int
248 i;
249
250 unsigned int
251 number_windows;
252
253 XWindowInfo
254 *magick_windows[MaxXWindows];
255
256 XWindows
257 *windows;
258
259 DestroyXWidget();
260 windows=XSetWindows((XWindows *) ~0);
261 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
262 return;
263 number_windows=0;
264 magick_windows[number_windows++]=(&windows->context);
265 magick_windows[number_windows++]=(&windows->group_leader);
266 magick_windows[number_windows++]=(&windows->backdrop);
267 magick_windows[number_windows++]=(&windows->icon);
268 magick_windows[number_windows++]=(&windows->image);
269 magick_windows[number_windows++]=(&windows->info);
270 magick_windows[number_windows++]=(&windows->magnify);
271 magick_windows[number_windows++]=(&windows->pan);
272 magick_windows[number_windows++]=(&windows->command);
273 magick_windows[number_windows++]=(&windows->widget);
274 magick_windows[number_windows++]=(&windows->popup);
275 magick_windows[number_windows++]=(&windows->context);
276 for (i=0; i < (int) number_windows; i++)
277 {
278 if (magick_windows[i]->mapped != MagickFalse)
279 {
280 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
281 magick_windows[i]->screen);
282 magick_windows[i]->mapped=MagickFalse;
283 }
284 if (magick_windows[i]->name != (char *) NULL)
285 magick_windows[i]->name=(char *)
286 RelinquishMagickMemory(magick_windows[i]->name);
287 if (magick_windows[i]->icon_name != (char *) NULL)
288 magick_windows[i]->icon_name=(char *)
289 RelinquishMagickMemory(magick_windows[i]->icon_name);
290 if (magick_windows[i]->cursor != (Cursor) NULL)
291 {
292 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
293 magick_windows[i]->cursor=(Cursor) NULL;
294 }
295 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
296 {
297 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
298 magick_windows[i]->busy_cursor=(Cursor) NULL;
299 }
300 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
301 {
302 (void) XFreePixmap(windows->display,
303 magick_windows[i]->highlight_stipple);
304 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
305 }
306 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
307 {
308 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
309 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
310 }
311 if (magick_windows[i]->ximage != (XImage *) NULL)
312 {
313 XDestroyImage(magick_windows[i]->ximage);
314 magick_windows[i]->ximage=(XImage *) NULL;
315 }
316 if (magick_windows[i]->pixmap != (Pixmap) NULL)
317 {
318 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
319 magick_windows[i]->pixmap=(Pixmap) NULL;
320 }
321 if (magick_windows[i]->id != (Window) NULL)
322 {
323 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
324 magick_windows[i]->id=(Window) NULL;
325 }
326 if (magick_windows[i]->destroy != MagickFalse)
327 {
328 if (magick_windows[i]->image != (Image *) NULL)
329 {
330 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
331 magick_windows[i]->image=NewImageList();
332 }
333 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
334 {
335 (void) XFreePixmap(windows->display,
336 magick_windows[i]->matte_pixmap);
337 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
338 }
339 }
340 if (magick_windows[i]->segment_info != (void *) NULL)
341 {
342#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
343 XShmSegmentInfo
344 *segment_info;
345
346 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
347 if (segment_info != (XShmSegmentInfo *) NULL)
348 if (segment_info[0].shmid >= 0)
349 {
350 if (segment_info[0].shmaddr != NULL)
351 (void) shmdt(segment_info[0].shmaddr);
352 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
353 segment_info[0].shmaddr=NULL;
354 segment_info[0].shmid=(-1);
355 }
356#endif
357 magick_windows[i]->segment_info=(void *)
358 RelinquishMagickMemory(magick_windows[i]->segment_info);
359 }
360 }
361 windows->icon_resources=(XResourceInfo *)
362 RelinquishMagickMemory(windows->icon_resources);
363 if (windows->icon_pixel != (XPixelInfo *) NULL)
364 {
cristyf2faecf2010-05-28 19:19:36 +0000365 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
366 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000367 RelinquishMagickMemory(windows->icon_pixel->pixels);
368 if (windows->icon_pixel->annotate_context != (GC) NULL)
369 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
370 windows->icon_pixel=(XPixelInfo *)
371 RelinquishMagickMemory(windows->icon_pixel);
372 }
373 if (windows->pixel_info != (XPixelInfo *) NULL)
374 {
cristyf2faecf2010-05-28 19:19:36 +0000375 if (windows->pixel_info->pixels != (unsigned long *) NULL)
376 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000377 RelinquishMagickMemory(windows->pixel_info->pixels);
378 if (windows->pixel_info->annotate_context != (GC) NULL)
379 XFreeGC(windows->display,windows->pixel_info->annotate_context);
380 if (windows->pixel_info->widget_context != (GC) NULL)
381 XFreeGC(windows->display,windows->pixel_info->widget_context);
382 if (windows->pixel_info->highlight_context != (GC) NULL)
383 XFreeGC(windows->display,windows->pixel_info->highlight_context);
384 windows->pixel_info=(XPixelInfo *)
385 RelinquishMagickMemory(windows->pixel_info);
386 }
387 if (windows->font_info != (XFontStruct *) NULL)
388 {
389 XFreeFont(windows->display,windows->font_info);
390 windows->font_info=(XFontStruct *) NULL;
391 }
392 if (windows->class_hints != (XClassHint *) NULL)
393 {
cristyc9cc4a72011-09-18 02:12:41 +0000394 if (windows->class_hints->res_name != (char *) NULL)
395 windows->class_hints->res_name=DestroyString(
396 windows->class_hints->res_name);
397 if (windows->class_hints->res_class != (char *) NULL)
398 windows->class_hints->res_class=DestroyString(
399 windows->class_hints->res_class);
cristy3ed852e2009-09-05 21:47:34 +0000400 XFree(windows->class_hints);
401 windows->class_hints=(XClassHint *) NULL;
402 }
403 if (windows->manager_hints != (XWMHints *) NULL)
404 {
405 XFree(windows->manager_hints);
406 windows->manager_hints=(XWMHints *) NULL;
407 }
408 if (windows->map_info != (XStandardColormap *) NULL)
409 {
410 XFree(windows->map_info);
411 windows->map_info=(XStandardColormap *) NULL;
412 }
413 if (windows->icon_map != (XStandardColormap *) NULL)
414 {
415 XFree(windows->icon_map);
416 windows->icon_map=(XStandardColormap *) NULL;
417 }
418 if (windows->visual_info != (XVisualInfo *) NULL)
419 {
420 XFree(windows->visual_info);
421 windows->visual_info=(XVisualInfo *) NULL;
422 }
423 if (windows->icon_visual != (XVisualInfo *) NULL)
424 {
425 XFree(windows->icon_visual);
426 windows->icon_visual=(XVisualInfo *) NULL;
427 }
428 (void) XSetWindows((XWindows *) NULL);
429}
430
431/*
432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
433% %
434% %
435% %
436% X A n n o t a t e I m a g e %
437% %
438% %
439% %
440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441%
442% XAnnotateImage() annotates the image with text.
443%
444% The format of the XAnnotateImage method is:
445%
446% MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000447% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
448% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000449%
450% A description of each parameter follows:
451%
452% o display: Specifies a connection to an X server; returned from
453% XOpenDisplay.
454%
455% o pixel: Specifies a pointer to a XPixelInfo structure.
456%
457% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
458%
459% o image: the image.
460%
cristy7c3af952011-10-20 16:04:16 +0000461% o exception: return any errors or warnings in this structure.
462%
cristy3ed852e2009-09-05 21:47:34 +0000463*/
cristybcbda3f2011-09-03 13:01:22 +0000464MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000465 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
466 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000467{
cristyc57f6942010-11-12 01:47:39 +0000468 CacheView
469 *annotate_view;
470
cristy3ed852e2009-09-05 21:47:34 +0000471 GC
472 annotate_context;
473
cristy3ed852e2009-09-05 21:47:34 +0000474 Image
475 *annotate_image;
476
477 int
478 x,
479 y;
480
cristyb0a657e2012-08-29 00:45:37 +0000481 PixelTrait
482 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +0000483
484 Pixmap
485 annotate_pixmap;
486
487 unsigned int
488 depth,
489 height,
490 width;
491
492 Window
493 root_window;
494
495 XGCValues
496 context_values;
497
498 XImage
499 *annotate_ximage;
500
501 /*
502 Initialize annotated image.
503 */
504 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
505 assert(display != (Display *) NULL);
506 assert(pixel != (XPixelInfo *) NULL);
507 assert(annotate_info != (XAnnotateInfo *) NULL);
508 assert(image != (Image *) NULL);
509 /*
510 Initialize annotated pixmap.
511 */
512 root_window=XRootWindow(display,XDefaultScreen(display));
513 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
514 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
515 annotate_info->height,depth);
516 if (annotate_pixmap == (Pixmap) NULL)
517 return(MagickFalse);
518 /*
519 Initialize graphics info.
520 */
521 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000522 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000523 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000524 annotate_context=XCreateGC(display,root_window,(unsigned long)
525 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000526 if (annotate_context == (GC) NULL)
527 return(MagickFalse);
528 /*
529 Draw text to pixmap.
530 */
531 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
532 (int) annotate_info->font_info->ascent,annotate_info->text,
533 (int) strlen(annotate_info->text));
534 (void) XFreeGC(display,annotate_context);
535 /*
536 Initialize annotated X image.
537 */
538 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
539 annotate_info->height,AllPlanes,ZPixmap);
540 if (annotate_ximage == (XImage *) NULL)
541 return(MagickFalse);
542 (void) XFreePixmap(display,annotate_pixmap);
543 /*
544 Initialize annotated image.
545 */
cristy6710d842011-10-20 23:23:00 +0000546 annotate_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +0000547 if (annotate_image == (Image *) NULL)
548 return(MagickFalse);
549 annotate_image->columns=annotate_info->width;
550 annotate_image->rows=annotate_info->height;
551 /*
552 Transfer annotated X image to image.
553 */
554 width=(unsigned int) image->columns;
555 height=(unsigned int) image->rows;
556 x=0;
557 y=0;
558 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +0000559 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
560 (ssize_t) y,&annotate_image->background_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000561 if (annotate_info->stencil == ForegroundStencil)
cristy8a46d822012-08-28 23:32:39 +0000562 annotate_image->alpha_trait=BlendPixelTrait;
cristy6f5395d2012-12-14 18:30:30 +0000563 annotate_view=AcquireAuthenticCacheView(annotate_image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000564 for (y=0; y < (int) annotate_image->rows; y++)
565 {
cristyc57f6942010-11-12 01:47:39 +0000566 register int
cristy3ed852e2009-09-05 21:47:34 +0000567 x;
568
cristy4c08aed2011-07-01 19:47:50 +0000569 register Quantum
dirk05d2ff72015-11-18 23:13:43 +0100570 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000571
cristyc57f6942010-11-12 01:47:39 +0000572 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
573 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000574 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000575 break;
cristyc57f6942010-11-12 01:47:39 +0000576 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000577 {
cristy4c08aed2011-07-01 19:47:50 +0000578 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000579 if (XGetPixel(annotate_ximage,x,y) == 0)
580 {
581 /*
582 Set this pixel to the background color.
583 */
cristy4c08aed2011-07-01 19:47:50 +0000584 SetPixelRed(annotate_image,ScaleShortToQuantum(
585 pixel->box_color.red),q);
586 SetPixelGreen(annotate_image,ScaleShortToQuantum(
587 pixel->box_color.green),q);
588 SetPixelBlue(annotate_image,ScaleShortToQuantum(
589 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000590 if ((annotate_info->stencil == ForegroundStencil) ||
591 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000592 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000593 }
594 else
595 {
596 /*
597 Set this pixel to the pen color.
598 */
cristy4c08aed2011-07-01 19:47:50 +0000599 SetPixelRed(annotate_image,ScaleShortToQuantum(
600 pixel->pen_color.red),q);
601 SetPixelGreen(annotate_image,ScaleShortToQuantum(
602 pixel->pen_color.green),q);
603 SetPixelBlue(annotate_image,ScaleShortToQuantum(
604 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000605 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000606 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000607 }
cristyed231572011-07-14 02:18:59 +0000608 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000609 }
cristyc57f6942010-11-12 01:47:39 +0000610 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000611 break;
612 }
cristyc57f6942010-11-12 01:47:39 +0000613 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000614 XDestroyImage(annotate_ximage);
615 /*
616 Determine annotate geometry.
617 */
618 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
619 if ((width != (unsigned int) annotate_image->columns) ||
620 (height != (unsigned int) annotate_image->rows))
621 {
622 char
cristy151b66d2015-04-15 10:50:31 +0000623 image_geometry[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000624
625 /*
626 Scale image.
627 */
cristy151b66d2015-04-15 10:50:31 +0000628 (void) FormatLocaleString(image_geometry,MagickPathExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000629 width,height);
cristye941a752011-10-15 01:52:48 +0000630 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
631 exception);
cristy3ed852e2009-09-05 21:47:34 +0000632 }
633 if (annotate_info->degrees != 0.0)
634 {
635 Image
636 *rotate_image;
637
638 int
639 rotations;
640
cristya19f1d72012-08-07 18:24:38 +0000641 double
cristy3ed852e2009-09-05 21:47:34 +0000642 normalized_degrees;
643
644 /*
645 Rotate image.
646 */
cristy6710d842011-10-20 23:23:00 +0000647 rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +0000648 if (rotate_image == (Image *) NULL)
649 return(MagickFalse);
650 annotate_image=DestroyImage(annotate_image);
651 annotate_image=rotate_image;
652 /*
653 Annotation is relative to the degree of rotation.
654 */
655 normalized_degrees=annotate_info->degrees;
656 while (normalized_degrees < -45.0)
657 normalized_degrees+=360.0;
658 for (rotations=0; normalized_degrees > 45.0; rotations++)
659 normalized_degrees-=90.0;
660 switch (rotations % 4)
661 {
662 default:
663 case 0:
664 break;
665 case 1:
666 {
667 /*
668 Rotate 90 degrees.
669 */
670 x-=(int) annotate_image->columns/2;
671 y+=(int) annotate_image->columns/2;
672 break;
673 }
674 case 2:
675 {
676 /*
677 Rotate 180 degrees.
678 */
679 x=x-(int) annotate_image->columns;
680 break;
681 }
682 case 3:
683 {
684 /*
685 Rotate 270 degrees.
686 */
687 x=x-(int) annotate_image->columns/2;
688 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
689 break;
690 }
691 }
692 }
693 /*
694 Composite text onto the image.
695 */
696 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyb0a657e2012-08-29 00:45:37 +0000697 alpha_trait=image->alpha_trait;
cristyfeb3e962012-03-29 17:25:55 +0000698 (void) CompositeImage(image,annotate_image,
cristy17f11b02014-12-20 19:37:04 +0000699 annotate_image->alpha_trait != UndefinedPixelTrait ? OverCompositeOp :
cristyb0a657e2012-08-29 00:45:37 +0000700 CopyCompositeOp,MagickTrue,(ssize_t) x,(ssize_t) y,exception);
701 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +0000702 annotate_image=DestroyImage(annotate_image);
703 return(MagickTrue);
704}
705
706/*
707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
708% %
709% %
710% %
711% X B e s t F o n t %
712% %
713% %
714% %
715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
716%
717% XBestFont() returns the "best" font. "Best" is defined as a font specified
718% in the X resource database or a font such that the text width displayed
719% with the font does not exceed the specified maximum width.
720%
721% The format of the XBestFont method is:
722%
723% XFontStruct *XBestFont(Display *display,
724% const XResourceInfo *resource_info,const MagickBooleanType text_font)
725%
726% A description of each parameter follows:
727%
728% o font: XBestFont returns a pointer to a XFontStruct structure.
729%
730% o display: Specifies a connection to an X server; returned from
731% XOpenDisplay.
732%
733% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
734%
735% o text_font: True is font should be mono-spaced (typewriter style).
736%
cristy3ed852e2009-09-05 21:47:34 +0000737*/
738
739static char **FontToList(char *font)
740{
741 char
742 **fontlist;
743
744 register char
745 *p,
746 *q;
747
748 register int
749 i;
750
751 unsigned int
752 fonts;
753
754 if (font == (char *) NULL)
755 return((char **) NULL);
756 /*
757 Convert string to an ASCII list.
758 */
759 fonts=1U;
760 for (p=font; *p != '\0'; p++)
761 if ((*p == ':') || (*p == ';') || (*p == ','))
762 fonts++;
763 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
764 if (fontlist == (char **) NULL)
765 {
cristyc38fbf52013-11-03 13:55:54 +0000766 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",font);
cristy3ed852e2009-09-05 21:47:34 +0000767 return((char **) NULL);
768 }
769 p=font;
770 for (i=0; i < (int) fonts; i++)
771 {
772 for (q=p; *q != '\0'; q++)
773 if ((*q == ':') || (*q == ';') || (*q == ','))
774 break;
775 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
776 sizeof(*fontlist[i]));
777 if (fontlist[i] == (char *) NULL)
778 {
cristyc38fbf52013-11-03 13:55:54 +0000779 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",font);
cristy3ed852e2009-09-05 21:47:34 +0000780 return((char **) NULL);
781 }
782 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
783 p=q+1;
784 }
785 fontlist[i]=(char *) NULL;
786 return(fontlist);
787}
788
cristybcbda3f2011-09-03 13:01:22 +0000789MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000790 const XResourceInfo *resource_info,const MagickBooleanType text_font)
791{
792 static const char
793 *Fonts[]=
794 {
795 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
796 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
797 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
798 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
799 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
800 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
801 "variable",
802 "fixed",
803 (char *) NULL
804 },
805 *TextFonts[]=
806 {
807 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
808 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
809 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
810 "fixed",
811 (char *) NULL
812 };
813
814 char
815 *font_name;
816
817 register const char
818 **p;
819
820 XFontStruct
821 *font_info;
822
823 font_info=(XFontStruct *) NULL;
824 font_name=resource_info->font;
825 if (text_font != MagickFalse)
826 font_name=resource_info->text_font;
827 if ((font_name != (char *) NULL) && (*font_name != '\0'))
828 {
829 char
830 **fontlist;
831
832 register int
833 i;
834
835 /*
836 Load preferred font specified in the X resource database.
837 */
838 fontlist=FontToList(font_name);
839 if (fontlist != (char **) NULL)
840 {
841 for (i=0; fontlist[i] != (char *) NULL; i++)
842 {
843 if (font_info == (XFontStruct *) NULL)
844 font_info=XLoadQueryFont(display,fontlist[i]);
845 fontlist[i]=DestroyString(fontlist[i]);
846 }
847 fontlist=(char **) RelinquishMagickMemory(fontlist);
848 }
849 if (font_info == (XFontStruct *) NULL)
cristyc38fbf52013-11-03 13:55:54 +0000850 ThrowXWindowException(XServerError,"UnableToLoadFont",font_name);
cristy3ed852e2009-09-05 21:47:34 +0000851 }
852 /*
853 Load fonts from list of fonts until one is found.
854 */
855 p=Fonts;
856 if (text_font != MagickFalse)
857 p=TextFonts;
858 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
859 p++;
860 while (*p != (char *) NULL)
861 {
862 if (font_info != (XFontStruct *) NULL)
863 break;
864 font_info=XLoadQueryFont(display,(char *) *p);
865 p++;
866 }
867 return(font_info);
868}
869
870/*
871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
872% %
873% %
874% %
875% X B e s t I c o n S i z e %
876% %
877% %
878% %
879%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
880%
881% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
882% size that maintains the aspect ratio of the image. If the window manager
883% has preferred icon sizes, one of the preferred sizes is used.
884%
885% The format of the XBestIconSize method is:
886%
887% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
888%
889% A description of each parameter follows:
890%
891% o display: Specifies a connection to an X server; returned from
892% XOpenDisplay.
893%
894% o image: the image.
895%
896*/
cristybcbda3f2011-09-03 13:01:22 +0000897MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000898 Image *image)
899{
900 int
901 i,
902 number_sizes;
903
cristya19f1d72012-08-07 18:24:38 +0000904 double
cristy3ed852e2009-09-05 21:47:34 +0000905 scale_factor;
906
907 unsigned int
908 height,
909 icon_height,
910 icon_width,
911 width;
912
913 Window
914 root_window;
915
916 XIconSize
917 *icon_size,
918 *size_list;
919
920 /*
921 Determine if the window manager has specified preferred icon sizes.
922 */
923 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
924 assert(display != (Display *) NULL);
925 assert(window != (XWindowInfo *) NULL);
926 assert(image != (Image *) NULL);
927 window->width=MaxIconSize;
928 window->height=MaxIconSize;
929 icon_size=(XIconSize *) NULL;
930 number_sizes=0;
931 root_window=XRootWindow(display,window->screen);
932 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
933 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
934 icon_size=size_list;
935 if (icon_size == (XIconSize *) NULL)
936 {
937 /*
938 Window manager does not restrict icon size.
939 */
940 icon_size=XAllocIconSize();
941 if (icon_size == (XIconSize *) NULL)
942 {
cristyc38fbf52013-11-03 13:55:54 +0000943 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
944 image->filename);
cristy3ed852e2009-09-05 21:47:34 +0000945 return;
946 }
947 icon_size->min_width=1;
948 icon_size->max_width=MaxIconSize;
949 icon_size->min_height=1;
950 icon_size->max_height=MaxIconSize;
951 icon_size->width_inc=1;
952 icon_size->height_inc=1;
953 }
954 /*
955 Determine aspect ratio of image.
956 */
957 width=(unsigned int) image->columns;
958 height=(unsigned int) image->rows;
959 i=0;
960 if (window->crop_geometry)
961 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
962 /*
963 Look for an icon size that maintains the aspect ratio of image.
964 */
cristya19f1d72012-08-07 18:24:38 +0000965 scale_factor=(double) icon_size->max_width/width;
966 if (scale_factor > ((double) icon_size->max_height/height))
967 scale_factor=(double) icon_size->max_height/height;
cristy3ed852e2009-09-05 21:47:34 +0000968 icon_width=(unsigned int) icon_size->min_width;
969 while ((int) icon_width < icon_size->max_width)
970 {
971 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
972 break;
973 icon_width+=icon_size->width_inc;
974 }
975 icon_height=(unsigned int) icon_size->min_height;
976 while ((int) icon_height < icon_size->max_height)
977 {
978 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
979 break;
980 icon_height+=icon_size->height_inc;
981 }
982 (void) XFree((void *) icon_size);
983 window->width=icon_width;
984 window->height=icon_height;
985}
986
987/*
988%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
989% %
990% %
991% %
992% X B e s t P i x e l %
993% %
994% %
995% %
996%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997%
998% XBestPixel() returns a pixel from an array of pixels that is closest to the
999% requested color. If the color array is NULL, the colors are obtained from
1000% the X server.
1001%
1002% The format of the XBestPixel method is:
1003%
1004% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1005% unsigned int number_colors,XColor *color)
1006%
1007% A description of each parameter follows:
1008%
1009% o pixel: XBestPixel returns the pixel value closest to the requested
1010% color.
1011%
1012% o display: Specifies a connection to an X server; returned from
1013% XOpenDisplay.
1014%
1015% o colormap: Specifies the ID of the X server colormap.
1016%
1017% o colors: Specifies an array of XColor structures.
1018%
1019% o number_colors: Specifies the number of XColor structures in the
1020% color definition array.
1021%
1022% o color: Specifies the desired RGB value to find in the colors array.
1023%
1024*/
cristybcbda3f2011-09-03 13:01:22 +00001025MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001026 XColor *colors,unsigned int number_colors,XColor *color)
1027{
1028 MagickBooleanType
1029 query_server;
1030
cristy4c08aed2011-07-01 19:47:50 +00001031 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001032 pixel;
1033
cristya19f1d72012-08-07 18:24:38 +00001034 double
cristy3ed852e2009-09-05 21:47:34 +00001035 min_distance;
1036
cristya19f1d72012-08-07 18:24:38 +00001037 register double
cristy3ed852e2009-09-05 21:47:34 +00001038 distance;
1039
1040 register int
1041 i,
1042 j;
1043
1044 Status
1045 status;
1046
1047 /*
1048 Find closest representation for the requested RGB color.
1049 */
1050 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1051 assert(display != (Display *) NULL);
1052 assert(color != (XColor *) NULL);
1053 status=XAllocColor(display,colormap,color);
1054 if (status != False)
1055 return;
1056 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1057 if (query_server != MagickFalse)
1058 {
1059 /*
1060 Read X server colormap.
1061 */
1062 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1063 if (colors == (XColor *) NULL)
1064 {
cristyc38fbf52013-11-03 13:55:54 +00001065 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
1066 "...");
cristy3ed852e2009-09-05 21:47:34 +00001067 return;
1068 }
1069 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001070 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001071 if (number_colors > 256)
1072 number_colors=256;
1073 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1074 }
cristya19f1d72012-08-07 18:24:38 +00001075 min_distance=3.0*((double) QuantumRange+1.0)*((double)
cristy3ed852e2009-09-05 21:47:34 +00001076 QuantumRange+1.0);
1077 j=0;
1078 for (i=0; i < (int) number_colors; i++)
1079 {
cristya19f1d72012-08-07 18:24:38 +00001080 pixel.red=colors[i].red-(double) color->red;
cristy3ed852e2009-09-05 21:47:34 +00001081 distance=pixel.red*pixel.red;
1082 if (distance > min_distance)
1083 continue;
cristya19f1d72012-08-07 18:24:38 +00001084 pixel.green=colors[i].green-(double) color->green;
cristy3ed852e2009-09-05 21:47:34 +00001085 distance+=pixel.green*pixel.green;
1086 if (distance > min_distance)
1087 continue;
cristya19f1d72012-08-07 18:24:38 +00001088 pixel.blue=colors[i].blue-(double) color->blue;
cristy3ed852e2009-09-05 21:47:34 +00001089 distance+=pixel.blue*pixel.blue;
1090 if (distance > min_distance)
1091 continue;
1092 min_distance=distance;
1093 color->pixel=colors[i].pixel;
1094 j=i;
1095 }
1096 (void) XAllocColor(display,colormap,&colors[j]);
1097 if (query_server != MagickFalse)
1098 colors=(XColor *) RelinquishMagickMemory(colors);
1099}
1100
1101/*
1102%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1103% %
1104% %
1105% %
1106% X B e s t V i s u a l I n f o %
1107% %
1108% %
1109% %
1110%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1111%
1112% XBestVisualInfo() returns visual information for a visual that is the "best"
1113% the server supports. "Best" is defined as:
1114%
1115% 1. Restrict the visual list to those supported by the default screen.
1116%
1117% 2. If a visual type is specified, restrict the visual list to those of
1118% that type.
1119%
1120% 3. If a map type is specified, choose the visual that matches the id
1121% specified by the Standard Colormap.
1122%
1123% 4 From the list of visuals, choose one that can display the most
1124% simultaneous colors. If more than one visual can display the same
1125% number of simultaneous colors, one is chosen based on a rank.
1126%
1127% The format of the XBestVisualInfo method is:
1128%
1129% XVisualInfo *XBestVisualInfo(Display *display,
1130% XStandardColormap *map_info,XResourceInfo *resource_info)
1131%
1132% A description of each parameter follows:
1133%
1134% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1135% structure.
1136%
1137% o display: Specifies a connection to an X server; returned from
1138% XOpenDisplay.
1139%
1140% o map_info: If map_type is specified, this structure is initialized
1141% with info from the Standard Colormap.
1142%
1143% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1144%
1145*/
cristybcbda3f2011-09-03 13:01:22 +00001146MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001147 XStandardColormap *map_info,XResourceInfo *resource_info)
1148{
1149#define MaxStandardColormaps 7
1150#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1151 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1152 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
cristydf409582015-06-12 16:35:04 +00001153 (unsigned long) visual_info->colormap_size),1UL << visual_info->depth)
cristy3ed852e2009-09-05 21:47:34 +00001154
1155 char
1156 *map_type,
1157 *visual_type;
1158
cristyc57f6942010-11-12 01:47:39 +00001159 int
1160 visual_mask;
1161
cristy3ed852e2009-09-05 21:47:34 +00001162 register int
1163 i;
1164
cristy8891f9c2010-06-04 23:32:17 +00001165 size_t
1166 one;
1167
cristy3ed852e2009-09-05 21:47:34 +00001168 static int
1169 number_visuals;
1170
1171 static XVisualInfo
1172 visual_template;
1173
1174 XVisualInfo
1175 *visual_info,
1176 *visual_list;
1177
1178 /*
1179 Restrict visual search by screen number.
1180 */
1181 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1182 assert(display != (Display *) NULL);
1183 assert(map_info != (XStandardColormap *) NULL);
1184 assert(resource_info != (XResourceInfo *) NULL);
1185 map_type=resource_info->map_type;
1186 visual_type=resource_info->visual_type;
1187 visual_mask=VisualScreenMask;
1188 visual_template.screen=XDefaultScreen(display);
1189 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001190 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001191 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001192 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001193 visual_mask|=VisualDepthMask;
1194 if (visual_type != (char *) NULL)
1195 {
1196 /*
1197 Restrict visual search by class or visual id.
1198 */
1199 if (LocaleCompare("staticgray",visual_type) == 0)
1200 {
1201 visual_mask|=VisualClassMask;
1202 visual_template.klass=StaticGray;
1203 }
1204 else
1205 if (LocaleCompare("grayscale",visual_type) == 0)
1206 {
1207 visual_mask|=VisualClassMask;
1208 visual_template.klass=GrayScale;
1209 }
1210 else
1211 if (LocaleCompare("staticcolor",visual_type) == 0)
1212 {
1213 visual_mask|=VisualClassMask;
1214 visual_template.klass=StaticColor;
1215 }
1216 else
1217 if (LocaleCompare("pseudocolor",visual_type) == 0)
1218 {
1219 visual_mask|=VisualClassMask;
1220 visual_template.klass=PseudoColor;
1221 }
1222 else
1223 if (LocaleCompare("truecolor",visual_type) == 0)
1224 {
1225 visual_mask|=VisualClassMask;
1226 visual_template.klass=TrueColor;
1227 }
1228 else
1229 if (LocaleCompare("directcolor",visual_type) == 0)
1230 {
1231 visual_mask|=VisualClassMask;
1232 visual_template.klass=DirectColor;
1233 }
1234 else
1235 if (LocaleCompare("default",visual_type) == 0)
1236 {
1237 visual_mask|=VisualIDMask;
1238 visual_template.visualid=XVisualIDFromVisual(
1239 XDefaultVisual(display,XDefaultScreen(display)));
1240 }
1241 else
1242 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1243 {
1244 visual_mask|=VisualIDMask;
1245 visual_template.visualid=
1246 strtol(visual_type,(char **) NULL,0);
1247 }
1248 else
cristyc38fbf52013-11-03 13:55:54 +00001249 ThrowXWindowException(XServerError,
cristy3ed852e2009-09-05 21:47:34 +00001250 "UnrecognizedVisualSpecifier",visual_type);
1251 }
1252 /*
1253 Get all visuals that meet our criteria so far.
1254 */
1255 number_visuals=0;
1256 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1257 &number_visuals);
1258 visual_mask=VisualScreenMask | VisualIDMask;
1259 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1260 {
1261 /*
1262 Failed to get visual; try using the default visual.
1263 */
cristyc38fbf52013-11-03 13:55:54 +00001264 ThrowXWindowException(XServerWarning,"UnableToGetVisual",visual_type);
cristy3ed852e2009-09-05 21:47:34 +00001265 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1266 XDefaultScreen(display)));
1267 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1268 &number_visuals);
1269 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1270 return((XVisualInfo *) NULL);
cristyc38fbf52013-11-03 13:55:54 +00001271 ThrowXWindowException(XServerWarning,"UsingDefaultVisual",
cristy3ed852e2009-09-05 21:47:34 +00001272 XVisualClassName(visual_list->klass));
1273 }
1274 resource_info->color_recovery=MagickFalse;
1275 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1276 {
1277 Atom
1278 map_property;
1279
1280 char
cristy151b66d2015-04-15 10:50:31 +00001281 map_name[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00001282
1283 int
1284 j,
1285 number_maps;
1286
1287 Status
1288 status;
1289
1290 Window
1291 root_window;
1292
1293 XStandardColormap
1294 *map_list;
1295
1296 /*
1297 Choose a visual associated with a standard colormap.
1298 */
1299 root_window=XRootWindow(display,XDefaultScreen(display));
1300 status=False;
cristy53365c22013-11-24 15:13:41 +00001301 number_maps=0;
cristy3ed852e2009-09-05 21:47:34 +00001302 if (LocaleCompare(map_type,"list") != 0)
1303 {
1304 /*
1305 User specified Standard Colormap.
1306 */
cristy151b66d2015-04-15 10:50:31 +00001307 (void) FormatLocaleString((char *) map_name,MagickPathExtent,
cristy3ed852e2009-09-05 21:47:34 +00001308 "RGB_%s_MAP",map_type);
1309 LocaleUpper(map_name);
1310 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1311 if (map_property != (Atom) NULL)
1312 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1313 map_property);
1314 }
1315 else
1316 {
1317 static const char
1318 *colormap[MaxStandardColormaps]=
1319 {
1320 "_HP_RGB_SMOOTH_MAP_LIST",
1321 "RGB_BEST_MAP",
1322 "RGB_DEFAULT_MAP",
1323 "RGB_GRAY_MAP",
1324 "RGB_RED_MAP",
1325 "RGB_GREEN_MAP",
1326 "RGB_BLUE_MAP",
1327 };
1328
1329 /*
1330 Choose a standard colormap from a list.
1331 */
1332 for (i=0; i < MaxStandardColormaps; i++)
1333 {
1334 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1335 if (map_property == (Atom) NULL)
1336 continue;
1337 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1338 map_property);
1339 if (status != False)
1340 break;
1341 }
1342 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1343 }
1344 if (status == False)
1345 {
cristyc38fbf52013-11-03 13:55:54 +00001346 ThrowXWindowException(XServerError,"UnableToGetStandardColormap",
cristy3ed852e2009-09-05 21:47:34 +00001347 map_type);
1348 return((XVisualInfo *) NULL);
1349 }
1350 /*
1351 Search all Standard Colormaps and visuals for ids that match.
1352 */
1353 *map_info=map_list[0];
1354#if !defined(PRE_R4_ICCCM)
1355 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1356 for (i=0; i < number_maps; i++)
1357 for (j=0; j < number_visuals; j++)
1358 if (map_list[i].visualid ==
1359 XVisualIDFromVisual(visual_list[j].visual))
1360 {
1361 *map_info=map_list[i];
1362 visual_template.visualid=XVisualIDFromVisual(
1363 visual_list[j].visual);
1364 break;
1365 }
1366 if (map_info->visualid != visual_template.visualid)
1367 {
cristyc38fbf52013-11-03 13:55:54 +00001368 ThrowXWindowException(XServerError,
cristy3ed852e2009-09-05 21:47:34 +00001369 "UnableToMatchVisualToStandardColormap",map_type);
1370 return((XVisualInfo *) NULL);
1371 }
1372#endif
1373 if (map_info->colormap == (Colormap) NULL)
1374 {
cristyc38fbf52013-11-03 13:55:54 +00001375 ThrowXWindowException(XServerError,"StandardColormapIsNotInitialized",
1376 map_type);
cristy3ed852e2009-09-05 21:47:34 +00001377 return((XVisualInfo *) NULL);
1378 }
1379 (void) XFree((void *) map_list);
1380 }
1381 else
1382 {
1383 static const unsigned int
1384 rank[]=
1385 {
1386 StaticGray,
1387 GrayScale,
1388 StaticColor,
1389 DirectColor,
1390 TrueColor,
1391 PseudoColor
1392 };
1393
1394 XVisualInfo
1395 *p;
1396
1397 /*
1398 Pick one visual that displays the most simultaneous colors.
1399 */
1400 visual_info=visual_list;
1401 p=visual_list;
1402 for (i=1; i < number_visuals; i++)
1403 {
1404 p++;
1405 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1406 visual_info=p;
1407 else
1408 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1409 if (rank[p->klass] > rank[visual_info->klass])
1410 visual_info=p;
1411 }
1412 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1413 }
1414 (void) XFree((void *) visual_list);
1415 /*
1416 Retrieve only one visual by its screen & id number.
1417 */
1418 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1419 &number_visuals);
1420 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1421 return((XVisualInfo *) NULL);
1422 return(visual_info);
1423}
1424
1425/*
1426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1427% %
1428% %
1429% %
1430% X C h e c k D e f i n e C u r s o r %
1431% %
1432% %
1433% %
1434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1435%
1436% XCheckDefineCursor() prevents cursor changes on the root window.
1437%
1438% The format of the XXCheckDefineCursor method is:
1439%
1440% XCheckDefineCursor(display,window,cursor)
1441%
1442% A description of each parameter follows:
1443%
1444% o display: Specifies a connection to an X server; returned from
1445% XOpenDisplay.
1446%
1447% o window: the window.
1448%
1449% o cursor: the cursor.
1450%
1451*/
cristybcbda3f2011-09-03 13:01:22 +00001452MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001453 Cursor cursor)
1454{
1455 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1456 assert(display != (Display *) NULL);
1457 if (window == XRootWindow(display,XDefaultScreen(display)))
1458 return(0);
1459 return(XDefineCursor(display,window,cursor));
1460}
1461
1462/*
1463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1464% %
1465% %
1466% %
1467% X C h e c k R e f r e s h W i n d o w s %
1468% %
1469% %
1470% %
1471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1472%
1473% XCheckRefreshWindows() checks the X server for exposure events for a
1474% particular window and updates the areassociated with the exposure event.
1475%
1476% The format of the XCheckRefreshWindows method is:
1477%
1478% void XCheckRefreshWindows(Display *display,XWindows *windows)
1479%
1480% A description of each parameter follows:
1481%
1482% o display: Specifies a connection to an X server; returned from
1483% XOpenDisplay.
1484%
1485% o windows: Specifies a pointer to a XWindows structure.
1486%
1487*/
cristybcbda3f2011-09-03 13:01:22 +00001488MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001489{
1490 Window
1491 id;
1492
1493 XEvent
1494 event;
1495
1496 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1497 assert(display != (Display *) NULL);
1498 assert(windows != (XWindows *) NULL);
1499 XDelay(display,SuspendTime);
1500 id=windows->command.id;
1501 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1502 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1503 id=windows->image.id;
1504 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1505 XRefreshWindow(display,&windows->image,&event);
1506 XDelay(display,SuspendTime << 1);
1507 id=windows->command.id;
1508 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1509 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1510 id=windows->image.id;
1511 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1512 XRefreshWindow(display,&windows->image,&event);
1513}
1514
1515/*
1516%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1517% %
1518% %
1519% %
1520% X C l i e n t M e s s a g e %
1521% %
1522% %
1523% %
1524%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1525%
1526% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1527% initialized with a particular protocol type and atom.
1528%
1529% The format of the XClientMessage function is:
1530%
1531% XClientMessage(display,window,protocol,reason,timestamp)
1532%
1533% A description of each parameter follows:
1534%
1535% o display: Specifies a pointer to the Display structure; returned from
1536% XOpenDisplay.
1537%
1538% o window: Specifies a pointer to a Window structure.
1539%
1540% o protocol: Specifies an atom value.
1541%
1542% o reason: Specifies an atom value which is the reason to send.
1543%
1544% o timestamp: Specifies a value of type Time.
1545%
1546*/
cristybcbda3f2011-09-03 13:01:22 +00001547MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001548 const Atom protocol,const Atom reason,const Time timestamp)
1549{
1550 XClientMessageEvent
1551 client_event;
1552
1553 assert(display != (Display *) NULL);
1554 client_event.type=ClientMessage;
1555 client_event.window=window;
1556 client_event.message_type=protocol;
1557 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001558 client_event.data.l[0]=(long) reason;
1559 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001560 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1561}
1562
1563/*
1564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1565% %
1566% %
1567% %
1568+ X C l i e n t W i n d o w %
1569% %
1570% %
1571% %
1572%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1573%
1574% XClientWindow() finds a window, at or below the specified window, which has
1575% a WM_STATE property. If such a window is found, it is returned, otherwise
1576% the argument window is returned.
1577%
1578% The format of the XClientWindow function is:
1579%
1580% client_window=XClientWindow(display,target_window)
1581%
1582% A description of each parameter follows:
1583%
1584% o client_window: XClientWindow returns a window, at or below the specified
1585% window, which has a WM_STATE property otherwise the argument
1586% target_window is returned.
1587%
1588% o display: Specifies a pointer to the Display structure; returned from
1589% XOpenDisplay.
1590%
1591% o target_window: Specifies the window to find a WM_STATE property.
1592%
cristy3ed852e2009-09-05 21:47:34 +00001593*/
1594static Window XClientWindow(Display *display,Window target_window)
1595{
1596 Atom
1597 state,
1598 type;
1599
1600 int
1601 format;
1602
1603 Status
1604 status;
1605
1606 unsigned char
1607 *data;
1608
cristyf2faecf2010-05-28 19:19:36 +00001609 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001610 after,
1611 number_items;
1612
1613 Window
1614 client_window;
1615
1616 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1617 assert(display != (Display *) NULL);
1618 state=XInternAtom(display,"WM_STATE",MagickTrue);
1619 if (state == (Atom) NULL)
1620 return(target_window);
1621 type=(Atom) NULL;
1622 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1623 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1624 if ((status == Success) && (type != (Atom) NULL))
1625 return(target_window);
1626 client_window=XWindowByProperty(display,target_window,state);
1627 if (client_window == (Window) NULL)
1628 return(target_window);
1629 return(client_window);
1630}
1631
1632/*
1633%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1634% %
1635% %
1636% %
cristyf34a1452009-10-24 22:29:27 +00001637+ X C o m p o n e n t T e r m i n u s %
1638% %
1639% %
1640% %
1641%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1642%
1643% XComponentTerminus() destroys the module component.
1644%
1645% The format of the XComponentTerminus method is:
1646%
1647% XComponentTerminus(void)
1648%
1649*/
cristy5ff4eaf2011-09-03 01:38:02 +00001650MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001651{
1652 DestroyXResources();
1653}
1654
1655/*
1656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1657% %
1658% %
1659% %
cristy3ed852e2009-09-05 21:47:34 +00001660% X C o n f i g u r e I m a g e C o l o r m a p %
1661% %
1662% %
1663% %
1664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1665%
1666% XConfigureImageColormap() creates a new X colormap.
1667%
1668% The format of the XConfigureImageColormap method is:
1669%
1670% void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001671% XResourceInfo *resource_info,XWindows *windows,Image *image,
1672% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001673%
1674% A description of each parameter follows:
1675%
1676% o display: Specifies a connection to an X server; returned from
1677% XOpenDisplay.
1678%
1679% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1680%
1681% o windows: Specifies a pointer to a XWindows structure.
1682%
1683% o image: the image.
1684%
cristy6710d842011-10-20 23:23:00 +00001685% o exception: return any errors or warnings in this structure.
1686%
cristy3ed852e2009-09-05 21:47:34 +00001687*/
cristybcbda3f2011-09-03 13:01:22 +00001688MagickPrivate void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001689 XResourceInfo *resource_info,XWindows *windows,Image *image,
1690 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001691{
1692 Colormap
1693 colormap;
1694
1695 /*
1696 Make standard colormap.
1697 */
1698 XSetCursorState(display,windows,MagickTrue);
1699 XCheckRefreshWindows(display,windows);
1700 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
cristy6710d842011-10-20 23:23:00 +00001701 windows->map_info,windows->pixel_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00001702 colormap=windows->map_info->colormap;
1703 (void) XSetWindowColormap(display,windows->image.id,colormap);
1704 (void) XSetWindowColormap(display,windows->command.id,colormap);
1705 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1706 if (windows->magnify.mapped != MagickFalse)
1707 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1708 if (windows->pan.mapped != MagickFalse)
1709 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1710 XSetCursorState(display,windows,MagickFalse);
1711 XClientMessage(display,windows->image.id,windows->im_protocols,
1712 windows->im_update_colormap,CurrentTime);
1713}
1714
1715/*
1716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1717% %
1718% %
1719% %
1720% X C o n s t r a i n W i n d o w P o s i t i o n %
1721% %
1722% %
1723% %
1724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725%
1726% XConstrainWindowPosition() assures a window is positioned within the X
1727% server boundaries.
1728%
1729% The format of the XConstrainWindowPosition method is:
1730%
1731% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1732%
1733% A description of each parameter follows:
1734%
1735% o display: Specifies a pointer to the Display structure; returned from
1736% XOpenDisplay.
1737%
1738% o window_info: Specifies a pointer to a XWindowInfo structure.
1739%
1740*/
cristybcbda3f2011-09-03 13:01:22 +00001741MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001742 XWindowInfo *window_info)
1743{
1744 int
1745 limit;
1746
1747 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1748 assert(display != (Display *) NULL);
1749 assert(window_info != (XWindowInfo *) NULL);
1750 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1751 if (window_info->x < 0)
1752 window_info->x=0;
1753 else
1754 if (window_info->x > (int) limit)
1755 window_info->x=(int) limit;
1756 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1757 if (window_info->y < 0)
1758 window_info->y=0;
1759 else
1760 if (window_info->y > limit)
1761 window_info->y=limit;
1762}
1763
1764/*
1765%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1766% %
1767% %
1768% %
1769% X D e l a y %
1770% %
1771% %
1772% %
1773%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1774%
1775% XDelay() suspends program execution for the number of milliseconds
1776% specified.
1777%
1778% The format of the Delay method is:
1779%
cristybb503372010-05-27 20:51:26 +00001780% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001781%
1782% A description of each parameter follows:
1783%
1784% o display: Specifies a pointer to the Display structure; returned from
1785% XOpenDisplay.
1786%
1787% o milliseconds: Specifies the number of milliseconds to delay before
1788% returning.
1789%
1790*/
cristybcbda3f2011-09-03 13:01:22 +00001791MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001792{
1793 assert(display != (Display *) NULL);
1794 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001795 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001796}
1797
1798/*
1799%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1800% %
1801% %
1802% %
1803% X D e s t r o y R e s o u r c e I n f o %
1804% %
1805% %
1806% %
1807%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1808%
1809% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1810% structure.
1811%
1812% The format of the XDestroyResourceInfo method is:
1813%
1814% void XDestroyResourceInfo(XResourceInfo *resource_info)
1815%
1816% A description of each parameter follows:
1817%
1818% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1819%
1820*/
1821MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1822{
1823 if (resource_info->image_geometry != (char *) NULL)
1824 resource_info->image_geometry=(char *)
1825 RelinquishMagickMemory(resource_info->image_geometry);
1826 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1827 resource_info->quantize_info=DestroyQuantizeInfo(
1828 resource_info->quantize_info);
1829 if (resource_info->client_name != (char *) NULL)
1830 resource_info->client_name=(char *)
1831 RelinquishMagickMemory(resource_info->client_name);
1832 if (resource_info->name != (char *) NULL)
1833 resource_info->name=DestroyString(resource_info->name);
1834 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1835}
1836
1837/*
1838%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1839% %
1840% %
1841% %
1842% X D e s t r o y W i n d o w C o l o r s %
1843% %
1844% %
1845% %
1846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1847%
1848% XDestroyWindowColors() frees X11 color resources previously saved on a
1849% window by XRetainWindowColors or programs like xsetroot.
1850%
1851% The format of the XDestroyWindowColors method is:
1852%
1853% void XDestroyWindowColors(Display *display,Window window)
1854%
1855% A description of each parameter follows:
1856%
1857% o display: Specifies a connection to an X server; returned from
1858% XOpenDisplay.
1859%
1860% o window: Specifies a pointer to a Window structure.
1861%
1862*/
cristybcbda3f2011-09-03 13:01:22 +00001863MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001864{
1865 Atom
1866 property,
1867 type;
1868
1869 int
1870 format;
1871
1872 Status
1873 status;
1874
1875 unsigned char
1876 *data;
1877
cristyf2faecf2010-05-28 19:19:36 +00001878 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001879 after,
1880 length;
1881
1882 /*
1883 If there are previous resources on the root window, destroy them.
1884 */
1885 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1886 assert(display != (Display *) NULL);
1887 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1888 if (property == (Atom) NULL)
1889 {
cristyc38fbf52013-11-03 13:55:54 +00001890 ThrowXWindowException(XServerError,"UnableToCreateProperty",
cristy3ed852e2009-09-05 21:47:34 +00001891 "_XSETROOT_ID");
1892 return;
1893 }
1894 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1895 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1896 if (status != Success)
1897 return;
1898 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1899 {
1900 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1901 (void) XDeleteProperty(display,window,property);
1902 }
1903 if (type != None)
1904 (void) XFree((void *) data);
1905}
1906
1907/*
1908%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1909% %
1910% %
1911% %
1912% X D i s p l a y I m a g e I n f o %
1913% %
1914% %
1915% %
1916%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1917%
1918% XDisplayImageInfo() displays information about an X image.
1919%
1920% The format of the XDisplayImageInfo method is:
1921%
1922% void XDisplayImageInfo(Display *display,
1923% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001924% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001925%
1926% A description of each parameter follows:
1927%
1928% o display: Specifies a connection to an X server; returned from
1929% XOpenDisplay.
1930%
1931% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1932%
1933% o windows: Specifies a pointer to a XWindows structure.
1934%
1935% o undo_image: the undo image.
1936%
1937% o image: the image.
1938%
cristy6710d842011-10-20 23:23:00 +00001939% o exception: return any errors or warnings in this structure.
1940%
cristy3ed852e2009-09-05 21:47:34 +00001941*/
cristybcbda3f2011-09-03 13:01:22 +00001942MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001943 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001944 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001945{
1946 char
cristy151b66d2015-04-15 10:50:31 +00001947 filename[MagickPathExtent],
cristy3ed852e2009-09-05 21:47:34 +00001948 *text,
1949 **textlist;
1950
1951 FILE
1952 *file;
1953
1954 int
1955 unique_file;
1956
cristybb503372010-05-27 20:51:26 +00001957 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001958 i;
1959
cristybb503372010-05-27 20:51:26 +00001960 size_t
cristy3ed852e2009-09-05 21:47:34 +00001961 number_pixels;
1962
cristy9d314ff2011-03-09 01:30:28 +00001963 ssize_t
1964 bytes;
1965
1966 unsigned int
1967 levels;
1968
cristy3ed852e2009-09-05 21:47:34 +00001969 /*
1970 Write info about the X server to a file.
1971 */
1972 assert(display != (Display *) NULL);
1973 assert(resource_info != (XResourceInfo *) NULL);
1974 assert(windows != (XWindows *) NULL);
1975 assert(image != (Image *) NULL);
1976 if (image->debug)
1977 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1978 file=(FILE *) NULL;
1979 unique_file=AcquireUniqueFileResource(filename);
1980 if (unique_file != -1)
1981 file=fdopen(unique_file,"w");
1982 if ((unique_file == -1) || (file == (FILE *) NULL))
1983 {
1984 XNoticeWidget(display,windows,"Unable to display image info",filename);
1985 return;
1986 }
1987 if (resource_info->gamma_correct != MagickFalse)
1988 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00001989 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00001990 resource_info->display_gamma);
1991 /*
1992 Write info about the X image to a file.
1993 */
cristyb51dff52011-05-19 16:55:47 +00001994 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00001995 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00001996 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00001997 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00001998 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00001999 windows->visual_info->colormap_size);
2000 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002001 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002002 else
cristyb51dff52011-05-19 16:55:47 +00002003 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002004 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2005 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002006 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002007 (void) FormatLocaleFile(file," crop geometry: %s\n",
2008 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002009 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002010 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002011 else
cristyb51dff52011-05-19 16:55:47 +00002012 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002013 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002014 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002015 else
cristyb51dff52011-05-19 16:55:47 +00002016 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002017 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002018 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002019 else
cristyb51dff52011-05-19 16:55:47 +00002020 (void) FormatLocaleFile(file," shared memory: False\n");
2021 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002022 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002023 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002024 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002025 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002026 /*
2027 Write info about the undo cache to a file.
2028 */
2029 bytes=0;
2030 for (levels=0; undo_image != (Image *) NULL; levels++)
2031 {
2032 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002033 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002034 undo_image=GetPreviousImageInList(undo_image);
2035 }
cristyb51dff52011-05-19 16:55:47 +00002036 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002037 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2038 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002039 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002040 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002041 /*
2042 Write info about the image to a file.
2043 */
cristy6710d842011-10-20 23:23:00 +00002044 (void) IdentifyImage(image,file,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00002045 (void) fclose(file);
cristy3a5987c2013-11-07 14:18:46 +00002046 text=FileToString(filename,~0UL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002047 (void) RelinquishUniqueFileResource(filename);
2048 if (text == (char *) NULL)
2049 {
2050 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2051 "UnableToDisplayImageInfo");
2052 return;
2053 }
2054 textlist=StringToList(text);
2055 if (textlist != (char **) NULL)
2056 {
2057 char
cristy151b66d2015-04-15 10:50:31 +00002058 title[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00002059
2060 /*
2061 Display information about the image in the Text View widget.
2062 */
2063 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristy151b66d2015-04-15 10:50:31 +00002064 (void) FormatLocaleString(title,MagickPathExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002065 image->filename);
2066 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2067 (char const **) textlist);
2068 for (i=0; textlist[i] != (char *) NULL; i++)
2069 textlist[i]=DestroyString(textlist[i]);
2070 textlist=(char **) RelinquishMagickMemory(textlist);
2071 }
2072 text=DestroyString(text);
2073}
2074
2075/*
2076%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2077% %
2078% %
2079% %
2080+ X D i t h e r I m a g e %
2081% %
2082% %
2083% %
2084%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2085%
2086% XDitherImage() dithers the reference image as required by the HP Color
2087% Recovery algorithm. The color values are quantized to 3 bits of red and
2088% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2089% standard colormap.
2090%
2091% The format of the XDitherImage method is:
2092%
cristy6710d842011-10-20 23:23:00 +00002093% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002094%
2095% A description of each parameter follows:
2096%
2097% o image: the image.
2098%
2099% o ximage: Specifies a pointer to a XImage structure; returned from
2100% XCreateImage.
2101%
cristy6710d842011-10-20 23:23:00 +00002102% o exception: return any errors or warnings in this structure.
2103%
cristy3ed852e2009-09-05 21:47:34 +00002104*/
cristy6710d842011-10-20 23:23:00 +00002105static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002106{
2107 static const short int
2108 dither_red[2][16]=
2109 {
2110 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2111 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2112 },
2113 dither_green[2][16]=
2114 {
2115 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2116 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2117 },
2118 dither_blue[2][16]=
2119 {
2120 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2121 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2122 };
2123
cristyc57f6942010-11-12 01:47:39 +00002124 CacheView
2125 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002126
2127 int
cristyc57f6942010-11-12 01:47:39 +00002128 value,
cristy3ed852e2009-09-05 21:47:34 +00002129 y;
2130
cristy101ab702011-10-13 13:06:32 +00002131 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002132 color;
cristy3ed852e2009-09-05 21:47:34 +00002133
2134 register char
2135 *q;
2136
cristy4c08aed2011-07-01 19:47:50 +00002137 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002138 *p;
2139
2140 register int
2141 i,
2142 j,
2143 x;
2144
2145 unsigned int
2146 scanline_pad;
2147
cristybb503372010-05-27 20:51:26 +00002148 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002149 pixel;
2150
2151 unsigned char
2152 *blue_map[2][16],
2153 *green_map[2][16],
2154 *red_map[2][16];
2155
2156 /*
2157 Allocate and initialize dither maps.
2158 */
2159 for (i=0; i < 2; i++)
2160 for (j=0; j < 16; j++)
2161 {
2162 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2163 sizeof(*red_map));
2164 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2165 sizeof(*green_map));
2166 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2167 sizeof(*blue_map));
2168 if ((red_map[i][j] == (unsigned char *) NULL) ||
2169 (green_map[i][j] == (unsigned char *) NULL) ||
2170 (blue_map[i][j] == (unsigned char *) NULL))
2171 {
cristyc38fbf52013-11-03 13:55:54 +00002172 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
2173 image->filename);
cristy3ed852e2009-09-05 21:47:34 +00002174 return;
2175 }
2176 }
2177 /*
2178 Initialize dither tables.
2179 */
2180 for (i=0; i < 2; i++)
2181 for (j=0; j < 16; j++)
2182 for (x=0; x < 256; x++)
2183 {
2184 value=x-16;
2185 if (x < 48)
2186 value=x/2+8;
2187 value+=dither_red[i][j];
2188 red_map[i][j][x]=(unsigned char)
2189 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2190 value=x-16;
2191 if (x < 48)
2192 value=x/2+8;
2193 value+=dither_green[i][j];
2194 green_map[i][j][x]=(unsigned char)
2195 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2196 value=x-32;
2197 if (x < 112)
2198 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002199 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002200 blue_map[i][j][x]=(unsigned char)
2201 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2202 }
2203 /*
2204 Dither image.
2205 */
2206 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002207 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002208 i=0;
2209 j=0;
2210 q=ximage->data;
cristy46ff2672012-12-14 15:32:26 +00002211 image_view=AcquireVirtualCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002212 for (y=0; y < (int) image->rows; y++)
2213 {
cristyc57f6942010-11-12 01:47:39 +00002214 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
cristy6710d842011-10-20 23:23:00 +00002215 exception);
cristy4c08aed2011-07-01 19:47:50 +00002216 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002217 break;
2218 for (x=0; x < (int) image->columns; x++)
2219 {
cristyada285b2012-07-07 19:00:46 +00002220 color.red=(double) ClampToQuantum((double) (red_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002221 (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002222 color.green=(double) ClampToQuantum((double) (green_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002223 (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002224 color.blue=(double) ClampToQuantum((double) (blue_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002225 (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002226 pixel=(size_t) (((size_t) color.red & 0xe0) |
2227 (((size_t) color.green & 0xe0) >> 3) |
2228 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002229 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002230 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002231 j++;
2232 if (j == 16)
2233 j=0;
2234 }
2235 q+=scanline_pad;
2236 i++;
2237 if (i == 2)
2238 i=0;
2239 }
cristyc57f6942010-11-12 01:47:39 +00002240 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002241 /*
2242 Free allocated memory.
2243 */
2244 for (i=0; i < 2; i++)
2245 for (j=0; j < 16; j++)
2246 {
2247 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2248 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2249 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2250 }
2251}
2252
2253/*
2254%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2255% %
2256% %
2257% %
2258% X D r a w I m a g e %
2259% %
2260% %
2261% %
2262%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2263%
2264% XDrawImage() draws a line on the image.
2265%
2266% The format of the XDrawImage method is:
2267%
cristy6710d842011-10-20 23:23:00 +00002268% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2269% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002270%
2271% A description of each parameter follows:
2272%
2273% o display: Specifies a connection to an X server; returned from
2274% XOpenDisplay.
2275%
2276% o pixel: Specifies a pointer to a XPixelInfo structure.
2277%
2278% o draw_info: Specifies a pointer to a XDrawInfo structure.
2279%
2280% o image: the image.
2281%
cristy6710d842011-10-20 23:23:00 +00002282% o exception: return any errors or warnings in this structure.
2283%
cristy3ed852e2009-09-05 21:47:34 +00002284*/
cristybcbda3f2011-09-03 13:01:22 +00002285MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy6710d842011-10-20 23:23:00 +00002286 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2287 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002288{
cristyc57f6942010-11-12 01:47:39 +00002289 CacheView
2290 *draw_view;
2291
cristy3ed852e2009-09-05 21:47:34 +00002292 GC
2293 draw_context;
2294
2295 Image
2296 *draw_image;
2297
2298 int
2299 x,
2300 y;
2301
cristyb0a657e2012-08-29 00:45:37 +00002302 PixelTrait
2303 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002304
2305 Pixmap
2306 draw_pixmap;
2307
2308 unsigned int
2309 depth,
2310 height,
2311 width;
2312
2313 Window
2314 root_window;
2315
2316 XGCValues
2317 context_values;
2318
2319 XImage
2320 *draw_ximage;
2321
2322 /*
2323 Initialize drawd image.
2324 */
2325 assert(display != (Display *) NULL);
2326 assert(pixel != (XPixelInfo *) NULL);
2327 assert(draw_info != (XDrawInfo *) NULL);
2328 assert(image != (Image *) NULL);
2329 if (image->debug != MagickFalse)
2330 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2331 /*
2332 Initialize drawd pixmap.
2333 */
2334 root_window=XRootWindow(display,XDefaultScreen(display));
2335 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2336 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2337 draw_info->height,depth);
2338 if (draw_pixmap == (Pixmap) NULL)
2339 return(MagickFalse);
2340 /*
2341 Initialize graphics info.
2342 */
cristybb503372010-05-27 20:51:26 +00002343 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002344 context_values.foreground=0;
2345 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002346 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002347 (GCBackground | GCForeground | GCLineWidth),&context_values);
2348 if (draw_context == (GC) NULL)
2349 return(MagickFalse);
2350 /*
2351 Clear pixmap.
2352 */
2353 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2354 draw_info->height);
2355 /*
2356 Draw line to pixmap.
2357 */
2358 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002359 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002360 if (draw_info->stipple != (Pixmap) NULL)
2361 {
2362 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2363 (void) XSetStipple(display,draw_context,draw_info->stipple);
2364 }
cristy3ed852e2009-09-05 21:47:34 +00002365 switch (draw_info->element)
2366 {
2367 case PointElement:
2368 default:
2369 {
2370 (void) XDrawLines(display,draw_pixmap,draw_context,
2371 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2372 CoordModeOrigin);
2373 break;
2374 }
2375 case LineElement:
2376 {
2377 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2378 draw_info->line_info.y1,draw_info->line_info.x2,
2379 draw_info->line_info.y2);
2380 break;
2381 }
2382 case RectangleElement:
2383 {
2384 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2385 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2386 (unsigned int) draw_info->rectangle_info.width,
2387 (unsigned int) draw_info->rectangle_info.height);
2388 break;
2389 }
2390 case FillRectangleElement:
2391 {
2392 (void) XFillRectangle(display,draw_pixmap,draw_context,
2393 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2394 (unsigned int) draw_info->rectangle_info.width,
2395 (unsigned int) draw_info->rectangle_info.height);
2396 break;
2397 }
2398 case CircleElement:
2399 case EllipseElement:
2400 {
2401 (void) XDrawArc(display,draw_pixmap,draw_context,
2402 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2403 (unsigned int) draw_info->rectangle_info.width,
2404 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2405 break;
2406 }
2407 case FillCircleElement:
2408 case FillEllipseElement:
2409 {
2410 (void) XFillArc(display,draw_pixmap,draw_context,
2411 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2412 (unsigned int) draw_info->rectangle_info.width,
2413 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2414 break;
2415 }
2416 case PolygonElement:
2417 {
2418 XPoint
2419 *coordinate_info;
2420
2421 coordinate_info=draw_info->coordinate_info;
2422 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2423 (int) draw_info->number_coordinates,CoordModeOrigin);
2424 (void) XDrawLine(display,draw_pixmap,draw_context,
2425 coordinate_info[draw_info->number_coordinates-1].x,
2426 coordinate_info[draw_info->number_coordinates-1].y,
2427 coordinate_info[0].x,coordinate_info[0].y);
2428 break;
2429 }
2430 case FillPolygonElement:
2431 {
2432 (void) XFillPolygon(display,draw_pixmap,draw_context,
2433 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2434 CoordModeOrigin);
2435 break;
2436 }
2437 }
2438 (void) XFreeGC(display,draw_context);
2439 /*
2440 Initialize X image.
2441 */
2442 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2443 draw_info->height,AllPlanes,ZPixmap);
2444 if (draw_ximage == (XImage *) NULL)
2445 return(MagickFalse);
2446 (void) XFreePixmap(display,draw_pixmap);
2447 /*
2448 Initialize draw image.
2449 */
cristy6710d842011-10-20 23:23:00 +00002450 draw_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002451 if (draw_image == (Image *) NULL)
2452 return(MagickFalse);
2453 draw_image->columns=draw_info->width;
2454 draw_image->rows=draw_info->height;
2455 /*
2456 Transfer drawn X image to image.
2457 */
2458 width=(unsigned int) image->columns;
2459 height=(unsigned int) image->rows;
2460 x=0;
2461 y=0;
2462 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +00002463 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
2464 (ssize_t) y,&draw_image->background_color,exception);
cristy6710d842011-10-20 23:23:00 +00002465 if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002466 return(MagickFalse);
cristy8a46d822012-08-28 23:32:39 +00002467 draw_image->alpha_trait=BlendPixelTrait;
cristy6f5395d2012-12-14 18:30:30 +00002468 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002469 for (y=0; y < (int) draw_image->rows; y++)
2470 {
cristyc57f6942010-11-12 01:47:39 +00002471 register int
cristy3ed852e2009-09-05 21:47:34 +00002472 x;
2473
cristy4c08aed2011-07-01 19:47:50 +00002474 register Quantum
dirk05d2ff72015-11-18 23:13:43 +01002475 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002476
cristyc57f6942010-11-12 01:47:39 +00002477 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2478 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002479 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002480 break;
cristyc57f6942010-11-12 01:47:39 +00002481 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002482 {
2483 if (XGetPixel(draw_ximage,x,y) == 0)
2484 {
2485 /*
2486 Set this pixel to the background color.
2487 */
cristy11a06d32015-01-04 12:03:27 +00002488 SetPixelViaPixelInfo(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002489 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002490 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002491 }
2492 else
2493 {
2494 /*
2495 Set this pixel to the pen color.
2496 */
cristy4c08aed2011-07-01 19:47:50 +00002497 SetPixelRed(draw_image,ScaleShortToQuantum(
2498 pixel->pen_color.red),q);
2499 SetPixelGreen(draw_image,ScaleShortToQuantum(
2500 pixel->pen_color.green),q);
2501 SetPixelBlue(draw_image,ScaleShortToQuantum(
2502 pixel->pen_color.blue),q);
2503 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2504 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002505 }
cristyed231572011-07-14 02:18:59 +00002506 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002507 }
cristyc57f6942010-11-12 01:47:39 +00002508 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002509 break;
2510 }
cristyc57f6942010-11-12 01:47:39 +00002511 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002512 XDestroyImage(draw_ximage);
2513 /*
2514 Determine draw geometry.
2515 */
2516 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2517 if ((width != (unsigned int) draw_image->columns) ||
2518 (height != (unsigned int) draw_image->rows))
2519 {
2520 char
cristy151b66d2015-04-15 10:50:31 +00002521 image_geometry[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00002522
2523 /*
2524 Scale image.
2525 */
cristy151b66d2015-04-15 10:50:31 +00002526 (void) FormatLocaleString(image_geometry,MagickPathExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002527 width,height);
cristye941a752011-10-15 01:52:48 +00002528 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2529 exception);
cristy3ed852e2009-09-05 21:47:34 +00002530 }
2531 if (draw_info->degrees != 0.0)
2532 {
2533 Image
2534 *rotate_image;
2535
2536 int
2537 rotations;
2538
cristya19f1d72012-08-07 18:24:38 +00002539 double
cristy3ed852e2009-09-05 21:47:34 +00002540 normalized_degrees;
2541
2542 /*
2543 Rotate image.
2544 */
cristy6710d842011-10-20 23:23:00 +00002545 rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +00002546 if (rotate_image == (Image *) NULL)
2547 return(MagickFalse);
2548 draw_image=DestroyImage(draw_image);
2549 draw_image=rotate_image;
2550 /*
2551 Annotation is relative to the degree of rotation.
2552 */
2553 normalized_degrees=draw_info->degrees;
2554 while (normalized_degrees < -45.0)
2555 normalized_degrees+=360.0;
2556 for (rotations=0; normalized_degrees > 45.0; rotations++)
2557 normalized_degrees-=90.0;
2558 switch (rotations % 4)
2559 {
2560 default:
2561 case 0:
2562 break;
2563 case 1:
2564 {
2565 /*
2566 Rotate 90 degrees.
2567 */
2568 x=x-(int) draw_image->columns/2;
2569 y=y+(int) draw_image->columns/2;
2570 break;
2571 }
2572 case 2:
2573 {
2574 /*
2575 Rotate 180 degrees.
2576 */
2577 x=x-(int) draw_image->columns;
2578 break;
2579 }
2580 case 3:
2581 {
2582 /*
2583 Rotate 270 degrees.
2584 */
2585 x=x-(int) draw_image->columns/2;
2586 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2587 break;
2588 }
2589 }
2590 }
2591 /*
2592 Composite text onto the image.
2593 */
cristy6f5395d2012-12-14 18:30:30 +00002594 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002595 for (y=0; y < (int) draw_image->rows; y++)
2596 {
cristyc57f6942010-11-12 01:47:39 +00002597 register int
cristy3ed852e2009-09-05 21:47:34 +00002598 x;
2599
cristy4c08aed2011-07-01 19:47:50 +00002600 register Quantum
dirk05d2ff72015-11-18 23:13:43 +01002601 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002602
cristyc57f6942010-11-12 01:47:39 +00002603 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2604 exception);
cristyacd2ed22011-08-30 01:44:23 +00002605 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002606 break;
cristyc57f6942010-11-12 01:47:39 +00002607 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002608 {
cristy4c08aed2011-07-01 19:47:50 +00002609 if (GetPixelAlpha(image,q) != TransparentAlpha)
2610 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002611 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002612 }
cristyc57f6942010-11-12 01:47:39 +00002613 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002614 break;
2615 }
cristyc57f6942010-11-12 01:47:39 +00002616 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002617 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2618 if (draw_info->stencil == TransparentStencil)
cristy39172402012-03-30 13:04:39 +00002619 (void) CompositeImage(image,draw_image,CopyAlphaCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002620 (ssize_t) x,(ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002621 else
2622 {
cristyb0a657e2012-08-29 00:45:37 +00002623 alpha_trait=image->alpha_trait;
cristy39172402012-03-30 13:04:39 +00002624 (void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002625 (ssize_t) x,(ssize_t) y,exception);
cristyb0a657e2012-08-29 00:45:37 +00002626 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002627 }
2628 draw_image=DestroyImage(draw_image);
2629 return(MagickTrue);
2630}
2631
2632/*
2633%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2634% %
2635% %
2636% %
2637% X E r r o r %
2638% %
2639% %
2640% %
2641%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2642%
2643% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2644% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002645% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2646% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002647%
2648% The format of the XError function is:
2649%
cristybcbda3f2011-09-03 13:01:22 +00002650% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002651%
2652% A description of each parameter follows:
2653%
2654% o display: Specifies a pointer to the Display structure; returned from
2655% XOpenDisplay.
2656%
2657% o error: Specifies the error event.
2658%
2659*/
2660
2661#if defined(__cplusplus) || defined(c_plusplus)
2662extern "C" {
2663#endif
2664
2665MagickExport int XError(Display *display,XErrorEvent *error)
2666{
2667 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2668 assert(display != (Display *) NULL);
2669 assert(error != (XErrorEvent *) NULL);
2670 xerror_alert=MagickTrue;
2671 switch (error->request_code)
2672 {
2673 case X_GetGeometry:
2674 {
2675 if ((int) error->error_code == BadDrawable)
2676 return(MagickFalse);
2677 break;
2678 }
2679 case X_GetWindowAttributes:
2680 case X_QueryTree:
2681 {
2682 if ((int) error->error_code == BadWindow)
2683 return(MagickFalse);
2684 break;
2685 }
2686 case X_QueryColors:
2687 {
2688 if ((int) error->error_code == BadValue)
2689 return(MagickFalse);
2690 break;
2691 }
2692 }
2693 return(MagickTrue);
2694}
2695
2696#if defined(__cplusplus) || defined(c_plusplus)
2697}
2698#endif
2699
2700/*
2701%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2702% %
2703% %
2704% %
2705% X F r e e R e s o u r c e s %
2706% %
2707% %
2708% %
2709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2710%
2711% XFreeResources() frees X11 resources.
2712%
2713% The format of the XFreeResources method is:
2714%
2715% void XFreeResources(Display *display,XVisualInfo *visual_info,
2716% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2717% XResourceInfo *resource_info,XWindowInfo *window_info)
2718% resource_info,window_info)
2719%
2720% A description of each parameter follows:
2721%
2722% o display: Specifies a connection to an X server; returned from
2723% XOpenDisplay.
2724%
2725% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2726% returned from XGetVisualInfo.
2727%
2728% o map_info: If map_type is specified, this structure is initialized
2729% with info from the Standard Colormap.
2730%
2731% o pixel: Specifies a pointer to a XPixelInfo structure.
2732%
2733% o font_info: Specifies a pointer to a XFontStruct structure.
2734%
2735% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2736%
2737% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2738%
2739*/
cristybcbda3f2011-09-03 13:01:22 +00002740MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002741 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2742 XResourceInfo *resource_info,XWindowInfo *window_info)
2743{
2744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2745 assert(display != (Display *) NULL);
2746 assert(resource_info != (XResourceInfo *) NULL);
2747 if (window_info != (XWindowInfo *) NULL)
2748 {
2749 /*
2750 Free X image.
2751 */
2752 if (window_info->ximage != (XImage *) NULL)
2753 XDestroyImage(window_info->ximage);
2754 if (window_info->id != (Window) NULL)
2755 {
2756 /*
2757 Free destroy window and free cursors.
2758 */
2759 if (window_info->id != XRootWindow(display,visual_info->screen))
2760 (void) XDestroyWindow(display,window_info->id);
2761 if (window_info->annotate_context != (GC) NULL)
2762 (void) XFreeGC(display,window_info->annotate_context);
2763 if (window_info->highlight_context != (GC) NULL)
2764 (void) XFreeGC(display,window_info->highlight_context);
2765 if (window_info->widget_context != (GC) NULL)
2766 (void) XFreeGC(display,window_info->widget_context);
2767 if (window_info->cursor != (Cursor) NULL)
2768 (void) XFreeCursor(display,window_info->cursor);
2769 window_info->cursor=(Cursor) NULL;
2770 if (window_info->busy_cursor != (Cursor) NULL)
2771 (void) XFreeCursor(display,window_info->busy_cursor);
2772 window_info->busy_cursor=(Cursor) NULL;
2773 }
2774 }
2775 /*
2776 Free font.
2777 */
2778 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002779 {
2780 (void) XFreeFont(display,font_info);
2781 font_info=(XFontStruct *) NULL;
2782 }
cristy3ed852e2009-09-05 21:47:34 +00002783 if (map_info != (XStandardColormap *) NULL)
2784 {
2785 /*
2786 Free X Standard Colormap.
2787 */
2788 if (resource_info->map_type == (char *) NULL)
2789 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2790 (void) XFree((void *) map_info);
2791 }
2792 /*
2793 Free X visual info.
2794 */
2795 if (visual_info != (XVisualInfo *) NULL)
2796 (void) XFree((void *) visual_info);
2797 if (resource_info->close_server != MagickFalse)
2798 (void) XCloseDisplay(display);
2799}
2800
2801/*
2802%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2803% %
2804% %
2805% %
2806% X F r e e S t a n d a r d C o l o r m a p %
2807% %
2808% %
2809% %
2810%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2811%
2812% XFreeStandardColormap() frees an X11 colormap.
2813%
2814% The format of the XFreeStandardColormap method is:
2815%
2816% void XFreeStandardColormap(Display *display,
2817% const XVisualInfo *visual_info,XStandardColormap *map_info,
2818% XPixelInfo *pixel)
2819%
2820% A description of each parameter follows:
2821%
2822% o display: Specifies a connection to an X server; returned from
2823% XOpenDisplay.
2824%
2825% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2826% returned from XGetVisualInfo.
2827%
2828% o map_info: If map_type is specified, this structure is initialized
2829% with info from the Standard Colormap.
2830%
2831% o pixel: Specifies a pointer to a XPixelInfo structure.
2832%
2833*/
cristybcbda3f2011-09-03 13:01:22 +00002834MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002835 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2836{
2837 /*
2838 Free colormap.
2839 */
2840 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2841 assert(display != (Display *) NULL);
2842 assert(visual_info != (XVisualInfo *) NULL);
2843 assert(map_info != (XStandardColormap *) NULL);
2844 (void) XFlush(display);
2845 if (map_info->colormap != (Colormap) NULL)
2846 {
2847 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2848 (void) XFreeColormap(display,map_info->colormap);
2849 else
2850 if (pixel != (XPixelInfo *) NULL)
2851 if ((visual_info->klass != TrueColor) &&
2852 (visual_info->klass != DirectColor))
2853 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2854 (int) pixel->colors,0);
2855 }
2856 map_info->colormap=(Colormap) NULL;
2857 if (pixel != (XPixelInfo *) NULL)
2858 {
cristyf2faecf2010-05-28 19:19:36 +00002859 if (pixel->pixels != (unsigned long *) NULL)
2860 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2861 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002862 }
2863}
2864
2865/*
2866%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2867% %
2868% %
2869% %
2870% X G e t A n n o t a t e I n f o %
2871% %
2872% %
2873% %
2874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2875%
2876% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2877%
2878% The format of the XGetAnnotateInfo method is:
2879%
2880% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2881%
2882% A description of each parameter follows:
2883%
2884% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2885%
2886*/
cristybcbda3f2011-09-03 13:01:22 +00002887MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002888{
2889 /*
2890 Initialize annotate structure.
2891 */
2892 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2893 assert(annotate_info != (XAnnotateInfo *) NULL);
2894 annotate_info->x=0;
2895 annotate_info->y=0;
2896 annotate_info->width=0;
2897 annotate_info->height=0;
2898 annotate_info->stencil=ForegroundStencil;
2899 annotate_info->degrees=0.0;
2900 annotate_info->font_info=(XFontStruct *) NULL;
2901 annotate_info->text=(char *) NULL;
2902 *annotate_info->geometry='\0';
2903 annotate_info->previous=(XAnnotateInfo *) NULL;
2904 annotate_info->next=(XAnnotateInfo *) NULL;
2905 (void) XSupportsLocale();
2906 (void) XSetLocaleModifiers("");
2907}
2908
2909/*
2910%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2911% %
2912% %
2913% %
2914% X G e t M a p I n f o %
2915% %
2916% %
2917% %
2918%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2919%
2920% XGetMapInfo() initializes the XStandardColormap structure.
2921%
2922% The format of the XStandardColormap method is:
2923%
2924% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2925% XStandardColormap *map_info)
2926%
2927% A description of each parameter follows:
2928%
2929% o colormap: Specifies the ID of the X server colormap.
2930%
2931% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2932% returned from XGetVisualInfo.
2933%
2934% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2935%
2936*/
cristybcbda3f2011-09-03 13:01:22 +00002937MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002938 const Colormap colormap,XStandardColormap *map_info)
2939{
2940 /*
2941 Initialize map info.
2942 */
2943 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2944 assert(visual_info != (XVisualInfo *) NULL);
2945 assert(map_info != (XStandardColormap *) NULL);
2946 map_info->colormap=colormap;
2947 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002948 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002949 if (map_info->red_max != 0)
2950 while ((map_info->red_max & 0x01) == 0)
2951 {
2952 map_info->red_max>>=1;
2953 map_info->red_mult<<=1;
2954 }
2955 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002956 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002957 if (map_info->green_max != 0)
2958 while ((map_info->green_max & 0x01) == 0)
2959 {
2960 map_info->green_max>>=1;
2961 map_info->green_mult<<=1;
2962 }
2963 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002964 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002965 if (map_info->blue_max != 0)
2966 while ((map_info->blue_max & 0x01) == 0)
2967 {
2968 map_info->blue_max>>=1;
2969 map_info->blue_mult<<=1;
2970 }
2971 map_info->base_pixel=0;
2972}
2973
2974/*
2975%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2976% %
2977% %
2978% %
2979% X G e t P i x e l I n f o %
2980% %
2981% %
2982% %
2983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2984%
cristy101ab702011-10-13 13:06:32 +00002985% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00002986%
cristy4c08aed2011-07-01 19:47:50 +00002987% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00002988%
cristy4c08aed2011-07-01 19:47:50 +00002989% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002990% const XStandardColormap *map_info,const XResourceInfo *resource_info,
2991% Image *image,XPixelInfo *pixel)
2992% pixel)
2993%
2994% A description of each parameter follows:
2995%
2996% o display: Specifies a connection to an X server; returned from
2997% XOpenDisplay.
2998%
2999% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3000% returned from XGetVisualInfo.
3001%
3002% o map_info: If map_type is specified, this structure is initialized
3003% with info from the Standard Colormap.
3004%
3005% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3006%
3007% o image: the image.
3008%
3009% o pixel: Specifies a pointer to a XPixelInfo structure.
3010%
3011*/
cristybcbda3f2011-09-03 13:01:22 +00003012MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003013 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3014 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3015{
3016 static const char
3017 *PenColors[MaxNumberPens]=
3018 {
3019 "#000000000000", /* black */
3020 "#00000000ffff", /* blue */
3021 "#0000ffffffff", /* cyan */
3022 "#0000ffff0000", /* green */
3023 "#bdbdbdbdbdbd", /* gray */
3024 "#ffff00000000", /* red */
3025 "#ffff0000ffff", /* magenta */
3026 "#ffffffff0000", /* yellow */
3027 "#ffffffffffff", /* white */
3028 "#bdbdbdbdbdbd", /* gray */
3029 "#bdbdbdbdbdbd" /* gray */
3030 };
3031
3032 Colormap
3033 colormap;
3034
cristybcdf5672012-05-24 22:58:54 +00003035 extern const char
3036 BorderColor[],
3037 ForegroundColor[];
3038
cristybb503372010-05-27 20:51:26 +00003039 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003040 i;
3041
3042 Status
3043 status;
3044
3045 unsigned int
3046 packets;
3047
3048 /*
3049 Initialize pixel info.
3050 */
3051 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3052 assert(display != (Display *) NULL);
3053 assert(visual_info != (XVisualInfo *) NULL);
3054 assert(map_info != (XStandardColormap *) NULL);
3055 assert(resource_info != (XResourceInfo *) NULL);
3056 assert(pixel != (XPixelInfo *) NULL);
3057 pixel->colors=0;
3058 if (image != (Image *) NULL)
3059 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003060 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003061 packets=(unsigned int)
3062 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003063 if (pixel->pixels != (unsigned long *) NULL)
3064 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3065 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristyc3306092015-02-28 22:57:28 +00003066 sizeof(*pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003067 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003068 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3069 image->filename);
3070 /*
3071 Set foreground color.
3072 */
3073 colormap=map_info->colormap;
3074 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3075 &pixel->foreground_color);
3076 status=XParseColor(display,colormap,resource_info->foreground_color,
3077 &pixel->foreground_color);
3078 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003079 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003080 resource_info->foreground_color);
3081 pixel->foreground_color.pixel=
3082 XStandardPixel(map_info,&pixel->foreground_color);
3083 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3084 /*
3085 Set background color.
3086 */
3087 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3088 status=XParseColor(display,colormap,resource_info->background_color,
3089 &pixel->background_color);
3090 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003091 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003092 resource_info->background_color);
3093 pixel->background_color.pixel=
3094 XStandardPixel(map_info,&pixel->background_color);
3095 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3096 /*
3097 Set border color.
3098 */
3099 (void) XParseColor(display,colormap,(char *) BorderColor,
3100 &pixel->border_color);
3101 status=XParseColor(display,colormap,resource_info->border_color,
3102 &pixel->border_color);
3103 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003104 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003105 resource_info->border_color);
3106 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3107 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3108 /*
3109 Set matte color.
3110 */
3111 pixel->matte_color=pixel->background_color;
3112 if (resource_info->matte_color != (char *) NULL)
3113 {
3114 /*
3115 Matte color is specified as a X resource or command line argument.
3116 */
3117 status=XParseColor(display,colormap,resource_info->matte_color,
3118 &pixel->matte_color);
3119 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003120 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003121 resource_info->matte_color);
3122 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3123 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3124 }
3125 /*
3126 Set highlight color.
3127 */
cristy5467fcf2014-05-18 17:20:55 +00003128 pixel->highlight_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003129 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3130 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
cristy5467fcf2014-05-18 17:20:55 +00003131 pixel->highlight_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003132 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3133 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
cristy5467fcf2014-05-18 17:20:55 +00003134 pixel->highlight_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003135 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3136 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
cristy5467fcf2014-05-18 17:20:55 +00003137 pixel->highlight_color.pixel=XStandardPixel(map_info,&pixel->highlight_color);
cristy3ed852e2009-09-05 21:47:34 +00003138 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3139 /*
3140 Set shadow color.
3141 */
cristya19f1d72012-08-07 18:24:38 +00003142 pixel->shadow_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003143 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003144 pixel->shadow_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003145 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003146 pixel->shadow_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003147 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3148 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3149 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3150 /*
3151 Set depth color.
3152 */
cristya19f1d72012-08-07 18:24:38 +00003153 pixel->depth_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003154 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003155 pixel->depth_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003156 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003157 pixel->depth_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003158 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3159 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3160 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3161 /*
3162 Set trough color.
3163 */
cristya19f1d72012-08-07 18:24:38 +00003164 pixel->trough_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003165 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003166 pixel->trough_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003167 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003168 pixel->trough_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003169 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3170 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3171 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3172 /*
3173 Set pen color.
3174 */
3175 for (i=0; i < MaxNumberPens; i++)
3176 {
3177 (void) XParseColor(display,colormap,(char *) PenColors[i],
3178 &pixel->pen_colors[i]);
3179 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3180 &pixel->pen_colors[i]);
3181 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00003182 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
cristy3ed852e2009-09-05 21:47:34 +00003183 resource_info->pen_colors[i]);
3184 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3185 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3186 }
3187 pixel->box_color=pixel->background_color;
3188 pixel->pen_color=pixel->foreground_color;
3189 pixel->box_index=0;
3190 pixel->pen_index=1;
3191 if (image != (Image *) NULL)
3192 {
3193 if ((resource_info->gamma_correct != MagickFalse) &&
3194 (image->gamma != 0.0))
3195 {
3196 GeometryInfo
3197 geometry_info;
3198
3199 MagickStatusType
3200 flags;
3201
3202 /*
3203 Initialize map relative to display and image gamma.
3204 */
3205 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3206 red_gamma=geometry_info.rho;
3207 green_gamma=geometry_info.sigma;
3208 if ((flags & SigmaValue) == 0)
3209 green_gamma=red_gamma;
3210 blue_gamma=geometry_info.xi;
3211 if ((flags & XiValue) == 0)
3212 blue_gamma=red_gamma;
3213 red_gamma*=image->gamma;
3214 green_gamma*=image->gamma;
3215 blue_gamma*=image->gamma;
3216 }
3217 if (image->storage_class == PseudoClass)
3218 {
3219 /*
3220 Initialize pixel array for images of type PseudoClass.
3221 */
cristybb503372010-05-27 20:51:26 +00003222 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003223 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003224 for (i=0; i < MaxNumberPens; i++)
3225 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3226 pixel->colors+=MaxNumberPens;
3227 }
3228 }
3229}
3230
3231/*
3232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3233% %
3234% %
3235% %
3236% X G e t R e s o u r c e C l a s s %
3237% %
3238% %
3239% %
3240%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3241%
3242% XGetResourceClass() queries the X server for the specified resource name or
3243% class. If the resource name or class is not defined in the database, the
3244% supplied default value is returned.
3245%
3246% The format of the XGetResourceClass method is:
3247%
3248% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3249% const char *keyword,char *resource_default)
3250%
3251% A description of each parameter follows:
3252%
3253% o database: Specifies a resource database; returned from
3254% XrmGetStringDatabase.
3255%
3256% o client_name: Specifies the application name used to retrieve resource
3257% info from the X server database.
3258%
3259% o keyword: Specifies the keyword of the value being retrieved.
3260%
3261% o resource_default: Specifies the default value to return if the query
3262% fails to find the specified keyword/class.
3263%
3264*/
3265MagickExport char *XGetResourceClass(XrmDatabase database,
3266 const char *client_name,const char *keyword,char *resource_default)
3267{
3268 char
cristy151b66d2015-04-15 10:50:31 +00003269 resource_class[MagickPathExtent],
3270 resource_name[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00003271
3272 static char
3273 *resource_type;
3274
3275 Status
3276 status;
3277
3278 XrmValue
3279 resource_value;
3280
3281 if (database == (XrmDatabase) NULL)
3282 return(resource_default);
3283 *resource_name='\0';
3284 *resource_class='\0';
3285 if (keyword != (char *) NULL)
3286 {
3287 int
3288 c,
3289 k;
3290
3291 /*
3292 Initialize resource keyword and class.
3293 */
cristy151b66d2015-04-15 10:50:31 +00003294 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003295 client_name,keyword);
3296 c=(int) (*client_name);
3297 if ((c >= XK_a) && (c <= XK_z))
3298 c-=(XK_a-XK_A);
3299 else
3300 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3301 c-=(XK_agrave-XK_Agrave);
3302 else
3303 if ((c >= XK_oslash) && (c <= XK_thorn))
3304 c-=(XK_oslash-XK_Ooblique);
3305 k=(int) (*keyword);
3306 if ((k >= XK_a) && (k <= XK_z))
3307 k-=(XK_a-XK_A);
3308 else
3309 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3310 k-=(XK_agrave-XK_Agrave);
3311 else
3312 if ((k >= XK_oslash) && (k <= XK_thorn))
3313 k-=(XK_oslash-XK_Ooblique);
cristy151b66d2015-04-15 10:50:31 +00003314 (void) FormatLocaleString(resource_class,MagickPathExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003315 client_name+1,k,keyword+1);
3316 }
3317 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3318 &resource_value);
3319 if (status == False)
3320 return(resource_default);
3321 return(resource_value.addr);
3322}
3323
3324/*
3325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3326% %
3327% %
3328% %
3329% X G e t R e s o u r c e D a t a b a s e %
3330% %
3331% %
3332% %
3333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3334%
3335% XGetResourceDatabase() creates a new resource database and initializes it.
3336%
3337% The format of the XGetResourceDatabase method is:
3338%
3339% XrmDatabase XGetResourceDatabase(Display *display,
3340% const char *client_name)
3341%
3342% A description of each parameter follows:
3343%
3344% o database: XGetResourceDatabase() returns the database after it is
3345% initialized.
3346%
3347% o display: Specifies a connection to an X server; returned from
3348% XOpenDisplay.
3349%
3350% o client_name: Specifies the application name used to retrieve resource
3351% info from the X server database.
3352%
3353*/
3354MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3355 const char *client_name)
3356{
3357 char
cristy151b66d2015-04-15 10:50:31 +00003358 filename[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00003359
3360 int
3361 c;
3362
3363 register const char
3364 *p;
3365
3366 XrmDatabase
3367 resource_database,
3368 server_database;
3369
3370 if (display == (Display *) NULL)
3371 return((XrmDatabase) NULL);
3372 assert(client_name != (char *) NULL);
3373 /*
3374 Initialize resource database.
3375 */
3376 XrmInitialize();
3377 (void) XGetDefault(display,(char *) client_name,"dummy");
3378 resource_database=XrmGetDatabase(display);
3379 /*
3380 Combine application database.
3381 */
3382 if (client_name != (char *) NULL)
3383 {
3384 /*
3385 Get basename of client.
3386 */
3387 p=client_name+(strlen(client_name)-1);
3388 while ((p > client_name) && (*p != '/'))
3389 p--;
3390 if (*p == '/')
3391 client_name=p+1;
3392 }
3393 c=(int) (*client_name);
3394 if ((c >= XK_a) && (c <= XK_z))
3395 c-=(XK_a-XK_A);
3396 else
3397 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3398 c-=(XK_agrave-XK_Agrave);
3399 else
3400 if ((c >= XK_oslash) && (c <= XK_thorn))
3401 c-=(XK_oslash-XK_Ooblique);
3402#if defined(X11_APPLICATION_PATH)
cristy151b66d2015-04-15 10:50:31 +00003403 (void) FormatLocaleString(filename,MagickPathExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003404 X11_APPLICATION_PATH,c,client_name+1);
3405 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3406#endif
3407 if (XResourceManagerString(display) != (char *) NULL)
3408 {
3409 /*
3410 Combine server database.
3411 */
3412 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3413 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3414 }
3415 /*
3416 Merge user preferences database.
3417 */
3418#if defined(X11_PREFERENCES_PATH)
cristy151b66d2015-04-15 10:50:31 +00003419 (void) FormatLocaleString(filename,MagickPathExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003420 X11_PREFERENCES_PATH,client_name);
3421 ExpandFilename(filename);
3422 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3423#endif
3424 return(resource_database);
3425}
3426
3427/*
3428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3429% %
3430% %
3431% %
3432% X G e t R e s o u r c e I n f o %
3433% %
3434% %
3435% %
3436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3437%
3438% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3439%
3440% The format of the XGetResourceInfo method is:
3441%
3442% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3443% const char *client_name,XResourceInfo *resource_info)
3444%
3445% A description of each parameter follows:
3446%
3447% o image_info: the image info.
3448%
3449% o database: Specifies a resource database; returned from
3450% XrmGetStringDatabase.
3451%
3452% o client_name: Specifies the application name used to retrieve
3453% resource info from the X server database.
3454%
3455% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3456%
3457*/
3458MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3459 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3460{
3461 char
cristy00976d82011-02-20 20:31:28 +00003462 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003463 *resource_value;
3464
cristybcdf5672012-05-24 22:58:54 +00003465 extern const char
3466 BorderColor[],
3467 ForegroundColor[];
3468
cristy3ed852e2009-09-05 21:47:34 +00003469 /*
3470 Initialize resource info fields.
3471 */
3472 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3473 assert(resource_info != (XResourceInfo *) NULL);
3474 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3475 resource_info->resource_database=database;
3476 resource_info->image_info=(ImageInfo *) image_info;
3477 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3478 XMagickProgressMonitor,(void *) NULL);
3479 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3480 resource_info->close_server=MagickTrue;
3481 resource_info->client_name=AcquireString(client_name);
3482 resource_value=XGetResourceClass(database,client_name,"backdrop",
3483 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003484 resource_info->backdrop=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003485 resource_info->background_color=XGetResourceInstance(database,client_name,
3486 "background",(char *) "#d6d6d6d6d6d6");
3487 resource_info->border_color=XGetResourceInstance(database,client_name,
3488 "borderColor",BorderColor);
3489 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3490 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003491 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3492 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003493 resource_value=XGetResourceClass(database,client_name,"colormap",
3494 (char *) "shared");
3495 resource_info->colormap=UndefinedColormap;
3496 if (LocaleCompare("private",resource_value) == 0)
3497 resource_info->colormap=PrivateColormap;
3498 if (LocaleCompare("shared",resource_value) == 0)
3499 resource_info->colormap=SharedColormap;
3500 if (resource_info->colormap == UndefinedColormap)
cristyc38fbf52013-11-03 13:55:54 +00003501 ThrowXWindowException(OptionError,"UnrecognizedColormapType",
cristy3ed852e2009-09-05 21:47:34 +00003502 resource_value);
3503 resource_value=XGetResourceClass(database,client_name,
3504 "colorRecovery",(char *) "False");
anthony6f201312012-03-30 04:08:15 +00003505 resource_info->color_recovery=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003506 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3507 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003508 resource_info->confirm_exit=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003509 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3510 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003511 resource_info->confirm_edit=IsStringTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003512 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003513 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003514 resource_info->display_gamma=XGetResourceClass(database,client_name,
3515 "displayGamma",(char *) "2.2");
3516 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3517 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003518 resource_info->display_warnings=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003519 resource_info->font=XGetResourceClass(database,client_name,"font",
3520 (char *) NULL);
3521 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3522 resource_info->font);
3523 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3524 (char *) "fixed");
3525 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3526 (char *) "variable");
3527 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3528 (char *) "5x8");
3529 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3530 (char *) "6x10");
3531 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3532 (char *) "7x13bold");
3533 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3534 (char *) "8x13bold");
3535 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3536 (char *) "9x15bold");
3537 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3538 (char *) "10x20");
3539 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3540 (char *) "12x24");
3541 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3542 (char *) "fixed");
3543 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3544 (char *) "fixed");
3545 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3546 "foreground",ForegroundColor);
3547 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
cristy8bc259b2012-06-21 23:53:15 +00003548 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003549 resource_info->gamma_correct=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003550 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3551 client_name,"geometry",(char *) NULL));
3552 resource_value=XGetResourceClass(database,client_name,"gravity",
3553 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003554 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003555 MagickFalse,resource_value);
cristy151b66d2015-04-15 10:50:31 +00003556 directory=getcwd(resource_info->home_directory,MagickPathExtent);
cristy00976d82011-02-20 20:31:28 +00003557 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003558 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3559 "iconGeometry",(char *) NULL);
3560 resource_value=XGetResourceClass(database,client_name,"iconic",
3561 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003562 resource_info->iconic=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003563 resource_value=XGetResourceClass(database,client_name,"immutable",
3564 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3565 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003566 resource_info->immutable=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003567 resource_value=XGetResourceClass(database,client_name,"magnify",
3568 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003569 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003570 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3571 (char *) NULL);
3572 resource_info->matte_color=XGetResourceInstance(database,client_name,
3573 "mattecolor",(char *) NULL);
3574 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3575 "name",(char *) NULL));
3576 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3577 (char *) "black");
3578 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3579 (char *) "blue");
3580 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3581 (char *) "cyan");
3582 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3583 (char *) "green");
3584 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3585 (char *) "gray");
3586 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3587 (char *) "red");
3588 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3589 (char *) "magenta");
3590 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3591 (char *) "yellow");
3592 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3593 (char *) "white");
3594 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3595 (char *) "gray");
3596 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3597 (char *) "gray");
3598 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003599 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003600 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003601 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003602 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3603 "font",(char *) "fixed");
3604 resource_info->text_font=XGetResourceClass(database,client_name,
3605 "textFontList",resource_info->text_font);
3606 resource_info->title=XGetResourceClass(database,client_name,"title",
3607 (char *) NULL);
3608 resource_value=XGetResourceClass(database,client_name,"undoCache",
cristy92befbd2012-09-16 14:08:12 +00003609 (char *) "256");
cristye27293e2009-12-18 02:53:20 +00003610 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003611 resource_value=XGetResourceClass(database,client_name,"update",
3612 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003613 resource_info->update=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003614 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3615 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003616 resource_info->use_pixmap=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003617 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3618 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003619 resource_info->use_shared_memory=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003620 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3621 (char *) NULL);
3622 resource_info->window_group=XGetResourceClass(database,client_name,
3623 "windowGroup",(char *) NULL);
3624 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3625 (char *) NULL);
3626 resource_info->write_filename=XGetResourceClass(database,client_name,
3627 "writeFilename",(char *) NULL);
3628}
3629
3630/*
3631%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3632% %
3633% %
3634% %
3635% X G e t R e s o u r c e I n s t a n c e %
3636% %
3637% %
3638% %
3639%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3640%
3641% XGetResourceInstance() queries the X server for the specified resource name.
3642% If the resource name is not defined in the database, the supplied default
3643% value is returned.
3644%
3645% The format of the XGetResourceInstance method is:
3646%
3647% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3648% const char *keyword,const char *resource_default)
3649%
3650% A description of each parameter follows:
3651%
3652% o database: Specifies a resource database; returned from
3653% XrmGetStringDatabase.
3654%
3655% o client_name: Specifies the application name used to retrieve
3656% resource info from the X server database.
3657%
3658% o keyword: Specifies the keyword of the value being retrieved.
3659%
3660% o resource_default: Specifies the default value to return if the query
3661% fails to find the specified keyword/class.
3662%
3663*/
3664MagickExport char *XGetResourceInstance(XrmDatabase database,
3665 const char *client_name,const char *keyword,const char *resource_default)
3666{
3667 char
3668 *resource_type,
cristy151b66d2015-04-15 10:50:31 +00003669 resource_name[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00003670
3671 Status
3672 status;
3673
3674 XrmValue
3675 resource_value;
3676
3677 if (database == (XrmDatabase) NULL)
3678 return((char *) resource_default);
3679 *resource_name='\0';
3680 if (keyword != (char *) NULL)
cristy151b66d2015-04-15 10:50:31 +00003681 (void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003682 keyword);
3683 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3684 &resource_value);
3685 if (status == False)
3686 return((char *) resource_default);
3687 return(resource_value.addr);
3688}
3689
3690/*
3691%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3692% %
3693% %
3694% %
3695% X G e t S c r e e n D e n s i t y %
3696% %
3697% %
3698% %
3699%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3700%
3701% XGetScreenDensity() returns the density of the X server screen in
3702% dots-per-inch.
3703%
3704% The format of the XGetScreenDensity method is:
3705%
3706% char *XGetScreenDensity(Display *display)
3707%
3708% A description of each parameter follows:
3709%
3710% o density: XGetScreenDensity() returns the density of the X screen in
3711% dots-per-inch.
3712%
3713% o display: Specifies a connection to an X server; returned from
3714% XOpenDisplay.
3715%
3716*/
3717MagickExport char *XGetScreenDensity(Display *display)
3718{
3719 char
cristy151b66d2015-04-15 10:50:31 +00003720 density[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00003721
3722 double
3723 x_density,
3724 y_density;
3725
3726 /*
3727 Set density as determined by screen size.
3728 */
3729 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3730 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3731 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3732 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristy151b66d2015-04-15 10:50:31 +00003733 (void) FormatLocaleString(density,MagickPathExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003734 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003735 return(GetPageGeometry(density));
3736}
3737
3738/*
3739%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3740% %
3741% %
3742% %
3743+ X G e t S u b w i n d o w %
3744% %
3745% %
3746% %
3747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3748%
3749% XGetSubwindow() returns the subwindow of a window chosen the user with the
3750% pointer and a button press.
3751%
3752% The format of the XGetSubwindow method is:
3753%
3754% Window XGetSubwindow(Display *display,Window window,int x,int y)
3755%
3756% A description of each parameter follows:
3757%
3758% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3759% otherwise the subwindow is returned.
3760%
3761% o display: Specifies a connection to an X server; returned from
3762% XOpenDisplay.
3763%
3764% o window: Specifies a pointer to a Window.
3765%
3766% o x: the x coordinate of the pointer relative to the origin of the
3767% window.
3768%
3769% o y: the y coordinate of the pointer relative to the origin of the
3770% window.
3771%
cristy3ed852e2009-09-05 21:47:34 +00003772*/
3773static Window XGetSubwindow(Display *display,Window window,int x,int y)
3774{
3775 int
3776 x_offset,
3777 y_offset;
3778
3779 Status
3780 status;
3781
3782 Window
3783 source_window,
3784 target_window;
3785
3786 assert(display != (Display *) NULL);
3787 source_window=XRootWindow(display,XDefaultScreen(display));
3788 if (window == (Window) NULL)
3789 return(source_window);
3790 target_window=window;
3791 for ( ; ; )
3792 {
3793 status=XTranslateCoordinates(display,source_window,window,x,y,
3794 &x_offset,&y_offset,&target_window);
3795 if (status != True)
3796 break;
3797 if (target_window == (Window) NULL)
3798 break;
3799 source_window=window;
3800 window=target_window;
3801 x=x_offset;
3802 y=y_offset;
3803 }
3804 if (target_window == (Window) NULL)
3805 target_window=window;
3806 return(target_window);
3807}
3808
3809/*
3810%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3811% %
3812% %
3813% %
3814% X G e t W i n d o w C o l o r %
3815% %
3816% %
3817% %
3818%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3819%
3820% XGetWindowColor() returns the color of a pixel interactively chosen from the
3821% X server.
3822%
3823% The format of the XGetWindowColor method is:
3824%
3825% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003826% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003827%
3828% A description of each parameter follows:
3829%
3830% o display: Specifies a connection to an X server; returned from
3831% XOpenDisplay.
3832%
3833% o windows: Specifies a pointer to a XWindows structure.
3834%
3835% o name: the name of the color if found in the X Color Database is
3836% returned in this character string.
3837%
cristy6710d842011-10-20 23:23:00 +00003838% o exception: return any errors or warnings in this structure.
3839%
cristy3ed852e2009-09-05 21:47:34 +00003840*/
cristybcbda3f2011-09-03 13:01:22 +00003841MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003842 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003843{
3844 int
3845 x,
3846 y;
3847
cristy101ab702011-10-13 13:06:32 +00003848 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003849 pixel;
3850
3851 RectangleInfo
3852 crop_info;
3853
3854 Status
3855 status;
3856
3857 Window
3858 child,
3859 client_window,
3860 root_window,
3861 target_window;
3862
3863 XColor
3864 color;
3865
3866 XImage
3867 *ximage;
3868
3869 XWindowAttributes
3870 window_attributes;
3871
3872 /*
3873 Choose a pixel from the X server.
3874 */
3875 assert(display != (Display *) NULL);
3876 assert(name != (char *) NULL);
3877 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3878 *name='\0';
3879 target_window=XSelectWindow(display,&crop_info);
3880 if (target_window == (Window) NULL)
3881 return(MagickFalse);
3882 root_window=XRootWindow(display,XDefaultScreen(display));
3883 client_window=target_window;
3884 if (target_window != root_window)
3885 {
3886 unsigned int
3887 d;
3888
3889 /*
3890 Get client window.
3891 */
3892 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3893 if (status != False)
3894 {
3895 client_window=XClientWindow(display,target_window);
3896 target_window=client_window;
3897 }
3898 }
3899 /*
3900 Verify window is viewable.
3901 */
3902 status=XGetWindowAttributes(display,target_window,&window_attributes);
3903 if ((status == False) || (window_attributes.map_state != IsViewable))
3904 return(MagickFalse);
3905 /*
3906 Get window X image.
3907 */
3908 (void) XTranslateCoordinates(display,root_window,target_window,
3909 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3910 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3911 if (ximage == (XImage *) NULL)
3912 return(MagickFalse);
3913 color.pixel=XGetPixel(ximage,0,0);
3914 XDestroyImage(ximage);
3915 /*
3916 Match color against the color database.
3917 */
3918 (void) XQueryColor(display,window_attributes.colormap,&color);
cristye42f6582012-02-11 17:59:50 +00003919 pixel.red=(double) ScaleShortToQuantum(color.red);
3920 pixel.green=(double) ScaleShortToQuantum(color.green);
3921 pixel.blue=(double) ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003922 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003923 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003924 exception);
cristy3ed852e2009-09-05 21:47:34 +00003925 return(MagickTrue);
3926}
3927
3928/*
3929%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3930% %
3931% %
3932% %
3933+ X G e t W i n d o w I m a g e %
3934% %
3935% %
3936% %
3937%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3938%
3939% XGetWindowImage() reads an image from the target X window and returns it.
3940% XGetWindowImage() optionally descends the window hierarchy and overlays the
3941% target image with each child image in an optimized fashion. Any child
3942% window that have the same visual, colormap, and are contained by its parent
3943% are exempted.
3944%
3945% The format of the XGetWindowImage method is:
3946%
3947% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003948% const unsigned int borders,const unsigned int level,
3949% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003950%
3951% A description of each parameter follows:
3952%
3953% o display: Specifies a connection to an X server; returned from
3954% XOpenDisplay.
3955%
3956% o window: Specifies the window to obtain the image from.
3957%
3958% o borders: Specifies whether borders pixels are to be saved with
3959% the image.
3960%
3961% o level: Specifies an unsigned integer representing the level of
3962% decent in the window hierarchy. This value must be zero or one on
3963% the initial call to XGetWindowImage. A value of zero returns after
3964% one call. A value of one causes the function to descend the window
3965% hierarchy and overlay the target image with each subwindow image.
3966%
cristy6710d842011-10-20 23:23:00 +00003967% o exception: return any errors or warnings in this structure.
3968%
cristy3ed852e2009-09-05 21:47:34 +00003969*/
3970static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003971 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003972{
3973 typedef struct _ColormapInfo
3974 {
3975 Colormap
3976 colormap;
3977
3978 XColor
3979 *colors;
3980
3981 struct _ColormapInfo
3982 *next;
3983 } ColormapInfo;
3984
3985 typedef struct _WindowInfo
3986 {
3987 Window
3988 window,
3989 parent;
3990
3991 Visual
3992 *visual;
3993
3994 Colormap
3995 colormap;
3996
3997 XSegment
3998 bounds;
3999
4000 RectangleInfo
4001 crop_info;
4002 } WindowInfo;
4003
cristy3ed852e2009-09-05 21:47:34 +00004004 int
4005 display_height,
4006 display_width,
4007 id,
4008 x_offset,
4009 y_offset;
4010
cristy4c08aed2011-07-01 19:47:50 +00004011 Quantum
4012 index;
4013
cristy3ed852e2009-09-05 21:47:34 +00004014 RectangleInfo
4015 crop_info;
4016
cristy3ed852e2009-09-05 21:47:34 +00004017 register int
4018 i;
4019
4020 static ColormapInfo
4021 *colormap_info = (ColormapInfo *) NULL;
4022
4023 static int
4024 max_windows = 0,
4025 number_windows = 0;
4026
4027 static WindowInfo
4028 *window_info;
4029
4030 Status
4031 status;
4032
4033 Window
4034 child,
4035 root_window;
4036
4037 XWindowAttributes
4038 window_attributes;
4039
4040 /*
4041 Verify window is viewable.
4042 */
4043 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4044 assert(display != (Display *) NULL);
4045 status=XGetWindowAttributes(display,window,&window_attributes);
4046 if ((status == False) || (window_attributes.map_state != IsViewable))
4047 return((Image *) NULL);
4048 /*
4049 Cropping rectangle is relative to root window.
4050 */
4051 root_window=XRootWindow(display,XDefaultScreen(display));
4052 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4053 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004054 crop_info.x=(ssize_t) x_offset;
4055 crop_info.y=(ssize_t) y_offset;
4056 crop_info.width=(size_t) window_attributes.width;
4057 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004058 if (borders != MagickFalse)
4059 {
4060 /*
4061 Include border in image.
4062 */
cristybb503372010-05-27 20:51:26 +00004063 crop_info.x-=(ssize_t) window_attributes.border_width;
4064 crop_info.y-=(ssize_t) window_attributes.border_width;
4065 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4066 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004067 }
4068 /*
4069 Crop to root window.
4070 */
4071 if (crop_info.x < 0)
4072 {
4073 crop_info.width+=crop_info.x;
4074 crop_info.x=0;
4075 }
4076 if (crop_info.y < 0)
4077 {
4078 crop_info.height+=crop_info.y;
4079 crop_info.y=0;
4080 }
4081 display_width=XDisplayWidth(display,XDefaultScreen(display));
4082 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004083 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004084 display_height=XDisplayHeight(display,XDefaultScreen(display));
4085 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004086 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004087 /*
4088 Initialize window info attributes.
4089 */
4090 if (number_windows >= max_windows)
4091 {
4092 /*
4093 Allocate or resize window info buffer.
4094 */
4095 max_windows+=1024;
4096 if (window_info == (WindowInfo *) NULL)
4097 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4098 sizeof(*window_info));
4099 else
4100 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4101 max_windows,sizeof(*window_info));
4102 }
4103 if (window_info == (WindowInfo *) NULL)
4104 {
cristyc38fbf52013-11-03 13:55:54 +00004105 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed","...");
cristy3ed852e2009-09-05 21:47:34 +00004106 return((Image *) NULL);
4107 }
4108 id=number_windows++;
4109 window_info[id].window=window;
4110 window_info[id].visual=window_attributes.visual;
4111 window_info[id].colormap=window_attributes.colormap;
4112 window_info[id].bounds.x1=(short) crop_info.x;
4113 window_info[id].bounds.y1=(short) crop_info.y;
4114 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4115 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4116 crop_info.x-=x_offset;
4117 crop_info.y-=y_offset;
4118 window_info[id].crop_info=crop_info;
4119 if (level != 0)
4120 {
4121 unsigned int
4122 number_children;
4123
4124 Window
4125 *children;
4126
4127 /*
4128 Descend the window hierarchy.
4129 */
4130 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4131 &children,&number_children);
4132 for (i=0; i < id; i++)
4133 if ((window_info[i].window == window_info[id].parent) &&
4134 (window_info[i].visual == window_info[id].visual) &&
4135 (window_info[i].colormap == window_info[id].colormap))
4136 {
cristy64057b02013-01-11 00:09:58 +00004137 if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
4138 (window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
4139 (window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
4140 (window_info[id].bounds.y2 > window_info[i].bounds.y2))
cristy3ed852e2009-09-05 21:47:34 +00004141 {
4142 /*
4143 Eliminate windows not circumscribed by their parent.
4144 */
4145 number_windows--;
4146 break;
4147 }
4148 }
4149 if ((status == True) && (number_children != 0))
4150 {
4151 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004152 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4153 exception);
cristy3ed852e2009-09-05 21:47:34 +00004154 (void) XFree((void *) children);
4155 }
4156 }
4157 if (level <= 1)
4158 {
cristyc57f6942010-11-12 01:47:39 +00004159 CacheView
4160 *composite_view;
4161
cristy3ed852e2009-09-05 21:47:34 +00004162 ColormapInfo
4163 *next;
4164
cristy3ed852e2009-09-05 21:47:34 +00004165 Image
4166 *composite_image,
4167 *image;
4168
4169 int
4170 y;
4171
4172 MagickBooleanType
4173 import;
4174
4175 register int
4176 j,
4177 x;
4178
cristy4c08aed2011-07-01 19:47:50 +00004179 register Quantum
dirk05d2ff72015-11-18 23:13:43 +01004180 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004181
cristybb503372010-05-27 20:51:26 +00004182 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004183 pixel;
4184
4185 unsigned int
4186 number_colors;
4187
4188 XColor
4189 *colors;
4190
4191 XImage
4192 *ximage;
4193
4194 /*
4195 Get X image for each window in the list.
4196 */
4197 image=NewImageList();
4198 for (id=0; id < number_windows; id++)
4199 {
4200 /*
4201 Does target window intersect top level window?
4202 */
cristy088af952013-08-19 18:34:20 +00004203 import=((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
cristy3ed852e2009-09-05 21:47:34 +00004204 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4205 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4206 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4207 MagickTrue : MagickFalse;
4208 /*
4209 Is target window contained by another window with the same colormap?
4210 */
4211 for (j=0; j < id; j++)
4212 if ((window_info[id].visual == window_info[j].visual) &&
4213 (window_info[id].colormap == window_info[j].colormap))
4214 {
cristy64057b02013-01-11 00:09:58 +00004215 if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
4216 (window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
4217 (window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
4218 (window_info[id].bounds.y2 <= window_info[j].bounds.y2))
cristy088af952013-08-19 18:34:20 +00004219 import=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00004220 }
cristy3ed852e2009-09-05 21:47:34 +00004221 if (import == MagickFalse)
4222 continue;
4223 /*
4224 Get X image.
4225 */
4226 ximage=XGetImage(display,window_info[id].window,(int)
4227 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4228 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4229 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4230 if (ximage == (XImage *) NULL)
4231 continue;
4232 /*
4233 Initialize window colormap.
4234 */
4235 number_colors=0;
4236 colors=(XColor *) NULL;
4237 if (window_info[id].colormap != (Colormap) NULL)
4238 {
4239 ColormapInfo
4240 *p;
4241
4242 /*
4243 Search colormap list for window colormap.
4244 */
4245 number_colors=(unsigned int) window_info[id].visual->map_entries;
4246 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4247 if (p->colormap == window_info[id].colormap)
4248 break;
4249 if (p == (ColormapInfo *) NULL)
4250 {
4251 /*
4252 Get the window colormap.
4253 */
4254 colors=(XColor *) AcquireQuantumMemory(number_colors,
4255 sizeof(*colors));
4256 if (colors == (XColor *) NULL)
4257 {
4258 XDestroyImage(ximage);
4259 return((Image *) NULL);
4260 }
4261 if ((window_info[id].visual->klass != DirectColor) &&
4262 (window_info[id].visual->klass != TrueColor))
4263 for (i=0; i < (int) number_colors; i++)
4264 {
cristybb503372010-05-27 20:51:26 +00004265 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004266 colors[i].pad='\0';
4267 }
4268 else
4269 {
cristybb503372010-05-27 20:51:26 +00004270 size_t
cristy3ed852e2009-09-05 21:47:34 +00004271 blue,
4272 blue_bit,
4273 green,
4274 green_bit,
4275 red,
4276 red_bit;
4277
4278 /*
4279 DirectColor or TrueColor visual.
4280 */
4281 red=0;
4282 green=0;
4283 blue=0;
4284 red_bit=window_info[id].visual->red_mask &
4285 (~(window_info[id].visual->red_mask)+1);
4286 green_bit=window_info[id].visual->green_mask &
4287 (~(window_info[id].visual->green_mask)+1);
4288 blue_bit=window_info[id].visual->blue_mask &
4289 (~(window_info[id].visual->blue_mask)+1);
4290 for (i=0; i < (int) number_colors; i++)
4291 {
cristy8891f9c2010-06-04 23:32:17 +00004292 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004293 colors[i].pad='\0';
4294 red+=red_bit;
4295 if (red > window_info[id].visual->red_mask)
4296 red=0;
4297 green+=green_bit;
4298 if (green > window_info[id].visual->green_mask)
4299 green=0;
4300 blue+=blue_bit;
4301 if (blue > window_info[id].visual->blue_mask)
4302 blue=0;
4303 }
4304 }
4305 (void) XQueryColors(display,window_info[id].colormap,colors,
4306 (int) number_colors);
4307 /*
4308 Append colormap to colormap list.
4309 */
cristy73bd4a52010-10-05 11:24:23 +00004310 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004311 if (p == (ColormapInfo *) NULL)
4312 return((Image *) NULL);
4313 p->colormap=window_info[id].colormap;
4314 p->colors=colors;
4315 p->next=colormap_info;
4316 colormap_info=p;
4317 }
4318 colors=p->colors;
4319 }
4320 /*
4321 Allocate image structure.
4322 */
cristy6710d842011-10-20 23:23:00 +00004323 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004324 if (composite_image == (Image *) NULL)
4325 {
4326 XDestroyImage(ximage);
4327 return((Image *) NULL);
4328 }
4329 /*
4330 Convert X image to MIFF format.
4331 */
4332 if ((window_info[id].visual->klass != TrueColor) &&
4333 (window_info[id].visual->klass != DirectColor))
4334 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004335 composite_image->columns=(size_t) ximage->width;
4336 composite_image->rows=(size_t) ximage->height;
cristy46ff2672012-12-14 15:32:26 +00004337 composite_view=AcquireAuthenticCacheView(composite_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00004338 switch (composite_image->storage_class)
4339 {
4340 case DirectClass:
4341 default:
4342 {
cristybb503372010-05-27 20:51:26 +00004343 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004344 color,
4345 index;
4346
cristybb503372010-05-27 20:51:26 +00004347 size_t
cristy3ed852e2009-09-05 21:47:34 +00004348 blue_mask,
4349 blue_shift,
4350 green_mask,
4351 green_shift,
4352 red_mask,
4353 red_shift;
4354
4355 /*
4356 Determine shift and mask for red, green, and blue.
4357 */
4358 red_mask=window_info[id].visual->red_mask;
4359 red_shift=0;
4360 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4361 {
4362 red_mask>>=1;
4363 red_shift++;
4364 }
4365 green_mask=window_info[id].visual->green_mask;
4366 green_shift=0;
4367 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4368 {
4369 green_mask>>=1;
4370 green_shift++;
4371 }
4372 blue_mask=window_info[id].visual->blue_mask;
4373 blue_shift=0;
4374 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4375 {
4376 blue_mask>>=1;
4377 blue_shift++;
4378 }
4379 /*
4380 Convert X image to DirectClass packets.
4381 */
4382 if ((number_colors != 0) &&
4383 (window_info[id].visual->klass == DirectColor))
4384 for (y=0; y < (int) composite_image->rows; y++)
4385 {
cristyc57f6942010-11-12 01:47:39 +00004386 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004387 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004388 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004389 break;
4390 for (x=0; x < (int) composite_image->columns; x++)
4391 {
4392 pixel=XGetPixel(ximage,x,y);
4393 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004394 SetPixelRed(composite_image,
4395 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004396 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004397 SetPixelGreen(composite_image,
4398 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004399 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004400 SetPixelBlue(composite_image,
4401 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004402 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004403 }
cristy0b1a7972011-10-22 22:17:02 +00004404 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4405 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004406 break;
4407 }
4408 else
4409 for (y=0; y < (int) composite_image->rows; y++)
4410 {
cristyc57f6942010-11-12 01:47:39 +00004411 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004412 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004413 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004414 break;
4415 for (x=0; x < (int) composite_image->columns; x++)
4416 {
4417 pixel=XGetPixel(ximage,x,y);
4418 color=(pixel >> red_shift) & red_mask;
cristy9a7df362014-01-14 15:03:18 +00004419 if (red_mask != 0)
4420 color=(65535UL*color)/red_mask;
4421 SetPixelRed(composite_image,ScaleShortToQuantum(
4422 (unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004423 color=(pixel >> green_shift) & green_mask;
cristy9a7df362014-01-14 15:03:18 +00004424 if (green_mask != 0)
4425 color=(65535UL*color)/green_mask;
4426 SetPixelGreen(composite_image,ScaleShortToQuantum(
4427 (unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004428 color=(pixel >> blue_shift) & blue_mask;
cristy9a7df362014-01-14 15:03:18 +00004429 if (blue_mask != 0)
4430 color=(65535UL*color)/blue_mask;
4431 SetPixelBlue(composite_image,ScaleShortToQuantum(
4432 (unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004433 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004434 }
cristy0b1a7972011-10-22 22:17:02 +00004435 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4436 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004437 break;
4438 }
4439 break;
4440 }
4441 case PseudoClass:
4442 {
4443 /*
4444 Create colormap.
4445 */
cristy0b1a7972011-10-22 22:17:02 +00004446 status=AcquireImageColormap(composite_image,number_colors,
4447 exception);
4448 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004449 {
4450 XDestroyImage(ximage);
4451 composite_image=DestroyImage(composite_image);
4452 return((Image *) NULL);
4453 }
4454 for (i=0; i < (int) composite_image->colors; i++)
4455 {
cristye42f6582012-02-11 17:59:50 +00004456 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004457 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004458 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004459 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004460 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004461 ScaleShortToQuantum(colors[i].blue);
4462 }
4463 /*
4464 Convert X image to PseudoClass packets.
4465 */
4466 for (y=0; y < (int) composite_image->rows; y++)
4467 {
cristyc57f6942010-11-12 01:47:39 +00004468 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4469 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004470 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004471 break;
cristy3ed852e2009-09-05 21:47:34 +00004472 for (x=0; x < (int) composite_image->columns; x++)
4473 {
cristy4c08aed2011-07-01 19:47:50 +00004474 index=(Quantum) XGetPixel(ximage,x,y);
4475 SetPixelIndex(composite_image,index,q);
cristy11a06d32015-01-04 12:03:27 +00004476 SetPixelViaPixelInfo(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004477 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004478 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004479 }
cristy0b1a7972011-10-22 22:17:02 +00004480 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4481 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004482 break;
4483 }
4484 break;
4485 }
4486 }
cristyc57f6942010-11-12 01:47:39 +00004487 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004488 XDestroyImage(ximage);
4489 if (image == (Image *) NULL)
4490 {
4491 image=composite_image;
4492 continue;
4493 }
4494 /*
4495 Composite any children in back-to-front order.
4496 */
4497 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4498 &x_offset,&y_offset,&child);
4499 x_offset-=(int) crop_info.x;
4500 if (x_offset < 0)
4501 x_offset=0;
4502 y_offset-=(int) crop_info.y;
4503 if (y_offset < 0)
4504 y_offset=0;
cristy39172402012-03-30 13:04:39 +00004505 (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00004506 (ssize_t) x_offset,(ssize_t) y_offset,exception);
cristy5f257b22012-03-07 00:27:29 +00004507 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004508 }
4509 /*
4510 Relinquish resources.
4511 */
4512 while (colormap_info != (ColormapInfo *) NULL)
4513 {
4514 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004515 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4516 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004517 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4518 colormap_info=next;
4519 }
4520 /*
4521 Relinquish resources and restore initial state.
4522 */
4523 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4524 max_windows=0;
4525 number_windows=0;
4526 colormap_info=(ColormapInfo *) NULL;
4527 return(image);
4528 }
4529 return((Image *) NULL);
4530}
4531
4532/*
4533%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4534% %
4535% %
4536% %
4537% X G e t W i n d o w I n f o %
4538% %
4539% %
4540% %
4541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4542%
4543% XGetWindowInfo() initializes the XWindowInfo structure.
4544%
4545% The format of the XGetWindowInfo method is:
4546%
4547% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4548% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4549% XResourceInfo *resource_info,XWindowInfo *window)
4550% resource_info,window)
4551%
4552% A description of each parameter follows:
4553%
4554% o display: Specifies a connection to an X server; returned from
4555% XOpenDisplay.
4556%
4557% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4558% returned from XGetVisualInfo.
4559%
4560% o map_info: If map_type is specified, this structure is initialized
4561% with info from the Standard Colormap.
4562%
4563% o pixel: Specifies a pointer to a XPixelInfo structure.
4564%
4565% o font_info: Specifies a pointer to a XFontStruct structure.
4566%
4567% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4568%
4569*/
cristybcbda3f2011-09-03 13:01:22 +00004570MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004571 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4572 XResourceInfo *resource_info,XWindowInfo *window)
4573{
4574 /*
4575 Initialize window info.
4576 */
4577 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4578 assert(display != (Display *) NULL);
4579 assert(visual_info != (XVisualInfo *) NULL);
4580 assert(map_info != (XStandardColormap *) NULL);
4581 assert(pixel != (XPixelInfo *) NULL);
4582 assert(resource_info != (XResourceInfo *) NULL);
4583 assert(window != (XWindowInfo *) NULL);
4584 if (window->id != (Window) NULL)
4585 {
4586 if (window->cursor != (Cursor) NULL)
4587 (void) XFreeCursor(display,window->cursor);
4588 if (window->busy_cursor != (Cursor) NULL)
4589 (void) XFreeCursor(display,window->busy_cursor);
4590 if (window->highlight_stipple != (Pixmap) NULL)
4591 (void) XFreePixmap(display,window->highlight_stipple);
4592 if (window->shadow_stipple != (Pixmap) NULL)
4593 (void) XFreePixmap(display,window->shadow_stipple);
4594 if (window->name == (char *) NULL)
4595 window->name=AcquireString("");
4596 if (window->icon_name == (char *) NULL)
4597 window->icon_name=AcquireString("");
4598 }
4599 else
4600 {
4601 /*
4602 Initialize these attributes just once.
4603 */
4604 window->id=(Window) NULL;
4605 if (window->name == (char *) NULL)
4606 window->name=AcquireString("");
4607 if (window->icon_name == (char *) NULL)
4608 window->icon_name=AcquireString("");
4609 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4610 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4611 window->ximage=(XImage *) NULL;
4612 window->matte_image=(XImage *) NULL;
4613 window->pixmap=(Pixmap) NULL;
4614 window->matte_pixmap=(Pixmap) NULL;
4615 window->mapped=MagickFalse;
4616 window->stasis=MagickFalse;
4617 window->shared_memory=MagickTrue;
4618 window->segment_info=(void *) NULL;
4619#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4620 {
4621 XShmSegmentInfo
4622 *segment_info;
4623
4624 if (window->segment_info == (void *) NULL)
4625 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4626 segment_info=(XShmSegmentInfo *) window->segment_info;
4627 segment_info[0].shmid=(-1);
4628 segment_info[0].shmaddr=(char *) NULL;
4629 segment_info[1].shmid=(-1);
4630 segment_info[1].shmaddr=(char *) NULL;
4631 }
4632#endif
4633 }
4634 /*
4635 Initialize these attributes every time function is called.
4636 */
4637 window->screen=visual_info->screen;
4638 window->root=XRootWindow(display,visual_info->screen);
4639 window->visual=visual_info->visual;
4640 window->storage_class=(unsigned int) visual_info->klass;
4641 window->depth=(unsigned int) visual_info->depth;
4642 window->visual_info=visual_info;
4643 window->map_info=map_info;
4644 window->pixel_info=pixel;
4645 window->font_info=font_info;
4646 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4647 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4648 window->geometry=(char *) NULL;
4649 window->icon_geometry=(char *) NULL;
4650 if (resource_info->icon_geometry != (char *) NULL)
4651 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4652 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004653 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004654 window->width=1;
4655 window->height=1;
4656 window->min_width=1;
4657 window->min_height=1;
4658 window->width_inc=1;
4659 window->height_inc=1;
4660 window->border_width=resource_info->border_width;
4661 window->annotate_context=pixel->annotate_context;
4662 window->highlight_context=pixel->highlight_context;
4663 window->widget_context=pixel->widget_context;
4664 window->shadow_stipple=(Pixmap) NULL;
4665 window->highlight_stipple=(Pixmap) NULL;
4666 window->use_pixmap=MagickTrue;
4667 window->immutable=MagickFalse;
4668 window->shape=MagickFalse;
4669 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004670 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004671 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4672 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4673 window->attributes.background_pixel=pixel->background_color.pixel;
4674 window->attributes.background_pixmap=(Pixmap) NULL;
4675 window->attributes.bit_gravity=ForgetGravity;
4676 window->attributes.backing_store=WhenMapped;
4677 window->attributes.save_under=MagickTrue;
4678 window->attributes.border_pixel=pixel->border_color.pixel;
4679 window->attributes.colormap=map_info->colormap;
4680 window->attributes.cursor=window->cursor;
4681 window->attributes.do_not_propagate_mask=NoEventMask;
4682 window->attributes.event_mask=NoEventMask;
4683 window->attributes.override_redirect=MagickFalse;
4684 window->attributes.win_gravity=NorthWestGravity;
4685 window->orphan=MagickFalse;
4686}
4687
4688/*
4689%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4690% %
4691% %
4692% %
4693% X H i g h l i g h t E l l i p s e %
4694% %
4695% %
4696% %
4697%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4698%
4699% XHighlightEllipse() puts a border on the X server around a region defined by
4700% highlight_info.
4701%
4702% The format of the XHighlightEllipse method is:
4703%
4704% void XHighlightEllipse(Display *display,Window window,
4705% GC annotate_context,const RectangleInfo *highlight_info)
4706%
4707% A description of each parameter follows:
4708%
4709% o display: Specifies a connection to an X server; returned from
4710% XOpenDisplay.
4711%
4712% o window: Specifies a pointer to a Window structure.
4713%
4714% o annotate_context: Specifies a pointer to a GC structure.
4715%
4716% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4717% contains the extents of any highlighting rectangle.
4718%
4719*/
cristybcbda3f2011-09-03 13:01:22 +00004720MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004721 GC annotate_context,const RectangleInfo *highlight_info)
4722{
4723 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4724 assert(display != (Display *) NULL);
4725 assert(window != (Window) NULL);
4726 assert(annotate_context != (GC) NULL);
4727 assert(highlight_info != (RectangleInfo *) NULL);
4728 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4729 return;
4730 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4731 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4732 (unsigned int) highlight_info->height-1,0,360*64);
4733 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4734 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4735 (unsigned int) highlight_info->height-3,0,360*64);
4736}
4737
4738/*
4739%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4740% %
4741% %
4742% %
4743% X H i g h l i g h t L i n e %
4744% %
4745% %
4746% %
4747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4748%
4749% XHighlightLine() puts a border on the X server around a region defined by
4750% highlight_info.
4751%
4752% The format of the XHighlightLine method is:
4753%
4754% void XHighlightLine(Display *display,Window window,GC annotate_context,
4755% const XSegment *highlight_info)
4756%
4757% A description of each parameter follows:
4758%
4759% o display: Specifies a connection to an X server; returned from
4760% XOpenDisplay.
4761%
4762% o window: Specifies a pointer to a Window structure.
4763%
4764% o annotate_context: Specifies a pointer to a GC structure.
4765%
4766% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4767% contains the extents of any highlighting rectangle.
4768%
4769*/
cristybcbda3f2011-09-03 13:01:22 +00004770MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004771 GC annotate_context,const XSegment *highlight_info)
4772{
4773 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4774 assert(display != (Display *) NULL);
4775 assert(window != (Window) NULL);
4776 assert(annotate_context != (GC) NULL);
4777 assert(highlight_info != (XSegment *) NULL);
4778 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4779 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4780}
4781
4782/*
4783%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4784% %
4785% %
4786% %
4787% X H i g h l i g h t R e c t a n g l e %
4788% %
4789% %
4790% %
4791%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4792%
4793% XHighlightRectangle() puts a border on the X server around a region defined
4794% by highlight_info.
4795%
4796% The format of the XHighlightRectangle method is:
4797%
4798% void XHighlightRectangle(Display *display,Window window,
4799% GC annotate_context,const RectangleInfo *highlight_info)
4800%
4801% A description of each parameter follows:
4802%
4803% o display: Specifies a connection to an X server; returned from
4804% XOpenDisplay.
4805%
4806% o window: Specifies a pointer to a Window structure.
4807%
4808% o annotate_context: Specifies a pointer to a GC structure.
4809%
4810% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4811% contains the extents of any highlighting rectangle.
4812%
4813*/
cristybcbda3f2011-09-03 13:01:22 +00004814MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004815 GC annotate_context,const RectangleInfo *highlight_info)
4816{
4817 assert(display != (Display *) NULL);
4818 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4819 assert(window != (Window) NULL);
4820 assert(annotate_context != (GC) NULL);
4821 assert(highlight_info != (RectangleInfo *) NULL);
4822 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4823 return;
4824 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4825 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4826 (unsigned int) highlight_info->height-1);
4827 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4828 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4829 (unsigned int) highlight_info->height-3);
4830}
4831
4832/*
4833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4834% %
4835% %
4836% %
4837% X I m p o r t I m a g e %
4838% %
4839% %
4840% %
4841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4842%
4843% XImportImage() reads an image from an X window.
4844%
4845% The format of the XImportImage method is:
4846%
cristy6710d842011-10-20 23:23:00 +00004847% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4848% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004849%
4850% A description of each parameter follows:
4851%
4852% o image_info: the image info.
4853%
4854% o ximage_info: Specifies a pointer to an XImportInfo structure.
4855%
cristy6710d842011-10-20 23:23:00 +00004856% o exception: return any errors or warnings in this structure.
4857%
cristy3ed852e2009-09-05 21:47:34 +00004858*/
4859MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004860 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004861{
4862 Colormap
4863 *colormaps;
4864
4865 Display
4866 *display;
4867
4868 Image
4869 *image;
4870
4871 int
4872 number_colormaps,
4873 number_windows,
4874 x;
4875
4876 RectangleInfo
4877 crop_info;
4878
4879 Status
4880 status;
4881
4882 Window
4883 *children,
4884 client,
4885 prior_target,
4886 root,
4887 target;
4888
4889 XTextProperty
4890 window_name;
4891
4892 /*
4893 Open X server connection.
4894 */
4895 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00004896 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00004897 if (image_info->debug != MagickFalse)
4898 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4899 image_info->filename);
4900 assert(ximage_info != (XImportInfo *) NULL);
4901 display=XOpenDisplay(image_info->server_name);
4902 if (display == (Display *) NULL)
4903 {
cristyc38fbf52013-11-03 13:55:54 +00004904 ThrowXWindowException(XServerError,"UnableToOpenXServer",
cristy3ed852e2009-09-05 21:47:34 +00004905 XDisplayName(image_info->server_name));
4906 return((Image *) NULL);
4907 }
4908 /*
4909 Set our forgiving exception handler.
4910 */
4911 (void) XSetErrorHandler(XError);
4912 /*
4913 Select target window.
4914 */
4915 crop_info.x=0;
4916 crop_info.y=0;
4917 crop_info.width=0;
4918 crop_info.height=0;
4919 root=XRootWindow(display,XDefaultScreen(display));
4920 target=(Window) NULL;
cristy6f008fd2014-05-25 23:27:26 +00004921 if (*image_info->filename != '\0')
cristy3ed852e2009-09-05 21:47:34 +00004922 {
4923 if (LocaleCompare(image_info->filename,"root") == 0)
4924 target=root;
4925 else
4926 {
4927 /*
4928 Select window by ID or name.
4929 */
cristy02e64f82013-11-14 16:20:04 +00004930 if (isdigit((int) ((unsigned char) *image_info->filename)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00004931 target=XWindowByID(display,root,(Window)
4932 strtol(image_info->filename,(char **) NULL,0));
4933 if (target == (Window) NULL)
4934 target=XWindowByName(display,root,image_info->filename);
4935 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004936 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
4937 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00004938 }
4939 }
4940 /*
4941 If target window is not defined, interactively select one.
4942 */
4943 prior_target=target;
4944 if (target == (Window) NULL)
4945 target=XSelectWindow(display,&crop_info);
4946 if (target == (Window) NULL)
cristyc38fbf52013-11-03 13:55:54 +00004947 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00004948 image_info->filename);
4949 client=target; /* obsolete */
4950 if (target != root)
4951 {
4952 unsigned int
4953 d;
4954
4955 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4956 if (status != False)
4957 {
4958 for ( ; ; )
4959 {
4960 Window
4961 parent;
4962
4963 /*
4964 Find window manager frame.
4965 */
4966 status=XQueryTree(display,target,&root,&parent,&children,&d);
4967 if ((status != False) && (children != (Window *) NULL))
4968 (void) XFree((char *) children);
4969 if ((status == False) || (parent == (Window) NULL) ||
4970 (parent == root))
4971 break;
4972 target=parent;
4973 }
4974 /*
4975 Get client window.
4976 */
4977 client=XClientWindow(display,target);
4978 if (ximage_info->frame == MagickFalse)
4979 target=client;
4980 if ((ximage_info->frame == MagickFalse) &&
4981 (prior_target != MagickFalse))
4982 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00004983 }
4984 }
4985 if (ximage_info->screen)
4986 {
4987 int
4988 y;
4989
4990 Window
4991 child;
4992
4993 XWindowAttributes
4994 window_attributes;
4995
4996 /*
4997 Obtain window image directly from screen.
4998 */
4999 status=XGetWindowAttributes(display,target,&window_attributes);
5000 if (status == False)
5001 {
cristyc38fbf52013-11-03 13:55:54 +00005002 ThrowXWindowException(XServerError,"UnableToReadXWindowAttributes",
5003 image_info->filename);
cristy3ed852e2009-09-05 21:47:34 +00005004 (void) XCloseDisplay(display);
5005 return((Image *) NULL);
5006 }
5007 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005008 crop_info.x=(ssize_t) x;
5009 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005010 crop_info.width=(size_t) window_attributes.width;
5011 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005012 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005013 {
5014 /*
5015 Include border in image.
5016 */
5017 crop_info.x-=window_attributes.border_width;
5018 crop_info.y-=window_attributes.border_width;
5019 crop_info.width+=window_attributes.border_width << 1;
5020 crop_info.height+=window_attributes.border_width << 1;
5021 }
5022 target=root;
5023 }
5024 /*
5025 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5026 */
5027 number_windows=0;
5028 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5029 if ((status == True) && (number_windows > 0))
5030 {
5031 ximage_info->descend=MagickTrue;
5032 (void) XFree ((char *) children);
5033 }
5034 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5035 if (number_colormaps > 0)
5036 {
5037 if (number_colormaps > 1)
5038 ximage_info->descend=MagickTrue;
5039 (void) XFree((char *) colormaps);
5040 }
5041 /*
5042 Alert the user not to alter the screen.
5043 */
5044 if (ximage_info->silent == MagickFalse)
5045 (void) XBell(display,0);
5046 /*
5047 Get image by window id.
5048 */
5049 (void) XGrabServer(display);
5050 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005051 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005052 (void) XUngrabServer(display);
5053 if (image == (Image *) NULL)
cristyc38fbf52013-11-03 13:55:54 +00005054 ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
cristy3ed852e2009-09-05 21:47:34 +00005055 image_info->filename)
5056 else
5057 {
5058 (void) CopyMagickString(image->filename,image_info->filename,
cristy151b66d2015-04-15 10:50:31 +00005059 MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00005060 if ((crop_info.width != 0) && (crop_info.height != 0))
5061 {
5062 Image
5063 *clone_image,
5064 *crop_image;
5065
5066 /*
5067 Crop image as defined by the cropping rectangle.
5068 */
cristy6710d842011-10-20 23:23:00 +00005069 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005070 if (clone_image != (Image *) NULL)
5071 {
cristy6710d842011-10-20 23:23:00 +00005072 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005073 if (crop_image != (Image *) NULL)
5074 {
5075 image=DestroyImage(image);
5076 image=crop_image;
5077 }
5078 }
5079 }
5080 status=XGetWMName(display,target,&window_name);
5081 if (status == True)
5082 {
cristy8418c7e2014-05-18 18:38:26 +00005083 if (*image_info->filename == '\0')
cristy3ed852e2009-09-05 21:47:34 +00005084 (void) CopyMagickString(image->filename,(char *) window_name.value,
5085 (size_t) window_name.nitems+1);
5086 (void) XFree((void *) window_name.value);
5087 }
5088 }
5089 if (ximage_info->silent == MagickFalse)
5090 {
5091 /*
5092 Alert the user we're done.
5093 */
5094 (void) XBell(display,0);
5095 (void) XBell(display,0);
5096 }
5097 (void) XCloseDisplay(display);
5098 return(image);
5099}
5100
5101/*
5102%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5103% %
5104% %
5105% %
5106% X I n i t i a l i z e W i n d o w s %
5107% %
5108% %
5109% %
5110%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5111%
5112% XInitializeWindows() initializes the XWindows structure.
5113%
5114% The format of the XInitializeWindows method is:
5115%
5116% XWindows *XInitializeWindows(Display *display,
5117% XResourceInfo *resource_info)
5118%
5119% A description of each parameter follows:
5120%
5121% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5122%
5123% o display: Specifies a connection to an X server; returned from
5124% XOpenDisplay.
5125%
5126% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5127%
5128*/
cristybcbda3f2011-09-03 13:01:22 +00005129MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005130 XResourceInfo *resource_info)
5131{
5132 Window
5133 root_window;
5134
5135 XWindows
5136 *windows;
5137
5138 /*
5139 Allocate windows structure.
5140 */
cristy73bd4a52010-10-05 11:24:23 +00005141 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005142 if (windows == (XWindows *) NULL)
5143 {
5144 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5145 "...");
5146 return((XWindows *) NULL);
5147 }
5148 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5149 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5150 sizeof(*windows->pixel_info));
5151 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5152 sizeof(*windows->icon_pixel));
5153 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5154 sizeof(*windows->icon_resources));
5155 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5156 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5157 (windows->icon_resources == (XResourceInfo *) NULL))
5158 {
5159 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5160 "...");
5161 return((XWindows *) NULL);
5162 }
5163 /*
5164 Initialize windows structure.
5165 */
5166 windows->display=display;
5167 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5168 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5169 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5170 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5171 windows->im_remote_command=
5172 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5173 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5174 windows->im_update_colormap=
5175 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5176 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5177 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5178 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5179 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5180 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005181#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005182 (void) XSynchronize(display,IsWindows95());
5183#endif
5184 if (IsEventLogging())
5185 {
5186 (void) XSynchronize(display,MagickTrue);
5187 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005188 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005189 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5190 (void) LogMagickEvent(X11Event,GetMagickModule(),
5191 " Window Manager: 0x%lx",windows->wm_protocols);
5192 (void) LogMagickEvent(X11Event,GetMagickModule(),
5193 " delete window: 0x%lx",windows->wm_delete_window);
5194 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5195 windows->wm_take_focus);
5196 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5197 windows->im_protocols);
5198 (void) LogMagickEvent(X11Event,GetMagickModule(),
5199 " remote command: 0x%lx",windows->im_remote_command);
5200 (void) LogMagickEvent(X11Event,GetMagickModule(),
5201 " update widget: 0x%lx",windows->im_update_widget);
5202 (void) LogMagickEvent(X11Event,GetMagickModule(),
5203 " update colormap: 0x%lx",windows->im_update_colormap);
5204 (void) LogMagickEvent(X11Event,GetMagickModule(),
5205 " former image: 0x%lx",windows->im_former_image);
5206 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5207 windows->im_next_image);
5208 (void) LogMagickEvent(X11Event,GetMagickModule(),
5209 " retain colors: 0x%lx",windows->im_retain_colors);
5210 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5211 windows->im_exit);
5212 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5213 windows->dnd_protocols);
5214 }
5215 /*
5216 Allocate standard colormap.
5217 */
5218 windows->map_info=XAllocStandardColormap();
5219 windows->icon_map=XAllocStandardColormap();
5220 if ((windows->map_info == (XStandardColormap *) NULL) ||
5221 (windows->icon_map == (XStandardColormap *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005222 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5223 "...");
cristy3ed852e2009-09-05 21:47:34 +00005224 windows->map_info->colormap=(Colormap) NULL;
5225 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005226 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005227 windows->pixel_info->annotate_context=(GC) NULL;
5228 windows->pixel_info->highlight_context=(GC) NULL;
5229 windows->pixel_info->widget_context=(GC) NULL;
5230 windows->font_info=(XFontStruct *) NULL;
5231 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005232 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005233 /*
5234 Allocate visual.
5235 */
5236 *windows->icon_resources=(*resource_info);
5237 windows->icon_resources->visual_type=(char *) "default";
5238 windows->icon_resources->colormap=SharedColormap;
5239 windows->visual_info=
5240 XBestVisualInfo(display,windows->map_info,resource_info);
5241 windows->icon_visual=
5242 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5243 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5244 (windows->icon_visual == (XVisualInfo *) NULL))
5245 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5246 resource_info->visual_type);
5247 if (IsEventLogging())
5248 {
5249 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5250 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5251 windows->visual_info->visualid);
5252 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5253 XVisualClassName(windows->visual_info->klass));
5254 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5255 windows->visual_info->depth);
5256 (void) LogMagickEvent(X11Event,GetMagickModule(),
5257 " size of colormap: %d entries",windows->visual_info->colormap_size);
5258 (void) LogMagickEvent(X11Event,GetMagickModule(),
5259 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5260 windows->visual_info->red_mask,windows->visual_info->green_mask,
5261 windows->visual_info->blue_mask);
5262 (void) LogMagickEvent(X11Event,GetMagickModule(),
5263 " significant bits in color: %d bits",
5264 windows->visual_info->bits_per_rgb);
5265 }
5266 /*
5267 Allocate class and manager hints.
5268 */
5269 windows->class_hints=XAllocClassHint();
5270 windows->manager_hints=XAllocWMHints();
5271 if ((windows->class_hints == (XClassHint *) NULL) ||
5272 (windows->manager_hints == (XWMHints *) NULL))
cristyc38fbf52013-11-03 13:55:54 +00005273 ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
5274 "...");
cristy3ed852e2009-09-05 21:47:34 +00005275 /*
5276 Determine group leader if we have one.
5277 */
5278 root_window=XRootWindow(display,windows->visual_info->screen);
5279 windows->group_leader.id=(Window) NULL;
5280 if (resource_info->window_group != (char *) NULL)
5281 {
cristy02e64f82013-11-14 16:20:04 +00005282 if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00005283 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5284 strtol((char *) resource_info->window_group,(char **) NULL,0));
5285 if (windows->group_leader.id == (Window) NULL)
5286 windows->group_leader.id=
5287 XWindowByName(display,root_window,resource_info->window_group);
5288 }
5289 return(windows);
5290}
5291
5292/*
5293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5294% %
5295% %
5296% %
5297% X M a k e C u r s o r %
5298% %
5299% %
5300% %
5301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5302%
5303% XMakeCursor() creates a crosshairs X11 cursor.
5304%
5305% The format of the XMakeCursor method is:
5306%
5307% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5308% char *background_color,char *foreground_color)
5309%
5310% A description of each parameter follows:
5311%
5312% o display: Specifies a connection to an X server; returned from
5313% XOpenDisplay.
5314%
5315% o window: Specifies the ID of the window for which the cursor is
5316% assigned.
5317%
5318% o colormap: Specifies the ID of the colormap from which the background
5319% and foreground color will be retrieved.
5320%
5321% o background_color: Specifies the color to use for the cursor background.
5322%
5323% o foreground_color: Specifies the color to use for the cursor foreground.
5324%
5325*/
cristybcbda3f2011-09-03 13:01:22 +00005326MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005327 Colormap colormap,char *background_color,char *foreground_color)
5328{
5329#define scope_height 17
5330#define scope_x_hot 8
5331#define scope_y_hot 8
5332#define scope_width 17
5333
5334 static const unsigned char
5335 scope_bits[] =
5336 {
5337 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5338 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5339 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5340 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5341 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5342 },
5343 scope_mask_bits[] =
5344 {
5345 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5346 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5347 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5348 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5349 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5350 };
5351
5352 Cursor
5353 cursor;
5354
5355 Pixmap
5356 mask,
5357 source;
5358
5359 XColor
5360 background,
5361 foreground;
5362
5363 assert(display != (Display *) NULL);
5364 assert(window != (Window) NULL);
5365 assert(colormap != (Colormap) NULL);
5366 assert(background_color != (char *) NULL);
5367 assert(foreground_color != (char *) NULL);
5368 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5369 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5370 scope_height);
5371 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5372 scope_width,scope_height);
5373 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5374 {
cristyc38fbf52013-11-03 13:55:54 +00005375 ThrowXWindowException(XServerError,"UnableToCreatePixmap","...");
cristy3ed852e2009-09-05 21:47:34 +00005376 return((Cursor) NULL);
5377 }
5378 (void) XParseColor(display,colormap,background_color,&background);
5379 (void) XParseColor(display,colormap,foreground_color,&foreground);
5380 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5381 scope_x_hot,scope_y_hot);
5382 (void) XFreePixmap(display,source);
5383 (void) XFreePixmap(display,mask);
5384 return(cursor);
5385}
5386
5387/*
5388%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5389% %
5390% %
5391% %
5392% X M a k e I m a g e %
5393% %
5394% %
5395% %
5396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5397%
5398% XMakeImage() creates an X11 image. If the image size differs from the X11
5399% image size, the image is first resized.
5400%
5401% The format of the XMakeImage method is:
5402%
5403% MagickBooleanType XMakeImage(Display *display,
5404% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005405% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005406%
5407% A description of each parameter follows:
5408%
5409% o display: Specifies a connection to an X server; returned from
5410% XOpenDisplay.
5411%
5412% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5413%
5414% o window: Specifies a pointer to a XWindowInfo structure.
5415%
5416% o image: the image.
5417%
5418% o width: Specifies the width in pixels of the rectangular area to
5419% display.
5420%
5421% o height: Specifies the height in pixels of the rectangular area to
5422% display.
5423%
cristy051718b2011-08-28 22:49:25 +00005424% o exception: return any errors or warnings in this structure.
5425%
cristy3ed852e2009-09-05 21:47:34 +00005426*/
cristybcbda3f2011-09-03 13:01:22 +00005427MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005428 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005429 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005430{
5431#define CheckOverflowException(length,width,height) \
5432 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5433
5434 int
5435 depth,
5436 format;
5437
5438 size_t
5439 length;
5440
5441 XImage
5442 *matte_image,
5443 *ximage;
5444
5445 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5446 assert(display != (Display *) NULL);
5447 assert(resource_info != (XResourceInfo *) NULL);
5448 assert(window != (XWindowInfo *) NULL);
5449 assert(width != 0);
5450 assert(height != 0);
5451 if ((window->width == 0) || (window->height == 0))
5452 return(MagickFalse);
5453 /*
5454 Apply user transforms to the image.
5455 */
5456 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5457 (void) XFlush(display);
5458 depth=(int) window->depth;
5459 if (window->destroy)
5460 window->image=DestroyImage(window->image);
5461 window->image=image;
5462 window->destroy=MagickFalse;
5463 if (window->image != (Image *) NULL)
5464 {
5465 if (window->crop_geometry != (char *) NULL)
5466 {
5467 Image
5468 *crop_image;
5469
5470 RectangleInfo
5471 crop_info;
5472
5473 /*
5474 Crop image.
5475 */
5476 window->image->page.x=0;
5477 window->image->page.y=0;
5478 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005479 &crop_info,exception);
5480 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005481 if (crop_image != (Image *) NULL)
5482 {
5483 if (window->image != image)
5484 window->image=DestroyImage(window->image);
5485 window->image=crop_image;
5486 window->destroy=MagickTrue;
5487 }
5488 }
5489 if ((width != (unsigned int) window->image->columns) ||
5490 (height != (unsigned int) window->image->rows))
5491 {
5492 Image
5493 *resize_image;
5494
5495 /*
5496 Resize image.
5497 */
5498 resize_image=NewImageList();
cristy865489b2013-10-12 01:03:29 +00005499 if ((window->pixel_info->colors == 0) &&
5500 (window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
5501 (window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
5502 resize_image=ResizeImage(window->image,width,height,
5503 image->filter,exception);
cristy3ed852e2009-09-05 21:47:34 +00005504 else
cristy865489b2013-10-12 01:03:29 +00005505 {
5506 if (window->image->storage_class == PseudoClass)
5507 resize_image=SampleImage(window->image,width,height,
5508 exception);
5509 else
5510 resize_image=ThumbnailImage(window->image,width,height,
5511 exception);
5512 }
cristy3ed852e2009-09-05 21:47:34 +00005513 if (resize_image != (Image *) NULL)
5514 {
5515 if (window->image != image)
5516 window->image=DestroyImage(window->image);
5517 window->image=resize_image;
5518 window->destroy=MagickTrue;
5519 }
5520 }
5521 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005522 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005523 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005524 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005525 }
5526 /*
5527 Create X image.
5528 */
5529 ximage=(XImage *) NULL;
5530 format=(depth == 1) ? XYBitmap : ZPixmap;
5531#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5532 if (window->shared_memory != MagickFalse)
5533 {
5534 XShmSegmentInfo
5535 *segment_info;
5536
5537 segment_info=(XShmSegmentInfo *) window->segment_info;
5538 segment_info[1].shmid=(-1);
5539 segment_info[1].shmaddr=(char *) NULL;
5540 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5541 (char *) NULL,&segment_info[1],width,height);
5542 if (ximage == (XImage *) NULL)
5543 window->shared_memory=MagickFalse;
cristy9c5171c2014-05-25 21:26:39 +00005544 else
5545 {
5546 length=(size_t) ximage->bytes_per_line*ximage->height;
5547 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5548 window->shared_memory=MagickFalse;
5549 }
cristy3ed852e2009-09-05 21:47:34 +00005550 if (window->shared_memory != MagickFalse)
5551 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5552 if (window->shared_memory != MagickFalse)
5553 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5554 if (segment_info[1].shmid < 0)
5555 window->shared_memory=MagickFalse;
5556 if (window->shared_memory != MagickFalse)
5557 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5558 else
5559 {
5560 if (ximage != (XImage *) NULL)
5561 XDestroyImage(ximage);
5562 ximage=(XImage *) NULL;
5563 if (segment_info[1].shmaddr)
5564 {
5565 (void) shmdt(segment_info[1].shmaddr);
5566 segment_info[1].shmaddr=(char *) NULL;
5567 }
5568 if (segment_info[1].shmid >= 0)
5569 {
5570 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5571 segment_info[1].shmid=(-1);
5572 }
5573 }
5574 }
5575#endif
5576 /*
5577 Allocate X image pixel data.
5578 */
5579#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5580 if (window->shared_memory)
5581 {
5582 Status
5583 status;
5584
5585 XShmSegmentInfo
5586 *segment_info;
5587
5588 (void) XSync(display,MagickFalse);
5589 xerror_alert=MagickFalse;
5590 segment_info=(XShmSegmentInfo *) window->segment_info;
5591 ximage->data=segment_info[1].shmaddr;
5592 segment_info[1].readOnly=MagickFalse;
5593 status=XShmAttach(display,&segment_info[1]);
5594 if (status != False)
5595 (void) XSync(display,MagickFalse);
5596 if ((status == False) || (xerror_alert != MagickFalse))
5597 {
5598 window->shared_memory=MagickFalse;
5599 if (status != False)
5600 XShmDetach(display,&segment_info[1]);
cristyfa18e622014-05-18 17:37:00 +00005601 ximage->data=NULL;
5602 XDestroyImage(ximage);
5603 ximage=(XImage *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005604 if (segment_info[1].shmid >= 0)
5605 {
5606 if (segment_info[1].shmaddr != NULL)
5607 (void) shmdt(segment_info[1].shmaddr);
5608 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5609 segment_info[1].shmid=(-1);
5610 segment_info[1].shmaddr=(char *) NULL;
5611 }
5612 }
5613 }
5614#endif
5615 if (window->shared_memory == MagickFalse)
5616 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5617 (char *) NULL,width,height,XBitmapPad(display),0);
5618 if (ximage == (XImage *) NULL)
5619 {
5620 /*
5621 Unable to create X image.
5622 */
5623 (void) XCheckDefineCursor(display,window->id,window->cursor);
5624 return(MagickFalse);
5625 }
5626 length=(size_t) ximage->bytes_per_line*ximage->height;
5627 if (IsEventLogging())
5628 {
5629 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5630 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5631 ximage->width,ximage->height);
5632 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5633 ximage->format);
5634 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5635 ximage->byte_order);
5636 (void) LogMagickEvent(X11Event,GetMagickModule(),
5637 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5638 ximage->bitmap_bit_order,ximage->bitmap_pad);
5639 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5640 ximage->depth);
5641 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5642 ximage->bytes_per_line);
5643 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5644 ximage->bits_per_pixel);
5645 (void) LogMagickEvent(X11Event,GetMagickModule(),
5646 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5647 ximage->green_mask,ximage->blue_mask);
5648 }
5649 if (window->shared_memory == MagickFalse)
5650 {
5651 if (ximage->format != XYBitmap)
cristy9aecad62013-04-18 10:37:47 +00005652 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5653 ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005654 else
cristy9aecad62013-04-18 10:37:47 +00005655 ximage->data=(char *) malloc((size_t) ximage->bytes_per_line*
5656 ximage->depth*ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00005657 }
5658 if (ximage->data == (char *) NULL)
5659 {
5660 /*
5661 Unable to allocate pixel data.
5662 */
5663 XDestroyImage(ximage);
5664 ximage=(XImage *) NULL;
5665 (void) XCheckDefineCursor(display,window->id,window->cursor);
5666 return(MagickFalse);
5667 }
5668 if (window->ximage != (XImage *) NULL)
5669 {
5670 /*
5671 Destroy previous X image.
5672 */
5673 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5674#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5675 if (window->segment_info != (XShmSegmentInfo *) NULL)
5676 {
5677 XShmSegmentInfo
5678 *segment_info;
5679
5680 segment_info=(XShmSegmentInfo *) window->segment_info;
5681 if (segment_info[0].shmid >= 0)
5682 {
5683 (void) XSync(display,MagickFalse);
5684 (void) XShmDetach(display,&segment_info[0]);
5685 (void) XSync(display,MagickFalse);
5686 if (segment_info[0].shmaddr != (char *) NULL)
5687 (void) shmdt(segment_info[0].shmaddr);
5688 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5689 segment_info[0].shmid=(-1);
5690 segment_info[0].shmaddr=(char *) NULL;
5691 window->ximage->data=(char *) NULL;
5692 }
5693 }
5694#endif
5695 if (window->ximage->data != (char *) NULL)
5696 free(window->ximage->data);
5697 window->ximage->data=(char *) NULL;
5698 XDestroyImage(window->ximage);
5699 window->ximage=(XImage *) NULL;
5700 }
5701#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5702 if (window->segment_info != (XShmSegmentInfo *) NULL)
5703 {
5704 XShmSegmentInfo
5705 *segment_info;
5706
5707 segment_info=(XShmSegmentInfo *) window->segment_info;
5708 segment_info[0]=segment_info[1];
5709 }
5710#endif
5711 window->ximage=ximage;
5712 matte_image=(XImage *) NULL;
5713 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
cristy17f11b02014-12-20 19:37:04 +00005714 if ((window->image->alpha_trait != UndefinedPixelTrait) &&
cristyc57f6942010-11-12 01:47:39 +00005715 ((int) width <= XDisplayWidth(display,window->screen)) &&
5716 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005717 {
5718 /*
5719 Create matte image.
5720 */
5721 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5722 (char *) NULL,width,height,XBitmapPad(display),0);
5723 if (IsEventLogging())
5724 {
5725 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5726 (void) LogMagickEvent(X11Event,GetMagickModule(),
5727 " width, height: %dx%d",matte_image->width,matte_image->height);
5728 }
5729 if (matte_image != (XImage *) NULL)
5730 {
5731 /*
5732 Allocate matte image pixel data.
5733 */
cristy9aecad62013-04-18 10:37:47 +00005734 matte_image->data=(char *) malloc((size_t)
5735 matte_image->bytes_per_line*matte_image->depth*
5736 matte_image->height);
cristy3ed852e2009-09-05 21:47:34 +00005737 if (matte_image->data == (char *) NULL)
5738 {
5739 XDestroyImage(matte_image);
5740 matte_image=(XImage *) NULL;
5741 }
5742 }
5743 }
5744 if (window->matte_image != (XImage *) NULL)
5745 {
5746 /*
5747 Free matte image.
5748 */
5749 if (window->matte_image->data != (char *) NULL)
5750 free(window->matte_image->data);
5751 window->matte_image->data=(char *) NULL;
5752 XDestroyImage(window->matte_image);
5753 window->matte_image=(XImage *) NULL;
5754 }
5755 window->matte_image=matte_image;
5756 if (window->matte_pixmap != (Pixmap) NULL)
5757 {
5758 (void) XFreePixmap(display,window->matte_pixmap);
5759 window->matte_pixmap=(Pixmap) NULL;
5760#if defined(MAGICKCORE_HAVE_SHAPE)
5761 if (window->shape != MagickFalse)
5762 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5763#endif
5764 }
5765 window->stasis=MagickFalse;
5766 /*
5767 Convert pixels to X image data.
5768 */
5769 if (window->image != (Image *) NULL)
5770 {
5771 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5772 (ximage->bitmap_bit_order == LSBFirst)))
5773 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005774 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005775 else
5776 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005777 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005778 }
5779 if (window->matte_image != (XImage *) NULL)
5780 {
5781 /*
5782 Create matte pixmap.
5783 */
5784 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5785 if (window->matte_pixmap != (Pixmap) NULL)
5786 {
5787 GC
5788 graphics_context;
5789
5790 XGCValues
5791 context_values;
5792
5793 /*
5794 Copy matte image to matte pixmap.
5795 */
cristy4c08aed2011-07-01 19:47:50 +00005796 context_values.background=0;
5797 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005798 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005799 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005800 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5801 window->matte_image,0,0,0,0,width,height);
5802 (void) XFreeGC(display,graphics_context);
5803#if defined(MAGICKCORE_HAVE_SHAPE)
5804 if (window->shape != MagickFalse)
5805 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5806 window->matte_pixmap,ShapeSet);
5807#endif
5808 }
5809 }
5810 (void) XMakePixmap(display,resource_info,window);
5811 /*
5812 Restore cursor.
5813 */
5814 (void) XCheckDefineCursor(display,window->id,window->cursor);
5815 return(MagickTrue);
5816}
5817
5818/*
5819%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5820% %
5821% %
5822% %
5823+ X M a k e I m a g e L S B F i r s t %
5824% %
5825% %
5826% %
5827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5828%
5829% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5830% pixels are copied in least-significant bit and byte first order. The
5831% server's scanline pad is respected. Rather than using one or two general
5832% cases, many special cases are found here to help speed up the image
5833% conversion.
5834%
5835% The format of the XMakeImageLSBFirst method is:
5836%
cristye941a752011-10-15 01:52:48 +00005837% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5838% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005839%
5840% A description of each parameter follows:
5841%
5842% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5843%
5844% o window: Specifies a pointer to a XWindowInfo structure.
5845%
5846% o image: the image.
5847%
5848% o ximage: Specifies a pointer to a XImage structure; returned from
5849% XCreateImage.
5850%
5851% o matte_image: Specifies a pointer to a XImage structure; returned from
5852% XCreateImage.
5853%
cristye941a752011-10-15 01:52:48 +00005854% o exception: return any errors or warnings in this structure.
5855%
cristy3ed852e2009-09-05 21:47:34 +00005856*/
5857static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005858 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5859 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005860{
cristyc57f6942010-11-12 01:47:39 +00005861 CacheView
5862 *canvas_view;
5863
cristy3ed852e2009-09-05 21:47:34 +00005864 Image
5865 *canvas;
5866
5867 int
5868 y;
5869
cristy4c08aed2011-07-01 19:47:50 +00005870 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005871 *p;
5872
5873 register int
5874 x;
5875
5876 register unsigned char
5877 *q;
5878
5879 unsigned char
5880 bit,
5881 byte;
5882
5883 unsigned int
5884 scanline_pad;
5885
cristyf2faecf2010-05-28 19:19:36 +00005886 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005887 pixel,
5888 *pixels;
5889
5890 XStandardColormap
5891 *map_info;
5892
5893 assert(resource_info != (XResourceInfo *) NULL);
5894 assert(window != (XWindowInfo *) NULL);
5895 assert(image != (Image *) NULL);
5896 if (image->debug != MagickFalse)
5897 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5898 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005899 if ((window->immutable == MagickFalse) &&
cristy17f11b02014-12-20 19:37:04 +00005900 (image->storage_class == DirectClass) && (image->alpha_trait != UndefinedPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00005901 {
5902 char
cristy151b66d2015-04-15 10:50:31 +00005903 size[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00005904
5905 Image
5906 *pattern;
5907
5908 ImageInfo
5909 *image_info;
5910
5911 image_info=AcquireImageInfo();
5912 (void) CopyMagickString(image_info->filename,
5913 resource_info->image_info->texture != (char *) NULL ?
5914 resource_info->image_info->texture : "pattern:checkerboard",
cristy151b66d2015-04-15 10:50:31 +00005915 MagickPathExtent);
5916 (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005917 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005918 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005919 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005920 image_info=DestroyImageInfo(image_info);
5921 if (pattern != (Image *) NULL)
5922 {
cristy6710d842011-10-20 23:23:00 +00005923 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005924 if (canvas != (Image *) NULL)
cristy39172402012-03-30 13:04:39 +00005925 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00005926 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00005927 pattern=DestroyImage(pattern);
5928 }
5929 }
5930 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5931 ximage->bits_per_pixel) >> 3));
5932 map_info=window->map_info;
5933 pixels=window->pixel_info->pixels;
5934 q=(unsigned char *) ximage->data;
5935 x=0;
cristy46ff2672012-12-14 15:32:26 +00005936 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00005937 if (ximage->format == XYBitmap)
5938 {
5939 register unsigned short
5940 polarity;
5941
5942 unsigned char
5943 background,
5944 foreground;
5945
5946 /*
5947 Convert canvas to big-endian bitmap.
5948 */
5949 background=(unsigned char)
5950 (XPixelIntensity(&window->pixel_info->foreground_color) <
5951 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5952 foreground=(unsigned char)
5953 (XPixelIntensity(&window->pixel_info->background_color) <
5954 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy11a06d32015-01-04 12:03:27 +00005955 polarity=(unsigned short) ((GetPixelInfoIntensity(image,
cristyc3306092015-02-28 22:57:28 +00005956 &canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00005957 if (canvas->colors == 2)
cristy11a06d32015-01-04 12:03:27 +00005958 polarity=GetPixelInfoIntensity(image,&canvas->colormap[0]) <
5959 GetPixelInfoIntensity(image,&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005960 for (y=0; y < (int) canvas->rows; y++)
5961 {
cristyc57f6942010-11-12 01:47:39 +00005962 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005963 exception);
cristy4c08aed2011-07-01 19:47:50 +00005964 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005965 break;
cristy3ed852e2009-09-05 21:47:34 +00005966 bit=0;
5967 byte=0;
5968 for (x=0; x < (int) canvas->columns; x++)
5969 {
5970 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005971 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005972 byte|=foreground;
5973 else
5974 byte|=background;
5975 bit++;
5976 if (bit == 8)
5977 {
5978 *q++=byte;
5979 bit=0;
5980 byte=0;
5981 }
cristyed231572011-07-14 02:18:59 +00005982 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005983 }
5984 if (bit != 0)
5985 *q=byte >> (8-bit);
5986 q+=scanline_pad;
5987 }
5988 }
5989 else
5990 if (window->pixel_info->colors != 0)
5991 switch (ximage->bits_per_pixel)
5992 {
5993 case 2:
5994 {
5995 register unsigned int
5996 nibble;
5997
5998 /*
5999 Convert to 2 bit color-mapped X canvas.
6000 */
6001 for (y=0; y < (int) canvas->rows; y++)
6002 {
cristyc57f6942010-11-12 01:47:39 +00006003 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006004 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006005 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006006 break;
cristy3ed852e2009-09-05 21:47:34 +00006007 nibble=0;
6008 for (x=0; x < (int) canvas->columns; x++)
6009 {
cristy4c08aed2011-07-01 19:47:50 +00006010 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006011 switch (nibble)
6012 {
6013 case 0:
6014 {
6015 *q=(unsigned char) pixel;
6016 nibble++;
6017 break;
6018 }
6019 case 1:
6020 {
6021 *q|=(unsigned char) (pixel << 2);
6022 nibble++;
6023 break;
6024 }
6025 case 2:
6026 {
6027 *q|=(unsigned char) (pixel << 4);
6028 nibble++;
6029 break;
6030 }
6031 case 3:
6032 {
6033 *q|=(unsigned char) (pixel << 6);
6034 q++;
6035 nibble=0;
6036 break;
6037 }
6038 }
cristyed231572011-07-14 02:18:59 +00006039 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006040 }
6041 q+=scanline_pad;
6042 }
6043 break;
6044 }
6045 case 4:
6046 {
6047 register unsigned int
6048 nibble;
6049
6050 /*
6051 Convert to 4 bit color-mapped X canvas.
6052 */
6053 for (y=0; y < (int) canvas->rows; y++)
6054 {
cristyc57f6942010-11-12 01:47:39 +00006055 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006056 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006057 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006058 break;
cristy3ed852e2009-09-05 21:47:34 +00006059 nibble=0;
6060 for (x=0; x < (int) canvas->columns; x++)
6061 {
cristy4c08aed2011-07-01 19:47:50 +00006062 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006063 switch (nibble)
6064 {
6065 case 0:
6066 {
6067 *q=(unsigned char) pixel;
6068 nibble++;
6069 break;
6070 }
6071 case 1:
6072 {
6073 *q|=(unsigned char) (pixel << 4);
6074 q++;
6075 nibble=0;
6076 break;
6077 }
6078 }
cristyed231572011-07-14 02:18:59 +00006079 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006080 }
6081 q+=scanline_pad;
6082 }
6083 break;
6084 }
6085 case 6:
6086 case 8:
6087 {
6088 /*
6089 Convert to 8 bit color-mapped X canvas.
6090 */
6091 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006092 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006093 {
cristy6710d842011-10-20 23:23:00 +00006094 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006095 break;
6096 }
6097 for (y=0; y < (int) canvas->rows; y++)
6098 {
cristyc57f6942010-11-12 01:47:39 +00006099 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006100 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006101 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006102 break;
cristy3ed852e2009-09-05 21:47:34 +00006103 for (x=0; x < (int) canvas->columns; x++)
6104 {
cristy4c08aed2011-07-01 19:47:50 +00006105 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006106 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006107 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006108 }
6109 q+=scanline_pad;
6110 }
6111 break;
6112 }
6113 default:
6114 {
6115 register int
6116 k;
6117
6118 register unsigned int
6119 bytes_per_pixel;
6120
cristy3ed852e2009-09-05 21:47:34 +00006121 /*
6122 Convert to multi-byte color-mapped X canvas.
6123 */
6124 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6125 for (y=0; y < (int) canvas->rows; y++)
6126 {
cristyc57f6942010-11-12 01:47:39 +00006127 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006128 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006129 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006130 break;
cristy3ed852e2009-09-05 21:47:34 +00006131 for (x=0; x < (int) canvas->columns; x++)
6132 {
cristy4c08aed2011-07-01 19:47:50 +00006133 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006134 for (k=0; k < (int) bytes_per_pixel; k++)
6135 {
cristy42daae12013-04-07 22:36:07 +00006136 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006137 pixel>>=8;
6138 }
cristyed231572011-07-14 02:18:59 +00006139 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006140 }
6141 q+=scanline_pad;
6142 }
6143 break;
6144 }
6145 }
6146 else
6147 switch (ximage->bits_per_pixel)
6148 {
6149 case 2:
6150 {
6151 register unsigned int
6152 nibble;
6153
6154 /*
6155 Convert to contiguous 2 bit continuous-tone X canvas.
6156 */
6157 for (y=0; y < (int) canvas->rows; y++)
6158 {
6159 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006160 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006161 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006162 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006163 break;
6164 for (x=0; x < (int) canvas->columns; x++)
6165 {
cristy4c08aed2011-07-01 19:47:50 +00006166 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006167 pixel&=0xf;
6168 switch (nibble)
6169 {
6170 case 0:
6171 {
6172 *q=(unsigned char) pixel;
6173 nibble++;
6174 break;
6175 }
6176 case 1:
6177 {
6178 *q|=(unsigned char) (pixel << 2);
6179 nibble++;
6180 break;
6181 }
6182 case 2:
6183 {
6184 *q|=(unsigned char) (pixel << 4);
6185 nibble++;
6186 break;
6187 }
6188 case 3:
6189 {
6190 *q|=(unsigned char) (pixel << 6);
6191 q++;
6192 nibble=0;
6193 break;
6194 }
6195 }
cristyed231572011-07-14 02:18:59 +00006196 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006197 }
6198 q+=scanline_pad;
6199 }
6200 break;
6201 }
6202 case 4:
6203 {
6204 register unsigned int
6205 nibble;
6206
6207 /*
6208 Convert to contiguous 4 bit continuous-tone X canvas.
6209 */
6210 for (y=0; y < (int) canvas->rows; y++)
6211 {
cristyc57f6942010-11-12 01:47:39 +00006212 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006213 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006214 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006215 break;
6216 nibble=0;
6217 for (x=0; x < (int) canvas->columns; x++)
6218 {
cristy4c08aed2011-07-01 19:47:50 +00006219 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006220 pixel&=0xf;
6221 switch (nibble)
6222 {
6223 case 0:
6224 {
6225 *q=(unsigned char) pixel;
6226 nibble++;
6227 break;
6228 }
6229 case 1:
6230 {
6231 *q|=(unsigned char) (pixel << 4);
6232 q++;
6233 nibble=0;
6234 break;
6235 }
6236 }
cristyed231572011-07-14 02:18:59 +00006237 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006238 }
6239 q+=scanline_pad;
6240 }
6241 break;
6242 }
6243 case 6:
6244 case 8:
6245 {
6246 /*
6247 Convert to contiguous 8 bit continuous-tone X canvas.
6248 */
6249 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006250 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006251 {
cristy6710d842011-10-20 23:23:00 +00006252 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006253 break;
6254 }
6255 for (y=0; y < (int) canvas->rows; y++)
6256 {
cristyc57f6942010-11-12 01:47:39 +00006257 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006258 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006259 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006260 break;
6261 for (x=0; x < (int) canvas->columns; x++)
6262 {
cristy4c08aed2011-07-01 19:47:50 +00006263 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006264 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006265 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006266 }
6267 q+=scanline_pad;
6268 }
6269 break;
6270 }
6271 default:
6272 {
6273 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6274 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6275 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6276 (map_info->blue_mult == 1))
6277 {
6278 /*
6279 Convert to 32 bit continuous-tone X canvas.
6280 */
6281 for (y=0; y < (int) canvas->rows; y++)
6282 {
cristyc57f6942010-11-12 01:47:39 +00006283 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006284 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006285 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006286 break;
6287 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6288 (blue_gamma != 1.0))
6289 {
6290 /*
6291 Gamma correct canvas.
6292 */
6293 for (x=(int) canvas->columns-1; x >= 0; x--)
6294 {
cristyccf844f2010-02-03 23:28:16 +00006295 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006296 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006297 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006298 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006299 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006300 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006301 *q++=0;
cristyed231572011-07-14 02:18:59 +00006302 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006303 }
6304 continue;
6305 }
6306 for (x=(int) canvas->columns-1; x >= 0; x--)
6307 {
cristy8bc259b2012-06-21 23:53:15 +00006308 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6309 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6310 *q++=ScaleQuantumToChar((Quantum) 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 }
6315 }
6316 else
6317 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6318 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6319 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6320 (map_info->blue_mult == 65536L))
6321 {
6322 /*
6323 Convert to 32 bit continuous-tone X canvas.
6324 */
6325 for (y=0; y < (int) canvas->rows; y++)
6326 {
cristyc57f6942010-11-12 01:47:39 +00006327 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006328 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006329 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006330 break;
6331 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6332 (blue_gamma != 1.0))
6333 {
6334 /*
6335 Gamma correct canvas.
6336 */
6337 for (x=(int) canvas->columns-1; x >= 0; x--)
6338 {
cristyccf844f2010-02-03 23:28:16 +00006339 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006340 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006341 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006342 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006343 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006344 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006345 *q++=0;
cristyed231572011-07-14 02:18:59 +00006346 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006347 }
6348 continue;
6349 }
6350 for (x=(int) canvas->columns-1; x >= 0; x--)
6351 {
cristy8bc259b2012-06-21 23:53:15 +00006352 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6353 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6354 *q++=ScaleQuantumToChar((Quantum) 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 }
6359 }
6360 else
6361 {
6362 register int
6363 k;
6364
6365 register unsigned int
6366 bytes_per_pixel;
6367
cristy3ed852e2009-09-05 21:47:34 +00006368 /*
6369 Convert to multi-byte continuous-tone X canvas.
6370 */
6371 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6372 for (y=0; y < (int) canvas->rows; y++)
6373 {
cristyc57f6942010-11-12 01:47:39 +00006374 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006375 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006376 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006377 break;
cristyc57f6942010-11-12 01:47:39 +00006378 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006379 {
cristy4c08aed2011-07-01 19:47:50 +00006380 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006381 for (k=0; k < (int) bytes_per_pixel; k++)
6382 {
cristy42daae12013-04-07 22:36:07 +00006383 *q++=(unsigned char) (pixel & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00006384 pixel>>=8;
6385 }
cristyed231572011-07-14 02:18:59 +00006386 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006387 }
6388 q+=scanline_pad;
6389 }
6390 }
6391 break;
6392 }
6393 }
6394 if (matte_image != (XImage *) NULL)
6395 {
6396 /*
6397 Initialize matte canvas.
6398 */
6399 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6400 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6401 q=(unsigned char *) matte_image->data;
6402 for (y=0; y < (int) canvas->rows; y++)
6403 {
cristyc57f6942010-11-12 01:47:39 +00006404 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006405 exception);
cristy4c08aed2011-07-01 19:47:50 +00006406 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006407 break;
6408 bit=0;
6409 byte=0;
6410 for (x=(int) canvas->columns-1; x >= 0; x--)
6411 {
6412 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006413 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006414 byte|=0x80;
6415 bit++;
6416 if (bit == 8)
6417 {
6418 *q++=byte;
6419 bit=0;
6420 byte=0;
6421 }
cristyed231572011-07-14 02:18:59 +00006422 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006423 }
6424 if (bit != 0)
6425 *q=byte >> (8-bit);
6426 q+=scanline_pad;
6427 }
6428 }
cristyc57f6942010-11-12 01:47:39 +00006429 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006430 if (canvas != image)
6431 canvas=DestroyImage(canvas);
6432}
6433
6434/*
6435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6436% %
6437% %
6438% %
6439+ X M a k e I m a g e M S B F i r s t %
6440% %
6441% %
6442% %
6443%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6444%
6445% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6446% image pixels are copied in most-significant bit and byte first order. The
6447% server's scanline pad is also respected. Rather than using one or two
6448% general cases, many special cases are found here to help speed up the image
6449% conversion.
6450%
6451% The format of the XMakeImageMSBFirst method is:
6452%
cristye941a752011-10-15 01:52:48 +00006453% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6454% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006455%
6456% A description of each parameter follows:
6457%
6458% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6459%
6460% o window: Specifies a pointer to a XWindowInfo structure.
6461%
6462% o image: the image.
6463%
6464% o ximage: Specifies a pointer to a XImage structure; returned from
6465% XCreateImage.
6466%
6467% o matte_image: Specifies a pointer to a XImage structure; returned from
6468% XCreateImage.
6469%
cristye941a752011-10-15 01:52:48 +00006470% o exception: return any errors or warnings in this structure.
6471%
cristy3ed852e2009-09-05 21:47:34 +00006472*/
6473static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006474 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6475 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006476{
cristyc57f6942010-11-12 01:47:39 +00006477 CacheView
6478 *canvas_view;
6479
cristy3ed852e2009-09-05 21:47:34 +00006480 Image
6481 *canvas;
6482
6483 int
6484 y;
6485
6486 register int
6487 x;
6488
cristy4c08aed2011-07-01 19:47:50 +00006489 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006490 *p;
6491
6492 register unsigned char
6493 *q;
6494
6495 unsigned char
6496 bit,
6497 byte;
6498
6499 unsigned int
6500 scanline_pad;
6501
cristyf2faecf2010-05-28 19:19:36 +00006502 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006503 pixel,
6504 *pixels;
6505
6506 XStandardColormap
6507 *map_info;
6508
6509 assert(resource_info != (XResourceInfo *) NULL);
6510 assert(window != (XWindowInfo *) NULL);
6511 assert(image != (Image *) NULL);
6512 if (image->debug != MagickFalse)
6513 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6514 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006515 if ((window->immutable != MagickFalse) &&
cristy11a06d32015-01-04 12:03:27 +00006516 (image->storage_class == DirectClass) &&
6517 (image->alpha_trait != UndefinedPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00006518 {
6519 char
cristy151b66d2015-04-15 10:50:31 +00006520 size[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00006521
6522 Image
6523 *pattern;
6524
6525 ImageInfo
6526 *image_info;
6527
6528 image_info=AcquireImageInfo();
6529 (void) CopyMagickString(image_info->filename,
6530 resource_info->image_info->texture != (char *) NULL ?
6531 resource_info->image_info->texture : "pattern:checkerboard",
cristy151b66d2015-04-15 10:50:31 +00006532 MagickPathExtent);
6533 (void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006534 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006535 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006536 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006537 image_info=DestroyImageInfo(image_info);
6538 if (pattern != (Image *) NULL)
6539 {
cristy6710d842011-10-20 23:23:00 +00006540 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006541 if (canvas != (Image *) NULL)
cristyfeb3e962012-03-29 17:25:55 +00006542 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6543 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00006544 pattern=DestroyImage(pattern);
6545 }
6546 }
cristy4c08aed2011-07-01 19:47:50 +00006547 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6548 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006549 map_info=window->map_info;
6550 pixels=window->pixel_info->pixels;
6551 q=(unsigned char *) ximage->data;
6552 x=0;
cristy46ff2672012-12-14 15:32:26 +00006553 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00006554 if (ximage->format == XYBitmap)
6555 {
6556 register unsigned short
6557 polarity;
6558
6559 unsigned char
6560 background,
6561 foreground;
6562
6563 /*
6564 Convert canvas to big-endian bitmap.
6565 */
6566 background=(unsigned char)
6567 (XPixelIntensity(&window->pixel_info->foreground_color) <
6568 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6569 foreground=(unsigned char)
6570 (XPixelIntensity(&window->pixel_info->background_color) <
6571 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy11a06d32015-01-04 12:03:27 +00006572 polarity=(unsigned short) ((GetPixelInfoIntensity(image,
cristyc3306092015-02-28 22:57:28 +00006573 &canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00006574 if (canvas->colors == 2)
cristy11a06d32015-01-04 12:03:27 +00006575 polarity=GetPixelInfoIntensity(image,&canvas->colormap[0]) <
6576 GetPixelInfoIntensity(image,&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006577 for (y=0; y < (int) canvas->rows; y++)
6578 {
cristyc57f6942010-11-12 01:47:39 +00006579 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006580 exception);
cristy4c08aed2011-07-01 19:47:50 +00006581 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006582 break;
cristy3ed852e2009-09-05 21:47:34 +00006583 bit=0;
6584 byte=0;
6585 for (x=(int) canvas->columns-1; x >= 0; x--)
6586 {
6587 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006588 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006589 byte|=foreground;
6590 else
6591 byte|=background;
6592 bit++;
6593 if (bit == 8)
6594 {
6595 *q++=byte;
6596 bit=0;
6597 byte=0;
6598 }
cristyed231572011-07-14 02:18:59 +00006599 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006600 }
6601 if (bit != 0)
6602 *q=byte << (8-bit);
6603 q+=scanline_pad;
6604 }
6605 }
6606 else
6607 if (window->pixel_info->colors != 0)
6608 switch (ximage->bits_per_pixel)
6609 {
6610 case 2:
6611 {
6612 register unsigned int
6613 nibble;
6614
6615 /*
6616 Convert to 2 bit color-mapped X canvas.
6617 */
6618 for (y=0; y < (int) canvas->rows; y++)
6619 {
cristyc57f6942010-11-12 01:47:39 +00006620 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006621 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006622 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006623 break;
cristy3ed852e2009-09-05 21:47:34 +00006624 nibble=0;
6625 for (x=0; x < (int) canvas->columns; x++)
6626 {
cristy4c08aed2011-07-01 19:47:50 +00006627 pixel=pixels[(ssize_t)
6628 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006629 switch (nibble)
6630 {
6631 case 0:
6632 {
6633 *q=(unsigned char) (pixel << 6);
6634 nibble++;
6635 break;
6636 }
6637 case 1:
6638 {
6639 *q|=(unsigned char) (pixel << 4);
6640 nibble++;
6641 break;
6642 }
6643 case 2:
6644 {
6645 *q|=(unsigned char) (pixel << 2);
6646 nibble++;
6647 break;
6648 }
6649 case 3:
6650 {
6651 *q|=(unsigned char) pixel;
6652 q++;
6653 nibble=0;
6654 break;
6655 }
6656 }
cristyed231572011-07-14 02:18:59 +00006657 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006658 }
6659 q+=scanline_pad;
6660 }
6661 break;
6662 }
6663 case 4:
6664 {
6665 register unsigned int
6666 nibble;
6667
6668 /*
6669 Convert to 4 bit color-mapped X canvas.
6670 */
6671 for (y=0; y < (int) canvas->rows; y++)
6672 {
cristyc57f6942010-11-12 01:47:39 +00006673 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006674 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006675 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006676 break;
cristy3ed852e2009-09-05 21:47:34 +00006677 nibble=0;
6678 for (x=0; x < (int) canvas->columns; x++)
6679 {
cristy4c08aed2011-07-01 19:47:50 +00006680 pixel=pixels[(ssize_t)
6681 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006682 switch (nibble)
6683 {
6684 case 0:
6685 {
6686 *q=(unsigned char) (pixel << 4);
6687 nibble++;
6688 break;
6689 }
6690 case 1:
6691 {
6692 *q|=(unsigned char) pixel;
6693 q++;
6694 nibble=0;
6695 break;
6696 }
6697 }
cristyed231572011-07-14 02:18:59 +00006698 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006699 }
6700 q+=scanline_pad;
6701 }
6702 break;
6703 }
6704 case 6:
6705 case 8:
6706 {
6707 /*
6708 Convert to 8 bit color-mapped X canvas.
6709 */
6710 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006711 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006712 {
cristy6710d842011-10-20 23:23:00 +00006713 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006714 break;
6715 }
6716 for (y=0; y < (int) canvas->rows; y++)
6717 {
cristyc57f6942010-11-12 01:47:39 +00006718 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006719 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006720 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006721 break;
cristy3ed852e2009-09-05 21:47:34 +00006722 for (x=0; x < (int) canvas->columns; x++)
6723 {
cristy6710d842011-10-20 23:23:00 +00006724 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006725 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006726 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006727 }
6728 q+=scanline_pad;
6729 }
6730 break;
6731 }
6732 default:
6733 {
6734 register int
6735 k;
6736
6737 register unsigned int
6738 bytes_per_pixel;
6739
6740 unsigned char
cristybb503372010-05-27 20:51:26 +00006741 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006742
6743 /*
6744 Convert to 8 bit color-mapped X canvas.
6745 */
6746 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6747 for (y=0; y < (int) canvas->rows; y++)
6748 {
cristyc57f6942010-11-12 01:47:39 +00006749 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006750 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006751 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006752 break;
cristy3ed852e2009-09-05 21:47:34 +00006753 for (x=0; x < (int) canvas->columns; x++)
6754 {
cristy4c08aed2011-07-01 19:47:50 +00006755 pixel=pixels[(ssize_t)
6756 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006757 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6758 {
6759 channel[k]=(unsigned char) pixel;
6760 pixel>>=8;
6761 }
6762 for (k=0; k < (int) bytes_per_pixel; k++)
6763 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006764 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006765 }
6766 q+=scanline_pad;
6767 }
6768 break;
6769 }
6770 }
6771 else
6772 switch (ximage->bits_per_pixel)
6773 {
6774 case 2:
6775 {
6776 register unsigned int
6777 nibble;
6778
6779 /*
6780 Convert to 4 bit continuous-tone X canvas.
6781 */
6782 for (y=0; y < (int) canvas->rows; y++)
6783 {
cristyc57f6942010-11-12 01:47:39 +00006784 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006785 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006786 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006787 break;
6788 nibble=0;
6789 for (x=(int) canvas->columns-1; x >= 0; x--)
6790 {
cristy4c08aed2011-07-01 19:47:50 +00006791 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006792 pixel&=0xf;
6793 switch (nibble)
6794 {
6795 case 0:
6796 {
6797 *q=(unsigned char) (pixel << 6);
6798 nibble++;
6799 break;
6800 }
6801 case 1:
6802 {
6803 *q|=(unsigned char) (pixel << 4);
6804 nibble++;
6805 break;
6806 }
6807 case 2:
6808 {
6809 *q|=(unsigned char) (pixel << 2);
6810 nibble++;
6811 break;
6812 }
6813 case 3:
6814 {
6815 *q|=(unsigned char) pixel;
6816 q++;
6817 nibble=0;
6818 break;
6819 }
6820 }
cristyed231572011-07-14 02:18:59 +00006821 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006822 }
6823 q+=scanline_pad;
6824 }
6825 break;
6826 }
6827 case 4:
6828 {
6829 register unsigned int
6830 nibble;
6831
6832 /*
6833 Convert to 4 bit continuous-tone X canvas.
6834 */
6835 for (y=0; y < (int) canvas->rows; y++)
6836 {
cristyc57f6942010-11-12 01:47:39 +00006837 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006838 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006839 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006840 break;
6841 nibble=0;
6842 for (x=(int) canvas->columns-1; x >= 0; x--)
6843 {
cristy4c08aed2011-07-01 19:47:50 +00006844 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006845 pixel&=0xf;
6846 switch (nibble)
6847 {
6848 case 0:
6849 {
6850 *q=(unsigned char) (pixel << 4);
6851 nibble++;
6852 break;
6853 }
6854 case 1:
6855 {
6856 *q|=(unsigned char) pixel;
6857 q++;
6858 nibble=0;
6859 break;
6860 }
6861 }
cristyed231572011-07-14 02:18:59 +00006862 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006863 }
6864 q+=scanline_pad;
6865 }
6866 break;
6867 }
6868 case 6:
6869 case 8:
6870 {
6871 /*
6872 Convert to 8 bit continuous-tone X canvas.
6873 */
6874 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006875 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006876 {
cristy6710d842011-10-20 23:23:00 +00006877 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006878 break;
6879 }
6880 for (y=0; y < (int) canvas->rows; y++)
6881 {
cristyc57f6942010-11-12 01:47:39 +00006882 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006883 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006884 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006885 break;
6886 for (x=(int) canvas->columns-1; x >= 0; x--)
6887 {
cristy4c08aed2011-07-01 19:47:50 +00006888 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006889 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006890 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006891 }
6892 q+=scanline_pad;
6893 }
6894 break;
6895 }
6896 default:
6897 {
6898 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6899 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6900 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6901 (map_info->blue_mult == 1))
6902 {
6903 /*
6904 Convert to 32 bit continuous-tone X canvas.
6905 */
6906 for (y=0; y < (int) canvas->rows; y++)
6907 {
cristyc57f6942010-11-12 01:47:39 +00006908 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006909 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006910 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006911 break;
6912 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6913 (blue_gamma != 1.0))
6914 {
6915 /*
6916 Gamma correct canvas.
6917 */
6918 for (x=(int) canvas->columns-1; x >= 0; x--)
6919 {
6920 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006921 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006922 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006923 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006924 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006925 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006926 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006927 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006928 }
6929 continue;
6930 }
6931 for (x=(int) canvas->columns-1; x >= 0; x--)
6932 {
6933 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006934 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6935 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6936 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006937 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006938 }
6939 }
6940 }
6941 else
6942 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6943 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6944 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6945 (map_info->blue_mult == 65536L))
6946 {
6947 /*
6948 Convert to 32 bit continuous-tone X canvas.
6949 */
6950 for (y=0; y < (int) canvas->rows; y++)
6951 {
cristyc57f6942010-11-12 01:47:39 +00006952 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006953 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006954 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006955 break;
6956 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6957 (blue_gamma != 1.0))
6958 {
6959 /*
6960 Gamma correct canvas.
6961 */
6962 for (x=(int) canvas->columns-1; x >= 0; x--)
6963 {
6964 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006965 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006966 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006967 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006968 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006969 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006970 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006971 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006972 }
6973 continue;
6974 }
6975 for (x=(int) canvas->columns-1; x >= 0; x--)
6976 {
6977 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006978 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6979 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6980 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006981 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006982 }
6983 }
6984 }
6985 else
6986 {
6987 register int
6988 k;
6989
6990 register unsigned int
6991 bytes_per_pixel;
6992
6993 unsigned char
cristybb503372010-05-27 20:51:26 +00006994 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006995
6996 /*
6997 Convert to multi-byte continuous-tone X canvas.
6998 */
6999 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7000 for (y=0; y < (int) canvas->rows; y++)
7001 {
cristyc57f6942010-11-12 01:47:39 +00007002 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007003 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007004 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007005 break;
7006 for (x=(int) canvas->columns-1; x >= 0; x--)
7007 {
cristy4c08aed2011-07-01 19:47:50 +00007008 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007009 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7010 {
7011 channel[k]=(unsigned char) pixel;
7012 pixel>>=8;
7013 }
7014 for (k=0; k < (int) bytes_per_pixel; k++)
7015 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007016 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007017 }
7018 q+=scanline_pad;
7019 }
7020 }
7021 break;
7022 }
7023 }
7024 if (matte_image != (XImage *) NULL)
7025 {
7026 /*
7027 Initialize matte canvas.
7028 */
7029 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7030 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7031 q=(unsigned char *) matte_image->data;
7032 for (y=0; y < (int) canvas->rows; y++)
7033 {
cristyc57f6942010-11-12 01:47:39 +00007034 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007035 exception);
cristy4c08aed2011-07-01 19:47:50 +00007036 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007037 break;
7038 bit=0;
7039 byte=0;
7040 for (x=(int) canvas->columns-1; x >= 0; x--)
7041 {
7042 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007043 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007044 byte|=0x01;
7045 bit++;
7046 if (bit == 8)
7047 {
7048 *q++=byte;
7049 bit=0;
7050 byte=0;
7051 }
cristyed231572011-07-14 02:18:59 +00007052 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007053 }
7054 if (bit != 0)
7055 *q=byte << (8-bit);
7056 q+=scanline_pad;
7057 }
7058 }
cristyc57f6942010-11-12 01:47:39 +00007059 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007060 if (canvas != image)
7061 canvas=DestroyImage(canvas);
7062}
7063
7064/*
7065%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7066% %
7067% %
7068% %
7069% X M a k e M a g n i f y I m a g e %
7070% %
7071% %
7072% %
7073%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7074%
7075% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7076%
7077% The format of the XMakeMagnifyImage method is:
7078%
cristy6710d842011-10-20 23:23:00 +00007079% void XMakeMagnifyImage(Display *display,XWindows *windows,
7080% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007081%
7082% A description of each parameter follows:
7083%
7084% o display: Specifies a connection to an X server; returned from
7085% XOpenDisplay.
7086%
7087% o windows: Specifies a pointer to a XWindows structure.
7088%
cristy6710d842011-10-20 23:23:00 +00007089% o exception: return any errors or warnings in this structure.
7090%
cristy3ed852e2009-09-05 21:47:34 +00007091*/
cristy6710d842011-10-20 23:23:00 +00007092MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7093 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007094{
7095 char
cristy151b66d2015-04-15 10:50:31 +00007096 tuple[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00007097
7098 int
7099 y;
7100
cristy4c08aed2011-07-01 19:47:50 +00007101 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007102 pixel;
7103
7104 register int
7105 x;
7106
cristybb503372010-05-27 20:51:26 +00007107 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007108 i;
7109
7110 register unsigned char
7111 *p,
7112 *q;
7113
cristy9d314ff2011-03-09 01:30:28 +00007114 ssize_t
7115 n;
7116
cristy3ed852e2009-09-05 21:47:34 +00007117 static unsigned int
7118 previous_magnify = 0;
7119
7120 static XWindowInfo
7121 magnify_window;
7122
7123 unsigned int
7124 height,
7125 j,
7126 k,
7127 l,
7128 magnify,
7129 scanline_pad,
7130 width;
7131
7132 XImage
7133 *ximage;
7134
7135 /*
7136 Check boundary conditions.
7137 */
7138 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7139 assert(display != (Display *) NULL);
7140 assert(windows != (XWindows *) NULL);
7141 magnify=1;
cristybb503372010-05-27 20:51:26 +00007142 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007143 magnify<<=1;
7144 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7145 magnify<<=1;
7146 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7147 magnify<<=1;
7148 while (magnify > windows->magnify.width)
7149 magnify>>=1;
7150 while (magnify > windows->magnify.height)
7151 magnify>>=1;
cristy58a749e2014-05-25 17:36:53 +00007152 if (magnify == 0)
7153 magnify=1;
cristy3ed852e2009-09-05 21:47:34 +00007154 if (magnify != previous_magnify)
7155 {
7156 Status
7157 status;
7158
7159 XTextProperty
7160 window_name;
7161
7162 /*
7163 New magnify factor: update magnify window name.
7164 */
7165 i=0;
7166 while ((1 << i) <= (int) magnify)
7167 i++;
cristy151b66d2015-04-15 10:50:31 +00007168 (void) FormatLocaleString(windows->magnify.name,MagickPathExtent,
cristye8c25f92010-06-03 00:53:06 +00007169 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007170 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7171 if (status != False)
7172 {
7173 XSetWMName(display,windows->magnify.id,&window_name);
7174 XSetWMIconName(display,windows->magnify.id,&window_name);
7175 (void) XFree((void *) window_name.value);
7176 }
7177 }
7178 previous_magnify=magnify;
7179 ximage=windows->image.ximage;
7180 width=(unsigned int) windows->magnify.ximage->width;
7181 height=(unsigned int) windows->magnify.ximage->height;
7182 if ((windows->magnify.x < 0) ||
7183 (windows->magnify.x >= windows->image.ximage->width))
7184 windows->magnify.x=windows->image.ximage->width >> 1;
7185 x=windows->magnify.x-((width/magnify) >> 1);
7186 if (x < 0)
7187 x=0;
7188 else
7189 if (x > (int) (ximage->width-(width/magnify)))
7190 x=ximage->width-width/magnify;
7191 if ((windows->magnify.y < 0) ||
7192 (windows->magnify.y >= windows->image.ximage->height))
7193 windows->magnify.y=windows->image.ximage->height >> 1;
7194 y=windows->magnify.y-((height/magnify) >> 1);
7195 if (y < 0)
7196 y=0;
7197 else
7198 if (y > (int) (ximage->height-(height/magnify)))
7199 y=ximage->height-height/magnify;
7200 q=(unsigned char *) windows->magnify.ximage->data;
7201 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7202 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7203 if (ximage->bits_per_pixel < 8)
7204 {
7205 register unsigned char
7206 background,
7207 byte,
7208 foreground,
7209 p_bit,
7210 q_bit;
7211
7212 register unsigned int
7213 plane;
7214
7215 XPixelInfo
7216 *pixel_info;
7217
7218 pixel_info=windows->magnify.pixel_info;
7219 switch (ximage->bitmap_bit_order)
7220 {
7221 case LSBFirst:
7222 {
7223 /*
7224 Magnify little-endian bitmap.
7225 */
7226 background=0x00;
7227 foreground=0x80;
7228 if (ximage->format == XYBitmap)
7229 {
7230 background=(unsigned char)
7231 (XPixelIntensity(&pixel_info->foreground_color) <
7232 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7233 foreground=(unsigned char)
7234 (XPixelIntensity(&pixel_info->background_color) <
7235 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7236 if (windows->magnify.depth > 1)
7237 Swap(background,foreground);
7238 }
cristybb503372010-05-27 20:51:26 +00007239 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007240 {
7241 /*
7242 Propogate pixel magnify rows.
7243 */
7244 for (j=0; j < magnify; j++)
7245 {
7246 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7247 ((x*ximage->bits_per_pixel) >> 3);
7248 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7249 q_bit=0;
7250 byte=0;
7251 for (k=0; k < width; k+=magnify)
7252 {
7253 /*
7254 Propogate pixel magnify columns.
7255 */
7256 for (l=0; l < magnify; l++)
7257 {
7258 /*
7259 Propogate each bit plane.
7260 */
7261 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7262 {
7263 byte>>=1;
7264 if (*p & (0x01 << (p_bit+plane)))
7265 byte|=foreground;
7266 else
7267 byte|=background;
7268 q_bit++;
7269 if (q_bit == 8)
7270 {
7271 *q++=byte;
7272 q_bit=0;
7273 byte=0;
7274 }
7275 }
7276 }
7277 p_bit+=ximage->bits_per_pixel;
7278 if (p_bit == 8)
7279 {
7280 p++;
7281 p_bit=0;
7282 }
7283 if (q_bit != 0)
7284 *q=byte >> (8-q_bit);
7285 q+=scanline_pad;
7286 }
7287 }
7288 y++;
7289 }
7290 break;
7291 }
7292 case MSBFirst:
7293 default:
7294 {
7295 /*
7296 Magnify big-endian bitmap.
7297 */
7298 background=0x00;
7299 foreground=0x01;
7300 if (ximage->format == XYBitmap)
7301 {
7302 background=(unsigned char)
7303 (XPixelIntensity(&pixel_info->foreground_color) <
7304 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7305 foreground=(unsigned char)
7306 (XPixelIntensity(&pixel_info->background_color) <
7307 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7308 if (windows->magnify.depth > 1)
7309 Swap(background,foreground);
7310 }
cristybb503372010-05-27 20:51:26 +00007311 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007312 {
7313 /*
7314 Propogate pixel magnify rows.
7315 */
7316 for (j=0; j < magnify; j++)
7317 {
7318 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7319 ((x*ximage->bits_per_pixel) >> 3);
7320 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7321 q_bit=0;
7322 byte=0;
7323 for (k=0; k < width; k+=magnify)
7324 {
7325 /*
7326 Propogate pixel magnify columns.
7327 */
7328 for (l=0; l < magnify; l++)
7329 {
7330 /*
7331 Propogate each bit plane.
7332 */
7333 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7334 {
7335 byte<<=1;
7336 if (*p & (0x80 >> (p_bit+plane)))
7337 byte|=foreground;
7338 else
7339 byte|=background;
7340 q_bit++;
7341 if (q_bit == 8)
7342 {
7343 *q++=byte;
7344 q_bit=0;
7345 byte=0;
7346 }
7347 }
7348 }
7349 p_bit+=ximage->bits_per_pixel;
7350 if (p_bit == 8)
7351 {
7352 p++;
7353 p_bit=0;
7354 }
7355 if (q_bit != 0)
7356 *q=byte << (8-q_bit);
7357 q+=scanline_pad;
7358 }
7359 }
7360 y++;
7361 }
7362 break;
7363 }
7364 }
7365 }
7366 else
7367 switch (ximage->bits_per_pixel)
7368 {
7369 case 6:
7370 case 8:
7371 {
7372 /*
7373 Magnify 8 bit X image.
7374 */
cristybb503372010-05-27 20:51:26 +00007375 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007376 {
7377 /*
7378 Propogate pixel magnify rows.
7379 */
7380 for (j=0; j < magnify; j++)
7381 {
7382 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7383 ((x*ximage->bits_per_pixel) >> 3);
7384 for (k=0; k < width; k+=magnify)
7385 {
7386 /*
7387 Propogate pixel magnify columns.
7388 */
7389 for (l=0; l < magnify; l++)
7390 *q++=(*p);
7391 p++;
7392 }
7393 q+=scanline_pad;
7394 }
7395 y++;
7396 }
7397 break;
7398 }
7399 default:
7400 {
7401 register unsigned int
7402 bytes_per_pixel,
7403 m;
7404
7405 /*
7406 Magnify multi-byte X image.
7407 */
7408 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007409 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007410 {
7411 /*
7412 Propogate pixel magnify rows.
7413 */
7414 for (j=0; j < magnify; j++)
7415 {
7416 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7417 ((x*ximage->bits_per_pixel) >> 3);
7418 for (k=0; k < width; k+=magnify)
7419 {
7420 /*
7421 Propogate pixel magnify columns.
7422 */
7423 for (l=0; l < magnify; l++)
7424 for (m=0; m < bytes_per_pixel; m++)
7425 *q++=(*(p+m));
7426 p+=bytes_per_pixel;
7427 }
7428 q+=scanline_pad;
7429 }
7430 y++;
7431 }
7432 break;
7433 }
7434 }
7435 /*
7436 Copy X image to magnify pixmap.
7437 */
7438 x=windows->magnify.x-((width/magnify) >> 1);
7439 if (x < 0)
7440 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7441 else
7442 if (x > (int) (ximage->width-(width/magnify)))
7443 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7444 else
7445 x=0;
7446 y=windows->magnify.y-((height/magnify) >> 1);
7447 if (y < 0)
7448 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7449 else
7450 if (y > (int) (ximage->height-(height/magnify)))
7451 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7452 else
7453 y=0;
7454 if ((x != 0) || (y != 0))
7455 (void) XFillRectangle(display,windows->magnify.pixmap,
7456 windows->magnify.annotate_context,0,0,width,height);
7457 (void) XPutImage(display,windows->magnify.pixmap,
7458 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7459 height-y);
7460 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7461 (magnify <= (height >> 1))))
7462 {
7463 RectangleInfo
7464 highlight_info;
7465
7466 /*
7467 Highlight center pixel.
7468 */
cristybb503372010-05-27 20:51:26 +00007469 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7470 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007471 highlight_info.width=magnify;
7472 highlight_info.height=magnify;
7473 (void) XDrawRectangle(display,windows->magnify.pixmap,
7474 windows->magnify.highlight_context,(int) highlight_info.x,
7475 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7476 (unsigned int) highlight_info.height-1);
7477 if (magnify > 2)
7478 (void) XDrawRectangle(display,windows->magnify.pixmap,
7479 windows->magnify.annotate_context,(int) highlight_info.x+1,
7480 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7481 (unsigned int) highlight_info.height-3);
7482 }
7483 /*
7484 Show center pixel color.
7485 */
cristy3aa93752011-12-18 15:54:24 +00007486 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007487 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristy151b66d2015-04-15 10:50:31 +00007488 (void) FormatLocaleString(tuple,MagickPathExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007489 windows->magnify.x,windows->magnify.y);
cristy151b66d2015-04-15 10:50:31 +00007490 (void) ConcatenateMagickString(tuple,"(",MagickPathExtent);
cristyed231572011-07-14 02:18:59 +00007491 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy151b66d2015-04-15 10:50:31 +00007492 (void) ConcatenateMagickString(tuple,",",MagickPathExtent);
cristyed231572011-07-14 02:18:59 +00007493 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy151b66d2015-04-15 10:50:31 +00007494 (void) ConcatenateMagickString(tuple,",",MagickPathExtent);
cristyed231572011-07-14 02:18:59 +00007495 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007496 if (pixel.colorspace == CMYKColorspace)
7497 {
cristy151b66d2015-04-15 10:50:31 +00007498 (void) ConcatenateMagickString(tuple,",",MagickPathExtent);
cristyed231572011-07-14 02:18:59 +00007499 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007500 }
cristy17f11b02014-12-20 19:37:04 +00007501 if (pixel.alpha_trait != UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00007502 {
cristy151b66d2015-04-15 10:50:31 +00007503 (void) ConcatenateMagickString(tuple,",",MagickPathExtent);
cristyed231572011-07-14 02:18:59 +00007504 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007505 }
cristy151b66d2015-04-15 10:50:31 +00007506 (void) ConcatenateMagickString(tuple,")",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00007507 height=(unsigned int) windows->magnify.font_info->ascent+
7508 windows->magnify.font_info->descent;
7509 x=windows->magnify.font_info->max_bounds.width >> 1;
7510 y=windows->magnify.font_info->ascent+(height >> 2);
7511 (void) XDrawImageString(display,windows->magnify.pixmap,
7512 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7513 GetColorTuple(&pixel,MagickTrue,tuple);
7514 y+=height;
7515 (void) XDrawImageString(display,windows->magnify.pixmap,
7516 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007517 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007518 exception);
cristy3ed852e2009-09-05 21:47:34 +00007519 y+=height;
7520 (void) XDrawImageString(display,windows->magnify.pixmap,
7521 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7522 /*
7523 Refresh magnify window.
7524 */
7525 magnify_window=windows->magnify;
7526 magnify_window.x=0;
7527 magnify_window.y=0;
7528 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7529}
7530
7531/*
7532%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7533% %
7534% %
7535% %
7536% X M a k e P i x m a p %
7537% %
7538% %
7539% %
7540%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7541%
7542% XMakePixmap() creates an X11 pixmap.
7543%
7544% The format of the XMakePixmap method is:
7545%
7546% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7547% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7548% XPixelInfo *pixel)
7549%
7550% A description of each parameter follows:
7551%
7552% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7553%
7554% o display: Specifies a connection to an X server; returned from
7555% XOpenDisplay.
7556%
7557% o window: Specifies a pointer to a XWindowInfo structure.
7558%
cristy3ed852e2009-09-05 21:47:34 +00007559*/
7560static MagickBooleanType XMakePixmap(Display *display,
7561 const XResourceInfo *resource_info,XWindowInfo *window)
7562{
7563 unsigned int
7564 height,
7565 width;
7566
7567 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7568 assert(display != (Display *) NULL);
7569 assert(resource_info != (XResourceInfo *) NULL);
7570 assert(window != (XWindowInfo *) NULL);
7571 if (window->pixmap != (Pixmap) NULL)
7572 {
7573 /*
7574 Destroy previous X pixmap.
7575 */
7576 (void) XFreePixmap(display,window->pixmap);
7577 window->pixmap=(Pixmap) NULL;
7578 }
7579 if (window->use_pixmap == MagickFalse)
7580 return(MagickFalse);
7581 if (window->ximage == (XImage *) NULL)
7582 return(MagickFalse);
7583 /*
7584 Display busy cursor.
7585 */
7586 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7587 (void) XFlush(display);
7588 /*
7589 Create pixmap.
7590 */
7591 width=(unsigned int) window->ximage->width;
7592 height=(unsigned int) window->ximage->height;
7593 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7594 if (window->pixmap == (Pixmap) NULL)
7595 {
7596 /*
7597 Unable to allocate pixmap.
7598 */
7599 (void) XCheckDefineCursor(display,window->id,window->cursor);
7600 return(MagickFalse);
7601 }
7602 /*
7603 Copy X image to pixmap.
7604 */
7605#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7606 if (window->shared_memory)
7607 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7608 window->ximage,0,0,0,0,width,height,MagickTrue);
7609#endif
7610 if (window->shared_memory == MagickFalse)
7611 (void) XPutImage(display,window->pixmap,window->annotate_context,
7612 window->ximage,0,0,0,0,width,height);
7613 if (IsEventLogging())
7614 {
7615 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7616 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7617 width,height);
7618 }
7619 /*
7620 Restore cursor.
7621 */
7622 (void) XCheckDefineCursor(display,window->id,window->cursor);
7623 return(MagickTrue);
7624}
7625
7626/*
7627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7628% %
7629% %
7630% %
7631% X M a k e S t a n d a r d C o l o r m a p %
7632% %
7633% %
7634% %
7635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7636%
7637% XMakeStandardColormap() creates an X11 Standard Colormap.
7638%
7639% The format of the XMakeStandardColormap method is:
7640%
cristy6710d842011-10-20 23:23:00 +00007641% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7642% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7643% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007644%
7645% A description of each parameter follows:
7646%
7647% o display: Specifies a connection to an X server; returned from
7648% XOpenDisplay.
7649%
7650% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7651% returned from XGetVisualInfo.
7652%
7653% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7654%
7655% o image: the image.
7656%
7657% o map_info: If a Standard Colormap type is specified, this structure is
7658% initialized with info from the Standard Colormap.
7659%
7660% o pixel: Specifies a pointer to a XPixelInfo structure.
7661%
cristy6710d842011-10-20 23:23:00 +00007662% o exception: return any errors or warnings in this structure.
7663%
cristy3ed852e2009-09-05 21:47:34 +00007664*/
7665
7666#if defined(__cplusplus) || defined(c_plusplus)
7667extern "C" {
7668#endif
7669
cristya19f1d72012-08-07 18:24:38 +00007670static inline double DiversityPixelIntensity(
cristy3ed852e2009-09-05 21:47:34 +00007671 const DiversityPacket *pixel)
7672{
cristya19f1d72012-08-07 18:24:38 +00007673 double
cristy3ed852e2009-09-05 21:47:34 +00007674 intensity;
7675
cristyd3d2a272013-06-24 16:09:41 +00007676 intensity=0.212656*pixel->red+0.715158*pixel->green+0.072186*pixel->blue;
cristy3ed852e2009-09-05 21:47:34 +00007677 return(intensity);
7678}
7679
7680static int IntensityCompare(const void *x,const void *y)
7681{
7682 DiversityPacket
7683 *color_1,
7684 *color_2;
7685
7686 int
7687 diversity;
7688
7689 color_1=(DiversityPacket *) x;
7690 color_2=(DiversityPacket *) y;
7691 diversity=(int) (DiversityPixelIntensity(color_2)-
7692 DiversityPixelIntensity(color_1));
7693 return(diversity);
7694}
7695
7696static int PopularityCompare(const void *x,const void *y)
7697{
7698 DiversityPacket
7699 *color_1,
7700 *color_2;
7701
7702 color_1=(DiversityPacket *) x;
7703 color_2=(DiversityPacket *) y;
7704 return((int) color_2->count-(int) color_1->count);
7705}
7706
7707#if defined(__cplusplus) || defined(c_plusplus)
7708}
7709#endif
7710
cristybb503372010-05-27 20:51:26 +00007711static inline Quantum ScaleXToQuantum(const size_t x,
7712 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007713{
cristya19f1d72012-08-07 18:24:38 +00007714 return((Quantum) (((double) QuantumRange*x)/scale+0.5));
cristy3ed852e2009-09-05 21:47:34 +00007715}
7716
cristybcbda3f2011-09-03 13:01:22 +00007717MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007718 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007719 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007720{
7721 Colormap
7722 colormap;
7723
cristybb503372010-05-27 20:51:26 +00007724 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007725 i;
7726
7727 Status
7728 status;
7729
cristybb503372010-05-27 20:51:26 +00007730 size_t
cristy3ed852e2009-09-05 21:47:34 +00007731 number_colors,
7732 retain_colors;
7733
7734 unsigned short
7735 gray_value;
7736
7737 XColor
7738 color,
7739 *colors,
7740 *p;
7741
7742 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7743 assert(display != (Display *) NULL);
7744 assert(visual_info != (XVisualInfo *) NULL);
7745 assert(map_info != (XStandardColormap *) NULL);
7746 assert(resource_info != (XResourceInfo *) NULL);
7747 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007748 if (resource_info->map_type != (char *) NULL)
7749 {
7750 /*
7751 Standard Colormap is already defined (i.e. xstdcmap).
7752 */
cristy4c08aed2011-07-01 19:47:50 +00007753 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007754 pixel);
7755 number_colors=(unsigned int) (map_info->base_pixel+
7756 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7757 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
cristy17f11b02014-12-20 19:37:04 +00007758 if ((image->alpha_trait == UndefinedPixelTrait) &&
cristy3ed852e2009-09-05 21:47:34 +00007759 (resource_info->color_recovery == MagickFalse) &&
cristycbda6112012-05-27 20:57:16 +00007760 (resource_info->quantize_info->dither_method != NoDitherMethod) &&
cristy3ed852e2009-09-05 21:47:34 +00007761 (number_colors < MaxColormapSize))
7762 {
7763 Image
7764 *affinity_image;
7765
cristy4c08aed2011-07-01 19:47:50 +00007766 register Quantum
dirk05d2ff72015-11-18 23:13:43 +01007767 *magick_restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007768
7769 /*
7770 Improve image appearance with error diffusion.
7771 */
cristy6710d842011-10-20 23:23:00 +00007772 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007773 if (affinity_image == (Image *) NULL)
7774 ThrowXWindowFatalException(ResourceLimitFatalError,
7775 "UnableToDitherImage",image->filename);
7776 affinity_image->columns=number_colors;
7777 affinity_image->rows=1;
7778 /*
7779 Initialize colormap image.
7780 */
7781 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7782 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007783 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007784 {
cristybb503372010-05-27 20:51:26 +00007785 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007786 {
cristy4c08aed2011-07-01 19:47:50 +00007787 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007788 if (map_info->red_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007789 SetPixelRed(affinity_image,ScaleXToQuantum((size_t)
7790 (i/map_info->red_mult),map_info->red_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007791 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007792 if (map_info->green_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007793 SetPixelGreen(affinity_image,ScaleXToQuantum((size_t)
7794 ((i/map_info->green_mult) % (map_info->green_max+1)),
7795 map_info->green_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007796 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007797 if (map_info->blue_max != 0)
cristy534d0a32013-04-13 16:27:24 +00007798 SetPixelBlue(affinity_image,ScaleXToQuantum((size_t)
7799 (i % map_info->green_mult),map_info->blue_max),q);
cristy4c08aed2011-07-01 19:47:50 +00007800 SetPixelAlpha(affinity_image,
7801 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007802 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007803 }
7804 (void) SyncAuthenticPixels(affinity_image,exception);
7805 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007806 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007807 }
cristy4c08aed2011-07-01 19:47:50 +00007808 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007809 pixel);
cristy574cc262011-08-05 01:23:58 +00007810 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007811 affinity_image=DestroyImage(affinity_image);
7812 }
7813 if (IsEventLogging())
7814 {
7815 (void) LogMagickEvent(X11Event,GetMagickModule(),
7816 "Standard Colormap:");
7817 (void) LogMagickEvent(X11Event,GetMagickModule(),
7818 " colormap id: 0x%lx",map_info->colormap);
7819 (void) LogMagickEvent(X11Event,GetMagickModule(),
7820 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7821 map_info->green_max,map_info->blue_max);
7822 (void) LogMagickEvent(X11Event,GetMagickModule(),
7823 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7824 map_info->green_mult,map_info->blue_mult);
7825 }
7826 return;
7827 }
7828 if ((visual_info->klass != DirectColor) &&
7829 (visual_info->klass != TrueColor))
7830 if ((image->storage_class == DirectClass) ||
7831 ((int) image->colors > visual_info->colormap_size))
7832 {
7833 QuantizeInfo
7834 quantize_info;
7835
7836 /*
7837 Image has more colors than the visual supports.
7838 */
7839 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007840 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007841 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007842 }
7843 /*
7844 Free previous and create new colormap.
7845 */
7846 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7847 colormap=XDefaultColormap(display,visual_info->screen);
7848 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7849 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7850 visual_info->visual,visual_info->klass == DirectColor ?
7851 AllocAll : AllocNone);
7852 if (colormap == (Colormap) NULL)
7853 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7854 image->filename);
7855 /*
7856 Initialize the map and pixel info structures.
7857 */
7858 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007859 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007860 /*
7861 Allocating colors in server colormap is based on visual class.
7862 */
7863 switch (visual_info->klass)
7864 {
7865 case StaticGray:
7866 case StaticColor:
7867 {
7868 /*
7869 Define Standard Colormap for StaticGray or StaticColor visual.
7870 */
7871 number_colors=image->colors;
7872 colors=(XColor *) AcquireQuantumMemory((size_t)
7873 visual_info->colormap_size,sizeof(*colors));
7874 if (colors == (XColor *) NULL)
7875 ThrowXWindowFatalException(ResourceLimitFatalError,
7876 "UnableToCreateColormap",image->filename);
7877 p=colors;
7878 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007879 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007880 {
7881 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7882 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7883 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7884 if (visual_info->klass != StaticColor)
7885 {
7886 gray_value=(unsigned short) XPixelIntensity(&color);
7887 color.red=gray_value;
7888 color.green=gray_value;
7889 color.blue=gray_value;
7890 }
7891 status=XAllocColor(display,colormap,&color);
7892 if (status == False)
7893 {
7894 colormap=XCopyColormapAndFree(display,colormap);
7895 (void) XAllocColor(display,colormap,&color);
7896 }
7897 pixel->pixels[i]=color.pixel;
7898 *p++=color;
7899 }
7900 break;
7901 }
7902 case GrayScale:
7903 case PseudoColor:
7904 {
7905 unsigned int
7906 colormap_type;
7907
7908 /*
7909 Define Standard Colormap for GrayScale or PseudoColor visual.
7910 */
7911 number_colors=image->colors;
7912 colors=(XColor *) AcquireQuantumMemory((size_t)
7913 visual_info->colormap_size,sizeof(*colors));
7914 if (colors == (XColor *) NULL)
7915 ThrowXWindowFatalException(ResourceLimitFatalError,
7916 "UnableToCreateColormap",image->filename);
7917 /*
7918 Preallocate our GUI colors.
7919 */
7920 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7921 (void) XAllocColor(display,colormap,&pixel->background_color);
7922 (void) XAllocColor(display,colormap,&pixel->border_color);
7923 (void) XAllocColor(display,colormap,&pixel->matte_color);
7924 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7925 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7926 (void) XAllocColor(display,colormap,&pixel->depth_color);
7927 (void) XAllocColor(display,colormap,&pixel->trough_color);
7928 for (i=0; i < MaxNumberPens; i++)
7929 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7930 /*
7931 Determine if image colors will "fit" into X server colormap.
7932 */
7933 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007934 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007935 NULL,0,pixel->pixels,(unsigned int) image->colors);
7936 if (status != False)
7937 colormap_type=PrivateColormap;
7938 if (colormap_type == SharedColormap)
7939 {
cristyc57f6942010-11-12 01:47:39 +00007940 CacheView
7941 *image_view;
7942
cristy3ed852e2009-09-05 21:47:34 +00007943 DiversityPacket
7944 *diversity;
7945
7946 int
7947 y;
7948
7949 register int
7950 x;
7951
7952 unsigned short
7953 index;
7954
7955 XColor
7956 *server_colors;
7957
7958 /*
7959 Define Standard colormap for shared GrayScale or PseudoColor visual.
7960 */
7961 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7962 sizeof(*diversity));
7963 if (diversity == (DiversityPacket *) NULL)
7964 ThrowXWindowFatalException(ResourceLimitFatalError,
7965 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007966 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007967 {
cristye42f6582012-02-11 17:59:50 +00007968 diversity[i].red=ClampToQuantum(image->colormap[i].red);
7969 diversity[i].green=ClampToQuantum(image->colormap[i].green);
7970 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00007971 diversity[i].index=(unsigned short) i;
7972 diversity[i].count=0;
7973 }
cristy46ff2672012-12-14 15:32:26 +00007974 image_view=AcquireAuthenticCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007975 for (y=0; y < (int) image->rows; y++)
7976 {
cristyc57f6942010-11-12 01:47:39 +00007977 register int
cristy3ed852e2009-09-05 21:47:34 +00007978 x;
7979
cristy4c08aed2011-07-01 19:47:50 +00007980 register const Quantum
dirk05d2ff72015-11-18 23:13:43 +01007981 *magick_restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007982
cristyc57f6942010-11-12 01:47:39 +00007983 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7984 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007985 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007986 break;
cristyc57f6942010-11-12 01:47:39 +00007987 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00007988 {
7989 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00007990 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00007991 }
cristy3ed852e2009-09-05 21:47:34 +00007992 }
cristyc57f6942010-11-12 01:47:39 +00007993 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00007994 /*
7995 Sort colors by decreasing intensity.
7996 */
7997 qsort((void *) diversity,image->colors,sizeof(*diversity),
7998 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00007999 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008000 {
8001 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008002 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008003 }
8004 diversity[image->colors-1].count<<=4;
8005 qsort((void *) diversity,image->colors,sizeof(*diversity),
8006 PopularityCompare);
8007 /*
8008 Allocate colors.
8009 */
8010 p=colors;
8011 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008012 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008013 {
8014 index=diversity[i].index;
8015 color.red=
8016 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8017 color.green=
8018 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8019 color.blue=
8020 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8021 if (visual_info->klass != PseudoColor)
8022 {
8023 gray_value=(unsigned short) XPixelIntensity(&color);
8024 color.red=gray_value;
8025 color.green=gray_value;
8026 color.blue=gray_value;
8027 }
8028 status=XAllocColor(display,colormap,&color);
8029 if (status == False)
8030 break;
8031 pixel->pixels[index]=color.pixel;
8032 *p++=color;
8033 }
8034 /*
8035 Read X server colormap.
8036 */
8037 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8038 visual_info->colormap_size,sizeof(*server_colors));
8039 if (server_colors == (XColor *) NULL)
8040 ThrowXWindowFatalException(ResourceLimitFatalError,
8041 "UnableToCreateColormap",image->filename);
8042 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008043 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008044 (void) XQueryColors(display,colormap,server_colors,
8045 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8046 /*
8047 Select remaining colors from X server colormap.
8048 */
cristybb503372010-05-27 20:51:26 +00008049 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008050 {
8051 index=diversity[i].index;
cristy534d0a32013-04-13 16:27:24 +00008052 color.red=ScaleQuantumToShort(
8053 XRedGamma(image->colormap[index].red));
8054 color.green=ScaleQuantumToShort(
8055 XGreenGamma(image->colormap[index].green));
8056 color.blue=ScaleQuantumToShort(
8057 XBlueGamma(image->colormap[index].blue));
cristy3ed852e2009-09-05 21:47:34 +00008058 if (visual_info->klass != PseudoColor)
8059 {
8060 gray_value=(unsigned short) XPixelIntensity(&color);
8061 color.red=gray_value;
8062 color.green=gray_value;
8063 color.blue=gray_value;
8064 }
8065 XBestPixel(display,colormap,server_colors,(unsigned int)
8066 visual_info->colormap_size,&color);
8067 pixel->pixels[index]=color.pixel;
8068 *p++=color;
8069 }
8070 if ((int) image->colors < visual_info->colormap_size)
8071 {
8072 /*
8073 Fill up colors array-- more choices for pen colors.
8074 */
8075 retain_colors=MagickMin((unsigned int)
8076 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008077 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008078 *p++=server_colors[i];
8079 number_colors+=retain_colors;
8080 }
8081 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8082 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8083 break;
8084 }
8085 /*
8086 Define Standard colormap for private GrayScale or PseudoColor visual.
8087 */
8088 if (status == False)
8089 {
8090 /*
8091 Not enough colormap entries in the colormap-- Create a new colormap.
8092 */
8093 colormap=XCreateColormap(display,
8094 XRootWindow(display,visual_info->screen),visual_info->visual,
8095 AllocNone);
8096 if (colormap == (Colormap) NULL)
8097 ThrowXWindowFatalException(ResourceLimitFatalError,
8098 "UnableToCreateColormap",image->filename);
8099 map_info->colormap=colormap;
8100 if ((int) image->colors < visual_info->colormap_size)
8101 {
8102 /*
8103 Retain colors from the default colormap to help lessens the
8104 effects of colormap flashing.
8105 */
8106 retain_colors=MagickMin((unsigned int)
8107 (visual_info->colormap_size-image->colors),256);
8108 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008109 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008110 {
cristyc57f6942010-11-12 01:47:39 +00008111 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008112 p++;
8113 }
8114 (void) XQueryColors(display,
8115 XDefaultColormap(display,visual_info->screen),
8116 colors+image->colors,(int) retain_colors);
8117 /*
8118 Transfer colors from default to private colormap.
8119 */
8120 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008121 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008122 retain_colors);
8123 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008124 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008125 {
8126 p->pixel=pixel->pixels[i];
8127 p++;
8128 }
8129 (void) XStoreColors(display,colormap,colors+image->colors,
8130 (int) retain_colors);
8131 number_colors+=retain_colors;
8132 }
8133 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008134 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008135 image->colors);
8136 }
8137 /*
8138 Store the image colormap.
8139 */
8140 p=colors;
8141 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008142 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008143 {
8144 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8145 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8146 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8147 if (visual_info->klass != PseudoColor)
8148 {
8149 gray_value=(unsigned short) XPixelIntensity(&color);
8150 color.red=gray_value;
8151 color.green=gray_value;
8152 color.blue=gray_value;
8153 }
8154 color.pixel=pixel->pixels[i];
8155 *p++=color;
8156 }
8157 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8158 break;
8159 }
8160 case TrueColor:
8161 case DirectColor:
8162 default:
8163 {
8164 MagickBooleanType
8165 linear_colormap;
8166
8167 /*
8168 Define Standard Colormap for TrueColor or DirectColor visual.
8169 */
8170 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8171 (map_info->green_max*map_info->green_mult)+
8172 (map_info->blue_max*map_info->blue_mult)+1);
8173 linear_colormap=(number_colors > 4096) ||
8174 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8175 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8176 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8177 MagickTrue : MagickFalse;
8178 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008179 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008180 /*
8181 Allocate color array.
8182 */
8183 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8184 if (colors == (XColor *) NULL)
8185 ThrowXWindowFatalException(ResourceLimitFatalError,
8186 "UnableToCreateColormap",image->filename);
8187 /*
8188 Initialize linear color ramp.
8189 */
8190 p=colors;
8191 color.flags=(char) (DoRed | DoGreen | DoBlue);
8192 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008193 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008194 {
8195 color.blue=(unsigned short) 0;
8196 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008197 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008198 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8199 color.green=color.blue;
8200 color.red=color.blue;
8201 color.pixel=XStandardPixel(map_info,&color);
8202 *p++=color;
8203 }
8204 else
cristybb503372010-05-27 20:51:26 +00008205 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008206 {
8207 color.red=(unsigned short) 0;
8208 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008209 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008210 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8211 color.green=(unsigned int) 0;
8212 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008213 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008214 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8215 map_info->green_max));
8216 color.blue=(unsigned short) 0;
8217 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008218 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008219 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8220 color.pixel=XStandardPixel(map_info,&color);
8221 *p++=color;
8222 }
8223 if ((visual_info->klass == DirectColor) &&
8224 (colormap != XDefaultColormap(display,visual_info->screen)))
8225 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8226 else
cristybb503372010-05-27 20:51:26 +00008227 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008228 (void) XAllocColor(display,colormap,&colors[i]);
8229 break;
8230 }
8231 }
8232 if ((visual_info->klass != DirectColor) &&
8233 (visual_info->klass != TrueColor))
8234 {
8235 /*
8236 Set foreground, background, border, etc. pixels.
8237 */
8238 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8239 &pixel->foreground_color);
8240 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8241 &pixel->background_color);
8242 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8243 {
8244 /*
8245 Foreground and background colors must differ.
8246 */
8247 pixel->background_color.red=(~pixel->foreground_color.red);
8248 pixel->background_color.green=
8249 (~pixel->foreground_color.green);
8250 pixel->background_color.blue=
8251 (~pixel->foreground_color.blue);
8252 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8253 &pixel->background_color);
8254 }
8255 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8256 &pixel->border_color);
8257 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8258 &pixel->matte_color);
8259 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8260 &pixel->highlight_color);
8261 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8262 &pixel->shadow_color);
8263 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8264 &pixel->depth_color);
8265 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8266 &pixel->trough_color);
8267 for (i=0; i < MaxNumberPens; i++)
8268 {
8269 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8270 &pixel->pen_colors[i]);
8271 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8272 }
cristyc57f6942010-11-12 01:47:39 +00008273 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008274 }
8275 colors=(XColor *) RelinquishMagickMemory(colors);
8276 if (IsEventLogging())
8277 {
8278 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8279 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8280 map_info->colormap);
8281 (void) LogMagickEvent(X11Event,GetMagickModule(),
8282 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8283 map_info->green_max,map_info->blue_max);
8284 (void) LogMagickEvent(X11Event,GetMagickModule(),
8285 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8286 map_info->green_mult,map_info->blue_mult);
8287 }
8288}
8289
8290/*
8291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8292% %
8293% %
8294% %
8295% X M a k e W i n d o w %
8296% %
8297% %
8298% %
8299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8300%
8301% XMakeWindow() creates an X11 window.
8302%
8303% The format of the XMakeWindow method is:
8304%
8305% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8306% XClassHint *class_hint,XWMHints *manager_hints,
8307% XWindowInfo *window_info)
8308%
8309% A description of each parameter follows:
8310%
8311% o display: Specifies a connection to an X server; returned from
8312% XOpenDisplay.
8313%
8314% o parent: Specifies the parent window_info.
8315%
8316% o argv: Specifies the application's argument list.
8317%
8318% o argc: Specifies the number of arguments.
8319%
8320% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8321%
8322% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8323%
8324% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8325%
8326*/
cristybcbda3f2011-09-03 13:01:22 +00008327MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008328 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8329 XWindowInfo *window_info)
8330{
8331#define MinWindowSize 64
8332
8333 Atom
8334 atom_list[2];
8335
8336 int
8337 gravity;
8338
8339 static XTextProperty
8340 icon_name,
8341 window_name;
8342
8343 Status
8344 status;
8345
8346 XSizeHints
8347 *size_hints;
8348
8349 /*
8350 Set window info hints.
8351 */
8352 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8353 assert(display != (Display *) NULL);
8354 assert(window_info != (XWindowInfo *) NULL);
8355 size_hints=XAllocSizeHints();
8356 if (size_hints == (XSizeHints *) NULL)
8357 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008358 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008359 size_hints->x=window_info->x;
8360 size_hints->y=window_info->y;
8361 size_hints->width=(int) window_info->width;
8362 size_hints->height=(int) window_info->height;
8363 if (window_info->immutable != MagickFalse)
8364 {
8365 /*
8366 Window size cannot be changed.
8367 */
8368 size_hints->min_width=size_hints->width;
8369 size_hints->min_height=size_hints->height;
8370 size_hints->max_width=size_hints->width;
8371 size_hints->max_height=size_hints->height;
8372 size_hints->flags|=PMinSize;
8373 size_hints->flags|=PMaxSize;
8374 }
8375 else
8376 {
8377 /*
8378 Window size can be changed.
8379 */
8380 size_hints->min_width=(int) window_info->min_width;
8381 size_hints->min_height=(int) window_info->min_height;
8382 size_hints->flags|=PResizeInc;
8383 size_hints->width_inc=(int) window_info->width_inc;
8384 size_hints->height_inc=(int) window_info->height_inc;
8385#if !defined(PRE_R4_ICCCM)
8386 size_hints->flags|=PBaseSize;
8387 size_hints->base_width=size_hints->width_inc;
8388 size_hints->base_height=size_hints->height_inc;
8389#endif
8390 }
8391 gravity=NorthWestGravity;
8392 if (window_info->geometry != (char *) NULL)
8393 {
8394 char
cristy151b66d2015-04-15 10:50:31 +00008395 default_geometry[MagickPathExtent],
8396 geometry[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00008397
8398 int
8399 flags;
8400
8401 register char
8402 *p;
8403
8404 /*
8405 User specified geometry.
8406 */
cristy151b66d2015-04-15 10:50:31 +00008407 (void) FormatLocaleString(default_geometry,MagickPathExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008408 size_hints->width,size_hints->height);
cristy151b66d2015-04-15 10:50:31 +00008409 (void) CopyMagickString(geometry,window_info->geometry,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00008410 p=geometry;
8411 while (strlen(p) != 0)
8412 {
8413 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8414 p++;
8415 else
cristy151b66d2015-04-15 10:50:31 +00008416 (void) CopyMagickString(p,p+1,MagickPathExtent-(p-geometry));
cristy3ed852e2009-09-05 21:47:34 +00008417 }
8418 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8419 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8420 &size_hints->width,&size_hints->height,&gravity);
8421 if ((flags & WidthValue) && (flags & HeightValue))
8422 size_hints->flags|=USSize;
8423 if ((flags & XValue) && (flags & YValue))
8424 {
8425 size_hints->flags|=USPosition;
8426 window_info->x=size_hints->x;
8427 window_info->y=size_hints->y;
8428 }
8429 }
8430#if !defined(PRE_R4_ICCCM)
8431 size_hints->win_gravity=gravity;
8432 size_hints->flags|=PWinGravity;
8433#endif
8434 if (window_info->id == (Window) NULL)
8435 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8436 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8437 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008438 window_info->visual,(unsigned long) window_info->mask,
8439 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008440 else
8441 {
8442 MagickStatusType
8443 mask;
8444
8445 XEvent
8446 sans_event;
8447
8448 XWindowChanges
8449 window_changes;
8450
8451 /*
8452 Window already exists; change relevant attributes.
8453 */
cristyc57f6942010-11-12 01:47:39 +00008454 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8455 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008456 mask=ConfigureNotify;
8457 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8458 window_changes.x=window_info->x;
8459 window_changes.y=window_info->y;
8460 window_changes.width=(int) window_info->width;
8461 window_changes.height=(int) window_info->height;
8462 mask=(MagickStatusType) (CWWidth | CWHeight);
8463 if (window_info->flags & USPosition)
8464 mask|=CWX | CWY;
8465 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8466 mask,&window_changes);
8467 }
8468 if (window_info->id == (Window) NULL)
8469 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8470 window_info->name);
8471 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8472 if (status == False)
8473 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8474 window_info->name);
8475 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8476 if (status == False)
8477 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8478 window_info->icon_name);
8479 if (window_info->icon_geometry != (char *) NULL)
8480 {
8481 int
8482 flags,
8483 height,
8484 width;
8485
8486 /*
8487 User specified icon geometry.
8488 */
8489 size_hints->flags|=USPosition;
8490 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8491 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8492 &manager_hints->icon_y,&width,&height,&gravity);
8493 if ((flags & XValue) && (flags & YValue))
8494 manager_hints->flags|=IconPositionHint;
8495 }
8496 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8497 size_hints,manager_hints,class_hint);
8498 if (window_name.value != (void *) NULL)
8499 {
8500 (void) XFree((void *) window_name.value);
8501 window_name.value=(unsigned char *) NULL;
8502 window_name.nitems=0;
8503 }
8504 if (icon_name.value != (void *) NULL)
8505 {
8506 (void) XFree((void *) icon_name.value);
8507 icon_name.value=(unsigned char *) NULL;
8508 icon_name.nitems=0;
8509 }
8510 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8511 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8512 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8513 (void) XFree((void *) size_hints);
8514 if (window_info->shape != MagickFalse)
8515 {
8516#if defined(MAGICKCORE_HAVE_SHAPE)
8517 int
8518 error_base,
8519 event_base;
8520
8521 /*
8522 Can we apply a non-rectangular shaping mask?
8523 */
8524 error_base=0;
8525 event_base=0;
8526 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8527 window_info->shape=MagickFalse;
8528#else
8529 window_info->shape=MagickFalse;
8530#endif
8531 }
8532 if (window_info->shared_memory)
8533 {
8534#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8535 /*
8536 Can we use shared memory with this window?
8537 */
8538 if (XShmQueryExtension(display) == 0)
8539 window_info->shared_memory=MagickFalse;
8540#else
8541 window_info->shared_memory=MagickFalse;
8542#endif
8543 }
8544 window_info->image=NewImageList();
8545 window_info->destroy=MagickFalse;
8546}
8547
8548/*
8549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8550% %
8551% %
8552% %
8553% X M a g i c k P r o g r e s s M o n i t o r %
8554% %
8555% %
8556% %
8557%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8558%
8559% XMagickProgressMonitor() displays the progress a task is making in
8560% completing a task.
8561%
8562% The format of the XMagickProgressMonitor method is:
8563%
8564% void XMagickProgressMonitor(const char *task,
8565% const MagickOffsetType quantum,const MagickSizeType span,
8566% void *client_data)
8567%
8568% A description of each parameter follows:
8569%
8570% o task: Identifies the task in progress.
8571%
8572% o quantum: Specifies the quantum position within the span which represents
8573% how much progress has been made in completing a task.
8574%
8575% o span: Specifies the span relative to completing a task.
8576%
8577% o client_data: Pointer to any client data.
8578%
8579*/
8580
8581static const char *GetLocaleMonitorMessage(const char *text)
8582{
8583 char
cristy151b66d2015-04-15 10:50:31 +00008584 message[MagickPathExtent],
8585 tag[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00008586
8587 const char
8588 *locale_message;
8589
8590 register char
8591 *p;
8592
cristy151b66d2015-04-15 10:50:31 +00008593 (void) CopyMagickMemory(tag,text,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00008594 p=strrchr(tag,'/');
8595 if (p != (char *) NULL)
8596 *p='\0';
cristy151b66d2015-04-15 10:50:31 +00008597 (void) FormatLocaleString(message,MagickPathExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008598 locale_message=GetLocaleMessage(message);
8599 if (locale_message == message)
8600 return(text);
8601 return(locale_message);
8602}
8603
cristybcbda3f2011-09-03 13:01:22 +00008604MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008605 const MagickOffsetType quantum,const MagickSizeType span,
8606 void *magick_unused(client_data))
8607{
8608 XWindows
8609 *windows;
8610
8611 windows=XSetWindows((XWindows *) ~0);
8612 if (windows == (XWindows *) NULL)
8613 return(MagickTrue);
8614 if (windows->info.mapped != MagickFalse)
8615 XProgressMonitorWidget(windows->display,windows,
8616 GetLocaleMonitorMessage(tag),quantum,span);
8617 return(MagickTrue);
8618}
8619
8620/*
8621%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8622% %
8623% %
8624% %
8625% X Q u e r y C o l o r D a t a b a s e %
8626% %
8627% %
8628% %
8629%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8630%
cristy9950d572011-10-01 18:22:35 +00008631% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008632% string.
8633%
8634% The format of the XQueryColorDatabase method is:
8635%
cristy9950d572011-10-01 18:22:35 +00008636% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008637%
8638% A description of each parameter follows:
8639%
8640% o target: Specifies the color to lookup in the X color database.
8641%
cristy101ab702011-10-13 13:06:32 +00008642% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008643% color is returned as this value.
8644%
8645*/
cristy9950d572011-10-01 18:22:35 +00008646MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008647 XColor *color)
8648{
8649 Colormap
8650 colormap;
8651
8652 static Display
8653 *display = (Display *) NULL;
8654
8655 Status
8656 status;
8657
8658 XColor
8659 xcolor;
8660
8661 /*
8662 Initialize color return value.
8663 */
8664 assert(color != (XColor *) NULL);
8665 color->red=0;
8666 color->green=0;
8667 color->blue=0;
8668 color->flags=(char) (DoRed | DoGreen | DoBlue);
8669 if ((target == (char *) NULL) || (*target == '\0'))
8670 target="#ffffffffffff";
8671 /*
8672 Let the X server define the color for us.
8673 */
8674 if (display == (Display *) NULL)
8675 display=XOpenDisplay((char *) NULL);
8676 if (display == (Display *) NULL)
8677 {
cristyc38fbf52013-11-03 13:55:54 +00008678 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target);
cristy3ed852e2009-09-05 21:47:34 +00008679 return(MagickFalse);
8680 }
8681 colormap=XDefaultColormap(display,XDefaultScreen(display));
8682 status=XParseColor(display,colormap,(char *) target,&xcolor);
8683 if (status == False)
cristyc38fbf52013-11-03 13:55:54 +00008684 ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target)
cristy3ed852e2009-09-05 21:47:34 +00008685 else
8686 {
8687 color->red=xcolor.red;
8688 color->green=xcolor.green;
8689 color->blue=xcolor.blue;
8690 color->flags=xcolor.flags;
8691 }
8692 return(status != False ? MagickTrue : MagickFalse);
8693}
8694
8695/*
8696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8697% %
8698% %
8699% %
8700% X Q u e r y P o s i t i o n %
8701% %
8702% %
8703% %
8704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8705%
8706% XQueryPosition() gets the pointer coordinates relative to a window.
8707%
8708% The format of the XQueryPosition method is:
8709%
8710% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8711%
8712% A description of each parameter follows:
8713%
8714% o display: Specifies a connection to an X server; returned from
8715% XOpenDisplay.
8716%
8717% o window: Specifies a pointer to a Window.
8718%
8719% o x: Return the x coordinate of the pointer relative to the origin of the
8720% window.
8721%
8722% o y: Return the y coordinate of the pointer relative to the origin of the
8723% window.
8724%
8725*/
cristy534d0a32013-04-13 16:27:24 +00008726MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,
8727 int *y)
cristy3ed852e2009-09-05 21:47:34 +00008728{
8729 int
8730 x_root,
8731 y_root;
8732
8733 unsigned int
8734 mask;
8735
8736 Window
8737 root_window;
8738
8739 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8740 assert(display != (Display *) NULL);
8741 assert(window != (Window) NULL);
8742 assert(x != (int *) NULL);
8743 assert(y != (int *) NULL);
8744 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8745 x,y,&mask);
8746}
8747
8748/*
8749%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8750% %
8751% %
8752% %
8753% X R e f r e s h W i n d o w %
8754% %
8755% %
8756% %
8757%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8758%
8759% XRefreshWindow() refreshes an image in a X window.
8760%
8761% The format of the XRefreshWindow method is:
8762%
8763% void XRefreshWindow(Display *display,const XWindowInfo *window,
8764% const XEvent *event)
8765%
8766% A description of each parameter follows:
8767%
8768% o display: Specifies a connection to an X server; returned from
8769% XOpenDisplay.
8770%
8771% o window: Specifies a pointer to a XWindowInfo structure.
8772%
8773% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8774% the entire image is refreshed.
8775%
8776*/
cristybcbda3f2011-09-03 13:01:22 +00008777MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008778 const XEvent *event)
8779{
8780 int
8781 x,
8782 y;
8783
8784 unsigned int
8785 height,
8786 width;
8787
8788 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8789 assert(display != (Display *) NULL);
8790 assert(window != (XWindowInfo *) NULL);
8791 if (window->ximage == (XImage *) NULL)
8792 return;
8793 if (event != (XEvent *) NULL)
8794 {
8795 /*
8796 Determine geometry from expose event.
8797 */
8798 x=event->xexpose.x;
8799 y=event->xexpose.y;
8800 width=(unsigned int) event->xexpose.width;
8801 height=(unsigned int) event->xexpose.height;
8802 }
8803 else
8804 {
8805 XEvent
8806 sans_event;
8807
8808 /*
8809 Refresh entire window; discard outstanding expose events.
8810 */
8811 x=0;
8812 y=0;
8813 width=window->width;
8814 height=window->height;
8815 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008816 if (window->matte_pixmap != (Pixmap) NULL)
8817 {
8818#if defined(MAGICKCORE_HAVE_SHAPE)
8819 if (window->shape != MagickFalse)
8820 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8821 window->matte_pixmap,ShapeSet);
8822#endif
8823 }
cristy3ed852e2009-09-05 21:47:34 +00008824 }
8825 /*
8826 Check boundary conditions.
8827 */
8828 if ((window->ximage->width-(x+window->x)) < (int) width)
8829 width=(unsigned int) (window->ximage->width-(x+window->x));
8830 if ((window->ximage->height-(y+window->y)) < (int) height)
8831 height=(unsigned int) (window->ximage->height-(y+window->y));
8832 /*
8833 Refresh image.
8834 */
8835 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008836 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008837 if (window->pixmap != (Pixmap) NULL)
8838 {
8839 if (window->depth > 1)
8840 (void) XCopyArea(display,window->pixmap,window->id,
8841 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8842 else
8843 (void) XCopyPlane(display,window->pixmap,window->id,
8844 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8845 1L);
8846 }
8847 else
8848 {
8849#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8850 if (window->shared_memory)
8851 (void) XShmPutImage(display,window->id,window->annotate_context,
8852 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8853#endif
8854 if (window->shared_memory == MagickFalse)
8855 (void) XPutImage(display,window->id,window->annotate_context,
8856 window->ximage,x+window->x,y+window->y,x,y,width,height);
8857 }
8858 if (window->matte_pixmap != (Pixmap) NULL)
8859 (void) XSetClipMask(display,window->annotate_context,None);
8860 (void) XFlush(display);
8861}
8862
8863/*
8864%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8865% %
8866% %
8867% %
8868% X R e m o t e C o m m a n d %
8869% %
8870% %
8871% %
8872%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8873%
8874% XRemoteCommand() forces a remote display(1) to display the specified
8875% image filename.
8876%
8877% The format of the XRemoteCommand method is:
8878%
8879% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8880% const char *filename)
8881%
8882% A description of each parameter follows:
8883%
8884% o display: Specifies a connection to an X server; returned from
8885% XOpenDisplay.
8886%
8887% o window: Specifies the name or id of an X window.
8888%
8889% o filename: the name of the image filename to display.
8890%
8891*/
8892MagickExport MagickBooleanType XRemoteCommand(Display *display,
8893 const char *window,const char *filename)
8894{
8895 Atom
8896 remote_atom;
8897
8898 Window
8899 remote_window,
8900 root_window;
8901
8902 assert(filename != (char *) NULL);
8903 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8904 if (display == (Display *) NULL)
8905 display=XOpenDisplay((char *) NULL);
8906 if (display == (Display *) NULL)
8907 {
8908 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8909 return(MagickFalse);
8910 }
8911 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8912 remote_window=(Window) NULL;
8913 root_window=XRootWindow(display,XDefaultScreen(display));
8914 if (window != (char *) NULL)
8915 {
8916 /*
8917 Search window hierarchy and identify any clients by name or ID.
8918 */
cristy02e64f82013-11-14 16:20:04 +00008919 if (isdigit((int) ((unsigned char) *window)) != 0)
cristy3ed852e2009-09-05 21:47:34 +00008920 remote_window=XWindowByID(display,root_window,(Window)
8921 strtol((char *) window,(char **) NULL,0));
8922 if (remote_window == (Window) NULL)
8923 remote_window=XWindowByName(display,root_window,window);
8924 }
8925 if (remote_window == (Window) NULL)
8926 remote_window=XWindowByProperty(display,root_window,remote_atom);
8927 if (remote_window == (Window) NULL)
8928 {
8929 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8930 filename);
8931 return(MagickFalse);
8932 }
8933 /*
8934 Send remote command.
8935 */
8936 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8937 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8938 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8939 (void) XSync(display,MagickFalse);
8940 return(MagickTrue);
8941}
8942
8943/*
8944%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8945% %
8946% %
8947% %
cristy534d0a32013-04-13 16:27:24 +00008948% X R e n d e r I m a g e %
8949% %
8950% %
8951% %
8952%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8953%
8954% XRenderImage() renders text on the image with an X11 font. It also returns
8955% the bounding box of the text relative to the image.
8956%
8957% The format of the XRenderImage method is:
8958%
8959% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
8960% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
8961%
8962% A description of each parameter follows:
8963%
8964% o image: the image.
8965%
8966% o draw_info: the draw info.
8967%
8968% o offset: (x,y) location of text relative to image.
8969%
8970% o metrics: bounding box of text.
8971%
8972% o exception: return any errors or warnings in this structure.
8973%
8974*/
8975MagickPrivate MagickBooleanType XRenderImage(Image *image,
8976 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
8977 ExceptionInfo *exception)
8978{
8979 const char
8980 *client_name;
8981
8982 DrawInfo
8983 cache_info;
8984
8985 Display
8986 *display;
8987
8988 ImageInfo
8989 *image_info;
8990
8991 MagickBooleanType
8992 status;
8993
8994 size_t
8995 height,
8996 width;
8997
8998 XAnnotateInfo
8999 annotate_info;
9000
9001 XFontStruct
9002 *font_info;
9003
9004 XPixelInfo
9005 pixel;
9006
9007 XResourceInfo
9008 resource_info;
9009
9010 XrmDatabase
9011 resource_database;
9012
9013 XStandardColormap
9014 *map_info;
9015
9016 XVisualInfo
9017 *visual_info;
9018
9019 /*
9020 Open X server connection.
9021 */
9022 display=XOpenDisplay(draw_info->server_name);
9023 if (display == (Display *) NULL)
9024 {
9025 ThrowXWindowException(XServerError,"UnableToOpenXServer",
9026 draw_info->server_name);
9027 return(MagickFalse);
9028 }
9029 /*
9030 Get user defaults from X resource database.
9031 */
9032 (void) XSetErrorHandler(XError);
9033 image_info=AcquireImageInfo();
9034 client_name=GetClientName();
9035 resource_database=XGetResourceDatabase(display,client_name);
9036 XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
9037 resource_info.close_server=MagickFalse;
9038 resource_info.colormap=PrivateColormap;
9039 resource_info.font=AcquireString(draw_info->font);
9040 resource_info.background_color=AcquireString("#ffffffffffff");
9041 resource_info.foreground_color=AcquireString("#000000000000");
9042 map_info=XAllocStandardColormap();
cristy5da5d1e2014-05-24 23:37:48 +00009043 visual_info=(XVisualInfo *) NULL;
9044 font_info=(XFontStruct *) NULL;
9045 pixel.pixels=(unsigned long *) NULL;
cristy534d0a32013-04-13 16:27:24 +00009046 if (map_info == (XStandardColormap *) NULL)
9047 {
9048 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9049 image->filename);
9050 return(MagickFalse);
9051 }
9052 /*
9053 Initialize visual info.
9054 */
9055 visual_info=XBestVisualInfo(display,map_info,&resource_info);
9056 if (visual_info == (XVisualInfo *) NULL)
9057 {
cristy5da5d1e2014-05-24 23:37:48 +00009058 XFreeResources(display,visual_info,map_info,&pixel,font_info,
9059 &resource_info,(XWindowInfo *) NULL);
cristyc38fbf52013-11-03 13:55:54 +00009060 ThrowXWindowException(XServerError,"UnableToGetVisual",image->filename);
cristy534d0a32013-04-13 16:27:24 +00009061 return(MagickFalse);
9062 }
9063 map_info->colormap=(Colormap) NULL;
cristy534d0a32013-04-13 16:27:24 +00009064 /*
9065 Initialize Standard Colormap info.
9066 */
9067 XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
9068 map_info);
9069 XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
9070 &pixel);
9071 pixel.annotate_context=XDefaultGC(display,visual_info->screen);
9072 /*
9073 Initialize font info.
9074 */
9075 font_info=XBestFont(display,&resource_info,MagickFalse);
9076 if (font_info == (XFontStruct *) NULL)
9077 {
cristy534d0a32013-04-13 16:27:24 +00009078 XFreeResources(display,visual_info,map_info,&pixel,font_info,
9079 &resource_info,(XWindowInfo *) NULL);
cristy5da5d1e2014-05-24 23:37:48 +00009080 ThrowXWindowException(XServerError,"UnableToLoadFont",draw_info->font);
cristy534d0a32013-04-13 16:27:24 +00009081 return(MagickFalse);
9082 }
9083 cache_info=(*draw_info);
9084 /*
9085 Initialize annotate info.
9086 */
9087 XGetAnnotateInfo(&annotate_info);
9088 annotate_info.stencil=ForegroundStencil;
9089 if (cache_info.font != draw_info->font)
9090 {
9091 /*
9092 Type name has changed.
9093 */
9094 (void) XFreeFont(display,font_info);
9095 (void) CloneString(&resource_info.font,draw_info->font);
9096 font_info=XBestFont(display,&resource_info,MagickFalse);
9097 if (font_info == (XFontStruct *) NULL)
9098 {
9099 ThrowXWindowException(XServerError,"UnableToLoadFont",
9100 draw_info->font);
9101 return(MagickFalse);
9102 }
9103 }
9104 if (image->debug != MagickFalse)
9105 (void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
9106 "Font %s; pointsize %g",draw_info->font != (char *) NULL ?
9107 draw_info->font : "none",draw_info->pointsize);
9108 cache_info=(*draw_info);
9109 annotate_info.font_info=font_info;
9110 annotate_info.text=(char *) draw_info->text;
9111 annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
9112 strlen(draw_info->text));
9113 annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
9114 metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
9115 metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
9116 metrics->ascent=(double) font_info->ascent+4;
9117 metrics->descent=(double) (-font_info->descent);
9118 metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
9119 metrics->height=font_info->ascent+font_info->descent;
9120 metrics->max_advance=(double) font_info->max_bounds.width;
9121 metrics->bounds.x1=0.0;
9122 metrics->bounds.y1=metrics->descent;
9123 metrics->bounds.x2=metrics->ascent+metrics->descent;
9124 metrics->bounds.y2=metrics->ascent+metrics->descent;
9125 metrics->underline_position=(-2.0);
9126 metrics->underline_thickness=1.0;
9127 if (draw_info->render == MagickFalse)
9128 return(MagickTrue);
9129 if (draw_info->fill.alpha == TransparentAlpha)
9130 return(MagickTrue);
9131 /*
9132 Render fill color.
9133 */
9134 width=annotate_info.width;
9135 height=annotate_info.height;
9136 if ((fabs(draw_info->affine.rx) >= MagickEpsilon) ||
9137 (fabs(draw_info->affine.ry) >= MagickEpsilon))
9138 {
9139 if ((fabs(draw_info->affine.sx-draw_info->affine.sy) < MagickEpsilon) &&
9140 (fabs(draw_info->affine.rx+draw_info->affine.ry) < MagickEpsilon))
9141 annotate_info.degrees=(double) (180.0/MagickPI)*
9142 atan2(draw_info->affine.rx,draw_info->affine.sx);
9143 }
cristy151b66d2015-04-15 10:50:31 +00009144 (void) FormatLocaleString(annotate_info.geometry,MagickPathExtent,
cristy534d0a32013-04-13 16:27:24 +00009145 "%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
9146 ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
9147 draw_info->interline_spacing-0.5));
9148 pixel.pen_color.red=ScaleQuantumToShort(draw_info->fill.red);
9149 pixel.pen_color.green=ScaleQuantumToShort(draw_info->fill.green);
9150 pixel.pen_color.blue=ScaleQuantumToShort(draw_info->fill.blue);
9151 status=XAnnotateImage(display,&pixel,&annotate_info,image,exception);
9152 if (status == 0)
9153 {
9154 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
9155 image->filename);
9156 return(MagickFalse);
9157 }
9158 return(MagickTrue);
9159}
9160
9161/*
9162%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9163% %
9164% %
9165% %
cristy3ed852e2009-09-05 21:47:34 +00009166% X R e t a i n W i n d o w C o l o r s %
9167% %
9168% %
9169% %
9170%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9171%
9172% XRetainWindowColors() sets X11 color resources on a window. This preserves
9173% the colors associated with an image displayed on the window.
9174%
9175% The format of the XRetainWindowColors method is:
9176%
9177% void XRetainWindowColors(Display *display,const Window window)
9178%
9179% A description of each parameter follows:
9180%
9181% o display: Specifies a connection to an X server; returned from
9182% XOpenDisplay.
9183%
9184% o window: Specifies a pointer to a XWindowInfo structure.
9185%
9186*/
9187MagickExport void XRetainWindowColors(Display *display,const Window window)
9188{
9189 Atom
9190 property;
9191
9192 Pixmap
9193 pixmap;
9194
9195 /*
9196 Put property on the window.
9197 */
9198 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9199 assert(display != (Display *) NULL);
9200 assert(window != (Window) NULL);
9201 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9202 if (property == (Atom) NULL)
9203 {
cristyc38fbf52013-11-03 13:55:54 +00009204 ThrowXWindowException(XServerError,"UnableToCreateProperty",
cristy3ed852e2009-09-05 21:47:34 +00009205 "_XSETROOT_ID");
9206 return;
9207 }
9208 pixmap=XCreatePixmap(display,window,1,1,1);
9209 if (pixmap == (Pixmap) NULL)
9210 {
cristyc38fbf52013-11-03 13:55:54 +00009211 ThrowXWindowException(XServerError,"UnableToCreateBitmap","");
cristy3ed852e2009-09-05 21:47:34 +00009212 return;
9213 }
9214 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9215 (unsigned char *) &pixmap,1);
9216 (void) XSetCloseDownMode(display,RetainPermanent);
9217}
9218
9219/*
9220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9221% %
9222% %
9223% %
9224% X S e l e c t W i n d o w %
9225% %
9226% %
9227% %
9228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9229%
9230% XSelectWindow() allows a user to select a window using the mouse. If the
9231% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9232% is returned in the crop_info structure.
9233%
9234% The format of the XSelectWindow function is:
9235%
9236% target_window=XSelectWindow(display,crop_info)
9237%
9238% A description of each parameter follows:
9239%
9240% o window: XSelectWindow returns the window id.
9241%
9242% o display: Specifies a pointer to the Display structure; returned from
9243% XOpenDisplay.
9244%
9245% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9246% contains the extents of any cropping rectangle.
9247%
cristy3ed852e2009-09-05 21:47:34 +00009248*/
9249static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9250{
9251#define MinimumCropArea (unsigned int) 9
9252
9253 Cursor
9254 target_cursor;
9255
9256 GC
9257 annotate_context;
9258
9259 int
9260 presses,
9261 x_offset,
9262 y_offset;
9263
9264 Status
9265 status;
9266
9267 Window
9268 root_window,
9269 target_window;
9270
9271 XEvent
9272 event;
9273
9274 XGCValues
9275 context_values;
9276
9277 /*
9278 Initialize graphic context.
9279 */
9280 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9281 assert(display != (Display *) NULL);
9282 assert(crop_info != (RectangleInfo *) NULL);
9283 root_window=XRootWindow(display,XDefaultScreen(display));
9284 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9285 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9286 context_values.function=GXinvert;
9287 context_values.plane_mask=
9288 context_values.background ^ context_values.foreground;
9289 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009290 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009291 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9292 if (annotate_context == (GC) NULL)
9293 return(MagickFalse);
9294 /*
9295 Grab the pointer using target cursor.
9296 */
9297 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9298 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9299 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9300 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9301 GrabModeAsync,root_window,target_cursor,CurrentTime);
9302 if (status != GrabSuccess)
9303 {
cristyc38fbf52013-11-03 13:55:54 +00009304 ThrowXWindowException(XServerError,"UnableToGrabMouse","");
cristy3ed852e2009-09-05 21:47:34 +00009305 return((Window) NULL);
9306 }
9307 /*
9308 Select a window.
9309 */
9310 crop_info->width=0;
9311 crop_info->height=0;
9312 presses=0;
9313 target_window=(Window) NULL;
9314 x_offset=0;
9315 y_offset=0;
9316 do
9317 {
9318 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9319 (void) XDrawRectangle(display,root_window,annotate_context,
9320 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9321 (unsigned int) crop_info->height-1);
9322 /*
9323 Allow another event.
9324 */
9325 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9326 (void) XWindowEvent(display,root_window,ButtonPressMask |
9327 ButtonReleaseMask | ButtonMotionMask,&event);
9328 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9329 (void) XDrawRectangle(display,root_window,annotate_context,
9330 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9331 (unsigned int) crop_info->height-1);
9332 switch (event.type)
9333 {
9334 case ButtonPress:
9335 {
9336 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9337 event.xbutton.x,event.xbutton.y);
9338 if (target_window == (Window) NULL)
9339 target_window=root_window;
9340 x_offset=event.xbutton.x_root;
9341 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009342 crop_info->x=(ssize_t) x_offset;
9343 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009344 crop_info->width=0;
9345 crop_info->height=0;
9346 presses++;
9347 break;
9348 }
9349 case ButtonRelease:
9350 {
9351 presses--;
9352 break;
9353 }
9354 case MotionNotify:
9355 {
9356 /*
9357 Discard pending button motion events.
9358 */
9359 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009360 crop_info->x=(ssize_t) event.xmotion.x;
9361 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009362 /*
9363 Check boundary conditions.
9364 */
9365 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009366 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009367 else
9368 {
cristyecd0ab52010-05-30 14:59:20 +00009369 crop_info->width=(size_t) (crop_info->x-x_offset);
9370 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009371 }
9372 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009373 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009374 else
9375 {
cristyecd0ab52010-05-30 14:59:20 +00009376 crop_info->height=(size_t) (crop_info->y-y_offset);
9377 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009378 }
9379 }
9380 default:
9381 break;
9382 }
9383 } while ((target_window == (Window) NULL) || (presses > 0));
9384 (void) XUngrabPointer(display,CurrentTime);
9385 (void) XFreeCursor(display,target_cursor);
9386 (void) XFreeGC(display,annotate_context);
9387 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9388 {
9389 crop_info->width=0;
9390 crop_info->height=0;
9391 }
9392 if ((crop_info->width != 0) && (crop_info->height != 0))
9393 target_window=root_window;
9394 return(target_window);
9395}
9396
9397/*
9398%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9399% %
9400% %
9401% %
9402% X S e t C u r s o r S t a t e %
9403% %
9404% %
9405% %
9406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9407%
9408% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9409% reset to their default.
9410%
9411% The format of the XXSetCursorState method is:
9412%
9413% XSetCursorState(display,windows,const MagickStatusType state)
9414%
9415% A description of each parameter follows:
9416%
9417% o display: Specifies a connection to an X server; returned from
9418% XOpenDisplay.
9419%
9420% o windows: Specifies a pointer to a XWindows structure.
9421%
9422% o state: An unsigned integer greater than 0 sets the cursor state
9423% to busy, otherwise the cursor are reset to their default.
9424%
9425*/
cristybcbda3f2011-09-03 13:01:22 +00009426MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009427 const MagickStatusType state)
9428{
9429 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9430 assert(display != (Display *) NULL);
9431 assert(windows != (XWindows *) NULL);
9432 if (state)
9433 {
9434 (void) XCheckDefineCursor(display,windows->image.id,
9435 windows->image.busy_cursor);
9436 (void) XCheckDefineCursor(display,windows->pan.id,
9437 windows->pan.busy_cursor);
9438 (void) XCheckDefineCursor(display,windows->magnify.id,
9439 windows->magnify.busy_cursor);
9440 (void) XCheckDefineCursor(display,windows->command.id,
9441 windows->command.busy_cursor);
9442 }
9443 else
9444 {
9445 (void) XCheckDefineCursor(display,windows->image.id,
9446 windows->image.cursor);
9447 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9448 (void) XCheckDefineCursor(display,windows->magnify.id,
9449 windows->magnify.cursor);
9450 (void) XCheckDefineCursor(display,windows->command.id,
9451 windows->command.cursor);
9452 (void) XCheckDefineCursor(display,windows->command.id,
9453 windows->widget.cursor);
9454 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9455 }
9456 windows->info.mapped=MagickFalse;
9457}
9458
9459/*
9460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9461% %
9462% %
9463% %
9464% X S e t W i n d o w s %
9465% %
9466% %
9467% %
9468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9469%
9470% XSetWindows() sets the X windows structure if the windows info is specified.
9471% Otherwise the current windows structure is returned.
9472%
9473% The format of the XSetWindows method is:
9474%
9475% XWindows *XSetWindows(XWindows *windows_info)
9476%
9477% A description of each parameter follows:
9478%
9479% o windows_info: Initialize the Windows structure with this information.
9480%
9481*/
cristybcbda3f2011-09-03 13:01:22 +00009482MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009483{
9484 static XWindows
9485 *windows = (XWindows *) NULL;
9486
9487 if (windows_info != (XWindows *) ~0)
9488 {
9489 windows=(XWindows *) RelinquishMagickMemory(windows);
9490 windows=windows_info;
9491 }
9492 return(windows);
9493}
9494/*
9495%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9496% %
9497% %
9498% %
9499% X U s e r P r e f e r e n c e s %
9500% %
9501% %
9502% %
9503%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9504%
9505% XUserPreferences() saves the preferences in a configuration file in the
9506% users' home directory.
9507%
9508% The format of the XUserPreferences method is:
9509%
9510% void XUserPreferences(XResourceInfo *resource_info)
9511%
9512% A description of each parameter follows:
9513%
9514% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9515%
9516*/
cristybcbda3f2011-09-03 13:01:22 +00009517MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009518{
9519#if defined(X11_PREFERENCES_PATH)
9520 char
cristy151b66d2015-04-15 10:50:31 +00009521 cache[MagickPathExtent],
9522 filename[MagickPathExtent],
9523 specifier[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00009524
9525 const char
cristy104cea82009-10-25 02:26:51 +00009526 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009527 *value;
9528
9529 XrmDatabase
9530 preferences_database;
9531
9532 /*
9533 Save user preferences to the client configuration file.
9534 */
9535 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009536 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009537 preferences_database=XrmGetStringDatabase("");
cristy151b66d2015-04-15 10:50:31 +00009538 (void) FormatLocaleString(specifier,MagickPathExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009539 value=resource_info->backdrop ? "True" : "False";
9540 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy151b66d2015-04-15 10:50:31 +00009541 (void) FormatLocaleString(specifier,MagickPathExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009542 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9543 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy151b66d2015-04-15 10:50:31 +00009544 (void) FormatLocaleString(specifier,MagickPathExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009545 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009546 value=resource_info->confirm_exit ? "True" : "False";
9547 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy151b66d2015-04-15 10:50:31 +00009548 (void) FormatLocaleString(specifier,MagickPathExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009549 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009550 value=resource_info->confirm_edit ? "True" : "False";
9551 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy151b66d2015-04-15 10:50:31 +00009552 (void) FormatLocaleString(specifier,MagickPathExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009553 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009554 value=resource_info->display_warnings ? "True" : "False";
9555 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy151b66d2015-04-15 10:50:31 +00009556 (void) FormatLocaleString(specifier,MagickPathExtent,"%s.dither",client_name);
cristycbda6112012-05-27 20:57:16 +00009557 value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9558 "True" : "False";
cristy3ed852e2009-09-05 21:47:34 +00009559 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy151b66d2015-04-15 10:50:31 +00009560 (void) FormatLocaleString(specifier,MagickPathExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009561 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009562 value=resource_info->gamma_correct ? "True" : "False";
9563 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy151b66d2015-04-15 10:50:31 +00009564 (void) FormatLocaleString(specifier,MagickPathExtent,"%s.undoCache",client_name);
9565 (void) FormatLocaleString(cache,MagickPathExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009566 resource_info->undo_cache);
9567 XrmPutStringResource(&preferences_database,specifier,cache);
cristy151b66d2015-04-15 10:50:31 +00009568 (void) FormatLocaleString(specifier,MagickPathExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009569 value=resource_info->use_pixmap ? "True" : "False";
9570 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy151b66d2015-04-15 10:50:31 +00009571 (void) FormatLocaleString(filename,MagickPathExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009572 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009573 ExpandFilename(filename);
9574 XrmPutFileDatabase(preferences_database,filename);
9575#endif
9576}
9577
9578/*
9579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9580% %
9581% %
9582% %
9583% X V i s u a l C l a s s N a m e %
9584% %
9585% %
9586% %
9587%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9588%
9589% XVisualClassName() returns the visual class name as a character string.
9590%
9591% The format of the XVisualClassName method is:
9592%
9593% char *XVisualClassName(const int visual_class)
9594%
9595% A description of each parameter follows:
9596%
9597% o visual_type: XVisualClassName returns the visual class as a character
9598% string.
9599%
9600% o class: Specifies the visual class.
9601%
cristy3ed852e2009-09-05 21:47:34 +00009602*/
9603static const char *XVisualClassName(const int visual_class)
9604{
9605 switch (visual_class)
9606 {
9607 case StaticGray: return("StaticGray");
9608 case GrayScale: return("GrayScale");
9609 case StaticColor: return("StaticColor");
9610 case PseudoColor: return("PseudoColor");
9611 case TrueColor: return("TrueColor");
9612 case DirectColor: return("DirectColor");
9613 }
9614 return("unknown visual class");
9615}
9616
9617/*
9618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9619% %
9620% %
9621% %
9622% X W a r n i n g %
9623% %
9624% %
9625% %
9626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9627%
9628% XWarning() displays a warning reason in a Notice widget.
9629%
9630% The format of the XWarning method is:
9631%
9632% void XWarning(const unsigned int warning,const char *reason,
9633% const char *description)
9634%
9635% A description of each parameter follows:
9636%
9637% o warning: Specifies the numeric warning category.
9638%
9639% o reason: Specifies the reason to display before terminating the
9640% program.
9641%
9642% o description: Specifies any description to the reason.
9643%
9644*/
cristybcbda3f2011-09-03 13:01:22 +00009645MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009646 const char *reason,const char *description)
9647{
9648 char
cristy151b66d2015-04-15 10:50:31 +00009649 text[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00009650
9651 XWindows
9652 *windows;
9653
9654 if (reason == (char *) NULL)
9655 return;
cristy151b66d2015-04-15 10:50:31 +00009656 (void) CopyMagickString(text,reason,MagickPathExtent);
9657 (void) ConcatenateMagickString(text,":",MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00009658 windows=XSetWindows((XWindows *) ~0);
9659 XNoticeWidget(windows->display,windows,text,(char *) description);
9660}
9661
9662/*
9663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9664% %
9665% %
9666% %
9667% X W i n d o w B y I D %
9668% %
9669% %
9670% %
9671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9672%
9673% XWindowByID() locates a child window with a given ID. If not window with
9674% the given name is found, 0 is returned. Only the window specified and its
9675% subwindows are searched.
9676%
9677% The format of the XWindowByID function is:
9678%
9679% child=XWindowByID(display,window,id)
9680%
9681% A description of each parameter follows:
9682%
9683% o child: XWindowByID returns the window with the specified
9684% id. If no windows are found, XWindowByID returns 0.
9685%
9686% o display: Specifies a pointer to the Display structure; returned from
9687% XOpenDisplay.
9688%
9689% o id: Specifies the id of the window to locate.
9690%
9691*/
cristybcbda3f2011-09-03 13:01:22 +00009692MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009693 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009694{
9695 RectangleInfo
9696 rectangle_info;
9697
9698 register int
9699 i;
9700
9701 Status
9702 status;
9703
9704 unsigned int
9705 number_children;
9706
9707 Window
9708 child,
9709 *children,
9710 window;
9711
9712 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9713 assert(display != (Display *) NULL);
9714 assert(root_window != (Window) NULL);
9715 if (id == 0)
9716 return(XSelectWindow(display,&rectangle_info));
9717 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009718 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009719 status=XQueryTree(display,root_window,&child,&child,&children,
9720 &number_children);
9721 if (status == False)
9722 return((Window) NULL);
9723 window=(Window) NULL;
9724 for (i=0; i < (int) number_children; i++)
9725 {
9726 /*
9727 Search each child and their children.
9728 */
9729 window=XWindowByID(display,children[i],id);
9730 if (window != (Window) NULL)
9731 break;
9732 }
9733 if (children != (Window *) NULL)
9734 (void) XFree((void *) children);
9735 return(window);
9736}
9737
9738/*
9739%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9740% %
9741% %
9742% %
9743% X W i n d o w B y N a m e %
9744% %
9745% %
9746% %
9747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9748%
9749% XWindowByName() locates a window with a given name on a display. If no
9750% window with the given name is found, 0 is returned. If more than one window
9751% has the given name, the first one is returned. Only root and its children
9752% are searched.
9753%
9754% The format of the XWindowByName function is:
9755%
9756% window=XWindowByName(display,root_window,name)
9757%
9758% A description of each parameter follows:
9759%
9760% o window: XWindowByName returns the window id.
9761%
9762% o display: Specifies a pointer to the Display structure; returned from
9763% XOpenDisplay.
9764%
9765% o root_window: Specifies the id of the root window.
9766%
9767% o name: Specifies the name of the window to locate.
9768%
9769*/
cristybcbda3f2011-09-03 13:01:22 +00009770MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009771 const char *name)
9772{
9773 register int
9774 i;
9775
9776 Status
9777 status;
9778
9779 unsigned int
9780 number_children;
9781
9782 Window
9783 *children,
9784 child,
9785 window;
9786
9787 XTextProperty
9788 window_name;
9789
9790 assert(display != (Display *) NULL);
9791 assert(root_window != (Window) NULL);
9792 assert(name != (char *) NULL);
9793 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9794 if (XGetWMName(display,root_window,&window_name) != 0)
9795 if (LocaleCompare((char *) window_name.value,name) == 0)
9796 return(root_window);
9797 status=XQueryTree(display,root_window,&child,&child,&children,
9798 &number_children);
9799 if (status == False)
9800 return((Window) NULL);
9801 window=(Window) NULL;
9802 for (i=0; i < (int) number_children; i++)
9803 {
9804 /*
9805 Search each child and their children.
9806 */
9807 window=XWindowByName(display,children[i],name);
9808 if (window != (Window) NULL)
9809 break;
9810 }
9811 if (children != (Window *) NULL)
9812 (void) XFree((void *) children);
9813 return(window);
9814}
9815
9816/*
9817%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9818% %
9819% %
9820% %
9821% X W i n d o w B y P r o p e r y %
9822% %
9823% %
9824% %
9825%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9826%
9827% XWindowByProperty() locates a child window with a given property. If not
9828% window with the given name is found, 0 is returned. If more than one window
9829% has the given property, the first one is returned. Only the window
9830% specified and its subwindows are searched.
9831%
9832% The format of the XWindowByProperty function is:
9833%
9834% child=XWindowByProperty(display,window,property)
9835%
9836% A description of each parameter follows:
9837%
9838% o child: XWindowByProperty returns the window id with the specified
9839% property. If no windows are found, XWindowByProperty returns 0.
9840%
9841% o display: Specifies a pointer to the Display structure; returned from
9842% XOpenDisplay.
9843%
9844% o property: Specifies the property of the window to locate.
9845%
9846*/
cristybcbda3f2011-09-03 13:01:22 +00009847MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009848 const Atom property)
9849{
9850 Atom
9851 type;
9852
9853 int
9854 format;
9855
9856 Status
9857 status;
9858
9859 unsigned char
9860 *data;
9861
9862 unsigned int
9863 i,
9864 number_children;
9865
cristyf2faecf2010-05-28 19:19:36 +00009866 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009867 after,
9868 number_items;
9869
9870 Window
9871 child,
9872 *children,
9873 parent,
9874 root;
9875
9876 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9877 assert(display != (Display *) NULL);
9878 assert(window != (Window) NULL);
9879 assert(property != (Atom) NULL);
9880 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9881 if (status == False)
9882 return((Window) NULL);
9883 type=(Atom) NULL;
9884 child=(Window) NULL;
9885 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9886 {
9887 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9888 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9889 if (data != NULL)
9890 (void) XFree((void *) data);
9891 if ((status == Success) && (type != (Atom) NULL))
9892 child=children[i];
9893 }
9894 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9895 child=XWindowByProperty(display,children[i],property);
9896 if (children != (Window *) NULL)
9897 (void) XFree((void *) children);
9898 return(child);
9899}
9900#else
9901
9902/*
9903%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9904% %
9905% %
9906% %
9907% X I m p o r t I m a g e %
9908% %
9909% %
9910% %
9911%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9912%
9913% XImportImage() reads an image from an X window.
9914%
9915% The format of the XImportImage method is:
9916%
cristya0dc96a2011-12-19 23:58:54 +00009917% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9918% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009919%
9920% A description of each parameter follows:
9921%
9922% o image_info: the image info..
9923%
9924% o ximage_info: Specifies a pointer to an XImportInfo structure.
9925%
cristya0dc96a2011-12-19 23:58:54 +00009926% o exception: return any errors or warnings in this structure.
9927%
cristy3ed852e2009-09-05 21:47:34 +00009928*/
cristy4bc52022012-12-13 14:15:41 +00009929MagickExport Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009930 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009931{
9932 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00009933 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00009934 if (image_info->debug != MagickFalse)
9935 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9936 image_info->filename);
9937 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009938 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00009939 assert(exception->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00009940 return((Image *) NULL);
9941}
cristy534d0a32013-04-13 16:27:24 +00009942
9943/*
9944%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9945% %
9946% %
9947% %
9948% X R e n d e r X 1 1 %
9949% %
9950% %
9951% %
9952%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9953%
9954% XRenderImage() renders text on the image with an X11 font. It also returns
9955% the bounding box of the text relative to the image.
9956%
9957% The format of the XRenderImage method is:
9958%
9959% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
9960% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
9961%
9962% A description of each parameter follows:
9963%
9964% o image: the image.
9965%
9966% o draw_info: the draw info.
9967%
9968% o offset: (x,y) location of text relative to image.
9969%
9970% o metrics: bounding box of text.
9971%
9972% o exception: return any errors or warnings in this structure.
9973%
9974*/
9975MagickPrivate MagickBooleanType XRenderImage(Image *image,
9976 const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
9977 ExceptionInfo *exception)
9978{
9979 (void) draw_info;
9980 (void) offset;
9981 (void) metrics;
9982 (void) ThrowMagickException(exception,GetMagickModule(),
9983 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","'%s' (X11)",
9984 image->filename);
9985 return(MagickFalse);
9986}
cristy3ed852e2009-09-05 21:47:34 +00009987#endif
9988
9989/*
9990%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9991% %
9992% %
9993% %
cristy576974e2009-10-25 20:45:31 +00009994+ X C o m p o n e n t G e n e s i s %
9995% %
9996% %
9997% %
9998%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9999%
10000% XComponentGenesis() instantiates the X component.
10001%
10002% The format of the XComponentGenesis method is:
10003%
10004% MagickBooleanType XComponentGenesis(void)
10005%
10006*/
cristy5ff4eaf2011-09-03 01:38:02 +000010007MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +000010008{
10009 return(MagickTrue);
10010}
10011
10012/*
10013%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10014% %
10015% %
10016% %
cristy3ed852e2009-09-05 21:47:34 +000010017% X G e t I m p o r t I n f o %
10018% %
10019% %
10020% %
10021%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10022%
10023% XGetImportInfo() initializes the XImportInfo structure.
10024%
10025% The format of the XGetImportInfo method is:
10026%
10027% void XGetImportInfo(XImportInfo *ximage_info)
10028%
10029% A description of each parameter follows:
10030%
10031% o ximage_info: Specifies a pointer to an ImageInfo structure.
10032%
10033*/
10034MagickExport void XGetImportInfo(XImportInfo *ximage_info)
10035{
10036 assert(ximage_info != (XImportInfo *) NULL);
10037 ximage_info->frame=MagickFalse;
10038 ximage_info->borders=MagickFalse;
10039 ximage_info->screen=MagickFalse;
10040 ximage_info->descend=MagickTrue;
10041 ximage_info->silent=MagickFalse;
10042}