blob: 9e5f7a8dced7dc6a08a27d5e04e9e6e631432380 [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*/
42#include "magick/studio.h"
43#include "magick/animate.h"
44#include "magick/artifact.h"
45#include "magick/blob.h"
46#include "magick/cache.h"
47#include "magick/client.h"
48#include "magick/color.h"
49#include "magick/color-private.h"
cristyb67b4fa2010-04-25 20:03:59 +000050#include "magick/colormap.h"
cristy3ed852e2009-09-05 21:47:34 +000051#include "magick/composite.h"
52#include "magick/display.h"
53#include "magick/exception.h"
54#include "magick/exception-private.h"
55#include "magick/geometry.h"
56#include "magick/identify.h"
57#include "magick/image.h"
58#include "magick/image-private.h"
59#include "magick/list.h"
60#include "magick/locale_.h"
61#include "magick/log.h"
62#include "magick/magick.h"
63#include "magick/memory_.h"
64#include "magick/monitor.h"
65#include "magick/option.h"
66#include "magick/PreRvIcccm.h"
67#include "magick/quantize.h"
68#include "magick/quantum.h"
69#include "magick/quantum-private.h"
70#include "magick/resource_.h"
71#include "magick/resize.h"
72#include "magick/shear.h"
73#include "magick/statistic.h"
74#include "magick/string_.h"
cristyf2f27272009-12-17 14:48:46 +000075#include "magick/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000076#include "magick/transform.h"
77#include "magick/utility.h"
78#include "magick/widget.h"
79#include "magick/xwindow.h"
80#include "magick/xwindow-private.h"
81#include "magick/version.h"
82#if defined(__BEOS__)
83#include <OS.h>
84#endif
85#if defined(MAGICKCORE_X11_DELEGATE)
86#include <X11/Xproto.h>
87#include <X11/Xlocale.h>
88#if defined(MAGICK_HAVE_POLL)
89# include <sys/poll.h>
90#endif
91#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
92#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
93# include <machine/param.h>
94#endif
95#include <sys/ipc.h>
96#include <sys/shm.h>
97#include <X11/extensions/XShm.h>
98#endif
99#if defined(MAGICKCORE_HAVE_SHAPE)
100#include <X11/extensions/shape.h>
101#endif
102
103/*
104 X defines.
105*/
cristyce70c172010-01-07 17:15:30 +0000106#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000107 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
108 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000109#define XGammaPixel(map,color) (size_t) (map->base_pixel+ \
cristy3ed852e2009-09-05 21:47:34 +0000110 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
111 map->red_mult)+ \
112 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
113 map->green_mult)+ \
114 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
115 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000116#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000117 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
118 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000119#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000120 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
121 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000122#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy3ed852e2009-09-05 21:47:34 +0000123 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
124 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
125 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
126
127#define AccentuateModulate ScaleCharToQuantum(80)
128#define HighlightModulate ScaleCharToQuantum(125)
129#define ShadowModulate ScaleCharToQuantum(135)
130#define DepthModulate ScaleCharToQuantum(185)
131#define TroughModulate ScaleCharToQuantum(110)
132
133#define XLIB_ILLEGAL_ACCESS 1
134#undef ForgetGravity
135#undef NorthWestGravity
136#undef NorthGravity
137#undef NorthEastGravity
138#undef WestGravity
139#undef CenterGravity
140#undef EastGravity
141#undef SouthWestGravity
142#undef SouthGravity
143#undef SouthEastGravity
144#undef StaticGravity
145
146#undef index
147#if defined(hpux9)
148#define XFD_SET int
149#else
150#define XFD_SET fd_set
151#endif
152
153/*
154 Enumeration declarations.
155*/
156typedef enum
157{
158#undef DoRed
159 DoRed = 0x0001,
160#undef DoGreen
161 DoGreen = 0x0002,
162#undef DoBlue
163 DoBlue = 0x0004,
164 DoMatte = 0x0008
165} XColorFlags;
166
167/*
168 Typedef declarations.
169*/
170typedef struct _DiversityPacket
171{
172 Quantum
173 red,
174 green,
175 blue;
176
177 unsigned short
178 index;
179
cristybb503372010-05-27 20:51:26 +0000180 size_t
cristy3ed852e2009-09-05 21:47:34 +0000181 count;
182} DiversityPacket;
183
184/*
185 Constant declaractions.
186*/
187static MagickBooleanType
188 xerror_alert = MagickFalse;
189
190/*
191 Method prototypes.
192*/
193static const char
194 *XVisualClassName(const int);
195
196static MagickRealType
197 blue_gamma = 1.0,
198 green_gamma = 1.0,
199 red_gamma = 1.0;
200
201static MagickBooleanType
202 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
203
204static void
205 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
206 XImage *,XImage *),
207 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
208 XImage *,XImage *);
209
210static Window
211 XSelectWindow(Display *,RectangleInfo *);
212
213/*
214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215% %
216% %
217% %
218% D e s t r o y X R e s o u r c e s %
219% %
220% %
221% %
222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223%
224% DestroyXResources() destroys any X resources.
225%
226% The format of the DestroyXResources method is:
227%
228% void DestroyXResources()
229%
230% A description of each parameter follows:
231%
232*/
233MagickExport void DestroyXResources(void)
234{
235 register int
236 i;
237
238 unsigned int
239 number_windows;
240
241 XWindowInfo
242 *magick_windows[MaxXWindows];
243
244 XWindows
245 *windows;
246
247 DestroyXWidget();
248 windows=XSetWindows((XWindows *) ~0);
249 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
250 return;
251 number_windows=0;
252 magick_windows[number_windows++]=(&windows->context);
253 magick_windows[number_windows++]=(&windows->group_leader);
254 magick_windows[number_windows++]=(&windows->backdrop);
255 magick_windows[number_windows++]=(&windows->icon);
256 magick_windows[number_windows++]=(&windows->image);
257 magick_windows[number_windows++]=(&windows->info);
258 magick_windows[number_windows++]=(&windows->magnify);
259 magick_windows[number_windows++]=(&windows->pan);
260 magick_windows[number_windows++]=(&windows->command);
261 magick_windows[number_windows++]=(&windows->widget);
262 magick_windows[number_windows++]=(&windows->popup);
263 magick_windows[number_windows++]=(&windows->context);
264 for (i=0; i < (int) number_windows; i++)
265 {
266 if (magick_windows[i]->mapped != MagickFalse)
267 {
268 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
269 magick_windows[i]->screen);
270 magick_windows[i]->mapped=MagickFalse;
271 }
272 if (magick_windows[i]->name != (char *) NULL)
273 magick_windows[i]->name=(char *)
274 RelinquishMagickMemory(magick_windows[i]->name);
275 if (magick_windows[i]->icon_name != (char *) NULL)
276 magick_windows[i]->icon_name=(char *)
277 RelinquishMagickMemory(magick_windows[i]->icon_name);
278 if (magick_windows[i]->cursor != (Cursor) NULL)
279 {
280 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
281 magick_windows[i]->cursor=(Cursor) NULL;
282 }
283 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
284 {
285 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
286 magick_windows[i]->busy_cursor=(Cursor) NULL;
287 }
288 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
289 {
290 (void) XFreePixmap(windows->display,
291 magick_windows[i]->highlight_stipple);
292 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
293 }
294 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
295 {
296 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
297 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
298 }
299 if (magick_windows[i]->ximage != (XImage *) NULL)
300 {
301 XDestroyImage(magick_windows[i]->ximage);
302 magick_windows[i]->ximage=(XImage *) NULL;
303 }
304 if (magick_windows[i]->pixmap != (Pixmap) NULL)
305 {
306 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
307 magick_windows[i]->pixmap=(Pixmap) NULL;
308 }
309 if (magick_windows[i]->id != (Window) NULL)
310 {
311 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
312 magick_windows[i]->id=(Window) NULL;
313 }
314 if (magick_windows[i]->destroy != MagickFalse)
315 {
316 if (magick_windows[i]->image != (Image *) NULL)
317 {
318 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
319 magick_windows[i]->image=NewImageList();
320 }
321 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
322 {
323 (void) XFreePixmap(windows->display,
324 magick_windows[i]->matte_pixmap);
325 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
326 }
327 }
328 if (magick_windows[i]->segment_info != (void *) NULL)
329 {
330#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
331 XShmSegmentInfo
332 *segment_info;
333
334 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
335 if (segment_info != (XShmSegmentInfo *) NULL)
336 if (segment_info[0].shmid >= 0)
337 {
338 if (segment_info[0].shmaddr != NULL)
339 (void) shmdt(segment_info[0].shmaddr);
340 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
341 segment_info[0].shmaddr=NULL;
342 segment_info[0].shmid=(-1);
343 }
344#endif
345 magick_windows[i]->segment_info=(void *)
346 RelinquishMagickMemory(magick_windows[i]->segment_info);
347 }
348 }
349 windows->icon_resources=(XResourceInfo *)
350 RelinquishMagickMemory(windows->icon_resources);
351 if (windows->icon_pixel != (XPixelInfo *) NULL)
352 {
cristyf2faecf2010-05-28 19:19:36 +0000353 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
354 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000355 RelinquishMagickMemory(windows->icon_pixel->pixels);
356 if (windows->icon_pixel->annotate_context != (GC) NULL)
357 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
358 windows->icon_pixel=(XPixelInfo *)
359 RelinquishMagickMemory(windows->icon_pixel);
360 }
361 if (windows->pixel_info != (XPixelInfo *) NULL)
362 {
cristyf2faecf2010-05-28 19:19:36 +0000363 if (windows->pixel_info->pixels != (unsigned long *) NULL)
364 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000365 RelinquishMagickMemory(windows->pixel_info->pixels);
366 if (windows->pixel_info->annotate_context != (GC) NULL)
367 XFreeGC(windows->display,windows->pixel_info->annotate_context);
368 if (windows->pixel_info->widget_context != (GC) NULL)
369 XFreeGC(windows->display,windows->pixel_info->widget_context);
370 if (windows->pixel_info->highlight_context != (GC) NULL)
371 XFreeGC(windows->display,windows->pixel_info->highlight_context);
372 windows->pixel_info=(XPixelInfo *)
373 RelinquishMagickMemory(windows->pixel_info);
374 }
375 if (windows->font_info != (XFontStruct *) NULL)
376 {
377 XFreeFont(windows->display,windows->font_info);
378 windows->font_info=(XFontStruct *) NULL;
379 }
380 if (windows->class_hints != (XClassHint *) NULL)
381 {
382 if (windows->class_hints->res_name != (char *) NULL)
383 XFree(windows->class_hints->res_name);
384 if (windows->class_hints->res_class != (char *) NULL)
385 XFree(windows->class_hints->res_class);
386 XFree(windows->class_hints);
387 windows->class_hints=(XClassHint *) NULL;
388 }
389 if (windows->manager_hints != (XWMHints *) NULL)
390 {
391 XFree(windows->manager_hints);
392 windows->manager_hints=(XWMHints *) NULL;
393 }
394 if (windows->map_info != (XStandardColormap *) NULL)
395 {
396 XFree(windows->map_info);
397 windows->map_info=(XStandardColormap *) NULL;
398 }
399 if (windows->icon_map != (XStandardColormap *) NULL)
400 {
401 XFree(windows->icon_map);
402 windows->icon_map=(XStandardColormap *) NULL;
403 }
404 if (windows->visual_info != (XVisualInfo *) NULL)
405 {
406 XFree(windows->visual_info);
407 windows->visual_info=(XVisualInfo *) NULL;
408 }
409 if (windows->icon_visual != (XVisualInfo *) NULL)
410 {
411 XFree(windows->icon_visual);
412 windows->icon_visual=(XVisualInfo *) NULL;
413 }
414 (void) XSetWindows((XWindows *) NULL);
415}
416
417/*
418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419% %
420% %
421% %
422% X A n n o t a t e I m a g e %
423% %
424% %
425% %
426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427%
428% XAnnotateImage() annotates the image with text.
429%
430% The format of the XAnnotateImage method is:
431%
432% MagickBooleanType XAnnotateImage(Display *display,
433% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
434%
435% A description of each parameter follows:
436%
437% o display: Specifies a connection to an X server; returned from
438% XOpenDisplay.
439%
440% o pixel: Specifies a pointer to a XPixelInfo structure.
441%
442% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
443%
444% o image: the image.
445%
446*/
447MagickExport MagickBooleanType XAnnotateImage(Display *display,
448 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
449{
cristyc57f6942010-11-12 01:47:39 +0000450 CacheView
451 *annotate_view;
452
cristy3ed852e2009-09-05 21:47:34 +0000453 GC
454 annotate_context;
455
456 ExceptionInfo
457 *exception;
458
459 Image
460 *annotate_image;
461
462 int
463 x,
464 y;
465
466 MagickBooleanType
467 matte;
468
469 Pixmap
470 annotate_pixmap;
471
472 unsigned int
473 depth,
474 height,
475 width;
476
477 Window
478 root_window;
479
480 XGCValues
481 context_values;
482
483 XImage
484 *annotate_ximage;
485
486 /*
487 Initialize annotated image.
488 */
489 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
490 assert(display != (Display *) NULL);
491 assert(pixel != (XPixelInfo *) NULL);
492 assert(annotate_info != (XAnnotateInfo *) NULL);
493 assert(image != (Image *) NULL);
494 /*
495 Initialize annotated pixmap.
496 */
497 root_window=XRootWindow(display,XDefaultScreen(display));
498 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
499 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
500 annotate_info->height,depth);
501 if (annotate_pixmap == (Pixmap) NULL)
502 return(MagickFalse);
503 /*
504 Initialize graphics info.
505 */
506 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000507 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000508 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000509 annotate_context=XCreateGC(display,root_window,(unsigned long)
510 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000511 if (annotate_context == (GC) NULL)
512 return(MagickFalse);
513 /*
514 Draw text to pixmap.
515 */
516 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
517 (int) annotate_info->font_info->ascent,annotate_info->text,
518 (int) strlen(annotate_info->text));
519 (void) XFreeGC(display,annotate_context);
520 /*
521 Initialize annotated X image.
522 */
523 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
524 annotate_info->height,AllPlanes,ZPixmap);
525 if (annotate_ximage == (XImage *) NULL)
526 return(MagickFalse);
527 (void) XFreePixmap(display,annotate_pixmap);
528 /*
529 Initialize annotated image.
530 */
531 annotate_image=AcquireImage((ImageInfo *) NULL);
532 if (annotate_image == (Image *) NULL)
533 return(MagickFalse);
534 annotate_image->columns=annotate_info->width;
535 annotate_image->rows=annotate_info->height;
536 /*
537 Transfer annotated X image to image.
538 */
539 width=(unsigned int) image->columns;
540 height=(unsigned int) image->rows;
541 x=0;
542 y=0;
543 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +0000544 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
545 &annotate_image->background_color,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +0000546 if (annotate_info->stencil == ForegroundStencil)
547 annotate_image->matte=MagickTrue;
548 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +0000549 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000550 for (y=0; y < (int) annotate_image->rows; y++)
551 {
cristyc57f6942010-11-12 01:47:39 +0000552 register int
cristy3ed852e2009-09-05 21:47:34 +0000553 x;
554
555 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000556 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000557
cristyc57f6942010-11-12 01:47:39 +0000558 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
559 annotate_image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +0000560 if (q == (PixelPacket *) NULL)
561 break;
cristyc57f6942010-11-12 01:47:39 +0000562 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000563 {
cristyce70c172010-01-07 17:15:30 +0000564 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +0000565 if (XGetPixel(annotate_ximage,x,y) == 0)
566 {
567 /*
568 Set this pixel to the background color.
569 */
570 q->red=ScaleShortToQuantum(pixel->box_color.red);
571 q->green=ScaleShortToQuantum(pixel->box_color.green);
572 q->blue=ScaleShortToQuantum(pixel->box_color.blue);
573 if ((annotate_info->stencil == ForegroundStencil) ||
574 (annotate_info->stencil == OpaqueStencil))
575 q->opacity=(Quantum) TransparentOpacity;
576 }
577 else
578 {
579 /*
580 Set this pixel to the pen color.
581 */
582 q->red=ScaleShortToQuantum(pixel->pen_color.red);
583 q->green=ScaleShortToQuantum(pixel->pen_color.green);
584 q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
585 if (annotate_info->stencil == BackgroundStencil)
586 q->opacity=(Quantum) TransparentOpacity;
587 }
588 q++;
589 }
cristyc57f6942010-11-12 01:47:39 +0000590 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000591 break;
592 }
cristyc57f6942010-11-12 01:47:39 +0000593 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000594 XDestroyImage(annotate_ximage);
595 /*
596 Determine annotate geometry.
597 */
598 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
599 if ((width != (unsigned int) annotate_image->columns) ||
600 (height != (unsigned int) annotate_image->rows))
601 {
602 char
603 image_geometry[MaxTextExtent];
604
605 /*
606 Scale image.
607 */
608 (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
609 width,height);
610 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
611 }
612 if (annotate_info->degrees != 0.0)
613 {
614 Image
615 *rotate_image;
616
617 int
618 rotations;
619
620 MagickRealType
621 normalized_degrees;
622
623 /*
624 Rotate image.
625 */
626 rotate_image=
627 RotateImage(annotate_image,annotate_info->degrees,&image->exception);
628 if (rotate_image == (Image *) NULL)
629 return(MagickFalse);
630 annotate_image=DestroyImage(annotate_image);
631 annotate_image=rotate_image;
632 /*
633 Annotation is relative to the degree of rotation.
634 */
635 normalized_degrees=annotate_info->degrees;
636 while (normalized_degrees < -45.0)
637 normalized_degrees+=360.0;
638 for (rotations=0; normalized_degrees > 45.0; rotations++)
639 normalized_degrees-=90.0;
640 switch (rotations % 4)
641 {
642 default:
643 case 0:
644 break;
645 case 1:
646 {
647 /*
648 Rotate 90 degrees.
649 */
650 x-=(int) annotate_image->columns/2;
651 y+=(int) annotate_image->columns/2;
652 break;
653 }
654 case 2:
655 {
656 /*
657 Rotate 180 degrees.
658 */
659 x=x-(int) annotate_image->columns;
660 break;
661 }
662 case 3:
663 {
664 /*
665 Rotate 270 degrees.
666 */
667 x=x-(int) annotate_image->columns/2;
668 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
669 break;
670 }
671 }
672 }
673 /*
674 Composite text onto the image.
675 */
676 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
677 matte=image->matte;
678 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristyc57f6942010-11-12 01:47:39 +0000679 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +0000680 image->matte=matte;
681 annotate_image=DestroyImage(annotate_image);
682 return(MagickTrue);
683}
684
685/*
686%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
687% %
688% %
689% %
690% X B e s t F o n t %
691% %
692% %
693% %
694%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
695%
696% XBestFont() returns the "best" font. "Best" is defined as a font specified
697% in the X resource database or a font such that the text width displayed
698% with the font does not exceed the specified maximum width.
699%
700% The format of the XBestFont method is:
701%
702% XFontStruct *XBestFont(Display *display,
703% const XResourceInfo *resource_info,const MagickBooleanType text_font)
704%
705% A description of each parameter follows:
706%
707% o font: XBestFont returns a pointer to a XFontStruct structure.
708%
709% o display: Specifies a connection to an X server; returned from
710% XOpenDisplay.
711%
712% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
713%
714% o text_font: True is font should be mono-spaced (typewriter style).
715%
cristy3ed852e2009-09-05 21:47:34 +0000716*/
717
718static char **FontToList(char *font)
719{
720 char
721 **fontlist;
722
723 register char
724 *p,
725 *q;
726
727 register int
728 i;
729
730 unsigned int
731 fonts;
732
733 if (font == (char *) NULL)
734 return((char **) NULL);
735 /*
736 Convert string to an ASCII list.
737 */
738 fonts=1U;
739 for (p=font; *p != '\0'; p++)
740 if ((*p == ':') || (*p == ';') || (*p == ','))
741 fonts++;
742 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
743 if (fontlist == (char **) NULL)
744 {
745 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
746 font);
747 return((char **) NULL);
748 }
749 p=font;
750 for (i=0; i < (int) fonts; i++)
751 {
752 for (q=p; *q != '\0'; q++)
753 if ((*q == ':') || (*q == ';') || (*q == ','))
754 break;
755 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
756 sizeof(*fontlist[i]));
757 if (fontlist[i] == (char *) NULL)
758 {
759 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
760 font);
761 return((char **) NULL);
762 }
763 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
764 p=q+1;
765 }
766 fontlist[i]=(char *) NULL;
767 return(fontlist);
768}
769
770MagickExport XFontStruct *XBestFont(Display *display,
771 const XResourceInfo *resource_info,const MagickBooleanType text_font)
772{
773 static const char
774 *Fonts[]=
775 {
776 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
777 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
778 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
779 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
780 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
781 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
782 "variable",
783 "fixed",
784 (char *) NULL
785 },
786 *TextFonts[]=
787 {
788 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
789 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
790 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
791 "fixed",
792 (char *) NULL
793 };
794
795 char
796 *font_name;
797
798 register const char
799 **p;
800
801 XFontStruct
802 *font_info;
803
804 font_info=(XFontStruct *) NULL;
805 font_name=resource_info->font;
806 if (text_font != MagickFalse)
807 font_name=resource_info->text_font;
808 if ((font_name != (char *) NULL) && (*font_name != '\0'))
809 {
810 char
811 **fontlist;
812
813 register int
814 i;
815
816 /*
817 Load preferred font specified in the X resource database.
818 */
819 fontlist=FontToList(font_name);
820 if (fontlist != (char **) NULL)
821 {
822 for (i=0; fontlist[i] != (char *) NULL; i++)
823 {
824 if (font_info == (XFontStruct *) NULL)
825 font_info=XLoadQueryFont(display,fontlist[i]);
826 fontlist[i]=DestroyString(fontlist[i]);
827 }
828 fontlist=(char **) RelinquishMagickMemory(fontlist);
829 }
830 if (font_info == (XFontStruct *) NULL)
831 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
832 }
833 /*
834 Load fonts from list of fonts until one is found.
835 */
836 p=Fonts;
837 if (text_font != MagickFalse)
838 p=TextFonts;
839 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
840 p++;
841 while (*p != (char *) NULL)
842 {
843 if (font_info != (XFontStruct *) NULL)
844 break;
845 font_info=XLoadQueryFont(display,(char *) *p);
846 p++;
847 }
848 return(font_info);
849}
850
851/*
852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853% %
854% %
855% %
856% X B e s t I c o n S i z e %
857% %
858% %
859% %
860%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861%
862% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
863% size that maintains the aspect ratio of the image. If the window manager
864% has preferred icon sizes, one of the preferred sizes is used.
865%
866% The format of the XBestIconSize method is:
867%
868% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
869%
870% A description of each parameter follows:
871%
872% o display: Specifies a connection to an X server; returned from
873% XOpenDisplay.
874%
875% o image: the image.
876%
877*/
878MagickExport void XBestIconSize(Display *display,XWindowInfo *window,
879 Image *image)
880{
881 int
882 i,
883 number_sizes;
884
885 MagickRealType
886 scale_factor;
887
888 unsigned int
889 height,
890 icon_height,
891 icon_width,
892 width;
893
894 Window
895 root_window;
896
897 XIconSize
898 *icon_size,
899 *size_list;
900
901 /*
902 Determine if the window manager has specified preferred icon sizes.
903 */
904 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
905 assert(display != (Display *) NULL);
906 assert(window != (XWindowInfo *) NULL);
907 assert(image != (Image *) NULL);
908 window->width=MaxIconSize;
909 window->height=MaxIconSize;
910 icon_size=(XIconSize *) NULL;
911 number_sizes=0;
912 root_window=XRootWindow(display,window->screen);
913 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
914 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
915 icon_size=size_list;
916 if (icon_size == (XIconSize *) NULL)
917 {
918 /*
919 Window manager does not restrict icon size.
920 */
921 icon_size=XAllocIconSize();
922 if (icon_size == (XIconSize *) NULL)
923 {
924 ThrowXWindowFatalException(ResourceLimitError,
925 "MemoryAllocationFailed",image->filename);
926 return;
927 }
928 icon_size->min_width=1;
929 icon_size->max_width=MaxIconSize;
930 icon_size->min_height=1;
931 icon_size->max_height=MaxIconSize;
932 icon_size->width_inc=1;
933 icon_size->height_inc=1;
934 }
935 /*
936 Determine aspect ratio of image.
937 */
938 width=(unsigned int) image->columns;
939 height=(unsigned int) image->rows;
940 i=0;
941 if (window->crop_geometry)
942 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
943 /*
944 Look for an icon size that maintains the aspect ratio of image.
945 */
946 scale_factor=(MagickRealType) icon_size->max_width/width;
947 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
948 scale_factor=(MagickRealType) icon_size->max_height/height;
949 icon_width=(unsigned int) icon_size->min_width;
950 while ((int) icon_width < icon_size->max_width)
951 {
952 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
953 break;
954 icon_width+=icon_size->width_inc;
955 }
956 icon_height=(unsigned int) icon_size->min_height;
957 while ((int) icon_height < icon_size->max_height)
958 {
959 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
960 break;
961 icon_height+=icon_size->height_inc;
962 }
963 (void) XFree((void *) icon_size);
964 window->width=icon_width;
965 window->height=icon_height;
966}
967
968/*
969%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
970% %
971% %
972% %
973% X B e s t P i x e l %
974% %
975% %
976% %
977%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978%
979% XBestPixel() returns a pixel from an array of pixels that is closest to the
980% requested color. If the color array is NULL, the colors are obtained from
981% the X server.
982%
983% The format of the XBestPixel method is:
984%
985% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
986% unsigned int number_colors,XColor *color)
987%
988% A description of each parameter follows:
989%
990% o pixel: XBestPixel returns the pixel value closest to the requested
991% color.
992%
993% o display: Specifies a connection to an X server; returned from
994% XOpenDisplay.
995%
996% o colormap: Specifies the ID of the X server colormap.
997%
998% o colors: Specifies an array of XColor structures.
999%
1000% o number_colors: Specifies the number of XColor structures in the
1001% color definition array.
1002%
1003% o color: Specifies the desired RGB value to find in the colors array.
1004%
1005*/
1006MagickExport void XBestPixel(Display *display,const Colormap colormap,
1007 XColor *colors,unsigned int number_colors,XColor *color)
1008{
1009 MagickBooleanType
1010 query_server;
1011
1012 MagickPixelPacket
1013 pixel;
1014
1015 MagickRealType
1016 min_distance;
1017
1018 register MagickRealType
1019 distance;
1020
1021 register int
1022 i,
1023 j;
1024
1025 Status
1026 status;
1027
1028 /*
1029 Find closest representation for the requested RGB color.
1030 */
1031 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1032 assert(display != (Display *) NULL);
1033 assert(color != (XColor *) NULL);
1034 status=XAllocColor(display,colormap,color);
1035 if (status != False)
1036 return;
1037 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1038 if (query_server != MagickFalse)
1039 {
1040 /*
1041 Read X server colormap.
1042 */
1043 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1044 if (colors == (XColor *) NULL)
1045 {
1046 ThrowXWindowFatalException(ResourceLimitError,
1047 "MemoryAllocationFailed","...");
1048 return;
1049 }
1050 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001051 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001052 if (number_colors > 256)
1053 number_colors=256;
1054 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1055 }
1056 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1057 QuantumRange+1.0);
1058 j=0;
1059 for (i=0; i < (int) number_colors; i++)
1060 {
1061 pixel.red=colors[i].red-(MagickRealType) color->red;
1062 distance=pixel.red*pixel.red;
1063 if (distance > min_distance)
1064 continue;
1065 pixel.green=colors[i].green-(MagickRealType) color->green;
1066 distance+=pixel.green*pixel.green;
1067 if (distance > min_distance)
1068 continue;
1069 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1070 distance+=pixel.blue*pixel.blue;
1071 if (distance > min_distance)
1072 continue;
1073 min_distance=distance;
1074 color->pixel=colors[i].pixel;
1075 j=i;
1076 }
1077 (void) XAllocColor(display,colormap,&colors[j]);
1078 if (query_server != MagickFalse)
1079 colors=(XColor *) RelinquishMagickMemory(colors);
1080}
1081
1082/*
1083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1084% %
1085% %
1086% %
1087% X B e s t V i s u a l I n f o %
1088% %
1089% %
1090% %
1091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1092%
1093% XBestVisualInfo() returns visual information for a visual that is the "best"
1094% the server supports. "Best" is defined as:
1095%
1096% 1. Restrict the visual list to those supported by the default screen.
1097%
1098% 2. If a visual type is specified, restrict the visual list to those of
1099% that type.
1100%
1101% 3. If a map type is specified, choose the visual that matches the id
1102% specified by the Standard Colormap.
1103%
1104% 4 From the list of visuals, choose one that can display the most
1105% simultaneous colors. If more than one visual can display the same
1106% number of simultaneous colors, one is chosen based on a rank.
1107%
1108% The format of the XBestVisualInfo method is:
1109%
1110% XVisualInfo *XBestVisualInfo(Display *display,
1111% XStandardColormap *map_info,XResourceInfo *resource_info)
1112%
1113% A description of each parameter follows:
1114%
1115% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1116% structure.
1117%
1118% o display: Specifies a connection to an X server; returned from
1119% XOpenDisplay.
1120%
1121% o map_info: If map_type is specified, this structure is initialized
1122% with info from the Standard Colormap.
1123%
1124% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1125%
1126*/
1127
1128static inline int MagickMax(const int x,const int y)
1129{
1130 if (x > y)
1131 return(x);
1132 return(y);
1133}
1134
cristybb503372010-05-27 20:51:26 +00001135static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001136 const unsigned int y)
1137{
1138 if (x < y)
1139 return(x);
1140 return(y);
1141}
1142
1143MagickExport XVisualInfo *XBestVisualInfo(Display *display,
1144 XStandardColormap *map_info,XResourceInfo *resource_info)
1145{
1146#define MaxStandardColormaps 7
1147#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1148 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1149 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1150 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1151
1152 char
1153 *map_type,
1154 *visual_type;
1155
cristyc57f6942010-11-12 01:47:39 +00001156 int
1157 visual_mask;
1158
cristy3ed852e2009-09-05 21:47:34 +00001159 register int
1160 i;
1161
cristy8891f9c2010-06-04 23:32:17 +00001162 size_t
1163 one;
1164
cristy3ed852e2009-09-05 21:47:34 +00001165 static int
1166 number_visuals;
1167
1168 static XVisualInfo
1169 visual_template;
1170
1171 XVisualInfo
1172 *visual_info,
1173 *visual_list;
1174
1175 /*
1176 Restrict visual search by screen number.
1177 */
1178 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1179 assert(display != (Display *) NULL);
1180 assert(map_info != (XStandardColormap *) NULL);
1181 assert(resource_info != (XResourceInfo *) NULL);
1182 map_type=resource_info->map_type;
1183 visual_type=resource_info->visual_type;
1184 visual_mask=VisualScreenMask;
1185 visual_template.screen=XDefaultScreen(display);
1186 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001187 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001188 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001189 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001190 visual_mask|=VisualDepthMask;
1191 if (visual_type != (char *) NULL)
1192 {
1193 /*
1194 Restrict visual search by class or visual id.
1195 */
1196 if (LocaleCompare("staticgray",visual_type) == 0)
1197 {
1198 visual_mask|=VisualClassMask;
1199 visual_template.klass=StaticGray;
1200 }
1201 else
1202 if (LocaleCompare("grayscale",visual_type) == 0)
1203 {
1204 visual_mask|=VisualClassMask;
1205 visual_template.klass=GrayScale;
1206 }
1207 else
1208 if (LocaleCompare("staticcolor",visual_type) == 0)
1209 {
1210 visual_mask|=VisualClassMask;
1211 visual_template.klass=StaticColor;
1212 }
1213 else
1214 if (LocaleCompare("pseudocolor",visual_type) == 0)
1215 {
1216 visual_mask|=VisualClassMask;
1217 visual_template.klass=PseudoColor;
1218 }
1219 else
1220 if (LocaleCompare("truecolor",visual_type) == 0)
1221 {
1222 visual_mask|=VisualClassMask;
1223 visual_template.klass=TrueColor;
1224 }
1225 else
1226 if (LocaleCompare("directcolor",visual_type) == 0)
1227 {
1228 visual_mask|=VisualClassMask;
1229 visual_template.klass=DirectColor;
1230 }
1231 else
1232 if (LocaleCompare("default",visual_type) == 0)
1233 {
1234 visual_mask|=VisualIDMask;
1235 visual_template.visualid=XVisualIDFromVisual(
1236 XDefaultVisual(display,XDefaultScreen(display)));
1237 }
1238 else
1239 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1240 {
1241 visual_mask|=VisualIDMask;
1242 visual_template.visualid=
1243 strtol(visual_type,(char **) NULL,0);
1244 }
1245 else
1246 ThrowXWindowFatalException(XServerError,
1247 "UnrecognizedVisualSpecifier",visual_type);
1248 }
1249 /*
1250 Get all visuals that meet our criteria so far.
1251 */
1252 number_visuals=0;
1253 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1254 &number_visuals);
1255 visual_mask=VisualScreenMask | VisualIDMask;
1256 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1257 {
1258 /*
1259 Failed to get visual; try using the default visual.
1260 */
1261 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1262 visual_type);
1263 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1264 XDefaultScreen(display)));
1265 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1266 &number_visuals);
1267 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1268 return((XVisualInfo *) NULL);
1269 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1270 XVisualClassName(visual_list->klass));
1271 }
1272 resource_info->color_recovery=MagickFalse;
1273 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1274 {
1275 Atom
1276 map_property;
1277
1278 char
1279 map_name[MaxTextExtent];
1280
1281 int
1282 j,
1283 number_maps;
1284
1285 Status
1286 status;
1287
1288 Window
1289 root_window;
1290
1291 XStandardColormap
1292 *map_list;
1293
1294 /*
1295 Choose a visual associated with a standard colormap.
1296 */
1297 root_window=XRootWindow(display,XDefaultScreen(display));
1298 status=False;
1299 if (LocaleCompare(map_type,"list") != 0)
1300 {
1301 /*
1302 User specified Standard Colormap.
1303 */
1304 (void) FormatMagickString((char *) map_name,MaxTextExtent,
1305 "RGB_%s_MAP",map_type);
1306 LocaleUpper(map_name);
1307 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1308 if (map_property != (Atom) NULL)
1309 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1310 map_property);
1311 }
1312 else
1313 {
1314 static const char
1315 *colormap[MaxStandardColormaps]=
1316 {
1317 "_HP_RGB_SMOOTH_MAP_LIST",
1318 "RGB_BEST_MAP",
1319 "RGB_DEFAULT_MAP",
1320 "RGB_GRAY_MAP",
1321 "RGB_RED_MAP",
1322 "RGB_GREEN_MAP",
1323 "RGB_BLUE_MAP",
1324 };
1325
1326 /*
1327 Choose a standard colormap from a list.
1328 */
1329 for (i=0; i < MaxStandardColormaps; i++)
1330 {
1331 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1332 if (map_property == (Atom) NULL)
1333 continue;
1334 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1335 map_property);
1336 if (status != False)
1337 break;
1338 }
1339 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1340 }
1341 if (status == False)
1342 {
1343 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1344 map_type);
1345 return((XVisualInfo *) NULL);
1346 }
1347 /*
1348 Search all Standard Colormaps and visuals for ids that match.
1349 */
1350 *map_info=map_list[0];
1351#if !defined(PRE_R4_ICCCM)
1352 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1353 for (i=0; i < number_maps; i++)
1354 for (j=0; j < number_visuals; j++)
1355 if (map_list[i].visualid ==
1356 XVisualIDFromVisual(visual_list[j].visual))
1357 {
1358 *map_info=map_list[i];
1359 visual_template.visualid=XVisualIDFromVisual(
1360 visual_list[j].visual);
1361 break;
1362 }
1363 if (map_info->visualid != visual_template.visualid)
1364 {
1365 ThrowXWindowFatalException(XServerError,
1366 "UnableToMatchVisualToStandardColormap",map_type);
1367 return((XVisualInfo *) NULL);
1368 }
1369#endif
1370 if (map_info->colormap == (Colormap) NULL)
1371 {
1372 ThrowXWindowFatalException(XServerError,
1373 "StandardColormapIsNotInitialized",map_type);
1374 return((XVisualInfo *) NULL);
1375 }
1376 (void) XFree((void *) map_list);
1377 }
1378 else
1379 {
1380 static const unsigned int
1381 rank[]=
1382 {
1383 StaticGray,
1384 GrayScale,
1385 StaticColor,
1386 DirectColor,
1387 TrueColor,
1388 PseudoColor
1389 };
1390
1391 XVisualInfo
1392 *p;
1393
1394 /*
1395 Pick one visual that displays the most simultaneous colors.
1396 */
1397 visual_info=visual_list;
1398 p=visual_list;
1399 for (i=1; i < number_visuals; i++)
1400 {
1401 p++;
1402 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1403 visual_info=p;
1404 else
1405 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1406 if (rank[p->klass] > rank[visual_info->klass])
1407 visual_info=p;
1408 }
1409 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1410 }
1411 (void) XFree((void *) visual_list);
1412 /*
1413 Retrieve only one visual by its screen & id number.
1414 */
1415 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1416 &number_visuals);
1417 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1418 return((XVisualInfo *) NULL);
1419 return(visual_info);
1420}
1421
1422/*
1423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1424% %
1425% %
1426% %
1427% X C h e c k D e f i n e C u r s o r %
1428% %
1429% %
1430% %
1431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1432%
1433% XCheckDefineCursor() prevents cursor changes on the root window.
1434%
1435% The format of the XXCheckDefineCursor method is:
1436%
1437% XCheckDefineCursor(display,window,cursor)
1438%
1439% A description of each parameter follows:
1440%
1441% o display: Specifies a connection to an X server; returned from
1442% XOpenDisplay.
1443%
1444% o window: the window.
1445%
1446% o cursor: the cursor.
1447%
1448*/
1449MagickExport int XCheckDefineCursor(Display *display,Window window,
1450 Cursor cursor)
1451{
1452 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1453 assert(display != (Display *) NULL);
1454 if (window == XRootWindow(display,XDefaultScreen(display)))
1455 return(0);
1456 return(XDefineCursor(display,window,cursor));
1457}
1458
1459/*
1460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1461% %
1462% %
1463% %
1464% X C h e c k R e f r e s h W i n d o w s %
1465% %
1466% %
1467% %
1468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1469%
1470% XCheckRefreshWindows() checks the X server for exposure events for a
1471% particular window and updates the areassociated with the exposure event.
1472%
1473% The format of the XCheckRefreshWindows method is:
1474%
1475% void XCheckRefreshWindows(Display *display,XWindows *windows)
1476%
1477% A description of each parameter follows:
1478%
1479% o display: Specifies a connection to an X server; returned from
1480% XOpenDisplay.
1481%
1482% o windows: Specifies a pointer to a XWindows structure.
1483%
1484*/
1485MagickExport void XCheckRefreshWindows(Display *display,XWindows *windows)
1486{
1487 Window
1488 id;
1489
1490 XEvent
1491 event;
1492
1493 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1494 assert(display != (Display *) NULL);
1495 assert(windows != (XWindows *) NULL);
1496 XDelay(display,SuspendTime);
1497 id=windows->command.id;
1498 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1499 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1500 id=windows->image.id;
1501 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1502 XRefreshWindow(display,&windows->image,&event);
1503 XDelay(display,SuspendTime << 1);
1504 id=windows->command.id;
1505 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1506 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1507 id=windows->image.id;
1508 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1509 XRefreshWindow(display,&windows->image,&event);
1510}
1511
1512/*
1513%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1514% %
1515% %
1516% %
1517% X C l i e n t M e s s a g e %
1518% %
1519% %
1520% %
1521%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1522%
1523% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1524% initialized with a particular protocol type and atom.
1525%
1526% The format of the XClientMessage function is:
1527%
1528% XClientMessage(display,window,protocol,reason,timestamp)
1529%
1530% A description of each parameter follows:
1531%
1532% o display: Specifies a pointer to the Display structure; returned from
1533% XOpenDisplay.
1534%
1535% o window: Specifies a pointer to a Window structure.
1536%
1537% o protocol: Specifies an atom value.
1538%
1539% o reason: Specifies an atom value which is the reason to send.
1540%
1541% o timestamp: Specifies a value of type Time.
1542%
1543*/
1544MagickExport void XClientMessage(Display *display,const Window window,
1545 const Atom protocol,const Atom reason,const Time timestamp)
1546{
1547 XClientMessageEvent
1548 client_event;
1549
1550 assert(display != (Display *) NULL);
1551 client_event.type=ClientMessage;
1552 client_event.window=window;
1553 client_event.message_type=protocol;
1554 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001555 client_event.data.l[0]=(long) reason;
1556 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001557 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1558}
1559
1560/*
1561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1562% %
1563% %
1564% %
1565+ X C l i e n t W i n d o w %
1566% %
1567% %
1568% %
1569%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1570%
1571% XClientWindow() finds a window, at or below the specified window, which has
1572% a WM_STATE property. If such a window is found, it is returned, otherwise
1573% the argument window is returned.
1574%
1575% The format of the XClientWindow function is:
1576%
1577% client_window=XClientWindow(display,target_window)
1578%
1579% A description of each parameter follows:
1580%
1581% o client_window: XClientWindow returns a window, at or below the specified
1582% window, which has a WM_STATE property otherwise the argument
1583% target_window is returned.
1584%
1585% o display: Specifies a pointer to the Display structure; returned from
1586% XOpenDisplay.
1587%
1588% o target_window: Specifies the window to find a WM_STATE property.
1589%
cristy3ed852e2009-09-05 21:47:34 +00001590*/
1591static Window XClientWindow(Display *display,Window target_window)
1592{
1593 Atom
1594 state,
1595 type;
1596
1597 int
1598 format;
1599
1600 Status
1601 status;
1602
1603 unsigned char
1604 *data;
1605
cristyf2faecf2010-05-28 19:19:36 +00001606 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001607 after,
1608 number_items;
1609
1610 Window
1611 client_window;
1612
1613 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1614 assert(display != (Display *) NULL);
1615 state=XInternAtom(display,"WM_STATE",MagickTrue);
1616 if (state == (Atom) NULL)
1617 return(target_window);
1618 type=(Atom) NULL;
1619 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1620 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1621 if ((status == Success) && (type != (Atom) NULL))
1622 return(target_window);
1623 client_window=XWindowByProperty(display,target_window,state);
1624 if (client_window == (Window) NULL)
1625 return(target_window);
1626 return(client_window);
1627}
1628
1629/*
1630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1631% %
1632% %
1633% %
cristyf34a1452009-10-24 22:29:27 +00001634+ X C o m p o n e n t T e r m i n u s %
1635% %
1636% %
1637% %
1638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1639%
1640% XComponentTerminus() destroys the module component.
1641%
1642% The format of the XComponentTerminus method is:
1643%
1644% XComponentTerminus(void)
1645%
1646*/
1647MagickExport void XComponentTerminus(void)
1648{
1649 DestroyXResources();
1650}
1651
1652/*
1653%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1654% %
1655% %
1656% %
cristy3ed852e2009-09-05 21:47:34 +00001657% X C o n f i g u r e I m a g e C o l o r m a p %
1658% %
1659% %
1660% %
1661%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1662%
1663% XConfigureImageColormap() creates a new X colormap.
1664%
1665% The format of the XConfigureImageColormap method is:
1666%
1667% void XConfigureImageColormap(Display *display,
1668% XResourceInfo *resource_info,XWindows *windows,Image *image)
1669%
1670% A description of each parameter follows:
1671%
1672% o display: Specifies a connection to an X server; returned from
1673% XOpenDisplay.
1674%
1675% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1676%
1677% o windows: Specifies a pointer to a XWindows structure.
1678%
1679% o image: the image.
1680%
1681*/
1682MagickExport void XConfigureImageColormap(Display *display,
1683 XResourceInfo *resource_info,XWindows *windows,Image *image)
1684{
1685 Colormap
1686 colormap;
1687
1688 /*
1689 Make standard colormap.
1690 */
1691 XSetCursorState(display,windows,MagickTrue);
1692 XCheckRefreshWindows(display,windows);
1693 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1694 windows->map_info,windows->pixel_info);
1695 colormap=windows->map_info->colormap;
1696 (void) XSetWindowColormap(display,windows->image.id,colormap);
1697 (void) XSetWindowColormap(display,windows->command.id,colormap);
1698 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1699 if (windows->magnify.mapped != MagickFalse)
1700 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1701 if (windows->pan.mapped != MagickFalse)
1702 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1703 XSetCursorState(display,windows,MagickFalse);
1704 XClientMessage(display,windows->image.id,windows->im_protocols,
1705 windows->im_update_colormap,CurrentTime);
1706}
1707
1708/*
1709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1710% %
1711% %
1712% %
1713% X C o n s t r a i n W i n d o w P o s i t i o n %
1714% %
1715% %
1716% %
1717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1718%
1719% XConstrainWindowPosition() assures a window is positioned within the X
1720% server boundaries.
1721%
1722% The format of the XConstrainWindowPosition method is:
1723%
1724% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1725%
1726% A description of each parameter follows:
1727%
1728% o display: Specifies a pointer to the Display structure; returned from
1729% XOpenDisplay.
1730%
1731% o window_info: Specifies a pointer to a XWindowInfo structure.
1732%
1733*/
1734MagickExport void XConstrainWindowPosition(Display *display,
1735 XWindowInfo *window_info)
1736{
1737 int
1738 limit;
1739
1740 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1741 assert(display != (Display *) NULL);
1742 assert(window_info != (XWindowInfo *) NULL);
1743 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1744 if (window_info->x < 0)
1745 window_info->x=0;
1746 else
1747 if (window_info->x > (int) limit)
1748 window_info->x=(int) limit;
1749 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1750 if (window_info->y < 0)
1751 window_info->y=0;
1752 else
1753 if (window_info->y > limit)
1754 window_info->y=limit;
1755}
1756
1757/*
1758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1759% %
1760% %
1761% %
1762% X D e l a y %
1763% %
1764% %
1765% %
1766%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1767%
1768% XDelay() suspends program execution for the number of milliseconds
1769% specified.
1770%
1771% The format of the Delay method is:
1772%
cristybb503372010-05-27 20:51:26 +00001773% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001774%
1775% A description of each parameter follows:
1776%
1777% o display: Specifies a pointer to the Display structure; returned from
1778% XOpenDisplay.
1779%
1780% o milliseconds: Specifies the number of milliseconds to delay before
1781% returning.
1782%
1783*/
cristybb503372010-05-27 20:51:26 +00001784MagickExport void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001785{
1786 assert(display != (Display *) NULL);
1787 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001788 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001789}
1790
1791/*
1792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1793% %
1794% %
1795% %
1796% X D e s t r o y R e s o u r c e I n f o %
1797% %
1798% %
1799% %
1800%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1801%
1802% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1803% structure.
1804%
1805% The format of the XDestroyResourceInfo method is:
1806%
1807% void XDestroyResourceInfo(XResourceInfo *resource_info)
1808%
1809% A description of each parameter follows:
1810%
1811% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1812%
1813*/
1814MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1815{
1816 if (resource_info->image_geometry != (char *) NULL)
1817 resource_info->image_geometry=(char *)
1818 RelinquishMagickMemory(resource_info->image_geometry);
1819 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1820 resource_info->quantize_info=DestroyQuantizeInfo(
1821 resource_info->quantize_info);
1822 if (resource_info->client_name != (char *) NULL)
1823 resource_info->client_name=(char *)
1824 RelinquishMagickMemory(resource_info->client_name);
1825 if (resource_info->name != (char *) NULL)
1826 resource_info->name=DestroyString(resource_info->name);
1827 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1828}
1829
1830/*
1831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1832% %
1833% %
1834% %
1835% X D e s t r o y W i n d o w C o l o r s %
1836% %
1837% %
1838% %
1839%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1840%
1841% XDestroyWindowColors() frees X11 color resources previously saved on a
1842% window by XRetainWindowColors or programs like xsetroot.
1843%
1844% The format of the XDestroyWindowColors method is:
1845%
1846% void XDestroyWindowColors(Display *display,Window window)
1847%
1848% A description of each parameter follows:
1849%
1850% o display: Specifies a connection to an X server; returned from
1851% XOpenDisplay.
1852%
1853% o window: Specifies a pointer to a Window structure.
1854%
1855*/
1856MagickExport void XDestroyWindowColors(Display *display,Window window)
1857{
1858 Atom
1859 property,
1860 type;
1861
1862 int
1863 format;
1864
1865 Status
1866 status;
1867
1868 unsigned char
1869 *data;
1870
cristyf2faecf2010-05-28 19:19:36 +00001871 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001872 after,
1873 length;
1874
1875 /*
1876 If there are previous resources on the root window, destroy them.
1877 */
1878 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1879 assert(display != (Display *) NULL);
1880 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1881 if (property == (Atom) NULL)
1882 {
1883 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1884 "_XSETROOT_ID");
1885 return;
1886 }
1887 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1888 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1889 if (status != Success)
1890 return;
1891 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1892 {
1893 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1894 (void) XDeleteProperty(display,window,property);
1895 }
1896 if (type != None)
1897 (void) XFree((void *) data);
1898}
1899
1900/*
1901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1902% %
1903% %
1904% %
1905% X D i s p l a y I m a g e I n f o %
1906% %
1907% %
1908% %
1909%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1910%
1911% XDisplayImageInfo() displays information about an X image.
1912%
1913% The format of the XDisplayImageInfo method is:
1914%
1915% void XDisplayImageInfo(Display *display,
1916% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1917% Image *image)
1918%
1919% A description of each parameter follows:
1920%
1921% o display: Specifies a connection to an X server; returned from
1922% XOpenDisplay.
1923%
1924% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1925%
1926% o windows: Specifies a pointer to a XWindows structure.
1927%
1928% o undo_image: the undo image.
1929%
1930% o image: the image.
1931%
1932*/
1933MagickExport void XDisplayImageInfo(Display *display,
1934 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1935 Image *image)
1936{
1937 char
1938 filename[MaxTextExtent],
1939 *text,
1940 **textlist;
1941
1942 FILE
1943 *file;
1944
1945 int
1946 unique_file;
1947
cristybb503372010-05-27 20:51:26 +00001948 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001949 bytes;
1950
cristybb503372010-05-27 20:51:26 +00001951 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001952 i;
1953
1954 unsigned int
1955 levels;
1956
cristybb503372010-05-27 20:51:26 +00001957 size_t
cristy3ed852e2009-09-05 21:47:34 +00001958 number_pixels;
1959
1960 /*
1961 Write info about the X server to a file.
1962 */
1963 assert(display != (Display *) NULL);
1964 assert(resource_info != (XResourceInfo *) NULL);
1965 assert(windows != (XWindows *) NULL);
1966 assert(image != (Image *) NULL);
1967 if (image->debug)
1968 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1969 file=(FILE *) NULL;
1970 unique_file=AcquireUniqueFileResource(filename);
1971 if (unique_file != -1)
1972 file=fdopen(unique_file,"w");
1973 if ((unique_file == -1) || (file == (FILE *) NULL))
1974 {
1975 XNoticeWidget(display,windows,"Unable to display image info",filename);
1976 return;
1977 }
1978 if (resource_info->gamma_correct != MagickFalse)
1979 if (resource_info->display_gamma != (char *) NULL)
1980 (void) fprintf(file,"Display\n gamma: %s\n\n",
1981 resource_info->display_gamma);
1982 /*
1983 Write info about the X image to a file.
1984 */
1985 (void) fprintf(file,"X\n visual: %s\n",
1986 XVisualClassName((int) windows->image.storage_class));
1987 (void) fprintf(file," depth: %d\n",windows->image.ximage->depth);
1988 if (windows->visual_info->colormap_size != 0)
1989 (void) fprintf(file," colormap size: %d\n",
1990 windows->visual_info->colormap_size);
1991 if (resource_info->colormap== SharedColormap)
1992 (void) fprintf(file," colormap type: Shared\n");
1993 else
1994 (void) fprintf(file," colormap type: Private\n");
1995 (void) fprintf(file," geometry: %dx%d\n",windows->image.ximage->width,
1996 windows->image.ximage->height);
1997 if (windows->image.crop_geometry != (char *) NULL)
1998 (void) fprintf(file," crop geometry: %s\n",windows->image.crop_geometry);
1999 if (windows->image.pixmap == (Pixmap) NULL)
2000 (void) fprintf(file," type: X Image\n");
2001 else
2002 (void) fprintf(file," type: Pixmap\n");
2003 if (windows->image.shape != MagickFalse)
2004 (void) fprintf(file," non-rectangular shape: True\n");
2005 else
2006 (void) fprintf(file," non-rectangular shape: False\n");
2007 if (windows->image.shared_memory != MagickFalse)
2008 (void) fprintf(file," shared memory: True\n");
2009 else
2010 (void) fprintf(file," shared memory: False\n");
2011 (void) fprintf(file,"\n");
2012 if (resource_info->font != (char *) NULL)
2013 (void) fprintf(file,"Font: %s\n\n",resource_info->font);
2014 if (resource_info->text_font != (char *) NULL)
2015 (void) fprintf(file,"Text font: %s\n\n",resource_info->text_font);
2016 /*
2017 Write info about the undo cache to a file.
2018 */
2019 bytes=0;
2020 for (levels=0; undo_image != (Image *) NULL; levels++)
2021 {
2022 number_pixels=undo_image->list->columns*undo_image->list->rows;
2023 bytes+=number_pixels*sizeof(PixelPacket);
2024 undo_image=GetPreviousImageInList(undo_image);
2025 }
2026 (void) fprintf(file,"Undo Edit Cache\n levels: %u\n",levels);
cristye8c25f92010-06-03 00:53:06 +00002027 (void) fprintf(file," bytes: %.20gmb\n",(double) ((bytes+(1 << 19)) >> 20));
2028 (void) fprintf(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002029 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002030 /*
2031 Write info about the image to a file.
2032 */
2033 (void) IdentifyImage(image,file,MagickTrue);
2034 (void) fclose(file);
2035 text=FileToString(filename,~0,&image->exception);
2036 (void) RelinquishUniqueFileResource(filename);
2037 if (text == (char *) NULL)
2038 {
2039 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2040 "UnableToDisplayImageInfo");
2041 return;
2042 }
2043 textlist=StringToList(text);
2044 if (textlist != (char **) NULL)
2045 {
2046 char
2047 title[MaxTextExtent];
2048
2049 /*
2050 Display information about the image in the Text View widget.
2051 */
2052 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2053 (void) FormatMagickString(title,MaxTextExtent,"Image Info: %s",
2054 image->filename);
2055 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2056 (char const **) textlist);
2057 for (i=0; textlist[i] != (char *) NULL; i++)
2058 textlist[i]=DestroyString(textlist[i]);
2059 textlist=(char **) RelinquishMagickMemory(textlist);
2060 }
2061 text=DestroyString(text);
2062}
2063
2064/*
2065%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2066% %
2067% %
2068% %
2069+ X D i t h e r I m a g e %
2070% %
2071% %
2072% %
2073%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2074%
2075% XDitherImage() dithers the reference image as required by the HP Color
2076% Recovery algorithm. The color values are quantized to 3 bits of red and
2077% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2078% standard colormap.
2079%
2080% The format of the XDitherImage method is:
2081%
2082% void XDitherImage(Image *image,XImage *ximage)
2083%
2084% A description of each parameter follows:
2085%
2086% o image: the image.
2087%
2088% o ximage: Specifies a pointer to a XImage structure; returned from
2089% XCreateImage.
2090%
cristy3ed852e2009-09-05 21:47:34 +00002091*/
2092static void XDitherImage(Image *image,XImage *ximage)
2093{
2094 static const short int
2095 dither_red[2][16]=
2096 {
2097 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2098 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2099 },
2100 dither_green[2][16]=
2101 {
2102 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2103 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2104 },
2105 dither_blue[2][16]=
2106 {
2107 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2108 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2109 };
2110
cristyc57f6942010-11-12 01:47:39 +00002111 CacheView
2112 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002113
2114 int
cristyc57f6942010-11-12 01:47:39 +00002115 value,
cristy3ed852e2009-09-05 21:47:34 +00002116 y;
2117
cristyc57f6942010-11-12 01:47:39 +00002118 PixelPacket
2119 color;
cristy3ed852e2009-09-05 21:47:34 +00002120
2121 register char
2122 *q;
2123
2124 register const PixelPacket
2125 *p;
2126
2127 register int
2128 i,
2129 j,
2130 x;
2131
2132 unsigned int
2133 scanline_pad;
2134
cristybb503372010-05-27 20:51:26 +00002135 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002136 pixel;
2137
2138 unsigned char
2139 *blue_map[2][16],
2140 *green_map[2][16],
2141 *red_map[2][16];
2142
2143 /*
2144 Allocate and initialize dither maps.
2145 */
2146 for (i=0; i < 2; i++)
2147 for (j=0; j < 16; j++)
2148 {
2149 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2150 sizeof(*red_map));
2151 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2152 sizeof(*green_map));
2153 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2154 sizeof(*blue_map));
2155 if ((red_map[i][j] == (unsigned char *) NULL) ||
2156 (green_map[i][j] == (unsigned char *) NULL) ||
2157 (blue_map[i][j] == (unsigned char *) NULL))
2158 {
2159 ThrowXWindowFatalException(ResourceLimitError,
2160 "MemoryAllocationFailed",image->filename);
2161 return;
2162 }
2163 }
2164 /*
2165 Initialize dither tables.
2166 */
2167 for (i=0; i < 2; i++)
2168 for (j=0; j < 16; j++)
2169 for (x=0; x < 256; x++)
2170 {
2171 value=x-16;
2172 if (x < 48)
2173 value=x/2+8;
2174 value+=dither_red[i][j];
2175 red_map[i][j][x]=(unsigned char)
2176 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2177 value=x-16;
2178 if (x < 48)
2179 value=x/2+8;
2180 value+=dither_green[i][j];
2181 green_map[i][j][x]=(unsigned char)
2182 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2183 value=x-32;
2184 if (x < 112)
2185 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002186 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002187 blue_map[i][j][x]=(unsigned char)
2188 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2189 }
2190 /*
2191 Dither image.
2192 */
2193 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002194 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002195 i=0;
2196 j=0;
2197 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002198 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002199 for (y=0; y < (int) image->rows; y++)
2200 {
cristyc57f6942010-11-12 01:47:39 +00002201 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2202 &image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002203 if (p == (const PixelPacket *) NULL)
2204 break;
2205 for (x=0; x < (int) image->columns; x++)
2206 {
cristyce70c172010-01-07 17:15:30 +00002207 color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
2208 ScaleQuantumToChar(GetRedPixelComponent(p))] << 8));
2209 color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
2210 ScaleQuantumToChar(GetGreenPixelComponent(p))] << 8));
2211 color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
2212 ScaleQuantumToChar(GetBluePixelComponent(p))] << 8));
cristybb503372010-05-27 20:51:26 +00002213 pixel=(size_t) (((size_t) color.red & 0xe0) |
2214 (((size_t) color.green & 0xe0) >> 3) |
2215 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002216 *q++=(char) pixel;
2217 p++;
2218 j++;
2219 if (j == 16)
2220 j=0;
2221 }
2222 q+=scanline_pad;
2223 i++;
2224 if (i == 2)
2225 i=0;
2226 }
cristyc57f6942010-11-12 01:47:39 +00002227 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002228 /*
2229 Free allocated memory.
2230 */
2231 for (i=0; i < 2; i++)
2232 for (j=0; j < 16; j++)
2233 {
2234 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2235 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2236 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2237 }
2238}
2239
2240/*
2241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2242% %
2243% %
2244% %
2245% X D r a w I m a g e %
2246% %
2247% %
2248% %
2249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2250%
2251% XDrawImage() draws a line on the image.
2252%
2253% The format of the XDrawImage method is:
2254%
2255% MagickBooleanType XDrawImage(display,pixel,draw_info,image)
2256%
2257% A description of each parameter follows:
2258%
2259% o display: Specifies a connection to an X server; returned from
2260% XOpenDisplay.
2261%
2262% o pixel: Specifies a pointer to a XPixelInfo structure.
2263%
2264% o draw_info: Specifies a pointer to a XDrawInfo structure.
2265%
2266% o image: the image.
2267%
2268*/
2269MagickExport MagickBooleanType XDrawImage(Display *display,
2270 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
2271{
cristyc57f6942010-11-12 01:47:39 +00002272 CacheView
2273 *draw_view;
2274
cristy3ed852e2009-09-05 21:47:34 +00002275 ExceptionInfo
2276 *exception;
2277
2278 GC
2279 draw_context;
2280
2281 Image
2282 *draw_image;
2283
2284 int
2285 x,
2286 y;
2287
2288 MagickBooleanType
2289 matte;
2290
2291 Pixmap
2292 draw_pixmap;
2293
2294 unsigned int
2295 depth,
2296 height,
2297 width;
2298
2299 Window
2300 root_window;
2301
2302 XGCValues
2303 context_values;
2304
2305 XImage
2306 *draw_ximage;
2307
2308 /*
2309 Initialize drawd image.
2310 */
2311 assert(display != (Display *) NULL);
2312 assert(pixel != (XPixelInfo *) NULL);
2313 assert(draw_info != (XDrawInfo *) NULL);
2314 assert(image != (Image *) NULL);
2315 if (image->debug != MagickFalse)
2316 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2317 /*
2318 Initialize drawd pixmap.
2319 */
2320 root_window=XRootWindow(display,XDefaultScreen(display));
2321 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2322 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2323 draw_info->height,depth);
2324 if (draw_pixmap == (Pixmap) NULL)
2325 return(MagickFalse);
2326 /*
2327 Initialize graphics info.
2328 */
cristybb503372010-05-27 20:51:26 +00002329 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002330 context_values.foreground=0;
2331 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002332 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002333 (GCBackground | GCForeground | GCLineWidth),&context_values);
2334 if (draw_context == (GC) NULL)
2335 return(MagickFalse);
2336 /*
2337 Clear pixmap.
2338 */
2339 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2340 draw_info->height);
2341 /*
2342 Draw line to pixmap.
2343 */
2344 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002345 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002346 if (draw_info->stipple != (Pixmap) NULL)
2347 {
2348 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2349 (void) XSetStipple(display,draw_context,draw_info->stipple);
2350 }
cristy3ed852e2009-09-05 21:47:34 +00002351 switch (draw_info->element)
2352 {
2353 case PointElement:
2354 default:
2355 {
2356 (void) XDrawLines(display,draw_pixmap,draw_context,
2357 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2358 CoordModeOrigin);
2359 break;
2360 }
2361 case LineElement:
2362 {
2363 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2364 draw_info->line_info.y1,draw_info->line_info.x2,
2365 draw_info->line_info.y2);
2366 break;
2367 }
2368 case RectangleElement:
2369 {
2370 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2371 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2372 (unsigned int) draw_info->rectangle_info.width,
2373 (unsigned int) draw_info->rectangle_info.height);
2374 break;
2375 }
2376 case FillRectangleElement:
2377 {
2378 (void) XFillRectangle(display,draw_pixmap,draw_context,
2379 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2380 (unsigned int) draw_info->rectangle_info.width,
2381 (unsigned int) draw_info->rectangle_info.height);
2382 break;
2383 }
2384 case CircleElement:
2385 case EllipseElement:
2386 {
2387 (void) XDrawArc(display,draw_pixmap,draw_context,
2388 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2389 (unsigned int) draw_info->rectangle_info.width,
2390 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2391 break;
2392 }
2393 case FillCircleElement:
2394 case FillEllipseElement:
2395 {
2396 (void) XFillArc(display,draw_pixmap,draw_context,
2397 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2398 (unsigned int) draw_info->rectangle_info.width,
2399 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2400 break;
2401 }
2402 case PolygonElement:
2403 {
2404 XPoint
2405 *coordinate_info;
2406
2407 coordinate_info=draw_info->coordinate_info;
2408 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2409 (int) draw_info->number_coordinates,CoordModeOrigin);
2410 (void) XDrawLine(display,draw_pixmap,draw_context,
2411 coordinate_info[draw_info->number_coordinates-1].x,
2412 coordinate_info[draw_info->number_coordinates-1].y,
2413 coordinate_info[0].x,coordinate_info[0].y);
2414 break;
2415 }
2416 case FillPolygonElement:
2417 {
2418 (void) XFillPolygon(display,draw_pixmap,draw_context,
2419 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2420 CoordModeOrigin);
2421 break;
2422 }
2423 }
2424 (void) XFreeGC(display,draw_context);
2425 /*
2426 Initialize X image.
2427 */
2428 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2429 draw_info->height,AllPlanes,ZPixmap);
2430 if (draw_ximage == (XImage *) NULL)
2431 return(MagickFalse);
2432 (void) XFreePixmap(display,draw_pixmap);
2433 /*
2434 Initialize draw image.
2435 */
2436 draw_image=AcquireImage((ImageInfo *) NULL);
2437 if (draw_image == (Image *) NULL)
2438 return(MagickFalse);
2439 draw_image->columns=draw_info->width;
2440 draw_image->rows=draw_info->height;
2441 /*
2442 Transfer drawn X image to image.
2443 */
2444 width=(unsigned int) image->columns;
2445 height=(unsigned int) image->rows;
2446 x=0;
2447 y=0;
2448 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +00002449 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
2450 &draw_image->background_color,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002451 if (SetImageStorageClass(draw_image,DirectClass) == MagickFalse)
2452 return(MagickFalse);
2453 draw_image->matte=MagickTrue;
2454 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +00002455 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002456 for (y=0; y < (int) draw_image->rows; y++)
2457 {
cristyc57f6942010-11-12 01:47:39 +00002458 register int
cristy3ed852e2009-09-05 21:47:34 +00002459 x;
2460
2461 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002462 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002463
cristyc57f6942010-11-12 01:47:39 +00002464 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2465 1,exception);
cristy3ed852e2009-09-05 21:47:34 +00002466 if (q == (PixelPacket *) NULL)
2467 break;
cristyc57f6942010-11-12 01:47:39 +00002468 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002469 {
2470 if (XGetPixel(draw_ximage,x,y) == 0)
2471 {
2472 /*
2473 Set this pixel to the background color.
2474 */
2475 *q=draw_image->background_color;
2476 q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
2477 TransparentOpacity : OpaqueOpacity);
2478 }
2479 else
2480 {
2481 /*
2482 Set this pixel to the pen color.
2483 */
2484 q->red=ScaleShortToQuantum(pixel->pen_color.red);
2485 q->green=ScaleShortToQuantum(pixel->pen_color.green);
2486 q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
2487 q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
2488 OpaqueOpacity : TransparentOpacity);
2489 }
2490 q++;
2491 }
cristyc57f6942010-11-12 01:47:39 +00002492 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002493 break;
2494 }
cristyc57f6942010-11-12 01:47:39 +00002495 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002496 XDestroyImage(draw_ximage);
2497 /*
2498 Determine draw geometry.
2499 */
2500 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2501 if ((width != (unsigned int) draw_image->columns) ||
2502 (height != (unsigned int) draw_image->rows))
2503 {
2504 char
2505 image_geometry[MaxTextExtent];
2506
2507 /*
2508 Scale image.
2509 */
2510 (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
2511 width,height);
2512 (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
2513 }
2514 if (draw_info->degrees != 0.0)
2515 {
2516 Image
2517 *rotate_image;
2518
2519 int
2520 rotations;
2521
2522 MagickRealType
2523 normalized_degrees;
2524
2525 /*
2526 Rotate image.
2527 */
2528 rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
2529 if (rotate_image == (Image *) NULL)
2530 return(MagickFalse);
2531 draw_image=DestroyImage(draw_image);
2532 draw_image=rotate_image;
2533 /*
2534 Annotation is relative to the degree of rotation.
2535 */
2536 normalized_degrees=draw_info->degrees;
2537 while (normalized_degrees < -45.0)
2538 normalized_degrees+=360.0;
2539 for (rotations=0; normalized_degrees > 45.0; rotations++)
2540 normalized_degrees-=90.0;
2541 switch (rotations % 4)
2542 {
2543 default:
2544 case 0:
2545 break;
2546 case 1:
2547 {
2548 /*
2549 Rotate 90 degrees.
2550 */
2551 x=x-(int) draw_image->columns/2;
2552 y=y+(int) draw_image->columns/2;
2553 break;
2554 }
2555 case 2:
2556 {
2557 /*
2558 Rotate 180 degrees.
2559 */
2560 x=x-(int) draw_image->columns;
2561 break;
2562 }
2563 case 3:
2564 {
2565 /*
2566 Rotate 270 degrees.
2567 */
2568 x=x-(int) draw_image->columns/2;
2569 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2570 break;
2571 }
2572 }
2573 }
2574 /*
2575 Composite text onto the image.
2576 */
cristyc57f6942010-11-12 01:47:39 +00002577 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002578 for (y=0; y < (int) draw_image->rows; y++)
2579 {
cristyc57f6942010-11-12 01:47:39 +00002580 register int
cristy3ed852e2009-09-05 21:47:34 +00002581 x;
2582
2583 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002584 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002585
cristyc57f6942010-11-12 01:47:39 +00002586 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2587 exception);
cristy3ed852e2009-09-05 21:47:34 +00002588 if (q == (PixelPacket *) NULL)
2589 break;
cristyc57f6942010-11-12 01:47:39 +00002590 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002591 {
2592 if (q->opacity != (Quantum) TransparentOpacity)
cristyce70c172010-01-07 17:15:30 +00002593 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00002594 q++;
2595 }
cristyc57f6942010-11-12 01:47:39 +00002596 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002597 break;
2598 }
cristyc57f6942010-11-12 01:47:39 +00002599 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002600 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2601 if (draw_info->stencil == TransparentStencil)
cristyc57f6942010-11-12 01:47:39 +00002602 (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,(ssize_t) x,
2603 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002604 else
2605 {
2606 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002607 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
2608 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002609 image->matte=matte;
2610 }
2611 draw_image=DestroyImage(draw_image);
2612 return(MagickTrue);
2613}
2614
2615/*
2616%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2617% %
2618% %
2619% %
2620% X E r r o r %
2621% %
2622% %
2623% %
2624%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2625%
2626% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2627% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
2628% for XQueryColor. It returns MagickFalse in those cases. Otherwise it returns
2629% True.
2630%
2631% The format of the XError function is:
2632%
2633% XError(display,error)
2634%
2635% A description of each parameter follows:
2636%
2637% o display: Specifies a pointer to the Display structure; returned from
2638% XOpenDisplay.
2639%
2640% o error: Specifies the error event.
2641%
2642*/
2643
2644#if defined(__cplusplus) || defined(c_plusplus)
2645extern "C" {
2646#endif
2647
2648MagickExport int XError(Display *display,XErrorEvent *error)
2649{
2650 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2651 assert(display != (Display *) NULL);
2652 assert(error != (XErrorEvent *) NULL);
2653 xerror_alert=MagickTrue;
2654 switch (error->request_code)
2655 {
2656 case X_GetGeometry:
2657 {
2658 if ((int) error->error_code == BadDrawable)
2659 return(MagickFalse);
2660 break;
2661 }
2662 case X_GetWindowAttributes:
2663 case X_QueryTree:
2664 {
2665 if ((int) error->error_code == BadWindow)
2666 return(MagickFalse);
2667 break;
2668 }
2669 case X_QueryColors:
2670 {
2671 if ((int) error->error_code == BadValue)
2672 return(MagickFalse);
2673 break;
2674 }
2675 }
2676 return(MagickTrue);
2677}
2678
2679#if defined(__cplusplus) || defined(c_plusplus)
2680}
2681#endif
2682
2683/*
2684%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2685% %
2686% %
2687% %
2688% X F r e e R e s o u r c e s %
2689% %
2690% %
2691% %
2692%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2693%
2694% XFreeResources() frees X11 resources.
2695%
2696% The format of the XFreeResources method is:
2697%
2698% void XFreeResources(Display *display,XVisualInfo *visual_info,
2699% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2700% XResourceInfo *resource_info,XWindowInfo *window_info)
2701% resource_info,window_info)
2702%
2703% A description of each parameter follows:
2704%
2705% o display: Specifies a connection to an X server; returned from
2706% XOpenDisplay.
2707%
2708% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2709% returned from XGetVisualInfo.
2710%
2711% o map_info: If map_type is specified, this structure is initialized
2712% with info from the Standard Colormap.
2713%
2714% o pixel: Specifies a pointer to a XPixelInfo structure.
2715%
2716% o font_info: Specifies a pointer to a XFontStruct structure.
2717%
2718% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2719%
2720% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2721%
2722*/
2723MagickExport void XFreeResources(Display *display,XVisualInfo *visual_info,
2724 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2725 XResourceInfo *resource_info,XWindowInfo *window_info)
2726{
2727 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2728 assert(display != (Display *) NULL);
2729 assert(resource_info != (XResourceInfo *) NULL);
2730 if (window_info != (XWindowInfo *) NULL)
2731 {
2732 /*
2733 Free X image.
2734 */
2735 if (window_info->ximage != (XImage *) NULL)
2736 XDestroyImage(window_info->ximage);
2737 if (window_info->id != (Window) NULL)
2738 {
2739 /*
2740 Free destroy window and free cursors.
2741 */
2742 if (window_info->id != XRootWindow(display,visual_info->screen))
2743 (void) XDestroyWindow(display,window_info->id);
2744 if (window_info->annotate_context != (GC) NULL)
2745 (void) XFreeGC(display,window_info->annotate_context);
2746 if (window_info->highlight_context != (GC) NULL)
2747 (void) XFreeGC(display,window_info->highlight_context);
2748 if (window_info->widget_context != (GC) NULL)
2749 (void) XFreeGC(display,window_info->widget_context);
2750 if (window_info->cursor != (Cursor) NULL)
2751 (void) XFreeCursor(display,window_info->cursor);
2752 window_info->cursor=(Cursor) NULL;
2753 if (window_info->busy_cursor != (Cursor) NULL)
2754 (void) XFreeCursor(display,window_info->busy_cursor);
2755 window_info->busy_cursor=(Cursor) NULL;
2756 }
2757 }
2758 /*
2759 Free font.
2760 */
2761 if (font_info != (XFontStruct *) NULL)
2762 (void) XFreeFont(display,font_info);
2763 if (map_info != (XStandardColormap *) NULL)
2764 {
2765 /*
2766 Free X Standard Colormap.
2767 */
2768 if (resource_info->map_type == (char *) NULL)
2769 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2770 (void) XFree((void *) map_info);
2771 }
2772 /*
2773 Free X visual info.
2774 */
2775 if (visual_info != (XVisualInfo *) NULL)
2776 (void) XFree((void *) visual_info);
2777 if (resource_info->close_server != MagickFalse)
2778 (void) XCloseDisplay(display);
2779}
2780
2781/*
2782%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2783% %
2784% %
2785% %
2786% X F r e e S t a n d a r d C o l o r m a p %
2787% %
2788% %
2789% %
2790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2791%
2792% XFreeStandardColormap() frees an X11 colormap.
2793%
2794% The format of the XFreeStandardColormap method is:
2795%
2796% void XFreeStandardColormap(Display *display,
2797% const XVisualInfo *visual_info,XStandardColormap *map_info,
2798% XPixelInfo *pixel)
2799%
2800% A description of each parameter follows:
2801%
2802% o display: Specifies a connection to an X server; returned from
2803% XOpenDisplay.
2804%
2805% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2806% returned from XGetVisualInfo.
2807%
2808% o map_info: If map_type is specified, this structure is initialized
2809% with info from the Standard Colormap.
2810%
2811% o pixel: Specifies a pointer to a XPixelInfo structure.
2812%
2813*/
2814MagickExport void XFreeStandardColormap(Display *display,
2815 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2816{
2817 /*
2818 Free colormap.
2819 */
2820 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2821 assert(display != (Display *) NULL);
2822 assert(visual_info != (XVisualInfo *) NULL);
2823 assert(map_info != (XStandardColormap *) NULL);
2824 (void) XFlush(display);
2825 if (map_info->colormap != (Colormap) NULL)
2826 {
2827 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2828 (void) XFreeColormap(display,map_info->colormap);
2829 else
2830 if (pixel != (XPixelInfo *) NULL)
2831 if ((visual_info->klass != TrueColor) &&
2832 (visual_info->klass != DirectColor))
2833 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2834 (int) pixel->colors,0);
2835 }
2836 map_info->colormap=(Colormap) NULL;
2837 if (pixel != (XPixelInfo *) NULL)
2838 {
cristyf2faecf2010-05-28 19:19:36 +00002839 if (pixel->pixels != (unsigned long *) NULL)
2840 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2841 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002842 }
2843}
2844
2845/*
2846%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2847% %
2848% %
2849% %
2850% X G e t A n n o t a t e I n f o %
2851% %
2852% %
2853% %
2854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2855%
2856% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2857%
2858% The format of the XGetAnnotateInfo method is:
2859%
2860% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2861%
2862% A description of each parameter follows:
2863%
2864% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2865%
2866*/
2867MagickExport void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2868{
2869 /*
2870 Initialize annotate structure.
2871 */
2872 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2873 assert(annotate_info != (XAnnotateInfo *) NULL);
2874 annotate_info->x=0;
2875 annotate_info->y=0;
2876 annotate_info->width=0;
2877 annotate_info->height=0;
2878 annotate_info->stencil=ForegroundStencil;
2879 annotate_info->degrees=0.0;
2880 annotate_info->font_info=(XFontStruct *) NULL;
2881 annotate_info->text=(char *) NULL;
2882 *annotate_info->geometry='\0';
2883 annotate_info->previous=(XAnnotateInfo *) NULL;
2884 annotate_info->next=(XAnnotateInfo *) NULL;
2885 (void) XSupportsLocale();
2886 (void) XSetLocaleModifiers("");
2887}
2888
2889/*
2890%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2891% %
2892% %
2893% %
2894% X G e t M a p I n f o %
2895% %
2896% %
2897% %
2898%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2899%
2900% XGetMapInfo() initializes the XStandardColormap structure.
2901%
2902% The format of the XStandardColormap method is:
2903%
2904% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2905% XStandardColormap *map_info)
2906%
2907% A description of each parameter follows:
2908%
2909% o colormap: Specifies the ID of the X server colormap.
2910%
2911% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2912% returned from XGetVisualInfo.
2913%
2914% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2915%
2916*/
2917MagickExport void XGetMapInfo(const XVisualInfo *visual_info,
2918 const Colormap colormap,XStandardColormap *map_info)
2919{
2920 /*
2921 Initialize map info.
2922 */
2923 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2924 assert(visual_info != (XVisualInfo *) NULL);
2925 assert(map_info != (XStandardColormap *) NULL);
2926 map_info->colormap=colormap;
2927 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002928 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002929 if (map_info->red_max != 0)
2930 while ((map_info->red_max & 0x01) == 0)
2931 {
2932 map_info->red_max>>=1;
2933 map_info->red_mult<<=1;
2934 }
2935 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002936 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002937 if (map_info->green_max != 0)
2938 while ((map_info->green_max & 0x01) == 0)
2939 {
2940 map_info->green_max>>=1;
2941 map_info->green_mult<<=1;
2942 }
2943 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002944 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002945 if (map_info->blue_max != 0)
2946 while ((map_info->blue_max & 0x01) == 0)
2947 {
2948 map_info->blue_max>>=1;
2949 map_info->blue_mult<<=1;
2950 }
2951 map_info->base_pixel=0;
2952}
2953
2954/*
2955%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2956% %
2957% %
2958% %
2959% X G e t P i x e l I n f o %
2960% %
2961% %
2962% %
2963%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2964%
2965% XGetPixelPacket() initializes the PixelPacket structure.
2966%
2967% The format of the XGetPixelPacket method is:
2968%
2969% void XGetPixelPacket(Display *display,const XVisualInfo *visual_info,
2970% const XStandardColormap *map_info,const XResourceInfo *resource_info,
2971% Image *image,XPixelInfo *pixel)
2972% pixel)
2973%
2974% A description of each parameter follows:
2975%
2976% o display: Specifies a connection to an X server; returned from
2977% XOpenDisplay.
2978%
2979% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2980% returned from XGetVisualInfo.
2981%
2982% o map_info: If map_type is specified, this structure is initialized
2983% with info from the Standard Colormap.
2984%
2985% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2986%
2987% o image: the image.
2988%
2989% o pixel: Specifies a pointer to a XPixelInfo structure.
2990%
2991*/
2992MagickExport void XGetPixelPacket(Display *display,
2993 const XVisualInfo *visual_info,const XStandardColormap *map_info,
2994 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
2995{
2996 static const char
2997 *PenColors[MaxNumberPens]=
2998 {
2999 "#000000000000", /* black */
3000 "#00000000ffff", /* blue */
3001 "#0000ffffffff", /* cyan */
3002 "#0000ffff0000", /* green */
3003 "#bdbdbdbdbdbd", /* gray */
3004 "#ffff00000000", /* red */
3005 "#ffff0000ffff", /* magenta */
3006 "#ffffffff0000", /* yellow */
3007 "#ffffffffffff", /* white */
3008 "#bdbdbdbdbdbd", /* gray */
3009 "#bdbdbdbdbdbd" /* gray */
3010 };
3011
3012 Colormap
3013 colormap;
3014
cristybb503372010-05-27 20:51:26 +00003015 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003016 i;
3017
3018 Status
3019 status;
3020
3021 unsigned int
3022 packets;
3023
3024 /*
3025 Initialize pixel info.
3026 */
3027 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3028 assert(display != (Display *) NULL);
3029 assert(visual_info != (XVisualInfo *) NULL);
3030 assert(map_info != (XStandardColormap *) NULL);
3031 assert(resource_info != (XResourceInfo *) NULL);
3032 assert(pixel != (XPixelInfo *) NULL);
3033 pixel->colors=0;
3034 if (image != (Image *) NULL)
3035 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003036 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003037 packets=(unsigned int)
3038 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003039 if (pixel->pixels != (unsigned long *) NULL)
3040 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3041 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003042 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003043 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003044 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3045 image->filename);
3046 /*
3047 Set foreground color.
3048 */
3049 colormap=map_info->colormap;
3050 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3051 &pixel->foreground_color);
3052 status=XParseColor(display,colormap,resource_info->foreground_color,
3053 &pixel->foreground_color);
3054 if (status == False)
3055 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3056 resource_info->foreground_color);
3057 pixel->foreground_color.pixel=
3058 XStandardPixel(map_info,&pixel->foreground_color);
3059 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3060 /*
3061 Set background color.
3062 */
3063 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3064 status=XParseColor(display,colormap,resource_info->background_color,
3065 &pixel->background_color);
3066 if (status == False)
3067 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3068 resource_info->background_color);
3069 pixel->background_color.pixel=
3070 XStandardPixel(map_info,&pixel->background_color);
3071 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3072 /*
3073 Set border color.
3074 */
3075 (void) XParseColor(display,colormap,(char *) BorderColor,
3076 &pixel->border_color);
3077 status=XParseColor(display,colormap,resource_info->border_color,
3078 &pixel->border_color);
3079 if (status == False)
3080 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3081 resource_info->border_color);
3082 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3083 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3084 /*
3085 Set matte color.
3086 */
3087 pixel->matte_color=pixel->background_color;
3088 if (resource_info->matte_color != (char *) NULL)
3089 {
3090 /*
3091 Matte color is specified as a X resource or command line argument.
3092 */
3093 status=XParseColor(display,colormap,resource_info->matte_color,
3094 &pixel->matte_color);
3095 if (status == False)
3096 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3097 resource_info->matte_color);
3098 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3099 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3100 }
3101 /*
3102 Set highlight color.
3103 */
3104 pixel->highlight_color.red=(unsigned short) ((
3105 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3106 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3107 pixel->highlight_color.green=(unsigned short) ((
3108 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3109 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3110 pixel->highlight_color.blue=(unsigned short) ((
3111 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3112 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3113 pixel->highlight_color.pixel=
3114 XStandardPixel(map_info,&pixel->highlight_color);
3115 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3116 /*
3117 Set shadow color.
3118 */
3119 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3120 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3121 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3122 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3123 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3124 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3125 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3126 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3127 /*
3128 Set depth color.
3129 */
3130 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3131 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3132 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3133 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3134 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3135 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3136 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3137 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3138 /*
3139 Set trough color.
3140 */
3141 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3142 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3143 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3144 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3145 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3146 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3147 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3148 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3149 /*
3150 Set pen color.
3151 */
3152 for (i=0; i < MaxNumberPens; i++)
3153 {
3154 (void) XParseColor(display,colormap,(char *) PenColors[i],
3155 &pixel->pen_colors[i]);
3156 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3157 &pixel->pen_colors[i]);
3158 if (status == False)
3159 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3160 resource_info->pen_colors[i]);
3161 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3162 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3163 }
3164 pixel->box_color=pixel->background_color;
3165 pixel->pen_color=pixel->foreground_color;
3166 pixel->box_index=0;
3167 pixel->pen_index=1;
3168 if (image != (Image *) NULL)
3169 {
3170 if ((resource_info->gamma_correct != MagickFalse) &&
3171 (image->gamma != 0.0))
3172 {
3173 GeometryInfo
3174 geometry_info;
3175
3176 MagickStatusType
3177 flags;
3178
3179 /*
3180 Initialize map relative to display and image gamma.
3181 */
3182 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3183 red_gamma=geometry_info.rho;
3184 green_gamma=geometry_info.sigma;
3185 if ((flags & SigmaValue) == 0)
3186 green_gamma=red_gamma;
3187 blue_gamma=geometry_info.xi;
3188 if ((flags & XiValue) == 0)
3189 blue_gamma=red_gamma;
3190 red_gamma*=image->gamma;
3191 green_gamma*=image->gamma;
3192 blue_gamma*=image->gamma;
3193 }
3194 if (image->storage_class == PseudoClass)
3195 {
3196 /*
3197 Initialize pixel array for images of type PseudoClass.
3198 */
cristybb503372010-05-27 20:51:26 +00003199 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00003200 pixel->pixels[i]=
3201 XGammaPixel(map_info,image->colormap+i);
3202 for (i=0; i < MaxNumberPens; i++)
3203 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3204 pixel->colors+=MaxNumberPens;
3205 }
3206 }
3207}
3208
3209/*
3210%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3211% %
3212% %
3213% %
3214% X G e t R e s o u r c e C l a s s %
3215% %
3216% %
3217% %
3218%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3219%
3220% XGetResourceClass() queries the X server for the specified resource name or
3221% class. If the resource name or class is not defined in the database, the
3222% supplied default value is returned.
3223%
3224% The format of the XGetResourceClass method is:
3225%
3226% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3227% const char *keyword,char *resource_default)
3228%
3229% A description of each parameter follows:
3230%
3231% o database: Specifies a resource database; returned from
3232% XrmGetStringDatabase.
3233%
3234% o client_name: Specifies the application name used to retrieve resource
3235% info from the X server database.
3236%
3237% o keyword: Specifies the keyword of the value being retrieved.
3238%
3239% o resource_default: Specifies the default value to return if the query
3240% fails to find the specified keyword/class.
3241%
3242*/
3243MagickExport char *XGetResourceClass(XrmDatabase database,
3244 const char *client_name,const char *keyword,char *resource_default)
3245{
3246 char
3247 resource_class[MaxTextExtent],
3248 resource_name[MaxTextExtent];
3249
3250 static char
3251 *resource_type;
3252
3253 Status
3254 status;
3255
3256 XrmValue
3257 resource_value;
3258
3259 if (database == (XrmDatabase) NULL)
3260 return(resource_default);
3261 *resource_name='\0';
3262 *resource_class='\0';
3263 if (keyword != (char *) NULL)
3264 {
3265 int
3266 c,
3267 k;
3268
3269 /*
3270 Initialize resource keyword and class.
3271 */
3272 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",
3273 client_name,keyword);
3274 c=(int) (*client_name);
3275 if ((c >= XK_a) && (c <= XK_z))
3276 c-=(XK_a-XK_A);
3277 else
3278 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3279 c-=(XK_agrave-XK_Agrave);
3280 else
3281 if ((c >= XK_oslash) && (c <= XK_thorn))
3282 c-=(XK_oslash-XK_Ooblique);
3283 k=(int) (*keyword);
3284 if ((k >= XK_a) && (k <= XK_z))
3285 k-=(XK_a-XK_A);
3286 else
3287 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3288 k-=(XK_agrave-XK_Agrave);
3289 else
3290 if ((k >= XK_oslash) && (k <= XK_thorn))
3291 k-=(XK_oslash-XK_Ooblique);
3292 (void) FormatMagickString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
3293 client_name+1,k,keyword+1);
3294 }
3295 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3296 &resource_value);
3297 if (status == False)
3298 return(resource_default);
3299 return(resource_value.addr);
3300}
3301
3302/*
3303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3304% %
3305% %
3306% %
3307% X G e t R e s o u r c e D a t a b a s e %
3308% %
3309% %
3310% %
3311%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3312%
3313% XGetResourceDatabase() creates a new resource database and initializes it.
3314%
3315% The format of the XGetResourceDatabase method is:
3316%
3317% XrmDatabase XGetResourceDatabase(Display *display,
3318% const char *client_name)
3319%
3320% A description of each parameter follows:
3321%
3322% o database: XGetResourceDatabase() returns the database after it is
3323% initialized.
3324%
3325% o display: Specifies a connection to an X server; returned from
3326% XOpenDisplay.
3327%
3328% o client_name: Specifies the application name used to retrieve resource
3329% info from the X server database.
3330%
3331*/
3332MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3333 const char *client_name)
3334{
3335 char
3336 filename[MaxTextExtent];
3337
3338 int
3339 c;
3340
3341 register const char
3342 *p;
3343
3344 XrmDatabase
3345 resource_database,
3346 server_database;
3347
3348 if (display == (Display *) NULL)
3349 return((XrmDatabase) NULL);
3350 assert(client_name != (char *) NULL);
3351 /*
3352 Initialize resource database.
3353 */
3354 XrmInitialize();
3355 (void) XGetDefault(display,(char *) client_name,"dummy");
3356 resource_database=XrmGetDatabase(display);
3357 /*
3358 Combine application database.
3359 */
3360 if (client_name != (char *) NULL)
3361 {
3362 /*
3363 Get basename of client.
3364 */
3365 p=client_name+(strlen(client_name)-1);
3366 while ((p > client_name) && (*p != '/'))
3367 p--;
3368 if (*p == '/')
3369 client_name=p+1;
3370 }
3371 c=(int) (*client_name);
3372 if ((c >= XK_a) && (c <= XK_z))
3373 c-=(XK_a-XK_A);
3374 else
3375 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3376 c-=(XK_agrave-XK_Agrave);
3377 else
3378 if ((c >= XK_oslash) && (c <= XK_thorn))
3379 c-=(XK_oslash-XK_Ooblique);
3380#if defined(X11_APPLICATION_PATH)
3381 (void) FormatMagickString(filename,MaxTextExtent,"%s%c%s",
3382 X11_APPLICATION_PATH,c,client_name+1);
3383 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3384#endif
3385 if (XResourceManagerString(display) != (char *) NULL)
3386 {
3387 /*
3388 Combine server database.
3389 */
3390 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3391 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3392 }
3393 /*
3394 Merge user preferences database.
3395 */
3396#if defined(X11_PREFERENCES_PATH)
3397 (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
3398 X11_PREFERENCES_PATH,client_name);
3399 ExpandFilename(filename);
3400 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3401#endif
3402 return(resource_database);
3403}
3404
3405/*
3406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3407% %
3408% %
3409% %
3410% X G e t R e s o u r c e I n f o %
3411% %
3412% %
3413% %
3414%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3415%
3416% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3417%
3418% The format of the XGetResourceInfo method is:
3419%
3420% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3421% const char *client_name,XResourceInfo *resource_info)
3422%
3423% A description of each parameter follows:
3424%
3425% o image_info: the image info.
3426%
3427% o database: Specifies a resource database; returned from
3428% XrmGetStringDatabase.
3429%
3430% o client_name: Specifies the application name used to retrieve
3431% resource info from the X server database.
3432%
3433% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3434%
3435*/
3436MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3437 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3438{
3439 char
cristy00976d82011-02-20 20:31:28 +00003440 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003441 *resource_value;
3442
3443 /*
3444 Initialize resource info fields.
3445 */
3446 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3447 assert(resource_info != (XResourceInfo *) NULL);
3448 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3449 resource_info->resource_database=database;
3450 resource_info->image_info=(ImageInfo *) image_info;
3451 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3452 XMagickProgressMonitor,(void *) NULL);
3453 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3454 resource_info->close_server=MagickTrue;
3455 resource_info->client_name=AcquireString(client_name);
3456 resource_value=XGetResourceClass(database,client_name,"backdrop",
3457 (char *) "False");
3458 resource_info->backdrop=IsMagickTrue(resource_value);
3459 resource_info->background_color=XGetResourceInstance(database,client_name,
3460 "background",(char *) "#d6d6d6d6d6d6");
3461 resource_info->border_color=XGetResourceInstance(database,client_name,
3462 "borderColor",BorderColor);
3463 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3464 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003465 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3466 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003467 resource_value=XGetResourceClass(database,client_name,"colormap",
3468 (char *) "shared");
3469 resource_info->colormap=UndefinedColormap;
3470 if (LocaleCompare("private",resource_value) == 0)
3471 resource_info->colormap=PrivateColormap;
3472 if (LocaleCompare("shared",resource_value) == 0)
3473 resource_info->colormap=SharedColormap;
3474 if (resource_info->colormap == UndefinedColormap)
3475 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3476 resource_value);
3477 resource_value=XGetResourceClass(database,client_name,
3478 "colorRecovery",(char *) "False");
3479 resource_info->color_recovery=IsMagickTrue(resource_value);
3480 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3481 (char *) "False");
3482 resource_info->confirm_exit=IsMagickTrue(resource_value);
3483 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3484 (char *) "False");
3485 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003486 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003487 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003488 resource_info->display_gamma=XGetResourceClass(database,client_name,
3489 "displayGamma",(char *) "2.2");
3490 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3491 (char *) "True");
3492 resource_info->display_warnings=IsMagickTrue(resource_value);
3493 resource_info->font=XGetResourceClass(database,client_name,"font",
3494 (char *) NULL);
3495 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3496 resource_info->font);
3497 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3498 (char *) "fixed");
3499 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3500 (char *) "variable");
3501 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3502 (char *) "5x8");
3503 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3504 (char *) "6x10");
3505 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3506 (char *) "7x13bold");
3507 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3508 (char *) "8x13bold");
3509 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3510 (char *) "9x15bold");
3511 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3512 (char *) "10x20");
3513 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3514 (char *) "12x24");
3515 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3516 (char *) "fixed");
3517 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3518 (char *) "fixed");
3519 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3520 "foreground",ForegroundColor);
3521 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3522 (char *) "True");
3523 resource_info->gamma_correct=IsMagickTrue(resource_value);
3524 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3525 client_name,"geometry",(char *) NULL));
3526 resource_value=XGetResourceClass(database,client_name,"gravity",
3527 (char *) "Center");
3528 resource_info->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
3529 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003530 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3531 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003532 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3533 "iconGeometry",(char *) NULL);
3534 resource_value=XGetResourceClass(database,client_name,"iconic",
3535 (char *) "False");
3536 resource_info->iconic=IsMagickTrue(resource_value);
3537 resource_value=XGetResourceClass(database,client_name,"immutable",
3538 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3539 (char *) "False");
3540 resource_info->immutable=IsMagickTrue(resource_value);
3541 resource_value=XGetResourceClass(database,client_name,"magnify",
3542 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003543 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003544 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3545 (char *) NULL);
3546 resource_info->matte_color=XGetResourceInstance(database,client_name,
3547 "mattecolor",(char *) NULL);
3548 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3549 "name",(char *) NULL));
3550 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3551 (char *) "black");
3552 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3553 (char *) "blue");
3554 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3555 (char *) "cyan");
3556 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3557 (char *) "green");
3558 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3559 (char *) "gray");
3560 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3561 (char *) "red");
3562 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3563 (char *) "magenta");
3564 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3565 (char *) "yellow");
3566 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3567 (char *) "white");
3568 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3569 (char *) "gray");
3570 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3571 (char *) "gray");
3572 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003573 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003574 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003575 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003576 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3577 "font",(char *) "fixed");
3578 resource_info->text_font=XGetResourceClass(database,client_name,
3579 "textFontList",resource_info->text_font);
3580 resource_info->title=XGetResourceClass(database,client_name,"title",
3581 (char *) NULL);
3582 resource_value=XGetResourceClass(database,client_name,"undoCache",
3583 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003584 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003585 resource_value=XGetResourceClass(database,client_name,"update",
3586 (char *) "False");
3587 resource_info->update=IsMagickTrue(resource_value);
3588 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3589 (char *) "True");
3590 resource_info->use_pixmap=IsMagickTrue(resource_value);
3591 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3592 (char *) "True");
3593 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3594 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3595 (char *) NULL);
3596 resource_info->window_group=XGetResourceClass(database,client_name,
3597 "windowGroup",(char *) NULL);
3598 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3599 (char *) NULL);
3600 resource_info->write_filename=XGetResourceClass(database,client_name,
3601 "writeFilename",(char *) NULL);
3602}
3603
3604/*
3605%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3606% %
3607% %
3608% %
3609% X G e t R e s o u r c e I n s t a n c e %
3610% %
3611% %
3612% %
3613%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3614%
3615% XGetResourceInstance() queries the X server for the specified resource name.
3616% If the resource name is not defined in the database, the supplied default
3617% value is returned.
3618%
3619% The format of the XGetResourceInstance method is:
3620%
3621% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3622% const char *keyword,const char *resource_default)
3623%
3624% A description of each parameter follows:
3625%
3626% o database: Specifies a resource database; returned from
3627% XrmGetStringDatabase.
3628%
3629% o client_name: Specifies the application name used to retrieve
3630% resource info from the X server database.
3631%
3632% o keyword: Specifies the keyword of the value being retrieved.
3633%
3634% o resource_default: Specifies the default value to return if the query
3635% fails to find the specified keyword/class.
3636%
3637*/
3638MagickExport char *XGetResourceInstance(XrmDatabase database,
3639 const char *client_name,const char *keyword,const char *resource_default)
3640{
3641 char
3642 *resource_type,
3643 resource_name[MaxTextExtent];
3644
3645 Status
3646 status;
3647
3648 XrmValue
3649 resource_value;
3650
3651 if (database == (XrmDatabase) NULL)
3652 return((char *) resource_default);
3653 *resource_name='\0';
3654 if (keyword != (char *) NULL)
3655 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",client_name,
3656 keyword);
3657 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3658 &resource_value);
3659 if (status == False)
3660 return((char *) resource_default);
3661 return(resource_value.addr);
3662}
3663
3664/*
3665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3666% %
3667% %
3668% %
3669% X G e t S c r e e n D e n s i t y %
3670% %
3671% %
3672% %
3673%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3674%
3675% XGetScreenDensity() returns the density of the X server screen in
3676% dots-per-inch.
3677%
3678% The format of the XGetScreenDensity method is:
3679%
3680% char *XGetScreenDensity(Display *display)
3681%
3682% A description of each parameter follows:
3683%
3684% o density: XGetScreenDensity() returns the density of the X screen in
3685% dots-per-inch.
3686%
3687% o display: Specifies a connection to an X server; returned from
3688% XOpenDisplay.
3689%
3690*/
3691MagickExport char *XGetScreenDensity(Display *display)
3692{
3693 char
3694 density[MaxTextExtent];
3695
3696 double
3697 x_density,
3698 y_density;
3699
3700 /*
3701 Set density as determined by screen size.
3702 */
3703 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3704 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3705 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3706 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristye7f51092010-01-17 00:39:37 +00003707 (void) FormatMagickString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003708 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003709 return(GetPageGeometry(density));
3710}
3711
3712/*
3713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3714% %
3715% %
3716% %
3717+ X G e t S u b w i n d o w %
3718% %
3719% %
3720% %
3721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3722%
3723% XGetSubwindow() returns the subwindow of a window chosen the user with the
3724% pointer and a button press.
3725%
3726% The format of the XGetSubwindow method is:
3727%
3728% Window XGetSubwindow(Display *display,Window window,int x,int y)
3729%
3730% A description of each parameter follows:
3731%
3732% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3733% otherwise the subwindow is returned.
3734%
3735% o display: Specifies a connection to an X server; returned from
3736% XOpenDisplay.
3737%
3738% o window: Specifies a pointer to a Window.
3739%
3740% o x: the x coordinate of the pointer relative to the origin of the
3741% window.
3742%
3743% o y: the y coordinate of the pointer relative to the origin of the
3744% window.
3745%
cristy3ed852e2009-09-05 21:47:34 +00003746*/
3747static Window XGetSubwindow(Display *display,Window window,int x,int y)
3748{
3749 int
3750 x_offset,
3751 y_offset;
3752
3753 Status
3754 status;
3755
3756 Window
3757 source_window,
3758 target_window;
3759
3760 assert(display != (Display *) NULL);
3761 source_window=XRootWindow(display,XDefaultScreen(display));
3762 if (window == (Window) NULL)
3763 return(source_window);
3764 target_window=window;
3765 for ( ; ; )
3766 {
3767 status=XTranslateCoordinates(display,source_window,window,x,y,
3768 &x_offset,&y_offset,&target_window);
3769 if (status != True)
3770 break;
3771 if (target_window == (Window) NULL)
3772 break;
3773 source_window=window;
3774 window=target_window;
3775 x=x_offset;
3776 y=y_offset;
3777 }
3778 if (target_window == (Window) NULL)
3779 target_window=window;
3780 return(target_window);
3781}
3782
3783/*
3784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3785% %
3786% %
3787% %
3788% X G e t W i n d o w C o l o r %
3789% %
3790% %
3791% %
3792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3793%
3794% XGetWindowColor() returns the color of a pixel interactively chosen from the
3795% X server.
3796%
3797% The format of the XGetWindowColor method is:
3798%
3799% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3800% char *name)
3801%
3802% A description of each parameter follows:
3803%
3804% o display: Specifies a connection to an X server; returned from
3805% XOpenDisplay.
3806%
3807% o windows: Specifies a pointer to a XWindows structure.
3808%
3809% o name: the name of the color if found in the X Color Database is
3810% returned in this character string.
3811%
3812*/
3813MagickExport MagickBooleanType XGetWindowColor(Display *display,
3814 XWindows *windows,char *name)
3815{
3816 int
3817 x,
3818 y;
3819
3820 PixelPacket
3821 pixel;
3822
3823 RectangleInfo
3824 crop_info;
3825
3826 Status
3827 status;
3828
3829 Window
3830 child,
3831 client_window,
3832 root_window,
3833 target_window;
3834
3835 XColor
3836 color;
3837
3838 XImage
3839 *ximage;
3840
3841 XWindowAttributes
3842 window_attributes;
3843
3844 /*
3845 Choose a pixel from the X server.
3846 */
3847 assert(display != (Display *) NULL);
3848 assert(name != (char *) NULL);
3849 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3850 *name='\0';
3851 target_window=XSelectWindow(display,&crop_info);
3852 if (target_window == (Window) NULL)
3853 return(MagickFalse);
3854 root_window=XRootWindow(display,XDefaultScreen(display));
3855 client_window=target_window;
3856 if (target_window != root_window)
3857 {
3858 unsigned int
3859 d;
3860
3861 /*
3862 Get client window.
3863 */
3864 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3865 if (status != False)
3866 {
3867 client_window=XClientWindow(display,target_window);
3868 target_window=client_window;
3869 }
3870 }
3871 /*
3872 Verify window is viewable.
3873 */
3874 status=XGetWindowAttributes(display,target_window,&window_attributes);
3875 if ((status == False) || (window_attributes.map_state != IsViewable))
3876 return(MagickFalse);
3877 /*
3878 Get window X image.
3879 */
3880 (void) XTranslateCoordinates(display,root_window,target_window,
3881 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3882 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3883 if (ximage == (XImage *) NULL)
3884 return(MagickFalse);
3885 color.pixel=XGetPixel(ximage,0,0);
3886 XDestroyImage(ximage);
3887 /*
3888 Match color against the color database.
3889 */
3890 (void) XQueryColor(display,window_attributes.colormap,&color);
3891 pixel.red=ScaleShortToQuantum(color.red);
3892 pixel.green=ScaleShortToQuantum(color.green);
3893 pixel.blue=ScaleShortToQuantum(color.blue);
3894 pixel.opacity=OpaqueOpacity;
3895 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3896 &windows->image.image->exception);
3897 return(MagickTrue);
3898}
3899
3900/*
3901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3902% %
3903% %
3904% %
3905+ X G e t W i n d o w I m a g e %
3906% %
3907% %
3908% %
3909%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3910%
3911% XGetWindowImage() reads an image from the target X window and returns it.
3912% XGetWindowImage() optionally descends the window hierarchy and overlays the
3913% target image with each child image in an optimized fashion. Any child
3914% window that have the same visual, colormap, and are contained by its parent
3915% are exempted.
3916%
3917% The format of the XGetWindowImage method is:
3918%
3919% Image *XGetWindowImage(Display *display,const Window window,
3920% const unsigned int borders,const unsigned int level)
3921%
3922% A description of each parameter follows:
3923%
3924% o display: Specifies a connection to an X server; returned from
3925% XOpenDisplay.
3926%
3927% o window: Specifies the window to obtain the image from.
3928%
3929% o borders: Specifies whether borders pixels are to be saved with
3930% the image.
3931%
3932% o level: Specifies an unsigned integer representing the level of
3933% decent in the window hierarchy. This value must be zero or one on
3934% the initial call to XGetWindowImage. A value of zero returns after
3935% one call. A value of one causes the function to descend the window
3936% hierarchy and overlay the target image with each subwindow image.
3937%
cristy3ed852e2009-09-05 21:47:34 +00003938*/
3939static Image *XGetWindowImage(Display *display,const Window window,
3940 const unsigned int borders,const unsigned int level)
3941{
3942 typedef struct _ColormapInfo
3943 {
3944 Colormap
3945 colormap;
3946
3947 XColor
3948 *colors;
3949
3950 struct _ColormapInfo
3951 *next;
3952 } ColormapInfo;
3953
3954 typedef struct _WindowInfo
3955 {
3956 Window
3957 window,
3958 parent;
3959
3960 Visual
3961 *visual;
3962
3963 Colormap
3964 colormap;
3965
3966 XSegment
3967 bounds;
3968
3969 RectangleInfo
3970 crop_info;
3971 } WindowInfo;
3972
3973 IndexPacket
3974 index;
3975
3976 int
3977 display_height,
3978 display_width,
3979 id,
3980 x_offset,
3981 y_offset;
3982
3983 RectangleInfo
3984 crop_info;
3985
3986 register IndexPacket
3987 *indexes;
3988
3989 register int
3990 i;
3991
3992 static ColormapInfo
3993 *colormap_info = (ColormapInfo *) NULL;
3994
3995 static int
3996 max_windows = 0,
3997 number_windows = 0;
3998
3999 static WindowInfo
4000 *window_info;
4001
4002 Status
4003 status;
4004
4005 Window
4006 child,
4007 root_window;
4008
4009 XWindowAttributes
4010 window_attributes;
4011
4012 /*
4013 Verify window is viewable.
4014 */
4015 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4016 assert(display != (Display *) NULL);
4017 status=XGetWindowAttributes(display,window,&window_attributes);
4018 if ((status == False) || (window_attributes.map_state != IsViewable))
4019 return((Image *) NULL);
4020 /*
4021 Cropping rectangle is relative to root window.
4022 */
4023 root_window=XRootWindow(display,XDefaultScreen(display));
4024 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4025 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004026 crop_info.x=(ssize_t) x_offset;
4027 crop_info.y=(ssize_t) y_offset;
4028 crop_info.width=(size_t) window_attributes.width;
4029 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004030 if (borders != MagickFalse)
4031 {
4032 /*
4033 Include border in image.
4034 */
cristybb503372010-05-27 20:51:26 +00004035 crop_info.x-=(ssize_t) window_attributes.border_width;
4036 crop_info.y-=(ssize_t) window_attributes.border_width;
4037 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4038 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004039 }
4040 /*
4041 Crop to root window.
4042 */
4043 if (crop_info.x < 0)
4044 {
4045 crop_info.width+=crop_info.x;
4046 crop_info.x=0;
4047 }
4048 if (crop_info.y < 0)
4049 {
4050 crop_info.height+=crop_info.y;
4051 crop_info.y=0;
4052 }
4053 display_width=XDisplayWidth(display,XDefaultScreen(display));
4054 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004055 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004056 display_height=XDisplayHeight(display,XDefaultScreen(display));
4057 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004058 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004059 /*
4060 Initialize window info attributes.
4061 */
4062 if (number_windows >= max_windows)
4063 {
4064 /*
4065 Allocate or resize window info buffer.
4066 */
4067 max_windows+=1024;
4068 if (window_info == (WindowInfo *) NULL)
4069 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4070 sizeof(*window_info));
4071 else
4072 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4073 max_windows,sizeof(*window_info));
4074 }
4075 if (window_info == (WindowInfo *) NULL)
4076 {
4077 ThrowXWindowFatalException(ResourceLimitError,
4078 "MemoryAllocationFailed","...");
4079 return((Image *) NULL);
4080 }
4081 id=number_windows++;
4082 window_info[id].window=window;
4083 window_info[id].visual=window_attributes.visual;
4084 window_info[id].colormap=window_attributes.colormap;
4085 window_info[id].bounds.x1=(short) crop_info.x;
4086 window_info[id].bounds.y1=(short) crop_info.y;
4087 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4088 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4089 crop_info.x-=x_offset;
4090 crop_info.y-=y_offset;
4091 window_info[id].crop_info=crop_info;
4092 if (level != 0)
4093 {
4094 unsigned int
4095 number_children;
4096
4097 Window
4098 *children;
4099
4100 /*
4101 Descend the window hierarchy.
4102 */
4103 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4104 &children,&number_children);
4105 for (i=0; i < id; i++)
4106 if ((window_info[i].window == window_info[id].parent) &&
4107 (window_info[i].visual == window_info[id].visual) &&
4108 (window_info[i].colormap == window_info[id].colormap))
4109 {
4110 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4111 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4112 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4113 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4114 {
4115 /*
4116 Eliminate windows not circumscribed by their parent.
4117 */
4118 number_windows--;
4119 break;
4120 }
4121 }
4122 if ((status == True) && (number_children != 0))
4123 {
4124 for (i=0; i < (int) number_children; i++)
4125 (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4126 (void) XFree((void *) children);
4127 }
4128 }
4129 if (level <= 1)
4130 {
cristyc57f6942010-11-12 01:47:39 +00004131 CacheView
4132 *composite_view;
4133
cristy3ed852e2009-09-05 21:47:34 +00004134 ColormapInfo
4135 *next;
4136
4137 ExceptionInfo
4138 *exception;
4139
4140 Image
4141 *composite_image,
4142 *image;
4143
4144 int
4145 y;
4146
4147 MagickBooleanType
4148 import;
4149
4150 register int
4151 j,
4152 x;
4153
4154 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00004155 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004156
cristybb503372010-05-27 20:51:26 +00004157 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004158 pixel;
4159
4160 unsigned int
4161 number_colors;
4162
4163 XColor
4164 *colors;
4165
4166 XImage
4167 *ximage;
4168
4169 /*
4170 Get X image for each window in the list.
4171 */
4172 image=NewImageList();
4173 for (id=0; id < number_windows; id++)
4174 {
4175 /*
4176 Does target window intersect top level window?
4177 */
4178 import=
4179 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4180 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4181 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4182 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4183 MagickTrue : MagickFalse;
4184 /*
4185 Is target window contained by another window with the same colormap?
4186 */
4187 for (j=0; j < id; j++)
4188 if ((window_info[id].visual == window_info[j].visual) &&
4189 (window_info[id].colormap == window_info[j].colormap))
4190 {
4191 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4192 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4193 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4194 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4195 import=MagickFalse;
4196 }
4197 else
4198 if ((window_info[id].visual != window_info[j].visual) ||
4199 (window_info[id].colormap != window_info[j].colormap))
4200 {
4201 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4202 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4203 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4204 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4205 import=MagickTrue;
4206 }
4207 if (import == MagickFalse)
4208 continue;
4209 /*
4210 Get X image.
4211 */
4212 ximage=XGetImage(display,window_info[id].window,(int)
4213 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4214 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4215 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4216 if (ximage == (XImage *) NULL)
4217 continue;
4218 /*
4219 Initialize window colormap.
4220 */
4221 number_colors=0;
4222 colors=(XColor *) NULL;
4223 if (window_info[id].colormap != (Colormap) NULL)
4224 {
4225 ColormapInfo
4226 *p;
4227
4228 /*
4229 Search colormap list for window colormap.
4230 */
4231 number_colors=(unsigned int) window_info[id].visual->map_entries;
4232 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4233 if (p->colormap == window_info[id].colormap)
4234 break;
4235 if (p == (ColormapInfo *) NULL)
4236 {
4237 /*
4238 Get the window colormap.
4239 */
4240 colors=(XColor *) AcquireQuantumMemory(number_colors,
4241 sizeof(*colors));
4242 if (colors == (XColor *) NULL)
4243 {
4244 XDestroyImage(ximage);
4245 return((Image *) NULL);
4246 }
4247 if ((window_info[id].visual->klass != DirectColor) &&
4248 (window_info[id].visual->klass != TrueColor))
4249 for (i=0; i < (int) number_colors; i++)
4250 {
cristybb503372010-05-27 20:51:26 +00004251 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004252 colors[i].pad='\0';
4253 }
4254 else
4255 {
cristybb503372010-05-27 20:51:26 +00004256 size_t
cristy3ed852e2009-09-05 21:47:34 +00004257 blue,
4258 blue_bit,
4259 green,
4260 green_bit,
4261 red,
4262 red_bit;
4263
4264 /*
4265 DirectColor or TrueColor visual.
4266 */
4267 red=0;
4268 green=0;
4269 blue=0;
4270 red_bit=window_info[id].visual->red_mask &
4271 (~(window_info[id].visual->red_mask)+1);
4272 green_bit=window_info[id].visual->green_mask &
4273 (~(window_info[id].visual->green_mask)+1);
4274 blue_bit=window_info[id].visual->blue_mask &
4275 (~(window_info[id].visual->blue_mask)+1);
4276 for (i=0; i < (int) number_colors; i++)
4277 {
cristy8891f9c2010-06-04 23:32:17 +00004278 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004279 colors[i].pad='\0';
4280 red+=red_bit;
4281 if (red > window_info[id].visual->red_mask)
4282 red=0;
4283 green+=green_bit;
4284 if (green > window_info[id].visual->green_mask)
4285 green=0;
4286 blue+=blue_bit;
4287 if (blue > window_info[id].visual->blue_mask)
4288 blue=0;
4289 }
4290 }
4291 (void) XQueryColors(display,window_info[id].colormap,colors,
4292 (int) number_colors);
4293 /*
4294 Append colormap to colormap list.
4295 */
cristy73bd4a52010-10-05 11:24:23 +00004296 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004297 if (p == (ColormapInfo *) NULL)
4298 return((Image *) NULL);
4299 p->colormap=window_info[id].colormap;
4300 p->colors=colors;
4301 p->next=colormap_info;
4302 colormap_info=p;
4303 }
4304 colors=p->colors;
4305 }
4306 /*
4307 Allocate image structure.
4308 */
4309 composite_image=AcquireImage((ImageInfo *) NULL);
4310 if (composite_image == (Image *) NULL)
4311 {
4312 XDestroyImage(ximage);
4313 return((Image *) NULL);
4314 }
4315 /*
4316 Convert X image to MIFF format.
4317 */
4318 if ((window_info[id].visual->klass != TrueColor) &&
4319 (window_info[id].visual->klass != DirectColor))
4320 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004321 composite_image->columns=(size_t) ximage->width;
4322 composite_image->rows=(size_t) ximage->height;
cristy3ed852e2009-09-05 21:47:34 +00004323 exception=(&composite_image->exception);
cristyc57f6942010-11-12 01:47:39 +00004324 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004325 switch (composite_image->storage_class)
4326 {
4327 case DirectClass:
4328 default:
4329 {
cristybb503372010-05-27 20:51:26 +00004330 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004331 color,
4332 index;
4333
cristybb503372010-05-27 20:51:26 +00004334 size_t
cristy3ed852e2009-09-05 21:47:34 +00004335 blue_mask,
4336 blue_shift,
4337 green_mask,
4338 green_shift,
4339 red_mask,
4340 red_shift;
4341
4342 /*
4343 Determine shift and mask for red, green, and blue.
4344 */
4345 red_mask=window_info[id].visual->red_mask;
4346 red_shift=0;
4347 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4348 {
4349 red_mask>>=1;
4350 red_shift++;
4351 }
4352 green_mask=window_info[id].visual->green_mask;
4353 green_shift=0;
4354 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4355 {
4356 green_mask>>=1;
4357 green_shift++;
4358 }
4359 blue_mask=window_info[id].visual->blue_mask;
4360 blue_shift=0;
4361 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4362 {
4363 blue_mask>>=1;
4364 blue_shift++;
4365 }
4366 /*
4367 Convert X image to DirectClass packets.
4368 */
4369 if ((number_colors != 0) &&
4370 (window_info[id].visual->klass == DirectColor))
4371 for (y=0; y < (int) composite_image->rows; y++)
4372 {
cristyc57f6942010-11-12 01:47:39 +00004373 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004374 composite_image->columns,1,exception);
4375 if (q == (PixelPacket *) NULL)
4376 break;
4377 for (x=0; x < (int) composite_image->columns; x++)
4378 {
4379 pixel=XGetPixel(ximage,x,y);
4380 index=(pixel >> red_shift) & red_mask;
4381 q->red=ScaleShortToQuantum(colors[index].red);
4382 index=(pixel >> green_shift) & green_mask;
4383 q->green=ScaleShortToQuantum(colors[index].green);
4384 index=(pixel >> blue_shift) & blue_mask;
4385 q->blue=ScaleShortToQuantum(colors[index].blue);
4386 q++;
4387 }
cristyc57f6942010-11-12 01:47:39 +00004388 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004389 break;
4390 }
4391 else
4392 for (y=0; y < (int) composite_image->rows; y++)
4393 {
cristyc57f6942010-11-12 01:47:39 +00004394 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004395 composite_image->columns,1,exception);
4396 if (q == (PixelPacket *) NULL)
4397 break;
4398 for (x=0; x < (int) composite_image->columns; x++)
4399 {
4400 pixel=XGetPixel(ximage,x,y);
4401 color=(pixel >> red_shift) & red_mask;
4402 color=(65535UL*color)/red_mask;
4403 q->red=ScaleShortToQuantum((unsigned short) color);
4404 color=(pixel >> green_shift) & green_mask;
4405 color=(65535UL*color)/green_mask;
4406 q->green=ScaleShortToQuantum((unsigned short) color);
4407 color=(pixel >> blue_shift) & blue_mask;
4408 color=(65535UL*color)/blue_mask;
4409 q->blue=ScaleShortToQuantum((unsigned short) color);
4410 q++;
4411 }
cristyc57f6942010-11-12 01:47:39 +00004412 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004413 break;
4414 }
4415 break;
4416 }
4417 case PseudoClass:
4418 {
4419 /*
4420 Create colormap.
4421 */
4422 if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
4423 {
4424 XDestroyImage(ximage);
4425 composite_image=DestroyImage(composite_image);
4426 return((Image *) NULL);
4427 }
4428 for (i=0; i < (int) composite_image->colors; i++)
4429 {
4430 composite_image->colormap[colors[i].pixel].red=
4431 ScaleShortToQuantum(colors[i].red);
4432 composite_image->colormap[colors[i].pixel].green=
4433 ScaleShortToQuantum(colors[i].green);
4434 composite_image->colormap[colors[i].pixel].blue=
4435 ScaleShortToQuantum(colors[i].blue);
4436 }
4437 /*
4438 Convert X image to PseudoClass packets.
4439 */
4440 for (y=0; y < (int) composite_image->rows; y++)
4441 {
cristyc57f6942010-11-12 01:47:39 +00004442 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4443 composite_image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00004444 if (q == (PixelPacket *) NULL)
4445 break;
cristyc57f6942010-11-12 01:47:39 +00004446 indexes=GetCacheViewAuthenticIndexQueue(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004447 for (x=0; x < (int) composite_image->columns; x++)
4448 {
4449 index=(IndexPacket) XGetPixel(ximage,x,y);
4450 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +00004451 *q++=composite_image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +00004452 }
cristyc57f6942010-11-12 01:47:39 +00004453 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004454 break;
4455 }
4456 break;
4457 }
4458 }
cristyc57f6942010-11-12 01:47:39 +00004459 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004460 XDestroyImage(ximage);
4461 if (image == (Image *) NULL)
4462 {
4463 image=composite_image;
4464 continue;
4465 }
4466 /*
4467 Composite any children in back-to-front order.
4468 */
4469 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4470 &x_offset,&y_offset,&child);
4471 x_offset-=(int) crop_info.x;
4472 if (x_offset < 0)
4473 x_offset=0;
4474 y_offset-=(int) crop_info.y;
4475 if (y_offset < 0)
4476 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004477 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
4478 x_offset,(ssize_t) y_offset);
cristy3ed852e2009-09-05 21:47:34 +00004479 }
4480 /*
4481 Relinquish resources.
4482 */
4483 while (colormap_info != (ColormapInfo *) NULL)
4484 {
4485 next=colormap_info->next;
4486 colormap_info->colors=(XColor *)
4487 RelinquishMagickMemory(colormap_info->colors);
4488 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4489 colormap_info=next;
4490 }
4491 /*
4492 Relinquish resources and restore initial state.
4493 */
4494 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4495 max_windows=0;
4496 number_windows=0;
4497 colormap_info=(ColormapInfo *) NULL;
4498 return(image);
4499 }
4500 return((Image *) NULL);
4501}
4502
4503/*
4504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4505% %
4506% %
4507% %
4508% X G e t W i n d o w I n f o %
4509% %
4510% %
4511% %
4512%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4513%
4514% XGetWindowInfo() initializes the XWindowInfo structure.
4515%
4516% The format of the XGetWindowInfo method is:
4517%
4518% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4519% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4520% XResourceInfo *resource_info,XWindowInfo *window)
4521% resource_info,window)
4522%
4523% A description of each parameter follows:
4524%
4525% o display: Specifies a connection to an X server; returned from
4526% XOpenDisplay.
4527%
4528% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4529% returned from XGetVisualInfo.
4530%
4531% o map_info: If map_type is specified, this structure is initialized
4532% with info from the Standard Colormap.
4533%
4534% o pixel: Specifies a pointer to a XPixelInfo structure.
4535%
4536% o font_info: Specifies a pointer to a XFontStruct structure.
4537%
4538% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4539%
4540*/
4541MagickExport void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4542 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4543 XResourceInfo *resource_info,XWindowInfo *window)
4544{
4545 /*
4546 Initialize window info.
4547 */
4548 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4549 assert(display != (Display *) NULL);
4550 assert(visual_info != (XVisualInfo *) NULL);
4551 assert(map_info != (XStandardColormap *) NULL);
4552 assert(pixel != (XPixelInfo *) NULL);
4553 assert(resource_info != (XResourceInfo *) NULL);
4554 assert(window != (XWindowInfo *) NULL);
4555 if (window->id != (Window) NULL)
4556 {
4557 if (window->cursor != (Cursor) NULL)
4558 (void) XFreeCursor(display,window->cursor);
4559 if (window->busy_cursor != (Cursor) NULL)
4560 (void) XFreeCursor(display,window->busy_cursor);
4561 if (window->highlight_stipple != (Pixmap) NULL)
4562 (void) XFreePixmap(display,window->highlight_stipple);
4563 if (window->shadow_stipple != (Pixmap) NULL)
4564 (void) XFreePixmap(display,window->shadow_stipple);
4565 if (window->name == (char *) NULL)
4566 window->name=AcquireString("");
4567 if (window->icon_name == (char *) NULL)
4568 window->icon_name=AcquireString("");
4569 }
4570 else
4571 {
4572 /*
4573 Initialize these attributes just once.
4574 */
4575 window->id=(Window) NULL;
4576 if (window->name == (char *) NULL)
4577 window->name=AcquireString("");
4578 if (window->icon_name == (char *) NULL)
4579 window->icon_name=AcquireString("");
4580 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4581 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4582 window->ximage=(XImage *) NULL;
4583 window->matte_image=(XImage *) NULL;
4584 window->pixmap=(Pixmap) NULL;
4585 window->matte_pixmap=(Pixmap) NULL;
4586 window->mapped=MagickFalse;
4587 window->stasis=MagickFalse;
4588 window->shared_memory=MagickTrue;
4589 window->segment_info=(void *) NULL;
4590#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4591 {
4592 XShmSegmentInfo
4593 *segment_info;
4594
4595 if (window->segment_info == (void *) NULL)
4596 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4597 segment_info=(XShmSegmentInfo *) window->segment_info;
4598 segment_info[0].shmid=(-1);
4599 segment_info[0].shmaddr=(char *) NULL;
4600 segment_info[1].shmid=(-1);
4601 segment_info[1].shmaddr=(char *) NULL;
4602 }
4603#endif
4604 }
4605 /*
4606 Initialize these attributes every time function is called.
4607 */
4608 window->screen=visual_info->screen;
4609 window->root=XRootWindow(display,visual_info->screen);
4610 window->visual=visual_info->visual;
4611 window->storage_class=(unsigned int) visual_info->klass;
4612 window->depth=(unsigned int) visual_info->depth;
4613 window->visual_info=visual_info;
4614 window->map_info=map_info;
4615 window->pixel_info=pixel;
4616 window->font_info=font_info;
4617 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4618 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4619 window->geometry=(char *) NULL;
4620 window->icon_geometry=(char *) NULL;
4621 if (resource_info->icon_geometry != (char *) NULL)
4622 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4623 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004624 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004625 window->width=1;
4626 window->height=1;
4627 window->min_width=1;
4628 window->min_height=1;
4629 window->width_inc=1;
4630 window->height_inc=1;
4631 window->border_width=resource_info->border_width;
4632 window->annotate_context=pixel->annotate_context;
4633 window->highlight_context=pixel->highlight_context;
4634 window->widget_context=pixel->widget_context;
4635 window->shadow_stipple=(Pixmap) NULL;
4636 window->highlight_stipple=(Pixmap) NULL;
4637 window->use_pixmap=MagickTrue;
4638 window->immutable=MagickFalse;
4639 window->shape=MagickFalse;
4640 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004641 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004642 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4643 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4644 window->attributes.background_pixel=pixel->background_color.pixel;
4645 window->attributes.background_pixmap=(Pixmap) NULL;
4646 window->attributes.bit_gravity=ForgetGravity;
4647 window->attributes.backing_store=WhenMapped;
4648 window->attributes.save_under=MagickTrue;
4649 window->attributes.border_pixel=pixel->border_color.pixel;
4650 window->attributes.colormap=map_info->colormap;
4651 window->attributes.cursor=window->cursor;
4652 window->attributes.do_not_propagate_mask=NoEventMask;
4653 window->attributes.event_mask=NoEventMask;
4654 window->attributes.override_redirect=MagickFalse;
4655 window->attributes.win_gravity=NorthWestGravity;
4656 window->orphan=MagickFalse;
4657}
4658
4659/*
4660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4661% %
4662% %
4663% %
4664% X H i g h l i g h t E l l i p s e %
4665% %
4666% %
4667% %
4668%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4669%
4670% XHighlightEllipse() puts a border on the X server around a region defined by
4671% highlight_info.
4672%
4673% The format of the XHighlightEllipse method is:
4674%
4675% void XHighlightEllipse(Display *display,Window window,
4676% GC annotate_context,const RectangleInfo *highlight_info)
4677%
4678% A description of each parameter follows:
4679%
4680% o display: Specifies a connection to an X server; returned from
4681% XOpenDisplay.
4682%
4683% o window: Specifies a pointer to a Window structure.
4684%
4685% o annotate_context: Specifies a pointer to a GC structure.
4686%
4687% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4688% contains the extents of any highlighting rectangle.
4689%
4690*/
4691MagickExport void XHighlightEllipse(Display *display,Window window,
4692 GC annotate_context,const RectangleInfo *highlight_info)
4693{
4694 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4695 assert(display != (Display *) NULL);
4696 assert(window != (Window) NULL);
4697 assert(annotate_context != (GC) NULL);
4698 assert(highlight_info != (RectangleInfo *) NULL);
4699 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4700 return;
4701 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4702 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4703 (unsigned int) highlight_info->height-1,0,360*64);
4704 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4705 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4706 (unsigned int) highlight_info->height-3,0,360*64);
4707}
4708
4709/*
4710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4711% %
4712% %
4713% %
4714% X H i g h l i g h t L i n e %
4715% %
4716% %
4717% %
4718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4719%
4720% XHighlightLine() puts a border on the X server around a region defined by
4721% highlight_info.
4722%
4723% The format of the XHighlightLine method is:
4724%
4725% void XHighlightLine(Display *display,Window window,GC annotate_context,
4726% const XSegment *highlight_info)
4727%
4728% A description of each parameter follows:
4729%
4730% o display: Specifies a connection to an X server; returned from
4731% XOpenDisplay.
4732%
4733% o window: Specifies a pointer to a Window structure.
4734%
4735% o annotate_context: Specifies a pointer to a GC structure.
4736%
4737% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4738% contains the extents of any highlighting rectangle.
4739%
4740*/
4741MagickExport void XHighlightLine(Display *display,Window window,
4742 GC annotate_context,const XSegment *highlight_info)
4743{
4744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4745 assert(display != (Display *) NULL);
4746 assert(window != (Window) NULL);
4747 assert(annotate_context != (GC) NULL);
4748 assert(highlight_info != (XSegment *) NULL);
4749 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4750 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4751}
4752
4753/*
4754%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4755% %
4756% %
4757% %
4758% X H i g h l i g h t R e c t a n g l e %
4759% %
4760% %
4761% %
4762%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4763%
4764% XHighlightRectangle() puts a border on the X server around a region defined
4765% by highlight_info.
4766%
4767% The format of the XHighlightRectangle method is:
4768%
4769% void XHighlightRectangle(Display *display,Window window,
4770% GC annotate_context,const RectangleInfo *highlight_info)
4771%
4772% A description of each parameter follows:
4773%
4774% o display: Specifies a connection to an X server; returned from
4775% XOpenDisplay.
4776%
4777% o window: Specifies a pointer to a Window structure.
4778%
4779% o annotate_context: Specifies a pointer to a GC structure.
4780%
4781% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4782% contains the extents of any highlighting rectangle.
4783%
4784*/
4785MagickExport void XHighlightRectangle(Display *display,Window window,
4786 GC annotate_context,const RectangleInfo *highlight_info)
4787{
4788 assert(display != (Display *) NULL);
4789 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4790 assert(window != (Window) NULL);
4791 assert(annotate_context != (GC) NULL);
4792 assert(highlight_info != (RectangleInfo *) NULL);
4793 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4794 return;
4795 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4796 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4797 (unsigned int) highlight_info->height-1);
4798 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4799 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4800 (unsigned int) highlight_info->height-3);
4801}
4802
4803/*
4804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4805% %
4806% %
4807% %
4808% X I m p o r t I m a g e %
4809% %
4810% %
4811% %
4812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4813%
4814% XImportImage() reads an image from an X window.
4815%
4816% The format of the XImportImage method is:
4817%
4818% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4819%
4820% A description of each parameter follows:
4821%
4822% o image_info: the image info.
4823%
4824% o ximage_info: Specifies a pointer to an XImportInfo structure.
4825%
4826*/
4827MagickExport Image *XImportImage(const ImageInfo *image_info,
4828 XImportInfo *ximage_info)
4829{
4830 Colormap
4831 *colormaps;
4832
4833 Display
4834 *display;
4835
4836 Image
4837 *image;
4838
4839 int
4840 number_colormaps,
4841 number_windows,
4842 x;
4843
4844 RectangleInfo
4845 crop_info;
4846
4847 Status
4848 status;
4849
4850 Window
4851 *children,
4852 client,
4853 prior_target,
4854 root,
4855 target;
4856
4857 XTextProperty
4858 window_name;
4859
4860 /*
4861 Open X server connection.
4862 */
4863 assert(image_info != (const ImageInfo *) NULL);
4864 assert(image_info->signature == MagickSignature);
4865 if (image_info->debug != MagickFalse)
4866 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4867 image_info->filename);
4868 assert(ximage_info != (XImportInfo *) NULL);
4869 display=XOpenDisplay(image_info->server_name);
4870 if (display == (Display *) NULL)
4871 {
4872 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4873 XDisplayName(image_info->server_name));
4874 return((Image *) NULL);
4875 }
4876 /*
4877 Set our forgiving exception handler.
4878 */
4879 (void) XSetErrorHandler(XError);
4880 /*
4881 Select target window.
4882 */
4883 crop_info.x=0;
4884 crop_info.y=0;
4885 crop_info.width=0;
4886 crop_info.height=0;
4887 root=XRootWindow(display,XDefaultScreen(display));
4888 target=(Window) NULL;
4889 if ((image_info->filename != (char *) NULL) &&
4890 (*image_info->filename != '\0'))
4891 {
4892 if (LocaleCompare(image_info->filename,"root") == 0)
4893 target=root;
4894 else
4895 {
4896 /*
4897 Select window by ID or name.
4898 */
4899 if (isdigit((unsigned char) *image_info->filename) != 0)
4900 target=XWindowByID(display,root,(Window)
4901 strtol(image_info->filename,(char **) NULL,0));
4902 if (target == (Window) NULL)
4903 target=XWindowByName(display,root,image_info->filename);
4904 if (target == (Window) NULL)
4905 ThrowXWindowFatalException(XServerError,
4906 "NoWindowWithSpecifiedIDExists",image_info->filename);
4907 }
4908 }
4909 /*
4910 If target window is not defined, interactively select one.
4911 */
4912 prior_target=target;
4913 if (target == (Window) NULL)
4914 target=XSelectWindow(display,&crop_info);
4915 if (target == (Window) NULL)
4916 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4917 image_info->filename);
4918 client=target; /* obsolete */
4919 if (target != root)
4920 {
4921 unsigned int
4922 d;
4923
4924 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4925 if (status != False)
4926 {
4927 for ( ; ; )
4928 {
4929 Window
4930 parent;
4931
4932 /*
4933 Find window manager frame.
4934 */
4935 status=XQueryTree(display,target,&root,&parent,&children,&d);
4936 if ((status != False) && (children != (Window *) NULL))
4937 (void) XFree((char *) children);
4938 if ((status == False) || (parent == (Window) NULL) ||
4939 (parent == root))
4940 break;
4941 target=parent;
4942 }
4943 /*
4944 Get client window.
4945 */
4946 client=XClientWindow(display,target);
4947 if (ximage_info->frame == MagickFalse)
4948 target=client;
4949 if ((ximage_info->frame == MagickFalse) &&
4950 (prior_target != MagickFalse))
4951 target=prior_target;
4952 XDelay(display,SuspendTime << 4);
4953 }
4954 }
4955 if (ximage_info->screen)
4956 {
4957 int
4958 y;
4959
4960 Window
4961 child;
4962
4963 XWindowAttributes
4964 window_attributes;
4965
4966 /*
4967 Obtain window image directly from screen.
4968 */
4969 status=XGetWindowAttributes(display,target,&window_attributes);
4970 if (status == False)
4971 {
4972 ThrowXWindowFatalException(XServerError,
4973 "UnableToReadXWindowAttributes",image_info->filename);
4974 (void) XCloseDisplay(display);
4975 return((Image *) NULL);
4976 }
4977 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00004978 crop_info.x=(ssize_t) x;
4979 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00004980 crop_info.width=(size_t) window_attributes.width;
4981 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00004982 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00004983 {
4984 /*
4985 Include border in image.
4986 */
4987 crop_info.x-=window_attributes.border_width;
4988 crop_info.y-=window_attributes.border_width;
4989 crop_info.width+=window_attributes.border_width << 1;
4990 crop_info.height+=window_attributes.border_width << 1;
4991 }
4992 target=root;
4993 }
4994 /*
4995 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
4996 */
4997 number_windows=0;
4998 status=XGetWMColormapWindows(display,target,&children,&number_windows);
4999 if ((status == True) && (number_windows > 0))
5000 {
5001 ximage_info->descend=MagickTrue;
5002 (void) XFree ((char *) children);
5003 }
5004 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5005 if (number_colormaps > 0)
5006 {
5007 if (number_colormaps > 1)
5008 ximage_info->descend=MagickTrue;
5009 (void) XFree((char *) colormaps);
5010 }
5011 /*
5012 Alert the user not to alter the screen.
5013 */
5014 if (ximage_info->silent == MagickFalse)
5015 (void) XBell(display,0);
5016 /*
5017 Get image by window id.
5018 */
5019 (void) XGrabServer(display);
5020 image=XGetWindowImage(display,target,ximage_info->borders,
5021 ximage_info->descend ? 1U : 0U);
5022 (void) XUngrabServer(display);
5023 if (image == (Image *) NULL)
5024 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5025 image_info->filename)
5026 else
5027 {
5028 (void) CopyMagickString(image->filename,image_info->filename,
5029 MaxTextExtent);
5030 if ((crop_info.width != 0) && (crop_info.height != 0))
5031 {
5032 Image
5033 *clone_image,
5034 *crop_image;
5035
5036 /*
5037 Crop image as defined by the cropping rectangle.
5038 */
5039 clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5040 if (clone_image != (Image *) NULL)
5041 {
5042 crop_image=CropImage(clone_image,&crop_info,&image->exception);
5043 if (crop_image != (Image *) NULL)
5044 {
5045 image=DestroyImage(image);
5046 image=crop_image;
5047 }
5048 }
5049 }
5050 status=XGetWMName(display,target,&window_name);
5051 if (status == True)
5052 {
5053 if ((image_info->filename != (char *) NULL) &&
5054 (*image_info->filename == '\0'))
5055 (void) CopyMagickString(image->filename,(char *) window_name.value,
5056 (size_t) window_name.nitems+1);
5057 (void) XFree((void *) window_name.value);
5058 }
5059 }
5060 if (ximage_info->silent == MagickFalse)
5061 {
5062 /*
5063 Alert the user we're done.
5064 */
5065 (void) XBell(display,0);
5066 (void) XBell(display,0);
5067 }
5068 (void) XCloseDisplay(display);
5069 return(image);
5070}
5071
5072/*
5073%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5074% %
5075% %
5076% %
5077% X I n i t i a l i z e W i n d o w s %
5078% %
5079% %
5080% %
5081%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5082%
5083% XInitializeWindows() initializes the XWindows structure.
5084%
5085% The format of the XInitializeWindows method is:
5086%
5087% XWindows *XInitializeWindows(Display *display,
5088% XResourceInfo *resource_info)
5089%
5090% A description of each parameter follows:
5091%
5092% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5093%
5094% o display: Specifies a connection to an X server; returned from
5095% XOpenDisplay.
5096%
5097% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5098%
5099*/
5100MagickExport XWindows *XInitializeWindows(Display *display,
5101 XResourceInfo *resource_info)
5102{
5103 Window
5104 root_window;
5105
5106 XWindows
5107 *windows;
5108
5109 /*
5110 Allocate windows structure.
5111 */
cristy73bd4a52010-10-05 11:24:23 +00005112 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005113 if (windows == (XWindows *) NULL)
5114 {
5115 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5116 "...");
5117 return((XWindows *) NULL);
5118 }
5119 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5120 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5121 sizeof(*windows->pixel_info));
5122 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5123 sizeof(*windows->icon_pixel));
5124 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5125 sizeof(*windows->icon_resources));
5126 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5127 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5128 (windows->icon_resources == (XResourceInfo *) NULL))
5129 {
5130 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5131 "...");
5132 return((XWindows *) NULL);
5133 }
5134 /*
5135 Initialize windows structure.
5136 */
5137 windows->display=display;
5138 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5139 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5140 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5141 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5142 windows->im_remote_command=
5143 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5144 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5145 windows->im_update_colormap=
5146 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5147 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5148 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5149 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5150 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5151 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005152#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005153 (void) XSynchronize(display,IsWindows95());
5154#endif
5155 if (IsEventLogging())
5156 {
5157 (void) XSynchronize(display,MagickTrue);
5158 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005159 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005160 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5161 (void) LogMagickEvent(X11Event,GetMagickModule(),
5162 " Window Manager: 0x%lx",windows->wm_protocols);
5163 (void) LogMagickEvent(X11Event,GetMagickModule(),
5164 " delete window: 0x%lx",windows->wm_delete_window);
5165 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5166 windows->wm_take_focus);
5167 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5168 windows->im_protocols);
5169 (void) LogMagickEvent(X11Event,GetMagickModule(),
5170 " remote command: 0x%lx",windows->im_remote_command);
5171 (void) LogMagickEvent(X11Event,GetMagickModule(),
5172 " update widget: 0x%lx",windows->im_update_widget);
5173 (void) LogMagickEvent(X11Event,GetMagickModule(),
5174 " update colormap: 0x%lx",windows->im_update_colormap);
5175 (void) LogMagickEvent(X11Event,GetMagickModule(),
5176 " former image: 0x%lx",windows->im_former_image);
5177 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5178 windows->im_next_image);
5179 (void) LogMagickEvent(X11Event,GetMagickModule(),
5180 " retain colors: 0x%lx",windows->im_retain_colors);
5181 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5182 windows->im_exit);
5183 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5184 windows->dnd_protocols);
5185 }
5186 /*
5187 Allocate standard colormap.
5188 */
5189 windows->map_info=XAllocStandardColormap();
5190 windows->icon_map=XAllocStandardColormap();
5191 if ((windows->map_info == (XStandardColormap *) NULL) ||
5192 (windows->icon_map == (XStandardColormap *) NULL))
5193 ThrowXWindowFatalException(ResourceLimitFatalError,
5194 "MemoryAllocationFailed","...");
5195 windows->map_info->colormap=(Colormap) NULL;
5196 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005197 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005198 windows->pixel_info->annotate_context=(GC) NULL;
5199 windows->pixel_info->highlight_context=(GC) NULL;
5200 windows->pixel_info->widget_context=(GC) NULL;
5201 windows->font_info=(XFontStruct *) NULL;
5202 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005203 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005204 /*
5205 Allocate visual.
5206 */
5207 *windows->icon_resources=(*resource_info);
5208 windows->icon_resources->visual_type=(char *) "default";
5209 windows->icon_resources->colormap=SharedColormap;
5210 windows->visual_info=
5211 XBestVisualInfo(display,windows->map_info,resource_info);
5212 windows->icon_visual=
5213 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5214 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5215 (windows->icon_visual == (XVisualInfo *) NULL))
5216 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5217 resource_info->visual_type);
5218 if (IsEventLogging())
5219 {
5220 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5221 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5222 windows->visual_info->visualid);
5223 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5224 XVisualClassName(windows->visual_info->klass));
5225 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5226 windows->visual_info->depth);
5227 (void) LogMagickEvent(X11Event,GetMagickModule(),
5228 " size of colormap: %d entries",windows->visual_info->colormap_size);
5229 (void) LogMagickEvent(X11Event,GetMagickModule(),
5230 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5231 windows->visual_info->red_mask,windows->visual_info->green_mask,
5232 windows->visual_info->blue_mask);
5233 (void) LogMagickEvent(X11Event,GetMagickModule(),
5234 " significant bits in color: %d bits",
5235 windows->visual_info->bits_per_rgb);
5236 }
5237 /*
5238 Allocate class and manager hints.
5239 */
5240 windows->class_hints=XAllocClassHint();
5241 windows->manager_hints=XAllocWMHints();
5242 if ((windows->class_hints == (XClassHint *) NULL) ||
5243 (windows->manager_hints == (XWMHints *) NULL))
5244 ThrowXWindowFatalException(ResourceLimitFatalError,
5245 "MemoryAllocationFailed","...");
5246 /*
5247 Determine group leader if we have one.
5248 */
5249 root_window=XRootWindow(display,windows->visual_info->screen);
5250 windows->group_leader.id=(Window) NULL;
5251 if (resource_info->window_group != (char *) NULL)
5252 {
5253 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5254 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5255 strtol((char *) resource_info->window_group,(char **) NULL,0));
5256 if (windows->group_leader.id == (Window) NULL)
5257 windows->group_leader.id=
5258 XWindowByName(display,root_window,resource_info->window_group);
5259 }
5260 return(windows);
5261}
5262
5263/*
5264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5265% %
5266% %
5267% %
5268% X M a k e C u r s o r %
5269% %
5270% %
5271% %
5272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5273%
5274% XMakeCursor() creates a crosshairs X11 cursor.
5275%
5276% The format of the XMakeCursor method is:
5277%
5278% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5279% char *background_color,char *foreground_color)
5280%
5281% A description of each parameter follows:
5282%
5283% o display: Specifies a connection to an X server; returned from
5284% XOpenDisplay.
5285%
5286% o window: Specifies the ID of the window for which the cursor is
5287% assigned.
5288%
5289% o colormap: Specifies the ID of the colormap from which the background
5290% and foreground color will be retrieved.
5291%
5292% o background_color: Specifies the color to use for the cursor background.
5293%
5294% o foreground_color: Specifies the color to use for the cursor foreground.
5295%
5296*/
5297MagickExport Cursor XMakeCursor(Display *display,Window window,
5298 Colormap colormap,char *background_color,char *foreground_color)
5299{
5300#define scope_height 17
5301#define scope_x_hot 8
5302#define scope_y_hot 8
5303#define scope_width 17
5304
5305 static const unsigned char
5306 scope_bits[] =
5307 {
5308 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5309 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5310 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5311 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5312 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5313 },
5314 scope_mask_bits[] =
5315 {
5316 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5317 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5318 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5319 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5320 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5321 };
5322
5323 Cursor
5324 cursor;
5325
5326 Pixmap
5327 mask,
5328 source;
5329
5330 XColor
5331 background,
5332 foreground;
5333
5334 assert(display != (Display *) NULL);
5335 assert(window != (Window) NULL);
5336 assert(colormap != (Colormap) NULL);
5337 assert(background_color != (char *) NULL);
5338 assert(foreground_color != (char *) NULL);
5339 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5340 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5341 scope_height);
5342 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5343 scope_width,scope_height);
5344 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5345 {
5346 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5347 return((Cursor) NULL);
5348 }
5349 (void) XParseColor(display,colormap,background_color,&background);
5350 (void) XParseColor(display,colormap,foreground_color,&foreground);
5351 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5352 scope_x_hot,scope_y_hot);
5353 (void) XFreePixmap(display,source);
5354 (void) XFreePixmap(display,mask);
5355 return(cursor);
5356}
5357
5358/*
5359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5360% %
5361% %
5362% %
5363% X M a k e I m a g e %
5364% %
5365% %
5366% %
5367%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5368%
5369% XMakeImage() creates an X11 image. If the image size differs from the X11
5370% image size, the image is first resized.
5371%
5372% The format of the XMakeImage method is:
5373%
5374% MagickBooleanType XMakeImage(Display *display,
5375% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5376% unsigned int width,unsigned int height)
5377%
5378% A description of each parameter follows:
5379%
5380% o display: Specifies a connection to an X server; returned from
5381% XOpenDisplay.
5382%
5383% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5384%
5385% o window: Specifies a pointer to a XWindowInfo structure.
5386%
5387% o image: the image.
5388%
5389% o width: Specifies the width in pixels of the rectangular area to
5390% display.
5391%
5392% o height: Specifies the height in pixels of the rectangular area to
5393% display.
5394%
5395*/
5396MagickExport MagickBooleanType XMakeImage(Display *display,
5397 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5398 unsigned int width,unsigned int height)
5399{
5400#define CheckOverflowException(length,width,height) \
5401 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5402
5403 int
5404 depth,
5405 format;
5406
5407 size_t
5408 length;
5409
5410 XImage
5411 *matte_image,
5412 *ximage;
5413
5414 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5415 assert(display != (Display *) NULL);
5416 assert(resource_info != (XResourceInfo *) NULL);
5417 assert(window != (XWindowInfo *) NULL);
5418 assert(width != 0);
5419 assert(height != 0);
5420 if ((window->width == 0) || (window->height == 0))
5421 return(MagickFalse);
5422 /*
5423 Apply user transforms to the image.
5424 */
5425 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5426 (void) XFlush(display);
5427 depth=(int) window->depth;
5428 if (window->destroy)
5429 window->image=DestroyImage(window->image);
5430 window->image=image;
5431 window->destroy=MagickFalse;
5432 if (window->image != (Image *) NULL)
5433 {
5434 if (window->crop_geometry != (char *) NULL)
5435 {
5436 Image
5437 *crop_image;
5438
5439 RectangleInfo
5440 crop_info;
5441
5442 /*
5443 Crop image.
5444 */
5445 window->image->page.x=0;
5446 window->image->page.y=0;
5447 (void) ParsePageGeometry(window->image,window->crop_geometry,
5448 &crop_info,&image->exception);
5449 crop_image=CropImage(window->image,&crop_info,&image->exception);
5450 if (crop_image != (Image *) NULL)
5451 {
5452 if (window->image != image)
5453 window->image=DestroyImage(window->image);
5454 window->image=crop_image;
5455 window->destroy=MagickTrue;
5456 }
5457 }
5458 if ((width != (unsigned int) window->image->columns) ||
5459 (height != (unsigned int) window->image->rows))
5460 {
5461 Image
5462 *resize_image;
5463
5464 /*
5465 Resize image.
5466 */
5467 resize_image=NewImageList();
5468 if (window->pixel_info->colors != 0)
5469 resize_image=SampleImage(window->image,width,height,
5470 &image->exception);
5471 else
5472 resize_image=ThumbnailImage(window->image,width,height,
5473 &image->exception);
5474 if (resize_image != (Image *) NULL)
5475 {
5476 if (window->image != image)
5477 window->image=DestroyImage(window->image);
5478 window->image=resize_image;
5479 window->destroy=MagickTrue;
5480 }
5481 }
5482 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005483 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005484 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005485 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005486 }
5487 /*
5488 Create X image.
5489 */
5490 ximage=(XImage *) NULL;
5491 format=(depth == 1) ? XYBitmap : ZPixmap;
5492#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5493 if (window->shared_memory != MagickFalse)
5494 {
5495 XShmSegmentInfo
5496 *segment_info;
5497
5498 segment_info=(XShmSegmentInfo *) window->segment_info;
5499 segment_info[1].shmid=(-1);
5500 segment_info[1].shmaddr=(char *) NULL;
5501 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5502 (char *) NULL,&segment_info[1],width,height);
5503 if (ximage == (XImage *) NULL)
5504 window->shared_memory=MagickFalse;
5505 length=(size_t) ximage->bytes_per_line*ximage->height;
5506 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5507 window->shared_memory=MagickFalse;
5508 if (window->shared_memory != MagickFalse)
5509 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5510 if (window->shared_memory != MagickFalse)
5511 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5512 if (segment_info[1].shmid < 0)
5513 window->shared_memory=MagickFalse;
5514 if (window->shared_memory != MagickFalse)
5515 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5516 else
5517 {
5518 if (ximage != (XImage *) NULL)
5519 XDestroyImage(ximage);
5520 ximage=(XImage *) NULL;
5521 if (segment_info[1].shmaddr)
5522 {
5523 (void) shmdt(segment_info[1].shmaddr);
5524 segment_info[1].shmaddr=(char *) NULL;
5525 }
5526 if (segment_info[1].shmid >= 0)
5527 {
5528 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5529 segment_info[1].shmid=(-1);
5530 }
5531 }
5532 }
5533#endif
5534 /*
5535 Allocate X image pixel data.
5536 */
5537#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5538 if (window->shared_memory)
5539 {
5540 Status
5541 status;
5542
5543 XShmSegmentInfo
5544 *segment_info;
5545
5546 (void) XSync(display,MagickFalse);
5547 xerror_alert=MagickFalse;
5548 segment_info=(XShmSegmentInfo *) window->segment_info;
5549 ximage->data=segment_info[1].shmaddr;
5550 segment_info[1].readOnly=MagickFalse;
5551 status=XShmAttach(display,&segment_info[1]);
5552 if (status != False)
5553 (void) XSync(display,MagickFalse);
5554 if ((status == False) || (xerror_alert != MagickFalse))
5555 {
5556 window->shared_memory=MagickFalse;
5557 if (status != False)
5558 XShmDetach(display,&segment_info[1]);
5559 if (ximage != (XImage *) NULL)
5560 {
5561 ximage->data=NULL;
5562 XDestroyImage(ximage);
5563 ximage=(XImage *) NULL;
5564 }
5565 if (segment_info[1].shmid >= 0)
5566 {
5567 if (segment_info[1].shmaddr != NULL)
5568 (void) shmdt(segment_info[1].shmaddr);
5569 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5570 segment_info[1].shmid=(-1);
5571 segment_info[1].shmaddr=(char *) NULL;
5572 }
5573 }
5574 }
5575#endif
5576 if (window->shared_memory == MagickFalse)
5577 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5578 (char *) NULL,width,height,XBitmapPad(display),0);
5579 if (ximage == (XImage *) NULL)
5580 {
5581 /*
5582 Unable to create X image.
5583 */
5584 (void) XCheckDefineCursor(display,window->id,window->cursor);
5585 return(MagickFalse);
5586 }
5587 length=(size_t) ximage->bytes_per_line*ximage->height;
5588 if (IsEventLogging())
5589 {
5590 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5591 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5592 ximage->width,ximage->height);
5593 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5594 ximage->format);
5595 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5596 ximage->byte_order);
5597 (void) LogMagickEvent(X11Event,GetMagickModule(),
5598 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5599 ximage->bitmap_bit_order,ximage->bitmap_pad);
5600 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5601 ximage->depth);
5602 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5603 ximage->bytes_per_line);
5604 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5605 ximage->bits_per_pixel);
5606 (void) LogMagickEvent(X11Event,GetMagickModule(),
5607 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5608 ximage->green_mask,ximage->blue_mask);
5609 }
5610 if (window->shared_memory == MagickFalse)
5611 {
5612 if (ximage->format != XYBitmap)
5613 ximage->data=(char *) AcquireQuantumMemory((size_t)
5614 ximage->bytes_per_line,(size_t) ximage->height);
5615 else
5616 ximage->data=(char *) AcquireQuantumMemory((size_t)
5617 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5618 }
5619 if (ximage->data == (char *) NULL)
5620 {
5621 /*
5622 Unable to allocate pixel data.
5623 */
5624 XDestroyImage(ximage);
5625 ximage=(XImage *) NULL;
5626 (void) XCheckDefineCursor(display,window->id,window->cursor);
5627 return(MagickFalse);
5628 }
5629 if (window->ximage != (XImage *) NULL)
5630 {
5631 /*
5632 Destroy previous X image.
5633 */
5634 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5635#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5636 if (window->segment_info != (XShmSegmentInfo *) NULL)
5637 {
5638 XShmSegmentInfo
5639 *segment_info;
5640
5641 segment_info=(XShmSegmentInfo *) window->segment_info;
5642 if (segment_info[0].shmid >= 0)
5643 {
5644 (void) XSync(display,MagickFalse);
5645 (void) XShmDetach(display,&segment_info[0]);
5646 (void) XSync(display,MagickFalse);
5647 if (segment_info[0].shmaddr != (char *) NULL)
5648 (void) shmdt(segment_info[0].shmaddr);
5649 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5650 segment_info[0].shmid=(-1);
5651 segment_info[0].shmaddr=(char *) NULL;
5652 window->ximage->data=(char *) NULL;
5653 }
5654 }
5655#endif
5656 if (window->ximage->data != (char *) NULL)
5657 free(window->ximage->data);
5658 window->ximage->data=(char *) NULL;
5659 XDestroyImage(window->ximage);
5660 window->ximage=(XImage *) NULL;
5661 }
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 segment_info[0]=segment_info[1];
5670 }
5671#endif
5672 window->ximage=ximage;
5673 matte_image=(XImage *) NULL;
5674 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5675 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005676 ((int) width <= XDisplayWidth(display,window->screen)) &&
5677 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005678 {
5679 /*
5680 Create matte image.
5681 */
5682 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5683 (char *) NULL,width,height,XBitmapPad(display),0);
5684 if (IsEventLogging())
5685 {
5686 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5687 (void) LogMagickEvent(X11Event,GetMagickModule(),
5688 " width, height: %dx%d",matte_image->width,matte_image->height);
5689 }
5690 if (matte_image != (XImage *) NULL)
5691 {
5692 /*
5693 Allocate matte image pixel data.
5694 */
5695 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5696 matte_image->bytes_per_line*matte_image->depth,
5697 (size_t) matte_image->height);
5698 if (matte_image->data == (char *) NULL)
5699 {
5700 XDestroyImage(matte_image);
5701 matte_image=(XImage *) NULL;
5702 }
5703 }
5704 }
5705 if (window->matte_image != (XImage *) NULL)
5706 {
5707 /*
5708 Free matte image.
5709 */
5710 if (window->matte_image->data != (char *) NULL)
5711 free(window->matte_image->data);
5712 window->matte_image->data=(char *) NULL;
5713 XDestroyImage(window->matte_image);
5714 window->matte_image=(XImage *) NULL;
5715 }
5716 window->matte_image=matte_image;
5717 if (window->matte_pixmap != (Pixmap) NULL)
5718 {
5719 (void) XFreePixmap(display,window->matte_pixmap);
5720 window->matte_pixmap=(Pixmap) NULL;
5721#if defined(MAGICKCORE_HAVE_SHAPE)
5722 if (window->shape != MagickFalse)
5723 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5724#endif
5725 }
5726 window->stasis=MagickFalse;
5727 /*
5728 Convert pixels to X image data.
5729 */
5730 if (window->image != (Image *) NULL)
5731 {
5732 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5733 (ximage->bitmap_bit_order == LSBFirst)))
5734 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5735 matte_image);
5736 else
5737 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5738 matte_image);
5739 }
5740 if (window->matte_image != (XImage *) NULL)
5741 {
5742 /*
5743 Create matte pixmap.
5744 */
5745 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5746 if (window->matte_pixmap != (Pixmap) NULL)
5747 {
5748 GC
5749 graphics_context;
5750
5751 XGCValues
5752 context_values;
5753
5754 /*
5755 Copy matte image to matte pixmap.
5756 */
5757 context_values.background=1;
5758 context_values.foreground=0;
5759 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005760 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005761 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5762 window->matte_image,0,0,0,0,width,height);
5763 (void) XFreeGC(display,graphics_context);
5764#if defined(MAGICKCORE_HAVE_SHAPE)
5765 if (window->shape != MagickFalse)
5766 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5767 window->matte_pixmap,ShapeSet);
5768#endif
5769 }
5770 }
5771 (void) XMakePixmap(display,resource_info,window);
5772 /*
5773 Restore cursor.
5774 */
5775 (void) XCheckDefineCursor(display,window->id,window->cursor);
5776 return(MagickTrue);
5777}
5778
5779/*
5780%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5781% %
5782% %
5783% %
5784+ X M a k e I m a g e L S B F i r s t %
5785% %
5786% %
5787% %
5788%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5789%
5790% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5791% pixels are copied in least-significant bit and byte first order. The
5792% server's scanline pad is respected. Rather than using one or two general
5793% cases, many special cases are found here to help speed up the image
5794% conversion.
5795%
5796% The format of the XMakeImageLSBFirst method is:
5797%
5798% void XMakeImageLSBFirst(Display *display,XWindows *windows)
5799%
5800% A description of each parameter follows:
5801%
5802% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5803%
5804% o window: Specifies a pointer to a XWindowInfo structure.
5805%
5806% o image: the image.
5807%
5808% o ximage: Specifies a pointer to a XImage structure; returned from
5809% XCreateImage.
5810%
5811% o matte_image: Specifies a pointer to a XImage structure; returned from
5812% XCreateImage.
5813%
5814*/
5815static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5816 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5817{
cristyc57f6942010-11-12 01:47:39 +00005818 CacheView
5819 *canvas_view;
5820
cristy3ed852e2009-09-05 21:47:34 +00005821 Image
5822 *canvas;
5823
5824 int
5825 y;
5826
5827 register const IndexPacket
5828 *indexes;
5829
5830 register const PixelPacket
5831 *p;
5832
5833 register int
5834 x;
5835
5836 register unsigned char
5837 *q;
5838
5839 unsigned char
5840 bit,
5841 byte;
5842
5843 unsigned int
5844 scanline_pad;
5845
cristyf2faecf2010-05-28 19:19:36 +00005846 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005847 pixel,
5848 *pixels;
5849
5850 XStandardColormap
5851 *map_info;
5852
5853 assert(resource_info != (XResourceInfo *) NULL);
5854 assert(window != (XWindowInfo *) NULL);
5855 assert(image != (Image *) NULL);
5856 if (image->debug != MagickFalse)
5857 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5858 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005859 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005860 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005861 {
5862 char
5863 size[MaxTextExtent];
5864
5865 Image
5866 *pattern;
5867
5868 ImageInfo
5869 *image_info;
5870
5871 image_info=AcquireImageInfo();
5872 (void) CopyMagickString(image_info->filename,
5873 resource_info->image_info->texture != (char *) NULL ?
5874 resource_info->image_info->texture : "pattern:checkerboard",
5875 MaxTextExtent);
cristye8c25f92010-06-03 00:53:06 +00005876 (void) FormatMagickString(size,MaxTextExtent,"%.20gx%.20g",(double)
5877 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005878 image_info->size=ConstantString(size);
5879 pattern=ReadImage(image_info,&image->exception);
5880 image_info=DestroyImageInfo(image_info);
5881 if (pattern != (Image *) NULL)
5882 {
5883 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5884 if (canvas != (Image *) NULL)
5885 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5886 pattern=DestroyImage(pattern);
5887 }
5888 }
5889 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5890 ximage->bits_per_pixel) >> 3));
5891 map_info=window->map_info;
5892 pixels=window->pixel_info->pixels;
5893 q=(unsigned char *) ximage->data;
5894 x=0;
cristyc57f6942010-11-12 01:47:39 +00005895 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005896 if (ximage->format == XYBitmap)
5897 {
5898 register unsigned short
5899 polarity;
5900
5901 unsigned char
5902 background,
5903 foreground;
5904
5905 /*
5906 Convert canvas to big-endian bitmap.
5907 */
5908 background=(unsigned char)
5909 (XPixelIntensity(&window->pixel_info->foreground_color) <
5910 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5911 foreground=(unsigned char)
5912 (XPixelIntensity(&window->pixel_info->background_color) <
5913 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5914 polarity=(unsigned short) ((PixelIntensityToQuantum(
5915 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5916 if (canvas->colors == 2)
5917 polarity=PixelIntensity(&canvas->colormap[0]) <
5918 PixelIntensity(&canvas->colormap[1]);
5919 for (y=0; y < (int) canvas->rows; y++)
5920 {
cristyc57f6942010-11-12 01:47:39 +00005921 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5922 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00005923 if (p == (const PixelPacket *) NULL)
5924 break;
cristyc57f6942010-11-12 01:47:39 +00005925 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00005926 bit=0;
5927 byte=0;
5928 for (x=0; x < (int) canvas->columns; x++)
5929 {
5930 byte>>=1;
5931 if (indexes[x] == (IndexPacket) polarity)
5932 byte|=foreground;
5933 else
5934 byte|=background;
5935 bit++;
5936 if (bit == 8)
5937 {
5938 *q++=byte;
5939 bit=0;
5940 byte=0;
5941 }
5942 }
5943 if (bit != 0)
5944 *q=byte >> (8-bit);
5945 q+=scanline_pad;
5946 }
5947 }
5948 else
5949 if (window->pixel_info->colors != 0)
5950 switch (ximage->bits_per_pixel)
5951 {
5952 case 2:
5953 {
5954 register unsigned int
5955 nibble;
5956
5957 /*
5958 Convert to 2 bit color-mapped X canvas.
5959 */
5960 for (y=0; y < (int) canvas->rows; y++)
5961 {
cristyc57f6942010-11-12 01:47:39 +00005962 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5963 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00005964 if (p == (const PixelPacket *) NULL)
5965 break;
cristyc57f6942010-11-12 01:47:39 +00005966 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00005967 nibble=0;
5968 for (x=0; x < (int) canvas->columns; x++)
5969 {
cristybb503372010-05-27 20:51:26 +00005970 pixel=pixels[(ssize_t) indexes[x]] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00005971 switch (nibble)
5972 {
5973 case 0:
5974 {
5975 *q=(unsigned char) pixel;
5976 nibble++;
5977 break;
5978 }
5979 case 1:
5980 {
5981 *q|=(unsigned char) (pixel << 2);
5982 nibble++;
5983 break;
5984 }
5985 case 2:
5986 {
5987 *q|=(unsigned char) (pixel << 4);
5988 nibble++;
5989 break;
5990 }
5991 case 3:
5992 {
5993 *q|=(unsigned char) (pixel << 6);
5994 q++;
5995 nibble=0;
5996 break;
5997 }
5998 }
5999 }
6000 q+=scanline_pad;
6001 }
6002 break;
6003 }
6004 case 4:
6005 {
6006 register unsigned int
6007 nibble;
6008
6009 /*
6010 Convert to 4 bit color-mapped X canvas.
6011 */
6012 for (y=0; y < (int) canvas->rows; y++)
6013 {
cristyc57f6942010-11-12 01:47:39 +00006014 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6015 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006016 if (p == (const PixelPacket *) NULL)
6017 break;
cristyc57f6942010-11-12 01:47:39 +00006018 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006019 nibble=0;
6020 for (x=0; x < (int) canvas->columns; x++)
6021 {
cristybb503372010-05-27 20:51:26 +00006022 pixel=pixels[(ssize_t) indexes[x]] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006023 switch (nibble)
6024 {
6025 case 0:
6026 {
6027 *q=(unsigned char) pixel;
6028 nibble++;
6029 break;
6030 }
6031 case 1:
6032 {
6033 *q|=(unsigned char) (pixel << 4);
6034 q++;
6035 nibble=0;
6036 break;
6037 }
6038 }
6039 }
6040 q+=scanline_pad;
6041 }
6042 break;
6043 }
6044 case 6:
6045 case 8:
6046 {
6047 /*
6048 Convert to 8 bit color-mapped X canvas.
6049 */
6050 if (resource_info->color_recovery &&
6051 resource_info->quantize_info->dither)
6052 {
6053 XDitherImage(canvas,ximage);
6054 break;
6055 }
6056 for (y=0; y < (int) canvas->rows; y++)
6057 {
cristyc57f6942010-11-12 01:47:39 +00006058 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6059 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006060 if (p == (const PixelPacket *) NULL)
6061 break;
cristyc57f6942010-11-12 01:47:39 +00006062 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006063 for (x=0; x < (int) canvas->columns; x++)
6064 {
cristybb503372010-05-27 20:51:26 +00006065 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006066 *q++=(unsigned char) pixel;
6067 }
6068 q+=scanline_pad;
6069 }
6070 break;
6071 }
6072 default:
6073 {
6074 register int
6075 k;
6076
6077 register unsigned int
6078 bytes_per_pixel;
6079
6080 unsigned char
cristybb503372010-05-27 20:51:26 +00006081 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006082
6083 /*
6084 Convert to multi-byte color-mapped X canvas.
6085 */
6086 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6087 for (y=0; y < (int) canvas->rows; y++)
6088 {
cristyc57f6942010-11-12 01:47:39 +00006089 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6090 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006091 if (p == (const PixelPacket *) NULL)
6092 break;
cristyc57f6942010-11-12 01:47:39 +00006093 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006094 for (x=0; x < (int) canvas->columns; x++)
6095 {
cristybb503372010-05-27 20:51:26 +00006096 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006097 for (k=0; k < (int) bytes_per_pixel; k++)
6098 {
6099 channel[k]=(unsigned char) pixel;
6100 pixel>>=8;
6101 }
6102 for (k=0; k < (int) bytes_per_pixel; k++)
6103 *q++=channel[k];
6104 }
6105 q+=scanline_pad;
6106 }
6107 break;
6108 }
6109 }
6110 else
6111 switch (ximage->bits_per_pixel)
6112 {
6113 case 2:
6114 {
6115 register unsigned int
6116 nibble;
6117
6118 /*
6119 Convert to contiguous 2 bit continuous-tone X canvas.
6120 */
6121 for (y=0; y < (int) canvas->rows; y++)
6122 {
6123 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006124 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6125 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006126 if (p == (const PixelPacket *) NULL)
6127 break;
6128 for (x=0; x < (int) canvas->columns; x++)
6129 {
6130 pixel=XGammaPixel(map_info,p);
6131 pixel&=0xf;
6132 switch (nibble)
6133 {
6134 case 0:
6135 {
6136 *q=(unsigned char) pixel;
6137 nibble++;
6138 break;
6139 }
6140 case 1:
6141 {
6142 *q|=(unsigned char) (pixel << 2);
6143 nibble++;
6144 break;
6145 }
6146 case 2:
6147 {
6148 *q|=(unsigned char) (pixel << 4);
6149 nibble++;
6150 break;
6151 }
6152 case 3:
6153 {
6154 *q|=(unsigned char) (pixel << 6);
6155 q++;
6156 nibble=0;
6157 break;
6158 }
6159 }
6160 p++;
6161 }
6162 q+=scanline_pad;
6163 }
6164 break;
6165 }
6166 case 4:
6167 {
6168 register unsigned int
6169 nibble;
6170
6171 /*
6172 Convert to contiguous 4 bit continuous-tone X canvas.
6173 */
6174 for (y=0; y < (int) canvas->rows; y++)
6175 {
cristyc57f6942010-11-12 01:47:39 +00006176 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6177 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006178 if (p == (const PixelPacket *) NULL)
6179 break;
6180 nibble=0;
6181 for (x=0; x < (int) canvas->columns; x++)
6182 {
6183 pixel=XGammaPixel(map_info,p);
6184 pixel&=0xf;
6185 switch (nibble)
6186 {
6187 case 0:
6188 {
6189 *q=(unsigned char) pixel;
6190 nibble++;
6191 break;
6192 }
6193 case 1:
6194 {
6195 *q|=(unsigned char) (pixel << 4);
6196 q++;
6197 nibble=0;
6198 break;
6199 }
6200 }
6201 p++;
6202 }
6203 q+=scanline_pad;
6204 }
6205 break;
6206 }
6207 case 6:
6208 case 8:
6209 {
6210 /*
6211 Convert to contiguous 8 bit continuous-tone X canvas.
6212 */
6213 if (resource_info->color_recovery &&
6214 resource_info->quantize_info->dither)
6215 {
6216 XDitherImage(canvas,ximage);
6217 break;
6218 }
6219 for (y=0; y < (int) canvas->rows; y++)
6220 {
cristyc57f6942010-11-12 01:47:39 +00006221 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6222 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006223 if (p == (const PixelPacket *) NULL)
6224 break;
6225 for (x=0; x < (int) canvas->columns; x++)
6226 {
6227 pixel=XGammaPixel(map_info,p);
6228 *q++=(unsigned char) pixel;
6229 p++;
6230 }
6231 q+=scanline_pad;
6232 }
6233 break;
6234 }
6235 default:
6236 {
6237 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6238 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6239 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6240 (map_info->blue_mult == 1))
6241 {
6242 /*
6243 Convert to 32 bit continuous-tone X canvas.
6244 */
6245 for (y=0; y < (int) canvas->rows; y++)
6246 {
cristyc57f6942010-11-12 01:47:39 +00006247 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6248 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006249 if (p == (const PixelPacket *) NULL)
6250 break;
6251 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6252 (blue_gamma != 1.0))
6253 {
6254 /*
6255 Gamma correct canvas.
6256 */
6257 for (x=(int) canvas->columns-1; x >= 0; x--)
6258 {
cristyccf844f2010-02-03 23:28:16 +00006259 *q++=ScaleQuantumToChar(XBlueGamma(
6260 GetBluePixelComponent(p)));
6261 *q++=ScaleQuantumToChar(XGreenGamma(
6262 GetGreenPixelComponent(p)));
6263 *q++=ScaleQuantumToChar(XRedGamma(
6264 GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006265 *q++=0;
6266 p++;
6267 }
6268 continue;
6269 }
6270 for (x=(int) canvas->columns-1; x >= 0; x--)
6271 {
cristyce70c172010-01-07 17:15:30 +00006272 *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
6273 *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6274 *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006275 *q++=0;
6276 p++;
6277 }
6278 }
6279 }
6280 else
6281 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6282 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6283 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6284 (map_info->blue_mult == 65536L))
6285 {
6286 /*
6287 Convert to 32 bit continuous-tone X canvas.
6288 */
6289 for (y=0; y < (int) canvas->rows; y++)
6290 {
cristyc57f6942010-11-12 01:47:39 +00006291 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6292 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006293 if (p == (const PixelPacket *) NULL)
6294 break;
6295 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6296 (blue_gamma != 1.0))
6297 {
6298 /*
6299 Gamma correct canvas.
6300 */
6301 for (x=(int) canvas->columns-1; x >= 0; x--)
6302 {
cristyccf844f2010-02-03 23:28:16 +00006303 *q++=ScaleQuantumToChar(XRedGamma(
6304 GetRedPixelComponent(p)));
6305 *q++=ScaleQuantumToChar(XGreenGamma(
6306 GetGreenPixelComponent(p)));
6307 *q++=ScaleQuantumToChar(XBlueGamma(
6308 GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006309 *q++=0;
6310 p++;
6311 }
6312 continue;
6313 }
6314 for (x=(int) canvas->columns-1; x >= 0; x--)
6315 {
cristyccf844f2010-02-03 23:28:16 +00006316 *q++=ScaleQuantumToChar((Quantum)
6317 GetRedPixelComponent(p));
6318 *q++=ScaleQuantumToChar((Quantum)
6319 GetGreenPixelComponent(p));
6320 *q++=ScaleQuantumToChar((Quantum)
6321 GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006322 *q++=0;
6323 p++;
6324 }
6325 }
6326 }
6327 else
6328 {
6329 register int
6330 k;
6331
6332 register unsigned int
6333 bytes_per_pixel;
6334
6335 unsigned char
cristybb503372010-05-27 20:51:26 +00006336 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006337
6338 /*
6339 Convert to multi-byte continuous-tone X canvas.
6340 */
6341 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6342 for (y=0; y < (int) canvas->rows; y++)
6343 {
cristyc57f6942010-11-12 01:47:39 +00006344 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6345 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006346 if (p == (PixelPacket *) NULL)
6347 break;
cristyc57f6942010-11-12 01:47:39 +00006348 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006349 {
6350 pixel=XGammaPixel(map_info,p);
6351 for (k=0; k < (int) bytes_per_pixel; k++)
6352 {
6353 channel[k]=(unsigned char) pixel;
6354 pixel>>=8;
6355 }
6356 for (k=0; k < (int) bytes_per_pixel; k++)
6357 *q++=channel[k];
6358 p++;
6359 }
6360 q+=scanline_pad;
6361 }
6362 }
6363 break;
6364 }
6365 }
6366 if (matte_image != (XImage *) NULL)
6367 {
6368 /*
6369 Initialize matte canvas.
6370 */
6371 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6372 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6373 q=(unsigned char *) matte_image->data;
6374 for (y=0; y < (int) canvas->rows; y++)
6375 {
cristyc57f6942010-11-12 01:47:39 +00006376 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6377 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006378 if (p == (const PixelPacket *) NULL)
6379 break;
6380 bit=0;
6381 byte=0;
6382 for (x=(int) canvas->columns-1; x >= 0; x--)
6383 {
6384 byte>>=1;
cristyc57f6942010-11-12 01:47:39 +00006385 if (p->opacity > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006386 byte|=0x80;
6387 bit++;
6388 if (bit == 8)
6389 {
6390 *q++=byte;
6391 bit=0;
6392 byte=0;
6393 }
6394 p++;
6395 }
6396 if (bit != 0)
6397 *q=byte >> (8-bit);
6398 q+=scanline_pad;
6399 }
6400 }
cristyc57f6942010-11-12 01:47:39 +00006401 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006402 if (canvas != image)
6403 canvas=DestroyImage(canvas);
6404}
6405
6406/*
6407%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6408% %
6409% %
6410% %
6411+ X M a k e I m a g e M S B F i r s t %
6412% %
6413% %
6414% %
6415%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6416%
6417% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6418% image pixels are copied in most-significant bit and byte first order. The
6419% server's scanline pad is also respected. Rather than using one or two
6420% general cases, many special cases are found here to help speed up the image
6421% conversion.
6422%
6423% The format of the XMakeImageMSBFirst method is:
6424%
6425% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6426%
6427% A description of each parameter follows:
6428%
6429% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6430%
6431% o window: Specifies a pointer to a XWindowInfo structure.
6432%
6433% o image: the image.
6434%
6435% o ximage: Specifies a pointer to a XImage structure; returned from
6436% XCreateImage.
6437%
6438% o matte_image: Specifies a pointer to a XImage structure; returned from
6439% XCreateImage.
6440%
cristy3ed852e2009-09-05 21:47:34 +00006441*/
6442static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6443 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6444{
cristyc57f6942010-11-12 01:47:39 +00006445 CacheView
6446 *canvas_view;
6447
cristy3ed852e2009-09-05 21:47:34 +00006448 Image
6449 *canvas;
6450
6451 int
6452 y;
6453
6454 register int
6455 x;
6456
6457 register const IndexPacket
6458 *indexes;
6459
6460 register const PixelPacket
6461 *p;
6462
6463 register unsigned char
6464 *q;
6465
6466 unsigned char
6467 bit,
6468 byte;
6469
6470 unsigned int
6471 scanline_pad;
6472
cristyf2faecf2010-05-28 19:19:36 +00006473 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006474 pixel,
6475 *pixels;
6476
6477 XStandardColormap
6478 *map_info;
6479
6480 assert(resource_info != (XResourceInfo *) NULL);
6481 assert(window != (XWindowInfo *) NULL);
6482 assert(image != (Image *) NULL);
6483 if (image->debug != MagickFalse)
6484 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6485 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006486 if ((window->immutable != MagickFalse) &&
6487 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006488 {
6489 char
6490 size[MaxTextExtent];
6491
6492 Image
6493 *pattern;
6494
6495 ImageInfo
6496 *image_info;
6497
6498 image_info=AcquireImageInfo();
6499 (void) CopyMagickString(image_info->filename,
6500 resource_info->image_info->texture != (char *) NULL ?
6501 resource_info->image_info->texture : "pattern:checkerboard",
6502 MaxTextExtent);
cristye8c25f92010-06-03 00:53:06 +00006503 (void) FormatMagickString(size,MaxTextExtent,"%.20gx%.20g",(double)
6504 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006505 image_info->size=ConstantString(size);
6506 pattern=ReadImage(image_info,&image->exception);
6507 image_info=DestroyImageInfo(image_info);
6508 if (pattern != (Image *) NULL)
6509 {
6510 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6511 if (canvas != (Image *) NULL)
6512 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6513 pattern=DestroyImage(pattern);
6514 }
6515 }
6516 scanline_pad=(unsigned int) (ximage->bytes_per_line-
6517 ((ximage->width*ximage->bits_per_pixel) >> 3));
6518 map_info=window->map_info;
6519 pixels=window->pixel_info->pixels;
6520 q=(unsigned char *) ximage->data;
6521 x=0;
cristyc57f6942010-11-12 01:47:39 +00006522 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006523 if (ximage->format == XYBitmap)
6524 {
6525 register unsigned short
6526 polarity;
6527
6528 unsigned char
6529 background,
6530 foreground;
6531
6532 /*
6533 Convert canvas to big-endian bitmap.
6534 */
6535 background=(unsigned char)
6536 (XPixelIntensity(&window->pixel_info->foreground_color) <
6537 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6538 foreground=(unsigned char)
6539 (XPixelIntensity(&window->pixel_info->background_color) <
6540 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
6541 polarity=(unsigned short) ((PixelIntensityToQuantum(
6542 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6543 if (canvas->colors == 2)
6544 polarity=PixelIntensity(&canvas->colormap[0]) <
6545 PixelIntensity(&canvas->colormap[1]);
6546 for (y=0; y < (int) canvas->rows; y++)
6547 {
cristyc57f6942010-11-12 01:47:39 +00006548 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6549 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006550 if (p == (const PixelPacket *) NULL)
6551 break;
cristyc57f6942010-11-12 01:47:39 +00006552 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006553 bit=0;
6554 byte=0;
6555 for (x=(int) canvas->columns-1; x >= 0; x--)
6556 {
6557 byte<<=1;
6558 if (indexes[x] == (IndexPacket) polarity)
6559 byte|=foreground;
6560 else
6561 byte|=background;
6562 bit++;
6563 if (bit == 8)
6564 {
6565 *q++=byte;
6566 bit=0;
6567 byte=0;
6568 }
6569 }
6570 if (bit != 0)
6571 *q=byte << (8-bit);
6572 q+=scanline_pad;
6573 }
6574 }
6575 else
6576 if (window->pixel_info->colors != 0)
6577 switch (ximage->bits_per_pixel)
6578 {
6579 case 2:
6580 {
6581 register unsigned int
6582 nibble;
6583
6584 /*
6585 Convert to 2 bit color-mapped X canvas.
6586 */
6587 for (y=0; y < (int) canvas->rows; y++)
6588 {
cristyc57f6942010-11-12 01:47:39 +00006589 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6590 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006591 if (p == (const PixelPacket *) NULL)
6592 break;
cristyc57f6942010-11-12 01:47:39 +00006593 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006594 nibble=0;
6595 for (x=0; x < (int) canvas->columns; x++)
6596 {
cristybb503372010-05-27 20:51:26 +00006597 pixel=pixels[(ssize_t) indexes[x]] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006598 switch (nibble)
6599 {
6600 case 0:
6601 {
6602 *q=(unsigned char) (pixel << 6);
6603 nibble++;
6604 break;
6605 }
6606 case 1:
6607 {
6608 *q|=(unsigned char) (pixel << 4);
6609 nibble++;
6610 break;
6611 }
6612 case 2:
6613 {
6614 *q|=(unsigned char) (pixel << 2);
6615 nibble++;
6616 break;
6617 }
6618 case 3:
6619 {
6620 *q|=(unsigned char) pixel;
6621 q++;
6622 nibble=0;
6623 break;
6624 }
6625 }
6626 }
6627 q+=scanline_pad;
6628 }
6629 break;
6630 }
6631 case 4:
6632 {
6633 register unsigned int
6634 nibble;
6635
6636 /*
6637 Convert to 4 bit color-mapped X canvas.
6638 */
6639 for (y=0; y < (int) canvas->rows; y++)
6640 {
cristyc57f6942010-11-12 01:47:39 +00006641 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6642 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006643 if (p == (const PixelPacket *) NULL)
6644 break;
cristyc57f6942010-11-12 01:47:39 +00006645 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006646 nibble=0;
6647 for (x=0; x < (int) canvas->columns; x++)
6648 {
cristybb503372010-05-27 20:51:26 +00006649 pixel=pixels[(ssize_t) indexes[x]] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006650 switch (nibble)
6651 {
6652 case 0:
6653 {
6654 *q=(unsigned char) (pixel << 4);
6655 nibble++;
6656 break;
6657 }
6658 case 1:
6659 {
6660 *q|=(unsigned char) pixel;
6661 q++;
6662 nibble=0;
6663 break;
6664 }
6665 }
6666 }
6667 q+=scanline_pad;
6668 }
6669 break;
6670 }
6671 case 6:
6672 case 8:
6673 {
6674 /*
6675 Convert to 8 bit color-mapped X canvas.
6676 */
6677 if (resource_info->color_recovery &&
6678 resource_info->quantize_info->dither)
6679 {
6680 XDitherImage(canvas,ximage);
6681 break;
6682 }
6683 for (y=0; y < (int) canvas->rows; y++)
6684 {
cristyc57f6942010-11-12 01:47:39 +00006685 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6686 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006687 if (p == (const PixelPacket *) NULL)
6688 break;
cristyc57f6942010-11-12 01:47:39 +00006689 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006690 for (x=0; x < (int) canvas->columns; x++)
6691 {
cristybb503372010-05-27 20:51:26 +00006692 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006693 *q++=(unsigned char) pixel;
6694 }
6695 q+=scanline_pad;
6696 }
6697 break;
6698 }
6699 default:
6700 {
6701 register int
6702 k;
6703
6704 register unsigned int
6705 bytes_per_pixel;
6706
6707 unsigned char
cristybb503372010-05-27 20:51:26 +00006708 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006709
6710 /*
6711 Convert to 8 bit color-mapped X canvas.
6712 */
6713 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6714 for (y=0; y < (int) canvas->rows; y++)
6715 {
cristyc57f6942010-11-12 01:47:39 +00006716 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6717 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006718 if (p == (const PixelPacket *) NULL)
6719 break;
cristyc57f6942010-11-12 01:47:39 +00006720 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006721 for (x=0; x < (int) canvas->columns; x++)
6722 {
cristybb503372010-05-27 20:51:26 +00006723 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006724 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6725 {
6726 channel[k]=(unsigned char) pixel;
6727 pixel>>=8;
6728 }
6729 for (k=0; k < (int) bytes_per_pixel; k++)
6730 *q++=channel[k];
6731 }
6732 q+=scanline_pad;
6733 }
6734 break;
6735 }
6736 }
6737 else
6738 switch (ximage->bits_per_pixel)
6739 {
6740 case 2:
6741 {
6742 register unsigned int
6743 nibble;
6744
6745 /*
6746 Convert to 4 bit continuous-tone X canvas.
6747 */
6748 for (y=0; y < (int) canvas->rows; y++)
6749 {
cristyc57f6942010-11-12 01:47:39 +00006750 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6751 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006752 if (p == (const PixelPacket *) NULL)
6753 break;
6754 nibble=0;
6755 for (x=(int) canvas->columns-1; x >= 0; x--)
6756 {
6757 pixel=XGammaPixel(map_info,p);
6758 pixel&=0xf;
6759 switch (nibble)
6760 {
6761 case 0:
6762 {
6763 *q=(unsigned char) (pixel << 6);
6764 nibble++;
6765 break;
6766 }
6767 case 1:
6768 {
6769 *q|=(unsigned char) (pixel << 4);
6770 nibble++;
6771 break;
6772 }
6773 case 2:
6774 {
6775 *q|=(unsigned char) (pixel << 2);
6776 nibble++;
6777 break;
6778 }
6779 case 3:
6780 {
6781 *q|=(unsigned char) pixel;
6782 q++;
6783 nibble=0;
6784 break;
6785 }
6786 }
6787 p++;
6788 }
6789 q+=scanline_pad;
6790 }
6791 break;
6792 }
6793 case 4:
6794 {
6795 register unsigned int
6796 nibble;
6797
6798 /*
6799 Convert to 4 bit continuous-tone X canvas.
6800 */
6801 for (y=0; y < (int) canvas->rows; y++)
6802 {
cristyc57f6942010-11-12 01:47:39 +00006803 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6804 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006805 if (p == (const PixelPacket *) NULL)
6806 break;
6807 nibble=0;
6808 for (x=(int) canvas->columns-1; x >= 0; x--)
6809 {
6810 pixel=XGammaPixel(map_info,p);
6811 pixel&=0xf;
6812 switch (nibble)
6813 {
6814 case 0:
6815 {
6816 *q=(unsigned char) (pixel << 4);
6817 nibble++;
6818 break;
6819 }
6820 case 1:
6821 {
6822 *q|=(unsigned char) pixel;
6823 q++;
6824 nibble=0;
6825 break;
6826 }
6827 }
6828 p++;
6829 }
6830 q+=scanline_pad;
6831 }
6832 break;
6833 }
6834 case 6:
6835 case 8:
6836 {
6837 /*
6838 Convert to 8 bit continuous-tone X canvas.
6839 */
6840 if (resource_info->color_recovery &&
6841 resource_info->quantize_info->dither)
6842 {
6843 XDitherImage(canvas,ximage);
6844 break;
6845 }
6846 for (y=0; y < (int) canvas->rows; y++)
6847 {
cristyc57f6942010-11-12 01:47:39 +00006848 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6849 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006850 if (p == (const PixelPacket *) NULL)
6851 break;
6852 for (x=(int) canvas->columns-1; x >= 0; x--)
6853 {
6854 pixel=XGammaPixel(map_info,p);
6855 *q++=(unsigned char) pixel;
6856 p++;
6857 }
6858 q+=scanline_pad;
6859 }
6860 break;
6861 }
6862 default:
6863 {
6864 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6865 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6866 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6867 (map_info->blue_mult == 1))
6868 {
6869 /*
6870 Convert to 32 bit continuous-tone X canvas.
6871 */
6872 for (y=0; y < (int) canvas->rows; y++)
6873 {
cristyc57f6942010-11-12 01:47:39 +00006874 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6875 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006876 if (p == (const PixelPacket *) NULL)
6877 break;
6878 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6879 (blue_gamma != 1.0))
6880 {
6881 /*
6882 Gamma correct canvas.
6883 */
6884 for (x=(int) canvas->columns-1; x >= 0; x--)
6885 {
6886 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006887 *q++=ScaleQuantumToChar(XRedGamma(
6888 GetRedPixelComponent(p)));
6889 *q++=ScaleQuantumToChar(XGreenGamma(
6890 GetGreenPixelComponent(p)));
6891 *q++=ScaleQuantumToChar(XBlueGamma(
6892 GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006893 p++;
6894 }
6895 continue;
6896 }
6897 for (x=(int) canvas->columns-1; x >= 0; x--)
6898 {
6899 *q++=0;
cristyce70c172010-01-07 17:15:30 +00006900 *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
6901 *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6902 *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006903 p++;
6904 }
6905 }
6906 }
6907 else
6908 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6909 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6910 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6911 (map_info->blue_mult == 65536L))
6912 {
6913 /*
6914 Convert to 32 bit continuous-tone X canvas.
6915 */
6916 for (y=0; y < (int) canvas->rows; y++)
6917 {
cristyc57f6942010-11-12 01:47:39 +00006918 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6919 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006920 if (p == (const PixelPacket *) NULL)
6921 break;
6922 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6923 (blue_gamma != 1.0))
6924 {
6925 /*
6926 Gamma correct canvas.
6927 */
6928 for (x=(int) canvas->columns-1; x >= 0; x--)
6929 {
6930 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006931 *q++=ScaleQuantumToChar(XBlueGamma(
6932 GetBluePixelComponent(p)));
6933 *q++=ScaleQuantumToChar(XGreenGamma(
6934 GetGreenPixelComponent(p)));
6935 *q++=ScaleQuantumToChar(XRedGamma(
6936 GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006937 p++;
6938 }
6939 continue;
6940 }
6941 for (x=(int) canvas->columns-1; x >= 0; x--)
6942 {
6943 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006944 *q++=ScaleQuantumToChar((Quantum)
6945 GetBluePixelComponent(p));
6946 *q++=ScaleQuantumToChar((Quantum)
6947 GetGreenPixelComponent(p));
6948 *q++=ScaleQuantumToChar((Quantum)
6949 GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006950 p++;
6951 }
6952 }
6953 }
6954 else
6955 {
6956 register int
6957 k;
6958
6959 register unsigned int
6960 bytes_per_pixel;
6961
6962 unsigned char
cristybb503372010-05-27 20:51:26 +00006963 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006964
6965 /*
6966 Convert to multi-byte continuous-tone X canvas.
6967 */
6968 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6969 for (y=0; y < (int) canvas->rows; y++)
6970 {
cristyc57f6942010-11-12 01:47:39 +00006971 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6972 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006973 if (p == (const PixelPacket *) NULL)
6974 break;
6975 for (x=(int) canvas->columns-1; x >= 0; x--)
6976 {
6977 pixel=XGammaPixel(map_info,p);
6978 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6979 {
6980 channel[k]=(unsigned char) pixel;
6981 pixel>>=8;
6982 }
6983 for (k=0; k < (int) bytes_per_pixel; k++)
6984 *q++=channel[k];
6985 p++;
6986 }
6987 q+=scanline_pad;
6988 }
6989 }
6990 break;
6991 }
6992 }
6993 if (matte_image != (XImage *) NULL)
6994 {
6995 /*
6996 Initialize matte canvas.
6997 */
6998 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6999 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7000 q=(unsigned char *) matte_image->data;
7001 for (y=0; y < (int) canvas->rows; y++)
7002 {
cristyc57f6942010-11-12 01:47:39 +00007003 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7004 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00007005 if (p == (const PixelPacket *) NULL)
7006 break;
7007 bit=0;
7008 byte=0;
7009 for (x=(int) canvas->columns-1; x >= 0; x--)
7010 {
7011 byte<<=1;
cristyc57f6942010-11-12 01:47:39 +00007012 if (p->opacity > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007013 byte|=0x01;
7014 bit++;
7015 if (bit == 8)
7016 {
7017 *q++=byte;
7018 bit=0;
7019 byte=0;
7020 }
7021 p++;
7022 }
7023 if (bit != 0)
7024 *q=byte << (8-bit);
7025 q+=scanline_pad;
7026 }
7027 }
cristyc57f6942010-11-12 01:47:39 +00007028 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007029 if (canvas != image)
7030 canvas=DestroyImage(canvas);
7031}
7032
7033/*
7034%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7035% %
7036% %
7037% %
7038% X M a k e M a g n i f y I m a g e %
7039% %
7040% %
7041% %
7042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7043%
7044% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7045%
7046% The format of the XMakeMagnifyImage method is:
7047%
7048% void XMakeMagnifyImage(display,windows)
7049%
7050% A description of each parameter follows:
7051%
7052% o display: Specifies a connection to an X server; returned from
7053% XOpenDisplay.
7054%
7055% o windows: Specifies a pointer to a XWindows structure.
7056%
7057*/
7058MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
7059{
7060 char
7061 tuple[MaxTextExtent];
7062
7063 int
7064 y;
7065
cristybb503372010-05-27 20:51:26 +00007066 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007067 n;
7068
7069 MagickPixelPacket
7070 pixel;
7071
7072 register int
7073 x;
7074
cristybb503372010-05-27 20:51:26 +00007075 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007076 i;
7077
7078 register unsigned char
7079 *p,
7080 *q;
7081
7082 static unsigned int
7083 previous_magnify = 0;
7084
7085 static XWindowInfo
7086 magnify_window;
7087
7088 unsigned int
7089 height,
7090 j,
7091 k,
7092 l,
7093 magnify,
7094 scanline_pad,
7095 width;
7096
7097 XImage
7098 *ximage;
7099
7100 /*
7101 Check boundary conditions.
7102 */
7103 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7104 assert(display != (Display *) NULL);
7105 assert(windows != (XWindows *) NULL);
7106 magnify=1;
cristybb503372010-05-27 20:51:26 +00007107 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007108 magnify<<=1;
7109 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7110 magnify<<=1;
7111 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7112 magnify<<=1;
7113 while (magnify > windows->magnify.width)
7114 magnify>>=1;
7115 while (magnify > windows->magnify.height)
7116 magnify>>=1;
7117 if (magnify != previous_magnify)
7118 {
7119 Status
7120 status;
7121
7122 XTextProperty
7123 window_name;
7124
7125 /*
7126 New magnify factor: update magnify window name.
7127 */
7128 i=0;
7129 while ((1 << i) <= (int) magnify)
7130 i++;
7131 (void) FormatMagickString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007132 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007133 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7134 if (status != False)
7135 {
7136 XSetWMName(display,windows->magnify.id,&window_name);
7137 XSetWMIconName(display,windows->magnify.id,&window_name);
7138 (void) XFree((void *) window_name.value);
7139 }
7140 }
7141 previous_magnify=magnify;
7142 ximage=windows->image.ximage;
7143 width=(unsigned int) windows->magnify.ximage->width;
7144 height=(unsigned int) windows->magnify.ximage->height;
7145 if ((windows->magnify.x < 0) ||
7146 (windows->magnify.x >= windows->image.ximage->width))
7147 windows->magnify.x=windows->image.ximage->width >> 1;
7148 x=windows->magnify.x-((width/magnify) >> 1);
7149 if (x < 0)
7150 x=0;
7151 else
7152 if (x > (int) (ximage->width-(width/magnify)))
7153 x=ximage->width-width/magnify;
7154 if ((windows->magnify.y < 0) ||
7155 (windows->magnify.y >= windows->image.ximage->height))
7156 windows->magnify.y=windows->image.ximage->height >> 1;
7157 y=windows->magnify.y-((height/magnify) >> 1);
7158 if (y < 0)
7159 y=0;
7160 else
7161 if (y > (int) (ximage->height-(height/magnify)))
7162 y=ximage->height-height/magnify;
7163 q=(unsigned char *) windows->magnify.ximage->data;
7164 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7165 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7166 if (ximage->bits_per_pixel < 8)
7167 {
7168 register unsigned char
7169 background,
7170 byte,
7171 foreground,
7172 p_bit,
7173 q_bit;
7174
7175 register unsigned int
7176 plane;
7177
7178 XPixelInfo
7179 *pixel_info;
7180
7181 pixel_info=windows->magnify.pixel_info;
7182 switch (ximage->bitmap_bit_order)
7183 {
7184 case LSBFirst:
7185 {
7186 /*
7187 Magnify little-endian bitmap.
7188 */
7189 background=0x00;
7190 foreground=0x80;
7191 if (ximage->format == XYBitmap)
7192 {
7193 background=(unsigned char)
7194 (XPixelIntensity(&pixel_info->foreground_color) <
7195 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7196 foreground=(unsigned char)
7197 (XPixelIntensity(&pixel_info->background_color) <
7198 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7199 if (windows->magnify.depth > 1)
7200 Swap(background,foreground);
7201 }
cristybb503372010-05-27 20:51:26 +00007202 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007203 {
7204 /*
7205 Propogate pixel magnify rows.
7206 */
7207 for (j=0; j < magnify; j++)
7208 {
7209 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7210 ((x*ximage->bits_per_pixel) >> 3);
7211 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7212 q_bit=0;
7213 byte=0;
7214 for (k=0; k < width; k+=magnify)
7215 {
7216 /*
7217 Propogate pixel magnify columns.
7218 */
7219 for (l=0; l < magnify; l++)
7220 {
7221 /*
7222 Propogate each bit plane.
7223 */
7224 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7225 {
7226 byte>>=1;
7227 if (*p & (0x01 << (p_bit+plane)))
7228 byte|=foreground;
7229 else
7230 byte|=background;
7231 q_bit++;
7232 if (q_bit == 8)
7233 {
7234 *q++=byte;
7235 q_bit=0;
7236 byte=0;
7237 }
7238 }
7239 }
7240 p_bit+=ximage->bits_per_pixel;
7241 if (p_bit == 8)
7242 {
7243 p++;
7244 p_bit=0;
7245 }
7246 if (q_bit != 0)
7247 *q=byte >> (8-q_bit);
7248 q+=scanline_pad;
7249 }
7250 }
7251 y++;
7252 }
7253 break;
7254 }
7255 case MSBFirst:
7256 default:
7257 {
7258 /*
7259 Magnify big-endian bitmap.
7260 */
7261 background=0x00;
7262 foreground=0x01;
7263 if (ximage->format == XYBitmap)
7264 {
7265 background=(unsigned char)
7266 (XPixelIntensity(&pixel_info->foreground_color) <
7267 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7268 foreground=(unsigned char)
7269 (XPixelIntensity(&pixel_info->background_color) <
7270 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7271 if (windows->magnify.depth > 1)
7272 Swap(background,foreground);
7273 }
cristybb503372010-05-27 20:51:26 +00007274 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007275 {
7276 /*
7277 Propogate pixel magnify rows.
7278 */
7279 for (j=0; j < magnify; j++)
7280 {
7281 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7282 ((x*ximage->bits_per_pixel) >> 3);
7283 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7284 q_bit=0;
7285 byte=0;
7286 for (k=0; k < width; k+=magnify)
7287 {
7288 /*
7289 Propogate pixel magnify columns.
7290 */
7291 for (l=0; l < magnify; l++)
7292 {
7293 /*
7294 Propogate each bit plane.
7295 */
7296 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7297 {
7298 byte<<=1;
7299 if (*p & (0x80 >> (p_bit+plane)))
7300 byte|=foreground;
7301 else
7302 byte|=background;
7303 q_bit++;
7304 if (q_bit == 8)
7305 {
7306 *q++=byte;
7307 q_bit=0;
7308 byte=0;
7309 }
7310 }
7311 }
7312 p_bit+=ximage->bits_per_pixel;
7313 if (p_bit == 8)
7314 {
7315 p++;
7316 p_bit=0;
7317 }
7318 if (q_bit != 0)
7319 *q=byte << (8-q_bit);
7320 q+=scanline_pad;
7321 }
7322 }
7323 y++;
7324 }
7325 break;
7326 }
7327 }
7328 }
7329 else
7330 switch (ximage->bits_per_pixel)
7331 {
7332 case 6:
7333 case 8:
7334 {
7335 /*
7336 Magnify 8 bit X image.
7337 */
cristybb503372010-05-27 20:51:26 +00007338 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007339 {
7340 /*
7341 Propogate pixel magnify rows.
7342 */
7343 for (j=0; j < magnify; j++)
7344 {
7345 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7346 ((x*ximage->bits_per_pixel) >> 3);
7347 for (k=0; k < width; k+=magnify)
7348 {
7349 /*
7350 Propogate pixel magnify columns.
7351 */
7352 for (l=0; l < magnify; l++)
7353 *q++=(*p);
7354 p++;
7355 }
7356 q+=scanline_pad;
7357 }
7358 y++;
7359 }
7360 break;
7361 }
7362 default:
7363 {
7364 register unsigned int
7365 bytes_per_pixel,
7366 m;
7367
7368 /*
7369 Magnify multi-byte X image.
7370 */
7371 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007372 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007373 {
7374 /*
7375 Propogate pixel magnify rows.
7376 */
7377 for (j=0; j < magnify; j++)
7378 {
7379 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7380 ((x*ximage->bits_per_pixel) >> 3);
7381 for (k=0; k < width; k+=magnify)
7382 {
7383 /*
7384 Propogate pixel magnify columns.
7385 */
7386 for (l=0; l < magnify; l++)
7387 for (m=0; m < bytes_per_pixel; m++)
7388 *q++=(*(p+m));
7389 p+=bytes_per_pixel;
7390 }
7391 q+=scanline_pad;
7392 }
7393 y++;
7394 }
7395 break;
7396 }
7397 }
7398 /*
7399 Copy X image to magnify pixmap.
7400 */
7401 x=windows->magnify.x-((width/magnify) >> 1);
7402 if (x < 0)
7403 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7404 else
7405 if (x > (int) (ximage->width-(width/magnify)))
7406 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7407 else
7408 x=0;
7409 y=windows->magnify.y-((height/magnify) >> 1);
7410 if (y < 0)
7411 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7412 else
7413 if (y > (int) (ximage->height-(height/magnify)))
7414 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7415 else
7416 y=0;
7417 if ((x != 0) || (y != 0))
7418 (void) XFillRectangle(display,windows->magnify.pixmap,
7419 windows->magnify.annotate_context,0,0,width,height);
7420 (void) XPutImage(display,windows->magnify.pixmap,
7421 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7422 height-y);
7423 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7424 (magnify <= (height >> 1))))
7425 {
7426 RectangleInfo
7427 highlight_info;
7428
7429 /*
7430 Highlight center pixel.
7431 */
cristybb503372010-05-27 20:51:26 +00007432 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7433 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007434 highlight_info.width=magnify;
7435 highlight_info.height=magnify;
7436 (void) XDrawRectangle(display,windows->magnify.pixmap,
7437 windows->magnify.highlight_context,(int) highlight_info.x,
7438 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7439 (unsigned int) highlight_info.height-1);
7440 if (magnify > 2)
7441 (void) XDrawRectangle(display,windows->magnify.pixmap,
7442 windows->magnify.annotate_context,(int) highlight_info.x+1,
7443 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7444 (unsigned int) highlight_info.height-3);
7445 }
7446 /*
7447 Show center pixel color.
7448 */
cristyc57f6942010-11-12 01:47:39 +00007449 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7450 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7451 &windows->image.image->exception);
cristy3ed852e2009-09-05 21:47:34 +00007452 (void) FormatMagickString(tuple,MaxTextExtent,"%d,%d: ",
7453 windows->magnify.x,windows->magnify.y);
7454 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7455 ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
7456 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7457 ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
7458 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7459 ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
7460 if (pixel.colorspace == CMYKColorspace)
7461 {
7462 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7463 ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
7464 }
7465 if (pixel.matte != MagickFalse)
7466 {
7467 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7468 ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
7469 }
7470 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7471 height=(unsigned int) windows->magnify.font_info->ascent+
7472 windows->magnify.font_info->descent;
7473 x=windows->magnify.font_info->max_bounds.width >> 1;
7474 y=windows->magnify.font_info->ascent+(height >> 2);
7475 (void) XDrawImageString(display,windows->magnify.pixmap,
7476 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7477 GetColorTuple(&pixel,MagickTrue,tuple);
7478 y+=height;
7479 (void) XDrawImageString(display,windows->magnify.pixmap,
7480 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7481 (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7482 &windows->image.image->exception);
7483 y+=height;
7484 (void) XDrawImageString(display,windows->magnify.pixmap,
7485 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7486 /*
7487 Refresh magnify window.
7488 */
7489 magnify_window=windows->magnify;
7490 magnify_window.x=0;
7491 magnify_window.y=0;
7492 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7493}
7494
7495/*
7496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7497% %
7498% %
7499% %
7500% X M a k e P i x m a p %
7501% %
7502% %
7503% %
7504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7505%
7506% XMakePixmap() creates an X11 pixmap.
7507%
7508% The format of the XMakePixmap method is:
7509%
7510% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7511% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7512% XPixelInfo *pixel)
7513%
7514% A description of each parameter follows:
7515%
7516% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7517%
7518% o display: Specifies a connection to an X server; returned from
7519% XOpenDisplay.
7520%
7521% o window: Specifies a pointer to a XWindowInfo structure.
7522%
cristy3ed852e2009-09-05 21:47:34 +00007523*/
7524static MagickBooleanType XMakePixmap(Display *display,
7525 const XResourceInfo *resource_info,XWindowInfo *window)
7526{
7527 unsigned int
7528 height,
7529 width;
7530
7531 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7532 assert(display != (Display *) NULL);
7533 assert(resource_info != (XResourceInfo *) NULL);
7534 assert(window != (XWindowInfo *) NULL);
7535 if (window->pixmap != (Pixmap) NULL)
7536 {
7537 /*
7538 Destroy previous X pixmap.
7539 */
7540 (void) XFreePixmap(display,window->pixmap);
7541 window->pixmap=(Pixmap) NULL;
7542 }
7543 if (window->use_pixmap == MagickFalse)
7544 return(MagickFalse);
7545 if (window->ximage == (XImage *) NULL)
7546 return(MagickFalse);
7547 /*
7548 Display busy cursor.
7549 */
7550 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7551 (void) XFlush(display);
7552 /*
7553 Create pixmap.
7554 */
7555 width=(unsigned int) window->ximage->width;
7556 height=(unsigned int) window->ximage->height;
7557 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7558 if (window->pixmap == (Pixmap) NULL)
7559 {
7560 /*
7561 Unable to allocate pixmap.
7562 */
7563 (void) XCheckDefineCursor(display,window->id,window->cursor);
7564 return(MagickFalse);
7565 }
7566 /*
7567 Copy X image to pixmap.
7568 */
7569#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7570 if (window->shared_memory)
7571 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7572 window->ximage,0,0,0,0,width,height,MagickTrue);
7573#endif
7574 if (window->shared_memory == MagickFalse)
7575 (void) XPutImage(display,window->pixmap,window->annotate_context,
7576 window->ximage,0,0,0,0,width,height);
7577 if (IsEventLogging())
7578 {
7579 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7580 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7581 width,height);
7582 }
7583 /*
7584 Restore cursor.
7585 */
7586 (void) XCheckDefineCursor(display,window->id,window->cursor);
7587 return(MagickTrue);
7588}
7589
7590/*
7591%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7592% %
7593% %
7594% %
7595% X M a k e S t a n d a r d C o l o r m a p %
7596% %
7597% %
7598% %
7599%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7600%
7601% XMakeStandardColormap() creates an X11 Standard Colormap.
7602%
7603% The format of the XMakeStandardColormap method is:
7604%
7605% XMakeStandardColormap(display,visual_info,resource_info,image,
7606% map_info,pixel)
7607%
7608% A description of each parameter follows:
7609%
7610% o display: Specifies a connection to an X server; returned from
7611% XOpenDisplay.
7612%
7613% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7614% returned from XGetVisualInfo.
7615%
7616% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7617%
7618% o image: the image.
7619%
7620% o map_info: If a Standard Colormap type is specified, this structure is
7621% initialized with info from the Standard Colormap.
7622%
7623% o pixel: Specifies a pointer to a XPixelInfo structure.
7624%
cristy3ed852e2009-09-05 21:47:34 +00007625*/
7626
7627#if defined(__cplusplus) || defined(c_plusplus)
7628extern "C" {
7629#endif
7630
7631static inline MagickRealType DiversityPixelIntensity(
7632 const DiversityPacket *pixel)
7633{
7634 MagickRealType
7635 intensity;
7636
7637 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7638 return(intensity);
7639}
7640
7641static int IntensityCompare(const void *x,const void *y)
7642{
7643 DiversityPacket
7644 *color_1,
7645 *color_2;
7646
7647 int
7648 diversity;
7649
7650 color_1=(DiversityPacket *) x;
7651 color_2=(DiversityPacket *) y;
7652 diversity=(int) (DiversityPixelIntensity(color_2)-
7653 DiversityPixelIntensity(color_1));
7654 return(diversity);
7655}
7656
7657static int PopularityCompare(const void *x,const void *y)
7658{
7659 DiversityPacket
7660 *color_1,
7661 *color_2;
7662
7663 color_1=(DiversityPacket *) x;
7664 color_2=(DiversityPacket *) y;
7665 return((int) color_2->count-(int) color_1->count);
7666}
7667
7668#if defined(__cplusplus) || defined(c_plusplus)
7669}
7670#endif
7671
cristybb503372010-05-27 20:51:26 +00007672static inline Quantum ScaleXToQuantum(const size_t x,
7673 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007674{
7675 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7676}
7677
7678MagickExport void XMakeStandardColormap(Display *display,
7679 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7680 XStandardColormap *map_info,XPixelInfo *pixel)
7681{
7682 Colormap
7683 colormap;
7684
7685 ExceptionInfo
7686 *exception;
7687
7688 register IndexPacket
7689 *indexes;
7690
cristybb503372010-05-27 20:51:26 +00007691 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007692 i;
7693
7694 Status
7695 status;
7696
cristybb503372010-05-27 20:51:26 +00007697 size_t
cristy3ed852e2009-09-05 21:47:34 +00007698 number_colors,
7699 retain_colors;
7700
7701 unsigned short
7702 gray_value;
7703
7704 XColor
7705 color,
7706 *colors,
7707 *p;
7708
7709 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7710 assert(display != (Display *) NULL);
7711 assert(visual_info != (XVisualInfo *) NULL);
7712 assert(map_info != (XStandardColormap *) NULL);
7713 assert(resource_info != (XResourceInfo *) NULL);
7714 assert(pixel != (XPixelInfo *) NULL);
7715 exception=(&image->exception);
7716 if (resource_info->map_type != (char *) NULL)
7717 {
7718 /*
7719 Standard Colormap is already defined (i.e. xstdcmap).
7720 */
7721 XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7722 pixel);
7723 number_colors=(unsigned int) (map_info->base_pixel+
7724 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7725 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7726 if ((image->matte == MagickFalse) &&
7727 (resource_info->color_recovery == MagickFalse) &&
7728 resource_info->quantize_info->dither &&
7729 (number_colors < MaxColormapSize))
7730 {
7731 Image
7732 *affinity_image;
7733
7734 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00007735 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007736
7737 /*
7738 Improve image appearance with error diffusion.
7739 */
7740 affinity_image=AcquireImage((ImageInfo *) NULL);
7741 if (affinity_image == (Image *) NULL)
7742 ThrowXWindowFatalException(ResourceLimitFatalError,
7743 "UnableToDitherImage",image->filename);
7744 affinity_image->columns=number_colors;
7745 affinity_image->rows=1;
7746 /*
7747 Initialize colormap image.
7748 */
7749 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7750 1,exception);
7751 if (q != (PixelPacket *) NULL)
7752 {
cristybb503372010-05-27 20:51:26 +00007753 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007754 {
7755 q->red=(Quantum) 0;
7756 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00007757 q->red=ScaleXToQuantum((size_t) (i/
cristy3ed852e2009-09-05 21:47:34 +00007758 map_info->red_mult),map_info->red_max);
7759 q->green=(Quantum) 0;
7760 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00007761 q->green=ScaleXToQuantum((size_t) ((i/
cristy3ed852e2009-09-05 21:47:34 +00007762 map_info->green_mult) % (map_info->green_max+1)),
7763 map_info->green_max);
7764 q->blue=(Quantum) 0;
7765 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00007766 q->blue=ScaleXToQuantum((size_t) (i %
cristy3ed852e2009-09-05 21:47:34 +00007767 map_info->green_mult),map_info->blue_max);
7768 q->opacity=(Quantum) TransparentOpacity;
7769 q++;
7770 }
7771 (void) SyncAuthenticPixels(affinity_image,exception);
7772 (void) RemapImage(resource_info->quantize_info,image,
7773 affinity_image);
7774 }
7775 XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7776 pixel);
7777 (void) SetImageStorageClass(image,DirectClass);
7778 affinity_image=DestroyImage(affinity_image);
7779 }
7780 if (IsEventLogging())
7781 {
7782 (void) LogMagickEvent(X11Event,GetMagickModule(),
7783 "Standard Colormap:");
7784 (void) LogMagickEvent(X11Event,GetMagickModule(),
7785 " colormap id: 0x%lx",map_info->colormap);
7786 (void) LogMagickEvent(X11Event,GetMagickModule(),
7787 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7788 map_info->green_max,map_info->blue_max);
7789 (void) LogMagickEvent(X11Event,GetMagickModule(),
7790 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7791 map_info->green_mult,map_info->blue_mult);
7792 }
7793 return;
7794 }
7795 if ((visual_info->klass != DirectColor) &&
7796 (visual_info->klass != TrueColor))
7797 if ((image->storage_class == DirectClass) ||
7798 ((int) image->colors > visual_info->colormap_size))
7799 {
7800 QuantizeInfo
7801 quantize_info;
7802
7803 /*
7804 Image has more colors than the visual supports.
7805 */
7806 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007807 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00007808 (void) QuantizeImage(&quantize_info,image);
7809 }
7810 /*
7811 Free previous and create new colormap.
7812 */
7813 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7814 colormap=XDefaultColormap(display,visual_info->screen);
7815 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7816 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7817 visual_info->visual,visual_info->klass == DirectColor ?
7818 AllocAll : AllocNone);
7819 if (colormap == (Colormap) NULL)
7820 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7821 image->filename);
7822 /*
7823 Initialize the map and pixel info structures.
7824 */
7825 XGetMapInfo(visual_info,colormap,map_info);
7826 XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
7827 /*
7828 Allocating colors in server colormap is based on visual class.
7829 */
7830 switch (visual_info->klass)
7831 {
7832 case StaticGray:
7833 case StaticColor:
7834 {
7835 /*
7836 Define Standard Colormap for StaticGray or StaticColor visual.
7837 */
7838 number_colors=image->colors;
7839 colors=(XColor *) AcquireQuantumMemory((size_t)
7840 visual_info->colormap_size,sizeof(*colors));
7841 if (colors == (XColor *) NULL)
7842 ThrowXWindowFatalException(ResourceLimitFatalError,
7843 "UnableToCreateColormap",image->filename);
7844 p=colors;
7845 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007846 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007847 {
7848 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7849 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7850 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7851 if (visual_info->klass != StaticColor)
7852 {
7853 gray_value=(unsigned short) XPixelIntensity(&color);
7854 color.red=gray_value;
7855 color.green=gray_value;
7856 color.blue=gray_value;
7857 }
7858 status=XAllocColor(display,colormap,&color);
7859 if (status == False)
7860 {
7861 colormap=XCopyColormapAndFree(display,colormap);
7862 (void) XAllocColor(display,colormap,&color);
7863 }
7864 pixel->pixels[i]=color.pixel;
7865 *p++=color;
7866 }
7867 break;
7868 }
7869 case GrayScale:
7870 case PseudoColor:
7871 {
7872 unsigned int
7873 colormap_type;
7874
7875 /*
7876 Define Standard Colormap for GrayScale or PseudoColor visual.
7877 */
7878 number_colors=image->colors;
7879 colors=(XColor *) AcquireQuantumMemory((size_t)
7880 visual_info->colormap_size,sizeof(*colors));
7881 if (colors == (XColor *) NULL)
7882 ThrowXWindowFatalException(ResourceLimitFatalError,
7883 "UnableToCreateColormap",image->filename);
7884 /*
7885 Preallocate our GUI colors.
7886 */
7887 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7888 (void) XAllocColor(display,colormap,&pixel->background_color);
7889 (void) XAllocColor(display,colormap,&pixel->border_color);
7890 (void) XAllocColor(display,colormap,&pixel->matte_color);
7891 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7892 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7893 (void) XAllocColor(display,colormap,&pixel->depth_color);
7894 (void) XAllocColor(display,colormap,&pixel->trough_color);
7895 for (i=0; i < MaxNumberPens; i++)
7896 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7897 /*
7898 Determine if image colors will "fit" into X server colormap.
7899 */
7900 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007901 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007902 NULL,0,pixel->pixels,(unsigned int) image->colors);
7903 if (status != False)
7904 colormap_type=PrivateColormap;
7905 if (colormap_type == SharedColormap)
7906 {
cristyc57f6942010-11-12 01:47:39 +00007907 CacheView
7908 *image_view;
7909
cristy3ed852e2009-09-05 21:47:34 +00007910 DiversityPacket
7911 *diversity;
7912
7913 int
7914 y;
7915
7916 register int
7917 x;
7918
7919 unsigned short
7920 index;
7921
7922 XColor
7923 *server_colors;
7924
7925 /*
7926 Define Standard colormap for shared GrayScale or PseudoColor visual.
7927 */
7928 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7929 sizeof(*diversity));
7930 if (diversity == (DiversityPacket *) NULL)
7931 ThrowXWindowFatalException(ResourceLimitFatalError,
7932 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007933 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007934 {
7935 diversity[i].red=image->colormap[i].red;
7936 diversity[i].green=image->colormap[i].green;
7937 diversity[i].blue=image->colormap[i].blue;
7938 diversity[i].index=(unsigned short) i;
7939 diversity[i].count=0;
7940 }
cristyc57f6942010-11-12 01:47:39 +00007941 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00007942 for (y=0; y < (int) image->rows; y++)
7943 {
cristyc57f6942010-11-12 01:47:39 +00007944 register int
cristy3ed852e2009-09-05 21:47:34 +00007945 x;
7946
cristyc57f6942010-11-12 01:47:39 +00007947 register const PixelPacket
7948 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007949
cristyc57f6942010-11-12 01:47:39 +00007950 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7951 image->columns,1,exception);
7952 if (p == (const PixelPacket *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007953 break;
cristyc57f6942010-11-12 01:47:39 +00007954 indexes=GetCacheViewAuthenticIndexQueue(image_view);
7955 for (x=(int) image->columns-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00007956 diversity[(ssize_t) indexes[x]].count++;
cristy3ed852e2009-09-05 21:47:34 +00007957 }
cristyc57f6942010-11-12 01:47:39 +00007958 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00007959 /*
7960 Sort colors by decreasing intensity.
7961 */
7962 qsort((void *) diversity,image->colors,sizeof(*diversity),
7963 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00007964 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00007965 {
7966 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00007967 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00007968 }
7969 diversity[image->colors-1].count<<=4;
7970 qsort((void *) diversity,image->colors,sizeof(*diversity),
7971 PopularityCompare);
7972 /*
7973 Allocate colors.
7974 */
7975 p=colors;
7976 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007977 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007978 {
7979 index=diversity[i].index;
7980 color.red=
7981 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7982 color.green=
7983 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7984 color.blue=
7985 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7986 if (visual_info->klass != PseudoColor)
7987 {
7988 gray_value=(unsigned short) XPixelIntensity(&color);
7989 color.red=gray_value;
7990 color.green=gray_value;
7991 color.blue=gray_value;
7992 }
7993 status=XAllocColor(display,colormap,&color);
7994 if (status == False)
7995 break;
7996 pixel->pixels[index]=color.pixel;
7997 *p++=color;
7998 }
7999 /*
8000 Read X server colormap.
8001 */
8002 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8003 visual_info->colormap_size,sizeof(*server_colors));
8004 if (server_colors == (XColor *) NULL)
8005 ThrowXWindowFatalException(ResourceLimitFatalError,
8006 "UnableToCreateColormap",image->filename);
8007 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008008 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008009 (void) XQueryColors(display,colormap,server_colors,
8010 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8011 /*
8012 Select remaining colors from X server colormap.
8013 */
cristybb503372010-05-27 20:51:26 +00008014 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008015 {
8016 index=diversity[i].index;
8017 color.red=
8018 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8019 color.green=
8020 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8021 color.blue=
8022 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8023 if (visual_info->klass != PseudoColor)
8024 {
8025 gray_value=(unsigned short) XPixelIntensity(&color);
8026 color.red=gray_value;
8027 color.green=gray_value;
8028 color.blue=gray_value;
8029 }
8030 XBestPixel(display,colormap,server_colors,(unsigned int)
8031 visual_info->colormap_size,&color);
8032 pixel->pixels[index]=color.pixel;
8033 *p++=color;
8034 }
8035 if ((int) image->colors < visual_info->colormap_size)
8036 {
8037 /*
8038 Fill up colors array-- more choices for pen colors.
8039 */
8040 retain_colors=MagickMin((unsigned int)
8041 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008042 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008043 *p++=server_colors[i];
8044 number_colors+=retain_colors;
8045 }
8046 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8047 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8048 break;
8049 }
8050 /*
8051 Define Standard colormap for private GrayScale or PseudoColor visual.
8052 */
8053 if (status == False)
8054 {
8055 /*
8056 Not enough colormap entries in the colormap-- Create a new colormap.
8057 */
8058 colormap=XCreateColormap(display,
8059 XRootWindow(display,visual_info->screen),visual_info->visual,
8060 AllocNone);
8061 if (colormap == (Colormap) NULL)
8062 ThrowXWindowFatalException(ResourceLimitFatalError,
8063 "UnableToCreateColormap",image->filename);
8064 map_info->colormap=colormap;
8065 if ((int) image->colors < visual_info->colormap_size)
8066 {
8067 /*
8068 Retain colors from the default colormap to help lessens the
8069 effects of colormap flashing.
8070 */
8071 retain_colors=MagickMin((unsigned int)
8072 (visual_info->colormap_size-image->colors),256);
8073 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008074 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008075 {
cristyc57f6942010-11-12 01:47:39 +00008076 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008077 p++;
8078 }
8079 (void) XQueryColors(display,
8080 XDefaultColormap(display,visual_info->screen),
8081 colors+image->colors,(int) retain_colors);
8082 /*
8083 Transfer colors from default to private colormap.
8084 */
8085 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008086 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008087 retain_colors);
8088 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008089 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008090 {
8091 p->pixel=pixel->pixels[i];
8092 p++;
8093 }
8094 (void) XStoreColors(display,colormap,colors+image->colors,
8095 (int) retain_colors);
8096 number_colors+=retain_colors;
8097 }
8098 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008099 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008100 image->colors);
8101 }
8102 /*
8103 Store the image colormap.
8104 */
8105 p=colors;
8106 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008107 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008108 {
8109 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8110 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8111 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8112 if (visual_info->klass != PseudoColor)
8113 {
8114 gray_value=(unsigned short) XPixelIntensity(&color);
8115 color.red=gray_value;
8116 color.green=gray_value;
8117 color.blue=gray_value;
8118 }
8119 color.pixel=pixel->pixels[i];
8120 *p++=color;
8121 }
8122 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8123 break;
8124 }
8125 case TrueColor:
8126 case DirectColor:
8127 default:
8128 {
8129 MagickBooleanType
8130 linear_colormap;
8131
8132 /*
8133 Define Standard Colormap for TrueColor or DirectColor visual.
8134 */
8135 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8136 (map_info->green_max*map_info->green_mult)+
8137 (map_info->blue_max*map_info->blue_mult)+1);
8138 linear_colormap=(number_colors > 4096) ||
8139 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8140 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8141 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8142 MagickTrue : MagickFalse;
8143 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008144 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008145 /*
8146 Allocate color array.
8147 */
8148 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8149 if (colors == (XColor *) NULL)
8150 ThrowXWindowFatalException(ResourceLimitFatalError,
8151 "UnableToCreateColormap",image->filename);
8152 /*
8153 Initialize linear color ramp.
8154 */
8155 p=colors;
8156 color.flags=(char) (DoRed | DoGreen | DoBlue);
8157 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008158 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008159 {
8160 color.blue=(unsigned short) 0;
8161 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008162 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008163 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8164 color.green=color.blue;
8165 color.red=color.blue;
8166 color.pixel=XStandardPixel(map_info,&color);
8167 *p++=color;
8168 }
8169 else
cristybb503372010-05-27 20:51:26 +00008170 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008171 {
8172 color.red=(unsigned short) 0;
8173 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008174 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008175 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8176 color.green=(unsigned int) 0;
8177 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008178 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008179 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8180 map_info->green_max));
8181 color.blue=(unsigned short) 0;
8182 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008183 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008184 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8185 color.pixel=XStandardPixel(map_info,&color);
8186 *p++=color;
8187 }
8188 if ((visual_info->klass == DirectColor) &&
8189 (colormap != XDefaultColormap(display,visual_info->screen)))
8190 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8191 else
cristybb503372010-05-27 20:51:26 +00008192 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008193 (void) XAllocColor(display,colormap,&colors[i]);
8194 break;
8195 }
8196 }
8197 if ((visual_info->klass != DirectColor) &&
8198 (visual_info->klass != TrueColor))
8199 {
8200 /*
8201 Set foreground, background, border, etc. pixels.
8202 */
8203 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8204 &pixel->foreground_color);
8205 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8206 &pixel->background_color);
8207 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8208 {
8209 /*
8210 Foreground and background colors must differ.
8211 */
8212 pixel->background_color.red=(~pixel->foreground_color.red);
8213 pixel->background_color.green=
8214 (~pixel->foreground_color.green);
8215 pixel->background_color.blue=
8216 (~pixel->foreground_color.blue);
8217 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8218 &pixel->background_color);
8219 }
8220 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8221 &pixel->border_color);
8222 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8223 &pixel->matte_color);
8224 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8225 &pixel->highlight_color);
8226 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8227 &pixel->shadow_color);
8228 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8229 &pixel->depth_color);
8230 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8231 &pixel->trough_color);
8232 for (i=0; i < MaxNumberPens; i++)
8233 {
8234 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8235 &pixel->pen_colors[i]);
8236 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8237 }
cristyc57f6942010-11-12 01:47:39 +00008238 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008239 }
8240 colors=(XColor *) RelinquishMagickMemory(colors);
8241 if (IsEventLogging())
8242 {
8243 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8244 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8245 map_info->colormap);
8246 (void) LogMagickEvent(X11Event,GetMagickModule(),
8247 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8248 map_info->green_max,map_info->blue_max);
8249 (void) LogMagickEvent(X11Event,GetMagickModule(),
8250 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8251 map_info->green_mult,map_info->blue_mult);
8252 }
8253}
8254
8255/*
8256%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8257% %
8258% %
8259% %
8260% X M a k e W i n d o w %
8261% %
8262% %
8263% %
8264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8265%
8266% XMakeWindow() creates an X11 window.
8267%
8268% The format of the XMakeWindow method is:
8269%
8270% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8271% XClassHint *class_hint,XWMHints *manager_hints,
8272% XWindowInfo *window_info)
8273%
8274% A description of each parameter follows:
8275%
8276% o display: Specifies a connection to an X server; returned from
8277% XOpenDisplay.
8278%
8279% o parent: Specifies the parent window_info.
8280%
8281% o argv: Specifies the application's argument list.
8282%
8283% o argc: Specifies the number of arguments.
8284%
8285% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8286%
8287% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8288%
8289% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8290%
8291*/
8292MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8293 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8294 XWindowInfo *window_info)
8295{
8296#define MinWindowSize 64
8297
8298 Atom
8299 atom_list[2];
8300
8301 int
8302 gravity;
8303
8304 static XTextProperty
8305 icon_name,
8306 window_name;
8307
8308 Status
8309 status;
8310
8311 XSizeHints
8312 *size_hints;
8313
8314 /*
8315 Set window info hints.
8316 */
8317 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8318 assert(display != (Display *) NULL);
8319 assert(window_info != (XWindowInfo *) NULL);
8320 size_hints=XAllocSizeHints();
8321 if (size_hints == (XSizeHints *) NULL)
8322 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008323 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008324 size_hints->x=window_info->x;
8325 size_hints->y=window_info->y;
8326 size_hints->width=(int) window_info->width;
8327 size_hints->height=(int) window_info->height;
8328 if (window_info->immutable != MagickFalse)
8329 {
8330 /*
8331 Window size cannot be changed.
8332 */
8333 size_hints->min_width=size_hints->width;
8334 size_hints->min_height=size_hints->height;
8335 size_hints->max_width=size_hints->width;
8336 size_hints->max_height=size_hints->height;
8337 size_hints->flags|=PMinSize;
8338 size_hints->flags|=PMaxSize;
8339 }
8340 else
8341 {
8342 /*
8343 Window size can be changed.
8344 */
8345 size_hints->min_width=(int) window_info->min_width;
8346 size_hints->min_height=(int) window_info->min_height;
8347 size_hints->flags|=PResizeInc;
8348 size_hints->width_inc=(int) window_info->width_inc;
8349 size_hints->height_inc=(int) window_info->height_inc;
8350#if !defined(PRE_R4_ICCCM)
8351 size_hints->flags|=PBaseSize;
8352 size_hints->base_width=size_hints->width_inc;
8353 size_hints->base_height=size_hints->height_inc;
8354#endif
8355 }
8356 gravity=NorthWestGravity;
8357 if (window_info->geometry != (char *) NULL)
8358 {
8359 char
8360 default_geometry[MaxTextExtent],
8361 geometry[MaxTextExtent];
8362
8363 int
8364 flags;
8365
8366 register char
8367 *p;
8368
8369 /*
8370 User specified geometry.
8371 */
8372 (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
8373 size_hints->width,size_hints->height);
8374 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8375 p=geometry;
8376 while (strlen(p) != 0)
8377 {
8378 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8379 p++;
8380 else
8381 (void) CopyMagickString(p,p+1,MaxTextExtent);
8382 }
8383 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8384 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8385 &size_hints->width,&size_hints->height,&gravity);
8386 if ((flags & WidthValue) && (flags & HeightValue))
8387 size_hints->flags|=USSize;
8388 if ((flags & XValue) && (flags & YValue))
8389 {
8390 size_hints->flags|=USPosition;
8391 window_info->x=size_hints->x;
8392 window_info->y=size_hints->y;
8393 }
8394 }
8395#if !defined(PRE_R4_ICCCM)
8396 size_hints->win_gravity=gravity;
8397 size_hints->flags|=PWinGravity;
8398#endif
8399 if (window_info->id == (Window) NULL)
8400 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8401 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8402 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008403 window_info->visual,(unsigned long) window_info->mask,
8404 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008405 else
8406 {
8407 MagickStatusType
8408 mask;
8409
8410 XEvent
8411 sans_event;
8412
8413 XWindowChanges
8414 window_changes;
8415
8416 /*
8417 Window already exists; change relevant attributes.
8418 */
cristyc57f6942010-11-12 01:47:39 +00008419 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8420 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008421 mask=ConfigureNotify;
8422 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8423 window_changes.x=window_info->x;
8424 window_changes.y=window_info->y;
8425 window_changes.width=(int) window_info->width;
8426 window_changes.height=(int) window_info->height;
8427 mask=(MagickStatusType) (CWWidth | CWHeight);
8428 if (window_info->flags & USPosition)
8429 mask|=CWX | CWY;
8430 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8431 mask,&window_changes);
8432 }
8433 if (window_info->id == (Window) NULL)
8434 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8435 window_info->name);
8436 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8437 if (status == False)
8438 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8439 window_info->name);
8440 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8441 if (status == False)
8442 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8443 window_info->icon_name);
8444 if (window_info->icon_geometry != (char *) NULL)
8445 {
8446 int
8447 flags,
8448 height,
8449 width;
8450
8451 /*
8452 User specified icon geometry.
8453 */
8454 size_hints->flags|=USPosition;
8455 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8456 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8457 &manager_hints->icon_y,&width,&height,&gravity);
8458 if ((flags & XValue) && (flags & YValue))
8459 manager_hints->flags|=IconPositionHint;
8460 }
8461 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8462 size_hints,manager_hints,class_hint);
8463 if (window_name.value != (void *) NULL)
8464 {
8465 (void) XFree((void *) window_name.value);
8466 window_name.value=(unsigned char *) NULL;
8467 window_name.nitems=0;
8468 }
8469 if (icon_name.value != (void *) NULL)
8470 {
8471 (void) XFree((void *) icon_name.value);
8472 icon_name.value=(unsigned char *) NULL;
8473 icon_name.nitems=0;
8474 }
8475 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8476 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8477 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8478 (void) XFree((void *) size_hints);
8479 if (window_info->shape != MagickFalse)
8480 {
8481#if defined(MAGICKCORE_HAVE_SHAPE)
8482 int
8483 error_base,
8484 event_base;
8485
8486 /*
8487 Can we apply a non-rectangular shaping mask?
8488 */
8489 error_base=0;
8490 event_base=0;
8491 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8492 window_info->shape=MagickFalse;
8493#else
8494 window_info->shape=MagickFalse;
8495#endif
8496 }
8497 if (window_info->shared_memory)
8498 {
8499#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8500 /*
8501 Can we use shared memory with this window?
8502 */
8503 if (XShmQueryExtension(display) == 0)
8504 window_info->shared_memory=MagickFalse;
8505#else
8506 window_info->shared_memory=MagickFalse;
8507#endif
8508 }
8509 window_info->image=NewImageList();
8510 window_info->destroy=MagickFalse;
8511}
8512
8513/*
8514%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8515% %
8516% %
8517% %
8518% X M a g i c k P r o g r e s s M o n i t o r %
8519% %
8520% %
8521% %
8522%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8523%
8524% XMagickProgressMonitor() displays the progress a task is making in
8525% completing a task.
8526%
8527% The format of the XMagickProgressMonitor method is:
8528%
8529% void XMagickProgressMonitor(const char *task,
8530% const MagickOffsetType quantum,const MagickSizeType span,
8531% void *client_data)
8532%
8533% A description of each parameter follows:
8534%
8535% o task: Identifies the task in progress.
8536%
8537% o quantum: Specifies the quantum position within the span which represents
8538% how much progress has been made in completing a task.
8539%
8540% o span: Specifies the span relative to completing a task.
8541%
8542% o client_data: Pointer to any client data.
8543%
8544*/
8545
8546static const char *GetLocaleMonitorMessage(const char *text)
8547{
8548 char
8549 message[MaxTextExtent],
8550 tag[MaxTextExtent];
8551
8552 const char
8553 *locale_message;
8554
8555 register char
8556 *p;
8557
8558 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8559 p=strrchr(tag,'/');
8560 if (p != (char *) NULL)
8561 *p='\0';
8562 (void) FormatMagickString(message,MaxTextExtent,"Monitor/%s",tag);
8563 locale_message=GetLocaleMessage(message);
8564 if (locale_message == message)
8565 return(text);
8566 return(locale_message);
8567}
8568
8569MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8570 const MagickOffsetType quantum,const MagickSizeType span,
8571 void *magick_unused(client_data))
8572{
8573 XWindows
8574 *windows;
8575
8576 windows=XSetWindows((XWindows *) ~0);
8577 if (windows == (XWindows *) NULL)
8578 return(MagickTrue);
8579 if (windows->info.mapped != MagickFalse)
8580 XProgressMonitorWidget(windows->display,windows,
8581 GetLocaleMonitorMessage(tag),quantum,span);
8582 return(MagickTrue);
8583}
8584
8585/*
8586%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8587% %
8588% %
8589% %
8590% X Q u e r y C o l o r D a t a b a s e %
8591% %
8592% %
8593% %
8594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8595%
8596% XQueryColorDatabase() looks up a RGB values for a color given in the target
8597% string.
8598%
8599% The format of the XQueryColorDatabase method is:
8600%
8601% MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8602%
8603% A description of each parameter follows:
8604%
8605% o target: Specifies the color to lookup in the X color database.
8606%
8607% o color: A pointer to an PixelPacket structure. The RGB value of the target
8608% color is returned as this value.
8609%
8610*/
8611MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8612 XColor *color)
8613{
8614 Colormap
8615 colormap;
8616
8617 static Display
8618 *display = (Display *) NULL;
8619
8620 Status
8621 status;
8622
8623 XColor
8624 xcolor;
8625
8626 /*
8627 Initialize color return value.
8628 */
8629 assert(color != (XColor *) NULL);
8630 color->red=0;
8631 color->green=0;
8632 color->blue=0;
8633 color->flags=(char) (DoRed | DoGreen | DoBlue);
8634 if ((target == (char *) NULL) || (*target == '\0'))
8635 target="#ffffffffffff";
8636 /*
8637 Let the X server define the color for us.
8638 */
8639 if (display == (Display *) NULL)
8640 display=XOpenDisplay((char *) NULL);
8641 if (display == (Display *) NULL)
8642 {
8643 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8644 return(MagickFalse);
8645 }
8646 colormap=XDefaultColormap(display,XDefaultScreen(display));
8647 status=XParseColor(display,colormap,(char *) target,&xcolor);
8648 if (status == False)
8649 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8650 else
8651 {
8652 color->red=xcolor.red;
8653 color->green=xcolor.green;
8654 color->blue=xcolor.blue;
8655 color->flags=xcolor.flags;
8656 }
8657 return(status != False ? MagickTrue : MagickFalse);
8658}
8659
8660/*
8661%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8662% %
8663% %
8664% %
8665% X Q u e r y P o s i t i o n %
8666% %
8667% %
8668% %
8669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8670%
8671% XQueryPosition() gets the pointer coordinates relative to a window.
8672%
8673% The format of the XQueryPosition method is:
8674%
8675% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8676%
8677% A description of each parameter follows:
8678%
8679% o display: Specifies a connection to an X server; returned from
8680% XOpenDisplay.
8681%
8682% o window: Specifies a pointer to a Window.
8683%
8684% o x: Return the x coordinate of the pointer relative to the origin of the
8685% window.
8686%
8687% o y: Return the y coordinate of the pointer relative to the origin of the
8688% window.
8689%
8690*/
8691MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8692{
8693 int
8694 x_root,
8695 y_root;
8696
8697 unsigned int
8698 mask;
8699
8700 Window
8701 root_window;
8702
8703 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8704 assert(display != (Display *) NULL);
8705 assert(window != (Window) NULL);
8706 assert(x != (int *) NULL);
8707 assert(y != (int *) NULL);
8708 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8709 x,y,&mask);
8710}
8711
8712/*
8713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8714% %
8715% %
8716% %
8717% X R e f r e s h W i n d o w %
8718% %
8719% %
8720% %
8721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8722%
8723% XRefreshWindow() refreshes an image in a X window.
8724%
8725% The format of the XRefreshWindow method is:
8726%
8727% void XRefreshWindow(Display *display,const XWindowInfo *window,
8728% const XEvent *event)
8729%
8730% A description of each parameter follows:
8731%
8732% o display: Specifies a connection to an X server; returned from
8733% XOpenDisplay.
8734%
8735% o window: Specifies a pointer to a XWindowInfo structure.
8736%
8737% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8738% the entire image is refreshed.
8739%
8740*/
8741MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8742 const XEvent *event)
8743{
8744 int
8745 x,
8746 y;
8747
8748 unsigned int
8749 height,
8750 width;
8751
8752 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8753 assert(display != (Display *) NULL);
8754 assert(window != (XWindowInfo *) NULL);
8755 if (window->ximage == (XImage *) NULL)
8756 return;
8757 if (event != (XEvent *) NULL)
8758 {
8759 /*
8760 Determine geometry from expose event.
8761 */
8762 x=event->xexpose.x;
8763 y=event->xexpose.y;
8764 width=(unsigned int) event->xexpose.width;
8765 height=(unsigned int) event->xexpose.height;
8766 }
8767 else
8768 {
8769 XEvent
8770 sans_event;
8771
8772 /*
8773 Refresh entire window; discard outstanding expose events.
8774 */
8775 x=0;
8776 y=0;
8777 width=window->width;
8778 height=window->height;
8779 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008780 if (window->matte_pixmap != (Pixmap) NULL)
8781 {
8782#if defined(MAGICKCORE_HAVE_SHAPE)
8783 if (window->shape != MagickFalse)
8784 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8785 window->matte_pixmap,ShapeSet);
8786#endif
8787 }
cristy3ed852e2009-09-05 21:47:34 +00008788 }
8789 /*
8790 Check boundary conditions.
8791 */
8792 if ((window->ximage->width-(x+window->x)) < (int) width)
8793 width=(unsigned int) (window->ximage->width-(x+window->x));
8794 if ((window->ximage->height-(y+window->y)) < (int) height)
8795 height=(unsigned int) (window->ximage->height-(y+window->y));
8796 /*
8797 Refresh image.
8798 */
8799 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008800 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008801 if (window->pixmap != (Pixmap) NULL)
8802 {
8803 if (window->depth > 1)
8804 (void) XCopyArea(display,window->pixmap,window->id,
8805 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8806 else
8807 (void) XCopyPlane(display,window->pixmap,window->id,
8808 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8809 1L);
8810 }
8811 else
8812 {
8813#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8814 if (window->shared_memory)
8815 (void) XShmPutImage(display,window->id,window->annotate_context,
8816 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8817#endif
8818 if (window->shared_memory == MagickFalse)
8819 (void) XPutImage(display,window->id,window->annotate_context,
8820 window->ximage,x+window->x,y+window->y,x,y,width,height);
8821 }
8822 if (window->matte_pixmap != (Pixmap) NULL)
8823 (void) XSetClipMask(display,window->annotate_context,None);
8824 (void) XFlush(display);
8825}
8826
8827/*
8828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8829% %
8830% %
8831% %
8832% X R e m o t e C o m m a n d %
8833% %
8834% %
8835% %
8836%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8837%
8838% XRemoteCommand() forces a remote display(1) to display the specified
8839% image filename.
8840%
8841% The format of the XRemoteCommand method is:
8842%
8843% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8844% const char *filename)
8845%
8846% A description of each parameter follows:
8847%
8848% o display: Specifies a connection to an X server; returned from
8849% XOpenDisplay.
8850%
8851% o window: Specifies the name or id of an X window.
8852%
8853% o filename: the name of the image filename to display.
8854%
8855*/
8856MagickExport MagickBooleanType XRemoteCommand(Display *display,
8857 const char *window,const char *filename)
8858{
8859 Atom
8860 remote_atom;
8861
8862 Window
8863 remote_window,
8864 root_window;
8865
8866 assert(filename != (char *) NULL);
8867 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8868 if (display == (Display *) NULL)
8869 display=XOpenDisplay((char *) NULL);
8870 if (display == (Display *) NULL)
8871 {
8872 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8873 return(MagickFalse);
8874 }
8875 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8876 remote_window=(Window) NULL;
8877 root_window=XRootWindow(display,XDefaultScreen(display));
8878 if (window != (char *) NULL)
8879 {
8880 /*
8881 Search window hierarchy and identify any clients by name or ID.
8882 */
8883 if (isdigit((unsigned char) *window) != 0)
8884 remote_window=XWindowByID(display,root_window,(Window)
8885 strtol((char *) window,(char **) NULL,0));
8886 if (remote_window == (Window) NULL)
8887 remote_window=XWindowByName(display,root_window,window);
8888 }
8889 if (remote_window == (Window) NULL)
8890 remote_window=XWindowByProperty(display,root_window,remote_atom);
8891 if (remote_window == (Window) NULL)
8892 {
8893 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8894 filename);
8895 return(MagickFalse);
8896 }
8897 /*
8898 Send remote command.
8899 */
8900 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8901 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8902 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8903 (void) XSync(display,MagickFalse);
8904 return(MagickTrue);
8905}
8906
8907/*
8908%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8909% %
8910% %
8911% %
8912% X R e t a i n W i n d o w C o l o r s %
8913% %
8914% %
8915% %
8916%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8917%
8918% XRetainWindowColors() sets X11 color resources on a window. This preserves
8919% the colors associated with an image displayed on the window.
8920%
8921% The format of the XRetainWindowColors method is:
8922%
8923% void XRetainWindowColors(Display *display,const Window window)
8924%
8925% A description of each parameter follows:
8926%
8927% o display: Specifies a connection to an X server; returned from
8928% XOpenDisplay.
8929%
8930% o window: Specifies a pointer to a XWindowInfo structure.
8931%
8932*/
8933MagickExport void XRetainWindowColors(Display *display,const Window window)
8934{
8935 Atom
8936 property;
8937
8938 Pixmap
8939 pixmap;
8940
8941 /*
8942 Put property on the window.
8943 */
8944 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8945 assert(display != (Display *) NULL);
8946 assert(window != (Window) NULL);
8947 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8948 if (property == (Atom) NULL)
8949 {
8950 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8951 "_XSETROOT_ID");
8952 return;
8953 }
8954 pixmap=XCreatePixmap(display,window,1,1,1);
8955 if (pixmap == (Pixmap) NULL)
8956 {
8957 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8958 return;
8959 }
8960 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8961 (unsigned char *) &pixmap,1);
8962 (void) XSetCloseDownMode(display,RetainPermanent);
8963}
8964
8965/*
8966%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8967% %
8968% %
8969% %
8970% X S e l e c t W i n d o w %
8971% %
8972% %
8973% %
8974%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8975%
8976% XSelectWindow() allows a user to select a window using the mouse. If the
8977% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
8978% is returned in the crop_info structure.
8979%
8980% The format of the XSelectWindow function is:
8981%
8982% target_window=XSelectWindow(display,crop_info)
8983%
8984% A description of each parameter follows:
8985%
8986% o window: XSelectWindow returns the window id.
8987%
8988% o display: Specifies a pointer to the Display structure; returned from
8989% XOpenDisplay.
8990%
8991% o crop_info: Specifies a pointer to a RectangleInfo structure. It
8992% contains the extents of any cropping rectangle.
8993%
cristy3ed852e2009-09-05 21:47:34 +00008994*/
8995static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
8996{
8997#define MinimumCropArea (unsigned int) 9
8998
8999 Cursor
9000 target_cursor;
9001
9002 GC
9003 annotate_context;
9004
9005 int
9006 presses,
9007 x_offset,
9008 y_offset;
9009
9010 Status
9011 status;
9012
9013 Window
9014 root_window,
9015 target_window;
9016
9017 XEvent
9018 event;
9019
9020 XGCValues
9021 context_values;
9022
9023 /*
9024 Initialize graphic context.
9025 */
9026 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9027 assert(display != (Display *) NULL);
9028 assert(crop_info != (RectangleInfo *) NULL);
9029 root_window=XRootWindow(display,XDefaultScreen(display));
9030 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9031 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9032 context_values.function=GXinvert;
9033 context_values.plane_mask=
9034 context_values.background ^ context_values.foreground;
9035 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009036 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009037 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9038 if (annotate_context == (GC) NULL)
9039 return(MagickFalse);
9040 /*
9041 Grab the pointer using target cursor.
9042 */
9043 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9044 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9045 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9046 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9047 GrabModeAsync,root_window,target_cursor,CurrentTime);
9048 if (status != GrabSuccess)
9049 {
9050 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9051 return((Window) NULL);
9052 }
9053 /*
9054 Select a window.
9055 */
9056 crop_info->width=0;
9057 crop_info->height=0;
9058 presses=0;
9059 target_window=(Window) NULL;
9060 x_offset=0;
9061 y_offset=0;
9062 do
9063 {
9064 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9065 (void) XDrawRectangle(display,root_window,annotate_context,
9066 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9067 (unsigned int) crop_info->height-1);
9068 /*
9069 Allow another event.
9070 */
9071 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9072 (void) XWindowEvent(display,root_window,ButtonPressMask |
9073 ButtonReleaseMask | ButtonMotionMask,&event);
9074 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9075 (void) XDrawRectangle(display,root_window,annotate_context,
9076 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9077 (unsigned int) crop_info->height-1);
9078 switch (event.type)
9079 {
9080 case ButtonPress:
9081 {
9082 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9083 event.xbutton.x,event.xbutton.y);
9084 if (target_window == (Window) NULL)
9085 target_window=root_window;
9086 x_offset=event.xbutton.x_root;
9087 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009088 crop_info->x=(ssize_t) x_offset;
9089 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009090 crop_info->width=0;
9091 crop_info->height=0;
9092 presses++;
9093 break;
9094 }
9095 case ButtonRelease:
9096 {
9097 presses--;
9098 break;
9099 }
9100 case MotionNotify:
9101 {
9102 /*
9103 Discard pending button motion events.
9104 */
9105 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009106 crop_info->x=(ssize_t) event.xmotion.x;
9107 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009108 /*
9109 Check boundary conditions.
9110 */
9111 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009112 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009113 else
9114 {
cristyecd0ab52010-05-30 14:59:20 +00009115 crop_info->width=(size_t) (crop_info->x-x_offset);
9116 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009117 }
9118 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009119 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009120 else
9121 {
cristyecd0ab52010-05-30 14:59:20 +00009122 crop_info->height=(size_t) (crop_info->y-y_offset);
9123 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009124 }
9125 }
9126 default:
9127 break;
9128 }
9129 } while ((target_window == (Window) NULL) || (presses > 0));
9130 (void) XUngrabPointer(display,CurrentTime);
9131 (void) XFreeCursor(display,target_cursor);
9132 (void) XFreeGC(display,annotate_context);
9133 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9134 {
9135 crop_info->width=0;
9136 crop_info->height=0;
9137 }
9138 if ((crop_info->width != 0) && (crop_info->height != 0))
9139 target_window=root_window;
9140 return(target_window);
9141}
9142
9143/*
9144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9145% %
9146% %
9147% %
9148% X S e t C u r s o r S t a t e %
9149% %
9150% %
9151% %
9152%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9153%
9154% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9155% reset to their default.
9156%
9157% The format of the XXSetCursorState method is:
9158%
9159% XSetCursorState(display,windows,const MagickStatusType state)
9160%
9161% A description of each parameter follows:
9162%
9163% o display: Specifies a connection to an X server; returned from
9164% XOpenDisplay.
9165%
9166% o windows: Specifies a pointer to a XWindows structure.
9167%
9168% o state: An unsigned integer greater than 0 sets the cursor state
9169% to busy, otherwise the cursor are reset to their default.
9170%
9171*/
9172MagickExport void XSetCursorState(Display *display,XWindows *windows,
9173 const MagickStatusType state)
9174{
9175 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9176 assert(display != (Display *) NULL);
9177 assert(windows != (XWindows *) NULL);
9178 if (state)
9179 {
9180 (void) XCheckDefineCursor(display,windows->image.id,
9181 windows->image.busy_cursor);
9182 (void) XCheckDefineCursor(display,windows->pan.id,
9183 windows->pan.busy_cursor);
9184 (void) XCheckDefineCursor(display,windows->magnify.id,
9185 windows->magnify.busy_cursor);
9186 (void) XCheckDefineCursor(display,windows->command.id,
9187 windows->command.busy_cursor);
9188 }
9189 else
9190 {
9191 (void) XCheckDefineCursor(display,windows->image.id,
9192 windows->image.cursor);
9193 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9194 (void) XCheckDefineCursor(display,windows->magnify.id,
9195 windows->magnify.cursor);
9196 (void) XCheckDefineCursor(display,windows->command.id,
9197 windows->command.cursor);
9198 (void) XCheckDefineCursor(display,windows->command.id,
9199 windows->widget.cursor);
9200 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9201 }
9202 windows->info.mapped=MagickFalse;
9203}
9204
9205/*
9206%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9207% %
9208% %
9209% %
9210% X S e t W i n d o w s %
9211% %
9212% %
9213% %
9214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9215%
9216% XSetWindows() sets the X windows structure if the windows info is specified.
9217% Otherwise the current windows structure is returned.
9218%
9219% The format of the XSetWindows method is:
9220%
9221% XWindows *XSetWindows(XWindows *windows_info)
9222%
9223% A description of each parameter follows:
9224%
9225% o windows_info: Initialize the Windows structure with this information.
9226%
9227*/
9228MagickExport XWindows *XSetWindows(XWindows *windows_info)
9229{
9230 static XWindows
9231 *windows = (XWindows *) NULL;
9232
9233 if (windows_info != (XWindows *) ~0)
9234 {
9235 windows=(XWindows *) RelinquishMagickMemory(windows);
9236 windows=windows_info;
9237 }
9238 return(windows);
9239}
9240/*
9241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9242% %
9243% %
9244% %
9245% X U s e r P r e f e r e n c e s %
9246% %
9247% %
9248% %
9249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9250%
9251% XUserPreferences() saves the preferences in a configuration file in the
9252% users' home directory.
9253%
9254% The format of the XUserPreferences method is:
9255%
9256% void XUserPreferences(XResourceInfo *resource_info)
9257%
9258% A description of each parameter follows:
9259%
9260% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9261%
9262*/
9263MagickExport void XUserPreferences(XResourceInfo *resource_info)
9264{
9265#if defined(X11_PREFERENCES_PATH)
9266 char
9267 cache[MaxTextExtent],
9268 filename[MaxTextExtent],
9269 specifier[MaxTextExtent];
9270
9271 const char
cristy104cea82009-10-25 02:26:51 +00009272 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009273 *value;
9274
9275 XrmDatabase
9276 preferences_database;
9277
9278 /*
9279 Save user preferences to the client configuration file.
9280 */
9281 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009282 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009283 preferences_database=XrmGetStringDatabase("");
cristy104cea82009-10-25 02:26:51 +00009284 (void) FormatMagickString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009285 value=resource_info->backdrop ? "True" : "False";
9286 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009287 (void) FormatMagickString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009288 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9289 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9290 (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009291 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009292 value=resource_info->confirm_exit ? "True" : "False";
9293 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9294 (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009295 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009296 value=resource_info->confirm_edit ? "True" : "False";
9297 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9298 (void) FormatMagickString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009299 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009300 value=resource_info->display_warnings ? "True" : "False";
9301 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009302 (void) FormatMagickString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009303 value=resource_info->quantize_info->dither ? "True" : "False";
9304 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9305 (void) FormatMagickString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009306 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009307 value=resource_info->gamma_correct ? "True" : "False";
9308 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009309 (void) FormatMagickString(specifier,MaxTextExtent,"%s.undoCache",client_name);
cristye8c25f92010-06-03 00:53:06 +00009310 (void) FormatMagickString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009311 resource_info->undo_cache);
9312 XrmPutStringResource(&preferences_database,specifier,cache);
cristy104cea82009-10-25 02:26:51 +00009313 (void) FormatMagickString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009314 value=resource_info->use_pixmap ? "True" : "False";
9315 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9316 (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009317 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009318 ExpandFilename(filename);
9319 XrmPutFileDatabase(preferences_database,filename);
9320#endif
9321}
9322
9323/*
9324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9325% %
9326% %
9327% %
9328% X V i s u a l C l a s s N a m e %
9329% %
9330% %
9331% %
9332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9333%
9334% XVisualClassName() returns the visual class name as a character string.
9335%
9336% The format of the XVisualClassName method is:
9337%
9338% char *XVisualClassName(const int visual_class)
9339%
9340% A description of each parameter follows:
9341%
9342% o visual_type: XVisualClassName returns the visual class as a character
9343% string.
9344%
9345% o class: Specifies the visual class.
9346%
cristy3ed852e2009-09-05 21:47:34 +00009347*/
9348static const char *XVisualClassName(const int visual_class)
9349{
9350 switch (visual_class)
9351 {
9352 case StaticGray: return("StaticGray");
9353 case GrayScale: return("GrayScale");
9354 case StaticColor: return("StaticColor");
9355 case PseudoColor: return("PseudoColor");
9356 case TrueColor: return("TrueColor");
9357 case DirectColor: return("DirectColor");
9358 }
9359 return("unknown visual class");
9360}
9361
9362/*
9363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9364% %
9365% %
9366% %
9367% X W a r n i n g %
9368% %
9369% %
9370% %
9371%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9372%
9373% XWarning() displays a warning reason in a Notice widget.
9374%
9375% The format of the XWarning method is:
9376%
9377% void XWarning(const unsigned int warning,const char *reason,
9378% const char *description)
9379%
9380% A description of each parameter follows:
9381%
9382% o warning: Specifies the numeric warning category.
9383%
9384% o reason: Specifies the reason to display before terminating the
9385% program.
9386%
9387% o description: Specifies any description to the reason.
9388%
9389*/
9390MagickExport void XWarning(const ExceptionType magick_unused(warning),
9391 const char *reason,const char *description)
9392{
9393 char
9394 text[MaxTextExtent];
9395
9396 XWindows
9397 *windows;
9398
9399 if (reason == (char *) NULL)
9400 return;
9401 (void) CopyMagickString(text,reason,MaxTextExtent);
9402 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9403 windows=XSetWindows((XWindows *) ~0);
9404 XNoticeWidget(windows->display,windows,text,(char *) description);
9405}
9406
9407/*
9408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9409% %
9410% %
9411% %
9412% X W i n d o w B y I D %
9413% %
9414% %
9415% %
9416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9417%
9418% XWindowByID() locates a child window with a given ID. If not window with
9419% the given name is found, 0 is returned. Only the window specified and its
9420% subwindows are searched.
9421%
9422% The format of the XWindowByID function is:
9423%
9424% child=XWindowByID(display,window,id)
9425%
9426% A description of each parameter follows:
9427%
9428% o child: XWindowByID returns the window with the specified
9429% id. If no windows are found, XWindowByID returns 0.
9430%
9431% o display: Specifies a pointer to the Display structure; returned from
9432% XOpenDisplay.
9433%
9434% o id: Specifies the id of the window to locate.
9435%
9436*/
9437MagickExport Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009438 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009439{
9440 RectangleInfo
9441 rectangle_info;
9442
9443 register int
9444 i;
9445
9446 Status
9447 status;
9448
9449 unsigned int
9450 number_children;
9451
9452 Window
9453 child,
9454 *children,
9455 window;
9456
9457 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9458 assert(display != (Display *) NULL);
9459 assert(root_window != (Window) NULL);
9460 if (id == 0)
9461 return(XSelectWindow(display,&rectangle_info));
9462 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009463 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009464 status=XQueryTree(display,root_window,&child,&child,&children,
9465 &number_children);
9466 if (status == False)
9467 return((Window) NULL);
9468 window=(Window) NULL;
9469 for (i=0; i < (int) number_children; i++)
9470 {
9471 /*
9472 Search each child and their children.
9473 */
9474 window=XWindowByID(display,children[i],id);
9475 if (window != (Window) NULL)
9476 break;
9477 }
9478 if (children != (Window *) NULL)
9479 (void) XFree((void *) children);
9480 return(window);
9481}
9482
9483/*
9484%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9485% %
9486% %
9487% %
9488% X W i n d o w B y N a m e %
9489% %
9490% %
9491% %
9492%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9493%
9494% XWindowByName() locates a window with a given name on a display. If no
9495% window with the given name is found, 0 is returned. If more than one window
9496% has the given name, the first one is returned. Only root and its children
9497% are searched.
9498%
9499% The format of the XWindowByName function is:
9500%
9501% window=XWindowByName(display,root_window,name)
9502%
9503% A description of each parameter follows:
9504%
9505% o window: XWindowByName returns the window id.
9506%
9507% o display: Specifies a pointer to the Display structure; returned from
9508% XOpenDisplay.
9509%
9510% o root_window: Specifies the id of the root window.
9511%
9512% o name: Specifies the name of the window to locate.
9513%
9514*/
9515MagickExport Window XWindowByName(Display *display,const Window root_window,
9516 const char *name)
9517{
9518 register int
9519 i;
9520
9521 Status
9522 status;
9523
9524 unsigned int
9525 number_children;
9526
9527 Window
9528 *children,
9529 child,
9530 window;
9531
9532 XTextProperty
9533 window_name;
9534
9535 assert(display != (Display *) NULL);
9536 assert(root_window != (Window) NULL);
9537 assert(name != (char *) NULL);
9538 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9539 if (XGetWMName(display,root_window,&window_name) != 0)
9540 if (LocaleCompare((char *) window_name.value,name) == 0)
9541 return(root_window);
9542 status=XQueryTree(display,root_window,&child,&child,&children,
9543 &number_children);
9544 if (status == False)
9545 return((Window) NULL);
9546 window=(Window) NULL;
9547 for (i=0; i < (int) number_children; i++)
9548 {
9549 /*
9550 Search each child and their children.
9551 */
9552 window=XWindowByName(display,children[i],name);
9553 if (window != (Window) NULL)
9554 break;
9555 }
9556 if (children != (Window *) NULL)
9557 (void) XFree((void *) children);
9558 return(window);
9559}
9560
9561/*
9562%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9563% %
9564% %
9565% %
9566% X W i n d o w B y P r o p e r y %
9567% %
9568% %
9569% %
9570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9571%
9572% XWindowByProperty() locates a child window with a given property. If not
9573% window with the given name is found, 0 is returned. If more than one window
9574% has the given property, the first one is returned. Only the window
9575% specified and its subwindows are searched.
9576%
9577% The format of the XWindowByProperty function is:
9578%
9579% child=XWindowByProperty(display,window,property)
9580%
9581% A description of each parameter follows:
9582%
9583% o child: XWindowByProperty returns the window id with the specified
9584% property. If no windows are found, XWindowByProperty returns 0.
9585%
9586% o display: Specifies a pointer to the Display structure; returned from
9587% XOpenDisplay.
9588%
9589% o property: Specifies the property of the window to locate.
9590%
9591*/
9592MagickExport Window XWindowByProperty(Display *display,const Window window,
9593 const Atom property)
9594{
9595 Atom
9596 type;
9597
9598 int
9599 format;
9600
9601 Status
9602 status;
9603
9604 unsigned char
9605 *data;
9606
9607 unsigned int
9608 i,
9609 number_children;
9610
cristyf2faecf2010-05-28 19:19:36 +00009611 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009612 after,
9613 number_items;
9614
9615 Window
9616 child,
9617 *children,
9618 parent,
9619 root;
9620
9621 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9622 assert(display != (Display *) NULL);
9623 assert(window != (Window) NULL);
9624 assert(property != (Atom) NULL);
9625 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9626 if (status == False)
9627 return((Window) NULL);
9628 type=(Atom) NULL;
9629 child=(Window) NULL;
9630 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9631 {
9632 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9633 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9634 if (data != NULL)
9635 (void) XFree((void *) data);
9636 if ((status == Success) && (type != (Atom) NULL))
9637 child=children[i];
9638 }
9639 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9640 child=XWindowByProperty(display,children[i],property);
9641 if (children != (Window *) NULL)
9642 (void) XFree((void *) children);
9643 return(child);
9644}
9645#else
9646
9647/*
9648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9649% %
9650% %
9651% %
9652% X I m p o r t I m a g e %
9653% %
9654% %
9655% %
9656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9657%
9658% XImportImage() reads an image from an X window.
9659%
9660% The format of the XImportImage method is:
9661%
9662% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9663%
9664% A description of each parameter follows:
9665%
9666% o image_info: the image info..
9667%
9668% o ximage_info: Specifies a pointer to an XImportInfo structure.
9669%
9670*/
9671MagickExport Image *XImportImage(const ImageInfo *image_info,
9672 XImportInfo *ximage_info)
9673{
9674 assert(image_info != (const ImageInfo *) NULL);
9675 assert(image_info->signature == MagickSignature);
9676 if (image_info->debug != MagickFalse)
9677 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9678 image_info->filename);
9679 assert(ximage_info != (XImportInfo *) NULL);
9680 return((Image *) NULL);
9681}
9682#endif
9683
9684/*
9685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9686% %
9687% %
9688% %
cristy576974e2009-10-25 20:45:31 +00009689+ X C o m p o n e n t G e n e s i s %
9690% %
9691% %
9692% %
9693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9694%
9695% XComponentGenesis() instantiates the X component.
9696%
9697% The format of the XComponentGenesis method is:
9698%
9699% MagickBooleanType XComponentGenesis(void)
9700%
9701*/
9702MagickExport MagickBooleanType XComponentGenesis(void)
9703{
9704 return(MagickTrue);
9705}
9706
9707/*
9708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9709% %
9710% %
9711% %
cristy3ed852e2009-09-05 21:47:34 +00009712% X G e t I m p o r t I n f o %
9713% %
9714% %
9715% %
9716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9717%
9718% XGetImportInfo() initializes the XImportInfo structure.
9719%
9720% The format of the XGetImportInfo method is:
9721%
9722% void XGetImportInfo(XImportInfo *ximage_info)
9723%
9724% A description of each parameter follows:
9725%
9726% o ximage_info: Specifies a pointer to an ImageInfo structure.
9727%
9728*/
9729MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9730{
9731 assert(ximage_info != (XImportInfo *) NULL);
9732 ximage_info->frame=MagickFalse;
9733 ximage_info->borders=MagickFalse;
9734 ximage_info->screen=MagickFalse;
9735 ximage_info->descend=MagickTrue;
9736 ximage_info->silent=MagickFalse;
9737}