blob: 1f9000d0f7c72a9e6ca9736e6266cc0d11c7103c [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% %
cristy7e41fe82010-12-04 23:12:08 +000020% Copyright 1999-2011 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"
52#include "MagickCore/display.h"
53#include "MagickCore/exception.h"
54#include "MagickCore/exception-private.h"
55#include "MagickCore/geometry.h"
56#include "MagickCore/identify.h"
57#include "MagickCore/image.h"
58#include "MagickCore/image-private.h"
59#include "MagickCore/list.h"
60#include "MagickCore/locale_.h"
61#include "MagickCore/log.h"
62#include "MagickCore/magick.h"
63#include "MagickCore/memory_.h"
64#include "MagickCore/monitor.h"
65#include "MagickCore/option.h"
66#include "MagickCore/pixel-accessor.h"
67#include "MagickCore/PreRvIcccm.h"
68#include "MagickCore/quantize.h"
69#include "MagickCore/quantum.h"
70#include "MagickCore/quantum-private.h"
71#include "MagickCore/resource_.h"
72#include "MagickCore/resize.h"
73#include "MagickCore/shear.h"
74#include "MagickCore/statistic.h"
75#include "MagickCore/string_.h"
76#include "MagickCore/string-private.h"
77#include "MagickCore/transform.h"
78#include "MagickCore/utility.h"
79#include "MagickCore/widget.h"
80#include "MagickCore/xwindow.h"
81#include "MagickCore/xwindow-private.h"
82#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000083#if defined(__BEOS__)
84#include <OS.h>
85#endif
86#if defined(MAGICKCORE_X11_DELEGATE)
87#include <X11/Xproto.h>
88#include <X11/Xlocale.h>
89#if defined(MAGICK_HAVE_POLL)
90# include <sys/poll.h>
91#endif
92#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
93#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
94# include <machine/param.h>
95#endif
96#include <sys/ipc.h>
97#include <sys/shm.h>
98#include <X11/extensions/XShm.h>
99#endif
100#if defined(MAGICKCORE_HAVE_SHAPE)
101#include <X11/extensions/shape.h>
102#endif
103
104/*
105 X defines.
106*/
cristyce70c172010-01-07 17:15:30 +0000107#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000108 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
109 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000110#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000111 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
112 map->red_mult)+ \
113 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
114 map->green_mult)+ \
115 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
116 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000117#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
118 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
119 map->red_mult)+ \
120 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
121 map->green_mult)+ \
122 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
123 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000124#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000125 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
126 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000127#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000128 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
129 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000130#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000131 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
132 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
133 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000134
135#define AccentuateModulate ScaleCharToQuantum(80)
136#define HighlightModulate ScaleCharToQuantum(125)
137#define ShadowModulate ScaleCharToQuantum(135)
138#define DepthModulate ScaleCharToQuantum(185)
139#define TroughModulate ScaleCharToQuantum(110)
140
141#define XLIB_ILLEGAL_ACCESS 1
142#undef ForgetGravity
143#undef NorthWestGravity
144#undef NorthGravity
145#undef NorthEastGravity
146#undef WestGravity
147#undef CenterGravity
148#undef EastGravity
149#undef SouthWestGravity
150#undef SouthGravity
151#undef SouthEastGravity
152#undef StaticGravity
153
154#undef index
155#if defined(hpux9)
156#define XFD_SET int
157#else
158#define XFD_SET fd_set
159#endif
160
161/*
162 Enumeration declarations.
163*/
164typedef enum
165{
166#undef DoRed
167 DoRed = 0x0001,
168#undef DoGreen
169 DoGreen = 0x0002,
170#undef DoBlue
171 DoBlue = 0x0004,
172 DoMatte = 0x0008
173} XColorFlags;
174
175/*
176 Typedef declarations.
177*/
178typedef struct _DiversityPacket
179{
180 Quantum
181 red,
182 green,
183 blue;
184
185 unsigned short
186 index;
187
cristybb503372010-05-27 20:51:26 +0000188 size_t
cristy3ed852e2009-09-05 21:47:34 +0000189 count;
190} DiversityPacket;
191
192/*
193 Constant declaractions.
194*/
195static MagickBooleanType
196 xerror_alert = MagickFalse;
197
198/*
199 Method prototypes.
200*/
201static const char
202 *XVisualClassName(const int);
203
204static MagickRealType
205 blue_gamma = 1.0,
206 green_gamma = 1.0,
207 red_gamma = 1.0;
208
209static MagickBooleanType
210 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
211
212static void
213 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
214 XImage *,XImage *),
215 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
216 XImage *,XImage *);
217
218static Window
219 XSelectWindow(Display *,RectangleInfo *);
220
221/*
222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223% %
224% %
225% %
226% D e s t r o y X R e s o u r c e s %
227% %
228% %
229% %
230%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231%
232% DestroyXResources() destroys any X resources.
233%
234% The format of the DestroyXResources method is:
235%
236% void DestroyXResources()
237%
238% A description of each parameter follows:
239%
240*/
241MagickExport void DestroyXResources(void)
242{
243 register int
244 i;
245
246 unsigned int
247 number_windows;
248
249 XWindowInfo
250 *magick_windows[MaxXWindows];
251
252 XWindows
253 *windows;
254
255 DestroyXWidget();
256 windows=XSetWindows((XWindows *) ~0);
257 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
258 return;
259 number_windows=0;
260 magick_windows[number_windows++]=(&windows->context);
261 magick_windows[number_windows++]=(&windows->group_leader);
262 magick_windows[number_windows++]=(&windows->backdrop);
263 magick_windows[number_windows++]=(&windows->icon);
264 magick_windows[number_windows++]=(&windows->image);
265 magick_windows[number_windows++]=(&windows->info);
266 magick_windows[number_windows++]=(&windows->magnify);
267 magick_windows[number_windows++]=(&windows->pan);
268 magick_windows[number_windows++]=(&windows->command);
269 magick_windows[number_windows++]=(&windows->widget);
270 magick_windows[number_windows++]=(&windows->popup);
271 magick_windows[number_windows++]=(&windows->context);
272 for (i=0; i < (int) number_windows; i++)
273 {
274 if (magick_windows[i]->mapped != MagickFalse)
275 {
276 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
277 magick_windows[i]->screen);
278 magick_windows[i]->mapped=MagickFalse;
279 }
280 if (magick_windows[i]->name != (char *) NULL)
281 magick_windows[i]->name=(char *)
282 RelinquishMagickMemory(magick_windows[i]->name);
283 if (magick_windows[i]->icon_name != (char *) NULL)
284 magick_windows[i]->icon_name=(char *)
285 RelinquishMagickMemory(magick_windows[i]->icon_name);
286 if (magick_windows[i]->cursor != (Cursor) NULL)
287 {
288 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
289 magick_windows[i]->cursor=(Cursor) NULL;
290 }
291 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
292 {
293 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
294 magick_windows[i]->busy_cursor=(Cursor) NULL;
295 }
296 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
297 {
298 (void) XFreePixmap(windows->display,
299 magick_windows[i]->highlight_stipple);
300 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
301 }
302 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
303 {
304 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
305 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
306 }
307 if (magick_windows[i]->ximage != (XImage *) NULL)
308 {
309 XDestroyImage(magick_windows[i]->ximage);
310 magick_windows[i]->ximage=(XImage *) NULL;
311 }
312 if (magick_windows[i]->pixmap != (Pixmap) NULL)
313 {
314 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
315 magick_windows[i]->pixmap=(Pixmap) NULL;
316 }
317 if (magick_windows[i]->id != (Window) NULL)
318 {
319 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
320 magick_windows[i]->id=(Window) NULL;
321 }
322 if (magick_windows[i]->destroy != MagickFalse)
323 {
324 if (magick_windows[i]->image != (Image *) NULL)
325 {
326 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
327 magick_windows[i]->image=NewImageList();
328 }
329 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
330 {
331 (void) XFreePixmap(windows->display,
332 magick_windows[i]->matte_pixmap);
333 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
334 }
335 }
336 if (magick_windows[i]->segment_info != (void *) NULL)
337 {
338#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
339 XShmSegmentInfo
340 *segment_info;
341
342 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
343 if (segment_info != (XShmSegmentInfo *) NULL)
344 if (segment_info[0].shmid >= 0)
345 {
346 if (segment_info[0].shmaddr != NULL)
347 (void) shmdt(segment_info[0].shmaddr);
348 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
349 segment_info[0].shmaddr=NULL;
350 segment_info[0].shmid=(-1);
351 }
352#endif
353 magick_windows[i]->segment_info=(void *)
354 RelinquishMagickMemory(magick_windows[i]->segment_info);
355 }
356 }
357 windows->icon_resources=(XResourceInfo *)
358 RelinquishMagickMemory(windows->icon_resources);
359 if (windows->icon_pixel != (XPixelInfo *) NULL)
360 {
cristyf2faecf2010-05-28 19:19:36 +0000361 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
362 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000363 RelinquishMagickMemory(windows->icon_pixel->pixels);
364 if (windows->icon_pixel->annotate_context != (GC) NULL)
365 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
366 windows->icon_pixel=(XPixelInfo *)
367 RelinquishMagickMemory(windows->icon_pixel);
368 }
369 if (windows->pixel_info != (XPixelInfo *) NULL)
370 {
cristyf2faecf2010-05-28 19:19:36 +0000371 if (windows->pixel_info->pixels != (unsigned long *) NULL)
372 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000373 RelinquishMagickMemory(windows->pixel_info->pixels);
374 if (windows->pixel_info->annotate_context != (GC) NULL)
375 XFreeGC(windows->display,windows->pixel_info->annotate_context);
376 if (windows->pixel_info->widget_context != (GC) NULL)
377 XFreeGC(windows->display,windows->pixel_info->widget_context);
378 if (windows->pixel_info->highlight_context != (GC) NULL)
379 XFreeGC(windows->display,windows->pixel_info->highlight_context);
380 windows->pixel_info=(XPixelInfo *)
381 RelinquishMagickMemory(windows->pixel_info);
382 }
383 if (windows->font_info != (XFontStruct *) NULL)
384 {
385 XFreeFont(windows->display,windows->font_info);
386 windows->font_info=(XFontStruct *) NULL;
387 }
388 if (windows->class_hints != (XClassHint *) NULL)
389 {
390 if (windows->class_hints->res_name != (char *) NULL)
391 XFree(windows->class_hints->res_name);
392 if (windows->class_hints->res_class != (char *) NULL)
393 XFree(windows->class_hints->res_class);
394 XFree(windows->class_hints);
395 windows->class_hints=(XClassHint *) NULL;
396 }
397 if (windows->manager_hints != (XWMHints *) NULL)
398 {
399 XFree(windows->manager_hints);
400 windows->manager_hints=(XWMHints *) NULL;
401 }
402 if (windows->map_info != (XStandardColormap *) NULL)
403 {
404 XFree(windows->map_info);
405 windows->map_info=(XStandardColormap *) NULL;
406 }
407 if (windows->icon_map != (XStandardColormap *) NULL)
408 {
409 XFree(windows->icon_map);
410 windows->icon_map=(XStandardColormap *) NULL;
411 }
412 if (windows->visual_info != (XVisualInfo *) NULL)
413 {
414 XFree(windows->visual_info);
415 windows->visual_info=(XVisualInfo *) NULL;
416 }
417 if (windows->icon_visual != (XVisualInfo *) NULL)
418 {
419 XFree(windows->icon_visual);
420 windows->icon_visual=(XVisualInfo *) NULL;
421 }
422 (void) XSetWindows((XWindows *) NULL);
423}
424
425/*
426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427% %
428% %
429% %
430% X A n n o t a t e I m a g e %
431% %
432% %
433% %
434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435%
436% XAnnotateImage() annotates the image with text.
437%
438% The format of the XAnnotateImage method is:
439%
440% MagickBooleanType XAnnotateImage(Display *display,
441% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
442%
443% A description of each parameter follows:
444%
445% o display: Specifies a connection to an X server; returned from
446% XOpenDisplay.
447%
448% o pixel: Specifies a pointer to a XPixelInfo structure.
449%
450% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
451%
452% o image: the image.
453%
454*/
455MagickExport MagickBooleanType XAnnotateImage(Display *display,
456 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
457{
cristyc57f6942010-11-12 01:47:39 +0000458 CacheView
459 *annotate_view;
460
cristy3ed852e2009-09-05 21:47:34 +0000461 GC
462 annotate_context;
463
464 ExceptionInfo
465 *exception;
466
467 Image
468 *annotate_image;
469
470 int
471 x,
472 y;
473
474 MagickBooleanType
475 matte;
476
477 Pixmap
478 annotate_pixmap;
479
480 unsigned int
481 depth,
482 height,
483 width;
484
485 Window
486 root_window;
487
488 XGCValues
489 context_values;
490
491 XImage
492 *annotate_ximage;
493
494 /*
495 Initialize annotated image.
496 */
497 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
498 assert(display != (Display *) NULL);
499 assert(pixel != (XPixelInfo *) NULL);
500 assert(annotate_info != (XAnnotateInfo *) NULL);
501 assert(image != (Image *) NULL);
502 /*
503 Initialize annotated pixmap.
504 */
505 root_window=XRootWindow(display,XDefaultScreen(display));
506 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
507 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
508 annotate_info->height,depth);
509 if (annotate_pixmap == (Pixmap) NULL)
510 return(MagickFalse);
511 /*
512 Initialize graphics info.
513 */
514 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000515 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000516 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000517 annotate_context=XCreateGC(display,root_window,(unsigned long)
518 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000519 if (annotate_context == (GC) NULL)
520 return(MagickFalse);
521 /*
522 Draw text to pixmap.
523 */
524 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
525 (int) annotate_info->font_info->ascent,annotate_info->text,
526 (int) strlen(annotate_info->text));
527 (void) XFreeGC(display,annotate_context);
528 /*
529 Initialize annotated X image.
530 */
531 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
532 annotate_info->height,AllPlanes,ZPixmap);
533 if (annotate_ximage == (XImage *) NULL)
534 return(MagickFalse);
535 (void) XFreePixmap(display,annotate_pixmap);
536 /*
537 Initialize annotated image.
538 */
539 annotate_image=AcquireImage((ImageInfo *) NULL);
540 if (annotate_image == (Image *) NULL)
541 return(MagickFalse);
542 annotate_image->columns=annotate_info->width;
543 annotate_image->rows=annotate_info->height;
544 /*
545 Transfer annotated X image to image.
546 */
547 width=(unsigned int) image->columns;
548 height=(unsigned int) image->rows;
549 x=0;
550 y=0;
551 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +0000552 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
553 &annotate_image->background_color,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +0000554 if (annotate_info->stencil == ForegroundStencil)
555 annotate_image->matte=MagickTrue;
556 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +0000557 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000558 for (y=0; y < (int) annotate_image->rows; y++)
559 {
cristyc57f6942010-11-12 01:47:39 +0000560 register int
cristy3ed852e2009-09-05 21:47:34 +0000561 x;
562
cristy4c08aed2011-07-01 19:47:50 +0000563 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000564 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000565
cristyc57f6942010-11-12 01:47:39 +0000566 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
567 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000568 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000569 break;
cristyc57f6942010-11-12 01:47:39 +0000570 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000571 {
cristy4c08aed2011-07-01 19:47:50 +0000572 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000573 if (XGetPixel(annotate_ximage,x,y) == 0)
574 {
575 /*
576 Set this pixel to the background color.
577 */
cristy4c08aed2011-07-01 19:47:50 +0000578 SetPixelRed(annotate_image,ScaleShortToQuantum(
579 pixel->box_color.red),q);
580 SetPixelGreen(annotate_image,ScaleShortToQuantum(
581 pixel->box_color.green),q);
582 SetPixelBlue(annotate_image,ScaleShortToQuantum(
583 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000584 if ((annotate_info->stencil == ForegroundStencil) ||
585 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000586 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000587 }
588 else
589 {
590 /*
591 Set this pixel to the pen color.
592 */
cristy4c08aed2011-07-01 19:47:50 +0000593 SetPixelRed(annotate_image,ScaleShortToQuantum(
594 pixel->pen_color.red),q);
595 SetPixelGreen(annotate_image,ScaleShortToQuantum(
596 pixel->pen_color.green),q);
597 SetPixelBlue(annotate_image,ScaleShortToQuantum(
598 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000599 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000600 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000601 }
cristyed231572011-07-14 02:18:59 +0000602 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000603 }
cristyc57f6942010-11-12 01:47:39 +0000604 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000605 break;
606 }
cristyc57f6942010-11-12 01:47:39 +0000607 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000608 XDestroyImage(annotate_ximage);
609 /*
610 Determine annotate geometry.
611 */
612 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
613 if ((width != (unsigned int) annotate_image->columns) ||
614 (height != (unsigned int) annotate_image->rows))
615 {
616 char
617 image_geometry[MaxTextExtent];
618
619 /*
620 Scale image.
621 */
cristyb51dff52011-05-19 16:55:47 +0000622 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000623 width,height);
624 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
625 }
626 if (annotate_info->degrees != 0.0)
627 {
628 Image
629 *rotate_image;
630
631 int
632 rotations;
633
634 MagickRealType
635 normalized_degrees;
636
637 /*
638 Rotate image.
639 */
640 rotate_image=
641 RotateImage(annotate_image,annotate_info->degrees,&image->exception);
642 if (rotate_image == (Image *) NULL)
643 return(MagickFalse);
644 annotate_image=DestroyImage(annotate_image);
645 annotate_image=rotate_image;
646 /*
647 Annotation is relative to the degree of rotation.
648 */
649 normalized_degrees=annotate_info->degrees;
650 while (normalized_degrees < -45.0)
651 normalized_degrees+=360.0;
652 for (rotations=0; normalized_degrees > 45.0; rotations++)
653 normalized_degrees-=90.0;
654 switch (rotations % 4)
655 {
656 default:
657 case 0:
658 break;
659 case 1:
660 {
661 /*
662 Rotate 90 degrees.
663 */
664 x-=(int) annotate_image->columns/2;
665 y+=(int) annotate_image->columns/2;
666 break;
667 }
668 case 2:
669 {
670 /*
671 Rotate 180 degrees.
672 */
673 x=x-(int) annotate_image->columns;
674 break;
675 }
676 case 3:
677 {
678 /*
679 Rotate 270 degrees.
680 */
681 x=x-(int) annotate_image->columns/2;
682 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
683 break;
684 }
685 }
686 }
687 /*
688 Composite text onto the image.
689 */
690 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
691 matte=image->matte;
692 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristyc57f6942010-11-12 01:47:39 +0000693 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +0000694 image->matte=matte;
695 annotate_image=DestroyImage(annotate_image);
696 return(MagickTrue);
697}
698
699/*
700%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
701% %
702% %
703% %
704% X B e s t F o n t %
705% %
706% %
707% %
708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
709%
710% XBestFont() returns the "best" font. "Best" is defined as a font specified
711% in the X resource database or a font such that the text width displayed
712% with the font does not exceed the specified maximum width.
713%
714% The format of the XBestFont method is:
715%
716% XFontStruct *XBestFont(Display *display,
717% const XResourceInfo *resource_info,const MagickBooleanType text_font)
718%
719% A description of each parameter follows:
720%
721% o font: XBestFont returns a pointer to a XFontStruct structure.
722%
723% o display: Specifies a connection to an X server; returned from
724% XOpenDisplay.
725%
726% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
727%
728% o text_font: True is font should be mono-spaced (typewriter style).
729%
cristy3ed852e2009-09-05 21:47:34 +0000730*/
731
732static char **FontToList(char *font)
733{
734 char
735 **fontlist;
736
737 register char
738 *p,
739 *q;
740
741 register int
742 i;
743
744 unsigned int
745 fonts;
746
747 if (font == (char *) NULL)
748 return((char **) NULL);
749 /*
750 Convert string to an ASCII list.
751 */
752 fonts=1U;
753 for (p=font; *p != '\0'; p++)
754 if ((*p == ':') || (*p == ';') || (*p == ','))
755 fonts++;
756 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
757 if (fontlist == (char **) NULL)
758 {
759 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
760 font);
761 return((char **) NULL);
762 }
763 p=font;
764 for (i=0; i < (int) fonts; i++)
765 {
766 for (q=p; *q != '\0'; q++)
767 if ((*q == ':') || (*q == ';') || (*q == ','))
768 break;
769 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
770 sizeof(*fontlist[i]));
771 if (fontlist[i] == (char *) NULL)
772 {
773 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
774 font);
775 return((char **) NULL);
776 }
777 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
778 p=q+1;
779 }
780 fontlist[i]=(char *) NULL;
781 return(fontlist);
782}
783
784MagickExport XFontStruct *XBestFont(Display *display,
785 const XResourceInfo *resource_info,const MagickBooleanType text_font)
786{
787 static const char
788 *Fonts[]=
789 {
790 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
791 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
792 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
793 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
794 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
795 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
796 "variable",
797 "fixed",
798 (char *) NULL
799 },
800 *TextFonts[]=
801 {
802 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
803 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
804 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
805 "fixed",
806 (char *) NULL
807 };
808
809 char
810 *font_name;
811
812 register const char
813 **p;
814
815 XFontStruct
816 *font_info;
817
818 font_info=(XFontStruct *) NULL;
819 font_name=resource_info->font;
820 if (text_font != MagickFalse)
821 font_name=resource_info->text_font;
822 if ((font_name != (char *) NULL) && (*font_name != '\0'))
823 {
824 char
825 **fontlist;
826
827 register int
828 i;
829
830 /*
831 Load preferred font specified in the X resource database.
832 */
833 fontlist=FontToList(font_name);
834 if (fontlist != (char **) NULL)
835 {
836 for (i=0; fontlist[i] != (char *) NULL; i++)
837 {
838 if (font_info == (XFontStruct *) NULL)
839 font_info=XLoadQueryFont(display,fontlist[i]);
840 fontlist[i]=DestroyString(fontlist[i]);
841 }
842 fontlist=(char **) RelinquishMagickMemory(fontlist);
843 }
844 if (font_info == (XFontStruct *) NULL)
845 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
846 }
847 /*
848 Load fonts from list of fonts until one is found.
849 */
850 p=Fonts;
851 if (text_font != MagickFalse)
852 p=TextFonts;
853 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
854 p++;
855 while (*p != (char *) NULL)
856 {
857 if (font_info != (XFontStruct *) NULL)
858 break;
859 font_info=XLoadQueryFont(display,(char *) *p);
860 p++;
861 }
862 return(font_info);
863}
864
865/*
866%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
867% %
868% %
869% %
870% X B e s t I c o n S i z e %
871% %
872% %
873% %
874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875%
876% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
877% size that maintains the aspect ratio of the image. If the window manager
878% has preferred icon sizes, one of the preferred sizes is used.
879%
880% The format of the XBestIconSize method is:
881%
882% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
883%
884% A description of each parameter follows:
885%
886% o display: Specifies a connection to an X server; returned from
887% XOpenDisplay.
888%
889% o image: the image.
890%
891*/
892MagickExport void XBestIconSize(Display *display,XWindowInfo *window,
893 Image *image)
894{
895 int
896 i,
897 number_sizes;
898
899 MagickRealType
900 scale_factor;
901
902 unsigned int
903 height,
904 icon_height,
905 icon_width,
906 width;
907
908 Window
909 root_window;
910
911 XIconSize
912 *icon_size,
913 *size_list;
914
915 /*
916 Determine if the window manager has specified preferred icon sizes.
917 */
918 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
919 assert(display != (Display *) NULL);
920 assert(window != (XWindowInfo *) NULL);
921 assert(image != (Image *) NULL);
922 window->width=MaxIconSize;
923 window->height=MaxIconSize;
924 icon_size=(XIconSize *) NULL;
925 number_sizes=0;
926 root_window=XRootWindow(display,window->screen);
927 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
928 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
929 icon_size=size_list;
930 if (icon_size == (XIconSize *) NULL)
931 {
932 /*
933 Window manager does not restrict icon size.
934 */
935 icon_size=XAllocIconSize();
936 if (icon_size == (XIconSize *) NULL)
937 {
938 ThrowXWindowFatalException(ResourceLimitError,
939 "MemoryAllocationFailed",image->filename);
940 return;
941 }
942 icon_size->min_width=1;
943 icon_size->max_width=MaxIconSize;
944 icon_size->min_height=1;
945 icon_size->max_height=MaxIconSize;
946 icon_size->width_inc=1;
947 icon_size->height_inc=1;
948 }
949 /*
950 Determine aspect ratio of image.
951 */
952 width=(unsigned int) image->columns;
953 height=(unsigned int) image->rows;
954 i=0;
955 if (window->crop_geometry)
956 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
957 /*
958 Look for an icon size that maintains the aspect ratio of image.
959 */
960 scale_factor=(MagickRealType) icon_size->max_width/width;
961 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
962 scale_factor=(MagickRealType) icon_size->max_height/height;
963 icon_width=(unsigned int) icon_size->min_width;
964 while ((int) icon_width < icon_size->max_width)
965 {
966 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
967 break;
968 icon_width+=icon_size->width_inc;
969 }
970 icon_height=(unsigned int) icon_size->min_height;
971 while ((int) icon_height < icon_size->max_height)
972 {
973 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
974 break;
975 icon_height+=icon_size->height_inc;
976 }
977 (void) XFree((void *) icon_size);
978 window->width=icon_width;
979 window->height=icon_height;
980}
981
982/*
983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
984% %
985% %
986% %
987% X B e s t P i x e l %
988% %
989% %
990% %
991%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992%
993% XBestPixel() returns a pixel from an array of pixels that is closest to the
994% requested color. If the color array is NULL, the colors are obtained from
995% the X server.
996%
997% The format of the XBestPixel method is:
998%
999% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1000% unsigned int number_colors,XColor *color)
1001%
1002% A description of each parameter follows:
1003%
1004% o pixel: XBestPixel returns the pixel value closest to the requested
1005% color.
1006%
1007% o display: Specifies a connection to an X server; returned from
1008% XOpenDisplay.
1009%
1010% o colormap: Specifies the ID of the X server colormap.
1011%
1012% o colors: Specifies an array of XColor structures.
1013%
1014% o number_colors: Specifies the number of XColor structures in the
1015% color definition array.
1016%
1017% o color: Specifies the desired RGB value to find in the colors array.
1018%
1019*/
1020MagickExport void XBestPixel(Display *display,const Colormap colormap,
1021 XColor *colors,unsigned int number_colors,XColor *color)
1022{
1023 MagickBooleanType
1024 query_server;
1025
cristy4c08aed2011-07-01 19:47:50 +00001026 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001027 pixel;
1028
1029 MagickRealType
1030 min_distance;
1031
1032 register MagickRealType
1033 distance;
1034
1035 register int
1036 i,
1037 j;
1038
1039 Status
1040 status;
1041
1042 /*
1043 Find closest representation for the requested RGB color.
1044 */
1045 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1046 assert(display != (Display *) NULL);
1047 assert(color != (XColor *) NULL);
1048 status=XAllocColor(display,colormap,color);
1049 if (status != False)
1050 return;
1051 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1052 if (query_server != MagickFalse)
1053 {
1054 /*
1055 Read X server colormap.
1056 */
1057 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1058 if (colors == (XColor *) NULL)
1059 {
1060 ThrowXWindowFatalException(ResourceLimitError,
1061 "MemoryAllocationFailed","...");
1062 return;
1063 }
1064 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001065 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001066 if (number_colors > 256)
1067 number_colors=256;
1068 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1069 }
1070 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1071 QuantumRange+1.0);
1072 j=0;
1073 for (i=0; i < (int) number_colors; i++)
1074 {
1075 pixel.red=colors[i].red-(MagickRealType) color->red;
1076 distance=pixel.red*pixel.red;
1077 if (distance > min_distance)
1078 continue;
1079 pixel.green=colors[i].green-(MagickRealType) color->green;
1080 distance+=pixel.green*pixel.green;
1081 if (distance > min_distance)
1082 continue;
1083 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1084 distance+=pixel.blue*pixel.blue;
1085 if (distance > min_distance)
1086 continue;
1087 min_distance=distance;
1088 color->pixel=colors[i].pixel;
1089 j=i;
1090 }
1091 (void) XAllocColor(display,colormap,&colors[j]);
1092 if (query_server != MagickFalse)
1093 colors=(XColor *) RelinquishMagickMemory(colors);
1094}
1095
1096/*
1097%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1098% %
1099% %
1100% %
1101% X B e s t V i s u a l I n f o %
1102% %
1103% %
1104% %
1105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1106%
1107% XBestVisualInfo() returns visual information for a visual that is the "best"
1108% the server supports. "Best" is defined as:
1109%
1110% 1. Restrict the visual list to those supported by the default screen.
1111%
1112% 2. If a visual type is specified, restrict the visual list to those of
1113% that type.
1114%
1115% 3. If a map type is specified, choose the visual that matches the id
1116% specified by the Standard Colormap.
1117%
1118% 4 From the list of visuals, choose one that can display the most
1119% simultaneous colors. If more than one visual can display the same
1120% number of simultaneous colors, one is chosen based on a rank.
1121%
1122% The format of the XBestVisualInfo method is:
1123%
1124% XVisualInfo *XBestVisualInfo(Display *display,
1125% XStandardColormap *map_info,XResourceInfo *resource_info)
1126%
1127% A description of each parameter follows:
1128%
1129% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1130% structure.
1131%
1132% o display: Specifies a connection to an X server; returned from
1133% XOpenDisplay.
1134%
1135% o map_info: If map_type is specified, this structure is initialized
1136% with info from the Standard Colormap.
1137%
1138% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1139%
1140*/
1141
1142static inline int MagickMax(const int x,const int y)
1143{
1144 if (x > y)
1145 return(x);
1146 return(y);
1147}
1148
cristybb503372010-05-27 20:51:26 +00001149static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001150 const unsigned int y)
1151{
1152 if (x < y)
1153 return(x);
1154 return(y);
1155}
1156
1157MagickExport XVisualInfo *XBestVisualInfo(Display *display,
1158 XStandardColormap *map_info,XResourceInfo *resource_info)
1159{
1160#define MaxStandardColormaps 7
1161#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1162 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1163 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1164 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1165
1166 char
1167 *map_type,
1168 *visual_type;
1169
cristyc57f6942010-11-12 01:47:39 +00001170 int
1171 visual_mask;
1172
cristy3ed852e2009-09-05 21:47:34 +00001173 register int
1174 i;
1175
cristy8891f9c2010-06-04 23:32:17 +00001176 size_t
1177 one;
1178
cristy3ed852e2009-09-05 21:47:34 +00001179 static int
1180 number_visuals;
1181
1182 static XVisualInfo
1183 visual_template;
1184
1185 XVisualInfo
1186 *visual_info,
1187 *visual_list;
1188
1189 /*
1190 Restrict visual search by screen number.
1191 */
1192 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1193 assert(display != (Display *) NULL);
1194 assert(map_info != (XStandardColormap *) NULL);
1195 assert(resource_info != (XResourceInfo *) NULL);
1196 map_type=resource_info->map_type;
1197 visual_type=resource_info->visual_type;
1198 visual_mask=VisualScreenMask;
1199 visual_template.screen=XDefaultScreen(display);
1200 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001201 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001202 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001203 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001204 visual_mask|=VisualDepthMask;
1205 if (visual_type != (char *) NULL)
1206 {
1207 /*
1208 Restrict visual search by class or visual id.
1209 */
1210 if (LocaleCompare("staticgray",visual_type) == 0)
1211 {
1212 visual_mask|=VisualClassMask;
1213 visual_template.klass=StaticGray;
1214 }
1215 else
1216 if (LocaleCompare("grayscale",visual_type) == 0)
1217 {
1218 visual_mask|=VisualClassMask;
1219 visual_template.klass=GrayScale;
1220 }
1221 else
1222 if (LocaleCompare("staticcolor",visual_type) == 0)
1223 {
1224 visual_mask|=VisualClassMask;
1225 visual_template.klass=StaticColor;
1226 }
1227 else
1228 if (LocaleCompare("pseudocolor",visual_type) == 0)
1229 {
1230 visual_mask|=VisualClassMask;
1231 visual_template.klass=PseudoColor;
1232 }
1233 else
1234 if (LocaleCompare("truecolor",visual_type) == 0)
1235 {
1236 visual_mask|=VisualClassMask;
1237 visual_template.klass=TrueColor;
1238 }
1239 else
1240 if (LocaleCompare("directcolor",visual_type) == 0)
1241 {
1242 visual_mask|=VisualClassMask;
1243 visual_template.klass=DirectColor;
1244 }
1245 else
1246 if (LocaleCompare("default",visual_type) == 0)
1247 {
1248 visual_mask|=VisualIDMask;
1249 visual_template.visualid=XVisualIDFromVisual(
1250 XDefaultVisual(display,XDefaultScreen(display)));
1251 }
1252 else
1253 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1254 {
1255 visual_mask|=VisualIDMask;
1256 visual_template.visualid=
1257 strtol(visual_type,(char **) NULL,0);
1258 }
1259 else
1260 ThrowXWindowFatalException(XServerError,
1261 "UnrecognizedVisualSpecifier",visual_type);
1262 }
1263 /*
1264 Get all visuals that meet our criteria so far.
1265 */
1266 number_visuals=0;
1267 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1268 &number_visuals);
1269 visual_mask=VisualScreenMask | VisualIDMask;
1270 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1271 {
1272 /*
1273 Failed to get visual; try using the default visual.
1274 */
1275 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1276 visual_type);
1277 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1278 XDefaultScreen(display)));
1279 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1280 &number_visuals);
1281 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1282 return((XVisualInfo *) NULL);
1283 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1284 XVisualClassName(visual_list->klass));
1285 }
1286 resource_info->color_recovery=MagickFalse;
1287 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1288 {
1289 Atom
1290 map_property;
1291
1292 char
1293 map_name[MaxTextExtent];
1294
1295 int
1296 j,
1297 number_maps;
1298
1299 Status
1300 status;
1301
1302 Window
1303 root_window;
1304
1305 XStandardColormap
1306 *map_list;
1307
1308 /*
1309 Choose a visual associated with a standard colormap.
1310 */
1311 root_window=XRootWindow(display,XDefaultScreen(display));
1312 status=False;
1313 if (LocaleCompare(map_type,"list") != 0)
1314 {
1315 /*
1316 User specified Standard Colormap.
1317 */
cristyb51dff52011-05-19 16:55:47 +00001318 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001319 "RGB_%s_MAP",map_type);
1320 LocaleUpper(map_name);
1321 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1322 if (map_property != (Atom) NULL)
1323 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1324 map_property);
1325 }
1326 else
1327 {
1328 static const char
1329 *colormap[MaxStandardColormaps]=
1330 {
1331 "_HP_RGB_SMOOTH_MAP_LIST",
1332 "RGB_BEST_MAP",
1333 "RGB_DEFAULT_MAP",
1334 "RGB_GRAY_MAP",
1335 "RGB_RED_MAP",
1336 "RGB_GREEN_MAP",
1337 "RGB_BLUE_MAP",
1338 };
1339
1340 /*
1341 Choose a standard colormap from a list.
1342 */
1343 for (i=0; i < MaxStandardColormaps; i++)
1344 {
1345 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1346 if (map_property == (Atom) NULL)
1347 continue;
1348 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1349 map_property);
1350 if (status != False)
1351 break;
1352 }
1353 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1354 }
1355 if (status == False)
1356 {
1357 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1358 map_type);
1359 return((XVisualInfo *) NULL);
1360 }
1361 /*
1362 Search all Standard Colormaps and visuals for ids that match.
1363 */
1364 *map_info=map_list[0];
1365#if !defined(PRE_R4_ICCCM)
1366 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1367 for (i=0; i < number_maps; i++)
1368 for (j=0; j < number_visuals; j++)
1369 if (map_list[i].visualid ==
1370 XVisualIDFromVisual(visual_list[j].visual))
1371 {
1372 *map_info=map_list[i];
1373 visual_template.visualid=XVisualIDFromVisual(
1374 visual_list[j].visual);
1375 break;
1376 }
1377 if (map_info->visualid != visual_template.visualid)
1378 {
1379 ThrowXWindowFatalException(XServerError,
1380 "UnableToMatchVisualToStandardColormap",map_type);
1381 return((XVisualInfo *) NULL);
1382 }
1383#endif
1384 if (map_info->colormap == (Colormap) NULL)
1385 {
1386 ThrowXWindowFatalException(XServerError,
1387 "StandardColormapIsNotInitialized",map_type);
1388 return((XVisualInfo *) NULL);
1389 }
1390 (void) XFree((void *) map_list);
1391 }
1392 else
1393 {
1394 static const unsigned int
1395 rank[]=
1396 {
1397 StaticGray,
1398 GrayScale,
1399 StaticColor,
1400 DirectColor,
1401 TrueColor,
1402 PseudoColor
1403 };
1404
1405 XVisualInfo
1406 *p;
1407
1408 /*
1409 Pick one visual that displays the most simultaneous colors.
1410 */
1411 visual_info=visual_list;
1412 p=visual_list;
1413 for (i=1; i < number_visuals; i++)
1414 {
1415 p++;
1416 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1417 visual_info=p;
1418 else
1419 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1420 if (rank[p->klass] > rank[visual_info->klass])
1421 visual_info=p;
1422 }
1423 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1424 }
1425 (void) XFree((void *) visual_list);
1426 /*
1427 Retrieve only one visual by its screen & id number.
1428 */
1429 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1430 &number_visuals);
1431 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1432 return((XVisualInfo *) NULL);
1433 return(visual_info);
1434}
1435
1436/*
1437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1438% %
1439% %
1440% %
1441% X C h e c k D e f i n e C u r s o r %
1442% %
1443% %
1444% %
1445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1446%
1447% XCheckDefineCursor() prevents cursor changes on the root window.
1448%
1449% The format of the XXCheckDefineCursor method is:
1450%
1451% XCheckDefineCursor(display,window,cursor)
1452%
1453% A description of each parameter follows:
1454%
1455% o display: Specifies a connection to an X server; returned from
1456% XOpenDisplay.
1457%
1458% o window: the window.
1459%
1460% o cursor: the cursor.
1461%
1462*/
1463MagickExport int XCheckDefineCursor(Display *display,Window window,
1464 Cursor cursor)
1465{
1466 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1467 assert(display != (Display *) NULL);
1468 if (window == XRootWindow(display,XDefaultScreen(display)))
1469 return(0);
1470 return(XDefineCursor(display,window,cursor));
1471}
1472
1473/*
1474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1475% %
1476% %
1477% %
1478% X C h e c k R e f r e s h W i n d o w s %
1479% %
1480% %
1481% %
1482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1483%
1484% XCheckRefreshWindows() checks the X server for exposure events for a
1485% particular window and updates the areassociated with the exposure event.
1486%
1487% The format of the XCheckRefreshWindows method is:
1488%
1489% void XCheckRefreshWindows(Display *display,XWindows *windows)
1490%
1491% A description of each parameter follows:
1492%
1493% o display: Specifies a connection to an X server; returned from
1494% XOpenDisplay.
1495%
1496% o windows: Specifies a pointer to a XWindows structure.
1497%
1498*/
1499MagickExport void XCheckRefreshWindows(Display *display,XWindows *windows)
1500{
1501 Window
1502 id;
1503
1504 XEvent
1505 event;
1506
1507 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1508 assert(display != (Display *) NULL);
1509 assert(windows != (XWindows *) NULL);
1510 XDelay(display,SuspendTime);
1511 id=windows->command.id;
1512 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1513 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1514 id=windows->image.id;
1515 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1516 XRefreshWindow(display,&windows->image,&event);
1517 XDelay(display,SuspendTime << 1);
1518 id=windows->command.id;
1519 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1520 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1521 id=windows->image.id;
1522 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1523 XRefreshWindow(display,&windows->image,&event);
1524}
1525
1526/*
1527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1528% %
1529% %
1530% %
1531% X C l i e n t M e s s a g e %
1532% %
1533% %
1534% %
1535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1536%
1537% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1538% initialized with a particular protocol type and atom.
1539%
1540% The format of the XClientMessage function is:
1541%
1542% XClientMessage(display,window,protocol,reason,timestamp)
1543%
1544% A description of each parameter follows:
1545%
1546% o display: Specifies a pointer to the Display structure; returned from
1547% XOpenDisplay.
1548%
1549% o window: Specifies a pointer to a Window structure.
1550%
1551% o protocol: Specifies an atom value.
1552%
1553% o reason: Specifies an atom value which is the reason to send.
1554%
1555% o timestamp: Specifies a value of type Time.
1556%
1557*/
1558MagickExport void XClientMessage(Display *display,const Window window,
1559 const Atom protocol,const Atom reason,const Time timestamp)
1560{
1561 XClientMessageEvent
1562 client_event;
1563
1564 assert(display != (Display *) NULL);
1565 client_event.type=ClientMessage;
1566 client_event.window=window;
1567 client_event.message_type=protocol;
1568 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001569 client_event.data.l[0]=(long) reason;
1570 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001571 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1572}
1573
1574/*
1575%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1576% %
1577% %
1578% %
1579+ X C l i e n t W i n d o w %
1580% %
1581% %
1582% %
1583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1584%
1585% XClientWindow() finds a window, at or below the specified window, which has
1586% a WM_STATE property. If such a window is found, it is returned, otherwise
1587% the argument window is returned.
1588%
1589% The format of the XClientWindow function is:
1590%
1591% client_window=XClientWindow(display,target_window)
1592%
1593% A description of each parameter follows:
1594%
1595% o client_window: XClientWindow returns a window, at or below the specified
1596% window, which has a WM_STATE property otherwise the argument
1597% target_window is returned.
1598%
1599% o display: Specifies a pointer to the Display structure; returned from
1600% XOpenDisplay.
1601%
1602% o target_window: Specifies the window to find a WM_STATE property.
1603%
cristy3ed852e2009-09-05 21:47:34 +00001604*/
1605static Window XClientWindow(Display *display,Window target_window)
1606{
1607 Atom
1608 state,
1609 type;
1610
1611 int
1612 format;
1613
1614 Status
1615 status;
1616
1617 unsigned char
1618 *data;
1619
cristyf2faecf2010-05-28 19:19:36 +00001620 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001621 after,
1622 number_items;
1623
1624 Window
1625 client_window;
1626
1627 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1628 assert(display != (Display *) NULL);
1629 state=XInternAtom(display,"WM_STATE",MagickTrue);
1630 if (state == (Atom) NULL)
1631 return(target_window);
1632 type=(Atom) NULL;
1633 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1634 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1635 if ((status == Success) && (type != (Atom) NULL))
1636 return(target_window);
1637 client_window=XWindowByProperty(display,target_window,state);
1638 if (client_window == (Window) NULL)
1639 return(target_window);
1640 return(client_window);
1641}
1642
1643/*
1644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1645% %
1646% %
1647% %
cristyf34a1452009-10-24 22:29:27 +00001648+ X C o m p o n e n t T e r m i n u s %
1649% %
1650% %
1651% %
1652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1653%
1654% XComponentTerminus() destroys the module component.
1655%
1656% The format of the XComponentTerminus method is:
1657%
1658% XComponentTerminus(void)
1659%
1660*/
1661MagickExport void XComponentTerminus(void)
1662{
1663 DestroyXResources();
1664}
1665
1666/*
1667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1668% %
1669% %
1670% %
cristy3ed852e2009-09-05 21:47:34 +00001671% X C o n f i g u r e I m a g e C o l o r m a p %
1672% %
1673% %
1674% %
1675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1676%
1677% XConfigureImageColormap() creates a new X colormap.
1678%
1679% The format of the XConfigureImageColormap method is:
1680%
1681% void XConfigureImageColormap(Display *display,
1682% XResourceInfo *resource_info,XWindows *windows,Image *image)
1683%
1684% A description of each parameter follows:
1685%
1686% o display: Specifies a connection to an X server; returned from
1687% XOpenDisplay.
1688%
1689% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1690%
1691% o windows: Specifies a pointer to a XWindows structure.
1692%
1693% o image: the image.
1694%
1695*/
1696MagickExport void XConfigureImageColormap(Display *display,
1697 XResourceInfo *resource_info,XWindows *windows,Image *image)
1698{
1699 Colormap
1700 colormap;
1701
1702 /*
1703 Make standard colormap.
1704 */
1705 XSetCursorState(display,windows,MagickTrue);
1706 XCheckRefreshWindows(display,windows);
1707 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1708 windows->map_info,windows->pixel_info);
1709 colormap=windows->map_info->colormap;
1710 (void) XSetWindowColormap(display,windows->image.id,colormap);
1711 (void) XSetWindowColormap(display,windows->command.id,colormap);
1712 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1713 if (windows->magnify.mapped != MagickFalse)
1714 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1715 if (windows->pan.mapped != MagickFalse)
1716 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1717 XSetCursorState(display,windows,MagickFalse);
1718 XClientMessage(display,windows->image.id,windows->im_protocols,
1719 windows->im_update_colormap,CurrentTime);
1720}
1721
1722/*
1723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1724% %
1725% %
1726% %
1727% X C o n s t r a i n W i n d o w P o s i t i o n %
1728% %
1729% %
1730% %
1731%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1732%
1733% XConstrainWindowPosition() assures a window is positioned within the X
1734% server boundaries.
1735%
1736% The format of the XConstrainWindowPosition method is:
1737%
1738% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1739%
1740% A description of each parameter follows:
1741%
1742% o display: Specifies a pointer to the Display structure; returned from
1743% XOpenDisplay.
1744%
1745% o window_info: Specifies a pointer to a XWindowInfo structure.
1746%
1747*/
1748MagickExport void XConstrainWindowPosition(Display *display,
1749 XWindowInfo *window_info)
1750{
1751 int
1752 limit;
1753
1754 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1755 assert(display != (Display *) NULL);
1756 assert(window_info != (XWindowInfo *) NULL);
1757 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1758 if (window_info->x < 0)
1759 window_info->x=0;
1760 else
1761 if (window_info->x > (int) limit)
1762 window_info->x=(int) limit;
1763 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1764 if (window_info->y < 0)
1765 window_info->y=0;
1766 else
1767 if (window_info->y > limit)
1768 window_info->y=limit;
1769}
1770
1771/*
1772%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1773% %
1774% %
1775% %
1776% X D e l a y %
1777% %
1778% %
1779% %
1780%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781%
1782% XDelay() suspends program execution for the number of milliseconds
1783% specified.
1784%
1785% The format of the Delay method is:
1786%
cristybb503372010-05-27 20:51:26 +00001787% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001788%
1789% A description of each parameter follows:
1790%
1791% o display: Specifies a pointer to the Display structure; returned from
1792% XOpenDisplay.
1793%
1794% o milliseconds: Specifies the number of milliseconds to delay before
1795% returning.
1796%
1797*/
cristybb503372010-05-27 20:51:26 +00001798MagickExport void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001799{
1800 assert(display != (Display *) NULL);
1801 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001802 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001803}
1804
1805/*
1806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1807% %
1808% %
1809% %
1810% X D e s t r o y R e s o u r c e I n f o %
1811% %
1812% %
1813% %
1814%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1815%
1816% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1817% structure.
1818%
1819% The format of the XDestroyResourceInfo method is:
1820%
1821% void XDestroyResourceInfo(XResourceInfo *resource_info)
1822%
1823% A description of each parameter follows:
1824%
1825% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1826%
1827*/
1828MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1829{
1830 if (resource_info->image_geometry != (char *) NULL)
1831 resource_info->image_geometry=(char *)
1832 RelinquishMagickMemory(resource_info->image_geometry);
1833 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1834 resource_info->quantize_info=DestroyQuantizeInfo(
1835 resource_info->quantize_info);
1836 if (resource_info->client_name != (char *) NULL)
1837 resource_info->client_name=(char *)
1838 RelinquishMagickMemory(resource_info->client_name);
1839 if (resource_info->name != (char *) NULL)
1840 resource_info->name=DestroyString(resource_info->name);
1841 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1842}
1843
1844/*
1845%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1846% %
1847% %
1848% %
1849% X D e s t r o y W i n d o w C o l o r s %
1850% %
1851% %
1852% %
1853%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1854%
1855% XDestroyWindowColors() frees X11 color resources previously saved on a
1856% window by XRetainWindowColors or programs like xsetroot.
1857%
1858% The format of the XDestroyWindowColors method is:
1859%
1860% void XDestroyWindowColors(Display *display,Window window)
1861%
1862% A description of each parameter follows:
1863%
1864% o display: Specifies a connection to an X server; returned from
1865% XOpenDisplay.
1866%
1867% o window: Specifies a pointer to a Window structure.
1868%
1869*/
1870MagickExport void XDestroyWindowColors(Display *display,Window window)
1871{
1872 Atom
1873 property,
1874 type;
1875
1876 int
1877 format;
1878
1879 Status
1880 status;
1881
1882 unsigned char
1883 *data;
1884
cristyf2faecf2010-05-28 19:19:36 +00001885 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001886 after,
1887 length;
1888
1889 /*
1890 If there are previous resources on the root window, destroy them.
1891 */
1892 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1893 assert(display != (Display *) NULL);
1894 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1895 if (property == (Atom) NULL)
1896 {
1897 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1898 "_XSETROOT_ID");
1899 return;
1900 }
1901 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1902 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1903 if (status != Success)
1904 return;
1905 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1906 {
1907 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1908 (void) XDeleteProperty(display,window,property);
1909 }
1910 if (type != None)
1911 (void) XFree((void *) data);
1912}
1913
1914/*
1915%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1916% %
1917% %
1918% %
1919% X D i s p l a y I m a g e I n f o %
1920% %
1921% %
1922% %
1923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1924%
1925% XDisplayImageInfo() displays information about an X image.
1926%
1927% The format of the XDisplayImageInfo method is:
1928%
1929% void XDisplayImageInfo(Display *display,
1930% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1931% Image *image)
1932%
1933% A description of each parameter follows:
1934%
1935% o display: Specifies a connection to an X server; returned from
1936% XOpenDisplay.
1937%
1938% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1939%
1940% o windows: Specifies a pointer to a XWindows structure.
1941%
1942% o undo_image: the undo image.
1943%
1944% o image: the image.
1945%
1946*/
1947MagickExport void XDisplayImageInfo(Display *display,
1948 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1949 Image *image)
1950{
1951 char
1952 filename[MaxTextExtent],
1953 *text,
1954 **textlist;
1955
1956 FILE
1957 *file;
1958
1959 int
1960 unique_file;
1961
cristybb503372010-05-27 20:51:26 +00001962 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001963 i;
1964
cristybb503372010-05-27 20:51:26 +00001965 size_t
cristy3ed852e2009-09-05 21:47:34 +00001966 number_pixels;
1967
cristy9d314ff2011-03-09 01:30:28 +00001968 ssize_t
1969 bytes;
1970
1971 unsigned int
1972 levels;
1973
cristy3ed852e2009-09-05 21:47:34 +00001974 /*
1975 Write info about the X server to a file.
1976 */
1977 assert(display != (Display *) NULL);
1978 assert(resource_info != (XResourceInfo *) NULL);
1979 assert(windows != (XWindows *) NULL);
1980 assert(image != (Image *) NULL);
1981 if (image->debug)
1982 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1983 file=(FILE *) NULL;
1984 unique_file=AcquireUniqueFileResource(filename);
1985 if (unique_file != -1)
1986 file=fdopen(unique_file,"w");
1987 if ((unique_file == -1) || (file == (FILE *) NULL))
1988 {
1989 XNoticeWidget(display,windows,"Unable to display image info",filename);
1990 return;
1991 }
1992 if (resource_info->gamma_correct != MagickFalse)
1993 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00001994 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00001995 resource_info->display_gamma);
1996 /*
1997 Write info about the X image to a file.
1998 */
cristyb51dff52011-05-19 16:55:47 +00001999 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002000 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002001 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002002 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002003 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002004 windows->visual_info->colormap_size);
2005 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002006 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002007 else
cristyb51dff52011-05-19 16:55:47 +00002008 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002009 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2010 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002011 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002012 (void) FormatLocaleFile(file," crop geometry: %s\n",
2013 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002014 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002015 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002016 else
cristyb51dff52011-05-19 16:55:47 +00002017 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002018 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002019 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002020 else
cristyb51dff52011-05-19 16:55:47 +00002021 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002022 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002023 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002024 else
cristyb51dff52011-05-19 16:55:47 +00002025 (void) FormatLocaleFile(file," shared memory: False\n");
2026 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002027 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002028 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002029 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002030 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002031 /*
2032 Write info about the undo cache to a file.
2033 */
2034 bytes=0;
2035 for (levels=0; undo_image != (Image *) NULL; levels++)
2036 {
2037 number_pixels=undo_image->list->columns*undo_image->list->rows;
2038 bytes+=number_pixels*sizeof(PixelPacket);
2039 undo_image=GetPreviousImageInList(undo_image);
2040 }
cristyb51dff52011-05-19 16:55:47 +00002041 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002042 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2043 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002044 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002045 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002046 /*
2047 Write info about the image to a file.
2048 */
cristya4037272011-08-28 15:11:39 +00002049 (void) IdentifyImage(image,file,MagickTrue,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002050 (void) fclose(file);
2051 text=FileToString(filename,~0,&image->exception);
2052 (void) RelinquishUniqueFileResource(filename);
2053 if (text == (char *) NULL)
2054 {
2055 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2056 "UnableToDisplayImageInfo");
2057 return;
2058 }
2059 textlist=StringToList(text);
2060 if (textlist != (char **) NULL)
2061 {
2062 char
2063 title[MaxTextExtent];
2064
2065 /*
2066 Display information about the image in the Text View widget.
2067 */
2068 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002069 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002070 image->filename);
2071 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2072 (char const **) textlist);
2073 for (i=0; textlist[i] != (char *) NULL; i++)
2074 textlist[i]=DestroyString(textlist[i]);
2075 textlist=(char **) RelinquishMagickMemory(textlist);
2076 }
2077 text=DestroyString(text);
2078}
2079
2080/*
2081%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2082% %
2083% %
2084% %
2085+ X D i t h e r I m a g e %
2086% %
2087% %
2088% %
2089%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2090%
2091% XDitherImage() dithers the reference image as required by the HP Color
2092% Recovery algorithm. The color values are quantized to 3 bits of red and
2093% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2094% standard colormap.
2095%
2096% The format of the XDitherImage method is:
2097%
2098% void XDitherImage(Image *image,XImage *ximage)
2099%
2100% A description of each parameter follows:
2101%
2102% o image: the image.
2103%
2104% o ximage: Specifies a pointer to a XImage structure; returned from
2105% XCreateImage.
2106%
cristy3ed852e2009-09-05 21:47:34 +00002107*/
2108static void XDitherImage(Image *image,XImage *ximage)
2109{
2110 static const short int
2111 dither_red[2][16]=
2112 {
2113 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2114 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2115 },
2116 dither_green[2][16]=
2117 {
2118 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2119 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2120 },
2121 dither_blue[2][16]=
2122 {
2123 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2124 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2125 };
2126
cristyc57f6942010-11-12 01:47:39 +00002127 CacheView
2128 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002129
2130 int
cristyc57f6942010-11-12 01:47:39 +00002131 value,
cristy3ed852e2009-09-05 21:47:34 +00002132 y;
2133
cristyc57f6942010-11-12 01:47:39 +00002134 PixelPacket
2135 color;
cristy3ed852e2009-09-05 21:47:34 +00002136
2137 register char
2138 *q;
2139
cristy4c08aed2011-07-01 19:47:50 +00002140 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002141 *p;
2142
2143 register int
2144 i,
2145 j,
2146 x;
2147
2148 unsigned int
2149 scanline_pad;
2150
cristybb503372010-05-27 20:51:26 +00002151 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002152 pixel;
2153
2154 unsigned char
2155 *blue_map[2][16],
2156 *green_map[2][16],
2157 *red_map[2][16];
2158
2159 /*
2160 Allocate and initialize dither maps.
2161 */
2162 for (i=0; i < 2; i++)
2163 for (j=0; j < 16; j++)
2164 {
2165 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2166 sizeof(*red_map));
2167 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2168 sizeof(*green_map));
2169 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2170 sizeof(*blue_map));
2171 if ((red_map[i][j] == (unsigned char *) NULL) ||
2172 (green_map[i][j] == (unsigned char *) NULL) ||
2173 (blue_map[i][j] == (unsigned char *) NULL))
2174 {
2175 ThrowXWindowFatalException(ResourceLimitError,
2176 "MemoryAllocationFailed",image->filename);
2177 return;
2178 }
2179 }
2180 /*
2181 Initialize dither tables.
2182 */
2183 for (i=0; i < 2; i++)
2184 for (j=0; j < 16; j++)
2185 for (x=0; x < 256; x++)
2186 {
2187 value=x-16;
2188 if (x < 48)
2189 value=x/2+8;
2190 value+=dither_red[i][j];
2191 red_map[i][j][x]=(unsigned char)
2192 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2193 value=x-16;
2194 if (x < 48)
2195 value=x/2+8;
2196 value+=dither_green[i][j];
2197 green_map[i][j][x]=(unsigned char)
2198 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2199 value=x-32;
2200 if (x < 112)
2201 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002202 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002203 blue_map[i][j][x]=(unsigned char)
2204 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2205 }
2206 /*
2207 Dither image.
2208 */
2209 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002210 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002211 i=0;
2212 j=0;
2213 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002214 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002215 for (y=0; y < (int) image->rows; y++)
2216 {
cristyc57f6942010-11-12 01:47:39 +00002217 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2218 &image->exception);
cristy4c08aed2011-07-01 19:47:50 +00002219 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002220 break;
2221 for (x=0; x < (int) image->columns; x++)
2222 {
cristyce70c172010-01-07 17:15:30 +00002223 color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002224 ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002225 color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002226 ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002227 color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002228 ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002229 pixel=(size_t) (((size_t) color.red & 0xe0) |
2230 (((size_t) color.green & 0xe0) >> 3) |
2231 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002232 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002233 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002234 j++;
2235 if (j == 16)
2236 j=0;
2237 }
2238 q+=scanline_pad;
2239 i++;
2240 if (i == 2)
2241 i=0;
2242 }
cristyc57f6942010-11-12 01:47:39 +00002243 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002244 /*
2245 Free allocated memory.
2246 */
2247 for (i=0; i < 2; i++)
2248 for (j=0; j < 16; j++)
2249 {
2250 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2251 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2252 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2253 }
2254}
2255
2256/*
2257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2258% %
2259% %
2260% %
2261% X D r a w I m a g e %
2262% %
2263% %
2264% %
2265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2266%
2267% XDrawImage() draws a line on the image.
2268%
2269% The format of the XDrawImage method is:
2270%
2271% MagickBooleanType XDrawImage(display,pixel,draw_info,image)
2272%
2273% A description of each parameter follows:
2274%
2275% o display: Specifies a connection to an X server; returned from
2276% XOpenDisplay.
2277%
2278% o pixel: Specifies a pointer to a XPixelInfo structure.
2279%
2280% o draw_info: Specifies a pointer to a XDrawInfo structure.
2281%
2282% o image: the image.
2283%
2284*/
2285MagickExport MagickBooleanType XDrawImage(Display *display,
2286 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
2287{
cristyc57f6942010-11-12 01:47:39 +00002288 CacheView
2289 *draw_view;
2290
cristy3ed852e2009-09-05 21:47:34 +00002291 ExceptionInfo
2292 *exception;
2293
2294 GC
2295 draw_context;
2296
2297 Image
2298 *draw_image;
2299
2300 int
2301 x,
2302 y;
2303
2304 MagickBooleanType
2305 matte;
2306
2307 Pixmap
2308 draw_pixmap;
2309
2310 unsigned int
2311 depth,
2312 height,
2313 width;
2314
2315 Window
2316 root_window;
2317
2318 XGCValues
2319 context_values;
2320
2321 XImage
2322 *draw_ximage;
2323
2324 /*
2325 Initialize drawd image.
2326 */
2327 assert(display != (Display *) NULL);
2328 assert(pixel != (XPixelInfo *) NULL);
2329 assert(draw_info != (XDrawInfo *) NULL);
2330 assert(image != (Image *) NULL);
2331 if (image->debug != MagickFalse)
2332 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2333 /*
2334 Initialize drawd pixmap.
2335 */
2336 root_window=XRootWindow(display,XDefaultScreen(display));
2337 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2338 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2339 draw_info->height,depth);
2340 if (draw_pixmap == (Pixmap) NULL)
2341 return(MagickFalse);
2342 /*
2343 Initialize graphics info.
2344 */
cristybb503372010-05-27 20:51:26 +00002345 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002346 context_values.foreground=0;
2347 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002348 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002349 (GCBackground | GCForeground | GCLineWidth),&context_values);
2350 if (draw_context == (GC) NULL)
2351 return(MagickFalse);
2352 /*
2353 Clear pixmap.
2354 */
2355 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2356 draw_info->height);
2357 /*
2358 Draw line to pixmap.
2359 */
2360 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002361 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002362 if (draw_info->stipple != (Pixmap) NULL)
2363 {
2364 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2365 (void) XSetStipple(display,draw_context,draw_info->stipple);
2366 }
cristy3ed852e2009-09-05 21:47:34 +00002367 switch (draw_info->element)
2368 {
2369 case PointElement:
2370 default:
2371 {
2372 (void) XDrawLines(display,draw_pixmap,draw_context,
2373 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2374 CoordModeOrigin);
2375 break;
2376 }
2377 case LineElement:
2378 {
2379 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2380 draw_info->line_info.y1,draw_info->line_info.x2,
2381 draw_info->line_info.y2);
2382 break;
2383 }
2384 case RectangleElement:
2385 {
2386 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2387 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2388 (unsigned int) draw_info->rectangle_info.width,
2389 (unsigned int) draw_info->rectangle_info.height);
2390 break;
2391 }
2392 case FillRectangleElement:
2393 {
2394 (void) XFillRectangle(display,draw_pixmap,draw_context,
2395 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2396 (unsigned int) draw_info->rectangle_info.width,
2397 (unsigned int) draw_info->rectangle_info.height);
2398 break;
2399 }
2400 case CircleElement:
2401 case EllipseElement:
2402 {
2403 (void) XDrawArc(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,0,360*64);
2407 break;
2408 }
2409 case FillCircleElement:
2410 case FillEllipseElement:
2411 {
2412 (void) XFillArc(display,draw_pixmap,draw_context,
2413 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2414 (unsigned int) draw_info->rectangle_info.width,
2415 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2416 break;
2417 }
2418 case PolygonElement:
2419 {
2420 XPoint
2421 *coordinate_info;
2422
2423 coordinate_info=draw_info->coordinate_info;
2424 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2425 (int) draw_info->number_coordinates,CoordModeOrigin);
2426 (void) XDrawLine(display,draw_pixmap,draw_context,
2427 coordinate_info[draw_info->number_coordinates-1].x,
2428 coordinate_info[draw_info->number_coordinates-1].y,
2429 coordinate_info[0].x,coordinate_info[0].y);
2430 break;
2431 }
2432 case FillPolygonElement:
2433 {
2434 (void) XFillPolygon(display,draw_pixmap,draw_context,
2435 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2436 CoordModeOrigin);
2437 break;
2438 }
2439 }
2440 (void) XFreeGC(display,draw_context);
2441 /*
2442 Initialize X image.
2443 */
2444 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2445 draw_info->height,AllPlanes,ZPixmap);
2446 if (draw_ximage == (XImage *) NULL)
2447 return(MagickFalse);
2448 (void) XFreePixmap(display,draw_pixmap);
2449 /*
2450 Initialize draw image.
2451 */
2452 draw_image=AcquireImage((ImageInfo *) NULL);
2453 if (draw_image == (Image *) NULL)
2454 return(MagickFalse);
2455 draw_image->columns=draw_info->width;
2456 draw_image->rows=draw_info->height;
2457 /*
2458 Transfer drawn X image to image.
2459 */
2460 width=(unsigned int) image->columns;
2461 height=(unsigned int) image->rows;
2462 x=0;
2463 y=0;
2464 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +00002465 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
2466 &draw_image->background_color,&image->exception);
cristy574cc262011-08-05 01:23:58 +00002467 if (SetImageStorageClass(draw_image,DirectClass,&image->exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002468 return(MagickFalse);
2469 draw_image->matte=MagickTrue;
2470 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +00002471 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002472 for (y=0; y < (int) draw_image->rows; y++)
2473 {
cristyc57f6942010-11-12 01:47:39 +00002474 register int
cristy3ed852e2009-09-05 21:47:34 +00002475 x;
2476
cristy4c08aed2011-07-01 19:47:50 +00002477 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002478 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002479
cristyc57f6942010-11-12 01:47:39 +00002480 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2481 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002482 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002483 break;
cristyc57f6942010-11-12 01:47:39 +00002484 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002485 {
2486 if (XGetPixel(draw_ximage,x,y) == 0)
2487 {
2488 /*
2489 Set this pixel to the background color.
2490 */
cristy4c08aed2011-07-01 19:47:50 +00002491 SetPixelPacket(draw_image,&draw_image->background_color,q);
2492 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2493 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002494 }
2495 else
2496 {
2497 /*
2498 Set this pixel to the pen color.
2499 */
cristy4c08aed2011-07-01 19:47:50 +00002500 SetPixelRed(draw_image,ScaleShortToQuantum(
2501 pixel->pen_color.red),q);
2502 SetPixelGreen(draw_image,ScaleShortToQuantum(
2503 pixel->pen_color.green),q);
2504 SetPixelBlue(draw_image,ScaleShortToQuantum(
2505 pixel->pen_color.blue),q);
2506 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2507 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002508 }
cristyed231572011-07-14 02:18:59 +00002509 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002510 }
cristyc57f6942010-11-12 01:47:39 +00002511 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002512 break;
2513 }
cristyc57f6942010-11-12 01:47:39 +00002514 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002515 XDestroyImage(draw_ximage);
2516 /*
2517 Determine draw geometry.
2518 */
2519 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2520 if ((width != (unsigned int) draw_image->columns) ||
2521 (height != (unsigned int) draw_image->rows))
2522 {
2523 char
2524 image_geometry[MaxTextExtent];
2525
2526 /*
2527 Scale image.
2528 */
cristyb51dff52011-05-19 16:55:47 +00002529 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002530 width,height);
2531 (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
2532 }
2533 if (draw_info->degrees != 0.0)
2534 {
2535 Image
2536 *rotate_image;
2537
2538 int
2539 rotations;
2540
2541 MagickRealType
2542 normalized_degrees;
2543
2544 /*
2545 Rotate image.
2546 */
2547 rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
2548 if (rotate_image == (Image *) NULL)
2549 return(MagickFalse);
2550 draw_image=DestroyImage(draw_image);
2551 draw_image=rotate_image;
2552 /*
2553 Annotation is relative to the degree of rotation.
2554 */
2555 normalized_degrees=draw_info->degrees;
2556 while (normalized_degrees < -45.0)
2557 normalized_degrees+=360.0;
2558 for (rotations=0; normalized_degrees > 45.0; rotations++)
2559 normalized_degrees-=90.0;
2560 switch (rotations % 4)
2561 {
2562 default:
2563 case 0:
2564 break;
2565 case 1:
2566 {
2567 /*
2568 Rotate 90 degrees.
2569 */
2570 x=x-(int) draw_image->columns/2;
2571 y=y+(int) draw_image->columns/2;
2572 break;
2573 }
2574 case 2:
2575 {
2576 /*
2577 Rotate 180 degrees.
2578 */
2579 x=x-(int) draw_image->columns;
2580 break;
2581 }
2582 case 3:
2583 {
2584 /*
2585 Rotate 270 degrees.
2586 */
2587 x=x-(int) draw_image->columns/2;
2588 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2589 break;
2590 }
2591 }
2592 }
2593 /*
2594 Composite text onto the image.
2595 */
cristyc57f6942010-11-12 01:47:39 +00002596 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002597 for (y=0; y < (int) draw_image->rows; y++)
2598 {
cristyc57f6942010-11-12 01:47:39 +00002599 register int
cristy3ed852e2009-09-05 21:47:34 +00002600 x;
2601
cristy4c08aed2011-07-01 19:47:50 +00002602 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002603 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002604
cristyc57f6942010-11-12 01:47:39 +00002605 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2606 exception);
cristyacd2ed22011-08-30 01:44:23 +00002607 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002608 break;
cristyc57f6942010-11-12 01:47:39 +00002609 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002610 {
cristy4c08aed2011-07-01 19:47:50 +00002611 if (GetPixelAlpha(image,q) != TransparentAlpha)
2612 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002613 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002614 }
cristyc57f6942010-11-12 01:47:39 +00002615 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002616 break;
2617 }
cristyc57f6942010-11-12 01:47:39 +00002618 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002619 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2620 if (draw_info->stencil == TransparentStencil)
cristyc57f6942010-11-12 01:47:39 +00002621 (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,(ssize_t) x,
2622 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002623 else
2624 {
2625 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002626 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
2627 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002628 image->matte=matte;
2629 }
2630 draw_image=DestroyImage(draw_image);
2631 return(MagickTrue);
2632}
2633
2634/*
2635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2636% %
2637% %
2638% %
2639% X E r r o r %
2640% %
2641% %
2642% %
2643%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2644%
2645% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2646% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
2647% for XQueryColor. It returns MagickFalse in those cases. Otherwise it returns
2648% True.
2649%
2650% The format of the XError function is:
2651%
2652% XError(display,error)
2653%
2654% A description of each parameter follows:
2655%
2656% o display: Specifies a pointer to the Display structure; returned from
2657% XOpenDisplay.
2658%
2659% o error: Specifies the error event.
2660%
2661*/
2662
2663#if defined(__cplusplus) || defined(c_plusplus)
2664extern "C" {
2665#endif
2666
2667MagickExport int XError(Display *display,XErrorEvent *error)
2668{
2669 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2670 assert(display != (Display *) NULL);
2671 assert(error != (XErrorEvent *) NULL);
2672 xerror_alert=MagickTrue;
2673 switch (error->request_code)
2674 {
2675 case X_GetGeometry:
2676 {
2677 if ((int) error->error_code == BadDrawable)
2678 return(MagickFalse);
2679 break;
2680 }
2681 case X_GetWindowAttributes:
2682 case X_QueryTree:
2683 {
2684 if ((int) error->error_code == BadWindow)
2685 return(MagickFalse);
2686 break;
2687 }
2688 case X_QueryColors:
2689 {
2690 if ((int) error->error_code == BadValue)
2691 return(MagickFalse);
2692 break;
2693 }
2694 }
2695 return(MagickTrue);
2696}
2697
2698#if defined(__cplusplus) || defined(c_plusplus)
2699}
2700#endif
2701
2702/*
2703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2704% %
2705% %
2706% %
2707% X F r e e R e s o u r c e s %
2708% %
2709% %
2710% %
2711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2712%
2713% XFreeResources() frees X11 resources.
2714%
2715% The format of the XFreeResources method is:
2716%
2717% void XFreeResources(Display *display,XVisualInfo *visual_info,
2718% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2719% XResourceInfo *resource_info,XWindowInfo *window_info)
2720% resource_info,window_info)
2721%
2722% A description of each parameter follows:
2723%
2724% o display: Specifies a connection to an X server; returned from
2725% XOpenDisplay.
2726%
2727% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2728% returned from XGetVisualInfo.
2729%
2730% o map_info: If map_type is specified, this structure is initialized
2731% with info from the Standard Colormap.
2732%
2733% o pixel: Specifies a pointer to a XPixelInfo structure.
2734%
2735% o font_info: Specifies a pointer to a XFontStruct structure.
2736%
2737% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2738%
2739% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2740%
2741*/
2742MagickExport void XFreeResources(Display *display,XVisualInfo *visual_info,
2743 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2744 XResourceInfo *resource_info,XWindowInfo *window_info)
2745{
2746 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2747 assert(display != (Display *) NULL);
2748 assert(resource_info != (XResourceInfo *) NULL);
2749 if (window_info != (XWindowInfo *) NULL)
2750 {
2751 /*
2752 Free X image.
2753 */
2754 if (window_info->ximage != (XImage *) NULL)
2755 XDestroyImage(window_info->ximage);
2756 if (window_info->id != (Window) NULL)
2757 {
2758 /*
2759 Free destroy window and free cursors.
2760 */
2761 if (window_info->id != XRootWindow(display,visual_info->screen))
2762 (void) XDestroyWindow(display,window_info->id);
2763 if (window_info->annotate_context != (GC) NULL)
2764 (void) XFreeGC(display,window_info->annotate_context);
2765 if (window_info->highlight_context != (GC) NULL)
2766 (void) XFreeGC(display,window_info->highlight_context);
2767 if (window_info->widget_context != (GC) NULL)
2768 (void) XFreeGC(display,window_info->widget_context);
2769 if (window_info->cursor != (Cursor) NULL)
2770 (void) XFreeCursor(display,window_info->cursor);
2771 window_info->cursor=(Cursor) NULL;
2772 if (window_info->busy_cursor != (Cursor) NULL)
2773 (void) XFreeCursor(display,window_info->busy_cursor);
2774 window_info->busy_cursor=(Cursor) NULL;
2775 }
2776 }
2777 /*
2778 Free font.
2779 */
2780 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002781 {
2782 (void) XFreeFont(display,font_info);
2783 font_info=(XFontStruct *) NULL;
2784 }
cristy3ed852e2009-09-05 21:47:34 +00002785 if (map_info != (XStandardColormap *) NULL)
2786 {
2787 /*
2788 Free X Standard Colormap.
2789 */
2790 if (resource_info->map_type == (char *) NULL)
2791 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2792 (void) XFree((void *) map_info);
2793 }
2794 /*
2795 Free X visual info.
2796 */
2797 if (visual_info != (XVisualInfo *) NULL)
2798 (void) XFree((void *) visual_info);
2799 if (resource_info->close_server != MagickFalse)
2800 (void) XCloseDisplay(display);
2801}
2802
2803/*
2804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2805% %
2806% %
2807% %
2808% X F r e e S t a n d a r d C o l o r m a p %
2809% %
2810% %
2811% %
2812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2813%
2814% XFreeStandardColormap() frees an X11 colormap.
2815%
2816% The format of the XFreeStandardColormap method is:
2817%
2818% void XFreeStandardColormap(Display *display,
2819% const XVisualInfo *visual_info,XStandardColormap *map_info,
2820% XPixelInfo *pixel)
2821%
2822% A description of each parameter follows:
2823%
2824% o display: Specifies a connection to an X server; returned from
2825% XOpenDisplay.
2826%
2827% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2828% returned from XGetVisualInfo.
2829%
2830% o map_info: If map_type is specified, this structure is initialized
2831% with info from the Standard Colormap.
2832%
2833% o pixel: Specifies a pointer to a XPixelInfo structure.
2834%
2835*/
2836MagickExport void XFreeStandardColormap(Display *display,
2837 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2838{
2839 /*
2840 Free colormap.
2841 */
2842 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2843 assert(display != (Display *) NULL);
2844 assert(visual_info != (XVisualInfo *) NULL);
2845 assert(map_info != (XStandardColormap *) NULL);
2846 (void) XFlush(display);
2847 if (map_info->colormap != (Colormap) NULL)
2848 {
2849 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2850 (void) XFreeColormap(display,map_info->colormap);
2851 else
2852 if (pixel != (XPixelInfo *) NULL)
2853 if ((visual_info->klass != TrueColor) &&
2854 (visual_info->klass != DirectColor))
2855 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2856 (int) pixel->colors,0);
2857 }
2858 map_info->colormap=(Colormap) NULL;
2859 if (pixel != (XPixelInfo *) NULL)
2860 {
cristyf2faecf2010-05-28 19:19:36 +00002861 if (pixel->pixels != (unsigned long *) NULL)
2862 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2863 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002864 }
2865}
2866
2867/*
2868%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2869% %
2870% %
2871% %
2872% X G e t A n n o t a t e I n f o %
2873% %
2874% %
2875% %
2876%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2877%
2878% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2879%
2880% The format of the XGetAnnotateInfo method is:
2881%
2882% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2883%
2884% A description of each parameter follows:
2885%
2886% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2887%
2888*/
2889MagickExport void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2890{
2891 /*
2892 Initialize annotate structure.
2893 */
2894 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2895 assert(annotate_info != (XAnnotateInfo *) NULL);
2896 annotate_info->x=0;
2897 annotate_info->y=0;
2898 annotate_info->width=0;
2899 annotate_info->height=0;
2900 annotate_info->stencil=ForegroundStencil;
2901 annotate_info->degrees=0.0;
2902 annotate_info->font_info=(XFontStruct *) NULL;
2903 annotate_info->text=(char *) NULL;
2904 *annotate_info->geometry='\0';
2905 annotate_info->previous=(XAnnotateInfo *) NULL;
2906 annotate_info->next=(XAnnotateInfo *) NULL;
2907 (void) XSupportsLocale();
2908 (void) XSetLocaleModifiers("");
2909}
2910
2911/*
2912%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2913% %
2914% %
2915% %
2916% X G e t M a p I n f o %
2917% %
2918% %
2919% %
2920%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2921%
2922% XGetMapInfo() initializes the XStandardColormap structure.
2923%
2924% The format of the XStandardColormap method is:
2925%
2926% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2927% XStandardColormap *map_info)
2928%
2929% A description of each parameter follows:
2930%
2931% o colormap: Specifies the ID of the X server colormap.
2932%
2933% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2934% returned from XGetVisualInfo.
2935%
2936% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2937%
2938*/
2939MagickExport void XGetMapInfo(const XVisualInfo *visual_info,
2940 const Colormap colormap,XStandardColormap *map_info)
2941{
2942 /*
2943 Initialize map info.
2944 */
2945 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2946 assert(visual_info != (XVisualInfo *) NULL);
2947 assert(map_info != (XStandardColormap *) NULL);
2948 map_info->colormap=colormap;
2949 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002950 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002951 if (map_info->red_max != 0)
2952 while ((map_info->red_max & 0x01) == 0)
2953 {
2954 map_info->red_max>>=1;
2955 map_info->red_mult<<=1;
2956 }
2957 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002958 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002959 if (map_info->green_max != 0)
2960 while ((map_info->green_max & 0x01) == 0)
2961 {
2962 map_info->green_max>>=1;
2963 map_info->green_mult<<=1;
2964 }
2965 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002966 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002967 if (map_info->blue_max != 0)
2968 while ((map_info->blue_max & 0x01) == 0)
2969 {
2970 map_info->blue_max>>=1;
2971 map_info->blue_mult<<=1;
2972 }
2973 map_info->base_pixel=0;
2974}
2975
2976/*
2977%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2978% %
2979% %
2980% %
2981% X G e t P i x e l I n f o %
2982% %
2983% %
2984% %
2985%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2986%
cristy4c08aed2011-07-01 19:47:50 +00002987% XGetPixelInfo() initializes the PixelPacket structure.
cristy3ed852e2009-09-05 21:47:34 +00002988%
cristy4c08aed2011-07-01 19:47:50 +00002989% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00002990%
cristy4c08aed2011-07-01 19:47:50 +00002991% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002992% const XStandardColormap *map_info,const XResourceInfo *resource_info,
2993% Image *image,XPixelInfo *pixel)
2994% pixel)
2995%
2996% A description of each parameter follows:
2997%
2998% o display: Specifies a connection to an X server; returned from
2999% XOpenDisplay.
3000%
3001% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3002% returned from XGetVisualInfo.
3003%
3004% o map_info: If map_type is specified, this structure is initialized
3005% with info from the Standard Colormap.
3006%
3007% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3008%
3009% o image: the image.
3010%
3011% o pixel: Specifies a pointer to a XPixelInfo structure.
3012%
3013*/
cristy4c08aed2011-07-01 19:47:50 +00003014MagickExport void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003015 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3016 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3017{
3018 static const char
3019 *PenColors[MaxNumberPens]=
3020 {
3021 "#000000000000", /* black */
3022 "#00000000ffff", /* blue */
3023 "#0000ffffffff", /* cyan */
3024 "#0000ffff0000", /* green */
3025 "#bdbdbdbdbdbd", /* gray */
3026 "#ffff00000000", /* red */
3027 "#ffff0000ffff", /* magenta */
3028 "#ffffffff0000", /* yellow */
3029 "#ffffffffffff", /* white */
3030 "#bdbdbdbdbdbd", /* gray */
3031 "#bdbdbdbdbdbd" /* gray */
3032 };
3033
3034 Colormap
3035 colormap;
3036
cristybb503372010-05-27 20:51:26 +00003037 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003038 i;
3039
3040 Status
3041 status;
3042
3043 unsigned int
3044 packets;
3045
3046 /*
3047 Initialize pixel info.
3048 */
3049 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3050 assert(display != (Display *) NULL);
3051 assert(visual_info != (XVisualInfo *) NULL);
3052 assert(map_info != (XStandardColormap *) NULL);
3053 assert(resource_info != (XResourceInfo *) NULL);
3054 assert(pixel != (XPixelInfo *) NULL);
3055 pixel->colors=0;
3056 if (image != (Image *) NULL)
3057 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003058 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003059 packets=(unsigned int)
3060 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003061 if (pixel->pixels != (unsigned long *) NULL)
3062 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3063 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003064 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003065 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003066 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3067 image->filename);
3068 /*
3069 Set foreground color.
3070 */
3071 colormap=map_info->colormap;
3072 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3073 &pixel->foreground_color);
3074 status=XParseColor(display,colormap,resource_info->foreground_color,
3075 &pixel->foreground_color);
3076 if (status == False)
3077 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3078 resource_info->foreground_color);
3079 pixel->foreground_color.pixel=
3080 XStandardPixel(map_info,&pixel->foreground_color);
3081 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3082 /*
3083 Set background color.
3084 */
3085 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3086 status=XParseColor(display,colormap,resource_info->background_color,
3087 &pixel->background_color);
3088 if (status == False)
3089 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3090 resource_info->background_color);
3091 pixel->background_color.pixel=
3092 XStandardPixel(map_info,&pixel->background_color);
3093 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3094 /*
3095 Set border color.
3096 */
3097 (void) XParseColor(display,colormap,(char *) BorderColor,
3098 &pixel->border_color);
3099 status=XParseColor(display,colormap,resource_info->border_color,
3100 &pixel->border_color);
3101 if (status == False)
3102 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3103 resource_info->border_color);
3104 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3105 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3106 /*
3107 Set matte color.
3108 */
3109 pixel->matte_color=pixel->background_color;
3110 if (resource_info->matte_color != (char *) NULL)
3111 {
3112 /*
3113 Matte color is specified as a X resource or command line argument.
3114 */
3115 status=XParseColor(display,colormap,resource_info->matte_color,
3116 &pixel->matte_color);
3117 if (status == False)
3118 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3119 resource_info->matte_color);
3120 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3121 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3122 }
3123 /*
3124 Set highlight color.
3125 */
3126 pixel->highlight_color.red=(unsigned short) ((
3127 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3128 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3129 pixel->highlight_color.green=(unsigned short) ((
3130 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3131 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3132 pixel->highlight_color.blue=(unsigned short) ((
3133 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3134 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3135 pixel->highlight_color.pixel=
3136 XStandardPixel(map_info,&pixel->highlight_color);
3137 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3138 /*
3139 Set shadow color.
3140 */
3141 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3142 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3143 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3144 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3145 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3146 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3147 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3148 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3149 /*
3150 Set depth color.
3151 */
3152 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3153 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3154 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3155 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3156 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3157 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3158 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3159 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3160 /*
3161 Set trough color.
3162 */
3163 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3164 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3165 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3166 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3167 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3168 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3169 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3170 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3171 /*
3172 Set pen color.
3173 */
3174 for (i=0; i < MaxNumberPens; i++)
3175 {
3176 (void) XParseColor(display,colormap,(char *) PenColors[i],
3177 &pixel->pen_colors[i]);
3178 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3179 &pixel->pen_colors[i]);
3180 if (status == False)
3181 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3182 resource_info->pen_colors[i]);
3183 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3184 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3185 }
3186 pixel->box_color=pixel->background_color;
3187 pixel->pen_color=pixel->foreground_color;
3188 pixel->box_index=0;
3189 pixel->pen_index=1;
3190 if (image != (Image *) NULL)
3191 {
3192 if ((resource_info->gamma_correct != MagickFalse) &&
3193 (image->gamma != 0.0))
3194 {
3195 GeometryInfo
3196 geometry_info;
3197
3198 MagickStatusType
3199 flags;
3200
3201 /*
3202 Initialize map relative to display and image gamma.
3203 */
3204 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3205 red_gamma=geometry_info.rho;
3206 green_gamma=geometry_info.sigma;
3207 if ((flags & SigmaValue) == 0)
3208 green_gamma=red_gamma;
3209 blue_gamma=geometry_info.xi;
3210 if ((flags & XiValue) == 0)
3211 blue_gamma=red_gamma;
3212 red_gamma*=image->gamma;
3213 green_gamma*=image->gamma;
3214 blue_gamma*=image->gamma;
3215 }
3216 if (image->storage_class == PseudoClass)
3217 {
3218 /*
3219 Initialize pixel array for images of type PseudoClass.
3220 */
cristybb503372010-05-27 20:51:26 +00003221 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003222 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003223 for (i=0; i < MaxNumberPens; i++)
3224 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3225 pixel->colors+=MaxNumberPens;
3226 }
3227 }
3228}
3229
3230/*
3231%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3232% %
3233% %
3234% %
3235% X G e t R e s o u r c e C l a s s %
3236% %
3237% %
3238% %
3239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3240%
3241% XGetResourceClass() queries the X server for the specified resource name or
3242% class. If the resource name or class is not defined in the database, the
3243% supplied default value is returned.
3244%
3245% The format of the XGetResourceClass method is:
3246%
3247% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3248% const char *keyword,char *resource_default)
3249%
3250% A description of each parameter follows:
3251%
3252% o database: Specifies a resource database; returned from
3253% XrmGetStringDatabase.
3254%
3255% o client_name: Specifies the application name used to retrieve resource
3256% info from the X server database.
3257%
3258% o keyword: Specifies the keyword of the value being retrieved.
3259%
3260% o resource_default: Specifies the default value to return if the query
3261% fails to find the specified keyword/class.
3262%
3263*/
3264MagickExport char *XGetResourceClass(XrmDatabase database,
3265 const char *client_name,const char *keyword,char *resource_default)
3266{
3267 char
3268 resource_class[MaxTextExtent],
3269 resource_name[MaxTextExtent];
3270
3271 static char
3272 *resource_type;
3273
3274 Status
3275 status;
3276
3277 XrmValue
3278 resource_value;
3279
3280 if (database == (XrmDatabase) NULL)
3281 return(resource_default);
3282 *resource_name='\0';
3283 *resource_class='\0';
3284 if (keyword != (char *) NULL)
3285 {
3286 int
3287 c,
3288 k;
3289
3290 /*
3291 Initialize resource keyword and class.
3292 */
cristyb51dff52011-05-19 16:55:47 +00003293 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003294 client_name,keyword);
3295 c=(int) (*client_name);
3296 if ((c >= XK_a) && (c <= XK_z))
3297 c-=(XK_a-XK_A);
3298 else
3299 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3300 c-=(XK_agrave-XK_Agrave);
3301 else
3302 if ((c >= XK_oslash) && (c <= XK_thorn))
3303 c-=(XK_oslash-XK_Ooblique);
3304 k=(int) (*keyword);
3305 if ((k >= XK_a) && (k <= XK_z))
3306 k-=(XK_a-XK_A);
3307 else
3308 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3309 k-=(XK_agrave-XK_Agrave);
3310 else
3311 if ((k >= XK_oslash) && (k <= XK_thorn))
3312 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003313 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003314 client_name+1,k,keyword+1);
3315 }
3316 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3317 &resource_value);
3318 if (status == False)
3319 return(resource_default);
3320 return(resource_value.addr);
3321}
3322
3323/*
3324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3325% %
3326% %
3327% %
3328% X G e t R e s o u r c e D a t a b a s e %
3329% %
3330% %
3331% %
3332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3333%
3334% XGetResourceDatabase() creates a new resource database and initializes it.
3335%
3336% The format of the XGetResourceDatabase method is:
3337%
3338% XrmDatabase XGetResourceDatabase(Display *display,
3339% const char *client_name)
3340%
3341% A description of each parameter follows:
3342%
3343% o database: XGetResourceDatabase() returns the database after it is
3344% initialized.
3345%
3346% o display: Specifies a connection to an X server; returned from
3347% XOpenDisplay.
3348%
3349% o client_name: Specifies the application name used to retrieve resource
3350% info from the X server database.
3351%
3352*/
3353MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3354 const char *client_name)
3355{
3356 char
3357 filename[MaxTextExtent];
3358
3359 int
3360 c;
3361
3362 register const char
3363 *p;
3364
3365 XrmDatabase
3366 resource_database,
3367 server_database;
3368
3369 if (display == (Display *) NULL)
3370 return((XrmDatabase) NULL);
3371 assert(client_name != (char *) NULL);
3372 /*
3373 Initialize resource database.
3374 */
3375 XrmInitialize();
3376 (void) XGetDefault(display,(char *) client_name,"dummy");
3377 resource_database=XrmGetDatabase(display);
3378 /*
3379 Combine application database.
3380 */
3381 if (client_name != (char *) NULL)
3382 {
3383 /*
3384 Get basename of client.
3385 */
3386 p=client_name+(strlen(client_name)-1);
3387 while ((p > client_name) && (*p != '/'))
3388 p--;
3389 if (*p == '/')
3390 client_name=p+1;
3391 }
3392 c=(int) (*client_name);
3393 if ((c >= XK_a) && (c <= XK_z))
3394 c-=(XK_a-XK_A);
3395 else
3396 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3397 c-=(XK_agrave-XK_Agrave);
3398 else
3399 if ((c >= XK_oslash) && (c <= XK_thorn))
3400 c-=(XK_oslash-XK_Ooblique);
3401#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003402 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003403 X11_APPLICATION_PATH,c,client_name+1);
3404 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3405#endif
3406 if (XResourceManagerString(display) != (char *) NULL)
3407 {
3408 /*
3409 Combine server database.
3410 */
3411 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3412 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3413 }
3414 /*
3415 Merge user preferences database.
3416 */
3417#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003418 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003419 X11_PREFERENCES_PATH,client_name);
3420 ExpandFilename(filename);
3421 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3422#endif
3423 return(resource_database);
3424}
3425
3426/*
3427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3428% %
3429% %
3430% %
3431% X G e t R e s o u r c e I n f o %
3432% %
3433% %
3434% %
3435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3436%
3437% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3438%
3439% The format of the XGetResourceInfo method is:
3440%
3441% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3442% const char *client_name,XResourceInfo *resource_info)
3443%
3444% A description of each parameter follows:
3445%
3446% o image_info: the image info.
3447%
3448% o database: Specifies a resource database; returned from
3449% XrmGetStringDatabase.
3450%
3451% o client_name: Specifies the application name used to retrieve
3452% resource info from the X server database.
3453%
3454% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3455%
3456*/
3457MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3458 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3459{
3460 char
cristy00976d82011-02-20 20:31:28 +00003461 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003462 *resource_value;
3463
3464 /*
3465 Initialize resource info fields.
3466 */
3467 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3468 assert(resource_info != (XResourceInfo *) NULL);
3469 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3470 resource_info->resource_database=database;
3471 resource_info->image_info=(ImageInfo *) image_info;
3472 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3473 XMagickProgressMonitor,(void *) NULL);
3474 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3475 resource_info->close_server=MagickTrue;
3476 resource_info->client_name=AcquireString(client_name);
3477 resource_value=XGetResourceClass(database,client_name,"backdrop",
3478 (char *) "False");
3479 resource_info->backdrop=IsMagickTrue(resource_value);
3480 resource_info->background_color=XGetResourceInstance(database,client_name,
3481 "background",(char *) "#d6d6d6d6d6d6");
3482 resource_info->border_color=XGetResourceInstance(database,client_name,
3483 "borderColor",BorderColor);
3484 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3485 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003486 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3487 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003488 resource_value=XGetResourceClass(database,client_name,"colormap",
3489 (char *) "shared");
3490 resource_info->colormap=UndefinedColormap;
3491 if (LocaleCompare("private",resource_value) == 0)
3492 resource_info->colormap=PrivateColormap;
3493 if (LocaleCompare("shared",resource_value) == 0)
3494 resource_info->colormap=SharedColormap;
3495 if (resource_info->colormap == UndefinedColormap)
3496 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3497 resource_value);
3498 resource_value=XGetResourceClass(database,client_name,
3499 "colorRecovery",(char *) "False");
3500 resource_info->color_recovery=IsMagickTrue(resource_value);
3501 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3502 (char *) "False");
3503 resource_info->confirm_exit=IsMagickTrue(resource_value);
3504 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3505 (char *) "False");
3506 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003507 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003508 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003509 resource_info->display_gamma=XGetResourceClass(database,client_name,
3510 "displayGamma",(char *) "2.2");
3511 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3512 (char *) "True");
3513 resource_info->display_warnings=IsMagickTrue(resource_value);
3514 resource_info->font=XGetResourceClass(database,client_name,"font",
3515 (char *) NULL);
3516 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3517 resource_info->font);
3518 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3519 (char *) "fixed");
3520 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3521 (char *) "variable");
3522 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3523 (char *) "5x8");
3524 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3525 (char *) "6x10");
3526 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3527 (char *) "7x13bold");
3528 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3529 (char *) "8x13bold");
3530 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3531 (char *) "9x15bold");
3532 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3533 (char *) "10x20");
3534 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3535 (char *) "12x24");
3536 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3537 (char *) "fixed");
3538 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3539 (char *) "fixed");
3540 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3541 "foreground",ForegroundColor);
3542 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3543 (char *) "True");
3544 resource_info->gamma_correct=IsMagickTrue(resource_value);
3545 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3546 client_name,"geometry",(char *) NULL));
3547 resource_value=XGetResourceClass(database,client_name,"gravity",
3548 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003549 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003550 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003551 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3552 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003553 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3554 "iconGeometry",(char *) NULL);
3555 resource_value=XGetResourceClass(database,client_name,"iconic",
3556 (char *) "False");
3557 resource_info->iconic=IsMagickTrue(resource_value);
3558 resource_value=XGetResourceClass(database,client_name,"immutable",
3559 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3560 (char *) "False");
3561 resource_info->immutable=IsMagickTrue(resource_value);
3562 resource_value=XGetResourceClass(database,client_name,"magnify",
3563 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003564 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003565 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3566 (char *) NULL);
3567 resource_info->matte_color=XGetResourceInstance(database,client_name,
3568 "mattecolor",(char *) NULL);
3569 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3570 "name",(char *) NULL));
3571 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3572 (char *) "black");
3573 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3574 (char *) "blue");
3575 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3576 (char *) "cyan");
3577 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3578 (char *) "green");
3579 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3580 (char *) "gray");
3581 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3582 (char *) "red");
3583 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3584 (char *) "magenta");
3585 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3586 (char *) "yellow");
3587 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3588 (char *) "white");
3589 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3590 (char *) "gray");
3591 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3592 (char *) "gray");
3593 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003594 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003595 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003596 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003597 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3598 "font",(char *) "fixed");
3599 resource_info->text_font=XGetResourceClass(database,client_name,
3600 "textFontList",resource_info->text_font);
3601 resource_info->title=XGetResourceClass(database,client_name,"title",
3602 (char *) NULL);
3603 resource_value=XGetResourceClass(database,client_name,"undoCache",
3604 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003605 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003606 resource_value=XGetResourceClass(database,client_name,"update",
3607 (char *) "False");
3608 resource_info->update=IsMagickTrue(resource_value);
3609 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3610 (char *) "True");
3611 resource_info->use_pixmap=IsMagickTrue(resource_value);
3612 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3613 (char *) "True");
3614 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3615 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3616 (char *) NULL);
3617 resource_info->window_group=XGetResourceClass(database,client_name,
3618 "windowGroup",(char *) NULL);
3619 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3620 (char *) NULL);
3621 resource_info->write_filename=XGetResourceClass(database,client_name,
3622 "writeFilename",(char *) NULL);
3623}
3624
3625/*
3626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3627% %
3628% %
3629% %
3630% X G e t R e s o u r c e I n s t a n c e %
3631% %
3632% %
3633% %
3634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3635%
3636% XGetResourceInstance() queries the X server for the specified resource name.
3637% If the resource name is not defined in the database, the supplied default
3638% value is returned.
3639%
3640% The format of the XGetResourceInstance method is:
3641%
3642% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3643% const char *keyword,const char *resource_default)
3644%
3645% A description of each parameter follows:
3646%
3647% o database: Specifies a resource database; returned from
3648% XrmGetStringDatabase.
3649%
3650% o client_name: Specifies the application name used to retrieve
3651% resource info from the X server database.
3652%
3653% o keyword: Specifies the keyword of the value being retrieved.
3654%
3655% o resource_default: Specifies the default value to return if the query
3656% fails to find the specified keyword/class.
3657%
3658*/
3659MagickExport char *XGetResourceInstance(XrmDatabase database,
3660 const char *client_name,const char *keyword,const char *resource_default)
3661{
3662 char
3663 *resource_type,
3664 resource_name[MaxTextExtent];
3665
3666 Status
3667 status;
3668
3669 XrmValue
3670 resource_value;
3671
3672 if (database == (XrmDatabase) NULL)
3673 return((char *) resource_default);
3674 *resource_name='\0';
3675 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003676 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003677 keyword);
3678 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3679 &resource_value);
3680 if (status == False)
3681 return((char *) resource_default);
3682 return(resource_value.addr);
3683}
3684
3685/*
3686%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3687% %
3688% %
3689% %
3690% X G e t S c r e e n D e n s i t y %
3691% %
3692% %
3693% %
3694%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3695%
3696% XGetScreenDensity() returns the density of the X server screen in
3697% dots-per-inch.
3698%
3699% The format of the XGetScreenDensity method is:
3700%
3701% char *XGetScreenDensity(Display *display)
3702%
3703% A description of each parameter follows:
3704%
3705% o density: XGetScreenDensity() returns the density of the X screen in
3706% dots-per-inch.
3707%
3708% o display: Specifies a connection to an X server; returned from
3709% XOpenDisplay.
3710%
3711*/
3712MagickExport char *XGetScreenDensity(Display *display)
3713{
3714 char
3715 density[MaxTextExtent];
3716
3717 double
3718 x_density,
3719 y_density;
3720
3721 /*
3722 Set density as determined by screen size.
3723 */
3724 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3725 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3726 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3727 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003728 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003729 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003730 return(GetPageGeometry(density));
3731}
3732
3733/*
3734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3735% %
3736% %
3737% %
3738+ X G e t S u b w i n d o w %
3739% %
3740% %
3741% %
3742%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3743%
3744% XGetSubwindow() returns the subwindow of a window chosen the user with the
3745% pointer and a button press.
3746%
3747% The format of the XGetSubwindow method is:
3748%
3749% Window XGetSubwindow(Display *display,Window window,int x,int y)
3750%
3751% A description of each parameter follows:
3752%
3753% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3754% otherwise the subwindow is returned.
3755%
3756% o display: Specifies a connection to an X server; returned from
3757% XOpenDisplay.
3758%
3759% o window: Specifies a pointer to a Window.
3760%
3761% o x: the x coordinate of the pointer relative to the origin of the
3762% window.
3763%
3764% o y: the y coordinate of the pointer relative to the origin of the
3765% window.
3766%
cristy3ed852e2009-09-05 21:47:34 +00003767*/
3768static Window XGetSubwindow(Display *display,Window window,int x,int y)
3769{
3770 int
3771 x_offset,
3772 y_offset;
3773
3774 Status
3775 status;
3776
3777 Window
3778 source_window,
3779 target_window;
3780
3781 assert(display != (Display *) NULL);
3782 source_window=XRootWindow(display,XDefaultScreen(display));
3783 if (window == (Window) NULL)
3784 return(source_window);
3785 target_window=window;
3786 for ( ; ; )
3787 {
3788 status=XTranslateCoordinates(display,source_window,window,x,y,
3789 &x_offset,&y_offset,&target_window);
3790 if (status != True)
3791 break;
3792 if (target_window == (Window) NULL)
3793 break;
3794 source_window=window;
3795 window=target_window;
3796 x=x_offset;
3797 y=y_offset;
3798 }
3799 if (target_window == (Window) NULL)
3800 target_window=window;
3801 return(target_window);
3802}
3803
3804/*
3805%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3806% %
3807% %
3808% %
3809% X G e t W i n d o w C o l o r %
3810% %
3811% %
3812% %
3813%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3814%
3815% XGetWindowColor() returns the color of a pixel interactively chosen from the
3816% X server.
3817%
3818% The format of the XGetWindowColor method is:
3819%
3820% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3821% char *name)
3822%
3823% A description of each parameter follows:
3824%
3825% o display: Specifies a connection to an X server; returned from
3826% XOpenDisplay.
3827%
3828% o windows: Specifies a pointer to a XWindows structure.
3829%
3830% o name: the name of the color if found in the X Color Database is
3831% returned in this character string.
3832%
3833*/
3834MagickExport MagickBooleanType XGetWindowColor(Display *display,
3835 XWindows *windows,char *name)
3836{
3837 int
3838 x,
3839 y;
3840
3841 PixelPacket
3842 pixel;
3843
3844 RectangleInfo
3845 crop_info;
3846
3847 Status
3848 status;
3849
3850 Window
3851 child,
3852 client_window,
3853 root_window,
3854 target_window;
3855
3856 XColor
3857 color;
3858
3859 XImage
3860 *ximage;
3861
3862 XWindowAttributes
3863 window_attributes;
3864
3865 /*
3866 Choose a pixel from the X server.
3867 */
3868 assert(display != (Display *) NULL);
3869 assert(name != (char *) NULL);
3870 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3871 *name='\0';
3872 target_window=XSelectWindow(display,&crop_info);
3873 if (target_window == (Window) NULL)
3874 return(MagickFalse);
3875 root_window=XRootWindow(display,XDefaultScreen(display));
3876 client_window=target_window;
3877 if (target_window != root_window)
3878 {
3879 unsigned int
3880 d;
3881
3882 /*
3883 Get client window.
3884 */
3885 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3886 if (status != False)
3887 {
3888 client_window=XClientWindow(display,target_window);
3889 target_window=client_window;
3890 }
3891 }
3892 /*
3893 Verify window is viewable.
3894 */
3895 status=XGetWindowAttributes(display,target_window,&window_attributes);
3896 if ((status == False) || (window_attributes.map_state != IsViewable))
3897 return(MagickFalse);
3898 /*
3899 Get window X image.
3900 */
3901 (void) XTranslateCoordinates(display,root_window,target_window,
3902 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3903 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3904 if (ximage == (XImage *) NULL)
3905 return(MagickFalse);
3906 color.pixel=XGetPixel(ximage,0,0);
3907 XDestroyImage(ximage);
3908 /*
3909 Match color against the color database.
3910 */
3911 (void) XQueryColor(display,window_attributes.colormap,&color);
3912 pixel.red=ScaleShortToQuantum(color.red);
3913 pixel.green=ScaleShortToQuantum(color.green);
3914 pixel.blue=ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003915 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003916 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3917 &windows->image.image->exception);
3918 return(MagickTrue);
3919}
3920
3921/*
3922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3923% %
3924% %
3925% %
3926+ X G e t W i n d o w I m a g e %
3927% %
3928% %
3929% %
3930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3931%
3932% XGetWindowImage() reads an image from the target X window and returns it.
3933% XGetWindowImage() optionally descends the window hierarchy and overlays the
3934% target image with each child image in an optimized fashion. Any child
3935% window that have the same visual, colormap, and are contained by its parent
3936% are exempted.
3937%
3938% The format of the XGetWindowImage method is:
3939%
3940% Image *XGetWindowImage(Display *display,const Window window,
3941% const unsigned int borders,const unsigned int level)
3942%
3943% A description of each parameter follows:
3944%
3945% o display: Specifies a connection to an X server; returned from
3946% XOpenDisplay.
3947%
3948% o window: Specifies the window to obtain the image from.
3949%
3950% o borders: Specifies whether borders pixels are to be saved with
3951% the image.
3952%
3953% o level: Specifies an unsigned integer representing the level of
3954% decent in the window hierarchy. This value must be zero or one on
3955% the initial call to XGetWindowImage. A value of zero returns after
3956% one call. A value of one causes the function to descend the window
3957% hierarchy and overlay the target image with each subwindow image.
3958%
cristy3ed852e2009-09-05 21:47:34 +00003959*/
3960static Image *XGetWindowImage(Display *display,const Window window,
3961 const unsigned int borders,const unsigned int level)
3962{
3963 typedef struct _ColormapInfo
3964 {
3965 Colormap
3966 colormap;
3967
3968 XColor
3969 *colors;
3970
3971 struct _ColormapInfo
3972 *next;
3973 } ColormapInfo;
3974
3975 typedef struct _WindowInfo
3976 {
3977 Window
3978 window,
3979 parent;
3980
3981 Visual
3982 *visual;
3983
3984 Colormap
3985 colormap;
3986
3987 XSegment
3988 bounds;
3989
3990 RectangleInfo
3991 crop_info;
3992 } WindowInfo;
3993
cristy3ed852e2009-09-05 21:47:34 +00003994 int
3995 display_height,
3996 display_width,
3997 id,
3998 x_offset,
3999 y_offset;
4000
cristy4c08aed2011-07-01 19:47:50 +00004001 Quantum
4002 index;
4003
cristy3ed852e2009-09-05 21:47:34 +00004004 RectangleInfo
4005 crop_info;
4006
cristy3ed852e2009-09-05 21:47:34 +00004007 register int
4008 i;
4009
4010 static ColormapInfo
4011 *colormap_info = (ColormapInfo *) NULL;
4012
4013 static int
4014 max_windows = 0,
4015 number_windows = 0;
4016
4017 static WindowInfo
4018 *window_info;
4019
4020 Status
4021 status;
4022
4023 Window
4024 child,
4025 root_window;
4026
4027 XWindowAttributes
4028 window_attributes;
4029
4030 /*
4031 Verify window is viewable.
4032 */
4033 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4034 assert(display != (Display *) NULL);
4035 status=XGetWindowAttributes(display,window,&window_attributes);
4036 if ((status == False) || (window_attributes.map_state != IsViewable))
4037 return((Image *) NULL);
4038 /*
4039 Cropping rectangle is relative to root window.
4040 */
4041 root_window=XRootWindow(display,XDefaultScreen(display));
4042 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4043 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004044 crop_info.x=(ssize_t) x_offset;
4045 crop_info.y=(ssize_t) y_offset;
4046 crop_info.width=(size_t) window_attributes.width;
4047 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004048 if (borders != MagickFalse)
4049 {
4050 /*
4051 Include border in image.
4052 */
cristybb503372010-05-27 20:51:26 +00004053 crop_info.x-=(ssize_t) window_attributes.border_width;
4054 crop_info.y-=(ssize_t) window_attributes.border_width;
4055 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4056 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004057 }
4058 /*
4059 Crop to root window.
4060 */
4061 if (crop_info.x < 0)
4062 {
4063 crop_info.width+=crop_info.x;
4064 crop_info.x=0;
4065 }
4066 if (crop_info.y < 0)
4067 {
4068 crop_info.height+=crop_info.y;
4069 crop_info.y=0;
4070 }
4071 display_width=XDisplayWidth(display,XDefaultScreen(display));
4072 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004073 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004074 display_height=XDisplayHeight(display,XDefaultScreen(display));
4075 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004076 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004077 /*
4078 Initialize window info attributes.
4079 */
4080 if (number_windows >= max_windows)
4081 {
4082 /*
4083 Allocate or resize window info buffer.
4084 */
4085 max_windows+=1024;
4086 if (window_info == (WindowInfo *) NULL)
4087 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4088 sizeof(*window_info));
4089 else
4090 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4091 max_windows,sizeof(*window_info));
4092 }
4093 if (window_info == (WindowInfo *) NULL)
4094 {
4095 ThrowXWindowFatalException(ResourceLimitError,
4096 "MemoryAllocationFailed","...");
4097 return((Image *) NULL);
4098 }
4099 id=number_windows++;
4100 window_info[id].window=window;
4101 window_info[id].visual=window_attributes.visual;
4102 window_info[id].colormap=window_attributes.colormap;
4103 window_info[id].bounds.x1=(short) crop_info.x;
4104 window_info[id].bounds.y1=(short) crop_info.y;
4105 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4106 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4107 crop_info.x-=x_offset;
4108 crop_info.y-=y_offset;
4109 window_info[id].crop_info=crop_info;
4110 if (level != 0)
4111 {
4112 unsigned int
4113 number_children;
4114
4115 Window
4116 *children;
4117
4118 /*
4119 Descend the window hierarchy.
4120 */
4121 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4122 &children,&number_children);
4123 for (i=0; i < id; i++)
4124 if ((window_info[i].window == window_info[id].parent) &&
4125 (window_info[i].visual == window_info[id].visual) &&
4126 (window_info[i].colormap == window_info[id].colormap))
4127 {
4128 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4129 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4130 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4131 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4132 {
4133 /*
4134 Eliminate windows not circumscribed by their parent.
4135 */
4136 number_windows--;
4137 break;
4138 }
4139 }
4140 if ((status == True) && (number_children != 0))
4141 {
4142 for (i=0; i < (int) number_children; i++)
4143 (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4144 (void) XFree((void *) children);
4145 }
4146 }
4147 if (level <= 1)
4148 {
cristyc57f6942010-11-12 01:47:39 +00004149 CacheView
4150 *composite_view;
4151
cristy3ed852e2009-09-05 21:47:34 +00004152 ColormapInfo
4153 *next;
4154
4155 ExceptionInfo
4156 *exception;
4157
4158 Image
4159 *composite_image,
4160 *image;
4161
4162 int
4163 y;
4164
4165 MagickBooleanType
4166 import;
4167
4168 register int
4169 j,
4170 x;
4171
cristy4c08aed2011-07-01 19:47:50 +00004172 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004173 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004174
cristybb503372010-05-27 20:51:26 +00004175 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004176 pixel;
4177
4178 unsigned int
4179 number_colors;
4180
4181 XColor
4182 *colors;
4183
4184 XImage
4185 *ximage;
4186
4187 /*
4188 Get X image for each window in the list.
4189 */
4190 image=NewImageList();
4191 for (id=0; id < number_windows; id++)
4192 {
4193 /*
4194 Does target window intersect top level window?
4195 */
4196 import=
4197 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4198 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4199 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4200 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4201 MagickTrue : MagickFalse;
4202 /*
4203 Is target window contained by another window with the same colormap?
4204 */
4205 for (j=0; j < id; j++)
4206 if ((window_info[id].visual == window_info[j].visual) &&
4207 (window_info[id].colormap == window_info[j].colormap))
4208 {
4209 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4210 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4211 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4212 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4213 import=MagickFalse;
4214 }
4215 else
4216 if ((window_info[id].visual != window_info[j].visual) ||
4217 (window_info[id].colormap != window_info[j].colormap))
4218 {
4219 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4220 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4221 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4222 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4223 import=MagickTrue;
4224 }
4225 if (import == MagickFalse)
4226 continue;
4227 /*
4228 Get X image.
4229 */
4230 ximage=XGetImage(display,window_info[id].window,(int)
4231 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4232 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4233 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4234 if (ximage == (XImage *) NULL)
4235 continue;
4236 /*
4237 Initialize window colormap.
4238 */
4239 number_colors=0;
4240 colors=(XColor *) NULL;
4241 if (window_info[id].colormap != (Colormap) NULL)
4242 {
4243 ColormapInfo
4244 *p;
4245
4246 /*
4247 Search colormap list for window colormap.
4248 */
4249 number_colors=(unsigned int) window_info[id].visual->map_entries;
4250 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4251 if (p->colormap == window_info[id].colormap)
4252 break;
4253 if (p == (ColormapInfo *) NULL)
4254 {
4255 /*
4256 Get the window colormap.
4257 */
4258 colors=(XColor *) AcquireQuantumMemory(number_colors,
4259 sizeof(*colors));
4260 if (colors == (XColor *) NULL)
4261 {
4262 XDestroyImage(ximage);
4263 return((Image *) NULL);
4264 }
4265 if ((window_info[id].visual->klass != DirectColor) &&
4266 (window_info[id].visual->klass != TrueColor))
4267 for (i=0; i < (int) number_colors; i++)
4268 {
cristybb503372010-05-27 20:51:26 +00004269 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004270 colors[i].pad='\0';
4271 }
4272 else
4273 {
cristybb503372010-05-27 20:51:26 +00004274 size_t
cristy3ed852e2009-09-05 21:47:34 +00004275 blue,
4276 blue_bit,
4277 green,
4278 green_bit,
4279 red,
4280 red_bit;
4281
4282 /*
4283 DirectColor or TrueColor visual.
4284 */
4285 red=0;
4286 green=0;
4287 blue=0;
4288 red_bit=window_info[id].visual->red_mask &
4289 (~(window_info[id].visual->red_mask)+1);
4290 green_bit=window_info[id].visual->green_mask &
4291 (~(window_info[id].visual->green_mask)+1);
4292 blue_bit=window_info[id].visual->blue_mask &
4293 (~(window_info[id].visual->blue_mask)+1);
4294 for (i=0; i < (int) number_colors; i++)
4295 {
cristy8891f9c2010-06-04 23:32:17 +00004296 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004297 colors[i].pad='\0';
4298 red+=red_bit;
4299 if (red > window_info[id].visual->red_mask)
4300 red=0;
4301 green+=green_bit;
4302 if (green > window_info[id].visual->green_mask)
4303 green=0;
4304 blue+=blue_bit;
4305 if (blue > window_info[id].visual->blue_mask)
4306 blue=0;
4307 }
4308 }
4309 (void) XQueryColors(display,window_info[id].colormap,colors,
4310 (int) number_colors);
4311 /*
4312 Append colormap to colormap list.
4313 */
cristy73bd4a52010-10-05 11:24:23 +00004314 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004315 if (p == (ColormapInfo *) NULL)
4316 return((Image *) NULL);
4317 p->colormap=window_info[id].colormap;
4318 p->colors=colors;
4319 p->next=colormap_info;
4320 colormap_info=p;
4321 }
4322 colors=p->colors;
4323 }
4324 /*
4325 Allocate image structure.
4326 */
4327 composite_image=AcquireImage((ImageInfo *) NULL);
4328 if (composite_image == (Image *) NULL)
4329 {
4330 XDestroyImage(ximage);
4331 return((Image *) NULL);
4332 }
4333 /*
4334 Convert X image to MIFF format.
4335 */
4336 if ((window_info[id].visual->klass != TrueColor) &&
4337 (window_info[id].visual->klass != DirectColor))
4338 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004339 composite_image->columns=(size_t) ximage->width;
4340 composite_image->rows=(size_t) ximage->height;
cristy3ed852e2009-09-05 21:47:34 +00004341 exception=(&composite_image->exception);
cristyc57f6942010-11-12 01:47:39 +00004342 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004343 switch (composite_image->storage_class)
4344 {
4345 case DirectClass:
4346 default:
4347 {
cristybb503372010-05-27 20:51:26 +00004348 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004349 color,
4350 index;
4351
cristybb503372010-05-27 20:51:26 +00004352 size_t
cristy3ed852e2009-09-05 21:47:34 +00004353 blue_mask,
4354 blue_shift,
4355 green_mask,
4356 green_shift,
4357 red_mask,
4358 red_shift;
4359
4360 /*
4361 Determine shift and mask for red, green, and blue.
4362 */
4363 red_mask=window_info[id].visual->red_mask;
4364 red_shift=0;
4365 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4366 {
4367 red_mask>>=1;
4368 red_shift++;
4369 }
4370 green_mask=window_info[id].visual->green_mask;
4371 green_shift=0;
4372 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4373 {
4374 green_mask>>=1;
4375 green_shift++;
4376 }
4377 blue_mask=window_info[id].visual->blue_mask;
4378 blue_shift=0;
4379 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4380 {
4381 blue_mask>>=1;
4382 blue_shift++;
4383 }
4384 /*
4385 Convert X image to DirectClass packets.
4386 */
4387 if ((number_colors != 0) &&
4388 (window_info[id].visual->klass == DirectColor))
4389 for (y=0; y < (int) composite_image->rows; y++)
4390 {
cristyc57f6942010-11-12 01:47:39 +00004391 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004392 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004393 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004394 break;
4395 for (x=0; x < (int) composite_image->columns; x++)
4396 {
4397 pixel=XGetPixel(ximage,x,y);
4398 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004399 SetPixelRed(composite_image,
4400 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004401 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004402 SetPixelGreen(composite_image,
4403 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004404 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004405 SetPixelBlue(composite_image,
4406 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004407 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004408 }
cristyc57f6942010-11-12 01:47:39 +00004409 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004410 break;
4411 }
4412 else
4413 for (y=0; y < (int) composite_image->rows; y++)
4414 {
cristyc57f6942010-11-12 01:47:39 +00004415 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004416 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004417 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004418 break;
4419 for (x=0; x < (int) composite_image->columns; x++)
4420 {
4421 pixel=XGetPixel(ximage,x,y);
4422 color=(pixel >> red_shift) & red_mask;
4423 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004424 SetPixelRed(composite_image,
4425 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004426 color=(pixel >> green_shift) & green_mask;
4427 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004428 SetPixelGreen(composite_image,
4429 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004430 color=(pixel >> blue_shift) & blue_mask;
4431 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004432 SetPixelBlue(composite_image,
4433 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004434 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004435 }
cristyc57f6942010-11-12 01:47:39 +00004436 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004437 break;
4438 }
4439 break;
4440 }
4441 case PseudoClass:
4442 {
4443 /*
4444 Create colormap.
4445 */
4446 if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
4447 {
4448 XDestroyImage(ximage);
4449 composite_image=DestroyImage(composite_image);
4450 return((Image *) NULL);
4451 }
4452 for (i=0; i < (int) composite_image->colors; i++)
4453 {
4454 composite_image->colormap[colors[i].pixel].red=
4455 ScaleShortToQuantum(colors[i].red);
4456 composite_image->colormap[colors[i].pixel].green=
4457 ScaleShortToQuantum(colors[i].green);
4458 composite_image->colormap[colors[i].pixel].blue=
4459 ScaleShortToQuantum(colors[i].blue);
4460 }
4461 /*
4462 Convert X image to PseudoClass packets.
4463 */
4464 for (y=0; y < (int) composite_image->rows; y++)
4465 {
cristyc57f6942010-11-12 01:47:39 +00004466 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4467 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004468 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004469 break;
cristy3ed852e2009-09-05 21:47:34 +00004470 for (x=0; x < (int) composite_image->columns; x++)
4471 {
cristy4c08aed2011-07-01 19:47:50 +00004472 index=(Quantum) XGetPixel(ximage,x,y);
4473 SetPixelIndex(composite_image,index,q);
4474 SetPixelPacket(composite_image,
4475 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004476 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004477 }
cristyc57f6942010-11-12 01:47:39 +00004478 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004479 break;
4480 }
4481 break;
4482 }
4483 }
cristyc57f6942010-11-12 01:47:39 +00004484 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004485 XDestroyImage(ximage);
4486 if (image == (Image *) NULL)
4487 {
4488 image=composite_image;
4489 continue;
4490 }
4491 /*
4492 Composite any children in back-to-front order.
4493 */
4494 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4495 &x_offset,&y_offset,&child);
4496 x_offset-=(int) crop_info.x;
4497 if (x_offset < 0)
4498 x_offset=0;
4499 y_offset-=(int) crop_info.y;
4500 if (y_offset < 0)
4501 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004502 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
4503 x_offset,(ssize_t) y_offset);
cristy3ed852e2009-09-05 21:47:34 +00004504 }
4505 /*
4506 Relinquish resources.
4507 */
4508 while (colormap_info != (ColormapInfo *) NULL)
4509 {
4510 next=colormap_info->next;
4511 colormap_info->colors=(XColor *)
4512 RelinquishMagickMemory(colormap_info->colors);
4513 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4514 colormap_info=next;
4515 }
4516 /*
4517 Relinquish resources and restore initial state.
4518 */
4519 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4520 max_windows=0;
4521 number_windows=0;
4522 colormap_info=(ColormapInfo *) NULL;
4523 return(image);
4524 }
4525 return((Image *) NULL);
4526}
4527
4528/*
4529%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4530% %
4531% %
4532% %
4533% X G e t W i n d o w I n f o %
4534% %
4535% %
4536% %
4537%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4538%
4539% XGetWindowInfo() initializes the XWindowInfo structure.
4540%
4541% The format of the XGetWindowInfo method is:
4542%
4543% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4544% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4545% XResourceInfo *resource_info,XWindowInfo *window)
4546% resource_info,window)
4547%
4548% A description of each parameter follows:
4549%
4550% o display: Specifies a connection to an X server; returned from
4551% XOpenDisplay.
4552%
4553% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4554% returned from XGetVisualInfo.
4555%
4556% o map_info: If map_type is specified, this structure is initialized
4557% with info from the Standard Colormap.
4558%
4559% o pixel: Specifies a pointer to a XPixelInfo structure.
4560%
4561% o font_info: Specifies a pointer to a XFontStruct structure.
4562%
4563% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4564%
4565*/
4566MagickExport void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4567 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4568 XResourceInfo *resource_info,XWindowInfo *window)
4569{
4570 /*
4571 Initialize window info.
4572 */
4573 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4574 assert(display != (Display *) NULL);
4575 assert(visual_info != (XVisualInfo *) NULL);
4576 assert(map_info != (XStandardColormap *) NULL);
4577 assert(pixel != (XPixelInfo *) NULL);
4578 assert(resource_info != (XResourceInfo *) NULL);
4579 assert(window != (XWindowInfo *) NULL);
4580 if (window->id != (Window) NULL)
4581 {
4582 if (window->cursor != (Cursor) NULL)
4583 (void) XFreeCursor(display,window->cursor);
4584 if (window->busy_cursor != (Cursor) NULL)
4585 (void) XFreeCursor(display,window->busy_cursor);
4586 if (window->highlight_stipple != (Pixmap) NULL)
4587 (void) XFreePixmap(display,window->highlight_stipple);
4588 if (window->shadow_stipple != (Pixmap) NULL)
4589 (void) XFreePixmap(display,window->shadow_stipple);
4590 if (window->name == (char *) NULL)
4591 window->name=AcquireString("");
4592 if (window->icon_name == (char *) NULL)
4593 window->icon_name=AcquireString("");
4594 }
4595 else
4596 {
4597 /*
4598 Initialize these attributes just once.
4599 */
4600 window->id=(Window) NULL;
4601 if (window->name == (char *) NULL)
4602 window->name=AcquireString("");
4603 if (window->icon_name == (char *) NULL)
4604 window->icon_name=AcquireString("");
4605 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4606 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4607 window->ximage=(XImage *) NULL;
4608 window->matte_image=(XImage *) NULL;
4609 window->pixmap=(Pixmap) NULL;
4610 window->matte_pixmap=(Pixmap) NULL;
4611 window->mapped=MagickFalse;
4612 window->stasis=MagickFalse;
4613 window->shared_memory=MagickTrue;
4614 window->segment_info=(void *) NULL;
4615#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4616 {
4617 XShmSegmentInfo
4618 *segment_info;
4619
4620 if (window->segment_info == (void *) NULL)
4621 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4622 segment_info=(XShmSegmentInfo *) window->segment_info;
4623 segment_info[0].shmid=(-1);
4624 segment_info[0].shmaddr=(char *) NULL;
4625 segment_info[1].shmid=(-1);
4626 segment_info[1].shmaddr=(char *) NULL;
4627 }
4628#endif
4629 }
4630 /*
4631 Initialize these attributes every time function is called.
4632 */
4633 window->screen=visual_info->screen;
4634 window->root=XRootWindow(display,visual_info->screen);
4635 window->visual=visual_info->visual;
4636 window->storage_class=(unsigned int) visual_info->klass;
4637 window->depth=(unsigned int) visual_info->depth;
4638 window->visual_info=visual_info;
4639 window->map_info=map_info;
4640 window->pixel_info=pixel;
4641 window->font_info=font_info;
4642 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4643 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4644 window->geometry=(char *) NULL;
4645 window->icon_geometry=(char *) NULL;
4646 if (resource_info->icon_geometry != (char *) NULL)
4647 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4648 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004649 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004650 window->width=1;
4651 window->height=1;
4652 window->min_width=1;
4653 window->min_height=1;
4654 window->width_inc=1;
4655 window->height_inc=1;
4656 window->border_width=resource_info->border_width;
4657 window->annotate_context=pixel->annotate_context;
4658 window->highlight_context=pixel->highlight_context;
4659 window->widget_context=pixel->widget_context;
4660 window->shadow_stipple=(Pixmap) NULL;
4661 window->highlight_stipple=(Pixmap) NULL;
4662 window->use_pixmap=MagickTrue;
4663 window->immutable=MagickFalse;
4664 window->shape=MagickFalse;
4665 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004666 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004667 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4668 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4669 window->attributes.background_pixel=pixel->background_color.pixel;
4670 window->attributes.background_pixmap=(Pixmap) NULL;
4671 window->attributes.bit_gravity=ForgetGravity;
4672 window->attributes.backing_store=WhenMapped;
4673 window->attributes.save_under=MagickTrue;
4674 window->attributes.border_pixel=pixel->border_color.pixel;
4675 window->attributes.colormap=map_info->colormap;
4676 window->attributes.cursor=window->cursor;
4677 window->attributes.do_not_propagate_mask=NoEventMask;
4678 window->attributes.event_mask=NoEventMask;
4679 window->attributes.override_redirect=MagickFalse;
4680 window->attributes.win_gravity=NorthWestGravity;
4681 window->orphan=MagickFalse;
4682}
4683
4684/*
4685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4686% %
4687% %
4688% %
4689% X H i g h l i g h t E l l i p s e %
4690% %
4691% %
4692% %
4693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4694%
4695% XHighlightEllipse() puts a border on the X server around a region defined by
4696% highlight_info.
4697%
4698% The format of the XHighlightEllipse method is:
4699%
4700% void XHighlightEllipse(Display *display,Window window,
4701% GC annotate_context,const RectangleInfo *highlight_info)
4702%
4703% A description of each parameter follows:
4704%
4705% o display: Specifies a connection to an X server; returned from
4706% XOpenDisplay.
4707%
4708% o window: Specifies a pointer to a Window structure.
4709%
4710% o annotate_context: Specifies a pointer to a GC structure.
4711%
4712% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4713% contains the extents of any highlighting rectangle.
4714%
4715*/
4716MagickExport void XHighlightEllipse(Display *display,Window window,
4717 GC annotate_context,const RectangleInfo *highlight_info)
4718{
4719 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4720 assert(display != (Display *) NULL);
4721 assert(window != (Window) NULL);
4722 assert(annotate_context != (GC) NULL);
4723 assert(highlight_info != (RectangleInfo *) NULL);
4724 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4725 return;
4726 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4727 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4728 (unsigned int) highlight_info->height-1,0,360*64);
4729 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4730 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4731 (unsigned int) highlight_info->height-3,0,360*64);
4732}
4733
4734/*
4735%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4736% %
4737% %
4738% %
4739% X H i g h l i g h t L i n e %
4740% %
4741% %
4742% %
4743%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4744%
4745% XHighlightLine() puts a border on the X server around a region defined by
4746% highlight_info.
4747%
4748% The format of the XHighlightLine method is:
4749%
4750% void XHighlightLine(Display *display,Window window,GC annotate_context,
4751% const XSegment *highlight_info)
4752%
4753% A description of each parameter follows:
4754%
4755% o display: Specifies a connection to an X server; returned from
4756% XOpenDisplay.
4757%
4758% o window: Specifies a pointer to a Window structure.
4759%
4760% o annotate_context: Specifies a pointer to a GC structure.
4761%
4762% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4763% contains the extents of any highlighting rectangle.
4764%
4765*/
4766MagickExport void XHighlightLine(Display *display,Window window,
4767 GC annotate_context,const XSegment *highlight_info)
4768{
4769 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4770 assert(display != (Display *) NULL);
4771 assert(window != (Window) NULL);
4772 assert(annotate_context != (GC) NULL);
4773 assert(highlight_info != (XSegment *) NULL);
4774 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4775 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4776}
4777
4778/*
4779%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4780% %
4781% %
4782% %
4783% X H i g h l i g h t R e c t a n g l e %
4784% %
4785% %
4786% %
4787%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4788%
4789% XHighlightRectangle() puts a border on the X server around a region defined
4790% by highlight_info.
4791%
4792% The format of the XHighlightRectangle method is:
4793%
4794% void XHighlightRectangle(Display *display,Window window,
4795% GC annotate_context,const RectangleInfo *highlight_info)
4796%
4797% A description of each parameter follows:
4798%
4799% o display: Specifies a connection to an X server; returned from
4800% XOpenDisplay.
4801%
4802% o window: Specifies a pointer to a Window structure.
4803%
4804% o annotate_context: Specifies a pointer to a GC structure.
4805%
4806% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4807% contains the extents of any highlighting rectangle.
4808%
4809*/
4810MagickExport void XHighlightRectangle(Display *display,Window window,
4811 GC annotate_context,const RectangleInfo *highlight_info)
4812{
4813 assert(display != (Display *) NULL);
4814 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4815 assert(window != (Window) NULL);
4816 assert(annotate_context != (GC) NULL);
4817 assert(highlight_info != (RectangleInfo *) NULL);
4818 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4819 return;
4820 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4821 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4822 (unsigned int) highlight_info->height-1);
4823 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4824 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4825 (unsigned int) highlight_info->height-3);
4826}
4827
4828/*
4829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4830% %
4831% %
4832% %
4833% X I m p o r t I m a g e %
4834% %
4835% %
4836% %
4837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4838%
4839% XImportImage() reads an image from an X window.
4840%
4841% The format of the XImportImage method is:
4842%
4843% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4844%
4845% A description of each parameter follows:
4846%
4847% o image_info: the image info.
4848%
4849% o ximage_info: Specifies a pointer to an XImportInfo structure.
4850%
4851*/
4852MagickExport Image *XImportImage(const ImageInfo *image_info,
4853 XImportInfo *ximage_info)
4854{
4855 Colormap
4856 *colormaps;
4857
4858 Display
4859 *display;
4860
4861 Image
4862 *image;
4863
4864 int
4865 number_colormaps,
4866 number_windows,
4867 x;
4868
4869 RectangleInfo
4870 crop_info;
4871
4872 Status
4873 status;
4874
4875 Window
4876 *children,
4877 client,
4878 prior_target,
4879 root,
4880 target;
4881
4882 XTextProperty
4883 window_name;
4884
4885 /*
4886 Open X server connection.
4887 */
4888 assert(image_info != (const ImageInfo *) NULL);
4889 assert(image_info->signature == MagickSignature);
4890 if (image_info->debug != MagickFalse)
4891 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4892 image_info->filename);
4893 assert(ximage_info != (XImportInfo *) NULL);
4894 display=XOpenDisplay(image_info->server_name);
4895 if (display == (Display *) NULL)
4896 {
4897 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4898 XDisplayName(image_info->server_name));
4899 return((Image *) NULL);
4900 }
4901 /*
4902 Set our forgiving exception handler.
4903 */
4904 (void) XSetErrorHandler(XError);
4905 /*
4906 Select target window.
4907 */
4908 crop_info.x=0;
4909 crop_info.y=0;
4910 crop_info.width=0;
4911 crop_info.height=0;
4912 root=XRootWindow(display,XDefaultScreen(display));
4913 target=(Window) NULL;
4914 if ((image_info->filename != (char *) NULL) &&
4915 (*image_info->filename != '\0'))
4916 {
4917 if (LocaleCompare(image_info->filename,"root") == 0)
4918 target=root;
4919 else
4920 {
4921 /*
4922 Select window by ID or name.
4923 */
4924 if (isdigit((unsigned char) *image_info->filename) != 0)
4925 target=XWindowByID(display,root,(Window)
4926 strtol(image_info->filename,(char **) NULL,0));
4927 if (target == (Window) NULL)
4928 target=XWindowByName(display,root,image_info->filename);
4929 if (target == (Window) NULL)
4930 ThrowXWindowFatalException(XServerError,
4931 "NoWindowWithSpecifiedIDExists",image_info->filename);
4932 }
4933 }
4934 /*
4935 If target window is not defined, interactively select one.
4936 */
4937 prior_target=target;
4938 if (target == (Window) NULL)
4939 target=XSelectWindow(display,&crop_info);
4940 if (target == (Window) NULL)
4941 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4942 image_info->filename);
4943 client=target; /* obsolete */
4944 if (target != root)
4945 {
4946 unsigned int
4947 d;
4948
4949 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4950 if (status != False)
4951 {
4952 for ( ; ; )
4953 {
4954 Window
4955 parent;
4956
4957 /*
4958 Find window manager frame.
4959 */
4960 status=XQueryTree(display,target,&root,&parent,&children,&d);
4961 if ((status != False) && (children != (Window *) NULL))
4962 (void) XFree((char *) children);
4963 if ((status == False) || (parent == (Window) NULL) ||
4964 (parent == root))
4965 break;
4966 target=parent;
4967 }
4968 /*
4969 Get client window.
4970 */
4971 client=XClientWindow(display,target);
4972 if (ximage_info->frame == MagickFalse)
4973 target=client;
4974 if ((ximage_info->frame == MagickFalse) &&
4975 (prior_target != MagickFalse))
4976 target=prior_target;
4977 XDelay(display,SuspendTime << 4);
4978 }
4979 }
4980 if (ximage_info->screen)
4981 {
4982 int
4983 y;
4984
4985 Window
4986 child;
4987
4988 XWindowAttributes
4989 window_attributes;
4990
4991 /*
4992 Obtain window image directly from screen.
4993 */
4994 status=XGetWindowAttributes(display,target,&window_attributes);
4995 if (status == False)
4996 {
4997 ThrowXWindowFatalException(XServerError,
4998 "UnableToReadXWindowAttributes",image_info->filename);
4999 (void) XCloseDisplay(display);
5000 return((Image *) NULL);
5001 }
5002 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005003 crop_info.x=(ssize_t) x;
5004 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005005 crop_info.width=(size_t) window_attributes.width;
5006 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005007 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005008 {
5009 /*
5010 Include border in image.
5011 */
5012 crop_info.x-=window_attributes.border_width;
5013 crop_info.y-=window_attributes.border_width;
5014 crop_info.width+=window_attributes.border_width << 1;
5015 crop_info.height+=window_attributes.border_width << 1;
5016 }
5017 target=root;
5018 }
5019 /*
5020 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5021 */
5022 number_windows=0;
5023 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5024 if ((status == True) && (number_windows > 0))
5025 {
5026 ximage_info->descend=MagickTrue;
5027 (void) XFree ((char *) children);
5028 }
5029 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5030 if (number_colormaps > 0)
5031 {
5032 if (number_colormaps > 1)
5033 ximage_info->descend=MagickTrue;
5034 (void) XFree((char *) colormaps);
5035 }
5036 /*
5037 Alert the user not to alter the screen.
5038 */
5039 if (ximage_info->silent == MagickFalse)
5040 (void) XBell(display,0);
5041 /*
5042 Get image by window id.
5043 */
5044 (void) XGrabServer(display);
5045 image=XGetWindowImage(display,target,ximage_info->borders,
5046 ximage_info->descend ? 1U : 0U);
5047 (void) XUngrabServer(display);
5048 if (image == (Image *) NULL)
5049 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5050 image_info->filename)
5051 else
5052 {
5053 (void) CopyMagickString(image->filename,image_info->filename,
5054 MaxTextExtent);
5055 if ((crop_info.width != 0) && (crop_info.height != 0))
5056 {
5057 Image
5058 *clone_image,
5059 *crop_image;
5060
5061 /*
5062 Crop image as defined by the cropping rectangle.
5063 */
5064 clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5065 if (clone_image != (Image *) NULL)
5066 {
5067 crop_image=CropImage(clone_image,&crop_info,&image->exception);
5068 if (crop_image != (Image *) NULL)
5069 {
5070 image=DestroyImage(image);
5071 image=crop_image;
5072 }
5073 }
5074 }
5075 status=XGetWMName(display,target,&window_name);
5076 if (status == True)
5077 {
5078 if ((image_info->filename != (char *) NULL) &&
5079 (*image_info->filename == '\0'))
5080 (void) CopyMagickString(image->filename,(char *) window_name.value,
5081 (size_t) window_name.nitems+1);
5082 (void) XFree((void *) window_name.value);
5083 }
5084 }
5085 if (ximage_info->silent == MagickFalse)
5086 {
5087 /*
5088 Alert the user we're done.
5089 */
5090 (void) XBell(display,0);
5091 (void) XBell(display,0);
5092 }
5093 (void) XCloseDisplay(display);
5094 return(image);
5095}
5096
5097/*
5098%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5099% %
5100% %
5101% %
5102% X I n i t i a l i z e W i n d o w s %
5103% %
5104% %
5105% %
5106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5107%
5108% XInitializeWindows() initializes the XWindows structure.
5109%
5110% The format of the XInitializeWindows method is:
5111%
5112% XWindows *XInitializeWindows(Display *display,
5113% XResourceInfo *resource_info)
5114%
5115% A description of each parameter follows:
5116%
5117% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5118%
5119% o display: Specifies a connection to an X server; returned from
5120% XOpenDisplay.
5121%
5122% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5123%
5124*/
5125MagickExport XWindows *XInitializeWindows(Display *display,
5126 XResourceInfo *resource_info)
5127{
5128 Window
5129 root_window;
5130
5131 XWindows
5132 *windows;
5133
5134 /*
5135 Allocate windows structure.
5136 */
cristy73bd4a52010-10-05 11:24:23 +00005137 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005138 if (windows == (XWindows *) NULL)
5139 {
5140 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5141 "...");
5142 return((XWindows *) NULL);
5143 }
5144 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5145 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5146 sizeof(*windows->pixel_info));
5147 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5148 sizeof(*windows->icon_pixel));
5149 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5150 sizeof(*windows->icon_resources));
5151 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5152 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5153 (windows->icon_resources == (XResourceInfo *) NULL))
5154 {
5155 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5156 "...");
5157 return((XWindows *) NULL);
5158 }
5159 /*
5160 Initialize windows structure.
5161 */
5162 windows->display=display;
5163 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5164 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5165 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5166 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5167 windows->im_remote_command=
5168 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5169 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5170 windows->im_update_colormap=
5171 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5172 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5173 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5174 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5175 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5176 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005177#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005178 (void) XSynchronize(display,IsWindows95());
5179#endif
5180 if (IsEventLogging())
5181 {
5182 (void) XSynchronize(display,MagickTrue);
5183 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005184 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005185 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5186 (void) LogMagickEvent(X11Event,GetMagickModule(),
5187 " Window Manager: 0x%lx",windows->wm_protocols);
5188 (void) LogMagickEvent(X11Event,GetMagickModule(),
5189 " delete window: 0x%lx",windows->wm_delete_window);
5190 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5191 windows->wm_take_focus);
5192 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5193 windows->im_protocols);
5194 (void) LogMagickEvent(X11Event,GetMagickModule(),
5195 " remote command: 0x%lx",windows->im_remote_command);
5196 (void) LogMagickEvent(X11Event,GetMagickModule(),
5197 " update widget: 0x%lx",windows->im_update_widget);
5198 (void) LogMagickEvent(X11Event,GetMagickModule(),
5199 " update colormap: 0x%lx",windows->im_update_colormap);
5200 (void) LogMagickEvent(X11Event,GetMagickModule(),
5201 " former image: 0x%lx",windows->im_former_image);
5202 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5203 windows->im_next_image);
5204 (void) LogMagickEvent(X11Event,GetMagickModule(),
5205 " retain colors: 0x%lx",windows->im_retain_colors);
5206 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5207 windows->im_exit);
5208 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5209 windows->dnd_protocols);
5210 }
5211 /*
5212 Allocate standard colormap.
5213 */
5214 windows->map_info=XAllocStandardColormap();
5215 windows->icon_map=XAllocStandardColormap();
5216 if ((windows->map_info == (XStandardColormap *) NULL) ||
5217 (windows->icon_map == (XStandardColormap *) NULL))
5218 ThrowXWindowFatalException(ResourceLimitFatalError,
5219 "MemoryAllocationFailed","...");
5220 windows->map_info->colormap=(Colormap) NULL;
5221 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005222 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005223 windows->pixel_info->annotate_context=(GC) NULL;
5224 windows->pixel_info->highlight_context=(GC) NULL;
5225 windows->pixel_info->widget_context=(GC) NULL;
5226 windows->font_info=(XFontStruct *) NULL;
5227 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005228 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005229 /*
5230 Allocate visual.
5231 */
5232 *windows->icon_resources=(*resource_info);
5233 windows->icon_resources->visual_type=(char *) "default";
5234 windows->icon_resources->colormap=SharedColormap;
5235 windows->visual_info=
5236 XBestVisualInfo(display,windows->map_info,resource_info);
5237 windows->icon_visual=
5238 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5239 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5240 (windows->icon_visual == (XVisualInfo *) NULL))
5241 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5242 resource_info->visual_type);
5243 if (IsEventLogging())
5244 {
5245 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5246 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5247 windows->visual_info->visualid);
5248 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5249 XVisualClassName(windows->visual_info->klass));
5250 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5251 windows->visual_info->depth);
5252 (void) LogMagickEvent(X11Event,GetMagickModule(),
5253 " size of colormap: %d entries",windows->visual_info->colormap_size);
5254 (void) LogMagickEvent(X11Event,GetMagickModule(),
5255 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5256 windows->visual_info->red_mask,windows->visual_info->green_mask,
5257 windows->visual_info->blue_mask);
5258 (void) LogMagickEvent(X11Event,GetMagickModule(),
5259 " significant bits in color: %d bits",
5260 windows->visual_info->bits_per_rgb);
5261 }
5262 /*
5263 Allocate class and manager hints.
5264 */
5265 windows->class_hints=XAllocClassHint();
5266 windows->manager_hints=XAllocWMHints();
5267 if ((windows->class_hints == (XClassHint *) NULL) ||
5268 (windows->manager_hints == (XWMHints *) NULL))
5269 ThrowXWindowFatalException(ResourceLimitFatalError,
5270 "MemoryAllocationFailed","...");
5271 /*
5272 Determine group leader if we have one.
5273 */
5274 root_window=XRootWindow(display,windows->visual_info->screen);
5275 windows->group_leader.id=(Window) NULL;
5276 if (resource_info->window_group != (char *) NULL)
5277 {
5278 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5279 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5280 strtol((char *) resource_info->window_group,(char **) NULL,0));
5281 if (windows->group_leader.id == (Window) NULL)
5282 windows->group_leader.id=
5283 XWindowByName(display,root_window,resource_info->window_group);
5284 }
5285 return(windows);
5286}
5287
5288/*
5289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5290% %
5291% %
5292% %
5293% X M a k e C u r s o r %
5294% %
5295% %
5296% %
5297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5298%
5299% XMakeCursor() creates a crosshairs X11 cursor.
5300%
5301% The format of the XMakeCursor method is:
5302%
5303% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5304% char *background_color,char *foreground_color)
5305%
5306% A description of each parameter follows:
5307%
5308% o display: Specifies a connection to an X server; returned from
5309% XOpenDisplay.
5310%
5311% o window: Specifies the ID of the window for which the cursor is
5312% assigned.
5313%
5314% o colormap: Specifies the ID of the colormap from which the background
5315% and foreground color will be retrieved.
5316%
5317% o background_color: Specifies the color to use for the cursor background.
5318%
5319% o foreground_color: Specifies the color to use for the cursor foreground.
5320%
5321*/
5322MagickExport Cursor XMakeCursor(Display *display,Window window,
5323 Colormap colormap,char *background_color,char *foreground_color)
5324{
5325#define scope_height 17
5326#define scope_x_hot 8
5327#define scope_y_hot 8
5328#define scope_width 17
5329
5330 static const unsigned char
5331 scope_bits[] =
5332 {
5333 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5334 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5335 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5336 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5337 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5338 },
5339 scope_mask_bits[] =
5340 {
5341 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5342 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5343 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5344 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5345 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5346 };
5347
5348 Cursor
5349 cursor;
5350
5351 Pixmap
5352 mask,
5353 source;
5354
5355 XColor
5356 background,
5357 foreground;
5358
5359 assert(display != (Display *) NULL);
5360 assert(window != (Window) NULL);
5361 assert(colormap != (Colormap) NULL);
5362 assert(background_color != (char *) NULL);
5363 assert(foreground_color != (char *) NULL);
5364 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5365 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5366 scope_height);
5367 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5368 scope_width,scope_height);
5369 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5370 {
5371 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5372 return((Cursor) NULL);
5373 }
5374 (void) XParseColor(display,colormap,background_color,&background);
5375 (void) XParseColor(display,colormap,foreground_color,&foreground);
5376 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5377 scope_x_hot,scope_y_hot);
5378 (void) XFreePixmap(display,source);
5379 (void) XFreePixmap(display,mask);
5380 return(cursor);
5381}
5382
5383/*
5384%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5385% %
5386% %
5387% %
5388% X M a k e I m a g e %
5389% %
5390% %
5391% %
5392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5393%
5394% XMakeImage() creates an X11 image. If the image size differs from the X11
5395% image size, the image is first resized.
5396%
5397% The format of the XMakeImage method is:
5398%
5399% MagickBooleanType XMakeImage(Display *display,
5400% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005401% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005402%
5403% A description of each parameter follows:
5404%
5405% o display: Specifies a connection to an X server; returned from
5406% XOpenDisplay.
5407%
5408% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5409%
5410% o window: Specifies a pointer to a XWindowInfo structure.
5411%
5412% o image: the image.
5413%
5414% o width: Specifies the width in pixels of the rectangular area to
5415% display.
5416%
5417% o height: Specifies the height in pixels of the rectangular area to
5418% display.
5419%
cristy051718b2011-08-28 22:49:25 +00005420% o exception: return any errors or warnings in this structure.
5421%
cristy3ed852e2009-09-05 21:47:34 +00005422*/
5423MagickExport MagickBooleanType XMakeImage(Display *display,
5424 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005425 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005426{
5427#define CheckOverflowException(length,width,height) \
5428 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5429
5430 int
5431 depth,
5432 format;
5433
5434 size_t
5435 length;
5436
5437 XImage
5438 *matte_image,
5439 *ximage;
5440
5441 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5442 assert(display != (Display *) NULL);
5443 assert(resource_info != (XResourceInfo *) NULL);
5444 assert(window != (XWindowInfo *) NULL);
5445 assert(width != 0);
5446 assert(height != 0);
5447 if ((window->width == 0) || (window->height == 0))
5448 return(MagickFalse);
5449 /*
5450 Apply user transforms to the image.
5451 */
5452 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5453 (void) XFlush(display);
5454 depth=(int) window->depth;
5455 if (window->destroy)
5456 window->image=DestroyImage(window->image);
5457 window->image=image;
5458 window->destroy=MagickFalse;
5459 if (window->image != (Image *) NULL)
5460 {
5461 if (window->crop_geometry != (char *) NULL)
5462 {
5463 Image
5464 *crop_image;
5465
5466 RectangleInfo
5467 crop_info;
5468
5469 /*
5470 Crop image.
5471 */
5472 window->image->page.x=0;
5473 window->image->page.y=0;
5474 (void) ParsePageGeometry(window->image,window->crop_geometry,
5475 &crop_info,&image->exception);
5476 crop_image=CropImage(window->image,&crop_info,&image->exception);
5477 if (crop_image != (Image *) NULL)
5478 {
5479 if (window->image != image)
5480 window->image=DestroyImage(window->image);
5481 window->image=crop_image;
5482 window->destroy=MagickTrue;
5483 }
5484 }
5485 if ((width != (unsigned int) window->image->columns) ||
5486 (height != (unsigned int) window->image->rows))
5487 {
5488 Image
5489 *resize_image;
5490
5491 /*
5492 Resize image.
5493 */
5494 resize_image=NewImageList();
5495 if (window->pixel_info->colors != 0)
5496 resize_image=SampleImage(window->image,width,height,
5497 &image->exception);
5498 else
5499 resize_image=ThumbnailImage(window->image,width,height,
5500 &image->exception);
5501 if (resize_image != (Image *) NULL)
5502 {
5503 if (window->image != image)
5504 window->image=DestroyImage(window->image);
5505 window->image=resize_image;
5506 window->destroy=MagickTrue;
5507 }
5508 }
5509 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005510 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005511 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005512 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005513 }
5514 /*
5515 Create X image.
5516 */
5517 ximage=(XImage *) NULL;
5518 format=(depth == 1) ? XYBitmap : ZPixmap;
5519#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5520 if (window->shared_memory != MagickFalse)
5521 {
5522 XShmSegmentInfo
5523 *segment_info;
5524
5525 segment_info=(XShmSegmentInfo *) window->segment_info;
5526 segment_info[1].shmid=(-1);
5527 segment_info[1].shmaddr=(char *) NULL;
5528 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5529 (char *) NULL,&segment_info[1],width,height);
5530 if (ximage == (XImage *) NULL)
5531 window->shared_memory=MagickFalse;
5532 length=(size_t) ximage->bytes_per_line*ximage->height;
5533 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5534 window->shared_memory=MagickFalse;
5535 if (window->shared_memory != MagickFalse)
5536 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5537 if (window->shared_memory != MagickFalse)
5538 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5539 if (segment_info[1].shmid < 0)
5540 window->shared_memory=MagickFalse;
5541 if (window->shared_memory != MagickFalse)
5542 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5543 else
5544 {
5545 if (ximage != (XImage *) NULL)
5546 XDestroyImage(ximage);
5547 ximage=(XImage *) NULL;
5548 if (segment_info[1].shmaddr)
5549 {
5550 (void) shmdt(segment_info[1].shmaddr);
5551 segment_info[1].shmaddr=(char *) NULL;
5552 }
5553 if (segment_info[1].shmid >= 0)
5554 {
5555 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5556 segment_info[1].shmid=(-1);
5557 }
5558 }
5559 }
5560#endif
5561 /*
5562 Allocate X image pixel data.
5563 */
5564#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5565 if (window->shared_memory)
5566 {
5567 Status
5568 status;
5569
5570 XShmSegmentInfo
5571 *segment_info;
5572
5573 (void) XSync(display,MagickFalse);
5574 xerror_alert=MagickFalse;
5575 segment_info=(XShmSegmentInfo *) window->segment_info;
5576 ximage->data=segment_info[1].shmaddr;
5577 segment_info[1].readOnly=MagickFalse;
5578 status=XShmAttach(display,&segment_info[1]);
5579 if (status != False)
5580 (void) XSync(display,MagickFalse);
5581 if ((status == False) || (xerror_alert != MagickFalse))
5582 {
5583 window->shared_memory=MagickFalse;
5584 if (status != False)
5585 XShmDetach(display,&segment_info[1]);
5586 if (ximage != (XImage *) NULL)
5587 {
5588 ximage->data=NULL;
5589 XDestroyImage(ximage);
5590 ximage=(XImage *) NULL;
5591 }
5592 if (segment_info[1].shmid >= 0)
5593 {
5594 if (segment_info[1].shmaddr != NULL)
5595 (void) shmdt(segment_info[1].shmaddr);
5596 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5597 segment_info[1].shmid=(-1);
5598 segment_info[1].shmaddr=(char *) NULL;
5599 }
5600 }
5601 }
5602#endif
5603 if (window->shared_memory == MagickFalse)
5604 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5605 (char *) NULL,width,height,XBitmapPad(display),0);
5606 if (ximage == (XImage *) NULL)
5607 {
5608 /*
5609 Unable to create X image.
5610 */
5611 (void) XCheckDefineCursor(display,window->id,window->cursor);
5612 return(MagickFalse);
5613 }
5614 length=(size_t) ximage->bytes_per_line*ximage->height;
5615 if (IsEventLogging())
5616 {
5617 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5618 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5619 ximage->width,ximage->height);
5620 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5621 ximage->format);
5622 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5623 ximage->byte_order);
5624 (void) LogMagickEvent(X11Event,GetMagickModule(),
5625 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5626 ximage->bitmap_bit_order,ximage->bitmap_pad);
5627 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5628 ximage->depth);
5629 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5630 ximage->bytes_per_line);
5631 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5632 ximage->bits_per_pixel);
5633 (void) LogMagickEvent(X11Event,GetMagickModule(),
5634 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5635 ximage->green_mask,ximage->blue_mask);
5636 }
5637 if (window->shared_memory == MagickFalse)
5638 {
5639 if (ximage->format != XYBitmap)
5640 ximage->data=(char *) AcquireQuantumMemory((size_t)
5641 ximage->bytes_per_line,(size_t) ximage->height);
5642 else
5643 ximage->data=(char *) AcquireQuantumMemory((size_t)
5644 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5645 }
5646 if (ximage->data == (char *) NULL)
5647 {
5648 /*
5649 Unable to allocate pixel data.
5650 */
5651 XDestroyImage(ximage);
5652 ximage=(XImage *) NULL;
5653 (void) XCheckDefineCursor(display,window->id,window->cursor);
5654 return(MagickFalse);
5655 }
5656 if (window->ximage != (XImage *) NULL)
5657 {
5658 /*
5659 Destroy previous X image.
5660 */
5661 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5662#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5663 if (window->segment_info != (XShmSegmentInfo *) NULL)
5664 {
5665 XShmSegmentInfo
5666 *segment_info;
5667
5668 segment_info=(XShmSegmentInfo *) window->segment_info;
5669 if (segment_info[0].shmid >= 0)
5670 {
5671 (void) XSync(display,MagickFalse);
5672 (void) XShmDetach(display,&segment_info[0]);
5673 (void) XSync(display,MagickFalse);
5674 if (segment_info[0].shmaddr != (char *) NULL)
5675 (void) shmdt(segment_info[0].shmaddr);
5676 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5677 segment_info[0].shmid=(-1);
5678 segment_info[0].shmaddr=(char *) NULL;
5679 window->ximage->data=(char *) NULL;
5680 }
5681 }
5682#endif
5683 if (window->ximage->data != (char *) NULL)
5684 free(window->ximage->data);
5685 window->ximage->data=(char *) NULL;
5686 XDestroyImage(window->ximage);
5687 window->ximage=(XImage *) NULL;
5688 }
5689#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5690 if (window->segment_info != (XShmSegmentInfo *) NULL)
5691 {
5692 XShmSegmentInfo
5693 *segment_info;
5694
5695 segment_info=(XShmSegmentInfo *) window->segment_info;
5696 segment_info[0]=segment_info[1];
5697 }
5698#endif
5699 window->ximage=ximage;
5700 matte_image=(XImage *) NULL;
5701 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5702 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005703 ((int) width <= XDisplayWidth(display,window->screen)) &&
5704 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005705 {
5706 /*
5707 Create matte image.
5708 */
5709 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5710 (char *) NULL,width,height,XBitmapPad(display),0);
5711 if (IsEventLogging())
5712 {
5713 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5714 (void) LogMagickEvent(X11Event,GetMagickModule(),
5715 " width, height: %dx%d",matte_image->width,matte_image->height);
5716 }
5717 if (matte_image != (XImage *) NULL)
5718 {
5719 /*
5720 Allocate matte image pixel data.
5721 */
5722 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5723 matte_image->bytes_per_line*matte_image->depth,
5724 (size_t) matte_image->height);
5725 if (matte_image->data == (char *) NULL)
5726 {
5727 XDestroyImage(matte_image);
5728 matte_image=(XImage *) NULL;
5729 }
5730 }
5731 }
5732 if (window->matte_image != (XImage *) NULL)
5733 {
5734 /*
5735 Free matte image.
5736 */
5737 if (window->matte_image->data != (char *) NULL)
5738 free(window->matte_image->data);
5739 window->matte_image->data=(char *) NULL;
5740 XDestroyImage(window->matte_image);
5741 window->matte_image=(XImage *) NULL;
5742 }
5743 window->matte_image=matte_image;
5744 if (window->matte_pixmap != (Pixmap) NULL)
5745 {
5746 (void) XFreePixmap(display,window->matte_pixmap);
5747 window->matte_pixmap=(Pixmap) NULL;
5748#if defined(MAGICKCORE_HAVE_SHAPE)
5749 if (window->shape != MagickFalse)
5750 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5751#endif
5752 }
5753 window->stasis=MagickFalse;
5754 /*
5755 Convert pixels to X image data.
5756 */
5757 if (window->image != (Image *) NULL)
5758 {
5759 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5760 (ximage->bitmap_bit_order == LSBFirst)))
5761 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5762 matte_image);
5763 else
5764 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5765 matte_image);
5766 }
5767 if (window->matte_image != (XImage *) NULL)
5768 {
5769 /*
5770 Create matte pixmap.
5771 */
5772 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5773 if (window->matte_pixmap != (Pixmap) NULL)
5774 {
5775 GC
5776 graphics_context;
5777
5778 XGCValues
5779 context_values;
5780
5781 /*
5782 Copy matte image to matte pixmap.
5783 */
cristy4c08aed2011-07-01 19:47:50 +00005784 context_values.background=0;
5785 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005786 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005787 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005788 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5789 window->matte_image,0,0,0,0,width,height);
5790 (void) XFreeGC(display,graphics_context);
5791#if defined(MAGICKCORE_HAVE_SHAPE)
5792 if (window->shape != MagickFalse)
5793 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5794 window->matte_pixmap,ShapeSet);
5795#endif
5796 }
5797 }
5798 (void) XMakePixmap(display,resource_info,window);
5799 /*
5800 Restore cursor.
5801 */
5802 (void) XCheckDefineCursor(display,window->id,window->cursor);
5803 return(MagickTrue);
5804}
5805
5806/*
5807%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5808% %
5809% %
5810% %
5811+ X M a k e I m a g e L S B F i r s t %
5812% %
5813% %
5814% %
5815%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5816%
5817% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5818% pixels are copied in least-significant bit and byte first order. The
5819% server's scanline pad is respected. Rather than using one or two general
5820% cases, many special cases are found here to help speed up the image
5821% conversion.
5822%
5823% The format of the XMakeImageLSBFirst method is:
5824%
5825% void XMakeImageLSBFirst(Display *display,XWindows *windows)
5826%
5827% A description of each parameter follows:
5828%
5829% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5830%
5831% o window: Specifies a pointer to a XWindowInfo structure.
5832%
5833% o image: the image.
5834%
5835% o ximage: Specifies a pointer to a XImage structure; returned from
5836% XCreateImage.
5837%
5838% o matte_image: Specifies a pointer to a XImage structure; returned from
5839% XCreateImage.
5840%
5841*/
5842static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5843 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5844{
cristyc57f6942010-11-12 01:47:39 +00005845 CacheView
5846 *canvas_view;
5847
cristy3ed852e2009-09-05 21:47:34 +00005848 Image
5849 *canvas;
5850
5851 int
5852 y;
5853
cristy4c08aed2011-07-01 19:47:50 +00005854 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005855 *p;
5856
5857 register int
5858 x;
5859
5860 register unsigned char
5861 *q;
5862
5863 unsigned char
5864 bit,
5865 byte;
5866
5867 unsigned int
5868 scanline_pad;
5869
cristyf2faecf2010-05-28 19:19:36 +00005870 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005871 pixel,
5872 *pixels;
5873
5874 XStandardColormap
5875 *map_info;
5876
5877 assert(resource_info != (XResourceInfo *) NULL);
5878 assert(window != (XWindowInfo *) NULL);
5879 assert(image != (Image *) NULL);
5880 if (image->debug != MagickFalse)
5881 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5882 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005883 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005884 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005885 {
5886 char
5887 size[MaxTextExtent];
5888
5889 Image
5890 *pattern;
5891
5892 ImageInfo
5893 *image_info;
5894
5895 image_info=AcquireImageInfo();
5896 (void) CopyMagickString(image_info->filename,
5897 resource_info->image_info->texture != (char *) NULL ?
5898 resource_info->image_info->texture : "pattern:checkerboard",
5899 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005900 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005901 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005902 image_info->size=ConstantString(size);
5903 pattern=ReadImage(image_info,&image->exception);
5904 image_info=DestroyImageInfo(image_info);
5905 if (pattern != (Image *) NULL)
5906 {
5907 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5908 if (canvas != (Image *) NULL)
5909 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5910 pattern=DestroyImage(pattern);
5911 }
5912 }
5913 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5914 ximage->bits_per_pixel) >> 3));
5915 map_info=window->map_info;
5916 pixels=window->pixel_info->pixels;
5917 q=(unsigned char *) ximage->data;
5918 x=0;
cristyc57f6942010-11-12 01:47:39 +00005919 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005920 if (ximage->format == XYBitmap)
5921 {
5922 register unsigned short
5923 polarity;
5924
5925 unsigned char
5926 background,
5927 foreground;
5928
5929 /*
5930 Convert canvas to big-endian bitmap.
5931 */
5932 background=(unsigned char)
5933 (XPixelIntensity(&window->pixel_info->foreground_color) <
5934 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5935 foreground=(unsigned char)
5936 (XPixelIntensity(&window->pixel_info->background_color) <
5937 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00005938 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005939 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5940 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00005941 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
5942 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005943 for (y=0; y < (int) canvas->rows; y++)
5944 {
cristyc57f6942010-11-12 01:47:39 +00005945 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5946 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005947 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005948 break;
cristy3ed852e2009-09-05 21:47:34 +00005949 bit=0;
5950 byte=0;
5951 for (x=0; x < (int) canvas->columns; x++)
5952 {
5953 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005954 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005955 byte|=foreground;
5956 else
5957 byte|=background;
5958 bit++;
5959 if (bit == 8)
5960 {
5961 *q++=byte;
5962 bit=0;
5963 byte=0;
5964 }
cristyed231572011-07-14 02:18:59 +00005965 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005966 }
5967 if (bit != 0)
5968 *q=byte >> (8-bit);
5969 q+=scanline_pad;
5970 }
5971 }
5972 else
5973 if (window->pixel_info->colors != 0)
5974 switch (ximage->bits_per_pixel)
5975 {
5976 case 2:
5977 {
5978 register unsigned int
5979 nibble;
5980
5981 /*
5982 Convert to 2 bit color-mapped X canvas.
5983 */
5984 for (y=0; y < (int) canvas->rows; y++)
5985 {
cristyc57f6942010-11-12 01:47:39 +00005986 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5987 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005988 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005989 break;
cristy3ed852e2009-09-05 21:47:34 +00005990 nibble=0;
5991 for (x=0; x < (int) canvas->columns; x++)
5992 {
cristy4c08aed2011-07-01 19:47:50 +00005993 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00005994 switch (nibble)
5995 {
5996 case 0:
5997 {
5998 *q=(unsigned char) pixel;
5999 nibble++;
6000 break;
6001 }
6002 case 1:
6003 {
6004 *q|=(unsigned char) (pixel << 2);
6005 nibble++;
6006 break;
6007 }
6008 case 2:
6009 {
6010 *q|=(unsigned char) (pixel << 4);
6011 nibble++;
6012 break;
6013 }
6014 case 3:
6015 {
6016 *q|=(unsigned char) (pixel << 6);
6017 q++;
6018 nibble=0;
6019 break;
6020 }
6021 }
cristyed231572011-07-14 02:18:59 +00006022 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006023 }
6024 q+=scanline_pad;
6025 }
6026 break;
6027 }
6028 case 4:
6029 {
6030 register unsigned int
6031 nibble;
6032
6033 /*
6034 Convert to 4 bit color-mapped X canvas.
6035 */
6036 for (y=0; y < (int) canvas->rows; y++)
6037 {
cristyc57f6942010-11-12 01:47:39 +00006038 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6039 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006040 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006041 break;
cristy3ed852e2009-09-05 21:47:34 +00006042 nibble=0;
6043 for (x=0; x < (int) canvas->columns; x++)
6044 {
cristy4c08aed2011-07-01 19:47:50 +00006045 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006046 switch (nibble)
6047 {
6048 case 0:
6049 {
6050 *q=(unsigned char) pixel;
6051 nibble++;
6052 break;
6053 }
6054 case 1:
6055 {
6056 *q|=(unsigned char) (pixel << 4);
6057 q++;
6058 nibble=0;
6059 break;
6060 }
6061 }
cristyed231572011-07-14 02:18:59 +00006062 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006063 }
6064 q+=scanline_pad;
6065 }
6066 break;
6067 }
6068 case 6:
6069 case 8:
6070 {
6071 /*
6072 Convert to 8 bit color-mapped X canvas.
6073 */
6074 if (resource_info->color_recovery &&
6075 resource_info->quantize_info->dither)
6076 {
6077 XDitherImage(canvas,ximage);
6078 break;
6079 }
6080 for (y=0; y < (int) canvas->rows; y++)
6081 {
cristyc57f6942010-11-12 01:47:39 +00006082 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6083 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006084 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006085 break;
cristy3ed852e2009-09-05 21:47:34 +00006086 for (x=0; x < (int) canvas->columns; x++)
6087 {
cristy4c08aed2011-07-01 19:47:50 +00006088 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006089 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006090 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006091 }
6092 q+=scanline_pad;
6093 }
6094 break;
6095 }
6096 default:
6097 {
6098 register int
6099 k;
6100
6101 register unsigned int
6102 bytes_per_pixel;
6103
6104 unsigned char
cristybb503372010-05-27 20:51:26 +00006105 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006106
6107 /*
6108 Convert to multi-byte color-mapped X canvas.
6109 */
6110 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6111 for (y=0; y < (int) canvas->rows; y++)
6112 {
cristyc57f6942010-11-12 01:47:39 +00006113 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6114 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006115 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006116 break;
cristy3ed852e2009-09-05 21:47:34 +00006117 for (x=0; x < (int) canvas->columns; x++)
6118 {
cristy4c08aed2011-07-01 19:47:50 +00006119 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006120 for (k=0; k < (int) bytes_per_pixel; k++)
6121 {
6122 channel[k]=(unsigned char) pixel;
6123 pixel>>=8;
6124 }
6125 for (k=0; k < (int) bytes_per_pixel; k++)
6126 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006127 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006128 }
6129 q+=scanline_pad;
6130 }
6131 break;
6132 }
6133 }
6134 else
6135 switch (ximage->bits_per_pixel)
6136 {
6137 case 2:
6138 {
6139 register unsigned int
6140 nibble;
6141
6142 /*
6143 Convert to contiguous 2 bit continuous-tone X canvas.
6144 */
6145 for (y=0; y < (int) canvas->rows; y++)
6146 {
6147 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006148 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6149 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006150 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006151 break;
6152 for (x=0; x < (int) canvas->columns; x++)
6153 {
cristy4c08aed2011-07-01 19:47:50 +00006154 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006155 pixel&=0xf;
6156 switch (nibble)
6157 {
6158 case 0:
6159 {
6160 *q=(unsigned char) pixel;
6161 nibble++;
6162 break;
6163 }
6164 case 1:
6165 {
6166 *q|=(unsigned char) (pixel << 2);
6167 nibble++;
6168 break;
6169 }
6170 case 2:
6171 {
6172 *q|=(unsigned char) (pixel << 4);
6173 nibble++;
6174 break;
6175 }
6176 case 3:
6177 {
6178 *q|=(unsigned char) (pixel << 6);
6179 q++;
6180 nibble=0;
6181 break;
6182 }
6183 }
cristyed231572011-07-14 02:18:59 +00006184 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006185 }
6186 q+=scanline_pad;
6187 }
6188 break;
6189 }
6190 case 4:
6191 {
6192 register unsigned int
6193 nibble;
6194
6195 /*
6196 Convert to contiguous 4 bit continuous-tone X canvas.
6197 */
6198 for (y=0; y < (int) canvas->rows; y++)
6199 {
cristyc57f6942010-11-12 01:47:39 +00006200 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6201 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006202 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006203 break;
6204 nibble=0;
6205 for (x=0; x < (int) canvas->columns; x++)
6206 {
cristy4c08aed2011-07-01 19:47:50 +00006207 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006208 pixel&=0xf;
6209 switch (nibble)
6210 {
6211 case 0:
6212 {
6213 *q=(unsigned char) pixel;
6214 nibble++;
6215 break;
6216 }
6217 case 1:
6218 {
6219 *q|=(unsigned char) (pixel << 4);
6220 q++;
6221 nibble=0;
6222 break;
6223 }
6224 }
cristyed231572011-07-14 02:18:59 +00006225 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006226 }
6227 q+=scanline_pad;
6228 }
6229 break;
6230 }
6231 case 6:
6232 case 8:
6233 {
6234 /*
6235 Convert to contiguous 8 bit continuous-tone X canvas.
6236 */
6237 if (resource_info->color_recovery &&
6238 resource_info->quantize_info->dither)
6239 {
6240 XDitherImage(canvas,ximage);
6241 break;
6242 }
6243 for (y=0; y < (int) canvas->rows; y++)
6244 {
cristyc57f6942010-11-12 01:47:39 +00006245 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6246 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006247 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006248 break;
6249 for (x=0; x < (int) canvas->columns; x++)
6250 {
cristy4c08aed2011-07-01 19:47:50 +00006251 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006252 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006253 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006254 }
6255 q+=scanline_pad;
6256 }
6257 break;
6258 }
6259 default:
6260 {
6261 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6262 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6263 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6264 (map_info->blue_mult == 1))
6265 {
6266 /*
6267 Convert to 32 bit continuous-tone X canvas.
6268 */
6269 for (y=0; y < (int) canvas->rows; y++)
6270 {
cristyc57f6942010-11-12 01:47:39 +00006271 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6272 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006273 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006274 break;
6275 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6276 (blue_gamma != 1.0))
6277 {
6278 /*
6279 Gamma correct canvas.
6280 */
6281 for (x=(int) canvas->columns-1; x >= 0; x--)
6282 {
cristyccf844f2010-02-03 23:28:16 +00006283 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006284 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006285 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006286 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006287 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006288 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006289 *q++=0;
cristyed231572011-07-14 02:18:59 +00006290 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006291 }
6292 continue;
6293 }
6294 for (x=(int) canvas->columns-1; x >= 0; x--)
6295 {
cristy4c08aed2011-07-01 19:47:50 +00006296 *q++=ScaleQuantumToChar((Quantum)
6297 GetPixelBlue(canvas,p));
6298 *q++=ScaleQuantumToChar((Quantum)
6299 GetPixelGreen(canvas,p));
6300 *q++=ScaleQuantumToChar((Quantum)
6301 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006302 *q++=0;
cristyed231572011-07-14 02:18:59 +00006303 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006304 }
6305 }
6306 }
6307 else
6308 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6309 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6310 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6311 (map_info->blue_mult == 65536L))
6312 {
6313 /*
6314 Convert to 32 bit continuous-tone X canvas.
6315 */
6316 for (y=0; y < (int) canvas->rows; y++)
6317 {
cristyc57f6942010-11-12 01:47:39 +00006318 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6319 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006320 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006321 break;
6322 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6323 (blue_gamma != 1.0))
6324 {
6325 /*
6326 Gamma correct canvas.
6327 */
6328 for (x=(int) canvas->columns-1; x >= 0; x--)
6329 {
cristyccf844f2010-02-03 23:28:16 +00006330 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006331 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006332 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006333 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006334 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006335 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006336 *q++=0;
cristyed231572011-07-14 02:18:59 +00006337 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006338 }
6339 continue;
6340 }
6341 for (x=(int) canvas->columns-1; x >= 0; x--)
6342 {
cristyccf844f2010-02-03 23:28:16 +00006343 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006344 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006345 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006346 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006347 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006348 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006349 *q++=0;
cristyed231572011-07-14 02:18:59 +00006350 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006351 }
6352 }
6353 }
6354 else
6355 {
6356 register int
6357 k;
6358
6359 register unsigned int
6360 bytes_per_pixel;
6361
6362 unsigned char
cristybb503372010-05-27 20:51:26 +00006363 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006364
6365 /*
6366 Convert to multi-byte continuous-tone X canvas.
6367 */
6368 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6369 for (y=0; y < (int) canvas->rows; y++)
6370 {
cristyc57f6942010-11-12 01:47:39 +00006371 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6372 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006373 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006374 break;
cristyc57f6942010-11-12 01:47:39 +00006375 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006376 {
cristy4c08aed2011-07-01 19:47:50 +00006377 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006378 for (k=0; k < (int) bytes_per_pixel; k++)
6379 {
6380 channel[k]=(unsigned char) pixel;
6381 pixel>>=8;
6382 }
6383 for (k=0; k < (int) bytes_per_pixel; k++)
6384 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006385 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006386 }
6387 q+=scanline_pad;
6388 }
6389 }
6390 break;
6391 }
6392 }
6393 if (matte_image != (XImage *) NULL)
6394 {
6395 /*
6396 Initialize matte canvas.
6397 */
6398 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6399 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6400 q=(unsigned char *) matte_image->data;
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,canvas->columns,1,
6404 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006405 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006406 break;
6407 bit=0;
6408 byte=0;
6409 for (x=(int) canvas->columns-1; x >= 0; x--)
6410 {
6411 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006412 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006413 byte|=0x80;
6414 bit++;
6415 if (bit == 8)
6416 {
6417 *q++=byte;
6418 bit=0;
6419 byte=0;
6420 }
cristyed231572011-07-14 02:18:59 +00006421 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006422 }
6423 if (bit != 0)
6424 *q=byte >> (8-bit);
6425 q+=scanline_pad;
6426 }
6427 }
cristyc57f6942010-11-12 01:47:39 +00006428 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006429 if (canvas != image)
6430 canvas=DestroyImage(canvas);
6431}
6432
6433/*
6434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6435% %
6436% %
6437% %
6438+ X M a k e I m a g e M S B F i r s t %
6439% %
6440% %
6441% %
6442%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6443%
6444% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6445% image pixels are copied in most-significant bit and byte first order. The
6446% server's scanline pad is also respected. Rather than using one or two
6447% general cases, many special cases are found here to help speed up the image
6448% conversion.
6449%
6450% The format of the XMakeImageMSBFirst method is:
6451%
6452% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6453%
6454% A description of each parameter follows:
6455%
6456% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6457%
6458% o window: Specifies a pointer to a XWindowInfo structure.
6459%
6460% o image: the image.
6461%
6462% o ximage: Specifies a pointer to a XImage structure; returned from
6463% XCreateImage.
6464%
6465% o matte_image: Specifies a pointer to a XImage structure; returned from
6466% XCreateImage.
6467%
cristy3ed852e2009-09-05 21:47:34 +00006468*/
6469static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6470 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6471{
cristyc57f6942010-11-12 01:47:39 +00006472 CacheView
6473 *canvas_view;
6474
cristy3ed852e2009-09-05 21:47:34 +00006475 Image
6476 *canvas;
6477
6478 int
6479 y;
6480
6481 register int
6482 x;
6483
cristy4c08aed2011-07-01 19:47:50 +00006484 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006485 *p;
6486
6487 register unsigned char
6488 *q;
6489
6490 unsigned char
6491 bit,
6492 byte;
6493
6494 unsigned int
6495 scanline_pad;
6496
cristyf2faecf2010-05-28 19:19:36 +00006497 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006498 pixel,
6499 *pixels;
6500
6501 XStandardColormap
6502 *map_info;
6503
6504 assert(resource_info != (XResourceInfo *) NULL);
6505 assert(window != (XWindowInfo *) NULL);
6506 assert(image != (Image *) NULL);
6507 if (image->debug != MagickFalse)
6508 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6509 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006510 if ((window->immutable != MagickFalse) &&
6511 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006512 {
6513 char
6514 size[MaxTextExtent];
6515
6516 Image
6517 *pattern;
6518
6519 ImageInfo
6520 *image_info;
6521
6522 image_info=AcquireImageInfo();
6523 (void) CopyMagickString(image_info->filename,
6524 resource_info->image_info->texture != (char *) NULL ?
6525 resource_info->image_info->texture : "pattern:checkerboard",
6526 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006527 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006528 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006529 image_info->size=ConstantString(size);
6530 pattern=ReadImage(image_info,&image->exception);
6531 image_info=DestroyImageInfo(image_info);
6532 if (pattern != (Image *) NULL)
6533 {
6534 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6535 if (canvas != (Image *) NULL)
6536 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6537 pattern=DestroyImage(pattern);
6538 }
6539 }
cristy4c08aed2011-07-01 19:47:50 +00006540 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6541 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006542 map_info=window->map_info;
6543 pixels=window->pixel_info->pixels;
6544 q=(unsigned char *) ximage->data;
6545 x=0;
cristyc57f6942010-11-12 01:47:39 +00006546 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006547 if (ximage->format == XYBitmap)
6548 {
6549 register unsigned short
6550 polarity;
6551
6552 unsigned char
6553 background,
6554 foreground;
6555
6556 /*
6557 Convert canvas to big-endian bitmap.
6558 */
6559 background=(unsigned char)
6560 (XPixelIntensity(&window->pixel_info->foreground_color) <
6561 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6562 foreground=(unsigned char)
6563 (XPixelIntensity(&window->pixel_info->background_color) <
6564 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00006565 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006566 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6567 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00006568 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
6569 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006570 for (y=0; y < (int) canvas->rows; y++)
6571 {
cristyc57f6942010-11-12 01:47:39 +00006572 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6573 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006574 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006575 break;
cristy3ed852e2009-09-05 21:47:34 +00006576 bit=0;
6577 byte=0;
6578 for (x=(int) canvas->columns-1; x >= 0; x--)
6579 {
6580 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006581 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006582 byte|=foreground;
6583 else
6584 byte|=background;
6585 bit++;
6586 if (bit == 8)
6587 {
6588 *q++=byte;
6589 bit=0;
6590 byte=0;
6591 }
cristyed231572011-07-14 02:18:59 +00006592 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006593 }
6594 if (bit != 0)
6595 *q=byte << (8-bit);
6596 q+=scanline_pad;
6597 }
6598 }
6599 else
6600 if (window->pixel_info->colors != 0)
6601 switch (ximage->bits_per_pixel)
6602 {
6603 case 2:
6604 {
6605 register unsigned int
6606 nibble;
6607
6608 /*
6609 Convert to 2 bit color-mapped X canvas.
6610 */
6611 for (y=0; y < (int) canvas->rows; y++)
6612 {
cristyc57f6942010-11-12 01:47:39 +00006613 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6614 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006615 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006616 break;
cristy3ed852e2009-09-05 21:47:34 +00006617 nibble=0;
6618 for (x=0; x < (int) canvas->columns; x++)
6619 {
cristy4c08aed2011-07-01 19:47:50 +00006620 pixel=pixels[(ssize_t)
6621 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006622 switch (nibble)
6623 {
6624 case 0:
6625 {
6626 *q=(unsigned char) (pixel << 6);
6627 nibble++;
6628 break;
6629 }
6630 case 1:
6631 {
6632 *q|=(unsigned char) (pixel << 4);
6633 nibble++;
6634 break;
6635 }
6636 case 2:
6637 {
6638 *q|=(unsigned char) (pixel << 2);
6639 nibble++;
6640 break;
6641 }
6642 case 3:
6643 {
6644 *q|=(unsigned char) pixel;
6645 q++;
6646 nibble=0;
6647 break;
6648 }
6649 }
cristyed231572011-07-14 02:18:59 +00006650 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006651 }
6652 q+=scanline_pad;
6653 }
6654 break;
6655 }
6656 case 4:
6657 {
6658 register unsigned int
6659 nibble;
6660
6661 /*
6662 Convert to 4 bit color-mapped X canvas.
6663 */
6664 for (y=0; y < (int) canvas->rows; y++)
6665 {
cristyc57f6942010-11-12 01:47:39 +00006666 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6667 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006668 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006669 break;
cristy3ed852e2009-09-05 21:47:34 +00006670 nibble=0;
6671 for (x=0; x < (int) canvas->columns; x++)
6672 {
cristy4c08aed2011-07-01 19:47:50 +00006673 pixel=pixels[(ssize_t)
6674 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006675 switch (nibble)
6676 {
6677 case 0:
6678 {
6679 *q=(unsigned char) (pixel << 4);
6680 nibble++;
6681 break;
6682 }
6683 case 1:
6684 {
6685 *q|=(unsigned char) pixel;
6686 q++;
6687 nibble=0;
6688 break;
6689 }
6690 }
cristyed231572011-07-14 02:18:59 +00006691 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006692 }
6693 q+=scanline_pad;
6694 }
6695 break;
6696 }
6697 case 6:
6698 case 8:
6699 {
6700 /*
6701 Convert to 8 bit color-mapped X canvas.
6702 */
6703 if (resource_info->color_recovery &&
6704 resource_info->quantize_info->dither)
6705 {
6706 XDitherImage(canvas,ximage);
6707 break;
6708 }
6709 for (y=0; y < (int) canvas->rows; y++)
6710 {
cristyc57f6942010-11-12 01:47:39 +00006711 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6712 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006713 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006714 break;
cristy3ed852e2009-09-05 21:47:34 +00006715 for (x=0; x < (int) canvas->columns; x++)
6716 {
cristy4c08aed2011-07-01 19:47:50 +00006717 pixel=pixels[(ssize_t)
6718 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006719 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006720 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006721 }
6722 q+=scanline_pad;
6723 }
6724 break;
6725 }
6726 default:
6727 {
6728 register int
6729 k;
6730
6731 register unsigned int
6732 bytes_per_pixel;
6733
6734 unsigned char
cristybb503372010-05-27 20:51:26 +00006735 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006736
6737 /*
6738 Convert to 8 bit color-mapped X canvas.
6739 */
6740 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6741 for (y=0; y < (int) canvas->rows; y++)
6742 {
cristyc57f6942010-11-12 01:47:39 +00006743 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6744 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006745 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006746 break;
cristy3ed852e2009-09-05 21:47:34 +00006747 for (x=0; x < (int) canvas->columns; x++)
6748 {
cristy4c08aed2011-07-01 19:47:50 +00006749 pixel=pixels[(ssize_t)
6750 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006751 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6752 {
6753 channel[k]=(unsigned char) pixel;
6754 pixel>>=8;
6755 }
6756 for (k=0; k < (int) bytes_per_pixel; k++)
6757 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006758 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006759 }
6760 q+=scanline_pad;
6761 }
6762 break;
6763 }
6764 }
6765 else
6766 switch (ximage->bits_per_pixel)
6767 {
6768 case 2:
6769 {
6770 register unsigned int
6771 nibble;
6772
6773 /*
6774 Convert to 4 bit continuous-tone X canvas.
6775 */
6776 for (y=0; y < (int) canvas->rows; y++)
6777 {
cristyc57f6942010-11-12 01:47:39 +00006778 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6779 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006780 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006781 break;
6782 nibble=0;
6783 for (x=(int) canvas->columns-1; x >= 0; x--)
6784 {
cristy4c08aed2011-07-01 19:47:50 +00006785 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006786 pixel&=0xf;
6787 switch (nibble)
6788 {
6789 case 0:
6790 {
6791 *q=(unsigned char) (pixel << 6);
6792 nibble++;
6793 break;
6794 }
6795 case 1:
6796 {
6797 *q|=(unsigned char) (pixel << 4);
6798 nibble++;
6799 break;
6800 }
6801 case 2:
6802 {
6803 *q|=(unsigned char) (pixel << 2);
6804 nibble++;
6805 break;
6806 }
6807 case 3:
6808 {
6809 *q|=(unsigned char) pixel;
6810 q++;
6811 nibble=0;
6812 break;
6813 }
6814 }
cristyed231572011-07-14 02:18:59 +00006815 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006816 }
6817 q+=scanline_pad;
6818 }
6819 break;
6820 }
6821 case 4:
6822 {
6823 register unsigned int
6824 nibble;
6825
6826 /*
6827 Convert to 4 bit continuous-tone X canvas.
6828 */
6829 for (y=0; y < (int) canvas->rows; y++)
6830 {
cristyc57f6942010-11-12 01:47:39 +00006831 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6832 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006833 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006834 break;
6835 nibble=0;
6836 for (x=(int) canvas->columns-1; x >= 0; x--)
6837 {
cristy4c08aed2011-07-01 19:47:50 +00006838 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006839 pixel&=0xf;
6840 switch (nibble)
6841 {
6842 case 0:
6843 {
6844 *q=(unsigned char) (pixel << 4);
6845 nibble++;
6846 break;
6847 }
6848 case 1:
6849 {
6850 *q|=(unsigned char) pixel;
6851 q++;
6852 nibble=0;
6853 break;
6854 }
6855 }
cristyed231572011-07-14 02:18:59 +00006856 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006857 }
6858 q+=scanline_pad;
6859 }
6860 break;
6861 }
6862 case 6:
6863 case 8:
6864 {
6865 /*
6866 Convert to 8 bit continuous-tone X canvas.
6867 */
6868 if (resource_info->color_recovery &&
6869 resource_info->quantize_info->dither)
6870 {
6871 XDitherImage(canvas,ximage);
6872 break;
6873 }
6874 for (y=0; y < (int) canvas->rows; y++)
6875 {
cristyc57f6942010-11-12 01:47:39 +00006876 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6877 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006878 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006879 break;
6880 for (x=(int) canvas->columns-1; x >= 0; x--)
6881 {
cristy4c08aed2011-07-01 19:47:50 +00006882 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006883 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006884 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006885 }
6886 q+=scanline_pad;
6887 }
6888 break;
6889 }
6890 default:
6891 {
6892 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6893 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6894 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6895 (map_info->blue_mult == 1))
6896 {
6897 /*
6898 Convert to 32 bit continuous-tone X canvas.
6899 */
6900 for (y=0; y < (int) canvas->rows; y++)
6901 {
cristyc57f6942010-11-12 01:47:39 +00006902 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6903 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006904 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006905 break;
6906 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6907 (blue_gamma != 1.0))
6908 {
6909 /*
6910 Gamma correct canvas.
6911 */
6912 for (x=(int) canvas->columns-1; x >= 0; x--)
6913 {
6914 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006915 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006916 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006917 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006918 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006919 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006920 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006921 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006922 }
6923 continue;
6924 }
6925 for (x=(int) canvas->columns-1; x >= 0; x--)
6926 {
6927 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006928 *q++=ScaleQuantumToChar((Quantum)
6929 GetPixelRed(canvas,p));
6930 *q++=ScaleQuantumToChar((Quantum)
6931 GetPixelGreen(canvas,p));
6932 *q++=ScaleQuantumToChar((Quantum)
6933 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006934 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006935 }
6936 }
6937 }
6938 else
6939 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6940 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6941 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6942 (map_info->blue_mult == 65536L))
6943 {
6944 /*
6945 Convert to 32 bit continuous-tone X canvas.
6946 */
6947 for (y=0; y < (int) canvas->rows; y++)
6948 {
cristyc57f6942010-11-12 01:47:39 +00006949 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6950 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006951 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006952 break;
6953 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6954 (blue_gamma != 1.0))
6955 {
6956 /*
6957 Gamma correct canvas.
6958 */
6959 for (x=(int) canvas->columns-1; x >= 0; x--)
6960 {
6961 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006962 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006963 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006964 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006965 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006966 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006967 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006968 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006969 }
6970 continue;
6971 }
6972 for (x=(int) canvas->columns-1; x >= 0; x--)
6973 {
6974 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006975 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006976 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006977 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006978 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006979 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006980 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006981 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006982 }
6983 }
6984 }
6985 else
6986 {
6987 register int
6988 k;
6989
6990 register unsigned int
6991 bytes_per_pixel;
6992
6993 unsigned char
cristybb503372010-05-27 20:51:26 +00006994 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006995
6996 /*
6997 Convert to multi-byte continuous-tone X canvas.
6998 */
6999 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7000 for (y=0; y < (int) canvas->rows; y++)
7001 {
cristyc57f6942010-11-12 01:47:39 +00007002 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
7003 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007004 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007005 break;
7006 for (x=(int) canvas->columns-1; x >= 0; x--)
7007 {
cristy4c08aed2011-07-01 19:47:50 +00007008 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007009 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7010 {
7011 channel[k]=(unsigned char) pixel;
7012 pixel>>=8;
7013 }
7014 for (k=0; k < (int) bytes_per_pixel; k++)
7015 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007016 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007017 }
7018 q+=scanline_pad;
7019 }
7020 }
7021 break;
7022 }
7023 }
7024 if (matte_image != (XImage *) NULL)
7025 {
7026 /*
7027 Initialize matte canvas.
7028 */
7029 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7030 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7031 q=(unsigned char *) matte_image->data;
7032 for (y=0; y < (int) canvas->rows; y++)
7033 {
cristyc57f6942010-11-12 01:47:39 +00007034 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7035 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007036 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007037 break;
7038 bit=0;
7039 byte=0;
7040 for (x=(int) canvas->columns-1; x >= 0; x--)
7041 {
7042 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007043 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007044 byte|=0x01;
7045 bit++;
7046 if (bit == 8)
7047 {
7048 *q++=byte;
7049 bit=0;
7050 byte=0;
7051 }
cristyed231572011-07-14 02:18:59 +00007052 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007053 }
7054 if (bit != 0)
7055 *q=byte << (8-bit);
7056 q+=scanline_pad;
7057 }
7058 }
cristyc57f6942010-11-12 01:47:39 +00007059 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007060 if (canvas != image)
7061 canvas=DestroyImage(canvas);
7062}
7063
7064/*
7065%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7066% %
7067% %
7068% %
7069% X M a k e M a g n i f y I m a g e %
7070% %
7071% %
7072% %
7073%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7074%
7075% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7076%
7077% The format of the XMakeMagnifyImage method is:
7078%
7079% void XMakeMagnifyImage(display,windows)
7080%
7081% A description of each parameter follows:
7082%
7083% o display: Specifies a connection to an X server; returned from
7084% XOpenDisplay.
7085%
7086% o windows: Specifies a pointer to a XWindows structure.
7087%
7088*/
7089MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
7090{
7091 char
7092 tuple[MaxTextExtent];
7093
7094 int
7095 y;
7096
cristy4c08aed2011-07-01 19:47:50 +00007097 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007098 pixel;
7099
7100 register int
7101 x;
7102
cristybb503372010-05-27 20:51:26 +00007103 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007104 i;
7105
7106 register unsigned char
7107 *p,
7108 *q;
7109
cristy9d314ff2011-03-09 01:30:28 +00007110 ssize_t
7111 n;
7112
cristy3ed852e2009-09-05 21:47:34 +00007113 static unsigned int
7114 previous_magnify = 0;
7115
7116 static XWindowInfo
7117 magnify_window;
7118
7119 unsigned int
7120 height,
7121 j,
7122 k,
7123 l,
7124 magnify,
7125 scanline_pad,
7126 width;
7127
7128 XImage
7129 *ximage;
7130
7131 /*
7132 Check boundary conditions.
7133 */
7134 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7135 assert(display != (Display *) NULL);
7136 assert(windows != (XWindows *) NULL);
7137 magnify=1;
cristybb503372010-05-27 20:51:26 +00007138 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007139 magnify<<=1;
7140 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7141 magnify<<=1;
7142 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7143 magnify<<=1;
7144 while (magnify > windows->magnify.width)
7145 magnify>>=1;
7146 while (magnify > windows->magnify.height)
7147 magnify>>=1;
7148 if (magnify != previous_magnify)
7149 {
7150 Status
7151 status;
7152
7153 XTextProperty
7154 window_name;
7155
7156 /*
7157 New magnify factor: update magnify window name.
7158 */
7159 i=0;
7160 while ((1 << i) <= (int) magnify)
7161 i++;
cristyb51dff52011-05-19 16:55:47 +00007162 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007163 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007164 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7165 if (status != False)
7166 {
7167 XSetWMName(display,windows->magnify.id,&window_name);
7168 XSetWMIconName(display,windows->magnify.id,&window_name);
7169 (void) XFree((void *) window_name.value);
7170 }
7171 }
7172 previous_magnify=magnify;
7173 ximage=windows->image.ximage;
7174 width=(unsigned int) windows->magnify.ximage->width;
7175 height=(unsigned int) windows->magnify.ximage->height;
7176 if ((windows->magnify.x < 0) ||
7177 (windows->magnify.x >= windows->image.ximage->width))
7178 windows->magnify.x=windows->image.ximage->width >> 1;
7179 x=windows->magnify.x-((width/magnify) >> 1);
7180 if (x < 0)
7181 x=0;
7182 else
7183 if (x > (int) (ximage->width-(width/magnify)))
7184 x=ximage->width-width/magnify;
7185 if ((windows->magnify.y < 0) ||
7186 (windows->magnify.y >= windows->image.ximage->height))
7187 windows->magnify.y=windows->image.ximage->height >> 1;
7188 y=windows->magnify.y-((height/magnify) >> 1);
7189 if (y < 0)
7190 y=0;
7191 else
7192 if (y > (int) (ximage->height-(height/magnify)))
7193 y=ximage->height-height/magnify;
7194 q=(unsigned char *) windows->magnify.ximage->data;
7195 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7196 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7197 if (ximage->bits_per_pixel < 8)
7198 {
7199 register unsigned char
7200 background,
7201 byte,
7202 foreground,
7203 p_bit,
7204 q_bit;
7205
7206 register unsigned int
7207 plane;
7208
7209 XPixelInfo
7210 *pixel_info;
7211
7212 pixel_info=windows->magnify.pixel_info;
7213 switch (ximage->bitmap_bit_order)
7214 {
7215 case LSBFirst:
7216 {
7217 /*
7218 Magnify little-endian bitmap.
7219 */
7220 background=0x00;
7221 foreground=0x80;
7222 if (ximage->format == XYBitmap)
7223 {
7224 background=(unsigned char)
7225 (XPixelIntensity(&pixel_info->foreground_color) <
7226 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7227 foreground=(unsigned char)
7228 (XPixelIntensity(&pixel_info->background_color) <
7229 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7230 if (windows->magnify.depth > 1)
7231 Swap(background,foreground);
7232 }
cristybb503372010-05-27 20:51:26 +00007233 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007234 {
7235 /*
7236 Propogate pixel magnify rows.
7237 */
7238 for (j=0; j < magnify; j++)
7239 {
7240 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7241 ((x*ximage->bits_per_pixel) >> 3);
7242 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7243 q_bit=0;
7244 byte=0;
7245 for (k=0; k < width; k+=magnify)
7246 {
7247 /*
7248 Propogate pixel magnify columns.
7249 */
7250 for (l=0; l < magnify; l++)
7251 {
7252 /*
7253 Propogate each bit plane.
7254 */
7255 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7256 {
7257 byte>>=1;
7258 if (*p & (0x01 << (p_bit+plane)))
7259 byte|=foreground;
7260 else
7261 byte|=background;
7262 q_bit++;
7263 if (q_bit == 8)
7264 {
7265 *q++=byte;
7266 q_bit=0;
7267 byte=0;
7268 }
7269 }
7270 }
7271 p_bit+=ximage->bits_per_pixel;
7272 if (p_bit == 8)
7273 {
7274 p++;
7275 p_bit=0;
7276 }
7277 if (q_bit != 0)
7278 *q=byte >> (8-q_bit);
7279 q+=scanline_pad;
7280 }
7281 }
7282 y++;
7283 }
7284 break;
7285 }
7286 case MSBFirst:
7287 default:
7288 {
7289 /*
7290 Magnify big-endian bitmap.
7291 */
7292 background=0x00;
7293 foreground=0x01;
7294 if (ximage->format == XYBitmap)
7295 {
7296 background=(unsigned char)
7297 (XPixelIntensity(&pixel_info->foreground_color) <
7298 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7299 foreground=(unsigned char)
7300 (XPixelIntensity(&pixel_info->background_color) <
7301 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7302 if (windows->magnify.depth > 1)
7303 Swap(background,foreground);
7304 }
cristybb503372010-05-27 20:51:26 +00007305 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007306 {
7307 /*
7308 Propogate pixel magnify rows.
7309 */
7310 for (j=0; j < magnify; j++)
7311 {
7312 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7313 ((x*ximage->bits_per_pixel) >> 3);
7314 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7315 q_bit=0;
7316 byte=0;
7317 for (k=0; k < width; k+=magnify)
7318 {
7319 /*
7320 Propogate pixel magnify columns.
7321 */
7322 for (l=0; l < magnify; l++)
7323 {
7324 /*
7325 Propogate each bit plane.
7326 */
7327 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7328 {
7329 byte<<=1;
7330 if (*p & (0x80 >> (p_bit+plane)))
7331 byte|=foreground;
7332 else
7333 byte|=background;
7334 q_bit++;
7335 if (q_bit == 8)
7336 {
7337 *q++=byte;
7338 q_bit=0;
7339 byte=0;
7340 }
7341 }
7342 }
7343 p_bit+=ximage->bits_per_pixel;
7344 if (p_bit == 8)
7345 {
7346 p++;
7347 p_bit=0;
7348 }
7349 if (q_bit != 0)
7350 *q=byte << (8-q_bit);
7351 q+=scanline_pad;
7352 }
7353 }
7354 y++;
7355 }
7356 break;
7357 }
7358 }
7359 }
7360 else
7361 switch (ximage->bits_per_pixel)
7362 {
7363 case 6:
7364 case 8:
7365 {
7366 /*
7367 Magnify 8 bit X image.
7368 */
cristybb503372010-05-27 20:51:26 +00007369 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007370 {
7371 /*
7372 Propogate pixel magnify rows.
7373 */
7374 for (j=0; j < magnify; j++)
7375 {
7376 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7377 ((x*ximage->bits_per_pixel) >> 3);
7378 for (k=0; k < width; k+=magnify)
7379 {
7380 /*
7381 Propogate pixel magnify columns.
7382 */
7383 for (l=0; l < magnify; l++)
7384 *q++=(*p);
7385 p++;
7386 }
7387 q+=scanline_pad;
7388 }
7389 y++;
7390 }
7391 break;
7392 }
7393 default:
7394 {
7395 register unsigned int
7396 bytes_per_pixel,
7397 m;
7398
7399 /*
7400 Magnify multi-byte X image.
7401 */
7402 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
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 for (m=0; m < bytes_per_pixel; m++)
7419 *q++=(*(p+m));
7420 p+=bytes_per_pixel;
7421 }
7422 q+=scanline_pad;
7423 }
7424 y++;
7425 }
7426 break;
7427 }
7428 }
7429 /*
7430 Copy X image to magnify pixmap.
7431 */
7432 x=windows->magnify.x-((width/magnify) >> 1);
7433 if (x < 0)
7434 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7435 else
7436 if (x > (int) (ximage->width-(width/magnify)))
7437 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7438 else
7439 x=0;
7440 y=windows->magnify.y-((height/magnify) >> 1);
7441 if (y < 0)
7442 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7443 else
7444 if (y > (int) (ximage->height-(height/magnify)))
7445 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7446 else
7447 y=0;
7448 if ((x != 0) || (y != 0))
7449 (void) XFillRectangle(display,windows->magnify.pixmap,
7450 windows->magnify.annotate_context,0,0,width,height);
7451 (void) XPutImage(display,windows->magnify.pixmap,
7452 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7453 height-y);
7454 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7455 (magnify <= (height >> 1))))
7456 {
7457 RectangleInfo
7458 highlight_info;
7459
7460 /*
7461 Highlight center pixel.
7462 */
cristybb503372010-05-27 20:51:26 +00007463 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7464 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007465 highlight_info.width=magnify;
7466 highlight_info.height=magnify;
7467 (void) XDrawRectangle(display,windows->magnify.pixmap,
7468 windows->magnify.highlight_context,(int) highlight_info.x,
7469 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7470 (unsigned int) highlight_info.height-1);
7471 if (magnify > 2)
7472 (void) XDrawRectangle(display,windows->magnify.pixmap,
7473 windows->magnify.annotate_context,(int) highlight_info.x+1,
7474 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7475 (unsigned int) highlight_info.height-3);
7476 }
7477 /*
7478 Show center pixel color.
7479 */
cristyc57f6942010-11-12 01:47:39 +00007480 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7481 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7482 &windows->image.image->exception);
cristyb51dff52011-05-19 16:55:47 +00007483 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007484 windows->magnify.x,windows->magnify.y);
7485 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007486 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007487 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007488 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007489 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007490 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007491 if (pixel.colorspace == CMYKColorspace)
7492 {
7493 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007494 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007495 }
7496 if (pixel.matte != MagickFalse)
7497 {
7498 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007499 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007500 }
7501 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7502 height=(unsigned int) windows->magnify.font_info->ascent+
7503 windows->magnify.font_info->descent;
7504 x=windows->magnify.font_info->max_bounds.width >> 1;
7505 y=windows->magnify.font_info->ascent+(height >> 2);
7506 (void) XDrawImageString(display,windows->magnify.pixmap,
7507 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7508 GetColorTuple(&pixel,MagickTrue,tuple);
7509 y+=height;
7510 (void) XDrawImageString(display,windows->magnify.pixmap,
7511 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7512 (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7513 &windows->image.image->exception);
7514 y+=height;
7515 (void) XDrawImageString(display,windows->magnify.pixmap,
7516 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7517 /*
7518 Refresh magnify window.
7519 */
7520 magnify_window=windows->magnify;
7521 magnify_window.x=0;
7522 magnify_window.y=0;
7523 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7524}
7525
7526/*
7527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7528% %
7529% %
7530% %
7531% X M a k e P i x m a p %
7532% %
7533% %
7534% %
7535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7536%
7537% XMakePixmap() creates an X11 pixmap.
7538%
7539% The format of the XMakePixmap method is:
7540%
7541% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7542% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7543% XPixelInfo *pixel)
7544%
7545% A description of each parameter follows:
7546%
7547% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7548%
7549% o display: Specifies a connection to an X server; returned from
7550% XOpenDisplay.
7551%
7552% o window: Specifies a pointer to a XWindowInfo structure.
7553%
cristy3ed852e2009-09-05 21:47:34 +00007554*/
7555static MagickBooleanType XMakePixmap(Display *display,
7556 const XResourceInfo *resource_info,XWindowInfo *window)
7557{
7558 unsigned int
7559 height,
7560 width;
7561
7562 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7563 assert(display != (Display *) NULL);
7564 assert(resource_info != (XResourceInfo *) NULL);
7565 assert(window != (XWindowInfo *) NULL);
7566 if (window->pixmap != (Pixmap) NULL)
7567 {
7568 /*
7569 Destroy previous X pixmap.
7570 */
7571 (void) XFreePixmap(display,window->pixmap);
7572 window->pixmap=(Pixmap) NULL;
7573 }
7574 if (window->use_pixmap == MagickFalse)
7575 return(MagickFalse);
7576 if (window->ximage == (XImage *) NULL)
7577 return(MagickFalse);
7578 /*
7579 Display busy cursor.
7580 */
7581 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7582 (void) XFlush(display);
7583 /*
7584 Create pixmap.
7585 */
7586 width=(unsigned int) window->ximage->width;
7587 height=(unsigned int) window->ximage->height;
7588 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7589 if (window->pixmap == (Pixmap) NULL)
7590 {
7591 /*
7592 Unable to allocate pixmap.
7593 */
7594 (void) XCheckDefineCursor(display,window->id,window->cursor);
7595 return(MagickFalse);
7596 }
7597 /*
7598 Copy X image to pixmap.
7599 */
7600#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7601 if (window->shared_memory)
7602 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7603 window->ximage,0,0,0,0,width,height,MagickTrue);
7604#endif
7605 if (window->shared_memory == MagickFalse)
7606 (void) XPutImage(display,window->pixmap,window->annotate_context,
7607 window->ximage,0,0,0,0,width,height);
7608 if (IsEventLogging())
7609 {
7610 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7611 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7612 width,height);
7613 }
7614 /*
7615 Restore cursor.
7616 */
7617 (void) XCheckDefineCursor(display,window->id,window->cursor);
7618 return(MagickTrue);
7619}
7620
7621/*
7622%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7623% %
7624% %
7625% %
7626% X M a k e S t a n d a r d C o l o r m a p %
7627% %
7628% %
7629% %
7630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7631%
7632% XMakeStandardColormap() creates an X11 Standard Colormap.
7633%
7634% The format of the XMakeStandardColormap method is:
7635%
7636% XMakeStandardColormap(display,visual_info,resource_info,image,
7637% map_info,pixel)
7638%
7639% A description of each parameter follows:
7640%
7641% o display: Specifies a connection to an X server; returned from
7642% XOpenDisplay.
7643%
7644% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7645% returned from XGetVisualInfo.
7646%
7647% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7648%
7649% o image: the image.
7650%
7651% o map_info: If a Standard Colormap type is specified, this structure is
7652% initialized with info from the Standard Colormap.
7653%
7654% o pixel: Specifies a pointer to a XPixelInfo structure.
7655%
cristy3ed852e2009-09-05 21:47:34 +00007656*/
7657
7658#if defined(__cplusplus) || defined(c_plusplus)
7659extern "C" {
7660#endif
7661
7662static inline MagickRealType DiversityPixelIntensity(
7663 const DiversityPacket *pixel)
7664{
7665 MagickRealType
7666 intensity;
7667
7668 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7669 return(intensity);
7670}
7671
7672static int IntensityCompare(const void *x,const void *y)
7673{
7674 DiversityPacket
7675 *color_1,
7676 *color_2;
7677
7678 int
7679 diversity;
7680
7681 color_1=(DiversityPacket *) x;
7682 color_2=(DiversityPacket *) y;
7683 diversity=(int) (DiversityPixelIntensity(color_2)-
7684 DiversityPixelIntensity(color_1));
7685 return(diversity);
7686}
7687
7688static int PopularityCompare(const void *x,const void *y)
7689{
7690 DiversityPacket
7691 *color_1,
7692 *color_2;
7693
7694 color_1=(DiversityPacket *) x;
7695 color_2=(DiversityPacket *) y;
7696 return((int) color_2->count-(int) color_1->count);
7697}
7698
7699#if defined(__cplusplus) || defined(c_plusplus)
7700}
7701#endif
7702
cristybb503372010-05-27 20:51:26 +00007703static inline Quantum ScaleXToQuantum(const size_t x,
7704 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007705{
7706 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7707}
7708
7709MagickExport void XMakeStandardColormap(Display *display,
7710 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7711 XStandardColormap *map_info,XPixelInfo *pixel)
7712{
7713 Colormap
7714 colormap;
7715
7716 ExceptionInfo
7717 *exception;
7718
cristybb503372010-05-27 20:51:26 +00007719 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007720 i;
7721
7722 Status
7723 status;
7724
cristybb503372010-05-27 20:51:26 +00007725 size_t
cristy3ed852e2009-09-05 21:47:34 +00007726 number_colors,
7727 retain_colors;
7728
7729 unsigned short
7730 gray_value;
7731
7732 XColor
7733 color,
7734 *colors,
7735 *p;
7736
7737 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7738 assert(display != (Display *) NULL);
7739 assert(visual_info != (XVisualInfo *) NULL);
7740 assert(map_info != (XStandardColormap *) NULL);
7741 assert(resource_info != (XResourceInfo *) NULL);
7742 assert(pixel != (XPixelInfo *) NULL);
7743 exception=(&image->exception);
7744 if (resource_info->map_type != (char *) NULL)
7745 {
7746 /*
7747 Standard Colormap is already defined (i.e. xstdcmap).
7748 */
cristy4c08aed2011-07-01 19:47:50 +00007749 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007750 pixel);
7751 number_colors=(unsigned int) (map_info->base_pixel+
7752 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7753 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7754 if ((image->matte == MagickFalse) &&
7755 (resource_info->color_recovery == MagickFalse) &&
7756 resource_info->quantize_info->dither &&
7757 (number_colors < MaxColormapSize))
7758 {
7759 Image
7760 *affinity_image;
7761
cristy4c08aed2011-07-01 19:47:50 +00007762 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007763 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007764
7765 /*
7766 Improve image appearance with error diffusion.
7767 */
7768 affinity_image=AcquireImage((ImageInfo *) NULL);
7769 if (affinity_image == (Image *) NULL)
7770 ThrowXWindowFatalException(ResourceLimitFatalError,
7771 "UnableToDitherImage",image->filename);
7772 affinity_image->columns=number_colors;
7773 affinity_image->rows=1;
7774 /*
7775 Initialize colormap image.
7776 */
7777 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7778 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007779 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007780 {
cristybb503372010-05-27 20:51:26 +00007781 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007782 {
cristy4c08aed2011-07-01 19:47:50 +00007783 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007784 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007785 SetPixelRed(affinity_image,
7786 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7787 map_info->red_max),q);
7788 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007789 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007790 SetPixelGreen(affinity_image,
7791 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7792 (map_info->green_max+1)),map_info->green_max),q);
7793 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007794 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007795 SetPixelBlue(affinity_image,
7796 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7797 map_info->blue_max),q);
7798 SetPixelAlpha(affinity_image,
7799 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007800 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007801 }
7802 (void) SyncAuthenticPixels(affinity_image,exception);
7803 (void) RemapImage(resource_info->quantize_info,image,
7804 affinity_image);
7805 }
cristy4c08aed2011-07-01 19:47:50 +00007806 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007807 pixel);
cristy574cc262011-08-05 01:23:58 +00007808 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007809 affinity_image=DestroyImage(affinity_image);
7810 }
7811 if (IsEventLogging())
7812 {
7813 (void) LogMagickEvent(X11Event,GetMagickModule(),
7814 "Standard Colormap:");
7815 (void) LogMagickEvent(X11Event,GetMagickModule(),
7816 " colormap id: 0x%lx",map_info->colormap);
7817 (void) LogMagickEvent(X11Event,GetMagickModule(),
7818 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7819 map_info->green_max,map_info->blue_max);
7820 (void) LogMagickEvent(X11Event,GetMagickModule(),
7821 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7822 map_info->green_mult,map_info->blue_mult);
7823 }
7824 return;
7825 }
7826 if ((visual_info->klass != DirectColor) &&
7827 (visual_info->klass != TrueColor))
7828 if ((image->storage_class == DirectClass) ||
7829 ((int) image->colors > visual_info->colormap_size))
7830 {
7831 QuantizeInfo
7832 quantize_info;
7833
7834 /*
7835 Image has more colors than the visual supports.
7836 */
7837 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007838 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00007839 (void) QuantizeImage(&quantize_info,image);
7840 }
7841 /*
7842 Free previous and create new colormap.
7843 */
7844 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7845 colormap=XDefaultColormap(display,visual_info->screen);
7846 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7847 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7848 visual_info->visual,visual_info->klass == DirectColor ?
7849 AllocAll : AllocNone);
7850 if (colormap == (Colormap) NULL)
7851 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7852 image->filename);
7853 /*
7854 Initialize the map and pixel info structures.
7855 */
7856 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007857 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007858 /*
7859 Allocating colors in server colormap is based on visual class.
7860 */
7861 switch (visual_info->klass)
7862 {
7863 case StaticGray:
7864 case StaticColor:
7865 {
7866 /*
7867 Define Standard Colormap for StaticGray or StaticColor visual.
7868 */
7869 number_colors=image->colors;
7870 colors=(XColor *) AcquireQuantumMemory((size_t)
7871 visual_info->colormap_size,sizeof(*colors));
7872 if (colors == (XColor *) NULL)
7873 ThrowXWindowFatalException(ResourceLimitFatalError,
7874 "UnableToCreateColormap",image->filename);
7875 p=colors;
7876 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007877 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007878 {
7879 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7880 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7881 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7882 if (visual_info->klass != StaticColor)
7883 {
7884 gray_value=(unsigned short) XPixelIntensity(&color);
7885 color.red=gray_value;
7886 color.green=gray_value;
7887 color.blue=gray_value;
7888 }
7889 status=XAllocColor(display,colormap,&color);
7890 if (status == False)
7891 {
7892 colormap=XCopyColormapAndFree(display,colormap);
7893 (void) XAllocColor(display,colormap,&color);
7894 }
7895 pixel->pixels[i]=color.pixel;
7896 *p++=color;
7897 }
7898 break;
7899 }
7900 case GrayScale:
7901 case PseudoColor:
7902 {
7903 unsigned int
7904 colormap_type;
7905
7906 /*
7907 Define Standard Colormap for GrayScale or PseudoColor visual.
7908 */
7909 number_colors=image->colors;
7910 colors=(XColor *) AcquireQuantumMemory((size_t)
7911 visual_info->colormap_size,sizeof(*colors));
7912 if (colors == (XColor *) NULL)
7913 ThrowXWindowFatalException(ResourceLimitFatalError,
7914 "UnableToCreateColormap",image->filename);
7915 /*
7916 Preallocate our GUI colors.
7917 */
7918 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7919 (void) XAllocColor(display,colormap,&pixel->background_color);
7920 (void) XAllocColor(display,colormap,&pixel->border_color);
7921 (void) XAllocColor(display,colormap,&pixel->matte_color);
7922 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7923 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7924 (void) XAllocColor(display,colormap,&pixel->depth_color);
7925 (void) XAllocColor(display,colormap,&pixel->trough_color);
7926 for (i=0; i < MaxNumberPens; i++)
7927 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7928 /*
7929 Determine if image colors will "fit" into X server colormap.
7930 */
7931 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007932 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007933 NULL,0,pixel->pixels,(unsigned int) image->colors);
7934 if (status != False)
7935 colormap_type=PrivateColormap;
7936 if (colormap_type == SharedColormap)
7937 {
cristyc57f6942010-11-12 01:47:39 +00007938 CacheView
7939 *image_view;
7940
cristy3ed852e2009-09-05 21:47:34 +00007941 DiversityPacket
7942 *diversity;
7943
7944 int
7945 y;
7946
7947 register int
7948 x;
7949
7950 unsigned short
7951 index;
7952
7953 XColor
7954 *server_colors;
7955
7956 /*
7957 Define Standard colormap for shared GrayScale or PseudoColor visual.
7958 */
7959 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7960 sizeof(*diversity));
7961 if (diversity == (DiversityPacket *) NULL)
7962 ThrowXWindowFatalException(ResourceLimitFatalError,
7963 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007964 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007965 {
7966 diversity[i].red=image->colormap[i].red;
7967 diversity[i].green=image->colormap[i].green;
7968 diversity[i].blue=image->colormap[i].blue;
7969 diversity[i].index=(unsigned short) i;
7970 diversity[i].count=0;
7971 }
cristyc57f6942010-11-12 01:47:39 +00007972 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00007973 for (y=0; y < (int) image->rows; y++)
7974 {
cristyc57f6942010-11-12 01:47:39 +00007975 register int
cristy3ed852e2009-09-05 21:47:34 +00007976 x;
7977
cristy4c08aed2011-07-01 19:47:50 +00007978 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007979 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007980
cristyc57f6942010-11-12 01:47:39 +00007981 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7982 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007983 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007984 break;
cristyc57f6942010-11-12 01:47:39 +00007985 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00007986 {
7987 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00007988 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00007989 }
cristy3ed852e2009-09-05 21:47:34 +00007990 }
cristyc57f6942010-11-12 01:47:39 +00007991 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00007992 /*
7993 Sort colors by decreasing intensity.
7994 */
7995 qsort((void *) diversity,image->colors,sizeof(*diversity),
7996 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00007997 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00007998 {
7999 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008000 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008001 }
8002 diversity[image->colors-1].count<<=4;
8003 qsort((void *) diversity,image->colors,sizeof(*diversity),
8004 PopularityCompare);
8005 /*
8006 Allocate colors.
8007 */
8008 p=colors;
8009 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008010 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008011 {
8012 index=diversity[i].index;
8013 color.red=
8014 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8015 color.green=
8016 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8017 color.blue=
8018 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8019 if (visual_info->klass != PseudoColor)
8020 {
8021 gray_value=(unsigned short) XPixelIntensity(&color);
8022 color.red=gray_value;
8023 color.green=gray_value;
8024 color.blue=gray_value;
8025 }
8026 status=XAllocColor(display,colormap,&color);
8027 if (status == False)
8028 break;
8029 pixel->pixels[index]=color.pixel;
8030 *p++=color;
8031 }
8032 /*
8033 Read X server colormap.
8034 */
8035 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8036 visual_info->colormap_size,sizeof(*server_colors));
8037 if (server_colors == (XColor *) NULL)
8038 ThrowXWindowFatalException(ResourceLimitFatalError,
8039 "UnableToCreateColormap",image->filename);
8040 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008041 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008042 (void) XQueryColors(display,colormap,server_colors,
8043 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8044 /*
8045 Select remaining colors from X server colormap.
8046 */
cristybb503372010-05-27 20:51:26 +00008047 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008048 {
8049 index=diversity[i].index;
8050 color.red=
8051 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8052 color.green=
8053 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8054 color.blue=
8055 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8056 if (visual_info->klass != PseudoColor)
8057 {
8058 gray_value=(unsigned short) XPixelIntensity(&color);
8059 color.red=gray_value;
8060 color.green=gray_value;
8061 color.blue=gray_value;
8062 }
8063 XBestPixel(display,colormap,server_colors,(unsigned int)
8064 visual_info->colormap_size,&color);
8065 pixel->pixels[index]=color.pixel;
8066 *p++=color;
8067 }
8068 if ((int) image->colors < visual_info->colormap_size)
8069 {
8070 /*
8071 Fill up colors array-- more choices for pen colors.
8072 */
8073 retain_colors=MagickMin((unsigned int)
8074 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008075 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008076 *p++=server_colors[i];
8077 number_colors+=retain_colors;
8078 }
8079 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8080 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8081 break;
8082 }
8083 /*
8084 Define Standard colormap for private GrayScale or PseudoColor visual.
8085 */
8086 if (status == False)
8087 {
8088 /*
8089 Not enough colormap entries in the colormap-- Create a new colormap.
8090 */
8091 colormap=XCreateColormap(display,
8092 XRootWindow(display,visual_info->screen),visual_info->visual,
8093 AllocNone);
8094 if (colormap == (Colormap) NULL)
8095 ThrowXWindowFatalException(ResourceLimitFatalError,
8096 "UnableToCreateColormap",image->filename);
8097 map_info->colormap=colormap;
8098 if ((int) image->colors < visual_info->colormap_size)
8099 {
8100 /*
8101 Retain colors from the default colormap to help lessens the
8102 effects of colormap flashing.
8103 */
8104 retain_colors=MagickMin((unsigned int)
8105 (visual_info->colormap_size-image->colors),256);
8106 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008107 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008108 {
cristyc57f6942010-11-12 01:47:39 +00008109 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008110 p++;
8111 }
8112 (void) XQueryColors(display,
8113 XDefaultColormap(display,visual_info->screen),
8114 colors+image->colors,(int) retain_colors);
8115 /*
8116 Transfer colors from default to private colormap.
8117 */
8118 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008119 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008120 retain_colors);
8121 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008122 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008123 {
8124 p->pixel=pixel->pixels[i];
8125 p++;
8126 }
8127 (void) XStoreColors(display,colormap,colors+image->colors,
8128 (int) retain_colors);
8129 number_colors+=retain_colors;
8130 }
8131 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008132 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008133 image->colors);
8134 }
8135 /*
8136 Store the image colormap.
8137 */
8138 p=colors;
8139 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008140 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008141 {
8142 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8143 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8144 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8145 if (visual_info->klass != PseudoColor)
8146 {
8147 gray_value=(unsigned short) XPixelIntensity(&color);
8148 color.red=gray_value;
8149 color.green=gray_value;
8150 color.blue=gray_value;
8151 }
8152 color.pixel=pixel->pixels[i];
8153 *p++=color;
8154 }
8155 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8156 break;
8157 }
8158 case TrueColor:
8159 case DirectColor:
8160 default:
8161 {
8162 MagickBooleanType
8163 linear_colormap;
8164
8165 /*
8166 Define Standard Colormap for TrueColor or DirectColor visual.
8167 */
8168 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8169 (map_info->green_max*map_info->green_mult)+
8170 (map_info->blue_max*map_info->blue_mult)+1);
8171 linear_colormap=(number_colors > 4096) ||
8172 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8173 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8174 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8175 MagickTrue : MagickFalse;
8176 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008177 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008178 /*
8179 Allocate color array.
8180 */
8181 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8182 if (colors == (XColor *) NULL)
8183 ThrowXWindowFatalException(ResourceLimitFatalError,
8184 "UnableToCreateColormap",image->filename);
8185 /*
8186 Initialize linear color ramp.
8187 */
8188 p=colors;
8189 color.flags=(char) (DoRed | DoGreen | DoBlue);
8190 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008191 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008192 {
8193 color.blue=(unsigned short) 0;
8194 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008195 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008196 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8197 color.green=color.blue;
8198 color.red=color.blue;
8199 color.pixel=XStandardPixel(map_info,&color);
8200 *p++=color;
8201 }
8202 else
cristybb503372010-05-27 20:51:26 +00008203 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008204 {
8205 color.red=(unsigned short) 0;
8206 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008207 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008208 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8209 color.green=(unsigned int) 0;
8210 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008211 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008212 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8213 map_info->green_max));
8214 color.blue=(unsigned short) 0;
8215 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008216 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008217 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8218 color.pixel=XStandardPixel(map_info,&color);
8219 *p++=color;
8220 }
8221 if ((visual_info->klass == DirectColor) &&
8222 (colormap != XDefaultColormap(display,visual_info->screen)))
8223 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8224 else
cristybb503372010-05-27 20:51:26 +00008225 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008226 (void) XAllocColor(display,colormap,&colors[i]);
8227 break;
8228 }
8229 }
8230 if ((visual_info->klass != DirectColor) &&
8231 (visual_info->klass != TrueColor))
8232 {
8233 /*
8234 Set foreground, background, border, etc. pixels.
8235 */
8236 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8237 &pixel->foreground_color);
8238 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8239 &pixel->background_color);
8240 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8241 {
8242 /*
8243 Foreground and background colors must differ.
8244 */
8245 pixel->background_color.red=(~pixel->foreground_color.red);
8246 pixel->background_color.green=
8247 (~pixel->foreground_color.green);
8248 pixel->background_color.blue=
8249 (~pixel->foreground_color.blue);
8250 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8251 &pixel->background_color);
8252 }
8253 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8254 &pixel->border_color);
8255 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8256 &pixel->matte_color);
8257 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8258 &pixel->highlight_color);
8259 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8260 &pixel->shadow_color);
8261 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8262 &pixel->depth_color);
8263 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8264 &pixel->trough_color);
8265 for (i=0; i < MaxNumberPens; i++)
8266 {
8267 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8268 &pixel->pen_colors[i]);
8269 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8270 }
cristyc57f6942010-11-12 01:47:39 +00008271 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008272 }
8273 colors=(XColor *) RelinquishMagickMemory(colors);
8274 if (IsEventLogging())
8275 {
8276 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8277 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8278 map_info->colormap);
8279 (void) LogMagickEvent(X11Event,GetMagickModule(),
8280 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8281 map_info->green_max,map_info->blue_max);
8282 (void) LogMagickEvent(X11Event,GetMagickModule(),
8283 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8284 map_info->green_mult,map_info->blue_mult);
8285 }
8286}
8287
8288/*
8289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8290% %
8291% %
8292% %
8293% X M a k e W i n d o w %
8294% %
8295% %
8296% %
8297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8298%
8299% XMakeWindow() creates an X11 window.
8300%
8301% The format of the XMakeWindow method is:
8302%
8303% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8304% XClassHint *class_hint,XWMHints *manager_hints,
8305% XWindowInfo *window_info)
8306%
8307% A description of each parameter follows:
8308%
8309% o display: Specifies a connection to an X server; returned from
8310% XOpenDisplay.
8311%
8312% o parent: Specifies the parent window_info.
8313%
8314% o argv: Specifies the application's argument list.
8315%
8316% o argc: Specifies the number of arguments.
8317%
8318% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8319%
8320% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8321%
8322% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8323%
8324*/
8325MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8326 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8327 XWindowInfo *window_info)
8328{
8329#define MinWindowSize 64
8330
8331 Atom
8332 atom_list[2];
8333
8334 int
8335 gravity;
8336
8337 static XTextProperty
8338 icon_name,
8339 window_name;
8340
8341 Status
8342 status;
8343
8344 XSizeHints
8345 *size_hints;
8346
8347 /*
8348 Set window info hints.
8349 */
8350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8351 assert(display != (Display *) NULL);
8352 assert(window_info != (XWindowInfo *) NULL);
8353 size_hints=XAllocSizeHints();
8354 if (size_hints == (XSizeHints *) NULL)
8355 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008356 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008357 size_hints->x=window_info->x;
8358 size_hints->y=window_info->y;
8359 size_hints->width=(int) window_info->width;
8360 size_hints->height=(int) window_info->height;
8361 if (window_info->immutable != MagickFalse)
8362 {
8363 /*
8364 Window size cannot be changed.
8365 */
8366 size_hints->min_width=size_hints->width;
8367 size_hints->min_height=size_hints->height;
8368 size_hints->max_width=size_hints->width;
8369 size_hints->max_height=size_hints->height;
8370 size_hints->flags|=PMinSize;
8371 size_hints->flags|=PMaxSize;
8372 }
8373 else
8374 {
8375 /*
8376 Window size can be changed.
8377 */
8378 size_hints->min_width=(int) window_info->min_width;
8379 size_hints->min_height=(int) window_info->min_height;
8380 size_hints->flags|=PResizeInc;
8381 size_hints->width_inc=(int) window_info->width_inc;
8382 size_hints->height_inc=(int) window_info->height_inc;
8383#if !defined(PRE_R4_ICCCM)
8384 size_hints->flags|=PBaseSize;
8385 size_hints->base_width=size_hints->width_inc;
8386 size_hints->base_height=size_hints->height_inc;
8387#endif
8388 }
8389 gravity=NorthWestGravity;
8390 if (window_info->geometry != (char *) NULL)
8391 {
8392 char
8393 default_geometry[MaxTextExtent],
8394 geometry[MaxTextExtent];
8395
8396 int
8397 flags;
8398
8399 register char
8400 *p;
8401
8402 /*
8403 User specified geometry.
8404 */
cristyb51dff52011-05-19 16:55:47 +00008405 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008406 size_hints->width,size_hints->height);
8407 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8408 p=geometry;
8409 while (strlen(p) != 0)
8410 {
8411 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8412 p++;
8413 else
8414 (void) CopyMagickString(p,p+1,MaxTextExtent);
8415 }
8416 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8417 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8418 &size_hints->width,&size_hints->height,&gravity);
8419 if ((flags & WidthValue) && (flags & HeightValue))
8420 size_hints->flags|=USSize;
8421 if ((flags & XValue) && (flags & YValue))
8422 {
8423 size_hints->flags|=USPosition;
8424 window_info->x=size_hints->x;
8425 window_info->y=size_hints->y;
8426 }
8427 }
8428#if !defined(PRE_R4_ICCCM)
8429 size_hints->win_gravity=gravity;
8430 size_hints->flags|=PWinGravity;
8431#endif
8432 if (window_info->id == (Window) NULL)
8433 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8434 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8435 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008436 window_info->visual,(unsigned long) window_info->mask,
8437 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008438 else
8439 {
8440 MagickStatusType
8441 mask;
8442
8443 XEvent
8444 sans_event;
8445
8446 XWindowChanges
8447 window_changes;
8448
8449 /*
8450 Window already exists; change relevant attributes.
8451 */
cristyc57f6942010-11-12 01:47:39 +00008452 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8453 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008454 mask=ConfigureNotify;
8455 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8456 window_changes.x=window_info->x;
8457 window_changes.y=window_info->y;
8458 window_changes.width=(int) window_info->width;
8459 window_changes.height=(int) window_info->height;
8460 mask=(MagickStatusType) (CWWidth | CWHeight);
8461 if (window_info->flags & USPosition)
8462 mask|=CWX | CWY;
8463 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8464 mask,&window_changes);
8465 }
8466 if (window_info->id == (Window) NULL)
8467 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8468 window_info->name);
8469 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8470 if (status == False)
8471 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8472 window_info->name);
8473 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8474 if (status == False)
8475 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8476 window_info->icon_name);
8477 if (window_info->icon_geometry != (char *) NULL)
8478 {
8479 int
8480 flags,
8481 height,
8482 width;
8483
8484 /*
8485 User specified icon geometry.
8486 */
8487 size_hints->flags|=USPosition;
8488 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8489 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8490 &manager_hints->icon_y,&width,&height,&gravity);
8491 if ((flags & XValue) && (flags & YValue))
8492 manager_hints->flags|=IconPositionHint;
8493 }
8494 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8495 size_hints,manager_hints,class_hint);
8496 if (window_name.value != (void *) NULL)
8497 {
8498 (void) XFree((void *) window_name.value);
8499 window_name.value=(unsigned char *) NULL;
8500 window_name.nitems=0;
8501 }
8502 if (icon_name.value != (void *) NULL)
8503 {
8504 (void) XFree((void *) icon_name.value);
8505 icon_name.value=(unsigned char *) NULL;
8506 icon_name.nitems=0;
8507 }
8508 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8509 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8510 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8511 (void) XFree((void *) size_hints);
8512 if (window_info->shape != MagickFalse)
8513 {
8514#if defined(MAGICKCORE_HAVE_SHAPE)
8515 int
8516 error_base,
8517 event_base;
8518
8519 /*
8520 Can we apply a non-rectangular shaping mask?
8521 */
8522 error_base=0;
8523 event_base=0;
8524 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8525 window_info->shape=MagickFalse;
8526#else
8527 window_info->shape=MagickFalse;
8528#endif
8529 }
8530 if (window_info->shared_memory)
8531 {
8532#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8533 /*
8534 Can we use shared memory with this window?
8535 */
8536 if (XShmQueryExtension(display) == 0)
8537 window_info->shared_memory=MagickFalse;
8538#else
8539 window_info->shared_memory=MagickFalse;
8540#endif
8541 }
8542 window_info->image=NewImageList();
8543 window_info->destroy=MagickFalse;
8544}
8545
8546/*
8547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8548% %
8549% %
8550% %
8551% X M a g i c k P r o g r e s s M o n i t o r %
8552% %
8553% %
8554% %
8555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8556%
8557% XMagickProgressMonitor() displays the progress a task is making in
8558% completing a task.
8559%
8560% The format of the XMagickProgressMonitor method is:
8561%
8562% void XMagickProgressMonitor(const char *task,
8563% const MagickOffsetType quantum,const MagickSizeType span,
8564% void *client_data)
8565%
8566% A description of each parameter follows:
8567%
8568% o task: Identifies the task in progress.
8569%
8570% o quantum: Specifies the quantum position within the span which represents
8571% how much progress has been made in completing a task.
8572%
8573% o span: Specifies the span relative to completing a task.
8574%
8575% o client_data: Pointer to any client data.
8576%
8577*/
8578
8579static const char *GetLocaleMonitorMessage(const char *text)
8580{
8581 char
8582 message[MaxTextExtent],
8583 tag[MaxTextExtent];
8584
8585 const char
8586 *locale_message;
8587
8588 register char
8589 *p;
8590
8591 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8592 p=strrchr(tag,'/');
8593 if (p != (char *) NULL)
8594 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008595 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008596 locale_message=GetLocaleMessage(message);
8597 if (locale_message == message)
8598 return(text);
8599 return(locale_message);
8600}
8601
8602MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8603 const MagickOffsetType quantum,const MagickSizeType span,
8604 void *magick_unused(client_data))
8605{
8606 XWindows
8607 *windows;
8608
8609 windows=XSetWindows((XWindows *) ~0);
8610 if (windows == (XWindows *) NULL)
8611 return(MagickTrue);
8612 if (windows->info.mapped != MagickFalse)
8613 XProgressMonitorWidget(windows->display,windows,
8614 GetLocaleMonitorMessage(tag),quantum,span);
8615 return(MagickTrue);
8616}
8617
8618/*
8619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8620% %
8621% %
8622% %
8623% X Q u e r y C o l o r D a t a b a s e %
8624% %
8625% %
8626% %
8627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8628%
8629% XQueryColorDatabase() looks up a RGB values for a color given in the target
8630% string.
8631%
8632% The format of the XQueryColorDatabase method is:
8633%
8634% MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8635%
8636% A description of each parameter follows:
8637%
8638% o target: Specifies the color to lookup in the X color database.
8639%
8640% o color: A pointer to an PixelPacket structure. The RGB value of the target
8641% color is returned as this value.
8642%
8643*/
8644MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8645 XColor *color)
8646{
8647 Colormap
8648 colormap;
8649
8650 static Display
8651 *display = (Display *) NULL;
8652
8653 Status
8654 status;
8655
8656 XColor
8657 xcolor;
8658
8659 /*
8660 Initialize color return value.
8661 */
8662 assert(color != (XColor *) NULL);
8663 color->red=0;
8664 color->green=0;
8665 color->blue=0;
8666 color->flags=(char) (DoRed | DoGreen | DoBlue);
8667 if ((target == (char *) NULL) || (*target == '\0'))
8668 target="#ffffffffffff";
8669 /*
8670 Let the X server define the color for us.
8671 */
8672 if (display == (Display *) NULL)
8673 display=XOpenDisplay((char *) NULL);
8674 if (display == (Display *) NULL)
8675 {
8676 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8677 return(MagickFalse);
8678 }
8679 colormap=XDefaultColormap(display,XDefaultScreen(display));
8680 status=XParseColor(display,colormap,(char *) target,&xcolor);
8681 if (status == False)
8682 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8683 else
8684 {
8685 color->red=xcolor.red;
8686 color->green=xcolor.green;
8687 color->blue=xcolor.blue;
8688 color->flags=xcolor.flags;
8689 }
8690 return(status != False ? MagickTrue : MagickFalse);
8691}
8692
8693/*
8694%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8695% %
8696% %
8697% %
8698% X Q u e r y P o s i t i o n %
8699% %
8700% %
8701% %
8702%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8703%
8704% XQueryPosition() gets the pointer coordinates relative to a window.
8705%
8706% The format of the XQueryPosition method is:
8707%
8708% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8709%
8710% A description of each parameter follows:
8711%
8712% o display: Specifies a connection to an X server; returned from
8713% XOpenDisplay.
8714%
8715% o window: Specifies a pointer to a Window.
8716%
8717% o x: Return the x coordinate of the pointer relative to the origin of the
8718% window.
8719%
8720% o y: Return the y coordinate of the pointer relative to the origin of the
8721% window.
8722%
8723*/
8724MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8725{
8726 int
8727 x_root,
8728 y_root;
8729
8730 unsigned int
8731 mask;
8732
8733 Window
8734 root_window;
8735
8736 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8737 assert(display != (Display *) NULL);
8738 assert(window != (Window) NULL);
8739 assert(x != (int *) NULL);
8740 assert(y != (int *) NULL);
8741 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8742 x,y,&mask);
8743}
8744
8745/*
8746%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8747% %
8748% %
8749% %
8750% X R e f r e s h W i n d o w %
8751% %
8752% %
8753% %
8754%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8755%
8756% XRefreshWindow() refreshes an image in a X window.
8757%
8758% The format of the XRefreshWindow method is:
8759%
8760% void XRefreshWindow(Display *display,const XWindowInfo *window,
8761% const XEvent *event)
8762%
8763% A description of each parameter follows:
8764%
8765% o display: Specifies a connection to an X server; returned from
8766% XOpenDisplay.
8767%
8768% o window: Specifies a pointer to a XWindowInfo structure.
8769%
8770% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8771% the entire image is refreshed.
8772%
8773*/
8774MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8775 const XEvent *event)
8776{
8777 int
8778 x,
8779 y;
8780
8781 unsigned int
8782 height,
8783 width;
8784
8785 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8786 assert(display != (Display *) NULL);
8787 assert(window != (XWindowInfo *) NULL);
8788 if (window->ximage == (XImage *) NULL)
8789 return;
8790 if (event != (XEvent *) NULL)
8791 {
8792 /*
8793 Determine geometry from expose event.
8794 */
8795 x=event->xexpose.x;
8796 y=event->xexpose.y;
8797 width=(unsigned int) event->xexpose.width;
8798 height=(unsigned int) event->xexpose.height;
8799 }
8800 else
8801 {
8802 XEvent
8803 sans_event;
8804
8805 /*
8806 Refresh entire window; discard outstanding expose events.
8807 */
8808 x=0;
8809 y=0;
8810 width=window->width;
8811 height=window->height;
8812 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008813 if (window->matte_pixmap != (Pixmap) NULL)
8814 {
8815#if defined(MAGICKCORE_HAVE_SHAPE)
8816 if (window->shape != MagickFalse)
8817 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8818 window->matte_pixmap,ShapeSet);
8819#endif
8820 }
cristy3ed852e2009-09-05 21:47:34 +00008821 }
8822 /*
8823 Check boundary conditions.
8824 */
8825 if ((window->ximage->width-(x+window->x)) < (int) width)
8826 width=(unsigned int) (window->ximage->width-(x+window->x));
8827 if ((window->ximage->height-(y+window->y)) < (int) height)
8828 height=(unsigned int) (window->ximage->height-(y+window->y));
8829 /*
8830 Refresh image.
8831 */
8832 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008833 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008834 if (window->pixmap != (Pixmap) NULL)
8835 {
8836 if (window->depth > 1)
8837 (void) XCopyArea(display,window->pixmap,window->id,
8838 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8839 else
8840 (void) XCopyPlane(display,window->pixmap,window->id,
8841 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8842 1L);
8843 }
8844 else
8845 {
8846#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8847 if (window->shared_memory)
8848 (void) XShmPutImage(display,window->id,window->annotate_context,
8849 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8850#endif
8851 if (window->shared_memory == MagickFalse)
8852 (void) XPutImage(display,window->id,window->annotate_context,
8853 window->ximage,x+window->x,y+window->y,x,y,width,height);
8854 }
8855 if (window->matte_pixmap != (Pixmap) NULL)
8856 (void) XSetClipMask(display,window->annotate_context,None);
8857 (void) XFlush(display);
8858}
8859
8860/*
8861%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8862% %
8863% %
8864% %
8865% X R e m o t e C o m m a n d %
8866% %
8867% %
8868% %
8869%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8870%
8871% XRemoteCommand() forces a remote display(1) to display the specified
8872% image filename.
8873%
8874% The format of the XRemoteCommand method is:
8875%
8876% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8877% const char *filename)
8878%
8879% A description of each parameter follows:
8880%
8881% o display: Specifies a connection to an X server; returned from
8882% XOpenDisplay.
8883%
8884% o window: Specifies the name or id of an X window.
8885%
8886% o filename: the name of the image filename to display.
8887%
8888*/
8889MagickExport MagickBooleanType XRemoteCommand(Display *display,
8890 const char *window,const char *filename)
8891{
8892 Atom
8893 remote_atom;
8894
8895 Window
8896 remote_window,
8897 root_window;
8898
8899 assert(filename != (char *) NULL);
8900 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8901 if (display == (Display *) NULL)
8902 display=XOpenDisplay((char *) NULL);
8903 if (display == (Display *) NULL)
8904 {
8905 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8906 return(MagickFalse);
8907 }
8908 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8909 remote_window=(Window) NULL;
8910 root_window=XRootWindow(display,XDefaultScreen(display));
8911 if (window != (char *) NULL)
8912 {
8913 /*
8914 Search window hierarchy and identify any clients by name or ID.
8915 */
8916 if (isdigit((unsigned char) *window) != 0)
8917 remote_window=XWindowByID(display,root_window,(Window)
8918 strtol((char *) window,(char **) NULL,0));
8919 if (remote_window == (Window) NULL)
8920 remote_window=XWindowByName(display,root_window,window);
8921 }
8922 if (remote_window == (Window) NULL)
8923 remote_window=XWindowByProperty(display,root_window,remote_atom);
8924 if (remote_window == (Window) NULL)
8925 {
8926 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8927 filename);
8928 return(MagickFalse);
8929 }
8930 /*
8931 Send remote command.
8932 */
8933 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8934 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8935 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8936 (void) XSync(display,MagickFalse);
8937 return(MagickTrue);
8938}
8939
8940/*
8941%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8942% %
8943% %
8944% %
8945% X R e t a i n W i n d o w C o l o r s %
8946% %
8947% %
8948% %
8949%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8950%
8951% XRetainWindowColors() sets X11 color resources on a window. This preserves
8952% the colors associated with an image displayed on the window.
8953%
8954% The format of the XRetainWindowColors method is:
8955%
8956% void XRetainWindowColors(Display *display,const Window window)
8957%
8958% A description of each parameter follows:
8959%
8960% o display: Specifies a connection to an X server; returned from
8961% XOpenDisplay.
8962%
8963% o window: Specifies a pointer to a XWindowInfo structure.
8964%
8965*/
8966MagickExport void XRetainWindowColors(Display *display,const Window window)
8967{
8968 Atom
8969 property;
8970
8971 Pixmap
8972 pixmap;
8973
8974 /*
8975 Put property on the window.
8976 */
8977 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8978 assert(display != (Display *) NULL);
8979 assert(window != (Window) NULL);
8980 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8981 if (property == (Atom) NULL)
8982 {
8983 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8984 "_XSETROOT_ID");
8985 return;
8986 }
8987 pixmap=XCreatePixmap(display,window,1,1,1);
8988 if (pixmap == (Pixmap) NULL)
8989 {
8990 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8991 return;
8992 }
8993 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8994 (unsigned char *) &pixmap,1);
8995 (void) XSetCloseDownMode(display,RetainPermanent);
8996}
8997
8998/*
8999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9000% %
9001% %
9002% %
9003% X S e l e c t W i n d o w %
9004% %
9005% %
9006% %
9007%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9008%
9009% XSelectWindow() allows a user to select a window using the mouse. If the
9010% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9011% is returned in the crop_info structure.
9012%
9013% The format of the XSelectWindow function is:
9014%
9015% target_window=XSelectWindow(display,crop_info)
9016%
9017% A description of each parameter follows:
9018%
9019% o window: XSelectWindow returns the window id.
9020%
9021% o display: Specifies a pointer to the Display structure; returned from
9022% XOpenDisplay.
9023%
9024% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9025% contains the extents of any cropping rectangle.
9026%
cristy3ed852e2009-09-05 21:47:34 +00009027*/
9028static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9029{
9030#define MinimumCropArea (unsigned int) 9
9031
9032 Cursor
9033 target_cursor;
9034
9035 GC
9036 annotate_context;
9037
9038 int
9039 presses,
9040 x_offset,
9041 y_offset;
9042
9043 Status
9044 status;
9045
9046 Window
9047 root_window,
9048 target_window;
9049
9050 XEvent
9051 event;
9052
9053 XGCValues
9054 context_values;
9055
9056 /*
9057 Initialize graphic context.
9058 */
9059 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9060 assert(display != (Display *) NULL);
9061 assert(crop_info != (RectangleInfo *) NULL);
9062 root_window=XRootWindow(display,XDefaultScreen(display));
9063 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9064 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9065 context_values.function=GXinvert;
9066 context_values.plane_mask=
9067 context_values.background ^ context_values.foreground;
9068 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009069 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009070 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9071 if (annotate_context == (GC) NULL)
9072 return(MagickFalse);
9073 /*
9074 Grab the pointer using target cursor.
9075 */
9076 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9077 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9078 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9079 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9080 GrabModeAsync,root_window,target_cursor,CurrentTime);
9081 if (status != GrabSuccess)
9082 {
9083 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9084 return((Window) NULL);
9085 }
9086 /*
9087 Select a window.
9088 */
9089 crop_info->width=0;
9090 crop_info->height=0;
9091 presses=0;
9092 target_window=(Window) NULL;
9093 x_offset=0;
9094 y_offset=0;
9095 do
9096 {
9097 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9098 (void) XDrawRectangle(display,root_window,annotate_context,
9099 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9100 (unsigned int) crop_info->height-1);
9101 /*
9102 Allow another event.
9103 */
9104 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9105 (void) XWindowEvent(display,root_window,ButtonPressMask |
9106 ButtonReleaseMask | ButtonMotionMask,&event);
9107 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9108 (void) XDrawRectangle(display,root_window,annotate_context,
9109 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9110 (unsigned int) crop_info->height-1);
9111 switch (event.type)
9112 {
9113 case ButtonPress:
9114 {
9115 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9116 event.xbutton.x,event.xbutton.y);
9117 if (target_window == (Window) NULL)
9118 target_window=root_window;
9119 x_offset=event.xbutton.x_root;
9120 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009121 crop_info->x=(ssize_t) x_offset;
9122 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009123 crop_info->width=0;
9124 crop_info->height=0;
9125 presses++;
9126 break;
9127 }
9128 case ButtonRelease:
9129 {
9130 presses--;
9131 break;
9132 }
9133 case MotionNotify:
9134 {
9135 /*
9136 Discard pending button motion events.
9137 */
9138 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009139 crop_info->x=(ssize_t) event.xmotion.x;
9140 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009141 /*
9142 Check boundary conditions.
9143 */
9144 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009145 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009146 else
9147 {
cristyecd0ab52010-05-30 14:59:20 +00009148 crop_info->width=(size_t) (crop_info->x-x_offset);
9149 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009150 }
9151 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009152 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009153 else
9154 {
cristyecd0ab52010-05-30 14:59:20 +00009155 crop_info->height=(size_t) (crop_info->y-y_offset);
9156 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009157 }
9158 }
9159 default:
9160 break;
9161 }
9162 } while ((target_window == (Window) NULL) || (presses > 0));
9163 (void) XUngrabPointer(display,CurrentTime);
9164 (void) XFreeCursor(display,target_cursor);
9165 (void) XFreeGC(display,annotate_context);
9166 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9167 {
9168 crop_info->width=0;
9169 crop_info->height=0;
9170 }
9171 if ((crop_info->width != 0) && (crop_info->height != 0))
9172 target_window=root_window;
9173 return(target_window);
9174}
9175
9176/*
9177%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9178% %
9179% %
9180% %
9181% X S e t C u r s o r S t a t e %
9182% %
9183% %
9184% %
9185%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9186%
9187% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9188% reset to their default.
9189%
9190% The format of the XXSetCursorState method is:
9191%
9192% XSetCursorState(display,windows,const MagickStatusType state)
9193%
9194% A description of each parameter follows:
9195%
9196% o display: Specifies a connection to an X server; returned from
9197% XOpenDisplay.
9198%
9199% o windows: Specifies a pointer to a XWindows structure.
9200%
9201% o state: An unsigned integer greater than 0 sets the cursor state
9202% to busy, otherwise the cursor are reset to their default.
9203%
9204*/
9205MagickExport void XSetCursorState(Display *display,XWindows *windows,
9206 const MagickStatusType state)
9207{
9208 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9209 assert(display != (Display *) NULL);
9210 assert(windows != (XWindows *) NULL);
9211 if (state)
9212 {
9213 (void) XCheckDefineCursor(display,windows->image.id,
9214 windows->image.busy_cursor);
9215 (void) XCheckDefineCursor(display,windows->pan.id,
9216 windows->pan.busy_cursor);
9217 (void) XCheckDefineCursor(display,windows->magnify.id,
9218 windows->magnify.busy_cursor);
9219 (void) XCheckDefineCursor(display,windows->command.id,
9220 windows->command.busy_cursor);
9221 }
9222 else
9223 {
9224 (void) XCheckDefineCursor(display,windows->image.id,
9225 windows->image.cursor);
9226 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9227 (void) XCheckDefineCursor(display,windows->magnify.id,
9228 windows->magnify.cursor);
9229 (void) XCheckDefineCursor(display,windows->command.id,
9230 windows->command.cursor);
9231 (void) XCheckDefineCursor(display,windows->command.id,
9232 windows->widget.cursor);
9233 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9234 }
9235 windows->info.mapped=MagickFalse;
9236}
9237
9238/*
9239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9240% %
9241% %
9242% %
9243% X S e t W i n d o w s %
9244% %
9245% %
9246% %
9247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9248%
9249% XSetWindows() sets the X windows structure if the windows info is specified.
9250% Otherwise the current windows structure is returned.
9251%
9252% The format of the XSetWindows method is:
9253%
9254% XWindows *XSetWindows(XWindows *windows_info)
9255%
9256% A description of each parameter follows:
9257%
9258% o windows_info: Initialize the Windows structure with this information.
9259%
9260*/
9261MagickExport XWindows *XSetWindows(XWindows *windows_info)
9262{
9263 static XWindows
9264 *windows = (XWindows *) NULL;
9265
9266 if (windows_info != (XWindows *) ~0)
9267 {
9268 windows=(XWindows *) RelinquishMagickMemory(windows);
9269 windows=windows_info;
9270 }
9271 return(windows);
9272}
9273/*
9274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9275% %
9276% %
9277% %
9278% X U s e r P r e f e r e n c e s %
9279% %
9280% %
9281% %
9282%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9283%
9284% XUserPreferences() saves the preferences in a configuration file in the
9285% users' home directory.
9286%
9287% The format of the XUserPreferences method is:
9288%
9289% void XUserPreferences(XResourceInfo *resource_info)
9290%
9291% A description of each parameter follows:
9292%
9293% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9294%
9295*/
9296MagickExport void XUserPreferences(XResourceInfo *resource_info)
9297{
9298#if defined(X11_PREFERENCES_PATH)
9299 char
9300 cache[MaxTextExtent],
9301 filename[MaxTextExtent],
9302 specifier[MaxTextExtent];
9303
9304 const char
cristy104cea82009-10-25 02:26:51 +00009305 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009306 *value;
9307
9308 XrmDatabase
9309 preferences_database;
9310
9311 /*
9312 Save user preferences to the client configuration file.
9313 */
9314 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009315 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009316 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009317 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009318 value=resource_info->backdrop ? "True" : "False";
9319 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009320 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009321 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9322 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009323 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009324 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009325 value=resource_info->confirm_exit ? "True" : "False";
9326 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009327 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009328 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009329 value=resource_info->confirm_edit ? "True" : "False";
9330 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009331 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009332 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009333 value=resource_info->display_warnings ? "True" : "False";
9334 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009335 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009336 value=resource_info->quantize_info->dither ? "True" : "False";
9337 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009338 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009339 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009340 value=resource_info->gamma_correct ? "True" : "False";
9341 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009342 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9343 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009344 resource_info->undo_cache);
9345 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009346 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009347 value=resource_info->use_pixmap ? "True" : "False";
9348 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009349 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009350 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009351 ExpandFilename(filename);
9352 XrmPutFileDatabase(preferences_database,filename);
9353#endif
9354}
9355
9356/*
9357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9358% %
9359% %
9360% %
9361% X V i s u a l C l a s s N a m e %
9362% %
9363% %
9364% %
9365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9366%
9367% XVisualClassName() returns the visual class name as a character string.
9368%
9369% The format of the XVisualClassName method is:
9370%
9371% char *XVisualClassName(const int visual_class)
9372%
9373% A description of each parameter follows:
9374%
9375% o visual_type: XVisualClassName returns the visual class as a character
9376% string.
9377%
9378% o class: Specifies the visual class.
9379%
cristy3ed852e2009-09-05 21:47:34 +00009380*/
9381static const char *XVisualClassName(const int visual_class)
9382{
9383 switch (visual_class)
9384 {
9385 case StaticGray: return("StaticGray");
9386 case GrayScale: return("GrayScale");
9387 case StaticColor: return("StaticColor");
9388 case PseudoColor: return("PseudoColor");
9389 case TrueColor: return("TrueColor");
9390 case DirectColor: return("DirectColor");
9391 }
9392 return("unknown visual class");
9393}
9394
9395/*
9396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9397% %
9398% %
9399% %
9400% X W a r n i n g %
9401% %
9402% %
9403% %
9404%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9405%
9406% XWarning() displays a warning reason in a Notice widget.
9407%
9408% The format of the XWarning method is:
9409%
9410% void XWarning(const unsigned int warning,const char *reason,
9411% const char *description)
9412%
9413% A description of each parameter follows:
9414%
9415% o warning: Specifies the numeric warning category.
9416%
9417% o reason: Specifies the reason to display before terminating the
9418% program.
9419%
9420% o description: Specifies any description to the reason.
9421%
9422*/
9423MagickExport void XWarning(const ExceptionType magick_unused(warning),
9424 const char *reason,const char *description)
9425{
9426 char
9427 text[MaxTextExtent];
9428
9429 XWindows
9430 *windows;
9431
9432 if (reason == (char *) NULL)
9433 return;
9434 (void) CopyMagickString(text,reason,MaxTextExtent);
9435 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9436 windows=XSetWindows((XWindows *) ~0);
9437 XNoticeWidget(windows->display,windows,text,(char *) description);
9438}
9439
9440/*
9441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9442% %
9443% %
9444% %
9445% X W i n d o w B y I D %
9446% %
9447% %
9448% %
9449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9450%
9451% XWindowByID() locates a child window with a given ID. If not window with
9452% the given name is found, 0 is returned. Only the window specified and its
9453% subwindows are searched.
9454%
9455% The format of the XWindowByID function is:
9456%
9457% child=XWindowByID(display,window,id)
9458%
9459% A description of each parameter follows:
9460%
9461% o child: XWindowByID returns the window with the specified
9462% id. If no windows are found, XWindowByID returns 0.
9463%
9464% o display: Specifies a pointer to the Display structure; returned from
9465% XOpenDisplay.
9466%
9467% o id: Specifies the id of the window to locate.
9468%
9469*/
9470MagickExport Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009471 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009472{
9473 RectangleInfo
9474 rectangle_info;
9475
9476 register int
9477 i;
9478
9479 Status
9480 status;
9481
9482 unsigned int
9483 number_children;
9484
9485 Window
9486 child,
9487 *children,
9488 window;
9489
9490 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9491 assert(display != (Display *) NULL);
9492 assert(root_window != (Window) NULL);
9493 if (id == 0)
9494 return(XSelectWindow(display,&rectangle_info));
9495 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009496 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009497 status=XQueryTree(display,root_window,&child,&child,&children,
9498 &number_children);
9499 if (status == False)
9500 return((Window) NULL);
9501 window=(Window) NULL;
9502 for (i=0; i < (int) number_children; i++)
9503 {
9504 /*
9505 Search each child and their children.
9506 */
9507 window=XWindowByID(display,children[i],id);
9508 if (window != (Window) NULL)
9509 break;
9510 }
9511 if (children != (Window *) NULL)
9512 (void) XFree((void *) children);
9513 return(window);
9514}
9515
9516/*
9517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9518% %
9519% %
9520% %
9521% X W i n d o w B y N a m e %
9522% %
9523% %
9524% %
9525%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9526%
9527% XWindowByName() locates a window with a given name on a display. If no
9528% window with the given name is found, 0 is returned. If more than one window
9529% has the given name, the first one is returned. Only root and its children
9530% are searched.
9531%
9532% The format of the XWindowByName function is:
9533%
9534% window=XWindowByName(display,root_window,name)
9535%
9536% A description of each parameter follows:
9537%
9538% o window: XWindowByName returns the window id.
9539%
9540% o display: Specifies a pointer to the Display structure; returned from
9541% XOpenDisplay.
9542%
9543% o root_window: Specifies the id of the root window.
9544%
9545% o name: Specifies the name of the window to locate.
9546%
9547*/
9548MagickExport Window XWindowByName(Display *display,const Window root_window,
9549 const char *name)
9550{
9551 register int
9552 i;
9553
9554 Status
9555 status;
9556
9557 unsigned int
9558 number_children;
9559
9560 Window
9561 *children,
9562 child,
9563 window;
9564
9565 XTextProperty
9566 window_name;
9567
9568 assert(display != (Display *) NULL);
9569 assert(root_window != (Window) NULL);
9570 assert(name != (char *) NULL);
9571 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9572 if (XGetWMName(display,root_window,&window_name) != 0)
9573 if (LocaleCompare((char *) window_name.value,name) == 0)
9574 return(root_window);
9575 status=XQueryTree(display,root_window,&child,&child,&children,
9576 &number_children);
9577 if (status == False)
9578 return((Window) NULL);
9579 window=(Window) NULL;
9580 for (i=0; i < (int) number_children; i++)
9581 {
9582 /*
9583 Search each child and their children.
9584 */
9585 window=XWindowByName(display,children[i],name);
9586 if (window != (Window) NULL)
9587 break;
9588 }
9589 if (children != (Window *) NULL)
9590 (void) XFree((void *) children);
9591 return(window);
9592}
9593
9594/*
9595%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9596% %
9597% %
9598% %
9599% X W i n d o w B y P r o p e r y %
9600% %
9601% %
9602% %
9603%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9604%
9605% XWindowByProperty() locates a child window with a given property. If not
9606% window with the given name is found, 0 is returned. If more than one window
9607% has the given property, the first one is returned. Only the window
9608% specified and its subwindows are searched.
9609%
9610% The format of the XWindowByProperty function is:
9611%
9612% child=XWindowByProperty(display,window,property)
9613%
9614% A description of each parameter follows:
9615%
9616% o child: XWindowByProperty returns the window id with the specified
9617% property. If no windows are found, XWindowByProperty returns 0.
9618%
9619% o display: Specifies a pointer to the Display structure; returned from
9620% XOpenDisplay.
9621%
9622% o property: Specifies the property of the window to locate.
9623%
9624*/
9625MagickExport Window XWindowByProperty(Display *display,const Window window,
9626 const Atom property)
9627{
9628 Atom
9629 type;
9630
9631 int
9632 format;
9633
9634 Status
9635 status;
9636
9637 unsigned char
9638 *data;
9639
9640 unsigned int
9641 i,
9642 number_children;
9643
cristyf2faecf2010-05-28 19:19:36 +00009644 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009645 after,
9646 number_items;
9647
9648 Window
9649 child,
9650 *children,
9651 parent,
9652 root;
9653
9654 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9655 assert(display != (Display *) NULL);
9656 assert(window != (Window) NULL);
9657 assert(property != (Atom) NULL);
9658 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9659 if (status == False)
9660 return((Window) NULL);
9661 type=(Atom) NULL;
9662 child=(Window) NULL;
9663 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9664 {
9665 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9666 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9667 if (data != NULL)
9668 (void) XFree((void *) data);
9669 if ((status == Success) && (type != (Atom) NULL))
9670 child=children[i];
9671 }
9672 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9673 child=XWindowByProperty(display,children[i],property);
9674 if (children != (Window *) NULL)
9675 (void) XFree((void *) children);
9676 return(child);
9677}
9678#else
9679
9680/*
9681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9682% %
9683% %
9684% %
9685% X I m p o r t I m a g e %
9686% %
9687% %
9688% %
9689%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9690%
9691% XImportImage() reads an image from an X window.
9692%
9693% The format of the XImportImage method is:
9694%
9695% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9696%
9697% A description of each parameter follows:
9698%
9699% o image_info: the image info..
9700%
9701% o ximage_info: Specifies a pointer to an XImportInfo structure.
9702%
9703*/
9704MagickExport Image *XImportImage(const ImageInfo *image_info,
9705 XImportInfo *ximage_info)
9706{
9707 assert(image_info != (const ImageInfo *) NULL);
9708 assert(image_info->signature == MagickSignature);
9709 if (image_info->debug != MagickFalse)
9710 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9711 image_info->filename);
9712 assert(ximage_info != (XImportInfo *) NULL);
9713 return((Image *) NULL);
9714}
9715#endif
9716
9717/*
9718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9719% %
9720% %
9721% %
cristy576974e2009-10-25 20:45:31 +00009722+ X C o m p o n e n t G e n e s i s %
9723% %
9724% %
9725% %
9726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9727%
9728% XComponentGenesis() instantiates the X component.
9729%
9730% The format of the XComponentGenesis method is:
9731%
9732% MagickBooleanType XComponentGenesis(void)
9733%
9734*/
9735MagickExport MagickBooleanType XComponentGenesis(void)
9736{
9737 return(MagickTrue);
9738}
9739
9740/*
9741%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9742% %
9743% %
9744% %
cristy3ed852e2009-09-05 21:47:34 +00009745% X G e t I m p o r t I n f o %
9746% %
9747% %
9748% %
9749%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9750%
9751% XGetImportInfo() initializes the XImportInfo structure.
9752%
9753% The format of the XGetImportInfo method is:
9754%
9755% void XGetImportInfo(XImportInfo *ximage_info)
9756%
9757% A description of each parameter follows:
9758%
9759% o ximage_info: Specifies a pointer to an ImageInfo structure.
9760%
9761*/
9762MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9763{
9764 assert(ximage_info != (XImportInfo *) NULL);
9765 ximage_info->frame=MagickFalse;
9766 ximage_info->borders=MagickFalse;
9767 ximage_info->screen=MagickFalse;
9768 ximage_info->descend=MagickTrue;
9769 ximage_info->silent=MagickFalse;
9770}