blob: 7584f3a3fee11600fb533dd0c266b9e74648089f [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% X X W W IIIII N N DDDD OOO W W %
7% X X W W I NN N D D O O W W %
8% X W W I N N N D D O O W W %
9% X X W W W I N NN D D O O W W W %
10% X X W W IIIII N N DDDD OOO W W %
11% %
12% %
13% MagickCore X11 Utility Methods %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/animate.h"
44#include "MagickCore/artifact.h"
45#include "MagickCore/blob.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/client.h"
48#include "MagickCore/color.h"
49#include "MagickCore/color-private.h"
50#include "MagickCore/colormap.h"
51#include "MagickCore/composite.h"
cristy030436f2012-01-06 21:56:17 +000052#include "MagickCore/constitute.h"
cristy4c08aed2011-07-01 19:47:50 +000053#include "MagickCore/display.h"
cristyc53413d2011-11-17 13:04:26 +000054#include "MagickCore/distort.h"
cristy4c08aed2011-07-01 19:47:50 +000055#include "MagickCore/exception.h"
56#include "MagickCore/exception-private.h"
57#include "MagickCore/geometry.h"
58#include "MagickCore/identify.h"
59#include "MagickCore/image.h"
60#include "MagickCore/image-private.h"
61#include "MagickCore/list.h"
62#include "MagickCore/locale_.h"
63#include "MagickCore/log.h"
64#include "MagickCore/magick.h"
65#include "MagickCore/memory_.h"
66#include "MagickCore/monitor.h"
cristy2c5fc272012-02-22 01:27:46 +000067#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000068#include "MagickCore/option.h"
69#include "MagickCore/pixel-accessor.h"
70#include "MagickCore/PreRvIcccm.h"
71#include "MagickCore/quantize.h"
72#include "MagickCore/quantum.h"
73#include "MagickCore/quantum-private.h"
74#include "MagickCore/resource_.h"
75#include "MagickCore/resize.h"
cristy4c08aed2011-07-01 19:47:50 +000076#include "MagickCore/statistic.h"
77#include "MagickCore/string_.h"
78#include "MagickCore/string-private.h"
79#include "MagickCore/transform.h"
cristy63a81872012-03-22 15:52:52 +000080#include "MagickCore/token.h"
cristy4c08aed2011-07-01 19:47:50 +000081#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000082#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000083#include "MagickCore/widget.h"
cristybcbda3f2011-09-03 13:01:22 +000084#include "MagickCore/widget-private.h"
cristy4c08aed2011-07-01 19:47:50 +000085#include "MagickCore/xwindow.h"
86#include "MagickCore/xwindow-private.h"
87#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000088#if defined(__BEOS__)
89#include <OS.h>
90#endif
91#if defined(MAGICKCORE_X11_DELEGATE)
92#include <X11/Xproto.h>
93#include <X11/Xlocale.h>
94#if defined(MAGICK_HAVE_POLL)
95# include <sys/poll.h>
96#endif
97#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
98#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
99# include <machine/param.h>
100#endif
101#include <sys/ipc.h>
102#include <sys/shm.h>
103#include <X11/extensions/XShm.h>
104#endif
105#if defined(MAGICKCORE_HAVE_SHAPE)
106#include <X11/extensions/shape.h>
107#endif
108
109/*
110 X defines.
111*/
cristyce70c172010-01-07 17:15:30 +0000112#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000113 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
114 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000115#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000116 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
117 map->red_mult)+ \
118 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
119 map->green_mult)+ \
120 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
121 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000122#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
123 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
124 map->red_mult)+ \
125 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
126 map->green_mult)+ \
127 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
128 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000129#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000130 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
131 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000132#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000133 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
134 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000135#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000136 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
137 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
138 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000139
140#define AccentuateModulate ScaleCharToQuantum(80)
141#define HighlightModulate ScaleCharToQuantum(125)
142#define ShadowModulate ScaleCharToQuantum(135)
143#define DepthModulate ScaleCharToQuantum(185)
144#define TroughModulate ScaleCharToQuantum(110)
145
146#define XLIB_ILLEGAL_ACCESS 1
147#undef ForgetGravity
148#undef NorthWestGravity
149#undef NorthGravity
150#undef NorthEastGravity
151#undef WestGravity
152#undef CenterGravity
153#undef EastGravity
154#undef SouthWestGravity
155#undef SouthGravity
156#undef SouthEastGravity
157#undef StaticGravity
158
159#undef index
160#if defined(hpux9)
161#define XFD_SET int
162#else
163#define XFD_SET fd_set
164#endif
165
166/*
167 Enumeration declarations.
168*/
169typedef enum
170{
171#undef DoRed
172 DoRed = 0x0001,
173#undef DoGreen
174 DoGreen = 0x0002,
175#undef DoBlue
176 DoBlue = 0x0004,
177 DoMatte = 0x0008
178} XColorFlags;
179
180/*
181 Typedef declarations.
182*/
183typedef struct _DiversityPacket
184{
185 Quantum
186 red,
187 green,
188 blue;
189
190 unsigned short
191 index;
192
cristybb503372010-05-27 20:51:26 +0000193 size_t
cristy3ed852e2009-09-05 21:47:34 +0000194 count;
195} DiversityPacket;
196
197/*
198 Constant declaractions.
199*/
200static MagickBooleanType
201 xerror_alert = MagickFalse;
202
203/*
204 Method prototypes.
205*/
206static const char
207 *XVisualClassName(const int);
208
cristya19f1d72012-08-07 18:24:38 +0000209static double
cristy3ed852e2009-09-05 21:47:34 +0000210 blue_gamma = 1.0,
211 green_gamma = 1.0,
212 red_gamma = 1.0;
213
214static MagickBooleanType
215 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
216
217static void
218 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000219 XImage *,XImage *,ExceptionInfo *),
cristy3ed852e2009-09-05 21:47:34 +0000220 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000221 XImage *,XImage *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +0000222
223static Window
224 XSelectWindow(Display *,RectangleInfo *);
225
226/*
227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228% %
229% %
230% %
231% D e s t r o y X R e s o u r c e s %
232% %
233% %
234% %
235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236%
237% DestroyXResources() destroys any X resources.
238%
239% The format of the DestroyXResources method is:
240%
241% void DestroyXResources()
242%
243% A description of each parameter follows:
244%
245*/
246MagickExport void DestroyXResources(void)
247{
248 register int
249 i;
250
251 unsigned int
252 number_windows;
253
254 XWindowInfo
255 *magick_windows[MaxXWindows];
256
257 XWindows
258 *windows;
259
260 DestroyXWidget();
261 windows=XSetWindows((XWindows *) ~0);
262 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
263 return;
264 number_windows=0;
265 magick_windows[number_windows++]=(&windows->context);
266 magick_windows[number_windows++]=(&windows->group_leader);
267 magick_windows[number_windows++]=(&windows->backdrop);
268 magick_windows[number_windows++]=(&windows->icon);
269 magick_windows[number_windows++]=(&windows->image);
270 magick_windows[number_windows++]=(&windows->info);
271 magick_windows[number_windows++]=(&windows->magnify);
272 magick_windows[number_windows++]=(&windows->pan);
273 magick_windows[number_windows++]=(&windows->command);
274 magick_windows[number_windows++]=(&windows->widget);
275 magick_windows[number_windows++]=(&windows->popup);
276 magick_windows[number_windows++]=(&windows->context);
277 for (i=0; i < (int) number_windows; i++)
278 {
279 if (magick_windows[i]->mapped != MagickFalse)
280 {
281 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
282 magick_windows[i]->screen);
283 magick_windows[i]->mapped=MagickFalse;
284 }
285 if (magick_windows[i]->name != (char *) NULL)
286 magick_windows[i]->name=(char *)
287 RelinquishMagickMemory(magick_windows[i]->name);
288 if (magick_windows[i]->icon_name != (char *) NULL)
289 magick_windows[i]->icon_name=(char *)
290 RelinquishMagickMemory(magick_windows[i]->icon_name);
291 if (magick_windows[i]->cursor != (Cursor) NULL)
292 {
293 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
294 magick_windows[i]->cursor=(Cursor) NULL;
295 }
296 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
297 {
298 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
299 magick_windows[i]->busy_cursor=(Cursor) NULL;
300 }
301 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
302 {
303 (void) XFreePixmap(windows->display,
304 magick_windows[i]->highlight_stipple);
305 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
306 }
307 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
308 {
309 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
310 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
311 }
312 if (magick_windows[i]->ximage != (XImage *) NULL)
313 {
314 XDestroyImage(magick_windows[i]->ximage);
315 magick_windows[i]->ximage=(XImage *) NULL;
316 }
317 if (magick_windows[i]->pixmap != (Pixmap) NULL)
318 {
319 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
320 magick_windows[i]->pixmap=(Pixmap) NULL;
321 }
322 if (magick_windows[i]->id != (Window) NULL)
323 {
324 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
325 magick_windows[i]->id=(Window) NULL;
326 }
327 if (magick_windows[i]->destroy != MagickFalse)
328 {
329 if (magick_windows[i]->image != (Image *) NULL)
330 {
331 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
332 magick_windows[i]->image=NewImageList();
333 }
334 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
335 {
336 (void) XFreePixmap(windows->display,
337 magick_windows[i]->matte_pixmap);
338 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
339 }
340 }
341 if (magick_windows[i]->segment_info != (void *) NULL)
342 {
343#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
344 XShmSegmentInfo
345 *segment_info;
346
347 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
348 if (segment_info != (XShmSegmentInfo *) NULL)
349 if (segment_info[0].shmid >= 0)
350 {
351 if (segment_info[0].shmaddr != NULL)
352 (void) shmdt(segment_info[0].shmaddr);
353 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
354 segment_info[0].shmaddr=NULL;
355 segment_info[0].shmid=(-1);
356 }
357#endif
358 magick_windows[i]->segment_info=(void *)
359 RelinquishMagickMemory(magick_windows[i]->segment_info);
360 }
361 }
362 windows->icon_resources=(XResourceInfo *)
363 RelinquishMagickMemory(windows->icon_resources);
364 if (windows->icon_pixel != (XPixelInfo *) NULL)
365 {
cristyf2faecf2010-05-28 19:19:36 +0000366 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
367 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000368 RelinquishMagickMemory(windows->icon_pixel->pixels);
369 if (windows->icon_pixel->annotate_context != (GC) NULL)
370 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
371 windows->icon_pixel=(XPixelInfo *)
372 RelinquishMagickMemory(windows->icon_pixel);
373 }
374 if (windows->pixel_info != (XPixelInfo *) NULL)
375 {
cristyf2faecf2010-05-28 19:19:36 +0000376 if (windows->pixel_info->pixels != (unsigned long *) NULL)
377 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000378 RelinquishMagickMemory(windows->pixel_info->pixels);
379 if (windows->pixel_info->annotate_context != (GC) NULL)
380 XFreeGC(windows->display,windows->pixel_info->annotate_context);
381 if (windows->pixel_info->widget_context != (GC) NULL)
382 XFreeGC(windows->display,windows->pixel_info->widget_context);
383 if (windows->pixel_info->highlight_context != (GC) NULL)
384 XFreeGC(windows->display,windows->pixel_info->highlight_context);
385 windows->pixel_info=(XPixelInfo *)
386 RelinquishMagickMemory(windows->pixel_info);
387 }
388 if (windows->font_info != (XFontStruct *) NULL)
389 {
390 XFreeFont(windows->display,windows->font_info);
391 windows->font_info=(XFontStruct *) NULL;
392 }
393 if (windows->class_hints != (XClassHint *) NULL)
394 {
cristyc9cc4a72011-09-18 02:12:41 +0000395 if (windows->class_hints->res_name != (char *) NULL)
396 windows->class_hints->res_name=DestroyString(
397 windows->class_hints->res_name);
398 if (windows->class_hints->res_class != (char *) NULL)
399 windows->class_hints->res_class=DestroyString(
400 windows->class_hints->res_class);
cristy3ed852e2009-09-05 21:47:34 +0000401 XFree(windows->class_hints);
402 windows->class_hints=(XClassHint *) NULL;
403 }
404 if (windows->manager_hints != (XWMHints *) NULL)
405 {
406 XFree(windows->manager_hints);
407 windows->manager_hints=(XWMHints *) NULL;
408 }
409 if (windows->map_info != (XStandardColormap *) NULL)
410 {
411 XFree(windows->map_info);
412 windows->map_info=(XStandardColormap *) NULL;
413 }
414 if (windows->icon_map != (XStandardColormap *) NULL)
415 {
416 XFree(windows->icon_map);
417 windows->icon_map=(XStandardColormap *) NULL;
418 }
419 if (windows->visual_info != (XVisualInfo *) NULL)
420 {
421 XFree(windows->visual_info);
422 windows->visual_info=(XVisualInfo *) NULL;
423 }
424 if (windows->icon_visual != (XVisualInfo *) NULL)
425 {
426 XFree(windows->icon_visual);
427 windows->icon_visual=(XVisualInfo *) NULL;
428 }
429 (void) XSetWindows((XWindows *) NULL);
430}
431
432/*
433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434% %
435% %
436% %
437% X A n n o t a t e I m a g e %
438% %
439% %
440% %
441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
442%
443% XAnnotateImage() annotates the image with text.
444%
445% The format of the XAnnotateImage method is:
446%
447% MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000448% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
449% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000450%
451% A description of each parameter follows:
452%
453% o display: Specifies a connection to an X server; returned from
454% XOpenDisplay.
455%
456% o pixel: Specifies a pointer to a XPixelInfo structure.
457%
458% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
459%
460% o image: the image.
461%
cristy7c3af952011-10-20 16:04:16 +0000462% o exception: return any errors or warnings in this structure.
463%
cristy3ed852e2009-09-05 21:47:34 +0000464*/
cristybcbda3f2011-09-03 13:01:22 +0000465MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000466 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
467 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000468{
cristyc57f6942010-11-12 01:47:39 +0000469 CacheView
470 *annotate_view;
471
cristy3ed852e2009-09-05 21:47:34 +0000472 GC
473 annotate_context;
474
cristy3ed852e2009-09-05 21:47:34 +0000475 Image
476 *annotate_image;
477
478 int
479 x,
480 y;
481
cristyb0a657e2012-08-29 00:45:37 +0000482 PixelTrait
483 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +0000484
485 Pixmap
486 annotate_pixmap;
487
488 unsigned int
489 depth,
490 height,
491 width;
492
493 Window
494 root_window;
495
496 XGCValues
497 context_values;
498
499 XImage
500 *annotate_ximage;
501
502 /*
503 Initialize annotated image.
504 */
505 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
506 assert(display != (Display *) NULL);
507 assert(pixel != (XPixelInfo *) NULL);
508 assert(annotate_info != (XAnnotateInfo *) NULL);
509 assert(image != (Image *) NULL);
510 /*
511 Initialize annotated pixmap.
512 */
513 root_window=XRootWindow(display,XDefaultScreen(display));
514 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
515 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
516 annotate_info->height,depth);
517 if (annotate_pixmap == (Pixmap) NULL)
518 return(MagickFalse);
519 /*
520 Initialize graphics info.
521 */
522 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000523 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000524 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000525 annotate_context=XCreateGC(display,root_window,(unsigned long)
526 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000527 if (annotate_context == (GC) NULL)
528 return(MagickFalse);
529 /*
530 Draw text to pixmap.
531 */
532 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
533 (int) annotate_info->font_info->ascent,annotate_info->text,
534 (int) strlen(annotate_info->text));
535 (void) XFreeGC(display,annotate_context);
536 /*
537 Initialize annotated X image.
538 */
539 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
540 annotate_info->height,AllPlanes,ZPixmap);
541 if (annotate_ximage == (XImage *) NULL)
542 return(MagickFalse);
543 (void) XFreePixmap(display,annotate_pixmap);
544 /*
545 Initialize annotated image.
546 */
cristy6710d842011-10-20 23:23:00 +0000547 annotate_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +0000548 if (annotate_image == (Image *) NULL)
549 return(MagickFalse);
550 annotate_image->columns=annotate_info->width;
551 annotate_image->rows=annotate_info->height;
552 /*
553 Transfer annotated X image to image.
554 */
555 width=(unsigned int) image->columns;
556 height=(unsigned int) image->rows;
557 x=0;
558 y=0;
559 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +0000560 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
561 (ssize_t) y,&annotate_image->background_color,exception);
cristy3ed852e2009-09-05 21:47:34 +0000562 if (annotate_info->stencil == ForegroundStencil)
cristy8a46d822012-08-28 23:32:39 +0000563 annotate_image->alpha_trait=BlendPixelTrait;
cristydb070952012-04-20 14:33:00 +0000564 annotate_view=AcquireAuthenticCacheView(annotate_image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000565 for (y=0; y < (int) annotate_image->rows; y++)
566 {
cristyc57f6942010-11-12 01:47:39 +0000567 register int
cristy3ed852e2009-09-05 21:47:34 +0000568 x;
569
cristy4c08aed2011-07-01 19:47:50 +0000570 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000571 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000572
cristyc57f6942010-11-12 01:47:39 +0000573 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
574 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000575 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000576 break;
cristyc57f6942010-11-12 01:47:39 +0000577 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000578 {
cristy4c08aed2011-07-01 19:47:50 +0000579 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000580 if (XGetPixel(annotate_ximage,x,y) == 0)
581 {
582 /*
583 Set this pixel to the background color.
584 */
cristy4c08aed2011-07-01 19:47:50 +0000585 SetPixelRed(annotate_image,ScaleShortToQuantum(
586 pixel->box_color.red),q);
587 SetPixelGreen(annotate_image,ScaleShortToQuantum(
588 pixel->box_color.green),q);
589 SetPixelBlue(annotate_image,ScaleShortToQuantum(
590 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000591 if ((annotate_info->stencil == ForegroundStencil) ||
592 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000593 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000594 }
595 else
596 {
597 /*
598 Set this pixel to the pen color.
599 */
cristy4c08aed2011-07-01 19:47:50 +0000600 SetPixelRed(annotate_image,ScaleShortToQuantum(
601 pixel->pen_color.red),q);
602 SetPixelGreen(annotate_image,ScaleShortToQuantum(
603 pixel->pen_color.green),q);
604 SetPixelBlue(annotate_image,ScaleShortToQuantum(
605 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000606 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000607 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000608 }
cristyed231572011-07-14 02:18:59 +0000609 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000610 }
cristyc57f6942010-11-12 01:47:39 +0000611 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000612 break;
613 }
cristyc57f6942010-11-12 01:47:39 +0000614 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000615 XDestroyImage(annotate_ximage);
616 /*
617 Determine annotate geometry.
618 */
619 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
620 if ((width != (unsigned int) annotate_image->columns) ||
621 (height != (unsigned int) annotate_image->rows))
622 {
623 char
624 image_geometry[MaxTextExtent];
625
626 /*
627 Scale image.
628 */
cristyb51dff52011-05-19 16:55:47 +0000629 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000630 width,height);
cristye941a752011-10-15 01:52:48 +0000631 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
632 exception);
cristy3ed852e2009-09-05 21:47:34 +0000633 }
634 if (annotate_info->degrees != 0.0)
635 {
636 Image
637 *rotate_image;
638
639 int
640 rotations;
641
cristya19f1d72012-08-07 18:24:38 +0000642 double
cristy3ed852e2009-09-05 21:47:34 +0000643 normalized_degrees;
644
645 /*
646 Rotate image.
647 */
cristy6710d842011-10-20 23:23:00 +0000648 rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +0000649 if (rotate_image == (Image *) NULL)
650 return(MagickFalse);
651 annotate_image=DestroyImage(annotate_image);
652 annotate_image=rotate_image;
653 /*
654 Annotation is relative to the degree of rotation.
655 */
656 normalized_degrees=annotate_info->degrees;
657 while (normalized_degrees < -45.0)
658 normalized_degrees+=360.0;
659 for (rotations=0; normalized_degrees > 45.0; rotations++)
660 normalized_degrees-=90.0;
661 switch (rotations % 4)
662 {
663 default:
664 case 0:
665 break;
666 case 1:
667 {
668 /*
669 Rotate 90 degrees.
670 */
671 x-=(int) annotate_image->columns/2;
672 y+=(int) annotate_image->columns/2;
673 break;
674 }
675 case 2:
676 {
677 /*
678 Rotate 180 degrees.
679 */
680 x=x-(int) annotate_image->columns;
681 break;
682 }
683 case 3:
684 {
685 /*
686 Rotate 270 degrees.
687 */
688 x=x-(int) annotate_image->columns/2;
689 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
690 break;
691 }
692 }
693 }
694 /*
695 Composite text onto the image.
696 */
697 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyb0a657e2012-08-29 00:45:37 +0000698 alpha_trait=image->alpha_trait;
cristyfeb3e962012-03-29 17:25:55 +0000699 (void) CompositeImage(image,annotate_image,
cristyb0a657e2012-08-29 00:45:37 +0000700 annotate_image->alpha_trait == BlendPixelTrait ? OverCompositeOp :
701 CopyCompositeOp,MagickTrue,(ssize_t) x,(ssize_t) y,exception);
702 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +0000703 annotate_image=DestroyImage(annotate_image);
704 return(MagickTrue);
705}
706
707/*
708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
709% %
710% %
711% %
712% X B e s t F o n t %
713% %
714% %
715% %
716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
717%
718% XBestFont() returns the "best" font. "Best" is defined as a font specified
719% in the X resource database or a font such that the text width displayed
720% with the font does not exceed the specified maximum width.
721%
722% The format of the XBestFont method is:
723%
724% XFontStruct *XBestFont(Display *display,
725% const XResourceInfo *resource_info,const MagickBooleanType text_font)
726%
727% A description of each parameter follows:
728%
729% o font: XBestFont returns a pointer to a XFontStruct structure.
730%
731% o display: Specifies a connection to an X server; returned from
732% XOpenDisplay.
733%
734% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
735%
736% o text_font: True is font should be mono-spaced (typewriter style).
737%
cristy3ed852e2009-09-05 21:47:34 +0000738*/
739
740static char **FontToList(char *font)
741{
742 char
743 **fontlist;
744
745 register char
746 *p,
747 *q;
748
749 register int
750 i;
751
752 unsigned int
753 fonts;
754
755 if (font == (char *) NULL)
756 return((char **) NULL);
757 /*
758 Convert string to an ASCII list.
759 */
760 fonts=1U;
761 for (p=font; *p != '\0'; p++)
762 if ((*p == ':') || (*p == ';') || (*p == ','))
763 fonts++;
764 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
765 if (fontlist == (char **) NULL)
766 {
767 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
768 font);
769 return((char **) NULL);
770 }
771 p=font;
772 for (i=0; i < (int) fonts; i++)
773 {
774 for (q=p; *q != '\0'; q++)
775 if ((*q == ':') || (*q == ';') || (*q == ','))
776 break;
777 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
778 sizeof(*fontlist[i]));
779 if (fontlist[i] == (char *) NULL)
780 {
781 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
782 font);
783 return((char **) NULL);
784 }
785 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
786 p=q+1;
787 }
788 fontlist[i]=(char *) NULL;
789 return(fontlist);
790}
791
cristybcbda3f2011-09-03 13:01:22 +0000792MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000793 const XResourceInfo *resource_info,const MagickBooleanType text_font)
794{
795 static const char
796 *Fonts[]=
797 {
798 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
799 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
800 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
801 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
802 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
803 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
804 "variable",
805 "fixed",
806 (char *) NULL
807 },
808 *TextFonts[]=
809 {
810 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
811 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
812 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
813 "fixed",
814 (char *) NULL
815 };
816
817 char
818 *font_name;
819
820 register const char
821 **p;
822
823 XFontStruct
824 *font_info;
825
826 font_info=(XFontStruct *) NULL;
827 font_name=resource_info->font;
828 if (text_font != MagickFalse)
829 font_name=resource_info->text_font;
830 if ((font_name != (char *) NULL) && (*font_name != '\0'))
831 {
832 char
833 **fontlist;
834
835 register int
836 i;
837
838 /*
839 Load preferred font specified in the X resource database.
840 */
841 fontlist=FontToList(font_name);
842 if (fontlist != (char **) NULL)
843 {
844 for (i=0; fontlist[i] != (char *) NULL; i++)
845 {
846 if (font_info == (XFontStruct *) NULL)
847 font_info=XLoadQueryFont(display,fontlist[i]);
848 fontlist[i]=DestroyString(fontlist[i]);
849 }
850 fontlist=(char **) RelinquishMagickMemory(fontlist);
851 }
852 if (font_info == (XFontStruct *) NULL)
853 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
854 }
855 /*
856 Load fonts from list of fonts until one is found.
857 */
858 p=Fonts;
859 if (text_font != MagickFalse)
860 p=TextFonts;
861 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
862 p++;
863 while (*p != (char *) NULL)
864 {
865 if (font_info != (XFontStruct *) NULL)
866 break;
867 font_info=XLoadQueryFont(display,(char *) *p);
868 p++;
869 }
870 return(font_info);
871}
872
873/*
874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875% %
876% %
877% %
878% X B e s t I c o n S i z e %
879% %
880% %
881% %
882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883%
884% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
885% size that maintains the aspect ratio of the image. If the window manager
886% has preferred icon sizes, one of the preferred sizes is used.
887%
888% The format of the XBestIconSize method is:
889%
890% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
891%
892% A description of each parameter follows:
893%
894% o display: Specifies a connection to an X server; returned from
895% XOpenDisplay.
896%
897% o image: the image.
898%
899*/
cristybcbda3f2011-09-03 13:01:22 +0000900MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000901 Image *image)
902{
903 int
904 i,
905 number_sizes;
906
cristya19f1d72012-08-07 18:24:38 +0000907 double
cristy3ed852e2009-09-05 21:47:34 +0000908 scale_factor;
909
910 unsigned int
911 height,
912 icon_height,
913 icon_width,
914 width;
915
916 Window
917 root_window;
918
919 XIconSize
920 *icon_size,
921 *size_list;
922
923 /*
924 Determine if the window manager has specified preferred icon sizes.
925 */
926 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
927 assert(display != (Display *) NULL);
928 assert(window != (XWindowInfo *) NULL);
929 assert(image != (Image *) NULL);
930 window->width=MaxIconSize;
931 window->height=MaxIconSize;
932 icon_size=(XIconSize *) NULL;
933 number_sizes=0;
934 root_window=XRootWindow(display,window->screen);
935 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
936 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
937 icon_size=size_list;
938 if (icon_size == (XIconSize *) NULL)
939 {
940 /*
941 Window manager does not restrict icon size.
942 */
943 icon_size=XAllocIconSize();
944 if (icon_size == (XIconSize *) NULL)
945 {
946 ThrowXWindowFatalException(ResourceLimitError,
947 "MemoryAllocationFailed",image->filename);
948 return;
949 }
950 icon_size->min_width=1;
951 icon_size->max_width=MaxIconSize;
952 icon_size->min_height=1;
953 icon_size->max_height=MaxIconSize;
954 icon_size->width_inc=1;
955 icon_size->height_inc=1;
956 }
957 /*
958 Determine aspect ratio of image.
959 */
960 width=(unsigned int) image->columns;
961 height=(unsigned int) image->rows;
962 i=0;
963 if (window->crop_geometry)
964 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
965 /*
966 Look for an icon size that maintains the aspect ratio of image.
967 */
cristya19f1d72012-08-07 18:24:38 +0000968 scale_factor=(double) icon_size->max_width/width;
969 if (scale_factor > ((double) icon_size->max_height/height))
970 scale_factor=(double) icon_size->max_height/height;
cristy3ed852e2009-09-05 21:47:34 +0000971 icon_width=(unsigned int) icon_size->min_width;
972 while ((int) icon_width < icon_size->max_width)
973 {
974 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
975 break;
976 icon_width+=icon_size->width_inc;
977 }
978 icon_height=(unsigned int) icon_size->min_height;
979 while ((int) icon_height < icon_size->max_height)
980 {
981 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
982 break;
983 icon_height+=icon_size->height_inc;
984 }
985 (void) XFree((void *) icon_size);
986 window->width=icon_width;
987 window->height=icon_height;
988}
989
990/*
991%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992% %
993% %
994% %
995% X B e s t P i x e l %
996% %
997% %
998% %
999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000%
1001% XBestPixel() returns a pixel from an array of pixels that is closest to the
1002% requested color. If the color array is NULL, the colors are obtained from
1003% the X server.
1004%
1005% The format of the XBestPixel method is:
1006%
1007% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1008% unsigned int number_colors,XColor *color)
1009%
1010% A description of each parameter follows:
1011%
1012% o pixel: XBestPixel returns the pixel value closest to the requested
1013% color.
1014%
1015% o display: Specifies a connection to an X server; returned from
1016% XOpenDisplay.
1017%
1018% o colormap: Specifies the ID of the X server colormap.
1019%
1020% o colors: Specifies an array of XColor structures.
1021%
1022% o number_colors: Specifies the number of XColor structures in the
1023% color definition array.
1024%
1025% o color: Specifies the desired RGB value to find in the colors array.
1026%
1027*/
cristybcbda3f2011-09-03 13:01:22 +00001028MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001029 XColor *colors,unsigned int number_colors,XColor *color)
1030{
1031 MagickBooleanType
1032 query_server;
1033
cristy4c08aed2011-07-01 19:47:50 +00001034 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001035 pixel;
1036
cristya19f1d72012-08-07 18:24:38 +00001037 double
cristy3ed852e2009-09-05 21:47:34 +00001038 min_distance;
1039
cristya19f1d72012-08-07 18:24:38 +00001040 register double
cristy3ed852e2009-09-05 21:47:34 +00001041 distance;
1042
1043 register int
1044 i,
1045 j;
1046
1047 Status
1048 status;
1049
1050 /*
1051 Find closest representation for the requested RGB color.
1052 */
1053 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1054 assert(display != (Display *) NULL);
1055 assert(color != (XColor *) NULL);
1056 status=XAllocColor(display,colormap,color);
1057 if (status != False)
1058 return;
1059 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1060 if (query_server != MagickFalse)
1061 {
1062 /*
1063 Read X server colormap.
1064 */
1065 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1066 if (colors == (XColor *) NULL)
1067 {
1068 ThrowXWindowFatalException(ResourceLimitError,
1069 "MemoryAllocationFailed","...");
1070 return;
1071 }
1072 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001073 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001074 if (number_colors > 256)
1075 number_colors=256;
1076 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1077 }
cristya19f1d72012-08-07 18:24:38 +00001078 min_distance=3.0*((double) QuantumRange+1.0)*((double)
cristy3ed852e2009-09-05 21:47:34 +00001079 QuantumRange+1.0);
1080 j=0;
1081 for (i=0; i < (int) number_colors; i++)
1082 {
cristya19f1d72012-08-07 18:24:38 +00001083 pixel.red=colors[i].red-(double) color->red;
cristy3ed852e2009-09-05 21:47:34 +00001084 distance=pixel.red*pixel.red;
1085 if (distance > min_distance)
1086 continue;
cristya19f1d72012-08-07 18:24:38 +00001087 pixel.green=colors[i].green-(double) color->green;
cristy3ed852e2009-09-05 21:47:34 +00001088 distance+=pixel.green*pixel.green;
1089 if (distance > min_distance)
1090 continue;
cristya19f1d72012-08-07 18:24:38 +00001091 pixel.blue=colors[i].blue-(double) color->blue;
cristy3ed852e2009-09-05 21:47:34 +00001092 distance+=pixel.blue*pixel.blue;
1093 if (distance > min_distance)
1094 continue;
1095 min_distance=distance;
1096 color->pixel=colors[i].pixel;
1097 j=i;
1098 }
1099 (void) XAllocColor(display,colormap,&colors[j]);
1100 if (query_server != MagickFalse)
1101 colors=(XColor *) RelinquishMagickMemory(colors);
1102}
1103
1104/*
1105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1106% %
1107% %
1108% %
1109% X B e s t V i s u a l I n f o %
1110% %
1111% %
1112% %
1113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114%
1115% XBestVisualInfo() returns visual information for a visual that is the "best"
1116% the server supports. "Best" is defined as:
1117%
1118% 1. Restrict the visual list to those supported by the default screen.
1119%
1120% 2. If a visual type is specified, restrict the visual list to those of
1121% that type.
1122%
1123% 3. If a map type is specified, choose the visual that matches the id
1124% specified by the Standard Colormap.
1125%
1126% 4 From the list of visuals, choose one that can display the most
1127% simultaneous colors. If more than one visual can display the same
1128% number of simultaneous colors, one is chosen based on a rank.
1129%
1130% The format of the XBestVisualInfo method is:
1131%
1132% XVisualInfo *XBestVisualInfo(Display *display,
1133% XStandardColormap *map_info,XResourceInfo *resource_info)
1134%
1135% A description of each parameter follows:
1136%
1137% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1138% structure.
1139%
1140% o display: Specifies a connection to an X server; returned from
1141% XOpenDisplay.
1142%
1143% o map_info: If map_type is specified, this structure is initialized
1144% with info from the Standard Colormap.
1145%
1146% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1147%
1148*/
1149
1150static inline int MagickMax(const int x,const int y)
1151{
1152 if (x > y)
1153 return(x);
1154 return(y);
1155}
1156
cristybb503372010-05-27 20:51:26 +00001157static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001158 const unsigned int y)
1159{
1160 if (x < y)
1161 return(x);
1162 return(y);
1163}
1164
cristybcbda3f2011-09-03 13:01:22 +00001165MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001166 XStandardColormap *map_info,XResourceInfo *resource_info)
1167{
1168#define MaxStandardColormaps 7
1169#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1170 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1171 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1172 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1173
1174 char
1175 *map_type,
1176 *visual_type;
1177
cristyc57f6942010-11-12 01:47:39 +00001178 int
1179 visual_mask;
1180
cristy3ed852e2009-09-05 21:47:34 +00001181 register int
1182 i;
1183
cristy8891f9c2010-06-04 23:32:17 +00001184 size_t
1185 one;
1186
cristy3ed852e2009-09-05 21:47:34 +00001187 static int
1188 number_visuals;
1189
1190 static XVisualInfo
1191 visual_template;
1192
1193 XVisualInfo
1194 *visual_info,
1195 *visual_list;
1196
1197 /*
1198 Restrict visual search by screen number.
1199 */
1200 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1201 assert(display != (Display *) NULL);
1202 assert(map_info != (XStandardColormap *) NULL);
1203 assert(resource_info != (XResourceInfo *) NULL);
1204 map_type=resource_info->map_type;
1205 visual_type=resource_info->visual_type;
1206 visual_mask=VisualScreenMask;
1207 visual_template.screen=XDefaultScreen(display);
1208 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001209 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001210 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001211 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001212 visual_mask|=VisualDepthMask;
1213 if (visual_type != (char *) NULL)
1214 {
1215 /*
1216 Restrict visual search by class or visual id.
1217 */
1218 if (LocaleCompare("staticgray",visual_type) == 0)
1219 {
1220 visual_mask|=VisualClassMask;
1221 visual_template.klass=StaticGray;
1222 }
1223 else
1224 if (LocaleCompare("grayscale",visual_type) == 0)
1225 {
1226 visual_mask|=VisualClassMask;
1227 visual_template.klass=GrayScale;
1228 }
1229 else
1230 if (LocaleCompare("staticcolor",visual_type) == 0)
1231 {
1232 visual_mask|=VisualClassMask;
1233 visual_template.klass=StaticColor;
1234 }
1235 else
1236 if (LocaleCompare("pseudocolor",visual_type) == 0)
1237 {
1238 visual_mask|=VisualClassMask;
1239 visual_template.klass=PseudoColor;
1240 }
1241 else
1242 if (LocaleCompare("truecolor",visual_type) == 0)
1243 {
1244 visual_mask|=VisualClassMask;
1245 visual_template.klass=TrueColor;
1246 }
1247 else
1248 if (LocaleCompare("directcolor",visual_type) == 0)
1249 {
1250 visual_mask|=VisualClassMask;
1251 visual_template.klass=DirectColor;
1252 }
1253 else
1254 if (LocaleCompare("default",visual_type) == 0)
1255 {
1256 visual_mask|=VisualIDMask;
1257 visual_template.visualid=XVisualIDFromVisual(
1258 XDefaultVisual(display,XDefaultScreen(display)));
1259 }
1260 else
1261 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1262 {
1263 visual_mask|=VisualIDMask;
1264 visual_template.visualid=
1265 strtol(visual_type,(char **) NULL,0);
1266 }
1267 else
1268 ThrowXWindowFatalException(XServerError,
1269 "UnrecognizedVisualSpecifier",visual_type);
1270 }
1271 /*
1272 Get all visuals that meet our criteria so far.
1273 */
1274 number_visuals=0;
1275 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1276 &number_visuals);
1277 visual_mask=VisualScreenMask | VisualIDMask;
1278 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1279 {
1280 /*
1281 Failed to get visual; try using the default visual.
1282 */
1283 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1284 visual_type);
1285 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1286 XDefaultScreen(display)));
1287 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1288 &number_visuals);
1289 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1290 return((XVisualInfo *) NULL);
1291 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1292 XVisualClassName(visual_list->klass));
1293 }
1294 resource_info->color_recovery=MagickFalse;
1295 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1296 {
1297 Atom
1298 map_property;
1299
1300 char
1301 map_name[MaxTextExtent];
1302
1303 int
1304 j,
1305 number_maps;
1306
1307 Status
1308 status;
1309
1310 Window
1311 root_window;
1312
1313 XStandardColormap
1314 *map_list;
1315
1316 /*
1317 Choose a visual associated with a standard colormap.
1318 */
1319 root_window=XRootWindow(display,XDefaultScreen(display));
1320 status=False;
1321 if (LocaleCompare(map_type,"list") != 0)
1322 {
1323 /*
1324 User specified Standard Colormap.
1325 */
cristyb51dff52011-05-19 16:55:47 +00001326 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001327 "RGB_%s_MAP",map_type);
1328 LocaleUpper(map_name);
1329 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1330 if (map_property != (Atom) NULL)
1331 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1332 map_property);
1333 }
1334 else
1335 {
1336 static const char
1337 *colormap[MaxStandardColormaps]=
1338 {
1339 "_HP_RGB_SMOOTH_MAP_LIST",
1340 "RGB_BEST_MAP",
1341 "RGB_DEFAULT_MAP",
1342 "RGB_GRAY_MAP",
1343 "RGB_RED_MAP",
1344 "RGB_GREEN_MAP",
1345 "RGB_BLUE_MAP",
1346 };
1347
1348 /*
1349 Choose a standard colormap from a list.
1350 */
1351 for (i=0; i < MaxStandardColormaps; i++)
1352 {
1353 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1354 if (map_property == (Atom) NULL)
1355 continue;
1356 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1357 map_property);
1358 if (status != False)
1359 break;
1360 }
1361 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1362 }
1363 if (status == False)
1364 {
1365 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1366 map_type);
1367 return((XVisualInfo *) NULL);
1368 }
1369 /*
1370 Search all Standard Colormaps and visuals for ids that match.
1371 */
1372 *map_info=map_list[0];
1373#if !defined(PRE_R4_ICCCM)
1374 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1375 for (i=0; i < number_maps; i++)
1376 for (j=0; j < number_visuals; j++)
1377 if (map_list[i].visualid ==
1378 XVisualIDFromVisual(visual_list[j].visual))
1379 {
1380 *map_info=map_list[i];
1381 visual_template.visualid=XVisualIDFromVisual(
1382 visual_list[j].visual);
1383 break;
1384 }
1385 if (map_info->visualid != visual_template.visualid)
1386 {
1387 ThrowXWindowFatalException(XServerError,
1388 "UnableToMatchVisualToStandardColormap",map_type);
1389 return((XVisualInfo *) NULL);
1390 }
1391#endif
1392 if (map_info->colormap == (Colormap) NULL)
1393 {
1394 ThrowXWindowFatalException(XServerError,
1395 "StandardColormapIsNotInitialized",map_type);
1396 return((XVisualInfo *) NULL);
1397 }
1398 (void) XFree((void *) map_list);
1399 }
1400 else
1401 {
1402 static const unsigned int
1403 rank[]=
1404 {
1405 StaticGray,
1406 GrayScale,
1407 StaticColor,
1408 DirectColor,
1409 TrueColor,
1410 PseudoColor
1411 };
1412
1413 XVisualInfo
1414 *p;
1415
1416 /*
1417 Pick one visual that displays the most simultaneous colors.
1418 */
1419 visual_info=visual_list;
1420 p=visual_list;
1421 for (i=1; i < number_visuals; i++)
1422 {
1423 p++;
1424 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1425 visual_info=p;
1426 else
1427 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1428 if (rank[p->klass] > rank[visual_info->klass])
1429 visual_info=p;
1430 }
1431 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1432 }
1433 (void) XFree((void *) visual_list);
1434 /*
1435 Retrieve only one visual by its screen & id number.
1436 */
1437 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1438 &number_visuals);
1439 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1440 return((XVisualInfo *) NULL);
1441 return(visual_info);
1442}
1443
1444/*
1445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1446% %
1447% %
1448% %
1449% X C h e c k D e f i n e C u r s o r %
1450% %
1451% %
1452% %
1453%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1454%
1455% XCheckDefineCursor() prevents cursor changes on the root window.
1456%
1457% The format of the XXCheckDefineCursor method is:
1458%
1459% XCheckDefineCursor(display,window,cursor)
1460%
1461% A description of each parameter follows:
1462%
1463% o display: Specifies a connection to an X server; returned from
1464% XOpenDisplay.
1465%
1466% o window: the window.
1467%
1468% o cursor: the cursor.
1469%
1470*/
cristybcbda3f2011-09-03 13:01:22 +00001471MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001472 Cursor cursor)
1473{
1474 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1475 assert(display != (Display *) NULL);
1476 if (window == XRootWindow(display,XDefaultScreen(display)))
1477 return(0);
1478 return(XDefineCursor(display,window,cursor));
1479}
1480
1481/*
1482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1483% %
1484% %
1485% %
1486% X C h e c k R e f r e s h W i n d o w s %
1487% %
1488% %
1489% %
1490%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1491%
1492% XCheckRefreshWindows() checks the X server for exposure events for a
1493% particular window and updates the areassociated with the exposure event.
1494%
1495% The format of the XCheckRefreshWindows method is:
1496%
1497% void XCheckRefreshWindows(Display *display,XWindows *windows)
1498%
1499% A description of each parameter follows:
1500%
1501% o display: Specifies a connection to an X server; returned from
1502% XOpenDisplay.
1503%
1504% o windows: Specifies a pointer to a XWindows structure.
1505%
1506*/
cristybcbda3f2011-09-03 13:01:22 +00001507MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001508{
1509 Window
1510 id;
1511
1512 XEvent
1513 event;
1514
1515 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1516 assert(display != (Display *) NULL);
1517 assert(windows != (XWindows *) NULL);
1518 XDelay(display,SuspendTime);
1519 id=windows->command.id;
1520 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1521 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1522 id=windows->image.id;
1523 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1524 XRefreshWindow(display,&windows->image,&event);
1525 XDelay(display,SuspendTime << 1);
1526 id=windows->command.id;
1527 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1528 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1529 id=windows->image.id;
1530 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1531 XRefreshWindow(display,&windows->image,&event);
1532}
1533
1534/*
1535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1536% %
1537% %
1538% %
1539% X C l i e n t M e s s a g e %
1540% %
1541% %
1542% %
1543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1544%
1545% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1546% initialized with a particular protocol type and atom.
1547%
1548% The format of the XClientMessage function is:
1549%
1550% XClientMessage(display,window,protocol,reason,timestamp)
1551%
1552% A description of each parameter follows:
1553%
1554% o display: Specifies a pointer to the Display structure; returned from
1555% XOpenDisplay.
1556%
1557% o window: Specifies a pointer to a Window structure.
1558%
1559% o protocol: Specifies an atom value.
1560%
1561% o reason: Specifies an atom value which is the reason to send.
1562%
1563% o timestamp: Specifies a value of type Time.
1564%
1565*/
cristybcbda3f2011-09-03 13:01:22 +00001566MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001567 const Atom protocol,const Atom reason,const Time timestamp)
1568{
1569 XClientMessageEvent
1570 client_event;
1571
1572 assert(display != (Display *) NULL);
1573 client_event.type=ClientMessage;
1574 client_event.window=window;
1575 client_event.message_type=protocol;
1576 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001577 client_event.data.l[0]=(long) reason;
1578 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001579 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1580}
1581
1582/*
1583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1584% %
1585% %
1586% %
1587+ X C l i e n t W i n d o w %
1588% %
1589% %
1590% %
1591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1592%
1593% XClientWindow() finds a window, at or below the specified window, which has
1594% a WM_STATE property. If such a window is found, it is returned, otherwise
1595% the argument window is returned.
1596%
1597% The format of the XClientWindow function is:
1598%
1599% client_window=XClientWindow(display,target_window)
1600%
1601% A description of each parameter follows:
1602%
1603% o client_window: XClientWindow returns a window, at or below the specified
1604% window, which has a WM_STATE property otherwise the argument
1605% target_window is returned.
1606%
1607% o display: Specifies a pointer to the Display structure; returned from
1608% XOpenDisplay.
1609%
1610% o target_window: Specifies the window to find a WM_STATE property.
1611%
cristy3ed852e2009-09-05 21:47:34 +00001612*/
1613static Window XClientWindow(Display *display,Window target_window)
1614{
1615 Atom
1616 state,
1617 type;
1618
1619 int
1620 format;
1621
1622 Status
1623 status;
1624
1625 unsigned char
1626 *data;
1627
cristyf2faecf2010-05-28 19:19:36 +00001628 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001629 after,
1630 number_items;
1631
1632 Window
1633 client_window;
1634
1635 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1636 assert(display != (Display *) NULL);
1637 state=XInternAtom(display,"WM_STATE",MagickTrue);
1638 if (state == (Atom) NULL)
1639 return(target_window);
1640 type=(Atom) NULL;
1641 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1642 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1643 if ((status == Success) && (type != (Atom) NULL))
1644 return(target_window);
1645 client_window=XWindowByProperty(display,target_window,state);
1646 if (client_window == (Window) NULL)
1647 return(target_window);
1648 return(client_window);
1649}
1650
1651/*
1652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1653% %
1654% %
1655% %
cristyf34a1452009-10-24 22:29:27 +00001656+ X C o m p o n e n t T e r m i n u s %
1657% %
1658% %
1659% %
1660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1661%
1662% XComponentTerminus() destroys the module component.
1663%
1664% The format of the XComponentTerminus method is:
1665%
1666% XComponentTerminus(void)
1667%
1668*/
cristy5ff4eaf2011-09-03 01:38:02 +00001669MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001670{
1671 DestroyXResources();
1672}
1673
1674/*
1675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1676% %
1677% %
1678% %
cristy3ed852e2009-09-05 21:47:34 +00001679% X C o n f i g u r e I m a g e C o l o r m a p %
1680% %
1681% %
1682% %
1683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1684%
1685% XConfigureImageColormap() creates a new X colormap.
1686%
1687% The format of the XConfigureImageColormap method is:
1688%
1689% void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001690% XResourceInfo *resource_info,XWindows *windows,Image *image,
1691% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001692%
1693% A description of each parameter follows:
1694%
1695% o display: Specifies a connection to an X server; returned from
1696% XOpenDisplay.
1697%
1698% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1699%
1700% o windows: Specifies a pointer to a XWindows structure.
1701%
1702% o image: the image.
1703%
cristy6710d842011-10-20 23:23:00 +00001704% o exception: return any errors or warnings in this structure.
1705%
cristy3ed852e2009-09-05 21:47:34 +00001706*/
cristybcbda3f2011-09-03 13:01:22 +00001707MagickPrivate void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001708 XResourceInfo *resource_info,XWindows *windows,Image *image,
1709 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001710{
1711 Colormap
1712 colormap;
1713
1714 /*
1715 Make standard colormap.
1716 */
1717 XSetCursorState(display,windows,MagickTrue);
1718 XCheckRefreshWindows(display,windows);
1719 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
cristy6710d842011-10-20 23:23:00 +00001720 windows->map_info,windows->pixel_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00001721 colormap=windows->map_info->colormap;
1722 (void) XSetWindowColormap(display,windows->image.id,colormap);
1723 (void) XSetWindowColormap(display,windows->command.id,colormap);
1724 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1725 if (windows->magnify.mapped != MagickFalse)
1726 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1727 if (windows->pan.mapped != MagickFalse)
1728 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1729 XSetCursorState(display,windows,MagickFalse);
1730 XClientMessage(display,windows->image.id,windows->im_protocols,
1731 windows->im_update_colormap,CurrentTime);
1732}
1733
1734/*
1735%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1736% %
1737% %
1738% %
1739% X C o n s t r a i n W i n d o w P o s i t i o n %
1740% %
1741% %
1742% %
1743%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1744%
1745% XConstrainWindowPosition() assures a window is positioned within the X
1746% server boundaries.
1747%
1748% The format of the XConstrainWindowPosition method is:
1749%
1750% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1751%
1752% A description of each parameter follows:
1753%
1754% o display: Specifies a pointer to the Display structure; returned from
1755% XOpenDisplay.
1756%
1757% o window_info: Specifies a pointer to a XWindowInfo structure.
1758%
1759*/
cristybcbda3f2011-09-03 13:01:22 +00001760MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001761 XWindowInfo *window_info)
1762{
1763 int
1764 limit;
1765
1766 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1767 assert(display != (Display *) NULL);
1768 assert(window_info != (XWindowInfo *) NULL);
1769 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1770 if (window_info->x < 0)
1771 window_info->x=0;
1772 else
1773 if (window_info->x > (int) limit)
1774 window_info->x=(int) limit;
1775 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1776 if (window_info->y < 0)
1777 window_info->y=0;
1778 else
1779 if (window_info->y > limit)
1780 window_info->y=limit;
1781}
1782
1783/*
1784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1785% %
1786% %
1787% %
1788% X D e l a y %
1789% %
1790% %
1791% %
1792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1793%
1794% XDelay() suspends program execution for the number of milliseconds
1795% specified.
1796%
1797% The format of the Delay method is:
1798%
cristybb503372010-05-27 20:51:26 +00001799% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001800%
1801% A description of each parameter follows:
1802%
1803% o display: Specifies a pointer to the Display structure; returned from
1804% XOpenDisplay.
1805%
1806% o milliseconds: Specifies the number of milliseconds to delay before
1807% returning.
1808%
1809*/
cristybcbda3f2011-09-03 13:01:22 +00001810MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001811{
1812 assert(display != (Display *) NULL);
1813 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001814 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001815}
1816
1817/*
1818%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1819% %
1820% %
1821% %
1822% X D e s t r o y R e s o u r c e I n f o %
1823% %
1824% %
1825% %
1826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1827%
1828% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1829% structure.
1830%
1831% The format of the XDestroyResourceInfo method is:
1832%
1833% void XDestroyResourceInfo(XResourceInfo *resource_info)
1834%
1835% A description of each parameter follows:
1836%
1837% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1838%
1839*/
1840MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1841{
1842 if (resource_info->image_geometry != (char *) NULL)
1843 resource_info->image_geometry=(char *)
1844 RelinquishMagickMemory(resource_info->image_geometry);
1845 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1846 resource_info->quantize_info=DestroyQuantizeInfo(
1847 resource_info->quantize_info);
1848 if (resource_info->client_name != (char *) NULL)
1849 resource_info->client_name=(char *)
1850 RelinquishMagickMemory(resource_info->client_name);
1851 if (resource_info->name != (char *) NULL)
1852 resource_info->name=DestroyString(resource_info->name);
1853 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1854}
1855
1856/*
1857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1858% %
1859% %
1860% %
1861% X D e s t r o y W i n d o w C o l o r s %
1862% %
1863% %
1864% %
1865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1866%
1867% XDestroyWindowColors() frees X11 color resources previously saved on a
1868% window by XRetainWindowColors or programs like xsetroot.
1869%
1870% The format of the XDestroyWindowColors method is:
1871%
1872% void XDestroyWindowColors(Display *display,Window window)
1873%
1874% A description of each parameter follows:
1875%
1876% o display: Specifies a connection to an X server; returned from
1877% XOpenDisplay.
1878%
1879% o window: Specifies a pointer to a Window structure.
1880%
1881*/
cristybcbda3f2011-09-03 13:01:22 +00001882MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001883{
1884 Atom
1885 property,
1886 type;
1887
1888 int
1889 format;
1890
1891 Status
1892 status;
1893
1894 unsigned char
1895 *data;
1896
cristyf2faecf2010-05-28 19:19:36 +00001897 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001898 after,
1899 length;
1900
1901 /*
1902 If there are previous resources on the root window, destroy them.
1903 */
1904 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1905 assert(display != (Display *) NULL);
1906 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1907 if (property == (Atom) NULL)
1908 {
1909 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1910 "_XSETROOT_ID");
1911 return;
1912 }
1913 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1914 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1915 if (status != Success)
1916 return;
1917 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1918 {
1919 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1920 (void) XDeleteProperty(display,window,property);
1921 }
1922 if (type != None)
1923 (void) XFree((void *) data);
1924}
1925
1926/*
1927%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1928% %
1929% %
1930% %
1931% X D i s p l a y I m a g e I n f o %
1932% %
1933% %
1934% %
1935%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1936%
1937% XDisplayImageInfo() displays information about an X image.
1938%
1939% The format of the XDisplayImageInfo method is:
1940%
1941% void XDisplayImageInfo(Display *display,
1942% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001943% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001944%
1945% A description of each parameter follows:
1946%
1947% o display: Specifies a connection to an X server; returned from
1948% XOpenDisplay.
1949%
1950% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1951%
1952% o windows: Specifies a pointer to a XWindows structure.
1953%
1954% o undo_image: the undo image.
1955%
1956% o image: the image.
1957%
cristy6710d842011-10-20 23:23:00 +00001958% o exception: return any errors or warnings in this structure.
1959%
cristy3ed852e2009-09-05 21:47:34 +00001960*/
cristybcbda3f2011-09-03 13:01:22 +00001961MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001962 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001963 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001964{
1965 char
1966 filename[MaxTextExtent],
1967 *text,
1968 **textlist;
1969
1970 FILE
1971 *file;
1972
1973 int
1974 unique_file;
1975
cristybb503372010-05-27 20:51:26 +00001976 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001977 i;
1978
cristybb503372010-05-27 20:51:26 +00001979 size_t
cristy3ed852e2009-09-05 21:47:34 +00001980 number_pixels;
1981
cristy9d314ff2011-03-09 01:30:28 +00001982 ssize_t
1983 bytes;
1984
1985 unsigned int
1986 levels;
1987
cristy3ed852e2009-09-05 21:47:34 +00001988 /*
1989 Write info about the X server to a file.
1990 */
1991 assert(display != (Display *) NULL);
1992 assert(resource_info != (XResourceInfo *) NULL);
1993 assert(windows != (XWindows *) NULL);
1994 assert(image != (Image *) NULL);
1995 if (image->debug)
1996 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1997 file=(FILE *) NULL;
1998 unique_file=AcquireUniqueFileResource(filename);
1999 if (unique_file != -1)
2000 file=fdopen(unique_file,"w");
2001 if ((unique_file == -1) || (file == (FILE *) NULL))
2002 {
2003 XNoticeWidget(display,windows,"Unable to display image info",filename);
2004 return;
2005 }
2006 if (resource_info->gamma_correct != MagickFalse)
2007 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002008 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002009 resource_info->display_gamma);
2010 /*
2011 Write info about the X image to a file.
2012 */
cristyb51dff52011-05-19 16:55:47 +00002013 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002014 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002015 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002016 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002017 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002018 windows->visual_info->colormap_size);
2019 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002020 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002021 else
cristyb51dff52011-05-19 16:55:47 +00002022 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002023 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2024 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002025 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002026 (void) FormatLocaleFile(file," crop geometry: %s\n",
2027 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002028 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002029 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002030 else
cristyb51dff52011-05-19 16:55:47 +00002031 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002032 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002033 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002034 else
cristyb51dff52011-05-19 16:55:47 +00002035 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002036 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002037 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002038 else
cristyb51dff52011-05-19 16:55:47 +00002039 (void) FormatLocaleFile(file," shared memory: False\n");
2040 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002041 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002042 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002043 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002044 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002045 /*
2046 Write info about the undo cache to a file.
2047 */
2048 bytes=0;
2049 for (levels=0; undo_image != (Image *) NULL; levels++)
2050 {
2051 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002052 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002053 undo_image=GetPreviousImageInList(undo_image);
2054 }
cristyb51dff52011-05-19 16:55:47 +00002055 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002056 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2057 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002058 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002059 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002060 /*
2061 Write info about the image to a file.
2062 */
cristy6710d842011-10-20 23:23:00 +00002063 (void) IdentifyImage(image,file,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00002064 (void) fclose(file);
cristy6710d842011-10-20 23:23:00 +00002065 text=FileToString(filename,~0,exception);
cristy3ed852e2009-09-05 21:47:34 +00002066 (void) RelinquishUniqueFileResource(filename);
2067 if (text == (char *) NULL)
2068 {
2069 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2070 "UnableToDisplayImageInfo");
2071 return;
2072 }
2073 textlist=StringToList(text);
2074 if (textlist != (char **) NULL)
2075 {
2076 char
2077 title[MaxTextExtent];
2078
2079 /*
2080 Display information about the image in the Text View widget.
2081 */
2082 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002083 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002084 image->filename);
2085 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2086 (char const **) textlist);
2087 for (i=0; textlist[i] != (char *) NULL; i++)
2088 textlist[i]=DestroyString(textlist[i]);
2089 textlist=(char **) RelinquishMagickMemory(textlist);
2090 }
2091 text=DestroyString(text);
2092}
2093
2094/*
2095%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2096% %
2097% %
2098% %
2099+ X D i t h e r I m a g e %
2100% %
2101% %
2102% %
2103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2104%
2105% XDitherImage() dithers the reference image as required by the HP Color
2106% Recovery algorithm. The color values are quantized to 3 bits of red and
2107% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2108% standard colormap.
2109%
2110% The format of the XDitherImage method is:
2111%
cristy6710d842011-10-20 23:23:00 +00002112% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002113%
2114% A description of each parameter follows:
2115%
2116% o image: the image.
2117%
2118% o ximage: Specifies a pointer to a XImage structure; returned from
2119% XCreateImage.
2120%
cristy6710d842011-10-20 23:23:00 +00002121% o exception: return any errors or warnings in this structure.
2122%
cristy3ed852e2009-09-05 21:47:34 +00002123*/
cristy6710d842011-10-20 23:23:00 +00002124static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002125{
2126 static const short int
2127 dither_red[2][16]=
2128 {
2129 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2130 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2131 },
2132 dither_green[2][16]=
2133 {
2134 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2135 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2136 },
2137 dither_blue[2][16]=
2138 {
2139 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2140 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2141 };
2142
cristyc57f6942010-11-12 01:47:39 +00002143 CacheView
2144 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002145
2146 int
cristyc57f6942010-11-12 01:47:39 +00002147 value,
cristy3ed852e2009-09-05 21:47:34 +00002148 y;
2149
cristy101ab702011-10-13 13:06:32 +00002150 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002151 color;
cristy3ed852e2009-09-05 21:47:34 +00002152
2153 register char
2154 *q;
2155
cristy4c08aed2011-07-01 19:47:50 +00002156 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002157 *p;
2158
2159 register int
2160 i,
2161 j,
2162 x;
2163
2164 unsigned int
2165 scanline_pad;
2166
cristybb503372010-05-27 20:51:26 +00002167 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002168 pixel;
2169
2170 unsigned char
2171 *blue_map[2][16],
2172 *green_map[2][16],
2173 *red_map[2][16];
2174
2175 /*
2176 Allocate and initialize dither maps.
2177 */
2178 for (i=0; i < 2; i++)
2179 for (j=0; j < 16; j++)
2180 {
2181 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2182 sizeof(*red_map));
2183 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2184 sizeof(*green_map));
2185 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2186 sizeof(*blue_map));
2187 if ((red_map[i][j] == (unsigned char *) NULL) ||
2188 (green_map[i][j] == (unsigned char *) NULL) ||
2189 (blue_map[i][j] == (unsigned char *) NULL))
2190 {
2191 ThrowXWindowFatalException(ResourceLimitError,
2192 "MemoryAllocationFailed",image->filename);
2193 return;
2194 }
2195 }
2196 /*
2197 Initialize dither tables.
2198 */
2199 for (i=0; i < 2; i++)
2200 for (j=0; j < 16; j++)
2201 for (x=0; x < 256; x++)
2202 {
2203 value=x-16;
2204 if (x < 48)
2205 value=x/2+8;
2206 value+=dither_red[i][j];
2207 red_map[i][j][x]=(unsigned char)
2208 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2209 value=x-16;
2210 if (x < 48)
2211 value=x/2+8;
2212 value+=dither_green[i][j];
2213 green_map[i][j][x]=(unsigned char)
2214 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2215 value=x-32;
2216 if (x < 112)
2217 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002218 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002219 blue_map[i][j][x]=(unsigned char)
2220 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2221 }
2222 /*
2223 Dither image.
2224 */
2225 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002226 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002227 i=0;
2228 j=0;
2229 q=ximage->data;
cristydb070952012-04-20 14:33:00 +00002230 image_view=AcquireVirtualCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002231 for (y=0; y < (int) image->rows; y++)
2232 {
cristyc57f6942010-11-12 01:47:39 +00002233 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
cristy6710d842011-10-20 23:23:00 +00002234 exception);
cristy4c08aed2011-07-01 19:47:50 +00002235 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002236 break;
2237 for (x=0; x < (int) image->columns; x++)
2238 {
cristyada285b2012-07-07 19:00:46 +00002239 color.red=(double) ClampToQuantum((double) (red_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002240 (int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002241 color.green=(double) ClampToQuantum((double) (green_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002242 (int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyada285b2012-07-07 19:00:46 +00002243 color.blue=(double) ClampToQuantum((double) (blue_map[i][j][
cristye42f6582012-02-11 17:59:50 +00002244 (int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002245 pixel=(size_t) (((size_t) color.red & 0xe0) |
2246 (((size_t) color.green & 0xe0) >> 3) |
2247 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002248 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002249 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002250 j++;
2251 if (j == 16)
2252 j=0;
2253 }
2254 q+=scanline_pad;
2255 i++;
2256 if (i == 2)
2257 i=0;
2258 }
cristyc57f6942010-11-12 01:47:39 +00002259 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002260 /*
2261 Free allocated memory.
2262 */
2263 for (i=0; i < 2; i++)
2264 for (j=0; j < 16; j++)
2265 {
2266 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2267 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2268 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2269 }
2270}
2271
2272/*
2273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2274% %
2275% %
2276% %
2277% X D r a w I m a g e %
2278% %
2279% %
2280% %
2281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2282%
2283% XDrawImage() draws a line on the image.
2284%
2285% The format of the XDrawImage method is:
2286%
cristy6710d842011-10-20 23:23:00 +00002287% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2288% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002289%
2290% A description of each parameter follows:
2291%
2292% o display: Specifies a connection to an X server; returned from
2293% XOpenDisplay.
2294%
2295% o pixel: Specifies a pointer to a XPixelInfo structure.
2296%
2297% o draw_info: Specifies a pointer to a XDrawInfo structure.
2298%
2299% o image: the image.
2300%
cristy6710d842011-10-20 23:23:00 +00002301% o exception: return any errors or warnings in this structure.
2302%
cristy3ed852e2009-09-05 21:47:34 +00002303*/
cristybcbda3f2011-09-03 13:01:22 +00002304MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy6710d842011-10-20 23:23:00 +00002305 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2306 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002307{
cristyc57f6942010-11-12 01:47:39 +00002308 CacheView
2309 *draw_view;
2310
cristy3ed852e2009-09-05 21:47:34 +00002311 GC
2312 draw_context;
2313
2314 Image
2315 *draw_image;
2316
2317 int
2318 x,
2319 y;
2320
cristyb0a657e2012-08-29 00:45:37 +00002321 PixelTrait
2322 alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002323
2324 Pixmap
2325 draw_pixmap;
2326
2327 unsigned int
2328 depth,
2329 height,
2330 width;
2331
2332 Window
2333 root_window;
2334
2335 XGCValues
2336 context_values;
2337
2338 XImage
2339 *draw_ximage;
2340
2341 /*
2342 Initialize drawd image.
2343 */
2344 assert(display != (Display *) NULL);
2345 assert(pixel != (XPixelInfo *) NULL);
2346 assert(draw_info != (XDrawInfo *) NULL);
2347 assert(image != (Image *) NULL);
2348 if (image->debug != MagickFalse)
2349 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2350 /*
2351 Initialize drawd pixmap.
2352 */
2353 root_window=XRootWindow(display,XDefaultScreen(display));
2354 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2355 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2356 draw_info->height,depth);
2357 if (draw_pixmap == (Pixmap) NULL)
2358 return(MagickFalse);
2359 /*
2360 Initialize graphics info.
2361 */
cristybb503372010-05-27 20:51:26 +00002362 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002363 context_values.foreground=0;
2364 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002365 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002366 (GCBackground | GCForeground | GCLineWidth),&context_values);
2367 if (draw_context == (GC) NULL)
2368 return(MagickFalse);
2369 /*
2370 Clear pixmap.
2371 */
2372 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2373 draw_info->height);
2374 /*
2375 Draw line to pixmap.
2376 */
2377 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002378 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002379 if (draw_info->stipple != (Pixmap) NULL)
2380 {
2381 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2382 (void) XSetStipple(display,draw_context,draw_info->stipple);
2383 }
cristy3ed852e2009-09-05 21:47:34 +00002384 switch (draw_info->element)
2385 {
2386 case PointElement:
2387 default:
2388 {
2389 (void) XDrawLines(display,draw_pixmap,draw_context,
2390 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2391 CoordModeOrigin);
2392 break;
2393 }
2394 case LineElement:
2395 {
2396 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2397 draw_info->line_info.y1,draw_info->line_info.x2,
2398 draw_info->line_info.y2);
2399 break;
2400 }
2401 case RectangleElement:
2402 {
2403 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2404 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2405 (unsigned int) draw_info->rectangle_info.width,
2406 (unsigned int) draw_info->rectangle_info.height);
2407 break;
2408 }
2409 case FillRectangleElement:
2410 {
2411 (void) XFillRectangle(display,draw_pixmap,draw_context,
2412 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2413 (unsigned int) draw_info->rectangle_info.width,
2414 (unsigned int) draw_info->rectangle_info.height);
2415 break;
2416 }
2417 case CircleElement:
2418 case EllipseElement:
2419 {
2420 (void) XDrawArc(display,draw_pixmap,draw_context,
2421 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2422 (unsigned int) draw_info->rectangle_info.width,
2423 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2424 break;
2425 }
2426 case FillCircleElement:
2427 case FillEllipseElement:
2428 {
2429 (void) XFillArc(display,draw_pixmap,draw_context,
2430 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2431 (unsigned int) draw_info->rectangle_info.width,
2432 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2433 break;
2434 }
2435 case PolygonElement:
2436 {
2437 XPoint
2438 *coordinate_info;
2439
2440 coordinate_info=draw_info->coordinate_info;
2441 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2442 (int) draw_info->number_coordinates,CoordModeOrigin);
2443 (void) XDrawLine(display,draw_pixmap,draw_context,
2444 coordinate_info[draw_info->number_coordinates-1].x,
2445 coordinate_info[draw_info->number_coordinates-1].y,
2446 coordinate_info[0].x,coordinate_info[0].y);
2447 break;
2448 }
2449 case FillPolygonElement:
2450 {
2451 (void) XFillPolygon(display,draw_pixmap,draw_context,
2452 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2453 CoordModeOrigin);
2454 break;
2455 }
2456 }
2457 (void) XFreeGC(display,draw_context);
2458 /*
2459 Initialize X image.
2460 */
2461 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2462 draw_info->height,AllPlanes,ZPixmap);
2463 if (draw_ximage == (XImage *) NULL)
2464 return(MagickFalse);
2465 (void) XFreePixmap(display,draw_pixmap);
2466 /*
2467 Initialize draw image.
2468 */
cristy6710d842011-10-20 23:23:00 +00002469 draw_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002470 if (draw_image == (Image *) NULL)
2471 return(MagickFalse);
2472 draw_image->columns=draw_info->width;
2473 draw_image->rows=draw_info->height;
2474 /*
2475 Transfer drawn X image to image.
2476 */
2477 width=(unsigned int) image->columns;
2478 height=(unsigned int) image->rows;
2479 x=0;
2480 y=0;
2481 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyf05d4942012-03-17 16:26:09 +00002482 (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
2483 (ssize_t) y,&draw_image->background_color,exception);
cristy6710d842011-10-20 23:23:00 +00002484 if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002485 return(MagickFalse);
cristy8a46d822012-08-28 23:32:39 +00002486 draw_image->alpha_trait=BlendPixelTrait;
cristydb070952012-04-20 14:33:00 +00002487 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002488 for (y=0; y < (int) draw_image->rows; y++)
2489 {
cristyc57f6942010-11-12 01:47:39 +00002490 register int
cristy3ed852e2009-09-05 21:47:34 +00002491 x;
2492
cristy4c08aed2011-07-01 19:47:50 +00002493 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002494 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002495
cristyc57f6942010-11-12 01:47:39 +00002496 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2497 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002498 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002499 break;
cristyc57f6942010-11-12 01:47:39 +00002500 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002501 {
2502 if (XGetPixel(draw_ximage,x,y) == 0)
2503 {
2504 /*
2505 Set this pixel to the background color.
2506 */
cristy803640d2011-11-17 02:11:32 +00002507 SetPixelInfoPixel(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002508 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002509 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002510 }
2511 else
2512 {
2513 /*
2514 Set this pixel to the pen color.
2515 */
cristy4c08aed2011-07-01 19:47:50 +00002516 SetPixelRed(draw_image,ScaleShortToQuantum(
2517 pixel->pen_color.red),q);
2518 SetPixelGreen(draw_image,ScaleShortToQuantum(
2519 pixel->pen_color.green),q);
2520 SetPixelBlue(draw_image,ScaleShortToQuantum(
2521 pixel->pen_color.blue),q);
2522 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2523 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002524 }
cristyed231572011-07-14 02:18:59 +00002525 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002526 }
cristyc57f6942010-11-12 01:47:39 +00002527 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002528 break;
2529 }
cristyc57f6942010-11-12 01:47:39 +00002530 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002531 XDestroyImage(draw_ximage);
2532 /*
2533 Determine draw geometry.
2534 */
2535 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2536 if ((width != (unsigned int) draw_image->columns) ||
2537 (height != (unsigned int) draw_image->rows))
2538 {
2539 char
2540 image_geometry[MaxTextExtent];
2541
2542 /*
2543 Scale image.
2544 */
cristyb51dff52011-05-19 16:55:47 +00002545 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002546 width,height);
cristye941a752011-10-15 01:52:48 +00002547 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2548 exception);
cristy3ed852e2009-09-05 21:47:34 +00002549 }
2550 if (draw_info->degrees != 0.0)
2551 {
2552 Image
2553 *rotate_image;
2554
2555 int
2556 rotations;
2557
cristya19f1d72012-08-07 18:24:38 +00002558 double
cristy3ed852e2009-09-05 21:47:34 +00002559 normalized_degrees;
2560
2561 /*
2562 Rotate image.
2563 */
cristy6710d842011-10-20 23:23:00 +00002564 rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +00002565 if (rotate_image == (Image *) NULL)
2566 return(MagickFalse);
2567 draw_image=DestroyImage(draw_image);
2568 draw_image=rotate_image;
2569 /*
2570 Annotation is relative to the degree of rotation.
2571 */
2572 normalized_degrees=draw_info->degrees;
2573 while (normalized_degrees < -45.0)
2574 normalized_degrees+=360.0;
2575 for (rotations=0; normalized_degrees > 45.0; rotations++)
2576 normalized_degrees-=90.0;
2577 switch (rotations % 4)
2578 {
2579 default:
2580 case 0:
2581 break;
2582 case 1:
2583 {
2584 /*
2585 Rotate 90 degrees.
2586 */
2587 x=x-(int) draw_image->columns/2;
2588 y=y+(int) draw_image->columns/2;
2589 break;
2590 }
2591 case 2:
2592 {
2593 /*
2594 Rotate 180 degrees.
2595 */
2596 x=x-(int) draw_image->columns;
2597 break;
2598 }
2599 case 3:
2600 {
2601 /*
2602 Rotate 270 degrees.
2603 */
2604 x=x-(int) draw_image->columns/2;
2605 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2606 break;
2607 }
2608 }
2609 }
2610 /*
2611 Composite text onto the image.
2612 */
cristydb070952012-04-20 14:33:00 +00002613 draw_view=AcquireAuthenticCacheView(draw_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00002614 for (y=0; y < (int) draw_image->rows; y++)
2615 {
cristyc57f6942010-11-12 01:47:39 +00002616 register int
cristy3ed852e2009-09-05 21:47:34 +00002617 x;
2618
cristy4c08aed2011-07-01 19:47:50 +00002619 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002620 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002621
cristyc57f6942010-11-12 01:47:39 +00002622 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2623 exception);
cristyacd2ed22011-08-30 01:44:23 +00002624 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002625 break;
cristyc57f6942010-11-12 01:47:39 +00002626 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002627 {
cristy4c08aed2011-07-01 19:47:50 +00002628 if (GetPixelAlpha(image,q) != TransparentAlpha)
2629 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002630 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002631 }
cristyc57f6942010-11-12 01:47:39 +00002632 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002633 break;
2634 }
cristyc57f6942010-11-12 01:47:39 +00002635 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002636 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2637 if (draw_info->stencil == TransparentStencil)
cristy39172402012-03-30 13:04:39 +00002638 (void) CompositeImage(image,draw_image,CopyAlphaCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002639 (ssize_t) x,(ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002640 else
2641 {
cristyb0a657e2012-08-29 00:45:37 +00002642 alpha_trait=image->alpha_trait;
cristy39172402012-03-30 13:04:39 +00002643 (void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00002644 (ssize_t) x,(ssize_t) y,exception);
cristyb0a657e2012-08-29 00:45:37 +00002645 image->alpha_trait=alpha_trait;
cristy3ed852e2009-09-05 21:47:34 +00002646 }
2647 draw_image=DestroyImage(draw_image);
2648 return(MagickTrue);
2649}
2650
2651/*
2652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2653% %
2654% %
2655% %
2656% X E r r o r %
2657% %
2658% %
2659% %
2660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2661%
2662% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2663% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002664% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2665% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002666%
2667% The format of the XError function is:
2668%
cristybcbda3f2011-09-03 13:01:22 +00002669% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002670%
2671% A description of each parameter follows:
2672%
2673% o display: Specifies a pointer to the Display structure; returned from
2674% XOpenDisplay.
2675%
2676% o error: Specifies the error event.
2677%
2678*/
2679
2680#if defined(__cplusplus) || defined(c_plusplus)
2681extern "C" {
2682#endif
2683
2684MagickExport int XError(Display *display,XErrorEvent *error)
2685{
2686 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2687 assert(display != (Display *) NULL);
2688 assert(error != (XErrorEvent *) NULL);
2689 xerror_alert=MagickTrue;
2690 switch (error->request_code)
2691 {
2692 case X_GetGeometry:
2693 {
2694 if ((int) error->error_code == BadDrawable)
2695 return(MagickFalse);
2696 break;
2697 }
2698 case X_GetWindowAttributes:
2699 case X_QueryTree:
2700 {
2701 if ((int) error->error_code == BadWindow)
2702 return(MagickFalse);
2703 break;
2704 }
2705 case X_QueryColors:
2706 {
2707 if ((int) error->error_code == BadValue)
2708 return(MagickFalse);
2709 break;
2710 }
2711 }
2712 return(MagickTrue);
2713}
2714
2715#if defined(__cplusplus) || defined(c_plusplus)
2716}
2717#endif
2718
2719/*
2720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2721% %
2722% %
2723% %
2724% X F r e e R e s o u r c e s %
2725% %
2726% %
2727% %
2728%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2729%
2730% XFreeResources() frees X11 resources.
2731%
2732% The format of the XFreeResources method is:
2733%
2734% void XFreeResources(Display *display,XVisualInfo *visual_info,
2735% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2736% XResourceInfo *resource_info,XWindowInfo *window_info)
2737% resource_info,window_info)
2738%
2739% A description of each parameter follows:
2740%
2741% o display: Specifies a connection to an X server; returned from
2742% XOpenDisplay.
2743%
2744% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2745% returned from XGetVisualInfo.
2746%
2747% o map_info: If map_type is specified, this structure is initialized
2748% with info from the Standard Colormap.
2749%
2750% o pixel: Specifies a pointer to a XPixelInfo structure.
2751%
2752% o font_info: Specifies a pointer to a XFontStruct structure.
2753%
2754% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2755%
2756% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2757%
2758*/
cristybcbda3f2011-09-03 13:01:22 +00002759MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002760 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2761 XResourceInfo *resource_info,XWindowInfo *window_info)
2762{
2763 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2764 assert(display != (Display *) NULL);
2765 assert(resource_info != (XResourceInfo *) NULL);
2766 if (window_info != (XWindowInfo *) NULL)
2767 {
2768 /*
2769 Free X image.
2770 */
2771 if (window_info->ximage != (XImage *) NULL)
2772 XDestroyImage(window_info->ximage);
2773 if (window_info->id != (Window) NULL)
2774 {
2775 /*
2776 Free destroy window and free cursors.
2777 */
2778 if (window_info->id != XRootWindow(display,visual_info->screen))
2779 (void) XDestroyWindow(display,window_info->id);
2780 if (window_info->annotate_context != (GC) NULL)
2781 (void) XFreeGC(display,window_info->annotate_context);
2782 if (window_info->highlight_context != (GC) NULL)
2783 (void) XFreeGC(display,window_info->highlight_context);
2784 if (window_info->widget_context != (GC) NULL)
2785 (void) XFreeGC(display,window_info->widget_context);
2786 if (window_info->cursor != (Cursor) NULL)
2787 (void) XFreeCursor(display,window_info->cursor);
2788 window_info->cursor=(Cursor) NULL;
2789 if (window_info->busy_cursor != (Cursor) NULL)
2790 (void) XFreeCursor(display,window_info->busy_cursor);
2791 window_info->busy_cursor=(Cursor) NULL;
2792 }
2793 }
2794 /*
2795 Free font.
2796 */
2797 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002798 {
2799 (void) XFreeFont(display,font_info);
2800 font_info=(XFontStruct *) NULL;
2801 }
cristy3ed852e2009-09-05 21:47:34 +00002802 if (map_info != (XStandardColormap *) NULL)
2803 {
2804 /*
2805 Free X Standard Colormap.
2806 */
2807 if (resource_info->map_type == (char *) NULL)
2808 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2809 (void) XFree((void *) map_info);
2810 }
2811 /*
2812 Free X visual info.
2813 */
2814 if (visual_info != (XVisualInfo *) NULL)
2815 (void) XFree((void *) visual_info);
2816 if (resource_info->close_server != MagickFalse)
2817 (void) XCloseDisplay(display);
2818}
2819
2820/*
2821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2822% %
2823% %
2824% %
2825% X F r e e S t a n d a r d C o l o r m a p %
2826% %
2827% %
2828% %
2829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2830%
2831% XFreeStandardColormap() frees an X11 colormap.
2832%
2833% The format of the XFreeStandardColormap method is:
2834%
2835% void XFreeStandardColormap(Display *display,
2836% const XVisualInfo *visual_info,XStandardColormap *map_info,
2837% XPixelInfo *pixel)
2838%
2839% A description of each parameter follows:
2840%
2841% o display: Specifies a connection to an X server; returned from
2842% XOpenDisplay.
2843%
2844% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2845% returned from XGetVisualInfo.
2846%
2847% o map_info: If map_type is specified, this structure is initialized
2848% with info from the Standard Colormap.
2849%
2850% o pixel: Specifies a pointer to a XPixelInfo structure.
2851%
2852*/
cristybcbda3f2011-09-03 13:01:22 +00002853MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002854 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2855{
2856 /*
2857 Free colormap.
2858 */
2859 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2860 assert(display != (Display *) NULL);
2861 assert(visual_info != (XVisualInfo *) NULL);
2862 assert(map_info != (XStandardColormap *) NULL);
2863 (void) XFlush(display);
2864 if (map_info->colormap != (Colormap) NULL)
2865 {
2866 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2867 (void) XFreeColormap(display,map_info->colormap);
2868 else
2869 if (pixel != (XPixelInfo *) NULL)
2870 if ((visual_info->klass != TrueColor) &&
2871 (visual_info->klass != DirectColor))
2872 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2873 (int) pixel->colors,0);
2874 }
2875 map_info->colormap=(Colormap) NULL;
2876 if (pixel != (XPixelInfo *) NULL)
2877 {
cristyf2faecf2010-05-28 19:19:36 +00002878 if (pixel->pixels != (unsigned long *) NULL)
2879 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2880 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002881 }
2882}
2883
2884/*
2885%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2886% %
2887% %
2888% %
2889% X G e t A n n o t a t e I n f o %
2890% %
2891% %
2892% %
2893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2894%
2895% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2896%
2897% The format of the XGetAnnotateInfo method is:
2898%
2899% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2900%
2901% A description of each parameter follows:
2902%
2903% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2904%
2905*/
cristybcbda3f2011-09-03 13:01:22 +00002906MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002907{
2908 /*
2909 Initialize annotate structure.
2910 */
2911 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2912 assert(annotate_info != (XAnnotateInfo *) NULL);
2913 annotate_info->x=0;
2914 annotate_info->y=0;
2915 annotate_info->width=0;
2916 annotate_info->height=0;
2917 annotate_info->stencil=ForegroundStencil;
2918 annotate_info->degrees=0.0;
2919 annotate_info->font_info=(XFontStruct *) NULL;
2920 annotate_info->text=(char *) NULL;
2921 *annotate_info->geometry='\0';
2922 annotate_info->previous=(XAnnotateInfo *) NULL;
2923 annotate_info->next=(XAnnotateInfo *) NULL;
2924 (void) XSupportsLocale();
2925 (void) XSetLocaleModifiers("");
2926}
2927
2928/*
2929%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2930% %
2931% %
2932% %
2933% X G e t M a p I n f o %
2934% %
2935% %
2936% %
2937%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2938%
2939% XGetMapInfo() initializes the XStandardColormap structure.
2940%
2941% The format of the XStandardColormap method is:
2942%
2943% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2944% XStandardColormap *map_info)
2945%
2946% A description of each parameter follows:
2947%
2948% o colormap: Specifies the ID of the X server colormap.
2949%
2950% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2951% returned from XGetVisualInfo.
2952%
2953% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2954%
2955*/
cristybcbda3f2011-09-03 13:01:22 +00002956MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002957 const Colormap colormap,XStandardColormap *map_info)
2958{
2959 /*
2960 Initialize map info.
2961 */
2962 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2963 assert(visual_info != (XVisualInfo *) NULL);
2964 assert(map_info != (XStandardColormap *) NULL);
2965 map_info->colormap=colormap;
2966 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002967 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002968 if (map_info->red_max != 0)
2969 while ((map_info->red_max & 0x01) == 0)
2970 {
2971 map_info->red_max>>=1;
2972 map_info->red_mult<<=1;
2973 }
2974 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002975 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002976 if (map_info->green_max != 0)
2977 while ((map_info->green_max & 0x01) == 0)
2978 {
2979 map_info->green_max>>=1;
2980 map_info->green_mult<<=1;
2981 }
2982 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002983 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002984 if (map_info->blue_max != 0)
2985 while ((map_info->blue_max & 0x01) == 0)
2986 {
2987 map_info->blue_max>>=1;
2988 map_info->blue_mult<<=1;
2989 }
2990 map_info->base_pixel=0;
2991}
2992
2993/*
2994%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2995% %
2996% %
2997% %
2998% X G e t P i x e l I n f o %
2999% %
3000% %
3001% %
3002%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3003%
cristy101ab702011-10-13 13:06:32 +00003004% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00003005%
cristy4c08aed2011-07-01 19:47:50 +00003006% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00003007%
cristy4c08aed2011-07-01 19:47:50 +00003008% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00003009% const XStandardColormap *map_info,const XResourceInfo *resource_info,
3010% Image *image,XPixelInfo *pixel)
3011% pixel)
3012%
3013% A description of each parameter follows:
3014%
3015% o display: Specifies a connection to an X server; returned from
3016% XOpenDisplay.
3017%
3018% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3019% returned from XGetVisualInfo.
3020%
3021% o map_info: If map_type is specified, this structure is initialized
3022% with info from the Standard Colormap.
3023%
3024% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3025%
3026% o image: the image.
3027%
3028% o pixel: Specifies a pointer to a XPixelInfo structure.
3029%
3030*/
cristybcbda3f2011-09-03 13:01:22 +00003031MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003032 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3033 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3034{
3035 static const char
3036 *PenColors[MaxNumberPens]=
3037 {
3038 "#000000000000", /* black */
3039 "#00000000ffff", /* blue */
3040 "#0000ffffffff", /* cyan */
3041 "#0000ffff0000", /* green */
3042 "#bdbdbdbdbdbd", /* gray */
3043 "#ffff00000000", /* red */
3044 "#ffff0000ffff", /* magenta */
3045 "#ffffffff0000", /* yellow */
3046 "#ffffffffffff", /* white */
3047 "#bdbdbdbdbdbd", /* gray */
3048 "#bdbdbdbdbdbd" /* gray */
3049 };
3050
3051 Colormap
3052 colormap;
3053
cristybcdf5672012-05-24 22:58:54 +00003054 extern const char
3055 BorderColor[],
3056 ForegroundColor[];
3057
cristybb503372010-05-27 20:51:26 +00003058 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003059 i;
3060
3061 Status
3062 status;
3063
3064 unsigned int
3065 packets;
3066
3067 /*
3068 Initialize pixel info.
3069 */
3070 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3071 assert(display != (Display *) NULL);
3072 assert(visual_info != (XVisualInfo *) NULL);
3073 assert(map_info != (XStandardColormap *) NULL);
3074 assert(resource_info != (XResourceInfo *) NULL);
3075 assert(pixel != (XPixelInfo *) NULL);
3076 pixel->colors=0;
3077 if (image != (Image *) NULL)
3078 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003079 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003080 packets=(unsigned int)
3081 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003082 if (pixel->pixels != (unsigned long *) NULL)
3083 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3084 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003085 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003086 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003087 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3088 image->filename);
3089 /*
3090 Set foreground color.
3091 */
3092 colormap=map_info->colormap;
3093 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3094 &pixel->foreground_color);
3095 status=XParseColor(display,colormap,resource_info->foreground_color,
3096 &pixel->foreground_color);
3097 if (status == False)
3098 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3099 resource_info->foreground_color);
3100 pixel->foreground_color.pixel=
3101 XStandardPixel(map_info,&pixel->foreground_color);
3102 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3103 /*
3104 Set background color.
3105 */
3106 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3107 status=XParseColor(display,colormap,resource_info->background_color,
3108 &pixel->background_color);
3109 if (status == False)
3110 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3111 resource_info->background_color);
3112 pixel->background_color.pixel=
3113 XStandardPixel(map_info,&pixel->background_color);
3114 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3115 /*
3116 Set border color.
3117 */
3118 (void) XParseColor(display,colormap,(char *) BorderColor,
3119 &pixel->border_color);
3120 status=XParseColor(display,colormap,resource_info->border_color,
3121 &pixel->border_color);
3122 if (status == False)
3123 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3124 resource_info->border_color);
3125 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3126 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3127 /*
3128 Set matte color.
3129 */
3130 pixel->matte_color=pixel->background_color;
3131 if (resource_info->matte_color != (char *) NULL)
3132 {
3133 /*
3134 Matte color is specified as a X resource or command line argument.
3135 */
3136 status=XParseColor(display,colormap,resource_info->matte_color,
3137 &pixel->matte_color);
3138 if (status == False)
3139 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3140 resource_info->matte_color);
3141 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3142 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3143 }
3144 /*
3145 Set highlight color.
3146 */
3147 pixel->highlight_color.red=(unsigned short) ((
3148 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3149 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3150 pixel->highlight_color.green=(unsigned short) ((
3151 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3152 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3153 pixel->highlight_color.blue=(unsigned short) ((
3154 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3155 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3156 pixel->highlight_color.pixel=
3157 XStandardPixel(map_info,&pixel->highlight_color);
3158 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3159 /*
3160 Set shadow color.
3161 */
cristya19f1d72012-08-07 18:24:38 +00003162 pixel->shadow_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003163 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003164 pixel->shadow_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003165 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003166 pixel->shadow_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003167 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3168 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3169 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3170 /*
3171 Set depth color.
3172 */
cristya19f1d72012-08-07 18:24:38 +00003173 pixel->depth_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003174 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003175 pixel->depth_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003176 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003177 pixel->depth_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003178 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3179 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3180 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3181 /*
3182 Set trough color.
3183 */
cristya19f1d72012-08-07 18:24:38 +00003184 pixel->trough_color.red=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003185 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003186 pixel->trough_color.green=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003187 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
cristya19f1d72012-08-07 18:24:38 +00003188 pixel->trough_color.blue=(unsigned short) (((double)
cristy3ed852e2009-09-05 21:47:34 +00003189 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3190 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3191 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3192 /*
3193 Set pen color.
3194 */
3195 for (i=0; i < MaxNumberPens; i++)
3196 {
3197 (void) XParseColor(display,colormap,(char *) PenColors[i],
3198 &pixel->pen_colors[i]);
3199 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3200 &pixel->pen_colors[i]);
3201 if (status == False)
3202 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3203 resource_info->pen_colors[i]);
3204 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3205 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3206 }
3207 pixel->box_color=pixel->background_color;
3208 pixel->pen_color=pixel->foreground_color;
3209 pixel->box_index=0;
3210 pixel->pen_index=1;
3211 if (image != (Image *) NULL)
3212 {
3213 if ((resource_info->gamma_correct != MagickFalse) &&
3214 (image->gamma != 0.0))
3215 {
3216 GeometryInfo
3217 geometry_info;
3218
3219 MagickStatusType
3220 flags;
3221
3222 /*
3223 Initialize map relative to display and image gamma.
3224 */
3225 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3226 red_gamma=geometry_info.rho;
3227 green_gamma=geometry_info.sigma;
3228 if ((flags & SigmaValue) == 0)
3229 green_gamma=red_gamma;
3230 blue_gamma=geometry_info.xi;
3231 if ((flags & XiValue) == 0)
3232 blue_gamma=red_gamma;
3233 red_gamma*=image->gamma;
3234 green_gamma*=image->gamma;
3235 blue_gamma*=image->gamma;
3236 }
3237 if (image->storage_class == PseudoClass)
3238 {
3239 /*
3240 Initialize pixel array for images of type PseudoClass.
3241 */
cristybb503372010-05-27 20:51:26 +00003242 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003243 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003244 for (i=0; i < MaxNumberPens; i++)
3245 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3246 pixel->colors+=MaxNumberPens;
3247 }
3248 }
3249}
3250
3251/*
3252%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3253% %
3254% %
3255% %
3256% X G e t R e s o u r c e C l a s s %
3257% %
3258% %
3259% %
3260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3261%
3262% XGetResourceClass() queries the X server for the specified resource name or
3263% class. If the resource name or class is not defined in the database, the
3264% supplied default value is returned.
3265%
3266% The format of the XGetResourceClass method is:
3267%
3268% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3269% const char *keyword,char *resource_default)
3270%
3271% A description of each parameter follows:
3272%
3273% o database: Specifies a resource database; returned from
3274% XrmGetStringDatabase.
3275%
3276% o client_name: Specifies the application name used to retrieve resource
3277% info from the X server database.
3278%
3279% o keyword: Specifies the keyword of the value being retrieved.
3280%
3281% o resource_default: Specifies the default value to return if the query
3282% fails to find the specified keyword/class.
3283%
3284*/
3285MagickExport char *XGetResourceClass(XrmDatabase database,
3286 const char *client_name,const char *keyword,char *resource_default)
3287{
3288 char
3289 resource_class[MaxTextExtent],
3290 resource_name[MaxTextExtent];
3291
3292 static char
3293 *resource_type;
3294
3295 Status
3296 status;
3297
3298 XrmValue
3299 resource_value;
3300
3301 if (database == (XrmDatabase) NULL)
3302 return(resource_default);
3303 *resource_name='\0';
3304 *resource_class='\0';
3305 if (keyword != (char *) NULL)
3306 {
3307 int
3308 c,
3309 k;
3310
3311 /*
3312 Initialize resource keyword and class.
3313 */
cristyb51dff52011-05-19 16:55:47 +00003314 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003315 client_name,keyword);
3316 c=(int) (*client_name);
3317 if ((c >= XK_a) && (c <= XK_z))
3318 c-=(XK_a-XK_A);
3319 else
3320 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3321 c-=(XK_agrave-XK_Agrave);
3322 else
3323 if ((c >= XK_oslash) && (c <= XK_thorn))
3324 c-=(XK_oslash-XK_Ooblique);
3325 k=(int) (*keyword);
3326 if ((k >= XK_a) && (k <= XK_z))
3327 k-=(XK_a-XK_A);
3328 else
3329 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3330 k-=(XK_agrave-XK_Agrave);
3331 else
3332 if ((k >= XK_oslash) && (k <= XK_thorn))
3333 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003334 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003335 client_name+1,k,keyword+1);
3336 }
3337 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3338 &resource_value);
3339 if (status == False)
3340 return(resource_default);
3341 return(resource_value.addr);
3342}
3343
3344/*
3345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3346% %
3347% %
3348% %
3349% X G e t R e s o u r c e D a t a b a s e %
3350% %
3351% %
3352% %
3353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3354%
3355% XGetResourceDatabase() creates a new resource database and initializes it.
3356%
3357% The format of the XGetResourceDatabase method is:
3358%
3359% XrmDatabase XGetResourceDatabase(Display *display,
3360% const char *client_name)
3361%
3362% A description of each parameter follows:
3363%
3364% o database: XGetResourceDatabase() returns the database after it is
3365% initialized.
3366%
3367% o display: Specifies a connection to an X server; returned from
3368% XOpenDisplay.
3369%
3370% o client_name: Specifies the application name used to retrieve resource
3371% info from the X server database.
3372%
3373*/
3374MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3375 const char *client_name)
3376{
3377 char
3378 filename[MaxTextExtent];
3379
3380 int
3381 c;
3382
3383 register const char
3384 *p;
3385
3386 XrmDatabase
3387 resource_database,
3388 server_database;
3389
3390 if (display == (Display *) NULL)
3391 return((XrmDatabase) NULL);
3392 assert(client_name != (char *) NULL);
3393 /*
3394 Initialize resource database.
3395 */
3396 XrmInitialize();
3397 (void) XGetDefault(display,(char *) client_name,"dummy");
3398 resource_database=XrmGetDatabase(display);
3399 /*
3400 Combine application database.
3401 */
3402 if (client_name != (char *) NULL)
3403 {
3404 /*
3405 Get basename of client.
3406 */
3407 p=client_name+(strlen(client_name)-1);
3408 while ((p > client_name) && (*p != '/'))
3409 p--;
3410 if (*p == '/')
3411 client_name=p+1;
3412 }
3413 c=(int) (*client_name);
3414 if ((c >= XK_a) && (c <= XK_z))
3415 c-=(XK_a-XK_A);
3416 else
3417 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3418 c-=(XK_agrave-XK_Agrave);
3419 else
3420 if ((c >= XK_oslash) && (c <= XK_thorn))
3421 c-=(XK_oslash-XK_Ooblique);
3422#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003423 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003424 X11_APPLICATION_PATH,c,client_name+1);
3425 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3426#endif
3427 if (XResourceManagerString(display) != (char *) NULL)
3428 {
3429 /*
3430 Combine server database.
3431 */
3432 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3433 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3434 }
3435 /*
3436 Merge user preferences database.
3437 */
3438#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003439 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003440 X11_PREFERENCES_PATH,client_name);
3441 ExpandFilename(filename);
3442 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3443#endif
3444 return(resource_database);
3445}
3446
3447/*
3448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3449% %
3450% %
3451% %
3452% X G e t R e s o u r c e I n f o %
3453% %
3454% %
3455% %
3456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3457%
3458% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3459%
3460% The format of the XGetResourceInfo method is:
3461%
3462% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3463% const char *client_name,XResourceInfo *resource_info)
3464%
3465% A description of each parameter follows:
3466%
3467% o image_info: the image info.
3468%
3469% o database: Specifies a resource database; returned from
3470% XrmGetStringDatabase.
3471%
3472% o client_name: Specifies the application name used to retrieve
3473% resource info from the X server database.
3474%
3475% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3476%
3477*/
3478MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3479 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3480{
3481 char
cristy00976d82011-02-20 20:31:28 +00003482 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003483 *resource_value;
3484
cristybcdf5672012-05-24 22:58:54 +00003485 extern const char
3486 BorderColor[],
3487 ForegroundColor[];
3488
cristy3ed852e2009-09-05 21:47:34 +00003489 /*
3490 Initialize resource info fields.
3491 */
3492 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3493 assert(resource_info != (XResourceInfo *) NULL);
3494 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3495 resource_info->resource_database=database;
3496 resource_info->image_info=(ImageInfo *) image_info;
3497 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3498 XMagickProgressMonitor,(void *) NULL);
3499 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3500 resource_info->close_server=MagickTrue;
3501 resource_info->client_name=AcquireString(client_name);
3502 resource_value=XGetResourceClass(database,client_name,"backdrop",
3503 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003504 resource_info->backdrop=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003505 resource_info->background_color=XGetResourceInstance(database,client_name,
3506 "background",(char *) "#d6d6d6d6d6d6");
3507 resource_info->border_color=XGetResourceInstance(database,client_name,
3508 "borderColor",BorderColor);
3509 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3510 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003511 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3512 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003513 resource_value=XGetResourceClass(database,client_name,"colormap",
3514 (char *) "shared");
3515 resource_info->colormap=UndefinedColormap;
3516 if (LocaleCompare("private",resource_value) == 0)
3517 resource_info->colormap=PrivateColormap;
3518 if (LocaleCompare("shared",resource_value) == 0)
3519 resource_info->colormap=SharedColormap;
3520 if (resource_info->colormap == UndefinedColormap)
3521 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3522 resource_value);
3523 resource_value=XGetResourceClass(database,client_name,
3524 "colorRecovery",(char *) "False");
anthony6f201312012-03-30 04:08:15 +00003525 resource_info->color_recovery=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003526 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3527 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003528 resource_info->confirm_exit=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003529 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3530 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003531 resource_info->confirm_edit=IsStringTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003532 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003533 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003534 resource_info->display_gamma=XGetResourceClass(database,client_name,
3535 "displayGamma",(char *) "2.2");
3536 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3537 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003538 resource_info->display_warnings=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003539 resource_info->font=XGetResourceClass(database,client_name,"font",
3540 (char *) NULL);
3541 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3542 resource_info->font);
3543 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3544 (char *) "fixed");
3545 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3546 (char *) "variable");
3547 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3548 (char *) "5x8");
3549 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3550 (char *) "6x10");
3551 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3552 (char *) "7x13bold");
3553 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3554 (char *) "8x13bold");
3555 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3556 (char *) "9x15bold");
3557 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3558 (char *) "10x20");
3559 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3560 (char *) "12x24");
3561 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3562 (char *) "fixed");
3563 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3564 (char *) "fixed");
3565 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3566 "foreground",ForegroundColor);
3567 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
cristy8bc259b2012-06-21 23:53:15 +00003568 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003569 resource_info->gamma_correct=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003570 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3571 client_name,"geometry",(char *) NULL));
3572 resource_value=XGetResourceClass(database,client_name,"gravity",
3573 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003574 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003575 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003576 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3577 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003578 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3579 "iconGeometry",(char *) NULL);
3580 resource_value=XGetResourceClass(database,client_name,"iconic",
3581 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003582 resource_info->iconic=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003583 resource_value=XGetResourceClass(database,client_name,"immutable",
3584 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3585 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003586 resource_info->immutable=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003587 resource_value=XGetResourceClass(database,client_name,"magnify",
3588 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003589 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003590 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3591 (char *) NULL);
3592 resource_info->matte_color=XGetResourceInstance(database,client_name,
3593 "mattecolor",(char *) NULL);
3594 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3595 "name",(char *) NULL));
3596 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3597 (char *) "black");
3598 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3599 (char *) "blue");
3600 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3601 (char *) "cyan");
3602 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3603 (char *) "green");
3604 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3605 (char *) "gray");
3606 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3607 (char *) "red");
3608 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3609 (char *) "magenta");
3610 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3611 (char *) "yellow");
3612 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3613 (char *) "white");
3614 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3615 (char *) "gray");
3616 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3617 (char *) "gray");
3618 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003619 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003620 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003621 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003622 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3623 "font",(char *) "fixed");
3624 resource_info->text_font=XGetResourceClass(database,client_name,
3625 "textFontList",resource_info->text_font);
3626 resource_info->title=XGetResourceClass(database,client_name,"title",
3627 (char *) NULL);
3628 resource_value=XGetResourceClass(database,client_name,"undoCache",
cristy92befbd2012-09-16 14:08:12 +00003629 (char *) "256");
cristye27293e2009-12-18 02:53:20 +00003630 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003631 resource_value=XGetResourceClass(database,client_name,"update",
3632 (char *) "False");
anthony6f201312012-03-30 04:08:15 +00003633 resource_info->update=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003634 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3635 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003636 resource_info->use_pixmap=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003637 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3638 (char *) "True");
anthony6f201312012-03-30 04:08:15 +00003639 resource_info->use_shared_memory=IsStringTrue(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003640 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3641 (char *) NULL);
3642 resource_info->window_group=XGetResourceClass(database,client_name,
3643 "windowGroup",(char *) NULL);
3644 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3645 (char *) NULL);
3646 resource_info->write_filename=XGetResourceClass(database,client_name,
3647 "writeFilename",(char *) NULL);
3648}
3649
3650/*
3651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3652% %
3653% %
3654% %
3655% X G e t R e s o u r c e I n s t a n c e %
3656% %
3657% %
3658% %
3659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3660%
3661% XGetResourceInstance() queries the X server for the specified resource name.
3662% If the resource name is not defined in the database, the supplied default
3663% value is returned.
3664%
3665% The format of the XGetResourceInstance method is:
3666%
3667% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3668% const char *keyword,const char *resource_default)
3669%
3670% A description of each parameter follows:
3671%
3672% o database: Specifies a resource database; returned from
3673% XrmGetStringDatabase.
3674%
3675% o client_name: Specifies the application name used to retrieve
3676% resource info from the X server database.
3677%
3678% o keyword: Specifies the keyword of the value being retrieved.
3679%
3680% o resource_default: Specifies the default value to return if the query
3681% fails to find the specified keyword/class.
3682%
3683*/
3684MagickExport char *XGetResourceInstance(XrmDatabase database,
3685 const char *client_name,const char *keyword,const char *resource_default)
3686{
3687 char
3688 *resource_type,
3689 resource_name[MaxTextExtent];
3690
3691 Status
3692 status;
3693
3694 XrmValue
3695 resource_value;
3696
3697 if (database == (XrmDatabase) NULL)
3698 return((char *) resource_default);
3699 *resource_name='\0';
3700 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003701 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003702 keyword);
3703 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3704 &resource_value);
3705 if (status == False)
3706 return((char *) resource_default);
3707 return(resource_value.addr);
3708}
3709
3710/*
3711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3712% %
3713% %
3714% %
3715% X G e t S c r e e n D e n s i t y %
3716% %
3717% %
3718% %
3719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3720%
3721% XGetScreenDensity() returns the density of the X server screen in
3722% dots-per-inch.
3723%
3724% The format of the XGetScreenDensity method is:
3725%
3726% char *XGetScreenDensity(Display *display)
3727%
3728% A description of each parameter follows:
3729%
3730% o density: XGetScreenDensity() returns the density of the X screen in
3731% dots-per-inch.
3732%
3733% o display: Specifies a connection to an X server; returned from
3734% XOpenDisplay.
3735%
3736*/
3737MagickExport char *XGetScreenDensity(Display *display)
3738{
3739 char
3740 density[MaxTextExtent];
3741
3742 double
3743 x_density,
3744 y_density;
3745
3746 /*
3747 Set density as determined by screen size.
3748 */
3749 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3750 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3751 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3752 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003753 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003754 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003755 return(GetPageGeometry(density));
3756}
3757
3758/*
3759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3760% %
3761% %
3762% %
3763+ X G e t S u b w i n d o w %
3764% %
3765% %
3766% %
3767%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3768%
3769% XGetSubwindow() returns the subwindow of a window chosen the user with the
3770% pointer and a button press.
3771%
3772% The format of the XGetSubwindow method is:
3773%
3774% Window XGetSubwindow(Display *display,Window window,int x,int y)
3775%
3776% A description of each parameter follows:
3777%
3778% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3779% otherwise the subwindow is returned.
3780%
3781% o display: Specifies a connection to an X server; returned from
3782% XOpenDisplay.
3783%
3784% o window: Specifies a pointer to a Window.
3785%
3786% o x: the x coordinate of the pointer relative to the origin of the
3787% window.
3788%
3789% o y: the y coordinate of the pointer relative to the origin of the
3790% window.
3791%
cristy3ed852e2009-09-05 21:47:34 +00003792*/
3793static Window XGetSubwindow(Display *display,Window window,int x,int y)
3794{
3795 int
3796 x_offset,
3797 y_offset;
3798
3799 Status
3800 status;
3801
3802 Window
3803 source_window,
3804 target_window;
3805
3806 assert(display != (Display *) NULL);
3807 source_window=XRootWindow(display,XDefaultScreen(display));
3808 if (window == (Window) NULL)
3809 return(source_window);
3810 target_window=window;
3811 for ( ; ; )
3812 {
3813 status=XTranslateCoordinates(display,source_window,window,x,y,
3814 &x_offset,&y_offset,&target_window);
3815 if (status != True)
3816 break;
3817 if (target_window == (Window) NULL)
3818 break;
3819 source_window=window;
3820 window=target_window;
3821 x=x_offset;
3822 y=y_offset;
3823 }
3824 if (target_window == (Window) NULL)
3825 target_window=window;
3826 return(target_window);
3827}
3828
3829/*
3830%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3831% %
3832% %
3833% %
3834% X G e t W i n d o w C o l o r %
3835% %
3836% %
3837% %
3838%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3839%
3840% XGetWindowColor() returns the color of a pixel interactively chosen from the
3841% X server.
3842%
3843% The format of the XGetWindowColor method is:
3844%
3845% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003846% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003847%
3848% A description of each parameter follows:
3849%
3850% o display: Specifies a connection to an X server; returned from
3851% XOpenDisplay.
3852%
3853% o windows: Specifies a pointer to a XWindows structure.
3854%
3855% o name: the name of the color if found in the X Color Database is
3856% returned in this character string.
3857%
cristy6710d842011-10-20 23:23:00 +00003858% o exception: return any errors or warnings in this structure.
3859%
cristy3ed852e2009-09-05 21:47:34 +00003860*/
cristybcbda3f2011-09-03 13:01:22 +00003861MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003862 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003863{
3864 int
3865 x,
3866 y;
3867
cristy101ab702011-10-13 13:06:32 +00003868 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003869 pixel;
3870
3871 RectangleInfo
3872 crop_info;
3873
3874 Status
3875 status;
3876
3877 Window
3878 child,
3879 client_window,
3880 root_window,
3881 target_window;
3882
3883 XColor
3884 color;
3885
3886 XImage
3887 *ximage;
3888
3889 XWindowAttributes
3890 window_attributes;
3891
3892 /*
3893 Choose a pixel from the X server.
3894 */
3895 assert(display != (Display *) NULL);
3896 assert(name != (char *) NULL);
3897 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3898 *name='\0';
3899 target_window=XSelectWindow(display,&crop_info);
3900 if (target_window == (Window) NULL)
3901 return(MagickFalse);
3902 root_window=XRootWindow(display,XDefaultScreen(display));
3903 client_window=target_window;
3904 if (target_window != root_window)
3905 {
3906 unsigned int
3907 d;
3908
3909 /*
3910 Get client window.
3911 */
3912 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3913 if (status != False)
3914 {
3915 client_window=XClientWindow(display,target_window);
3916 target_window=client_window;
3917 }
3918 }
3919 /*
3920 Verify window is viewable.
3921 */
3922 status=XGetWindowAttributes(display,target_window,&window_attributes);
3923 if ((status == False) || (window_attributes.map_state != IsViewable))
3924 return(MagickFalse);
3925 /*
3926 Get window X image.
3927 */
3928 (void) XTranslateCoordinates(display,root_window,target_window,
3929 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3930 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3931 if (ximage == (XImage *) NULL)
3932 return(MagickFalse);
3933 color.pixel=XGetPixel(ximage,0,0);
3934 XDestroyImage(ximage);
3935 /*
3936 Match color against the color database.
3937 */
3938 (void) XQueryColor(display,window_attributes.colormap,&color);
cristye42f6582012-02-11 17:59:50 +00003939 pixel.red=(double) ScaleShortToQuantum(color.red);
3940 pixel.green=(double) ScaleShortToQuantum(color.green);
3941 pixel.blue=(double) ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003942 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003943 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003944 exception);
cristy3ed852e2009-09-05 21:47:34 +00003945 return(MagickTrue);
3946}
3947
3948/*
3949%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3950% %
3951% %
3952% %
3953+ X G e t W i n d o w I m a g e %
3954% %
3955% %
3956% %
3957%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3958%
3959% XGetWindowImage() reads an image from the target X window and returns it.
3960% XGetWindowImage() optionally descends the window hierarchy and overlays the
3961% target image with each child image in an optimized fashion. Any child
3962% window that have the same visual, colormap, and are contained by its parent
3963% are exempted.
3964%
3965% The format of the XGetWindowImage method is:
3966%
3967% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003968% const unsigned int borders,const unsigned int level,
3969% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003970%
3971% A description of each parameter follows:
3972%
3973% o display: Specifies a connection to an X server; returned from
3974% XOpenDisplay.
3975%
3976% o window: Specifies the window to obtain the image from.
3977%
3978% o borders: Specifies whether borders pixels are to be saved with
3979% the image.
3980%
3981% o level: Specifies an unsigned integer representing the level of
3982% decent in the window hierarchy. This value must be zero or one on
3983% the initial call to XGetWindowImage. A value of zero returns after
3984% one call. A value of one causes the function to descend the window
3985% hierarchy and overlay the target image with each subwindow image.
3986%
cristy6710d842011-10-20 23:23:00 +00003987% o exception: return any errors or warnings in this structure.
3988%
cristy3ed852e2009-09-05 21:47:34 +00003989*/
3990static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003991 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003992{
3993 typedef struct _ColormapInfo
3994 {
3995 Colormap
3996 colormap;
3997
3998 XColor
3999 *colors;
4000
4001 struct _ColormapInfo
4002 *next;
4003 } ColormapInfo;
4004
4005 typedef struct _WindowInfo
4006 {
4007 Window
4008 window,
4009 parent;
4010
4011 Visual
4012 *visual;
4013
4014 Colormap
4015 colormap;
4016
4017 XSegment
4018 bounds;
4019
4020 RectangleInfo
4021 crop_info;
4022 } WindowInfo;
4023
cristy3ed852e2009-09-05 21:47:34 +00004024 int
4025 display_height,
4026 display_width,
4027 id,
4028 x_offset,
4029 y_offset;
4030
cristy4c08aed2011-07-01 19:47:50 +00004031 Quantum
4032 index;
4033
cristy3ed852e2009-09-05 21:47:34 +00004034 RectangleInfo
4035 crop_info;
4036
cristy3ed852e2009-09-05 21:47:34 +00004037 register int
4038 i;
4039
4040 static ColormapInfo
4041 *colormap_info = (ColormapInfo *) NULL;
4042
4043 static int
4044 max_windows = 0,
4045 number_windows = 0;
4046
4047 static WindowInfo
4048 *window_info;
4049
4050 Status
4051 status;
4052
4053 Window
4054 child,
4055 root_window;
4056
4057 XWindowAttributes
4058 window_attributes;
4059
4060 /*
4061 Verify window is viewable.
4062 */
4063 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4064 assert(display != (Display *) NULL);
4065 status=XGetWindowAttributes(display,window,&window_attributes);
4066 if ((status == False) || (window_attributes.map_state != IsViewable))
4067 return((Image *) NULL);
4068 /*
4069 Cropping rectangle is relative to root window.
4070 */
4071 root_window=XRootWindow(display,XDefaultScreen(display));
4072 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4073 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004074 crop_info.x=(ssize_t) x_offset;
4075 crop_info.y=(ssize_t) y_offset;
4076 crop_info.width=(size_t) window_attributes.width;
4077 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004078 if (borders != MagickFalse)
4079 {
4080 /*
4081 Include border in image.
4082 */
cristybb503372010-05-27 20:51:26 +00004083 crop_info.x-=(ssize_t) window_attributes.border_width;
4084 crop_info.y-=(ssize_t) window_attributes.border_width;
4085 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4086 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004087 }
4088 /*
4089 Crop to root window.
4090 */
4091 if (crop_info.x < 0)
4092 {
4093 crop_info.width+=crop_info.x;
4094 crop_info.x=0;
4095 }
4096 if (crop_info.y < 0)
4097 {
4098 crop_info.height+=crop_info.y;
4099 crop_info.y=0;
4100 }
4101 display_width=XDisplayWidth(display,XDefaultScreen(display));
4102 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004103 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004104 display_height=XDisplayHeight(display,XDefaultScreen(display));
4105 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004106 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004107 /*
4108 Initialize window info attributes.
4109 */
4110 if (number_windows >= max_windows)
4111 {
4112 /*
4113 Allocate or resize window info buffer.
4114 */
4115 max_windows+=1024;
4116 if (window_info == (WindowInfo *) NULL)
4117 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4118 sizeof(*window_info));
4119 else
4120 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4121 max_windows,sizeof(*window_info));
4122 }
4123 if (window_info == (WindowInfo *) NULL)
4124 {
4125 ThrowXWindowFatalException(ResourceLimitError,
4126 "MemoryAllocationFailed","...");
4127 return((Image *) NULL);
4128 }
4129 id=number_windows++;
4130 window_info[id].window=window;
4131 window_info[id].visual=window_attributes.visual;
4132 window_info[id].colormap=window_attributes.colormap;
4133 window_info[id].bounds.x1=(short) crop_info.x;
4134 window_info[id].bounds.y1=(short) crop_info.y;
4135 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4136 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4137 crop_info.x-=x_offset;
4138 crop_info.y-=y_offset;
4139 window_info[id].crop_info=crop_info;
4140 if (level != 0)
4141 {
4142 unsigned int
4143 number_children;
4144
4145 Window
4146 *children;
4147
4148 /*
4149 Descend the window hierarchy.
4150 */
4151 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4152 &children,&number_children);
4153 for (i=0; i < id; i++)
4154 if ((window_info[i].window == window_info[id].parent) &&
4155 (window_info[i].visual == window_info[id].visual) &&
4156 (window_info[i].colormap == window_info[id].colormap))
4157 {
4158 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4159 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4160 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4161 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4162 {
4163 /*
4164 Eliminate windows not circumscribed by their parent.
4165 */
4166 number_windows--;
4167 break;
4168 }
4169 }
4170 if ((status == True) && (number_children != 0))
4171 {
4172 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004173 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4174 exception);
cristy3ed852e2009-09-05 21:47:34 +00004175 (void) XFree((void *) children);
4176 }
4177 }
4178 if (level <= 1)
4179 {
cristyc57f6942010-11-12 01:47:39 +00004180 CacheView
4181 *composite_view;
4182
cristy3ed852e2009-09-05 21:47:34 +00004183 ColormapInfo
4184 *next;
4185
cristy3ed852e2009-09-05 21:47:34 +00004186 Image
4187 *composite_image,
4188 *image;
4189
4190 int
4191 y;
4192
4193 MagickBooleanType
4194 import;
4195
4196 register int
4197 j,
4198 x;
4199
cristy4c08aed2011-07-01 19:47:50 +00004200 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004201 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004202
cristybb503372010-05-27 20:51:26 +00004203 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004204 pixel;
4205
4206 unsigned int
4207 number_colors;
4208
4209 XColor
4210 *colors;
4211
4212 XImage
4213 *ximage;
4214
4215 /*
4216 Get X image for each window in the list.
4217 */
4218 image=NewImageList();
4219 for (id=0; id < number_windows; id++)
4220 {
4221 /*
4222 Does target window intersect top level window?
4223 */
4224 import=
4225 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4226 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4227 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4228 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4229 MagickTrue : MagickFalse;
4230 /*
4231 Is target window contained by another window with the same colormap?
4232 */
4233 for (j=0; j < id; j++)
4234 if ((window_info[id].visual == window_info[j].visual) &&
4235 (window_info[id].colormap == window_info[j].colormap))
4236 {
4237 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4238 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4239 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4240 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4241 import=MagickFalse;
4242 }
4243 else
4244 if ((window_info[id].visual != window_info[j].visual) ||
4245 (window_info[id].colormap != window_info[j].colormap))
4246 {
4247 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4248 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4249 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4250 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4251 import=MagickTrue;
4252 }
4253 if (import == MagickFalse)
4254 continue;
4255 /*
4256 Get X image.
4257 */
4258 ximage=XGetImage(display,window_info[id].window,(int)
4259 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4260 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4261 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4262 if (ximage == (XImage *) NULL)
4263 continue;
4264 /*
4265 Initialize window colormap.
4266 */
4267 number_colors=0;
4268 colors=(XColor *) NULL;
4269 if (window_info[id].colormap != (Colormap) NULL)
4270 {
4271 ColormapInfo
4272 *p;
4273
4274 /*
4275 Search colormap list for window colormap.
4276 */
4277 number_colors=(unsigned int) window_info[id].visual->map_entries;
4278 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4279 if (p->colormap == window_info[id].colormap)
4280 break;
4281 if (p == (ColormapInfo *) NULL)
4282 {
4283 /*
4284 Get the window colormap.
4285 */
4286 colors=(XColor *) AcquireQuantumMemory(number_colors,
4287 sizeof(*colors));
4288 if (colors == (XColor *) NULL)
4289 {
4290 XDestroyImage(ximage);
4291 return((Image *) NULL);
4292 }
4293 if ((window_info[id].visual->klass != DirectColor) &&
4294 (window_info[id].visual->klass != TrueColor))
4295 for (i=0; i < (int) number_colors; i++)
4296 {
cristybb503372010-05-27 20:51:26 +00004297 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004298 colors[i].pad='\0';
4299 }
4300 else
4301 {
cristybb503372010-05-27 20:51:26 +00004302 size_t
cristy3ed852e2009-09-05 21:47:34 +00004303 blue,
4304 blue_bit,
4305 green,
4306 green_bit,
4307 red,
4308 red_bit;
4309
4310 /*
4311 DirectColor or TrueColor visual.
4312 */
4313 red=0;
4314 green=0;
4315 blue=0;
4316 red_bit=window_info[id].visual->red_mask &
4317 (~(window_info[id].visual->red_mask)+1);
4318 green_bit=window_info[id].visual->green_mask &
4319 (~(window_info[id].visual->green_mask)+1);
4320 blue_bit=window_info[id].visual->blue_mask &
4321 (~(window_info[id].visual->blue_mask)+1);
4322 for (i=0; i < (int) number_colors; i++)
4323 {
cristy8891f9c2010-06-04 23:32:17 +00004324 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004325 colors[i].pad='\0';
4326 red+=red_bit;
4327 if (red > window_info[id].visual->red_mask)
4328 red=0;
4329 green+=green_bit;
4330 if (green > window_info[id].visual->green_mask)
4331 green=0;
4332 blue+=blue_bit;
4333 if (blue > window_info[id].visual->blue_mask)
4334 blue=0;
4335 }
4336 }
4337 (void) XQueryColors(display,window_info[id].colormap,colors,
4338 (int) number_colors);
4339 /*
4340 Append colormap to colormap list.
4341 */
cristy73bd4a52010-10-05 11:24:23 +00004342 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004343 if (p == (ColormapInfo *) NULL)
4344 return((Image *) NULL);
4345 p->colormap=window_info[id].colormap;
4346 p->colors=colors;
4347 p->next=colormap_info;
4348 colormap_info=p;
4349 }
4350 colors=p->colors;
4351 }
4352 /*
4353 Allocate image structure.
4354 */
cristy6710d842011-10-20 23:23:00 +00004355 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004356 if (composite_image == (Image *) NULL)
4357 {
4358 XDestroyImage(ximage);
4359 return((Image *) NULL);
4360 }
4361 /*
4362 Convert X image to MIFF format.
4363 */
4364 if ((window_info[id].visual->klass != TrueColor) &&
4365 (window_info[id].visual->klass != DirectColor))
4366 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004367 composite_image->columns=(size_t) ximage->width;
4368 composite_image->rows=(size_t) ximage->height;
cristydb070952012-04-20 14:33:00 +00004369 composite_view=AcquireAuthenticCacheView(composite_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00004370 switch (composite_image->storage_class)
4371 {
4372 case DirectClass:
4373 default:
4374 {
cristybb503372010-05-27 20:51:26 +00004375 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004376 color,
4377 index;
4378
cristybb503372010-05-27 20:51:26 +00004379 size_t
cristy3ed852e2009-09-05 21:47:34 +00004380 blue_mask,
4381 blue_shift,
4382 green_mask,
4383 green_shift,
4384 red_mask,
4385 red_shift;
4386
4387 /*
4388 Determine shift and mask for red, green, and blue.
4389 */
4390 red_mask=window_info[id].visual->red_mask;
4391 red_shift=0;
4392 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4393 {
4394 red_mask>>=1;
4395 red_shift++;
4396 }
4397 green_mask=window_info[id].visual->green_mask;
4398 green_shift=0;
4399 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4400 {
4401 green_mask>>=1;
4402 green_shift++;
4403 }
4404 blue_mask=window_info[id].visual->blue_mask;
4405 blue_shift=0;
4406 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4407 {
4408 blue_mask>>=1;
4409 blue_shift++;
4410 }
4411 /*
4412 Convert X image to DirectClass packets.
4413 */
4414 if ((number_colors != 0) &&
4415 (window_info[id].visual->klass == DirectColor))
4416 for (y=0; y < (int) composite_image->rows; y++)
4417 {
cristyc57f6942010-11-12 01:47:39 +00004418 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004419 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004420 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004421 break;
4422 for (x=0; x < (int) composite_image->columns; x++)
4423 {
4424 pixel=XGetPixel(ximage,x,y);
4425 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004426 SetPixelRed(composite_image,
4427 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004428 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004429 SetPixelGreen(composite_image,
4430 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004431 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004432 SetPixelBlue(composite_image,
4433 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004434 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004435 }
cristy0b1a7972011-10-22 22:17:02 +00004436 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4437 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004438 break;
4439 }
4440 else
4441 for (y=0; y < (int) composite_image->rows; y++)
4442 {
cristyc57f6942010-11-12 01:47:39 +00004443 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004444 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004445 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004446 break;
4447 for (x=0; x < (int) composite_image->columns; x++)
4448 {
4449 pixel=XGetPixel(ximage,x,y);
4450 color=(pixel >> red_shift) & red_mask;
4451 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004452 SetPixelRed(composite_image,
4453 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004454 color=(pixel >> green_shift) & green_mask;
4455 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004456 SetPixelGreen(composite_image,
4457 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004458 color=(pixel >> blue_shift) & blue_mask;
4459 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004460 SetPixelBlue(composite_image,
4461 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004462 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004463 }
cristy0b1a7972011-10-22 22:17:02 +00004464 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4465 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004466 break;
4467 }
4468 break;
4469 }
4470 case PseudoClass:
4471 {
4472 /*
4473 Create colormap.
4474 */
cristy0b1a7972011-10-22 22:17:02 +00004475 status=AcquireImageColormap(composite_image,number_colors,
4476 exception);
4477 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004478 {
4479 XDestroyImage(ximage);
4480 composite_image=DestroyImage(composite_image);
4481 return((Image *) NULL);
4482 }
4483 for (i=0; i < (int) composite_image->colors; i++)
4484 {
cristye42f6582012-02-11 17:59:50 +00004485 composite_image->colormap[colors[i].pixel].red=(double)
cristy3ed852e2009-09-05 21:47:34 +00004486 ScaleShortToQuantum(colors[i].red);
cristye42f6582012-02-11 17:59:50 +00004487 composite_image->colormap[colors[i].pixel].green=(double)
cristy3ed852e2009-09-05 21:47:34 +00004488 ScaleShortToQuantum(colors[i].green);
cristye42f6582012-02-11 17:59:50 +00004489 composite_image->colormap[colors[i].pixel].blue=(double)
cristy3ed852e2009-09-05 21:47:34 +00004490 ScaleShortToQuantum(colors[i].blue);
4491 }
4492 /*
4493 Convert X image to PseudoClass packets.
4494 */
4495 for (y=0; y < (int) composite_image->rows; y++)
4496 {
cristyc57f6942010-11-12 01:47:39 +00004497 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4498 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004499 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004500 break;
cristy3ed852e2009-09-05 21:47:34 +00004501 for (x=0; x < (int) composite_image->columns; x++)
4502 {
cristy4c08aed2011-07-01 19:47:50 +00004503 index=(Quantum) XGetPixel(ximage,x,y);
4504 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004505 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004506 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004507 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004508 }
cristy0b1a7972011-10-22 22:17:02 +00004509 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4510 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004511 break;
4512 }
4513 break;
4514 }
4515 }
cristyc57f6942010-11-12 01:47:39 +00004516 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004517 XDestroyImage(ximage);
4518 if (image == (Image *) NULL)
4519 {
4520 image=composite_image;
4521 continue;
4522 }
4523 /*
4524 Composite any children in back-to-front order.
4525 */
4526 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4527 &x_offset,&y_offset,&child);
4528 x_offset-=(int) crop_info.x;
4529 if (x_offset < 0)
4530 x_offset=0;
4531 y_offset-=(int) crop_info.y;
4532 if (y_offset < 0)
4533 y_offset=0;
cristy39172402012-03-30 13:04:39 +00004534 (void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00004535 (ssize_t) x_offset,(ssize_t) y_offset,exception);
cristy5f257b22012-03-07 00:27:29 +00004536 composite_image=DestroyImage(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004537 }
4538 /*
4539 Relinquish resources.
4540 */
4541 while (colormap_info != (ColormapInfo *) NULL)
4542 {
4543 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004544 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4545 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004546 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4547 colormap_info=next;
4548 }
4549 /*
4550 Relinquish resources and restore initial state.
4551 */
4552 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4553 max_windows=0;
4554 number_windows=0;
4555 colormap_info=(ColormapInfo *) NULL;
4556 return(image);
4557 }
4558 return((Image *) NULL);
4559}
4560
4561/*
4562%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4563% %
4564% %
4565% %
4566% X G e t W i n d o w I n f o %
4567% %
4568% %
4569% %
4570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4571%
4572% XGetWindowInfo() initializes the XWindowInfo structure.
4573%
4574% The format of the XGetWindowInfo method is:
4575%
4576% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4577% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4578% XResourceInfo *resource_info,XWindowInfo *window)
4579% resource_info,window)
4580%
4581% A description of each parameter follows:
4582%
4583% o display: Specifies a connection to an X server; returned from
4584% XOpenDisplay.
4585%
4586% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4587% returned from XGetVisualInfo.
4588%
4589% o map_info: If map_type is specified, this structure is initialized
4590% with info from the Standard Colormap.
4591%
4592% o pixel: Specifies a pointer to a XPixelInfo structure.
4593%
4594% o font_info: Specifies a pointer to a XFontStruct structure.
4595%
4596% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4597%
4598*/
cristybcbda3f2011-09-03 13:01:22 +00004599MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004600 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4601 XResourceInfo *resource_info,XWindowInfo *window)
4602{
4603 /*
4604 Initialize window info.
4605 */
4606 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4607 assert(display != (Display *) NULL);
4608 assert(visual_info != (XVisualInfo *) NULL);
4609 assert(map_info != (XStandardColormap *) NULL);
4610 assert(pixel != (XPixelInfo *) NULL);
4611 assert(resource_info != (XResourceInfo *) NULL);
4612 assert(window != (XWindowInfo *) NULL);
4613 if (window->id != (Window) NULL)
4614 {
4615 if (window->cursor != (Cursor) NULL)
4616 (void) XFreeCursor(display,window->cursor);
4617 if (window->busy_cursor != (Cursor) NULL)
4618 (void) XFreeCursor(display,window->busy_cursor);
4619 if (window->highlight_stipple != (Pixmap) NULL)
4620 (void) XFreePixmap(display,window->highlight_stipple);
4621 if (window->shadow_stipple != (Pixmap) NULL)
4622 (void) XFreePixmap(display,window->shadow_stipple);
4623 if (window->name == (char *) NULL)
4624 window->name=AcquireString("");
4625 if (window->icon_name == (char *) NULL)
4626 window->icon_name=AcquireString("");
4627 }
4628 else
4629 {
4630 /*
4631 Initialize these attributes just once.
4632 */
4633 window->id=(Window) NULL;
4634 if (window->name == (char *) NULL)
4635 window->name=AcquireString("");
4636 if (window->icon_name == (char *) NULL)
4637 window->icon_name=AcquireString("");
4638 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4639 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4640 window->ximage=(XImage *) NULL;
4641 window->matte_image=(XImage *) NULL;
4642 window->pixmap=(Pixmap) NULL;
4643 window->matte_pixmap=(Pixmap) NULL;
4644 window->mapped=MagickFalse;
4645 window->stasis=MagickFalse;
4646 window->shared_memory=MagickTrue;
4647 window->segment_info=(void *) NULL;
4648#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4649 {
4650 XShmSegmentInfo
4651 *segment_info;
4652
4653 if (window->segment_info == (void *) NULL)
4654 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4655 segment_info=(XShmSegmentInfo *) window->segment_info;
4656 segment_info[0].shmid=(-1);
4657 segment_info[0].shmaddr=(char *) NULL;
4658 segment_info[1].shmid=(-1);
4659 segment_info[1].shmaddr=(char *) NULL;
4660 }
4661#endif
4662 }
4663 /*
4664 Initialize these attributes every time function is called.
4665 */
4666 window->screen=visual_info->screen;
4667 window->root=XRootWindow(display,visual_info->screen);
4668 window->visual=visual_info->visual;
4669 window->storage_class=(unsigned int) visual_info->klass;
4670 window->depth=(unsigned int) visual_info->depth;
4671 window->visual_info=visual_info;
4672 window->map_info=map_info;
4673 window->pixel_info=pixel;
4674 window->font_info=font_info;
4675 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4676 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4677 window->geometry=(char *) NULL;
4678 window->icon_geometry=(char *) NULL;
4679 if (resource_info->icon_geometry != (char *) NULL)
4680 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4681 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004682 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004683 window->width=1;
4684 window->height=1;
4685 window->min_width=1;
4686 window->min_height=1;
4687 window->width_inc=1;
4688 window->height_inc=1;
4689 window->border_width=resource_info->border_width;
4690 window->annotate_context=pixel->annotate_context;
4691 window->highlight_context=pixel->highlight_context;
4692 window->widget_context=pixel->widget_context;
4693 window->shadow_stipple=(Pixmap) NULL;
4694 window->highlight_stipple=(Pixmap) NULL;
4695 window->use_pixmap=MagickTrue;
4696 window->immutable=MagickFalse;
4697 window->shape=MagickFalse;
4698 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004699 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004700 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4701 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4702 window->attributes.background_pixel=pixel->background_color.pixel;
4703 window->attributes.background_pixmap=(Pixmap) NULL;
4704 window->attributes.bit_gravity=ForgetGravity;
4705 window->attributes.backing_store=WhenMapped;
4706 window->attributes.save_under=MagickTrue;
4707 window->attributes.border_pixel=pixel->border_color.pixel;
4708 window->attributes.colormap=map_info->colormap;
4709 window->attributes.cursor=window->cursor;
4710 window->attributes.do_not_propagate_mask=NoEventMask;
4711 window->attributes.event_mask=NoEventMask;
4712 window->attributes.override_redirect=MagickFalse;
4713 window->attributes.win_gravity=NorthWestGravity;
4714 window->orphan=MagickFalse;
4715}
4716
4717/*
4718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4719% %
4720% %
4721% %
4722% X H i g h l i g h t E l l i p s e %
4723% %
4724% %
4725% %
4726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4727%
4728% XHighlightEllipse() puts a border on the X server around a region defined by
4729% highlight_info.
4730%
4731% The format of the XHighlightEllipse method is:
4732%
4733% void XHighlightEllipse(Display *display,Window window,
4734% GC annotate_context,const RectangleInfo *highlight_info)
4735%
4736% A description of each parameter follows:
4737%
4738% o display: Specifies a connection to an X server; returned from
4739% XOpenDisplay.
4740%
4741% o window: Specifies a pointer to a Window structure.
4742%
4743% o annotate_context: Specifies a pointer to a GC structure.
4744%
4745% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4746% contains the extents of any highlighting rectangle.
4747%
4748*/
cristybcbda3f2011-09-03 13:01:22 +00004749MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004750 GC annotate_context,const RectangleInfo *highlight_info)
4751{
4752 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4753 assert(display != (Display *) NULL);
4754 assert(window != (Window) NULL);
4755 assert(annotate_context != (GC) NULL);
4756 assert(highlight_info != (RectangleInfo *) NULL);
4757 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4758 return;
4759 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4760 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4761 (unsigned int) highlight_info->height-1,0,360*64);
4762 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4763 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4764 (unsigned int) highlight_info->height-3,0,360*64);
4765}
4766
4767/*
4768%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4769% %
4770% %
4771% %
4772% X H i g h l i g h t L i n e %
4773% %
4774% %
4775% %
4776%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4777%
4778% XHighlightLine() puts a border on the X server around a region defined by
4779% highlight_info.
4780%
4781% The format of the XHighlightLine method is:
4782%
4783% void XHighlightLine(Display *display,Window window,GC annotate_context,
4784% const XSegment *highlight_info)
4785%
4786% A description of each parameter follows:
4787%
4788% o display: Specifies a connection to an X server; returned from
4789% XOpenDisplay.
4790%
4791% o window: Specifies a pointer to a Window structure.
4792%
4793% o annotate_context: Specifies a pointer to a GC structure.
4794%
4795% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4796% contains the extents of any highlighting rectangle.
4797%
4798*/
cristybcbda3f2011-09-03 13:01:22 +00004799MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004800 GC annotate_context,const XSegment *highlight_info)
4801{
4802 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4803 assert(display != (Display *) NULL);
4804 assert(window != (Window) NULL);
4805 assert(annotate_context != (GC) NULL);
4806 assert(highlight_info != (XSegment *) NULL);
4807 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4808 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4809}
4810
4811/*
4812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4813% %
4814% %
4815% %
4816% X H i g h l i g h t R e c t a n g l e %
4817% %
4818% %
4819% %
4820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4821%
4822% XHighlightRectangle() puts a border on the X server around a region defined
4823% by highlight_info.
4824%
4825% The format of the XHighlightRectangle method is:
4826%
4827% void XHighlightRectangle(Display *display,Window window,
4828% GC annotate_context,const RectangleInfo *highlight_info)
4829%
4830% A description of each parameter follows:
4831%
4832% o display: Specifies a connection to an X server; returned from
4833% XOpenDisplay.
4834%
4835% o window: Specifies a pointer to a Window structure.
4836%
4837% o annotate_context: Specifies a pointer to a GC structure.
4838%
4839% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4840% contains the extents of any highlighting rectangle.
4841%
4842*/
cristybcbda3f2011-09-03 13:01:22 +00004843MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004844 GC annotate_context,const RectangleInfo *highlight_info)
4845{
4846 assert(display != (Display *) NULL);
4847 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4848 assert(window != (Window) NULL);
4849 assert(annotate_context != (GC) NULL);
4850 assert(highlight_info != (RectangleInfo *) NULL);
4851 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4852 return;
4853 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4854 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4855 (unsigned int) highlight_info->height-1);
4856 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4857 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4858 (unsigned int) highlight_info->height-3);
4859}
4860
4861/*
4862%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4863% %
4864% %
4865% %
4866% X I m p o r t I m a g e %
4867% %
4868% %
4869% %
4870%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4871%
4872% XImportImage() reads an image from an X window.
4873%
4874% The format of the XImportImage method is:
4875%
cristy6710d842011-10-20 23:23:00 +00004876% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4877% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004878%
4879% A description of each parameter follows:
4880%
4881% o image_info: the image info.
4882%
4883% o ximage_info: Specifies a pointer to an XImportInfo structure.
4884%
cristy6710d842011-10-20 23:23:00 +00004885% o exception: return any errors or warnings in this structure.
4886%
cristy3ed852e2009-09-05 21:47:34 +00004887*/
4888MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004889 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004890{
4891 Colormap
4892 *colormaps;
4893
4894 Display
4895 *display;
4896
4897 Image
4898 *image;
4899
4900 int
4901 number_colormaps,
4902 number_windows,
4903 x;
4904
4905 RectangleInfo
4906 crop_info;
4907
4908 Status
4909 status;
4910
4911 Window
4912 *children,
4913 client,
4914 prior_target,
4915 root,
4916 target;
4917
4918 XTextProperty
4919 window_name;
4920
4921 /*
4922 Open X server connection.
4923 */
4924 assert(image_info != (const ImageInfo *) NULL);
4925 assert(image_info->signature == MagickSignature);
4926 if (image_info->debug != MagickFalse)
4927 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4928 image_info->filename);
4929 assert(ximage_info != (XImportInfo *) NULL);
4930 display=XOpenDisplay(image_info->server_name);
4931 if (display == (Display *) NULL)
4932 {
4933 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4934 XDisplayName(image_info->server_name));
4935 return((Image *) NULL);
4936 }
4937 /*
4938 Set our forgiving exception handler.
4939 */
4940 (void) XSetErrorHandler(XError);
4941 /*
4942 Select target window.
4943 */
4944 crop_info.x=0;
4945 crop_info.y=0;
4946 crop_info.width=0;
4947 crop_info.height=0;
4948 root=XRootWindow(display,XDefaultScreen(display));
4949 target=(Window) NULL;
4950 if ((image_info->filename != (char *) NULL) &&
4951 (*image_info->filename != '\0'))
4952 {
4953 if (LocaleCompare(image_info->filename,"root") == 0)
4954 target=root;
4955 else
4956 {
4957 /*
4958 Select window by ID or name.
4959 */
4960 if (isdigit((unsigned char) *image_info->filename) != 0)
4961 target=XWindowByID(display,root,(Window)
4962 strtol(image_info->filename,(char **) NULL,0));
4963 if (target == (Window) NULL)
4964 target=XWindowByName(display,root,image_info->filename);
4965 if (target == (Window) NULL)
4966 ThrowXWindowFatalException(XServerError,
4967 "NoWindowWithSpecifiedIDExists",image_info->filename);
4968 }
4969 }
4970 /*
4971 If target window is not defined, interactively select one.
4972 */
4973 prior_target=target;
4974 if (target == (Window) NULL)
4975 target=XSelectWindow(display,&crop_info);
4976 if (target == (Window) NULL)
4977 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4978 image_info->filename);
4979 client=target; /* obsolete */
4980 if (target != root)
4981 {
4982 unsigned int
4983 d;
4984
4985 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4986 if (status != False)
4987 {
4988 for ( ; ; )
4989 {
4990 Window
4991 parent;
4992
4993 /*
4994 Find window manager frame.
4995 */
4996 status=XQueryTree(display,target,&root,&parent,&children,&d);
4997 if ((status != False) && (children != (Window *) NULL))
4998 (void) XFree((char *) children);
4999 if ((status == False) || (parent == (Window) NULL) ||
5000 (parent == root))
5001 break;
5002 target=parent;
5003 }
5004 /*
5005 Get client window.
5006 */
5007 client=XClientWindow(display,target);
5008 if (ximage_info->frame == MagickFalse)
5009 target=client;
5010 if ((ximage_info->frame == MagickFalse) &&
5011 (prior_target != MagickFalse))
5012 target=prior_target;
cristy3ed852e2009-09-05 21:47:34 +00005013 }
5014 }
5015 if (ximage_info->screen)
5016 {
5017 int
5018 y;
5019
5020 Window
5021 child;
5022
5023 XWindowAttributes
5024 window_attributes;
5025
5026 /*
5027 Obtain window image directly from screen.
5028 */
5029 status=XGetWindowAttributes(display,target,&window_attributes);
5030 if (status == False)
5031 {
5032 ThrowXWindowFatalException(XServerError,
5033 "UnableToReadXWindowAttributes",image_info->filename);
5034 (void) XCloseDisplay(display);
5035 return((Image *) NULL);
5036 }
5037 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005038 crop_info.x=(ssize_t) x;
5039 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005040 crop_info.width=(size_t) window_attributes.width;
5041 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005042 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005043 {
5044 /*
5045 Include border in image.
5046 */
5047 crop_info.x-=window_attributes.border_width;
5048 crop_info.y-=window_attributes.border_width;
5049 crop_info.width+=window_attributes.border_width << 1;
5050 crop_info.height+=window_attributes.border_width << 1;
5051 }
5052 target=root;
5053 }
5054 /*
5055 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5056 */
5057 number_windows=0;
5058 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5059 if ((status == True) && (number_windows > 0))
5060 {
5061 ximage_info->descend=MagickTrue;
5062 (void) XFree ((char *) children);
5063 }
5064 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5065 if (number_colormaps > 0)
5066 {
5067 if (number_colormaps > 1)
5068 ximage_info->descend=MagickTrue;
5069 (void) XFree((char *) colormaps);
5070 }
5071 /*
5072 Alert the user not to alter the screen.
5073 */
5074 if (ximage_info->silent == MagickFalse)
5075 (void) XBell(display,0);
5076 /*
5077 Get image by window id.
5078 */
5079 (void) XGrabServer(display);
5080 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005081 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005082 (void) XUngrabServer(display);
5083 if (image == (Image *) NULL)
5084 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5085 image_info->filename)
5086 else
5087 {
5088 (void) CopyMagickString(image->filename,image_info->filename,
5089 MaxTextExtent);
5090 if ((crop_info.width != 0) && (crop_info.height != 0))
5091 {
5092 Image
5093 *clone_image,
5094 *crop_image;
5095
5096 /*
5097 Crop image as defined by the cropping rectangle.
5098 */
cristy6710d842011-10-20 23:23:00 +00005099 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005100 if (clone_image != (Image *) NULL)
5101 {
cristy6710d842011-10-20 23:23:00 +00005102 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005103 if (crop_image != (Image *) NULL)
5104 {
5105 image=DestroyImage(image);
5106 image=crop_image;
5107 }
5108 }
5109 }
5110 status=XGetWMName(display,target,&window_name);
5111 if (status == True)
5112 {
5113 if ((image_info->filename != (char *) NULL) &&
5114 (*image_info->filename == '\0'))
5115 (void) CopyMagickString(image->filename,(char *) window_name.value,
5116 (size_t) window_name.nitems+1);
5117 (void) XFree((void *) window_name.value);
5118 }
5119 }
5120 if (ximage_info->silent == MagickFalse)
5121 {
5122 /*
5123 Alert the user we're done.
5124 */
5125 (void) XBell(display,0);
5126 (void) XBell(display,0);
5127 }
5128 (void) XCloseDisplay(display);
5129 return(image);
5130}
5131
5132/*
5133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5134% %
5135% %
5136% %
5137% X I n i t i a l i z e W i n d o w s %
5138% %
5139% %
5140% %
5141%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5142%
5143% XInitializeWindows() initializes the XWindows structure.
5144%
5145% The format of the XInitializeWindows method is:
5146%
5147% XWindows *XInitializeWindows(Display *display,
5148% XResourceInfo *resource_info)
5149%
5150% A description of each parameter follows:
5151%
5152% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5153%
5154% o display: Specifies a connection to an X server; returned from
5155% XOpenDisplay.
5156%
5157% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5158%
5159*/
cristybcbda3f2011-09-03 13:01:22 +00005160MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005161 XResourceInfo *resource_info)
5162{
5163 Window
5164 root_window;
5165
5166 XWindows
5167 *windows;
5168
5169 /*
5170 Allocate windows structure.
5171 */
cristy73bd4a52010-10-05 11:24:23 +00005172 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005173 if (windows == (XWindows *) NULL)
5174 {
5175 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5176 "...");
5177 return((XWindows *) NULL);
5178 }
5179 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5180 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5181 sizeof(*windows->pixel_info));
5182 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5183 sizeof(*windows->icon_pixel));
5184 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5185 sizeof(*windows->icon_resources));
5186 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5187 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5188 (windows->icon_resources == (XResourceInfo *) NULL))
5189 {
5190 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5191 "...");
5192 return((XWindows *) NULL);
5193 }
5194 /*
5195 Initialize windows structure.
5196 */
5197 windows->display=display;
5198 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5199 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5200 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5201 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5202 windows->im_remote_command=
5203 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5204 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5205 windows->im_update_colormap=
5206 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5207 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5208 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5209 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5210 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5211 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005212#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005213 (void) XSynchronize(display,IsWindows95());
5214#endif
5215 if (IsEventLogging())
5216 {
5217 (void) XSynchronize(display,MagickTrue);
5218 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005219 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005220 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5221 (void) LogMagickEvent(X11Event,GetMagickModule(),
5222 " Window Manager: 0x%lx",windows->wm_protocols);
5223 (void) LogMagickEvent(X11Event,GetMagickModule(),
5224 " delete window: 0x%lx",windows->wm_delete_window);
5225 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5226 windows->wm_take_focus);
5227 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5228 windows->im_protocols);
5229 (void) LogMagickEvent(X11Event,GetMagickModule(),
5230 " remote command: 0x%lx",windows->im_remote_command);
5231 (void) LogMagickEvent(X11Event,GetMagickModule(),
5232 " update widget: 0x%lx",windows->im_update_widget);
5233 (void) LogMagickEvent(X11Event,GetMagickModule(),
5234 " update colormap: 0x%lx",windows->im_update_colormap);
5235 (void) LogMagickEvent(X11Event,GetMagickModule(),
5236 " former image: 0x%lx",windows->im_former_image);
5237 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5238 windows->im_next_image);
5239 (void) LogMagickEvent(X11Event,GetMagickModule(),
5240 " retain colors: 0x%lx",windows->im_retain_colors);
5241 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5242 windows->im_exit);
5243 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5244 windows->dnd_protocols);
5245 }
5246 /*
5247 Allocate standard colormap.
5248 */
5249 windows->map_info=XAllocStandardColormap();
5250 windows->icon_map=XAllocStandardColormap();
5251 if ((windows->map_info == (XStandardColormap *) NULL) ||
5252 (windows->icon_map == (XStandardColormap *) NULL))
5253 ThrowXWindowFatalException(ResourceLimitFatalError,
5254 "MemoryAllocationFailed","...");
5255 windows->map_info->colormap=(Colormap) NULL;
5256 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005257 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005258 windows->pixel_info->annotate_context=(GC) NULL;
5259 windows->pixel_info->highlight_context=(GC) NULL;
5260 windows->pixel_info->widget_context=(GC) NULL;
5261 windows->font_info=(XFontStruct *) NULL;
5262 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005263 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005264 /*
5265 Allocate visual.
5266 */
5267 *windows->icon_resources=(*resource_info);
5268 windows->icon_resources->visual_type=(char *) "default";
5269 windows->icon_resources->colormap=SharedColormap;
5270 windows->visual_info=
5271 XBestVisualInfo(display,windows->map_info,resource_info);
5272 windows->icon_visual=
5273 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5274 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5275 (windows->icon_visual == (XVisualInfo *) NULL))
5276 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5277 resource_info->visual_type);
5278 if (IsEventLogging())
5279 {
5280 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5281 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5282 windows->visual_info->visualid);
5283 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5284 XVisualClassName(windows->visual_info->klass));
5285 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5286 windows->visual_info->depth);
5287 (void) LogMagickEvent(X11Event,GetMagickModule(),
5288 " size of colormap: %d entries",windows->visual_info->colormap_size);
5289 (void) LogMagickEvent(X11Event,GetMagickModule(),
5290 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5291 windows->visual_info->red_mask,windows->visual_info->green_mask,
5292 windows->visual_info->blue_mask);
5293 (void) LogMagickEvent(X11Event,GetMagickModule(),
5294 " significant bits in color: %d bits",
5295 windows->visual_info->bits_per_rgb);
5296 }
5297 /*
5298 Allocate class and manager hints.
5299 */
5300 windows->class_hints=XAllocClassHint();
5301 windows->manager_hints=XAllocWMHints();
5302 if ((windows->class_hints == (XClassHint *) NULL) ||
5303 (windows->manager_hints == (XWMHints *) NULL))
5304 ThrowXWindowFatalException(ResourceLimitFatalError,
5305 "MemoryAllocationFailed","...");
5306 /*
5307 Determine group leader if we have one.
5308 */
5309 root_window=XRootWindow(display,windows->visual_info->screen);
5310 windows->group_leader.id=(Window) NULL;
5311 if (resource_info->window_group != (char *) NULL)
5312 {
5313 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5314 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5315 strtol((char *) resource_info->window_group,(char **) NULL,0));
5316 if (windows->group_leader.id == (Window) NULL)
5317 windows->group_leader.id=
5318 XWindowByName(display,root_window,resource_info->window_group);
5319 }
5320 return(windows);
5321}
5322
5323/*
5324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5325% %
5326% %
5327% %
5328% X M a k e C u r s o r %
5329% %
5330% %
5331% %
5332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5333%
5334% XMakeCursor() creates a crosshairs X11 cursor.
5335%
5336% The format of the XMakeCursor method is:
5337%
5338% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5339% char *background_color,char *foreground_color)
5340%
5341% A description of each parameter follows:
5342%
5343% o display: Specifies a connection to an X server; returned from
5344% XOpenDisplay.
5345%
5346% o window: Specifies the ID of the window for which the cursor is
5347% assigned.
5348%
5349% o colormap: Specifies the ID of the colormap from which the background
5350% and foreground color will be retrieved.
5351%
5352% o background_color: Specifies the color to use for the cursor background.
5353%
5354% o foreground_color: Specifies the color to use for the cursor foreground.
5355%
5356*/
cristybcbda3f2011-09-03 13:01:22 +00005357MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005358 Colormap colormap,char *background_color,char *foreground_color)
5359{
5360#define scope_height 17
5361#define scope_x_hot 8
5362#define scope_y_hot 8
5363#define scope_width 17
5364
5365 static const unsigned char
5366 scope_bits[] =
5367 {
5368 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5369 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5370 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5371 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5372 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5373 },
5374 scope_mask_bits[] =
5375 {
5376 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5377 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5378 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5379 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5380 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5381 };
5382
5383 Cursor
5384 cursor;
5385
5386 Pixmap
5387 mask,
5388 source;
5389
5390 XColor
5391 background,
5392 foreground;
5393
5394 assert(display != (Display *) NULL);
5395 assert(window != (Window) NULL);
5396 assert(colormap != (Colormap) NULL);
5397 assert(background_color != (char *) NULL);
5398 assert(foreground_color != (char *) NULL);
5399 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5400 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5401 scope_height);
5402 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5403 scope_width,scope_height);
5404 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5405 {
5406 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5407 return((Cursor) NULL);
5408 }
5409 (void) XParseColor(display,colormap,background_color,&background);
5410 (void) XParseColor(display,colormap,foreground_color,&foreground);
5411 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5412 scope_x_hot,scope_y_hot);
5413 (void) XFreePixmap(display,source);
5414 (void) XFreePixmap(display,mask);
5415 return(cursor);
5416}
5417
5418/*
5419%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5420% %
5421% %
5422% %
5423% X M a k e I m a g e %
5424% %
5425% %
5426% %
5427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5428%
5429% XMakeImage() creates an X11 image. If the image size differs from the X11
5430% image size, the image is first resized.
5431%
5432% The format of the XMakeImage method is:
5433%
5434% MagickBooleanType XMakeImage(Display *display,
5435% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005436% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005437%
5438% A description of each parameter follows:
5439%
5440% o display: Specifies a connection to an X server; returned from
5441% XOpenDisplay.
5442%
5443% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5444%
5445% o window: Specifies a pointer to a XWindowInfo structure.
5446%
5447% o image: the image.
5448%
5449% o width: Specifies the width in pixels of the rectangular area to
5450% display.
5451%
5452% o height: Specifies the height in pixels of the rectangular area to
5453% display.
5454%
cristy051718b2011-08-28 22:49:25 +00005455% o exception: return any errors or warnings in this structure.
5456%
cristy3ed852e2009-09-05 21:47:34 +00005457*/
cristybcbda3f2011-09-03 13:01:22 +00005458MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005459 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005460 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005461{
5462#define CheckOverflowException(length,width,height) \
5463 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5464
5465 int
5466 depth,
5467 format;
5468
5469 size_t
5470 length;
5471
5472 XImage
5473 *matte_image,
5474 *ximage;
5475
5476 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5477 assert(display != (Display *) NULL);
5478 assert(resource_info != (XResourceInfo *) NULL);
5479 assert(window != (XWindowInfo *) NULL);
5480 assert(width != 0);
5481 assert(height != 0);
5482 if ((window->width == 0) || (window->height == 0))
5483 return(MagickFalse);
5484 /*
5485 Apply user transforms to the image.
5486 */
5487 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5488 (void) XFlush(display);
5489 depth=(int) window->depth;
5490 if (window->destroy)
5491 window->image=DestroyImage(window->image);
5492 window->image=image;
5493 window->destroy=MagickFalse;
5494 if (window->image != (Image *) NULL)
5495 {
5496 if (window->crop_geometry != (char *) NULL)
5497 {
5498 Image
5499 *crop_image;
5500
5501 RectangleInfo
5502 crop_info;
5503
5504 /*
5505 Crop image.
5506 */
5507 window->image->page.x=0;
5508 window->image->page.y=0;
5509 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005510 &crop_info,exception);
5511 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005512 if (crop_image != (Image *) NULL)
5513 {
5514 if (window->image != image)
5515 window->image=DestroyImage(window->image);
5516 window->image=crop_image;
5517 window->destroy=MagickTrue;
5518 }
5519 }
5520 if ((width != (unsigned int) window->image->columns) ||
5521 (height != (unsigned int) window->image->rows))
5522 {
5523 Image
5524 *resize_image;
5525
5526 /*
5527 Resize image.
5528 */
5529 resize_image=NewImageList();
5530 if (window->pixel_info->colors != 0)
cristy6710d842011-10-20 23:23:00 +00005531 resize_image=SampleImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005532 else
cristy6710d842011-10-20 23:23:00 +00005533 resize_image=ThumbnailImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005534 if (resize_image != (Image *) NULL)
5535 {
5536 if (window->image != image)
5537 window->image=DestroyImage(window->image);
5538 window->image=resize_image;
5539 window->destroy=MagickTrue;
5540 }
5541 }
5542 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005543 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005544 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005545 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005546 }
5547 /*
5548 Create X image.
5549 */
5550 ximage=(XImage *) NULL;
5551 format=(depth == 1) ? XYBitmap : ZPixmap;
5552#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5553 if (window->shared_memory != MagickFalse)
5554 {
5555 XShmSegmentInfo
5556 *segment_info;
5557
5558 segment_info=(XShmSegmentInfo *) window->segment_info;
5559 segment_info[1].shmid=(-1);
5560 segment_info[1].shmaddr=(char *) NULL;
5561 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5562 (char *) NULL,&segment_info[1],width,height);
5563 if (ximage == (XImage *) NULL)
5564 window->shared_memory=MagickFalse;
5565 length=(size_t) ximage->bytes_per_line*ximage->height;
5566 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5567 window->shared_memory=MagickFalse;
5568 if (window->shared_memory != MagickFalse)
5569 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5570 if (window->shared_memory != MagickFalse)
5571 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5572 if (segment_info[1].shmid < 0)
5573 window->shared_memory=MagickFalse;
5574 if (window->shared_memory != MagickFalse)
5575 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5576 else
5577 {
5578 if (ximage != (XImage *) NULL)
5579 XDestroyImage(ximage);
5580 ximage=(XImage *) NULL;
5581 if (segment_info[1].shmaddr)
5582 {
5583 (void) shmdt(segment_info[1].shmaddr);
5584 segment_info[1].shmaddr=(char *) NULL;
5585 }
5586 if (segment_info[1].shmid >= 0)
5587 {
5588 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5589 segment_info[1].shmid=(-1);
5590 }
5591 }
5592 }
5593#endif
5594 /*
5595 Allocate X image pixel data.
5596 */
5597#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5598 if (window->shared_memory)
5599 {
5600 Status
5601 status;
5602
5603 XShmSegmentInfo
5604 *segment_info;
5605
5606 (void) XSync(display,MagickFalse);
5607 xerror_alert=MagickFalse;
5608 segment_info=(XShmSegmentInfo *) window->segment_info;
5609 ximage->data=segment_info[1].shmaddr;
5610 segment_info[1].readOnly=MagickFalse;
5611 status=XShmAttach(display,&segment_info[1]);
5612 if (status != False)
5613 (void) XSync(display,MagickFalse);
5614 if ((status == False) || (xerror_alert != MagickFalse))
5615 {
5616 window->shared_memory=MagickFalse;
5617 if (status != False)
5618 XShmDetach(display,&segment_info[1]);
5619 if (ximage != (XImage *) NULL)
5620 {
5621 ximage->data=NULL;
5622 XDestroyImage(ximage);
5623 ximage=(XImage *) NULL;
5624 }
5625 if (segment_info[1].shmid >= 0)
5626 {
5627 if (segment_info[1].shmaddr != NULL)
5628 (void) shmdt(segment_info[1].shmaddr);
5629 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5630 segment_info[1].shmid=(-1);
5631 segment_info[1].shmaddr=(char *) NULL;
5632 }
5633 }
5634 }
5635#endif
5636 if (window->shared_memory == MagickFalse)
5637 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5638 (char *) NULL,width,height,XBitmapPad(display),0);
5639 if (ximage == (XImage *) NULL)
5640 {
5641 /*
5642 Unable to create X image.
5643 */
5644 (void) XCheckDefineCursor(display,window->id,window->cursor);
5645 return(MagickFalse);
5646 }
5647 length=(size_t) ximage->bytes_per_line*ximage->height;
5648 if (IsEventLogging())
5649 {
5650 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5651 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5652 ximage->width,ximage->height);
5653 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5654 ximage->format);
5655 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5656 ximage->byte_order);
5657 (void) LogMagickEvent(X11Event,GetMagickModule(),
5658 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5659 ximage->bitmap_bit_order,ximage->bitmap_pad);
5660 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5661 ximage->depth);
5662 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5663 ximage->bytes_per_line);
5664 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5665 ximage->bits_per_pixel);
5666 (void) LogMagickEvent(X11Event,GetMagickModule(),
5667 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5668 ximage->green_mask,ximage->blue_mask);
5669 }
5670 if (window->shared_memory == MagickFalse)
5671 {
5672 if (ximage->format != XYBitmap)
5673 ximage->data=(char *) AcquireQuantumMemory((size_t)
5674 ximage->bytes_per_line,(size_t) ximage->height);
5675 else
5676 ximage->data=(char *) AcquireQuantumMemory((size_t)
5677 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5678 }
5679 if (ximage->data == (char *) NULL)
5680 {
5681 /*
5682 Unable to allocate pixel data.
5683 */
5684 XDestroyImage(ximage);
5685 ximage=(XImage *) NULL;
5686 (void) XCheckDefineCursor(display,window->id,window->cursor);
5687 return(MagickFalse);
5688 }
5689 if (window->ximage != (XImage *) NULL)
5690 {
5691 /*
5692 Destroy previous X image.
5693 */
5694 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5695#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5696 if (window->segment_info != (XShmSegmentInfo *) NULL)
5697 {
5698 XShmSegmentInfo
5699 *segment_info;
5700
5701 segment_info=(XShmSegmentInfo *) window->segment_info;
5702 if (segment_info[0].shmid >= 0)
5703 {
5704 (void) XSync(display,MagickFalse);
5705 (void) XShmDetach(display,&segment_info[0]);
5706 (void) XSync(display,MagickFalse);
5707 if (segment_info[0].shmaddr != (char *) NULL)
5708 (void) shmdt(segment_info[0].shmaddr);
5709 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5710 segment_info[0].shmid=(-1);
5711 segment_info[0].shmaddr=(char *) NULL;
5712 window->ximage->data=(char *) NULL;
5713 }
5714 }
5715#endif
5716 if (window->ximage->data != (char *) NULL)
5717 free(window->ximage->data);
5718 window->ximage->data=(char *) NULL;
5719 XDestroyImage(window->ximage);
5720 window->ximage=(XImage *) NULL;
5721 }
5722#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5723 if (window->segment_info != (XShmSegmentInfo *) NULL)
5724 {
5725 XShmSegmentInfo
5726 *segment_info;
5727
5728 segment_info=(XShmSegmentInfo *) window->segment_info;
5729 segment_info[0]=segment_info[1];
5730 }
5731#endif
5732 window->ximage=ximage;
5733 matte_image=(XImage *) NULL;
5734 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
cristy8a46d822012-08-28 23:32:39 +00005735 if ((window->image->alpha_trait == BlendPixelTrait) &&
cristyc57f6942010-11-12 01:47:39 +00005736 ((int) width <= XDisplayWidth(display,window->screen)) &&
5737 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005738 {
5739 /*
5740 Create matte image.
5741 */
5742 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5743 (char *) NULL,width,height,XBitmapPad(display),0);
5744 if (IsEventLogging())
5745 {
5746 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5747 (void) LogMagickEvent(X11Event,GetMagickModule(),
5748 " width, height: %dx%d",matte_image->width,matte_image->height);
5749 }
5750 if (matte_image != (XImage *) NULL)
5751 {
5752 /*
5753 Allocate matte image pixel data.
5754 */
5755 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5756 matte_image->bytes_per_line*matte_image->depth,
5757 (size_t) matte_image->height);
5758 if (matte_image->data == (char *) NULL)
5759 {
5760 XDestroyImage(matte_image);
5761 matte_image=(XImage *) NULL;
5762 }
5763 }
5764 }
5765 if (window->matte_image != (XImage *) NULL)
5766 {
5767 /*
5768 Free matte image.
5769 */
5770 if (window->matte_image->data != (char *) NULL)
5771 free(window->matte_image->data);
5772 window->matte_image->data=(char *) NULL;
5773 XDestroyImage(window->matte_image);
5774 window->matte_image=(XImage *) NULL;
5775 }
5776 window->matte_image=matte_image;
5777 if (window->matte_pixmap != (Pixmap) NULL)
5778 {
5779 (void) XFreePixmap(display,window->matte_pixmap);
5780 window->matte_pixmap=(Pixmap) NULL;
5781#if defined(MAGICKCORE_HAVE_SHAPE)
5782 if (window->shape != MagickFalse)
5783 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5784#endif
5785 }
5786 window->stasis=MagickFalse;
5787 /*
5788 Convert pixels to X image data.
5789 */
5790 if (window->image != (Image *) NULL)
5791 {
5792 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5793 (ximage->bitmap_bit_order == LSBFirst)))
5794 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005795 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005796 else
5797 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005798 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005799 }
5800 if (window->matte_image != (XImage *) NULL)
5801 {
5802 /*
5803 Create matte pixmap.
5804 */
5805 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5806 if (window->matte_pixmap != (Pixmap) NULL)
5807 {
5808 GC
5809 graphics_context;
5810
5811 XGCValues
5812 context_values;
5813
5814 /*
5815 Copy matte image to matte pixmap.
5816 */
cristy4c08aed2011-07-01 19:47:50 +00005817 context_values.background=0;
5818 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005819 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005820 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005821 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5822 window->matte_image,0,0,0,0,width,height);
5823 (void) XFreeGC(display,graphics_context);
5824#if defined(MAGICKCORE_HAVE_SHAPE)
5825 if (window->shape != MagickFalse)
5826 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5827 window->matte_pixmap,ShapeSet);
5828#endif
5829 }
5830 }
5831 (void) XMakePixmap(display,resource_info,window);
5832 /*
5833 Restore cursor.
5834 */
5835 (void) XCheckDefineCursor(display,window->id,window->cursor);
5836 return(MagickTrue);
5837}
5838
5839/*
5840%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5841% %
5842% %
5843% %
5844+ X M a k e I m a g e L S B F i r s t %
5845% %
5846% %
5847% %
5848%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5849%
5850% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5851% pixels are copied in least-significant bit and byte first order. The
5852% server's scanline pad is respected. Rather than using one or two general
5853% cases, many special cases are found here to help speed up the image
5854% conversion.
5855%
5856% The format of the XMakeImageLSBFirst method is:
5857%
cristye941a752011-10-15 01:52:48 +00005858% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5859% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005860%
5861% A description of each parameter follows:
5862%
5863% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5864%
5865% o window: Specifies a pointer to a XWindowInfo structure.
5866%
5867% o image: the image.
5868%
5869% o ximage: Specifies a pointer to a XImage structure; returned from
5870% XCreateImage.
5871%
5872% o matte_image: Specifies a pointer to a XImage structure; returned from
5873% XCreateImage.
5874%
cristye941a752011-10-15 01:52:48 +00005875% o exception: return any errors or warnings in this structure.
5876%
cristy3ed852e2009-09-05 21:47:34 +00005877*/
5878static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005879 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5880 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005881{
cristyc57f6942010-11-12 01:47:39 +00005882 CacheView
5883 *canvas_view;
5884
cristy3ed852e2009-09-05 21:47:34 +00005885 Image
5886 *canvas;
5887
5888 int
5889 y;
5890
cristy4c08aed2011-07-01 19:47:50 +00005891 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005892 *p;
5893
5894 register int
5895 x;
5896
5897 register unsigned char
5898 *q;
5899
5900 unsigned char
5901 bit,
5902 byte;
5903
5904 unsigned int
5905 scanline_pad;
5906
cristyf2faecf2010-05-28 19:19:36 +00005907 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005908 pixel,
5909 *pixels;
5910
5911 XStandardColormap
5912 *map_info;
5913
5914 assert(resource_info != (XResourceInfo *) NULL);
5915 assert(window != (XWindowInfo *) NULL);
5916 assert(image != (Image *) NULL);
5917 if (image->debug != MagickFalse)
5918 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5919 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005920 if ((window->immutable == MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00005921 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00005922 {
5923 char
5924 size[MaxTextExtent];
5925
5926 Image
5927 *pattern;
5928
5929 ImageInfo
5930 *image_info;
5931
5932 image_info=AcquireImageInfo();
5933 (void) CopyMagickString(image_info->filename,
5934 resource_info->image_info->texture != (char *) NULL ?
5935 resource_info->image_info->texture : "pattern:checkerboard",
5936 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005937 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005938 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005939 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005940 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005941 image_info=DestroyImageInfo(image_info);
5942 if (pattern != (Image *) NULL)
5943 {
cristy6710d842011-10-20 23:23:00 +00005944 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005945 if (canvas != (Image *) NULL)
cristy39172402012-03-30 13:04:39 +00005946 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
cristyfeb3e962012-03-29 17:25:55 +00005947 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00005948 pattern=DestroyImage(pattern);
5949 }
5950 }
5951 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5952 ximage->bits_per_pixel) >> 3));
5953 map_info=window->map_info;
5954 pixels=window->pixel_info->pixels;
5955 q=(unsigned char *) ximage->data;
5956 x=0;
cristydb070952012-04-20 14:33:00 +00005957 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00005958 if (ximage->format == XYBitmap)
5959 {
5960 register unsigned short
5961 polarity;
5962
5963 unsigned char
5964 background,
5965 foreground;
5966
5967 /*
5968 Convert canvas to big-endian bitmap.
5969 */
5970 background=(unsigned char)
5971 (XPixelIntensity(&window->pixel_info->foreground_color) <
5972 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5973 foreground=(unsigned char)
5974 (XPixelIntensity(&window->pixel_info->background_color) <
5975 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005976 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00005977 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00005978 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005979 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5980 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005981 for (y=0; y < (int) canvas->rows; y++)
5982 {
cristyc57f6942010-11-12 01:47:39 +00005983 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005984 exception);
cristy4c08aed2011-07-01 19:47:50 +00005985 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005986 break;
cristy3ed852e2009-09-05 21:47:34 +00005987 bit=0;
5988 byte=0;
5989 for (x=0; x < (int) canvas->columns; x++)
5990 {
5991 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005992 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005993 byte|=foreground;
5994 else
5995 byte|=background;
5996 bit++;
5997 if (bit == 8)
5998 {
5999 *q++=byte;
6000 bit=0;
6001 byte=0;
6002 }
cristyed231572011-07-14 02:18:59 +00006003 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006004 }
6005 if (bit != 0)
6006 *q=byte >> (8-bit);
6007 q+=scanline_pad;
6008 }
6009 }
6010 else
6011 if (window->pixel_info->colors != 0)
6012 switch (ximage->bits_per_pixel)
6013 {
6014 case 2:
6015 {
6016 register unsigned int
6017 nibble;
6018
6019 /*
6020 Convert to 2 bit color-mapped X canvas.
6021 */
6022 for (y=0; y < (int) canvas->rows; y++)
6023 {
cristyc57f6942010-11-12 01:47:39 +00006024 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006025 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006026 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006027 break;
cristy3ed852e2009-09-05 21:47:34 +00006028 nibble=0;
6029 for (x=0; x < (int) canvas->columns; x++)
6030 {
cristy4c08aed2011-07-01 19:47:50 +00006031 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006032 switch (nibble)
6033 {
6034 case 0:
6035 {
6036 *q=(unsigned char) pixel;
6037 nibble++;
6038 break;
6039 }
6040 case 1:
6041 {
6042 *q|=(unsigned char) (pixel << 2);
6043 nibble++;
6044 break;
6045 }
6046 case 2:
6047 {
6048 *q|=(unsigned char) (pixel << 4);
6049 nibble++;
6050 break;
6051 }
6052 case 3:
6053 {
6054 *q|=(unsigned char) (pixel << 6);
6055 q++;
6056 nibble=0;
6057 break;
6058 }
6059 }
cristyed231572011-07-14 02:18:59 +00006060 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006061 }
6062 q+=scanline_pad;
6063 }
6064 break;
6065 }
6066 case 4:
6067 {
6068 register unsigned int
6069 nibble;
6070
6071 /*
6072 Convert to 4 bit color-mapped X canvas.
6073 */
6074 for (y=0; y < (int) canvas->rows; y++)
6075 {
cristyc57f6942010-11-12 01:47:39 +00006076 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006077 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006078 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006079 break;
cristy3ed852e2009-09-05 21:47:34 +00006080 nibble=0;
6081 for (x=0; x < (int) canvas->columns; x++)
6082 {
cristy4c08aed2011-07-01 19:47:50 +00006083 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006084 switch (nibble)
6085 {
6086 case 0:
6087 {
6088 *q=(unsigned char) pixel;
6089 nibble++;
6090 break;
6091 }
6092 case 1:
6093 {
6094 *q|=(unsigned char) (pixel << 4);
6095 q++;
6096 nibble=0;
6097 break;
6098 }
6099 }
cristyed231572011-07-14 02:18:59 +00006100 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006101 }
6102 q+=scanline_pad;
6103 }
6104 break;
6105 }
6106 case 6:
6107 case 8:
6108 {
6109 /*
6110 Convert to 8 bit color-mapped X canvas.
6111 */
6112 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006113 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006114 {
cristy6710d842011-10-20 23:23:00 +00006115 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006116 break;
6117 }
6118 for (y=0; y < (int) canvas->rows; y++)
6119 {
cristyc57f6942010-11-12 01:47:39 +00006120 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006121 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006122 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006123 break;
cristy3ed852e2009-09-05 21:47:34 +00006124 for (x=0; x < (int) canvas->columns; x++)
6125 {
cristy4c08aed2011-07-01 19:47:50 +00006126 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006127 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006128 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006129 }
6130 q+=scanline_pad;
6131 }
6132 break;
6133 }
6134 default:
6135 {
6136 register int
6137 k;
6138
6139 register unsigned int
6140 bytes_per_pixel;
6141
6142 unsigned char
cristybb503372010-05-27 20:51:26 +00006143 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006144
6145 /*
6146 Convert to multi-byte color-mapped X canvas.
6147 */
6148 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6149 for (y=0; y < (int) canvas->rows; y++)
6150 {
cristyc57f6942010-11-12 01:47:39 +00006151 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006152 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006153 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006154 break;
cristy3ed852e2009-09-05 21:47:34 +00006155 for (x=0; x < (int) canvas->columns; x++)
6156 {
cristy4c08aed2011-07-01 19:47:50 +00006157 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006158 for (k=0; k < (int) bytes_per_pixel; k++)
6159 {
6160 channel[k]=(unsigned char) pixel;
6161 pixel>>=8;
6162 }
6163 for (k=0; k < (int) bytes_per_pixel; k++)
6164 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006165 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006166 }
6167 q+=scanline_pad;
6168 }
6169 break;
6170 }
6171 }
6172 else
6173 switch (ximage->bits_per_pixel)
6174 {
6175 case 2:
6176 {
6177 register unsigned int
6178 nibble;
6179
6180 /*
6181 Convert to contiguous 2 bit continuous-tone X canvas.
6182 */
6183 for (y=0; y < (int) canvas->rows; y++)
6184 {
6185 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006186 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006187 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006188 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006189 break;
6190 for (x=0; x < (int) canvas->columns; x++)
6191 {
cristy4c08aed2011-07-01 19:47:50 +00006192 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006193 pixel&=0xf;
6194 switch (nibble)
6195 {
6196 case 0:
6197 {
6198 *q=(unsigned char) pixel;
6199 nibble++;
6200 break;
6201 }
6202 case 1:
6203 {
6204 *q|=(unsigned char) (pixel << 2);
6205 nibble++;
6206 break;
6207 }
6208 case 2:
6209 {
6210 *q|=(unsigned char) (pixel << 4);
6211 nibble++;
6212 break;
6213 }
6214 case 3:
6215 {
6216 *q|=(unsigned char) (pixel << 6);
6217 q++;
6218 nibble=0;
6219 break;
6220 }
6221 }
cristyed231572011-07-14 02:18:59 +00006222 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006223 }
6224 q+=scanline_pad;
6225 }
6226 break;
6227 }
6228 case 4:
6229 {
6230 register unsigned int
6231 nibble;
6232
6233 /*
6234 Convert to contiguous 4 bit continuous-tone X canvas.
6235 */
6236 for (y=0; y < (int) canvas->rows; y++)
6237 {
cristyc57f6942010-11-12 01:47:39 +00006238 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006239 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006240 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006241 break;
6242 nibble=0;
6243 for (x=0; x < (int) canvas->columns; x++)
6244 {
cristy4c08aed2011-07-01 19:47:50 +00006245 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006246 pixel&=0xf;
6247 switch (nibble)
6248 {
6249 case 0:
6250 {
6251 *q=(unsigned char) pixel;
6252 nibble++;
6253 break;
6254 }
6255 case 1:
6256 {
6257 *q|=(unsigned char) (pixel << 4);
6258 q++;
6259 nibble=0;
6260 break;
6261 }
6262 }
cristyed231572011-07-14 02:18:59 +00006263 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006264 }
6265 q+=scanline_pad;
6266 }
6267 break;
6268 }
6269 case 6:
6270 case 8:
6271 {
6272 /*
6273 Convert to contiguous 8 bit continuous-tone X canvas.
6274 */
6275 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006276 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006277 {
cristy6710d842011-10-20 23:23:00 +00006278 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006279 break;
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 for (x=0; x < (int) canvas->columns; x++)
6288 {
cristy4c08aed2011-07-01 19:47:50 +00006289 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006290 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006291 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006292 }
6293 q+=scanline_pad;
6294 }
6295 break;
6296 }
6297 default:
6298 {
6299 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6300 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6301 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6302 (map_info->blue_mult == 1))
6303 {
6304 /*
6305 Convert to 32 bit continuous-tone X canvas.
6306 */
6307 for (y=0; y < (int) canvas->rows; y++)
6308 {
cristyc57f6942010-11-12 01:47:39 +00006309 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006310 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006311 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006312 break;
6313 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6314 (blue_gamma != 1.0))
6315 {
6316 /*
6317 Gamma correct canvas.
6318 */
6319 for (x=(int) canvas->columns-1; x >= 0; x--)
6320 {
cristyccf844f2010-02-03 23:28:16 +00006321 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006322 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006323 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006324 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006325 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006326 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006327 *q++=0;
cristyed231572011-07-14 02:18:59 +00006328 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006329 }
6330 continue;
6331 }
6332 for (x=(int) canvas->columns-1; x >= 0; x--)
6333 {
cristy8bc259b2012-06-21 23:53:15 +00006334 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
6335 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6336 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006337 *q++=0;
cristyed231572011-07-14 02:18:59 +00006338 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006339 }
6340 }
6341 }
6342 else
6343 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6344 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6345 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6346 (map_info->blue_mult == 65536L))
6347 {
6348 /*
6349 Convert to 32 bit continuous-tone X canvas.
6350 */
6351 for (y=0; y < (int) canvas->rows; y++)
6352 {
cristyc57f6942010-11-12 01:47:39 +00006353 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006354 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006355 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006356 break;
6357 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6358 (blue_gamma != 1.0))
6359 {
6360 /*
6361 Gamma correct canvas.
6362 */
6363 for (x=(int) canvas->columns-1; x >= 0; x--)
6364 {
cristyccf844f2010-02-03 23:28:16 +00006365 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006366 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006367 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006368 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006369 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006370 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006371 *q++=0;
cristyed231572011-07-14 02:18:59 +00006372 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006373 }
6374 continue;
6375 }
6376 for (x=(int) canvas->columns-1; x >= 0; x--)
6377 {
cristy8bc259b2012-06-21 23:53:15 +00006378 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6379 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6380 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006381 *q++=0;
cristyed231572011-07-14 02:18:59 +00006382 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006383 }
6384 }
6385 }
6386 else
6387 {
6388 register int
6389 k;
6390
6391 register unsigned int
6392 bytes_per_pixel;
6393
6394 unsigned char
cristybb503372010-05-27 20:51:26 +00006395 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006396
6397 /*
6398 Convert to multi-byte continuous-tone X canvas.
6399 */
6400 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6401 for (y=0; y < (int) canvas->rows; y++)
6402 {
cristyc57f6942010-11-12 01:47:39 +00006403 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006404 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006405 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006406 break;
cristyc57f6942010-11-12 01:47:39 +00006407 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006408 {
cristy4c08aed2011-07-01 19:47:50 +00006409 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006410 for (k=0; k < (int) bytes_per_pixel; k++)
6411 {
6412 channel[k]=(unsigned char) pixel;
6413 pixel>>=8;
6414 }
6415 for (k=0; k < (int) bytes_per_pixel; k++)
6416 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006417 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006418 }
6419 q+=scanline_pad;
6420 }
6421 }
6422 break;
6423 }
6424 }
6425 if (matte_image != (XImage *) NULL)
6426 {
6427 /*
6428 Initialize matte canvas.
6429 */
6430 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6431 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6432 q=(unsigned char *) matte_image->data;
6433 for (y=0; y < (int) canvas->rows; y++)
6434 {
cristyc57f6942010-11-12 01:47:39 +00006435 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006436 exception);
cristy4c08aed2011-07-01 19:47:50 +00006437 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006438 break;
6439 bit=0;
6440 byte=0;
6441 for (x=(int) canvas->columns-1; x >= 0; x--)
6442 {
6443 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006444 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006445 byte|=0x80;
6446 bit++;
6447 if (bit == 8)
6448 {
6449 *q++=byte;
6450 bit=0;
6451 byte=0;
6452 }
cristyed231572011-07-14 02:18:59 +00006453 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006454 }
6455 if (bit != 0)
6456 *q=byte >> (8-bit);
6457 q+=scanline_pad;
6458 }
6459 }
cristyc57f6942010-11-12 01:47:39 +00006460 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006461 if (canvas != image)
6462 canvas=DestroyImage(canvas);
6463}
6464
6465/*
6466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6467% %
6468% %
6469% %
6470+ X M a k e I m a g e M S B F i r s t %
6471% %
6472% %
6473% %
6474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6475%
6476% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6477% image pixels are copied in most-significant bit and byte first order. The
6478% server's scanline pad is also respected. Rather than using one or two
6479% general cases, many special cases are found here to help speed up the image
6480% conversion.
6481%
6482% The format of the XMakeImageMSBFirst method is:
6483%
cristye941a752011-10-15 01:52:48 +00006484% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6485% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006486%
6487% A description of each parameter follows:
6488%
6489% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6490%
6491% o window: Specifies a pointer to a XWindowInfo structure.
6492%
6493% o image: the image.
6494%
6495% o ximage: Specifies a pointer to a XImage structure; returned from
6496% XCreateImage.
6497%
6498% o matte_image: Specifies a pointer to a XImage structure; returned from
6499% XCreateImage.
6500%
cristye941a752011-10-15 01:52:48 +00006501% o exception: return any errors or warnings in this structure.
6502%
cristy3ed852e2009-09-05 21:47:34 +00006503*/
6504static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006505 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6506 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006507{
cristyc57f6942010-11-12 01:47:39 +00006508 CacheView
6509 *canvas_view;
6510
cristy3ed852e2009-09-05 21:47:34 +00006511 Image
6512 *canvas;
6513
6514 int
6515 y;
6516
6517 register int
6518 x;
6519
cristy4c08aed2011-07-01 19:47:50 +00006520 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006521 *p;
6522
6523 register unsigned char
6524 *q;
6525
6526 unsigned char
6527 bit,
6528 byte;
6529
6530 unsigned int
6531 scanline_pad;
6532
cristyf2faecf2010-05-28 19:19:36 +00006533 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006534 pixel,
6535 *pixels;
6536
6537 XStandardColormap
6538 *map_info;
6539
6540 assert(resource_info != (XResourceInfo *) NULL);
6541 assert(window != (XWindowInfo *) NULL);
6542 assert(image != (Image *) NULL);
6543 if (image->debug != MagickFalse)
6544 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6545 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006546 if ((window->immutable != MagickFalse) &&
cristy8a46d822012-08-28 23:32:39 +00006547 (image->storage_class == DirectClass) && (image->alpha_trait == BlendPixelTrait))
cristy3ed852e2009-09-05 21:47:34 +00006548 {
6549 char
6550 size[MaxTextExtent];
6551
6552 Image
6553 *pattern;
6554
6555 ImageInfo
6556 *image_info;
6557
6558 image_info=AcquireImageInfo();
6559 (void) CopyMagickString(image_info->filename,
6560 resource_info->image_info->texture != (char *) NULL ?
6561 resource_info->image_info->texture : "pattern:checkerboard",
6562 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006563 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006564 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006565 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006566 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006567 image_info=DestroyImageInfo(image_info);
6568 if (pattern != (Image *) NULL)
6569 {
cristy6710d842011-10-20 23:23:00 +00006570 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006571 if (canvas != (Image *) NULL)
cristyfeb3e962012-03-29 17:25:55 +00006572 (void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
6573 0,0,exception);
cristy3ed852e2009-09-05 21:47:34 +00006574 pattern=DestroyImage(pattern);
6575 }
6576 }
cristy4c08aed2011-07-01 19:47:50 +00006577 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6578 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006579 map_info=window->map_info;
6580 pixels=window->pixel_info->pixels;
6581 q=(unsigned char *) ximage->data;
6582 x=0;
cristydb070952012-04-20 14:33:00 +00006583 canvas_view=AcquireVirtualCacheView(canvas,exception);
cristy3ed852e2009-09-05 21:47:34 +00006584 if (ximage->format == XYBitmap)
6585 {
6586 register unsigned short
6587 polarity;
6588
6589 unsigned char
6590 background,
6591 foreground;
6592
6593 /*
6594 Convert canvas to big-endian bitmap.
6595 */
6596 background=(unsigned char)
6597 (XPixelIntensity(&window->pixel_info->foreground_color) <
6598 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6599 foreground=(unsigned char)
6600 (XPixelIntensity(&window->pixel_info->background_color) <
6601 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006602 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy6e963d82012-06-19 15:23:24 +00006603 &canvas->colormap[0])) < (QuantumRange/2) ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00006604 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006605 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6606 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006607 for (y=0; y < (int) canvas->rows; y++)
6608 {
cristyc57f6942010-11-12 01:47:39 +00006609 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006610 exception);
cristy4c08aed2011-07-01 19:47:50 +00006611 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006612 break;
cristy3ed852e2009-09-05 21:47:34 +00006613 bit=0;
6614 byte=0;
6615 for (x=(int) canvas->columns-1; x >= 0; x--)
6616 {
6617 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006618 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006619 byte|=foreground;
6620 else
6621 byte|=background;
6622 bit++;
6623 if (bit == 8)
6624 {
6625 *q++=byte;
6626 bit=0;
6627 byte=0;
6628 }
cristyed231572011-07-14 02:18:59 +00006629 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006630 }
6631 if (bit != 0)
6632 *q=byte << (8-bit);
6633 q+=scanline_pad;
6634 }
6635 }
6636 else
6637 if (window->pixel_info->colors != 0)
6638 switch (ximage->bits_per_pixel)
6639 {
6640 case 2:
6641 {
6642 register unsigned int
6643 nibble;
6644
6645 /*
6646 Convert to 2 bit color-mapped X canvas.
6647 */
6648 for (y=0; y < (int) canvas->rows; y++)
6649 {
cristyc57f6942010-11-12 01:47:39 +00006650 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006651 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006652 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006653 break;
cristy3ed852e2009-09-05 21:47:34 +00006654 nibble=0;
6655 for (x=0; x < (int) canvas->columns; x++)
6656 {
cristy4c08aed2011-07-01 19:47:50 +00006657 pixel=pixels[(ssize_t)
6658 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006659 switch (nibble)
6660 {
6661 case 0:
6662 {
6663 *q=(unsigned char) (pixel << 6);
6664 nibble++;
6665 break;
6666 }
6667 case 1:
6668 {
6669 *q|=(unsigned char) (pixel << 4);
6670 nibble++;
6671 break;
6672 }
6673 case 2:
6674 {
6675 *q|=(unsigned char) (pixel << 2);
6676 nibble++;
6677 break;
6678 }
6679 case 3:
6680 {
6681 *q|=(unsigned char) pixel;
6682 q++;
6683 nibble=0;
6684 break;
6685 }
6686 }
cristyed231572011-07-14 02:18:59 +00006687 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006688 }
6689 q+=scanline_pad;
6690 }
6691 break;
6692 }
6693 case 4:
6694 {
6695 register unsigned int
6696 nibble;
6697
6698 /*
6699 Convert to 4 bit color-mapped X canvas.
6700 */
6701 for (y=0; y < (int) canvas->rows; y++)
6702 {
cristyc57f6942010-11-12 01:47:39 +00006703 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006704 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006705 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006706 break;
cristy3ed852e2009-09-05 21:47:34 +00006707 nibble=0;
6708 for (x=0; x < (int) canvas->columns; x++)
6709 {
cristy4c08aed2011-07-01 19:47:50 +00006710 pixel=pixels[(ssize_t)
6711 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006712 switch (nibble)
6713 {
6714 case 0:
6715 {
6716 *q=(unsigned char) (pixel << 4);
6717 nibble++;
6718 break;
6719 }
6720 case 1:
6721 {
6722 *q|=(unsigned char) pixel;
6723 q++;
6724 nibble=0;
6725 break;
6726 }
6727 }
cristyed231572011-07-14 02:18:59 +00006728 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006729 }
6730 q+=scanline_pad;
6731 }
6732 break;
6733 }
6734 case 6:
6735 case 8:
6736 {
6737 /*
6738 Convert to 8 bit color-mapped X canvas.
6739 */
6740 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006741 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006742 {
cristy6710d842011-10-20 23:23:00 +00006743 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006744 break;
6745 }
6746 for (y=0; y < (int) canvas->rows; y++)
6747 {
cristyc57f6942010-11-12 01:47:39 +00006748 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006749 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006750 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006751 break;
cristy3ed852e2009-09-05 21:47:34 +00006752 for (x=0; x < (int) canvas->columns; x++)
6753 {
cristy6710d842011-10-20 23:23:00 +00006754 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006755 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006756 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006757 }
6758 q+=scanline_pad;
6759 }
6760 break;
6761 }
6762 default:
6763 {
6764 register int
6765 k;
6766
6767 register unsigned int
6768 bytes_per_pixel;
6769
6770 unsigned char
cristybb503372010-05-27 20:51:26 +00006771 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006772
6773 /*
6774 Convert to 8 bit color-mapped X canvas.
6775 */
6776 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6777 for (y=0; y < (int) canvas->rows; y++)
6778 {
cristyc57f6942010-11-12 01:47:39 +00006779 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006780 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006781 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006782 break;
cristy3ed852e2009-09-05 21:47:34 +00006783 for (x=0; x < (int) canvas->columns; x++)
6784 {
cristy4c08aed2011-07-01 19:47:50 +00006785 pixel=pixels[(ssize_t)
6786 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006787 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6788 {
6789 channel[k]=(unsigned char) pixel;
6790 pixel>>=8;
6791 }
6792 for (k=0; k < (int) bytes_per_pixel; k++)
6793 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006794 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006795 }
6796 q+=scanline_pad;
6797 }
6798 break;
6799 }
6800 }
6801 else
6802 switch (ximage->bits_per_pixel)
6803 {
6804 case 2:
6805 {
6806 register unsigned int
6807 nibble;
6808
6809 /*
6810 Convert to 4 bit continuous-tone X canvas.
6811 */
6812 for (y=0; y < (int) canvas->rows; y++)
6813 {
cristyc57f6942010-11-12 01:47:39 +00006814 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006815 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006816 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006817 break;
6818 nibble=0;
6819 for (x=(int) canvas->columns-1; x >= 0; x--)
6820 {
cristy4c08aed2011-07-01 19:47:50 +00006821 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006822 pixel&=0xf;
6823 switch (nibble)
6824 {
6825 case 0:
6826 {
6827 *q=(unsigned char) (pixel << 6);
6828 nibble++;
6829 break;
6830 }
6831 case 1:
6832 {
6833 *q|=(unsigned char) (pixel << 4);
6834 nibble++;
6835 break;
6836 }
6837 case 2:
6838 {
6839 *q|=(unsigned char) (pixel << 2);
6840 nibble++;
6841 break;
6842 }
6843 case 3:
6844 {
6845 *q|=(unsigned char) pixel;
6846 q++;
6847 nibble=0;
6848 break;
6849 }
6850 }
cristyed231572011-07-14 02:18:59 +00006851 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006852 }
6853 q+=scanline_pad;
6854 }
6855 break;
6856 }
6857 case 4:
6858 {
6859 register unsigned int
6860 nibble;
6861
6862 /*
6863 Convert to 4 bit continuous-tone X canvas.
6864 */
6865 for (y=0; y < (int) canvas->rows; y++)
6866 {
cristyc57f6942010-11-12 01:47:39 +00006867 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006868 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006869 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006870 break;
6871 nibble=0;
6872 for (x=(int) canvas->columns-1; x >= 0; x--)
6873 {
cristy4c08aed2011-07-01 19:47:50 +00006874 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006875 pixel&=0xf;
6876 switch (nibble)
6877 {
6878 case 0:
6879 {
6880 *q=(unsigned char) (pixel << 4);
6881 nibble++;
6882 break;
6883 }
6884 case 1:
6885 {
6886 *q|=(unsigned char) pixel;
6887 q++;
6888 nibble=0;
6889 break;
6890 }
6891 }
cristyed231572011-07-14 02:18:59 +00006892 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006893 }
6894 q+=scanline_pad;
6895 }
6896 break;
6897 }
6898 case 6:
6899 case 8:
6900 {
6901 /*
6902 Convert to 8 bit continuous-tone X canvas.
6903 */
6904 if (resource_info->color_recovery &&
cristycbda6112012-05-27 20:57:16 +00006905 resource_info->quantize_info->dither_method != NoDitherMethod)
cristy3ed852e2009-09-05 21:47:34 +00006906 {
cristy6710d842011-10-20 23:23:00 +00006907 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006908 break;
6909 }
6910 for (y=0; y < (int) canvas->rows; y++)
6911 {
cristyc57f6942010-11-12 01:47:39 +00006912 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006913 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006914 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006915 break;
6916 for (x=(int) canvas->columns-1; x >= 0; x--)
6917 {
cristy4c08aed2011-07-01 19:47:50 +00006918 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006919 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006920 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006921 }
6922 q+=scanline_pad;
6923 }
6924 break;
6925 }
6926 default:
6927 {
6928 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6929 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6930 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6931 (map_info->blue_mult == 1))
6932 {
6933 /*
6934 Convert to 32 bit continuous-tone X canvas.
6935 */
6936 for (y=0; y < (int) canvas->rows; y++)
6937 {
cristyc57f6942010-11-12 01:47:39 +00006938 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006939 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006940 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006941 break;
6942 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6943 (blue_gamma != 1.0))
6944 {
6945 /*
6946 Gamma correct canvas.
6947 */
6948 for (x=(int) canvas->columns-1; x >= 0; x--)
6949 {
6950 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006951 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006952 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006953 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006954 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006955 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006956 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006957 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006958 }
6959 continue;
6960 }
6961 for (x=(int) canvas->columns-1; x >= 0; x--)
6962 {
6963 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00006964 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
6965 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
6966 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006967 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006968 }
6969 }
6970 }
6971 else
6972 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6973 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6974 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6975 (map_info->blue_mult == 65536L))
6976 {
6977 /*
6978 Convert to 32 bit continuous-tone X canvas.
6979 */
6980 for (y=0; y < (int) canvas->rows; y++)
6981 {
cristyc57f6942010-11-12 01:47:39 +00006982 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006983 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006984 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006985 break;
6986 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6987 (blue_gamma != 1.0))
6988 {
6989 /*
6990 Gamma correct canvas.
6991 */
6992 for (x=(int) canvas->columns-1; x >= 0; x--)
6993 {
6994 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006995 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006996 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006997 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006998 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006999 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00007000 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00007001 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007002 }
7003 continue;
7004 }
7005 for (x=(int) canvas->columns-1; x >= 0; x--)
7006 {
7007 *q++=0;
cristy8bc259b2012-06-21 23:53:15 +00007008 *q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
7009 *q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
7010 *q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00007011 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007012 }
7013 }
7014 }
7015 else
7016 {
7017 register int
7018 k;
7019
7020 register unsigned int
7021 bytes_per_pixel;
7022
7023 unsigned char
cristybb503372010-05-27 20:51:26 +00007024 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007025
7026 /*
7027 Convert to multi-byte continuous-tone X canvas.
7028 */
7029 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7030 for (y=0; y < (int) canvas->rows; y++)
7031 {
cristyc57f6942010-11-12 01:47:39 +00007032 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007033 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007034 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007035 break;
7036 for (x=(int) canvas->columns-1; x >= 0; x--)
7037 {
cristy4c08aed2011-07-01 19:47:50 +00007038 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007039 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7040 {
7041 channel[k]=(unsigned char) pixel;
7042 pixel>>=8;
7043 }
7044 for (k=0; k < (int) bytes_per_pixel; k++)
7045 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007046 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007047 }
7048 q+=scanline_pad;
7049 }
7050 }
7051 break;
7052 }
7053 }
7054 if (matte_image != (XImage *) NULL)
7055 {
7056 /*
7057 Initialize matte canvas.
7058 */
7059 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7060 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7061 q=(unsigned char *) matte_image->data;
7062 for (y=0; y < (int) canvas->rows; y++)
7063 {
cristyc57f6942010-11-12 01:47:39 +00007064 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007065 exception);
cristy4c08aed2011-07-01 19:47:50 +00007066 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007067 break;
7068 bit=0;
7069 byte=0;
7070 for (x=(int) canvas->columns-1; x >= 0; x--)
7071 {
7072 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007073 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007074 byte|=0x01;
7075 bit++;
7076 if (bit == 8)
7077 {
7078 *q++=byte;
7079 bit=0;
7080 byte=0;
7081 }
cristyed231572011-07-14 02:18:59 +00007082 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007083 }
7084 if (bit != 0)
7085 *q=byte << (8-bit);
7086 q+=scanline_pad;
7087 }
7088 }
cristyc57f6942010-11-12 01:47:39 +00007089 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007090 if (canvas != image)
7091 canvas=DestroyImage(canvas);
7092}
7093
7094/*
7095%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7096% %
7097% %
7098% %
7099% X M a k e M a g n i f y I m a g e %
7100% %
7101% %
7102% %
7103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7104%
7105% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7106%
7107% The format of the XMakeMagnifyImage method is:
7108%
cristy6710d842011-10-20 23:23:00 +00007109% void XMakeMagnifyImage(Display *display,XWindows *windows,
7110% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007111%
7112% A description of each parameter follows:
7113%
7114% o display: Specifies a connection to an X server; returned from
7115% XOpenDisplay.
7116%
7117% o windows: Specifies a pointer to a XWindows structure.
7118%
cristy6710d842011-10-20 23:23:00 +00007119% o exception: return any errors or warnings in this structure.
7120%
cristy3ed852e2009-09-05 21:47:34 +00007121*/
cristy6710d842011-10-20 23:23:00 +00007122MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7123 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007124{
7125 char
7126 tuple[MaxTextExtent];
7127
7128 int
7129 y;
7130
cristy4c08aed2011-07-01 19:47:50 +00007131 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007132 pixel;
7133
7134 register int
7135 x;
7136
cristybb503372010-05-27 20:51:26 +00007137 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007138 i;
7139
7140 register unsigned char
7141 *p,
7142 *q;
7143
cristy9d314ff2011-03-09 01:30:28 +00007144 ssize_t
7145 n;
7146
cristy3ed852e2009-09-05 21:47:34 +00007147 static unsigned int
7148 previous_magnify = 0;
7149
7150 static XWindowInfo
7151 magnify_window;
7152
7153 unsigned int
7154 height,
7155 j,
7156 k,
7157 l,
7158 magnify,
7159 scanline_pad,
7160 width;
7161
7162 XImage
7163 *ximage;
7164
7165 /*
7166 Check boundary conditions.
7167 */
7168 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7169 assert(display != (Display *) NULL);
7170 assert(windows != (XWindows *) NULL);
7171 magnify=1;
cristybb503372010-05-27 20:51:26 +00007172 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007173 magnify<<=1;
7174 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7175 magnify<<=1;
7176 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7177 magnify<<=1;
7178 while (magnify > windows->magnify.width)
7179 magnify>>=1;
7180 while (magnify > windows->magnify.height)
7181 magnify>>=1;
7182 if (magnify != previous_magnify)
7183 {
7184 Status
7185 status;
7186
7187 XTextProperty
7188 window_name;
7189
7190 /*
7191 New magnify factor: update magnify window name.
7192 */
7193 i=0;
7194 while ((1 << i) <= (int) magnify)
7195 i++;
cristyb51dff52011-05-19 16:55:47 +00007196 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007197 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007198 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7199 if (status != False)
7200 {
7201 XSetWMName(display,windows->magnify.id,&window_name);
7202 XSetWMIconName(display,windows->magnify.id,&window_name);
7203 (void) XFree((void *) window_name.value);
7204 }
7205 }
7206 previous_magnify=magnify;
7207 ximage=windows->image.ximage;
7208 width=(unsigned int) windows->magnify.ximage->width;
7209 height=(unsigned int) windows->magnify.ximage->height;
7210 if ((windows->magnify.x < 0) ||
7211 (windows->magnify.x >= windows->image.ximage->width))
7212 windows->magnify.x=windows->image.ximage->width >> 1;
7213 x=windows->magnify.x-((width/magnify) >> 1);
7214 if (x < 0)
7215 x=0;
7216 else
7217 if (x > (int) (ximage->width-(width/magnify)))
7218 x=ximage->width-width/magnify;
7219 if ((windows->magnify.y < 0) ||
7220 (windows->magnify.y >= windows->image.ximage->height))
7221 windows->magnify.y=windows->image.ximage->height >> 1;
7222 y=windows->magnify.y-((height/magnify) >> 1);
7223 if (y < 0)
7224 y=0;
7225 else
7226 if (y > (int) (ximage->height-(height/magnify)))
7227 y=ximage->height-height/magnify;
7228 q=(unsigned char *) windows->magnify.ximage->data;
7229 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7230 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7231 if (ximage->bits_per_pixel < 8)
7232 {
7233 register unsigned char
7234 background,
7235 byte,
7236 foreground,
7237 p_bit,
7238 q_bit;
7239
7240 register unsigned int
7241 plane;
7242
7243 XPixelInfo
7244 *pixel_info;
7245
7246 pixel_info=windows->magnify.pixel_info;
7247 switch (ximage->bitmap_bit_order)
7248 {
7249 case LSBFirst:
7250 {
7251 /*
7252 Magnify little-endian bitmap.
7253 */
7254 background=0x00;
7255 foreground=0x80;
7256 if (ximage->format == XYBitmap)
7257 {
7258 background=(unsigned char)
7259 (XPixelIntensity(&pixel_info->foreground_color) <
7260 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7261 foreground=(unsigned char)
7262 (XPixelIntensity(&pixel_info->background_color) <
7263 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7264 if (windows->magnify.depth > 1)
7265 Swap(background,foreground);
7266 }
cristybb503372010-05-27 20:51:26 +00007267 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007268 {
7269 /*
7270 Propogate pixel magnify rows.
7271 */
7272 for (j=0; j < magnify; j++)
7273 {
7274 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7275 ((x*ximage->bits_per_pixel) >> 3);
7276 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7277 q_bit=0;
7278 byte=0;
7279 for (k=0; k < width; k+=magnify)
7280 {
7281 /*
7282 Propogate pixel magnify columns.
7283 */
7284 for (l=0; l < magnify; l++)
7285 {
7286 /*
7287 Propogate each bit plane.
7288 */
7289 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7290 {
7291 byte>>=1;
7292 if (*p & (0x01 << (p_bit+plane)))
7293 byte|=foreground;
7294 else
7295 byte|=background;
7296 q_bit++;
7297 if (q_bit == 8)
7298 {
7299 *q++=byte;
7300 q_bit=0;
7301 byte=0;
7302 }
7303 }
7304 }
7305 p_bit+=ximage->bits_per_pixel;
7306 if (p_bit == 8)
7307 {
7308 p++;
7309 p_bit=0;
7310 }
7311 if (q_bit != 0)
7312 *q=byte >> (8-q_bit);
7313 q+=scanline_pad;
7314 }
7315 }
7316 y++;
7317 }
7318 break;
7319 }
7320 case MSBFirst:
7321 default:
7322 {
7323 /*
7324 Magnify big-endian bitmap.
7325 */
7326 background=0x00;
7327 foreground=0x01;
7328 if (ximage->format == XYBitmap)
7329 {
7330 background=(unsigned char)
7331 (XPixelIntensity(&pixel_info->foreground_color) <
7332 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7333 foreground=(unsigned char)
7334 (XPixelIntensity(&pixel_info->background_color) <
7335 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7336 if (windows->magnify.depth > 1)
7337 Swap(background,foreground);
7338 }
cristybb503372010-05-27 20:51:26 +00007339 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007340 {
7341 /*
7342 Propogate pixel magnify rows.
7343 */
7344 for (j=0; j < magnify; j++)
7345 {
7346 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7347 ((x*ximage->bits_per_pixel) >> 3);
7348 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7349 q_bit=0;
7350 byte=0;
7351 for (k=0; k < width; k+=magnify)
7352 {
7353 /*
7354 Propogate pixel magnify columns.
7355 */
7356 for (l=0; l < magnify; l++)
7357 {
7358 /*
7359 Propogate each bit plane.
7360 */
7361 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7362 {
7363 byte<<=1;
7364 if (*p & (0x80 >> (p_bit+plane)))
7365 byte|=foreground;
7366 else
7367 byte|=background;
7368 q_bit++;
7369 if (q_bit == 8)
7370 {
7371 *q++=byte;
7372 q_bit=0;
7373 byte=0;
7374 }
7375 }
7376 }
7377 p_bit+=ximage->bits_per_pixel;
7378 if (p_bit == 8)
7379 {
7380 p++;
7381 p_bit=0;
7382 }
7383 if (q_bit != 0)
7384 *q=byte << (8-q_bit);
7385 q+=scanline_pad;
7386 }
7387 }
7388 y++;
7389 }
7390 break;
7391 }
7392 }
7393 }
7394 else
7395 switch (ximage->bits_per_pixel)
7396 {
7397 case 6:
7398 case 8:
7399 {
7400 /*
7401 Magnify 8 bit X image.
7402 */
cristybb503372010-05-27 20:51:26 +00007403 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007404 {
7405 /*
7406 Propogate pixel magnify rows.
7407 */
7408 for (j=0; j < magnify; j++)
7409 {
7410 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7411 ((x*ximage->bits_per_pixel) >> 3);
7412 for (k=0; k < width; k+=magnify)
7413 {
7414 /*
7415 Propogate pixel magnify columns.
7416 */
7417 for (l=0; l < magnify; l++)
7418 *q++=(*p);
7419 p++;
7420 }
7421 q+=scanline_pad;
7422 }
7423 y++;
7424 }
7425 break;
7426 }
7427 default:
7428 {
7429 register unsigned int
7430 bytes_per_pixel,
7431 m;
7432
7433 /*
7434 Magnify multi-byte X image.
7435 */
7436 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007437 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007438 {
7439 /*
7440 Propogate pixel magnify rows.
7441 */
7442 for (j=0; j < magnify; j++)
7443 {
7444 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7445 ((x*ximage->bits_per_pixel) >> 3);
7446 for (k=0; k < width; k+=magnify)
7447 {
7448 /*
7449 Propogate pixel magnify columns.
7450 */
7451 for (l=0; l < magnify; l++)
7452 for (m=0; m < bytes_per_pixel; m++)
7453 *q++=(*(p+m));
7454 p+=bytes_per_pixel;
7455 }
7456 q+=scanline_pad;
7457 }
7458 y++;
7459 }
7460 break;
7461 }
7462 }
7463 /*
7464 Copy X image to magnify pixmap.
7465 */
7466 x=windows->magnify.x-((width/magnify) >> 1);
7467 if (x < 0)
7468 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7469 else
7470 if (x > (int) (ximage->width-(width/magnify)))
7471 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7472 else
7473 x=0;
7474 y=windows->magnify.y-((height/magnify) >> 1);
7475 if (y < 0)
7476 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7477 else
7478 if (y > (int) (ximage->height-(height/magnify)))
7479 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7480 else
7481 y=0;
7482 if ((x != 0) || (y != 0))
7483 (void) XFillRectangle(display,windows->magnify.pixmap,
7484 windows->magnify.annotate_context,0,0,width,height);
7485 (void) XPutImage(display,windows->magnify.pixmap,
7486 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7487 height-y);
7488 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7489 (magnify <= (height >> 1))))
7490 {
7491 RectangleInfo
7492 highlight_info;
7493
7494 /*
7495 Highlight center pixel.
7496 */
cristybb503372010-05-27 20:51:26 +00007497 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7498 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007499 highlight_info.width=magnify;
7500 highlight_info.height=magnify;
7501 (void) XDrawRectangle(display,windows->magnify.pixmap,
7502 windows->magnify.highlight_context,(int) highlight_info.x,
7503 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7504 (unsigned int) highlight_info.height-1);
7505 if (magnify > 2)
7506 (void) XDrawRectangle(display,windows->magnify.pixmap,
7507 windows->magnify.annotate_context,(int) highlight_info.x+1,
7508 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7509 (unsigned int) highlight_info.height-3);
7510 }
7511 /*
7512 Show center pixel color.
7513 */
cristy3aa93752011-12-18 15:54:24 +00007514 (void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
cristy52010022011-10-21 18:07:37 +00007515 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007516 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007517 windows->magnify.x,windows->magnify.y);
7518 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007519 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007520 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007521 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007522 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007523 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007524 if (pixel.colorspace == CMYKColorspace)
7525 {
7526 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007527 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007528 }
cristy8a46d822012-08-28 23:32:39 +00007529 if (pixel.alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +00007530 {
7531 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007532 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007533 }
7534 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7535 height=(unsigned int) windows->magnify.font_info->ascent+
7536 windows->magnify.font_info->descent;
7537 x=windows->magnify.font_info->max_bounds.width >> 1;
7538 y=windows->magnify.font_info->ascent+(height >> 2);
7539 (void) XDrawImageString(display,windows->magnify.pixmap,
7540 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7541 GetColorTuple(&pixel,MagickTrue,tuple);
7542 y+=height;
7543 (void) XDrawImageString(display,windows->magnify.pixmap,
7544 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007545 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007546 exception);
cristy3ed852e2009-09-05 21:47:34 +00007547 y+=height;
7548 (void) XDrawImageString(display,windows->magnify.pixmap,
7549 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7550 /*
7551 Refresh magnify window.
7552 */
7553 magnify_window=windows->magnify;
7554 magnify_window.x=0;
7555 magnify_window.y=0;
7556 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7557}
7558
7559/*
7560%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7561% %
7562% %
7563% %
7564% X M a k e P i x m a p %
7565% %
7566% %
7567% %
7568%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7569%
7570% XMakePixmap() creates an X11 pixmap.
7571%
7572% The format of the XMakePixmap method is:
7573%
7574% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7575% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7576% XPixelInfo *pixel)
7577%
7578% A description of each parameter follows:
7579%
7580% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7581%
7582% o display: Specifies a connection to an X server; returned from
7583% XOpenDisplay.
7584%
7585% o window: Specifies a pointer to a XWindowInfo structure.
7586%
cristy3ed852e2009-09-05 21:47:34 +00007587*/
7588static MagickBooleanType XMakePixmap(Display *display,
7589 const XResourceInfo *resource_info,XWindowInfo *window)
7590{
7591 unsigned int
7592 height,
7593 width;
7594
7595 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7596 assert(display != (Display *) NULL);
7597 assert(resource_info != (XResourceInfo *) NULL);
7598 assert(window != (XWindowInfo *) NULL);
7599 if (window->pixmap != (Pixmap) NULL)
7600 {
7601 /*
7602 Destroy previous X pixmap.
7603 */
7604 (void) XFreePixmap(display,window->pixmap);
7605 window->pixmap=(Pixmap) NULL;
7606 }
7607 if (window->use_pixmap == MagickFalse)
7608 return(MagickFalse);
7609 if (window->ximage == (XImage *) NULL)
7610 return(MagickFalse);
7611 /*
7612 Display busy cursor.
7613 */
7614 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7615 (void) XFlush(display);
7616 /*
7617 Create pixmap.
7618 */
7619 width=(unsigned int) window->ximage->width;
7620 height=(unsigned int) window->ximage->height;
7621 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7622 if (window->pixmap == (Pixmap) NULL)
7623 {
7624 /*
7625 Unable to allocate pixmap.
7626 */
7627 (void) XCheckDefineCursor(display,window->id,window->cursor);
7628 return(MagickFalse);
7629 }
7630 /*
7631 Copy X image to pixmap.
7632 */
7633#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7634 if (window->shared_memory)
7635 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7636 window->ximage,0,0,0,0,width,height,MagickTrue);
7637#endif
7638 if (window->shared_memory == MagickFalse)
7639 (void) XPutImage(display,window->pixmap,window->annotate_context,
7640 window->ximage,0,0,0,0,width,height);
7641 if (IsEventLogging())
7642 {
7643 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7644 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7645 width,height);
7646 }
7647 /*
7648 Restore cursor.
7649 */
7650 (void) XCheckDefineCursor(display,window->id,window->cursor);
7651 return(MagickTrue);
7652}
7653
7654/*
7655%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7656% %
7657% %
7658% %
7659% X M a k e S t a n d a r d C o l o r m a p %
7660% %
7661% %
7662% %
7663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7664%
7665% XMakeStandardColormap() creates an X11 Standard Colormap.
7666%
7667% The format of the XMakeStandardColormap method is:
7668%
cristy6710d842011-10-20 23:23:00 +00007669% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7670% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7671% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007672%
7673% A description of each parameter follows:
7674%
7675% o display: Specifies a connection to an X server; returned from
7676% XOpenDisplay.
7677%
7678% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7679% returned from XGetVisualInfo.
7680%
7681% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7682%
7683% o image: the image.
7684%
7685% o map_info: If a Standard Colormap type is specified, this structure is
7686% initialized with info from the Standard Colormap.
7687%
7688% o pixel: Specifies a pointer to a XPixelInfo structure.
7689%
cristy6710d842011-10-20 23:23:00 +00007690% o exception: return any errors or warnings in this structure.
7691%
cristy3ed852e2009-09-05 21:47:34 +00007692*/
7693
7694#if defined(__cplusplus) || defined(c_plusplus)
7695extern "C" {
7696#endif
7697
cristya19f1d72012-08-07 18:24:38 +00007698static inline double DiversityPixelIntensity(
cristy3ed852e2009-09-05 21:47:34 +00007699 const DiversityPacket *pixel)
7700{
cristya19f1d72012-08-07 18:24:38 +00007701 double
cristy3ed852e2009-09-05 21:47:34 +00007702 intensity;
7703
cristya86a5cb2012-10-14 13:40:33 +00007704 intensity=0.298839f*pixel->red+0.586811f*pixel->green+0.114350f*pixel->blue;
cristy3ed852e2009-09-05 21:47:34 +00007705 return(intensity);
7706}
7707
7708static int IntensityCompare(const void *x,const void *y)
7709{
7710 DiversityPacket
7711 *color_1,
7712 *color_2;
7713
7714 int
7715 diversity;
7716
7717 color_1=(DiversityPacket *) x;
7718 color_2=(DiversityPacket *) y;
7719 diversity=(int) (DiversityPixelIntensity(color_2)-
7720 DiversityPixelIntensity(color_1));
7721 return(diversity);
7722}
7723
7724static int PopularityCompare(const void *x,const void *y)
7725{
7726 DiversityPacket
7727 *color_1,
7728 *color_2;
7729
7730 color_1=(DiversityPacket *) x;
7731 color_2=(DiversityPacket *) y;
7732 return((int) color_2->count-(int) color_1->count);
7733}
7734
7735#if defined(__cplusplus) || defined(c_plusplus)
7736}
7737#endif
7738
cristybb503372010-05-27 20:51:26 +00007739static inline Quantum ScaleXToQuantum(const size_t x,
7740 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007741{
cristya19f1d72012-08-07 18:24:38 +00007742 return((Quantum) (((double) QuantumRange*x)/scale+0.5));
cristy3ed852e2009-09-05 21:47:34 +00007743}
7744
cristybcbda3f2011-09-03 13:01:22 +00007745MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007746 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007747 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007748{
7749 Colormap
7750 colormap;
7751
cristybb503372010-05-27 20:51:26 +00007752 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007753 i;
7754
7755 Status
7756 status;
7757
cristybb503372010-05-27 20:51:26 +00007758 size_t
cristy3ed852e2009-09-05 21:47:34 +00007759 number_colors,
7760 retain_colors;
7761
7762 unsigned short
7763 gray_value;
7764
7765 XColor
7766 color,
7767 *colors,
7768 *p;
7769
7770 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7771 assert(display != (Display *) NULL);
7772 assert(visual_info != (XVisualInfo *) NULL);
7773 assert(map_info != (XStandardColormap *) NULL);
7774 assert(resource_info != (XResourceInfo *) NULL);
7775 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007776 if (resource_info->map_type != (char *) NULL)
7777 {
7778 /*
7779 Standard Colormap is already defined (i.e. xstdcmap).
7780 */
cristy4c08aed2011-07-01 19:47:50 +00007781 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007782 pixel);
7783 number_colors=(unsigned int) (map_info->base_pixel+
7784 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7785 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
cristy8a46d822012-08-28 23:32:39 +00007786 if ((image->alpha_trait != BlendPixelTrait) &&
cristy3ed852e2009-09-05 21:47:34 +00007787 (resource_info->color_recovery == MagickFalse) &&
cristycbda6112012-05-27 20:57:16 +00007788 (resource_info->quantize_info->dither_method != NoDitherMethod) &&
cristy3ed852e2009-09-05 21:47:34 +00007789 (number_colors < MaxColormapSize))
7790 {
7791 Image
7792 *affinity_image;
7793
cristy4c08aed2011-07-01 19:47:50 +00007794 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007795 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007796
7797 /*
7798 Improve image appearance with error diffusion.
7799 */
cristy6710d842011-10-20 23:23:00 +00007800 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007801 if (affinity_image == (Image *) NULL)
7802 ThrowXWindowFatalException(ResourceLimitFatalError,
7803 "UnableToDitherImage",image->filename);
7804 affinity_image->columns=number_colors;
7805 affinity_image->rows=1;
7806 /*
7807 Initialize colormap image.
7808 */
7809 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7810 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007811 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007812 {
cristybb503372010-05-27 20:51:26 +00007813 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007814 {
cristy4c08aed2011-07-01 19:47:50 +00007815 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007816 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007817 SetPixelRed(affinity_image,
7818 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7819 map_info->red_max),q);
7820 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007821 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007822 SetPixelGreen(affinity_image,
7823 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7824 (map_info->green_max+1)),map_info->green_max),q);
7825 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007826 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007827 SetPixelBlue(affinity_image,
7828 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7829 map_info->blue_max),q);
7830 SetPixelAlpha(affinity_image,
7831 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007832 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007833 }
7834 (void) SyncAuthenticPixels(affinity_image,exception);
7835 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007836 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007837 }
cristy4c08aed2011-07-01 19:47:50 +00007838 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007839 pixel);
cristy574cc262011-08-05 01:23:58 +00007840 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007841 affinity_image=DestroyImage(affinity_image);
7842 }
7843 if (IsEventLogging())
7844 {
7845 (void) LogMagickEvent(X11Event,GetMagickModule(),
7846 "Standard Colormap:");
7847 (void) LogMagickEvent(X11Event,GetMagickModule(),
7848 " colormap id: 0x%lx",map_info->colormap);
7849 (void) LogMagickEvent(X11Event,GetMagickModule(),
7850 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7851 map_info->green_max,map_info->blue_max);
7852 (void) LogMagickEvent(X11Event,GetMagickModule(),
7853 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7854 map_info->green_mult,map_info->blue_mult);
7855 }
7856 return;
7857 }
7858 if ((visual_info->klass != DirectColor) &&
7859 (visual_info->klass != TrueColor))
7860 if ((image->storage_class == DirectClass) ||
7861 ((int) image->colors > visual_info->colormap_size))
7862 {
7863 QuantizeInfo
7864 quantize_info;
7865
7866 /*
7867 Image has more colors than the visual supports.
7868 */
7869 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007870 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007871 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007872 }
7873 /*
7874 Free previous and create new colormap.
7875 */
7876 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7877 colormap=XDefaultColormap(display,visual_info->screen);
7878 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7879 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7880 visual_info->visual,visual_info->klass == DirectColor ?
7881 AllocAll : AllocNone);
7882 if (colormap == (Colormap) NULL)
7883 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7884 image->filename);
7885 /*
7886 Initialize the map and pixel info structures.
7887 */
7888 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007889 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007890 /*
7891 Allocating colors in server colormap is based on visual class.
7892 */
7893 switch (visual_info->klass)
7894 {
7895 case StaticGray:
7896 case StaticColor:
7897 {
7898 /*
7899 Define Standard Colormap for StaticGray or StaticColor visual.
7900 */
7901 number_colors=image->colors;
7902 colors=(XColor *) AcquireQuantumMemory((size_t)
7903 visual_info->colormap_size,sizeof(*colors));
7904 if (colors == (XColor *) NULL)
7905 ThrowXWindowFatalException(ResourceLimitFatalError,
7906 "UnableToCreateColormap",image->filename);
7907 p=colors;
7908 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007909 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007910 {
7911 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7912 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7913 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7914 if (visual_info->klass != StaticColor)
7915 {
7916 gray_value=(unsigned short) XPixelIntensity(&color);
7917 color.red=gray_value;
7918 color.green=gray_value;
7919 color.blue=gray_value;
7920 }
7921 status=XAllocColor(display,colormap,&color);
7922 if (status == False)
7923 {
7924 colormap=XCopyColormapAndFree(display,colormap);
7925 (void) XAllocColor(display,colormap,&color);
7926 }
7927 pixel->pixels[i]=color.pixel;
7928 *p++=color;
7929 }
7930 break;
7931 }
7932 case GrayScale:
7933 case PseudoColor:
7934 {
7935 unsigned int
7936 colormap_type;
7937
7938 /*
7939 Define Standard Colormap for GrayScale or PseudoColor visual.
7940 */
7941 number_colors=image->colors;
7942 colors=(XColor *) AcquireQuantumMemory((size_t)
7943 visual_info->colormap_size,sizeof(*colors));
7944 if (colors == (XColor *) NULL)
7945 ThrowXWindowFatalException(ResourceLimitFatalError,
7946 "UnableToCreateColormap",image->filename);
7947 /*
7948 Preallocate our GUI colors.
7949 */
7950 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7951 (void) XAllocColor(display,colormap,&pixel->background_color);
7952 (void) XAllocColor(display,colormap,&pixel->border_color);
7953 (void) XAllocColor(display,colormap,&pixel->matte_color);
7954 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7955 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7956 (void) XAllocColor(display,colormap,&pixel->depth_color);
7957 (void) XAllocColor(display,colormap,&pixel->trough_color);
7958 for (i=0; i < MaxNumberPens; i++)
7959 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7960 /*
7961 Determine if image colors will "fit" into X server colormap.
7962 */
7963 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007964 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007965 NULL,0,pixel->pixels,(unsigned int) image->colors);
7966 if (status != False)
7967 colormap_type=PrivateColormap;
7968 if (colormap_type == SharedColormap)
7969 {
cristyc57f6942010-11-12 01:47:39 +00007970 CacheView
7971 *image_view;
7972
cristy3ed852e2009-09-05 21:47:34 +00007973 DiversityPacket
7974 *diversity;
7975
7976 int
7977 y;
7978
7979 register int
7980 x;
7981
7982 unsigned short
7983 index;
7984
7985 XColor
7986 *server_colors;
7987
7988 /*
7989 Define Standard colormap for shared GrayScale or PseudoColor visual.
7990 */
7991 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7992 sizeof(*diversity));
7993 if (diversity == (DiversityPacket *) NULL)
7994 ThrowXWindowFatalException(ResourceLimitFatalError,
7995 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007996 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007997 {
cristye42f6582012-02-11 17:59:50 +00007998 diversity[i].red=ClampToQuantum(image->colormap[i].red);
7999 diversity[i].green=ClampToQuantum(image->colormap[i].green);
8000 diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
cristy3ed852e2009-09-05 21:47:34 +00008001 diversity[i].index=(unsigned short) i;
8002 diversity[i].count=0;
8003 }
cristydb070952012-04-20 14:33:00 +00008004 image_view=AcquireAuthenticCacheView(image,exception);
cristy3ed852e2009-09-05 21:47:34 +00008005 for (y=0; y < (int) image->rows; y++)
8006 {
cristyc57f6942010-11-12 01:47:39 +00008007 register int
cristy3ed852e2009-09-05 21:47:34 +00008008 x;
8009
cristy4c08aed2011-07-01 19:47:50 +00008010 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00008011 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00008012
cristyc57f6942010-11-12 01:47:39 +00008013 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8014 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008015 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008016 break;
cristyc57f6942010-11-12 01:47:39 +00008017 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008018 {
8019 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008020 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008021 }
cristy3ed852e2009-09-05 21:47:34 +00008022 }
cristyc57f6942010-11-12 01:47:39 +00008023 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008024 /*
8025 Sort colors by decreasing intensity.
8026 */
8027 qsort((void *) diversity,image->colors,sizeof(*diversity),
8028 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008029 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008030 {
8031 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008032 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008033 }
8034 diversity[image->colors-1].count<<=4;
8035 qsort((void *) diversity,image->colors,sizeof(*diversity),
8036 PopularityCompare);
8037 /*
8038 Allocate colors.
8039 */
8040 p=colors;
8041 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008042 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008043 {
8044 index=diversity[i].index;
8045 color.red=
8046 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8047 color.green=
8048 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8049 color.blue=
8050 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8051 if (visual_info->klass != PseudoColor)
8052 {
8053 gray_value=(unsigned short) XPixelIntensity(&color);
8054 color.red=gray_value;
8055 color.green=gray_value;
8056 color.blue=gray_value;
8057 }
8058 status=XAllocColor(display,colormap,&color);
8059 if (status == False)
8060 break;
8061 pixel->pixels[index]=color.pixel;
8062 *p++=color;
8063 }
8064 /*
8065 Read X server colormap.
8066 */
8067 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8068 visual_info->colormap_size,sizeof(*server_colors));
8069 if (server_colors == (XColor *) NULL)
8070 ThrowXWindowFatalException(ResourceLimitFatalError,
8071 "UnableToCreateColormap",image->filename);
8072 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008073 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008074 (void) XQueryColors(display,colormap,server_colors,
8075 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8076 /*
8077 Select remaining colors from X server colormap.
8078 */
cristybb503372010-05-27 20:51:26 +00008079 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008080 {
8081 index=diversity[i].index;
8082 color.red=
8083 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8084 color.green=
8085 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8086 color.blue=
8087 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8088 if (visual_info->klass != PseudoColor)
8089 {
8090 gray_value=(unsigned short) XPixelIntensity(&color);
8091 color.red=gray_value;
8092 color.green=gray_value;
8093 color.blue=gray_value;
8094 }
8095 XBestPixel(display,colormap,server_colors,(unsigned int)
8096 visual_info->colormap_size,&color);
8097 pixel->pixels[index]=color.pixel;
8098 *p++=color;
8099 }
8100 if ((int) image->colors < visual_info->colormap_size)
8101 {
8102 /*
8103 Fill up colors array-- more choices for pen colors.
8104 */
8105 retain_colors=MagickMin((unsigned int)
8106 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008107 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008108 *p++=server_colors[i];
8109 number_colors+=retain_colors;
8110 }
8111 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8112 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8113 break;
8114 }
8115 /*
8116 Define Standard colormap for private GrayScale or PseudoColor visual.
8117 */
8118 if (status == False)
8119 {
8120 /*
8121 Not enough colormap entries in the colormap-- Create a new colormap.
8122 */
8123 colormap=XCreateColormap(display,
8124 XRootWindow(display,visual_info->screen),visual_info->visual,
8125 AllocNone);
8126 if (colormap == (Colormap) NULL)
8127 ThrowXWindowFatalException(ResourceLimitFatalError,
8128 "UnableToCreateColormap",image->filename);
8129 map_info->colormap=colormap;
8130 if ((int) image->colors < visual_info->colormap_size)
8131 {
8132 /*
8133 Retain colors from the default colormap to help lessens the
8134 effects of colormap flashing.
8135 */
8136 retain_colors=MagickMin((unsigned int)
8137 (visual_info->colormap_size-image->colors),256);
8138 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008139 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008140 {
cristyc57f6942010-11-12 01:47:39 +00008141 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008142 p++;
8143 }
8144 (void) XQueryColors(display,
8145 XDefaultColormap(display,visual_info->screen),
8146 colors+image->colors,(int) retain_colors);
8147 /*
8148 Transfer colors from default to private colormap.
8149 */
8150 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008151 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008152 retain_colors);
8153 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008154 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008155 {
8156 p->pixel=pixel->pixels[i];
8157 p++;
8158 }
8159 (void) XStoreColors(display,colormap,colors+image->colors,
8160 (int) retain_colors);
8161 number_colors+=retain_colors;
8162 }
8163 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008164 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008165 image->colors);
8166 }
8167 /*
8168 Store the image colormap.
8169 */
8170 p=colors;
8171 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008172 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008173 {
8174 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8175 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8176 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8177 if (visual_info->klass != PseudoColor)
8178 {
8179 gray_value=(unsigned short) XPixelIntensity(&color);
8180 color.red=gray_value;
8181 color.green=gray_value;
8182 color.blue=gray_value;
8183 }
8184 color.pixel=pixel->pixels[i];
8185 *p++=color;
8186 }
8187 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8188 break;
8189 }
8190 case TrueColor:
8191 case DirectColor:
8192 default:
8193 {
8194 MagickBooleanType
8195 linear_colormap;
8196
8197 /*
8198 Define Standard Colormap for TrueColor or DirectColor visual.
8199 */
8200 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8201 (map_info->green_max*map_info->green_mult)+
8202 (map_info->blue_max*map_info->blue_mult)+1);
8203 linear_colormap=(number_colors > 4096) ||
8204 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8205 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8206 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8207 MagickTrue : MagickFalse;
8208 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008209 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008210 /*
8211 Allocate color array.
8212 */
8213 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8214 if (colors == (XColor *) NULL)
8215 ThrowXWindowFatalException(ResourceLimitFatalError,
8216 "UnableToCreateColormap",image->filename);
8217 /*
8218 Initialize linear color ramp.
8219 */
8220 p=colors;
8221 color.flags=(char) (DoRed | DoGreen | DoBlue);
8222 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008223 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008224 {
8225 color.blue=(unsigned short) 0;
8226 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008227 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008228 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8229 color.green=color.blue;
8230 color.red=color.blue;
8231 color.pixel=XStandardPixel(map_info,&color);
8232 *p++=color;
8233 }
8234 else
cristybb503372010-05-27 20:51:26 +00008235 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008236 {
8237 color.red=(unsigned short) 0;
8238 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008239 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008240 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8241 color.green=(unsigned int) 0;
8242 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008243 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008244 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8245 map_info->green_max));
8246 color.blue=(unsigned short) 0;
8247 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008248 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008249 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8250 color.pixel=XStandardPixel(map_info,&color);
8251 *p++=color;
8252 }
8253 if ((visual_info->klass == DirectColor) &&
8254 (colormap != XDefaultColormap(display,visual_info->screen)))
8255 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8256 else
cristybb503372010-05-27 20:51:26 +00008257 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008258 (void) XAllocColor(display,colormap,&colors[i]);
8259 break;
8260 }
8261 }
8262 if ((visual_info->klass != DirectColor) &&
8263 (visual_info->klass != TrueColor))
8264 {
8265 /*
8266 Set foreground, background, border, etc. pixels.
8267 */
8268 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8269 &pixel->foreground_color);
8270 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8271 &pixel->background_color);
8272 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8273 {
8274 /*
8275 Foreground and background colors must differ.
8276 */
8277 pixel->background_color.red=(~pixel->foreground_color.red);
8278 pixel->background_color.green=
8279 (~pixel->foreground_color.green);
8280 pixel->background_color.blue=
8281 (~pixel->foreground_color.blue);
8282 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8283 &pixel->background_color);
8284 }
8285 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8286 &pixel->border_color);
8287 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8288 &pixel->matte_color);
8289 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8290 &pixel->highlight_color);
8291 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8292 &pixel->shadow_color);
8293 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8294 &pixel->depth_color);
8295 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8296 &pixel->trough_color);
8297 for (i=0; i < MaxNumberPens; i++)
8298 {
8299 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8300 &pixel->pen_colors[i]);
8301 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8302 }
cristyc57f6942010-11-12 01:47:39 +00008303 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008304 }
8305 colors=(XColor *) RelinquishMagickMemory(colors);
8306 if (IsEventLogging())
8307 {
8308 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8309 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8310 map_info->colormap);
8311 (void) LogMagickEvent(X11Event,GetMagickModule(),
8312 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8313 map_info->green_max,map_info->blue_max);
8314 (void) LogMagickEvent(X11Event,GetMagickModule(),
8315 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8316 map_info->green_mult,map_info->blue_mult);
8317 }
8318}
8319
8320/*
8321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8322% %
8323% %
8324% %
8325% X M a k e W i n d o w %
8326% %
8327% %
8328% %
8329%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8330%
8331% XMakeWindow() creates an X11 window.
8332%
8333% The format of the XMakeWindow method is:
8334%
8335% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8336% XClassHint *class_hint,XWMHints *manager_hints,
8337% XWindowInfo *window_info)
8338%
8339% A description of each parameter follows:
8340%
8341% o display: Specifies a connection to an X server; returned from
8342% XOpenDisplay.
8343%
8344% o parent: Specifies the parent window_info.
8345%
8346% o argv: Specifies the application's argument list.
8347%
8348% o argc: Specifies the number of arguments.
8349%
8350% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8351%
8352% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8353%
8354% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8355%
8356*/
cristybcbda3f2011-09-03 13:01:22 +00008357MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008358 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8359 XWindowInfo *window_info)
8360{
8361#define MinWindowSize 64
8362
8363 Atom
8364 atom_list[2];
8365
8366 int
8367 gravity;
8368
8369 static XTextProperty
8370 icon_name,
8371 window_name;
8372
8373 Status
8374 status;
8375
8376 XSizeHints
8377 *size_hints;
8378
8379 /*
8380 Set window info hints.
8381 */
8382 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8383 assert(display != (Display *) NULL);
8384 assert(window_info != (XWindowInfo *) NULL);
8385 size_hints=XAllocSizeHints();
8386 if (size_hints == (XSizeHints *) NULL)
8387 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008388 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008389 size_hints->x=window_info->x;
8390 size_hints->y=window_info->y;
8391 size_hints->width=(int) window_info->width;
8392 size_hints->height=(int) window_info->height;
8393 if (window_info->immutable != MagickFalse)
8394 {
8395 /*
8396 Window size cannot be changed.
8397 */
8398 size_hints->min_width=size_hints->width;
8399 size_hints->min_height=size_hints->height;
8400 size_hints->max_width=size_hints->width;
8401 size_hints->max_height=size_hints->height;
8402 size_hints->flags|=PMinSize;
8403 size_hints->flags|=PMaxSize;
8404 }
8405 else
8406 {
8407 /*
8408 Window size can be changed.
8409 */
8410 size_hints->min_width=(int) window_info->min_width;
8411 size_hints->min_height=(int) window_info->min_height;
8412 size_hints->flags|=PResizeInc;
8413 size_hints->width_inc=(int) window_info->width_inc;
8414 size_hints->height_inc=(int) window_info->height_inc;
8415#if !defined(PRE_R4_ICCCM)
8416 size_hints->flags|=PBaseSize;
8417 size_hints->base_width=size_hints->width_inc;
8418 size_hints->base_height=size_hints->height_inc;
8419#endif
8420 }
8421 gravity=NorthWestGravity;
8422 if (window_info->geometry != (char *) NULL)
8423 {
8424 char
8425 default_geometry[MaxTextExtent],
8426 geometry[MaxTextExtent];
8427
8428 int
8429 flags;
8430
8431 register char
8432 *p;
8433
8434 /*
8435 User specified geometry.
8436 */
cristyb51dff52011-05-19 16:55:47 +00008437 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008438 size_hints->width,size_hints->height);
8439 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8440 p=geometry;
8441 while (strlen(p) != 0)
8442 {
8443 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8444 p++;
8445 else
8446 (void) CopyMagickString(p,p+1,MaxTextExtent);
8447 }
8448 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8449 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8450 &size_hints->width,&size_hints->height,&gravity);
8451 if ((flags & WidthValue) && (flags & HeightValue))
8452 size_hints->flags|=USSize;
8453 if ((flags & XValue) && (flags & YValue))
8454 {
8455 size_hints->flags|=USPosition;
8456 window_info->x=size_hints->x;
8457 window_info->y=size_hints->y;
8458 }
8459 }
8460#if !defined(PRE_R4_ICCCM)
8461 size_hints->win_gravity=gravity;
8462 size_hints->flags|=PWinGravity;
8463#endif
8464 if (window_info->id == (Window) NULL)
8465 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8466 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8467 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008468 window_info->visual,(unsigned long) window_info->mask,
8469 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008470 else
8471 {
8472 MagickStatusType
8473 mask;
8474
8475 XEvent
8476 sans_event;
8477
8478 XWindowChanges
8479 window_changes;
8480
8481 /*
8482 Window already exists; change relevant attributes.
8483 */
cristyc57f6942010-11-12 01:47:39 +00008484 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8485 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008486 mask=ConfigureNotify;
8487 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8488 window_changes.x=window_info->x;
8489 window_changes.y=window_info->y;
8490 window_changes.width=(int) window_info->width;
8491 window_changes.height=(int) window_info->height;
8492 mask=(MagickStatusType) (CWWidth | CWHeight);
8493 if (window_info->flags & USPosition)
8494 mask|=CWX | CWY;
8495 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8496 mask,&window_changes);
8497 }
8498 if (window_info->id == (Window) NULL)
8499 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8500 window_info->name);
8501 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8502 if (status == False)
8503 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8504 window_info->name);
8505 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8506 if (status == False)
8507 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8508 window_info->icon_name);
8509 if (window_info->icon_geometry != (char *) NULL)
8510 {
8511 int
8512 flags,
8513 height,
8514 width;
8515
8516 /*
8517 User specified icon geometry.
8518 */
8519 size_hints->flags|=USPosition;
8520 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8521 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8522 &manager_hints->icon_y,&width,&height,&gravity);
8523 if ((flags & XValue) && (flags & YValue))
8524 manager_hints->flags|=IconPositionHint;
8525 }
8526 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8527 size_hints,manager_hints,class_hint);
8528 if (window_name.value != (void *) NULL)
8529 {
8530 (void) XFree((void *) window_name.value);
8531 window_name.value=(unsigned char *) NULL;
8532 window_name.nitems=0;
8533 }
8534 if (icon_name.value != (void *) NULL)
8535 {
8536 (void) XFree((void *) icon_name.value);
8537 icon_name.value=(unsigned char *) NULL;
8538 icon_name.nitems=0;
8539 }
8540 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8541 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8542 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8543 (void) XFree((void *) size_hints);
8544 if (window_info->shape != MagickFalse)
8545 {
8546#if defined(MAGICKCORE_HAVE_SHAPE)
8547 int
8548 error_base,
8549 event_base;
8550
8551 /*
8552 Can we apply a non-rectangular shaping mask?
8553 */
8554 error_base=0;
8555 event_base=0;
8556 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8557 window_info->shape=MagickFalse;
8558#else
8559 window_info->shape=MagickFalse;
8560#endif
8561 }
8562 if (window_info->shared_memory)
8563 {
8564#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8565 /*
8566 Can we use shared memory with this window?
8567 */
8568 if (XShmQueryExtension(display) == 0)
8569 window_info->shared_memory=MagickFalse;
8570#else
8571 window_info->shared_memory=MagickFalse;
8572#endif
8573 }
8574 window_info->image=NewImageList();
8575 window_info->destroy=MagickFalse;
8576}
8577
8578/*
8579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8580% %
8581% %
8582% %
8583% X M a g i c k P r o g r e s s M o n i t o r %
8584% %
8585% %
8586% %
8587%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8588%
8589% XMagickProgressMonitor() displays the progress a task is making in
8590% completing a task.
8591%
8592% The format of the XMagickProgressMonitor method is:
8593%
8594% void XMagickProgressMonitor(const char *task,
8595% const MagickOffsetType quantum,const MagickSizeType span,
8596% void *client_data)
8597%
8598% A description of each parameter follows:
8599%
8600% o task: Identifies the task in progress.
8601%
8602% o quantum: Specifies the quantum position within the span which represents
8603% how much progress has been made in completing a task.
8604%
8605% o span: Specifies the span relative to completing a task.
8606%
8607% o client_data: Pointer to any client data.
8608%
8609*/
8610
8611static const char *GetLocaleMonitorMessage(const char *text)
8612{
8613 char
8614 message[MaxTextExtent],
8615 tag[MaxTextExtent];
8616
8617 const char
8618 *locale_message;
8619
8620 register char
8621 *p;
8622
8623 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8624 p=strrchr(tag,'/');
8625 if (p != (char *) NULL)
8626 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008627 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008628 locale_message=GetLocaleMessage(message);
8629 if (locale_message == message)
8630 return(text);
8631 return(locale_message);
8632}
8633
cristybcbda3f2011-09-03 13:01:22 +00008634MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008635 const MagickOffsetType quantum,const MagickSizeType span,
8636 void *magick_unused(client_data))
8637{
8638 XWindows
8639 *windows;
8640
8641 windows=XSetWindows((XWindows *) ~0);
8642 if (windows == (XWindows *) NULL)
8643 return(MagickTrue);
8644 if (windows->info.mapped != MagickFalse)
8645 XProgressMonitorWidget(windows->display,windows,
8646 GetLocaleMonitorMessage(tag),quantum,span);
8647 return(MagickTrue);
8648}
8649
8650/*
8651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8652% %
8653% %
8654% %
8655% X Q u e r y C o l o r D a t a b a s e %
8656% %
8657% %
8658% %
8659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8660%
cristy9950d572011-10-01 18:22:35 +00008661% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008662% string.
8663%
8664% The format of the XQueryColorDatabase method is:
8665%
cristy9950d572011-10-01 18:22:35 +00008666% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008667%
8668% A description of each parameter follows:
8669%
8670% o target: Specifies the color to lookup in the X color database.
8671%
cristy101ab702011-10-13 13:06:32 +00008672% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008673% color is returned as this value.
8674%
8675*/
cristy9950d572011-10-01 18:22:35 +00008676MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008677 XColor *color)
8678{
8679 Colormap
8680 colormap;
8681
8682 static Display
8683 *display = (Display *) NULL;
8684
8685 Status
8686 status;
8687
8688 XColor
8689 xcolor;
8690
8691 /*
8692 Initialize color return value.
8693 */
8694 assert(color != (XColor *) NULL);
8695 color->red=0;
8696 color->green=0;
8697 color->blue=0;
8698 color->flags=(char) (DoRed | DoGreen | DoBlue);
8699 if ((target == (char *) NULL) || (*target == '\0'))
8700 target="#ffffffffffff";
8701 /*
8702 Let the X server define the color for us.
8703 */
8704 if (display == (Display *) NULL)
8705 display=XOpenDisplay((char *) NULL);
8706 if (display == (Display *) NULL)
8707 {
8708 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8709 return(MagickFalse);
8710 }
8711 colormap=XDefaultColormap(display,XDefaultScreen(display));
8712 status=XParseColor(display,colormap,(char *) target,&xcolor);
8713 if (status == False)
8714 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8715 else
8716 {
8717 color->red=xcolor.red;
8718 color->green=xcolor.green;
8719 color->blue=xcolor.blue;
8720 color->flags=xcolor.flags;
8721 }
8722 return(status != False ? MagickTrue : MagickFalse);
8723}
8724
8725/*
8726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8727% %
8728% %
8729% %
8730% X Q u e r y P o s i t i o n %
8731% %
8732% %
8733% %
8734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8735%
8736% XQueryPosition() gets the pointer coordinates relative to a window.
8737%
8738% The format of the XQueryPosition method is:
8739%
8740% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8741%
8742% A description of each parameter follows:
8743%
8744% o display: Specifies a connection to an X server; returned from
8745% XOpenDisplay.
8746%
8747% o window: Specifies a pointer to a Window.
8748%
8749% o x: Return the x coordinate of the pointer relative to the origin of the
8750% window.
8751%
8752% o y: Return the y coordinate of the pointer relative to the origin of the
8753% window.
8754%
8755*/
cristybcbda3f2011-09-03 13:01:22 +00008756MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008757{
8758 int
8759 x_root,
8760 y_root;
8761
8762 unsigned int
8763 mask;
8764
8765 Window
8766 root_window;
8767
8768 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8769 assert(display != (Display *) NULL);
8770 assert(window != (Window) NULL);
8771 assert(x != (int *) NULL);
8772 assert(y != (int *) NULL);
8773 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8774 x,y,&mask);
8775}
8776
8777/*
8778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8779% %
8780% %
8781% %
8782% X R e f r e s h W i n d o w %
8783% %
8784% %
8785% %
8786%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8787%
8788% XRefreshWindow() refreshes an image in a X window.
8789%
8790% The format of the XRefreshWindow method is:
8791%
8792% void XRefreshWindow(Display *display,const XWindowInfo *window,
8793% const XEvent *event)
8794%
8795% A description of each parameter follows:
8796%
8797% o display: Specifies a connection to an X server; returned from
8798% XOpenDisplay.
8799%
8800% o window: Specifies a pointer to a XWindowInfo structure.
8801%
8802% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8803% the entire image is refreshed.
8804%
8805*/
cristybcbda3f2011-09-03 13:01:22 +00008806MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008807 const XEvent *event)
8808{
8809 int
8810 x,
8811 y;
8812
8813 unsigned int
8814 height,
8815 width;
8816
8817 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8818 assert(display != (Display *) NULL);
8819 assert(window != (XWindowInfo *) NULL);
8820 if (window->ximage == (XImage *) NULL)
8821 return;
8822 if (event != (XEvent *) NULL)
8823 {
8824 /*
8825 Determine geometry from expose event.
8826 */
8827 x=event->xexpose.x;
8828 y=event->xexpose.y;
8829 width=(unsigned int) event->xexpose.width;
8830 height=(unsigned int) event->xexpose.height;
8831 }
8832 else
8833 {
8834 XEvent
8835 sans_event;
8836
8837 /*
8838 Refresh entire window; discard outstanding expose events.
8839 */
8840 x=0;
8841 y=0;
8842 width=window->width;
8843 height=window->height;
8844 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008845 if (window->matte_pixmap != (Pixmap) NULL)
8846 {
8847#if defined(MAGICKCORE_HAVE_SHAPE)
8848 if (window->shape != MagickFalse)
8849 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8850 window->matte_pixmap,ShapeSet);
8851#endif
8852 }
cristy3ed852e2009-09-05 21:47:34 +00008853 }
8854 /*
8855 Check boundary conditions.
8856 */
8857 if ((window->ximage->width-(x+window->x)) < (int) width)
8858 width=(unsigned int) (window->ximage->width-(x+window->x));
8859 if ((window->ximage->height-(y+window->y)) < (int) height)
8860 height=(unsigned int) (window->ximage->height-(y+window->y));
8861 /*
8862 Refresh image.
8863 */
8864 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008865 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008866 if (window->pixmap != (Pixmap) NULL)
8867 {
8868 if (window->depth > 1)
8869 (void) XCopyArea(display,window->pixmap,window->id,
8870 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8871 else
8872 (void) XCopyPlane(display,window->pixmap,window->id,
8873 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8874 1L);
8875 }
8876 else
8877 {
8878#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8879 if (window->shared_memory)
8880 (void) XShmPutImage(display,window->id,window->annotate_context,
8881 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8882#endif
8883 if (window->shared_memory == MagickFalse)
8884 (void) XPutImage(display,window->id,window->annotate_context,
8885 window->ximage,x+window->x,y+window->y,x,y,width,height);
8886 }
8887 if (window->matte_pixmap != (Pixmap) NULL)
8888 (void) XSetClipMask(display,window->annotate_context,None);
8889 (void) XFlush(display);
8890}
8891
8892/*
8893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8894% %
8895% %
8896% %
8897% X R e m o t e C o m m a n d %
8898% %
8899% %
8900% %
8901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8902%
8903% XRemoteCommand() forces a remote display(1) to display the specified
8904% image filename.
8905%
8906% The format of the XRemoteCommand method is:
8907%
8908% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8909% const char *filename)
8910%
8911% A description of each parameter follows:
8912%
8913% o display: Specifies a connection to an X server; returned from
8914% XOpenDisplay.
8915%
8916% o window: Specifies the name or id of an X window.
8917%
8918% o filename: the name of the image filename to display.
8919%
8920*/
8921MagickExport MagickBooleanType XRemoteCommand(Display *display,
8922 const char *window,const char *filename)
8923{
8924 Atom
8925 remote_atom;
8926
8927 Window
8928 remote_window,
8929 root_window;
8930
8931 assert(filename != (char *) NULL);
8932 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8933 if (display == (Display *) NULL)
8934 display=XOpenDisplay((char *) NULL);
8935 if (display == (Display *) NULL)
8936 {
8937 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8938 return(MagickFalse);
8939 }
8940 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8941 remote_window=(Window) NULL;
8942 root_window=XRootWindow(display,XDefaultScreen(display));
8943 if (window != (char *) NULL)
8944 {
8945 /*
8946 Search window hierarchy and identify any clients by name or ID.
8947 */
8948 if (isdigit((unsigned char) *window) != 0)
8949 remote_window=XWindowByID(display,root_window,(Window)
8950 strtol((char *) window,(char **) NULL,0));
8951 if (remote_window == (Window) NULL)
8952 remote_window=XWindowByName(display,root_window,window);
8953 }
8954 if (remote_window == (Window) NULL)
8955 remote_window=XWindowByProperty(display,root_window,remote_atom);
8956 if (remote_window == (Window) NULL)
8957 {
8958 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8959 filename);
8960 return(MagickFalse);
8961 }
8962 /*
8963 Send remote command.
8964 */
8965 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8966 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8967 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8968 (void) XSync(display,MagickFalse);
8969 return(MagickTrue);
8970}
8971
8972/*
8973%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8974% %
8975% %
8976% %
8977% X R e t a i n W i n d o w C o l o r s %
8978% %
8979% %
8980% %
8981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8982%
8983% XRetainWindowColors() sets X11 color resources on a window. This preserves
8984% the colors associated with an image displayed on the window.
8985%
8986% The format of the XRetainWindowColors method is:
8987%
8988% void XRetainWindowColors(Display *display,const Window window)
8989%
8990% A description of each parameter follows:
8991%
8992% o display: Specifies a connection to an X server; returned from
8993% XOpenDisplay.
8994%
8995% o window: Specifies a pointer to a XWindowInfo structure.
8996%
8997*/
8998MagickExport void XRetainWindowColors(Display *display,const Window window)
8999{
9000 Atom
9001 property;
9002
9003 Pixmap
9004 pixmap;
9005
9006 /*
9007 Put property on the window.
9008 */
9009 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9010 assert(display != (Display *) NULL);
9011 assert(window != (Window) NULL);
9012 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9013 if (property == (Atom) NULL)
9014 {
9015 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9016 "_XSETROOT_ID");
9017 return;
9018 }
9019 pixmap=XCreatePixmap(display,window,1,1,1);
9020 if (pixmap == (Pixmap) NULL)
9021 {
9022 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9023 return;
9024 }
9025 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9026 (unsigned char *) &pixmap,1);
9027 (void) XSetCloseDownMode(display,RetainPermanent);
9028}
9029
9030/*
9031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9032% %
9033% %
9034% %
9035% X S e l e c t W i n d o w %
9036% %
9037% %
9038% %
9039%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9040%
9041% XSelectWindow() allows a user to select a window using the mouse. If the
9042% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9043% is returned in the crop_info structure.
9044%
9045% The format of the XSelectWindow function is:
9046%
9047% target_window=XSelectWindow(display,crop_info)
9048%
9049% A description of each parameter follows:
9050%
9051% o window: XSelectWindow returns the window id.
9052%
9053% o display: Specifies a pointer to the Display structure; returned from
9054% XOpenDisplay.
9055%
9056% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9057% contains the extents of any cropping rectangle.
9058%
cristy3ed852e2009-09-05 21:47:34 +00009059*/
9060static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9061{
9062#define MinimumCropArea (unsigned int) 9
9063
9064 Cursor
9065 target_cursor;
9066
9067 GC
9068 annotate_context;
9069
9070 int
9071 presses,
9072 x_offset,
9073 y_offset;
9074
9075 Status
9076 status;
9077
9078 Window
9079 root_window,
9080 target_window;
9081
9082 XEvent
9083 event;
9084
9085 XGCValues
9086 context_values;
9087
9088 /*
9089 Initialize graphic context.
9090 */
9091 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9092 assert(display != (Display *) NULL);
9093 assert(crop_info != (RectangleInfo *) NULL);
9094 root_window=XRootWindow(display,XDefaultScreen(display));
9095 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9096 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9097 context_values.function=GXinvert;
9098 context_values.plane_mask=
9099 context_values.background ^ context_values.foreground;
9100 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009101 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009102 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9103 if (annotate_context == (GC) NULL)
9104 return(MagickFalse);
9105 /*
9106 Grab the pointer using target cursor.
9107 */
9108 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9109 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9110 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9111 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9112 GrabModeAsync,root_window,target_cursor,CurrentTime);
9113 if (status != GrabSuccess)
9114 {
9115 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9116 return((Window) NULL);
9117 }
9118 /*
9119 Select a window.
9120 */
9121 crop_info->width=0;
9122 crop_info->height=0;
9123 presses=0;
9124 target_window=(Window) NULL;
9125 x_offset=0;
9126 y_offset=0;
9127 do
9128 {
9129 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9130 (void) XDrawRectangle(display,root_window,annotate_context,
9131 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9132 (unsigned int) crop_info->height-1);
9133 /*
9134 Allow another event.
9135 */
9136 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9137 (void) XWindowEvent(display,root_window,ButtonPressMask |
9138 ButtonReleaseMask | ButtonMotionMask,&event);
9139 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9140 (void) XDrawRectangle(display,root_window,annotate_context,
9141 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9142 (unsigned int) crop_info->height-1);
9143 switch (event.type)
9144 {
9145 case ButtonPress:
9146 {
9147 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9148 event.xbutton.x,event.xbutton.y);
9149 if (target_window == (Window) NULL)
9150 target_window=root_window;
9151 x_offset=event.xbutton.x_root;
9152 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009153 crop_info->x=(ssize_t) x_offset;
9154 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009155 crop_info->width=0;
9156 crop_info->height=0;
9157 presses++;
9158 break;
9159 }
9160 case ButtonRelease:
9161 {
9162 presses--;
9163 break;
9164 }
9165 case MotionNotify:
9166 {
9167 /*
9168 Discard pending button motion events.
9169 */
9170 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009171 crop_info->x=(ssize_t) event.xmotion.x;
9172 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009173 /*
9174 Check boundary conditions.
9175 */
9176 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009177 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009178 else
9179 {
cristyecd0ab52010-05-30 14:59:20 +00009180 crop_info->width=(size_t) (crop_info->x-x_offset);
9181 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009182 }
9183 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009184 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009185 else
9186 {
cristyecd0ab52010-05-30 14:59:20 +00009187 crop_info->height=(size_t) (crop_info->y-y_offset);
9188 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009189 }
9190 }
9191 default:
9192 break;
9193 }
9194 } while ((target_window == (Window) NULL) || (presses > 0));
9195 (void) XUngrabPointer(display,CurrentTime);
9196 (void) XFreeCursor(display,target_cursor);
9197 (void) XFreeGC(display,annotate_context);
9198 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9199 {
9200 crop_info->width=0;
9201 crop_info->height=0;
9202 }
9203 if ((crop_info->width != 0) && (crop_info->height != 0))
9204 target_window=root_window;
9205 return(target_window);
9206}
9207
9208/*
9209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9210% %
9211% %
9212% %
9213% X S e t C u r s o r S t a t e %
9214% %
9215% %
9216% %
9217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9218%
9219% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9220% reset to their default.
9221%
9222% The format of the XXSetCursorState method is:
9223%
9224% XSetCursorState(display,windows,const MagickStatusType state)
9225%
9226% A description of each parameter follows:
9227%
9228% o display: Specifies a connection to an X server; returned from
9229% XOpenDisplay.
9230%
9231% o windows: Specifies a pointer to a XWindows structure.
9232%
9233% o state: An unsigned integer greater than 0 sets the cursor state
9234% to busy, otherwise the cursor are reset to their default.
9235%
9236*/
cristybcbda3f2011-09-03 13:01:22 +00009237MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009238 const MagickStatusType state)
9239{
9240 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9241 assert(display != (Display *) NULL);
9242 assert(windows != (XWindows *) NULL);
9243 if (state)
9244 {
9245 (void) XCheckDefineCursor(display,windows->image.id,
9246 windows->image.busy_cursor);
9247 (void) XCheckDefineCursor(display,windows->pan.id,
9248 windows->pan.busy_cursor);
9249 (void) XCheckDefineCursor(display,windows->magnify.id,
9250 windows->magnify.busy_cursor);
9251 (void) XCheckDefineCursor(display,windows->command.id,
9252 windows->command.busy_cursor);
9253 }
9254 else
9255 {
9256 (void) XCheckDefineCursor(display,windows->image.id,
9257 windows->image.cursor);
9258 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9259 (void) XCheckDefineCursor(display,windows->magnify.id,
9260 windows->magnify.cursor);
9261 (void) XCheckDefineCursor(display,windows->command.id,
9262 windows->command.cursor);
9263 (void) XCheckDefineCursor(display,windows->command.id,
9264 windows->widget.cursor);
9265 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9266 }
9267 windows->info.mapped=MagickFalse;
9268}
9269
9270/*
9271%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9272% %
9273% %
9274% %
9275% X S e t W i n d o w s %
9276% %
9277% %
9278% %
9279%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9280%
9281% XSetWindows() sets the X windows structure if the windows info is specified.
9282% Otherwise the current windows structure is returned.
9283%
9284% The format of the XSetWindows method is:
9285%
9286% XWindows *XSetWindows(XWindows *windows_info)
9287%
9288% A description of each parameter follows:
9289%
9290% o windows_info: Initialize the Windows structure with this information.
9291%
9292*/
cristybcbda3f2011-09-03 13:01:22 +00009293MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009294{
9295 static XWindows
9296 *windows = (XWindows *) NULL;
9297
9298 if (windows_info != (XWindows *) ~0)
9299 {
9300 windows=(XWindows *) RelinquishMagickMemory(windows);
9301 windows=windows_info;
9302 }
9303 return(windows);
9304}
9305/*
9306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9307% %
9308% %
9309% %
9310% X U s e r P r e f e r e n c e s %
9311% %
9312% %
9313% %
9314%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9315%
9316% XUserPreferences() saves the preferences in a configuration file in the
9317% users' home directory.
9318%
9319% The format of the XUserPreferences method is:
9320%
9321% void XUserPreferences(XResourceInfo *resource_info)
9322%
9323% A description of each parameter follows:
9324%
9325% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9326%
9327*/
cristybcbda3f2011-09-03 13:01:22 +00009328MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009329{
9330#if defined(X11_PREFERENCES_PATH)
9331 char
9332 cache[MaxTextExtent],
9333 filename[MaxTextExtent],
9334 specifier[MaxTextExtent];
9335
9336 const char
cristy104cea82009-10-25 02:26:51 +00009337 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009338 *value;
9339
9340 XrmDatabase
9341 preferences_database;
9342
9343 /*
9344 Save user preferences to the client configuration file.
9345 */
9346 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009347 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009348 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009349 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009350 value=resource_info->backdrop ? "True" : "False";
9351 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009352 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009353 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9354 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009355 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009356 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009357 value=resource_info->confirm_exit ? "True" : "False";
9358 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009359 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009360 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009361 value=resource_info->confirm_edit ? "True" : "False";
9362 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009363 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009364 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009365 value=resource_info->display_warnings ? "True" : "False";
9366 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009367 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristycbda6112012-05-27 20:57:16 +00009368 value=resource_info->quantize_info->dither_method != NoDitherMethod ?
9369 "True" : "False";
cristy3ed852e2009-09-05 21:47:34 +00009370 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009371 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009372 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009373 value=resource_info->gamma_correct ? "True" : "False";
9374 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009375 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9376 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009377 resource_info->undo_cache);
9378 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009379 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009380 value=resource_info->use_pixmap ? "True" : "False";
9381 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009382 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009383 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009384 ExpandFilename(filename);
9385 XrmPutFileDatabase(preferences_database,filename);
9386#endif
9387}
9388
9389/*
9390%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9391% %
9392% %
9393% %
9394% X V i s u a l C l a s s N a m e %
9395% %
9396% %
9397% %
9398%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9399%
9400% XVisualClassName() returns the visual class name as a character string.
9401%
9402% The format of the XVisualClassName method is:
9403%
9404% char *XVisualClassName(const int visual_class)
9405%
9406% A description of each parameter follows:
9407%
9408% o visual_type: XVisualClassName returns the visual class as a character
9409% string.
9410%
9411% o class: Specifies the visual class.
9412%
cristy3ed852e2009-09-05 21:47:34 +00009413*/
9414static const char *XVisualClassName(const int visual_class)
9415{
9416 switch (visual_class)
9417 {
9418 case StaticGray: return("StaticGray");
9419 case GrayScale: return("GrayScale");
9420 case StaticColor: return("StaticColor");
9421 case PseudoColor: return("PseudoColor");
9422 case TrueColor: return("TrueColor");
9423 case DirectColor: return("DirectColor");
9424 }
9425 return("unknown visual class");
9426}
9427
9428/*
9429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9430% %
9431% %
9432% %
9433% X W a r n i n g %
9434% %
9435% %
9436% %
9437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9438%
9439% XWarning() displays a warning reason in a Notice widget.
9440%
9441% The format of the XWarning method is:
9442%
9443% void XWarning(const unsigned int warning,const char *reason,
9444% const char *description)
9445%
9446% A description of each parameter follows:
9447%
9448% o warning: Specifies the numeric warning category.
9449%
9450% o reason: Specifies the reason to display before terminating the
9451% program.
9452%
9453% o description: Specifies any description to the reason.
9454%
9455*/
cristybcbda3f2011-09-03 13:01:22 +00009456MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009457 const char *reason,const char *description)
9458{
9459 char
9460 text[MaxTextExtent];
9461
9462 XWindows
9463 *windows;
9464
9465 if (reason == (char *) NULL)
9466 return;
9467 (void) CopyMagickString(text,reason,MaxTextExtent);
9468 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9469 windows=XSetWindows((XWindows *) ~0);
9470 XNoticeWidget(windows->display,windows,text,(char *) description);
9471}
9472
9473/*
9474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9475% %
9476% %
9477% %
9478% X W i n d o w B y I D %
9479% %
9480% %
9481% %
9482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9483%
9484% XWindowByID() locates a child window with a given ID. If not window with
9485% the given name is found, 0 is returned. Only the window specified and its
9486% subwindows are searched.
9487%
9488% The format of the XWindowByID function is:
9489%
9490% child=XWindowByID(display,window,id)
9491%
9492% A description of each parameter follows:
9493%
9494% o child: XWindowByID returns the window with the specified
9495% id. If no windows are found, XWindowByID returns 0.
9496%
9497% o display: Specifies a pointer to the Display structure; returned from
9498% XOpenDisplay.
9499%
9500% o id: Specifies the id of the window to locate.
9501%
9502*/
cristybcbda3f2011-09-03 13:01:22 +00009503MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009504 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009505{
9506 RectangleInfo
9507 rectangle_info;
9508
9509 register int
9510 i;
9511
9512 Status
9513 status;
9514
9515 unsigned int
9516 number_children;
9517
9518 Window
9519 child,
9520 *children,
9521 window;
9522
9523 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9524 assert(display != (Display *) NULL);
9525 assert(root_window != (Window) NULL);
9526 if (id == 0)
9527 return(XSelectWindow(display,&rectangle_info));
9528 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009529 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009530 status=XQueryTree(display,root_window,&child,&child,&children,
9531 &number_children);
9532 if (status == False)
9533 return((Window) NULL);
9534 window=(Window) NULL;
9535 for (i=0; i < (int) number_children; i++)
9536 {
9537 /*
9538 Search each child and their children.
9539 */
9540 window=XWindowByID(display,children[i],id);
9541 if (window != (Window) NULL)
9542 break;
9543 }
9544 if (children != (Window *) NULL)
9545 (void) XFree((void *) children);
9546 return(window);
9547}
9548
9549/*
9550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9551% %
9552% %
9553% %
9554% X W i n d o w B y N a m e %
9555% %
9556% %
9557% %
9558%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9559%
9560% XWindowByName() locates a window with a given name on a display. If no
9561% window with the given name is found, 0 is returned. If more than one window
9562% has the given name, the first one is returned. Only root and its children
9563% are searched.
9564%
9565% The format of the XWindowByName function is:
9566%
9567% window=XWindowByName(display,root_window,name)
9568%
9569% A description of each parameter follows:
9570%
9571% o window: XWindowByName returns the window id.
9572%
9573% o display: Specifies a pointer to the Display structure; returned from
9574% XOpenDisplay.
9575%
9576% o root_window: Specifies the id of the root window.
9577%
9578% o name: Specifies the name of the window to locate.
9579%
9580*/
cristybcbda3f2011-09-03 13:01:22 +00009581MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009582 const char *name)
9583{
9584 register int
9585 i;
9586
9587 Status
9588 status;
9589
9590 unsigned int
9591 number_children;
9592
9593 Window
9594 *children,
9595 child,
9596 window;
9597
9598 XTextProperty
9599 window_name;
9600
9601 assert(display != (Display *) NULL);
9602 assert(root_window != (Window) NULL);
9603 assert(name != (char *) NULL);
9604 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9605 if (XGetWMName(display,root_window,&window_name) != 0)
9606 if (LocaleCompare((char *) window_name.value,name) == 0)
9607 return(root_window);
9608 status=XQueryTree(display,root_window,&child,&child,&children,
9609 &number_children);
9610 if (status == False)
9611 return((Window) NULL);
9612 window=(Window) NULL;
9613 for (i=0; i < (int) number_children; i++)
9614 {
9615 /*
9616 Search each child and their children.
9617 */
9618 window=XWindowByName(display,children[i],name);
9619 if (window != (Window) NULL)
9620 break;
9621 }
9622 if (children != (Window *) NULL)
9623 (void) XFree((void *) children);
9624 return(window);
9625}
9626
9627/*
9628%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9629% %
9630% %
9631% %
9632% X W i n d o w B y P r o p e r y %
9633% %
9634% %
9635% %
9636%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9637%
9638% XWindowByProperty() locates a child window with a given property. If not
9639% window with the given name is found, 0 is returned. If more than one window
9640% has the given property, the first one is returned. Only the window
9641% specified and its subwindows are searched.
9642%
9643% The format of the XWindowByProperty function is:
9644%
9645% child=XWindowByProperty(display,window,property)
9646%
9647% A description of each parameter follows:
9648%
9649% o child: XWindowByProperty returns the window id with the specified
9650% property. If no windows are found, XWindowByProperty returns 0.
9651%
9652% o display: Specifies a pointer to the Display structure; returned from
9653% XOpenDisplay.
9654%
9655% o property: Specifies the property of the window to locate.
9656%
9657*/
cristybcbda3f2011-09-03 13:01:22 +00009658MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009659 const Atom property)
9660{
9661 Atom
9662 type;
9663
9664 int
9665 format;
9666
9667 Status
9668 status;
9669
9670 unsigned char
9671 *data;
9672
9673 unsigned int
9674 i,
9675 number_children;
9676
cristyf2faecf2010-05-28 19:19:36 +00009677 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009678 after,
9679 number_items;
9680
9681 Window
9682 child,
9683 *children,
9684 parent,
9685 root;
9686
9687 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9688 assert(display != (Display *) NULL);
9689 assert(window != (Window) NULL);
9690 assert(property != (Atom) NULL);
9691 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9692 if (status == False)
9693 return((Window) NULL);
9694 type=(Atom) NULL;
9695 child=(Window) NULL;
9696 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9697 {
9698 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9699 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9700 if (data != NULL)
9701 (void) XFree((void *) data);
9702 if ((status == Success) && (type != (Atom) NULL))
9703 child=children[i];
9704 }
9705 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9706 child=XWindowByProperty(display,children[i],property);
9707 if (children != (Window *) NULL)
9708 (void) XFree((void *) children);
9709 return(child);
9710}
9711#else
9712
9713/*
9714%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9715% %
9716% %
9717% %
9718% X I m p o r t I m a g e %
9719% %
9720% %
9721% %
9722%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9723%
9724% XImportImage() reads an image from an X window.
9725%
9726% The format of the XImportImage method is:
9727%
cristya0dc96a2011-12-19 23:58:54 +00009728% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
9729% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009730%
9731% A description of each parameter follows:
9732%
9733% o image_info: the image info..
9734%
9735% o ximage_info: Specifies a pointer to an XImportInfo structure.
9736%
cristya0dc96a2011-12-19 23:58:54 +00009737% o exception: return any errors or warnings in this structure.
9738%
cristy3ed852e2009-09-05 21:47:34 +00009739*/
cristybcbda3f2011-09-03 13:01:22 +00009740MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristya0dc96a2011-12-19 23:58:54 +00009741 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00009742{
9743 assert(image_info != (const ImageInfo *) NULL);
9744 assert(image_info->signature == MagickSignature);
9745 if (image_info->debug != MagickFalse)
9746 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9747 image_info->filename);
9748 assert(ximage_info != (XImportInfo *) NULL);
cristya0dc96a2011-12-19 23:58:54 +00009749 assert(exception != (ExceptionInfo *) NULL);
9750 assert(exception->signature == MagickSignature);
cristy3ed852e2009-09-05 21:47:34 +00009751 return((Image *) NULL);
9752}
9753#endif
9754
9755/*
9756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9757% %
9758% %
9759% %
cristy576974e2009-10-25 20:45:31 +00009760+ X C o m p o n e n t G e n e s i s %
9761% %
9762% %
9763% %
9764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9765%
9766% XComponentGenesis() instantiates the X component.
9767%
9768% The format of the XComponentGenesis method is:
9769%
9770% MagickBooleanType XComponentGenesis(void)
9771%
9772*/
cristy5ff4eaf2011-09-03 01:38:02 +00009773MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009774{
9775 return(MagickTrue);
9776}
9777
9778/*
9779%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9780% %
9781% %
9782% %
cristy3ed852e2009-09-05 21:47:34 +00009783% X G e t I m p o r t I n f o %
9784% %
9785% %
9786% %
9787%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9788%
9789% XGetImportInfo() initializes the XImportInfo structure.
9790%
9791% The format of the XGetImportInfo method is:
9792%
9793% void XGetImportInfo(XImportInfo *ximage_info)
9794%
9795% A description of each parameter follows:
9796%
9797% o ximage_info: Specifies a pointer to an ImageInfo structure.
9798%
9799*/
9800MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9801{
9802 assert(ximage_info != (XImportInfo *) NULL);
9803 ximage_info->frame=MagickFalse;
9804 ximage_info->borders=MagickFalse;
9805 ximage_info->screen=MagickFalse;
9806 ximage_info->descend=MagickTrue;
9807 ximage_info->silent=MagickFalse;
9808}