blob: 142c42ae00f90ff67fada32e1bc5787714e068a8 [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
3440 *cwd,
3441 *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");
cristye27293e2009-12-18 02:53:20 +00003465 resource_info->border_width=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003466 resource_value=XGetResourceClass(database,client_name,"colormap",
3467 (char *) "shared");
3468 resource_info->colormap=UndefinedColormap;
3469 if (LocaleCompare("private",resource_value) == 0)
3470 resource_info->colormap=PrivateColormap;
3471 if (LocaleCompare("shared",resource_value) == 0)
3472 resource_info->colormap=SharedColormap;
3473 if (resource_info->colormap == UndefinedColormap)
3474 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3475 resource_value);
3476 resource_value=XGetResourceClass(database,client_name,
3477 "colorRecovery",(char *) "False");
3478 resource_info->color_recovery=IsMagickTrue(resource_value);
3479 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3480 (char *) "False");
3481 resource_info->confirm_exit=IsMagickTrue(resource_value);
3482 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3483 (char *) "False");
3484 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003485 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003486 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003487 resource_info->display_gamma=XGetResourceClass(database,client_name,
3488 "displayGamma",(char *) "2.2");
3489 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3490 (char *) "True");
3491 resource_info->display_warnings=IsMagickTrue(resource_value);
3492 resource_info->font=XGetResourceClass(database,client_name,"font",
3493 (char *) NULL);
3494 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3495 resource_info->font);
3496 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3497 (char *) "fixed");
3498 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3499 (char *) "variable");
3500 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3501 (char *) "5x8");
3502 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3503 (char *) "6x10");
3504 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3505 (char *) "7x13bold");
3506 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3507 (char *) "8x13bold");
3508 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3509 (char *) "9x15bold");
3510 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3511 (char *) "10x20");
3512 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3513 (char *) "12x24");
3514 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3515 (char *) "fixed");
3516 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3517 (char *) "fixed");
3518 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3519 "foreground",ForegroundColor);
3520 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3521 (char *) "True");
3522 resource_info->gamma_correct=IsMagickTrue(resource_value);
3523 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3524 client_name,"geometry",(char *) NULL));
3525 resource_value=XGetResourceClass(database,client_name,"gravity",
3526 (char *) "Center");
3527 resource_info->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
3528 MagickFalse,resource_value);
3529 cwd=getcwd(resource_info->home_directory,MaxTextExtent);
3530 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3531 "iconGeometry",(char *) NULL);
3532 resource_value=XGetResourceClass(database,client_name,"iconic",
3533 (char *) "False");
3534 resource_info->iconic=IsMagickTrue(resource_value);
3535 resource_value=XGetResourceClass(database,client_name,"immutable",
3536 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3537 (char *) "False");
3538 resource_info->immutable=IsMagickTrue(resource_value);
3539 resource_value=XGetResourceClass(database,client_name,"magnify",
3540 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003541 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003542 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3543 (char *) NULL);
3544 resource_info->matte_color=XGetResourceInstance(database,client_name,
3545 "mattecolor",(char *) NULL);
3546 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3547 "name",(char *) NULL));
3548 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3549 (char *) "black");
3550 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3551 (char *) "blue");
3552 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3553 (char *) "cyan");
3554 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3555 (char *) "green");
3556 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3557 (char *) "gray");
3558 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3559 (char *) "red");
3560 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3561 (char *) "magenta");
3562 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3563 (char *) "yellow");
3564 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3565 (char *) "white");
3566 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3567 (char *) "gray");
3568 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3569 (char *) "gray");
3570 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003571 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003572 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003573 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003574 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3575 "font",(char *) "fixed");
3576 resource_info->text_font=XGetResourceClass(database,client_name,
3577 "textFontList",resource_info->text_font);
3578 resource_info->title=XGetResourceClass(database,client_name,"title",
3579 (char *) NULL);
3580 resource_value=XGetResourceClass(database,client_name,"undoCache",
3581 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003582 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003583 resource_value=XGetResourceClass(database,client_name,"update",
3584 (char *) "False");
3585 resource_info->update=IsMagickTrue(resource_value);
3586 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3587 (char *) "True");
3588 resource_info->use_pixmap=IsMagickTrue(resource_value);
3589 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3590 (char *) "True");
3591 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3592 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3593 (char *) NULL);
3594 resource_info->window_group=XGetResourceClass(database,client_name,
3595 "windowGroup",(char *) NULL);
3596 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3597 (char *) NULL);
3598 resource_info->write_filename=XGetResourceClass(database,client_name,
3599 "writeFilename",(char *) NULL);
3600}
3601
3602/*
3603%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3604% %
3605% %
3606% %
3607% X G e t R e s o u r c e I n s t a n c e %
3608% %
3609% %
3610% %
3611%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3612%
3613% XGetResourceInstance() queries the X server for the specified resource name.
3614% If the resource name is not defined in the database, the supplied default
3615% value is returned.
3616%
3617% The format of the XGetResourceInstance method is:
3618%
3619% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3620% const char *keyword,const char *resource_default)
3621%
3622% A description of each parameter follows:
3623%
3624% o database: Specifies a resource database; returned from
3625% XrmGetStringDatabase.
3626%
3627% o client_name: Specifies the application name used to retrieve
3628% resource info from the X server database.
3629%
3630% o keyword: Specifies the keyword of the value being retrieved.
3631%
3632% o resource_default: Specifies the default value to return if the query
3633% fails to find the specified keyword/class.
3634%
3635*/
3636MagickExport char *XGetResourceInstance(XrmDatabase database,
3637 const char *client_name,const char *keyword,const char *resource_default)
3638{
3639 char
3640 *resource_type,
3641 resource_name[MaxTextExtent];
3642
3643 Status
3644 status;
3645
3646 XrmValue
3647 resource_value;
3648
3649 if (database == (XrmDatabase) NULL)
3650 return((char *) resource_default);
3651 *resource_name='\0';
3652 if (keyword != (char *) NULL)
3653 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",client_name,
3654 keyword);
3655 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3656 &resource_value);
3657 if (status == False)
3658 return((char *) resource_default);
3659 return(resource_value.addr);
3660}
3661
3662/*
3663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3664% %
3665% %
3666% %
3667% X G e t S c r e e n D e n s i t y %
3668% %
3669% %
3670% %
3671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3672%
3673% XGetScreenDensity() returns the density of the X server screen in
3674% dots-per-inch.
3675%
3676% The format of the XGetScreenDensity method is:
3677%
3678% char *XGetScreenDensity(Display *display)
3679%
3680% A description of each parameter follows:
3681%
3682% o density: XGetScreenDensity() returns the density of the X screen in
3683% dots-per-inch.
3684%
3685% o display: Specifies a connection to an X server; returned from
3686% XOpenDisplay.
3687%
3688*/
3689MagickExport char *XGetScreenDensity(Display *display)
3690{
3691 char
3692 density[MaxTextExtent];
3693
3694 double
3695 x_density,
3696 y_density;
3697
3698 /*
3699 Set density as determined by screen size.
3700 */
3701 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3702 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3703 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3704 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristye7f51092010-01-17 00:39:37 +00003705 (void) FormatMagickString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003706 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003707 return(GetPageGeometry(density));
3708}
3709
3710/*
3711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3712% %
3713% %
3714% %
3715+ X G e t S u b w i n d o w %
3716% %
3717% %
3718% %
3719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3720%
3721% XGetSubwindow() returns the subwindow of a window chosen the user with the
3722% pointer and a button press.
3723%
3724% The format of the XGetSubwindow method is:
3725%
3726% Window XGetSubwindow(Display *display,Window window,int x,int y)
3727%
3728% A description of each parameter follows:
3729%
3730% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3731% otherwise the subwindow is returned.
3732%
3733% o display: Specifies a connection to an X server; returned from
3734% XOpenDisplay.
3735%
3736% o window: Specifies a pointer to a Window.
3737%
3738% o x: the x coordinate of the pointer relative to the origin of the
3739% window.
3740%
3741% o y: the y coordinate of the pointer relative to the origin of the
3742% window.
3743%
cristy3ed852e2009-09-05 21:47:34 +00003744*/
3745static Window XGetSubwindow(Display *display,Window window,int x,int y)
3746{
3747 int
3748 x_offset,
3749 y_offset;
3750
3751 Status
3752 status;
3753
3754 Window
3755 source_window,
3756 target_window;
3757
3758 assert(display != (Display *) NULL);
3759 source_window=XRootWindow(display,XDefaultScreen(display));
3760 if (window == (Window) NULL)
3761 return(source_window);
3762 target_window=window;
3763 for ( ; ; )
3764 {
3765 status=XTranslateCoordinates(display,source_window,window,x,y,
3766 &x_offset,&y_offset,&target_window);
3767 if (status != True)
3768 break;
3769 if (target_window == (Window) NULL)
3770 break;
3771 source_window=window;
3772 window=target_window;
3773 x=x_offset;
3774 y=y_offset;
3775 }
3776 if (target_window == (Window) NULL)
3777 target_window=window;
3778 return(target_window);
3779}
3780
3781/*
3782%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3783% %
3784% %
3785% %
3786% X G e t W i n d o w C o l o r %
3787% %
3788% %
3789% %
3790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3791%
3792% XGetWindowColor() returns the color of a pixel interactively chosen from the
3793% X server.
3794%
3795% The format of the XGetWindowColor method is:
3796%
3797% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3798% char *name)
3799%
3800% A description of each parameter follows:
3801%
3802% o display: Specifies a connection to an X server; returned from
3803% XOpenDisplay.
3804%
3805% o windows: Specifies a pointer to a XWindows structure.
3806%
3807% o name: the name of the color if found in the X Color Database is
3808% returned in this character string.
3809%
3810*/
3811MagickExport MagickBooleanType XGetWindowColor(Display *display,
3812 XWindows *windows,char *name)
3813{
3814 int
3815 x,
3816 y;
3817
3818 PixelPacket
3819 pixel;
3820
3821 RectangleInfo
3822 crop_info;
3823
3824 Status
3825 status;
3826
3827 Window
3828 child,
3829 client_window,
3830 root_window,
3831 target_window;
3832
3833 XColor
3834 color;
3835
3836 XImage
3837 *ximage;
3838
3839 XWindowAttributes
3840 window_attributes;
3841
3842 /*
3843 Choose a pixel from the X server.
3844 */
3845 assert(display != (Display *) NULL);
3846 assert(name != (char *) NULL);
3847 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3848 *name='\0';
3849 target_window=XSelectWindow(display,&crop_info);
3850 if (target_window == (Window) NULL)
3851 return(MagickFalse);
3852 root_window=XRootWindow(display,XDefaultScreen(display));
3853 client_window=target_window;
3854 if (target_window != root_window)
3855 {
3856 unsigned int
3857 d;
3858
3859 /*
3860 Get client window.
3861 */
3862 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3863 if (status != False)
3864 {
3865 client_window=XClientWindow(display,target_window);
3866 target_window=client_window;
3867 }
3868 }
3869 /*
3870 Verify window is viewable.
3871 */
3872 status=XGetWindowAttributes(display,target_window,&window_attributes);
3873 if ((status == False) || (window_attributes.map_state != IsViewable))
3874 return(MagickFalse);
3875 /*
3876 Get window X image.
3877 */
3878 (void) XTranslateCoordinates(display,root_window,target_window,
3879 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3880 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3881 if (ximage == (XImage *) NULL)
3882 return(MagickFalse);
3883 color.pixel=XGetPixel(ximage,0,0);
3884 XDestroyImage(ximage);
3885 /*
3886 Match color against the color database.
3887 */
3888 (void) XQueryColor(display,window_attributes.colormap,&color);
3889 pixel.red=ScaleShortToQuantum(color.red);
3890 pixel.green=ScaleShortToQuantum(color.green);
3891 pixel.blue=ScaleShortToQuantum(color.blue);
3892 pixel.opacity=OpaqueOpacity;
3893 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3894 &windows->image.image->exception);
3895 return(MagickTrue);
3896}
3897
3898/*
3899%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3900% %
3901% %
3902% %
3903+ X G e t W i n d o w I m a g e %
3904% %
3905% %
3906% %
3907%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3908%
3909% XGetWindowImage() reads an image from the target X window and returns it.
3910% XGetWindowImage() optionally descends the window hierarchy and overlays the
3911% target image with each child image in an optimized fashion. Any child
3912% window that have the same visual, colormap, and are contained by its parent
3913% are exempted.
3914%
3915% The format of the XGetWindowImage method is:
3916%
3917% Image *XGetWindowImage(Display *display,const Window window,
3918% const unsigned int borders,const unsigned int level)
3919%
3920% A description of each parameter follows:
3921%
3922% o display: Specifies a connection to an X server; returned from
3923% XOpenDisplay.
3924%
3925% o window: Specifies the window to obtain the image from.
3926%
3927% o borders: Specifies whether borders pixels are to be saved with
3928% the image.
3929%
3930% o level: Specifies an unsigned integer representing the level of
3931% decent in the window hierarchy. This value must be zero or one on
3932% the initial call to XGetWindowImage. A value of zero returns after
3933% one call. A value of one causes the function to descend the window
3934% hierarchy and overlay the target image with each subwindow image.
3935%
cristy3ed852e2009-09-05 21:47:34 +00003936*/
3937static Image *XGetWindowImage(Display *display,const Window window,
3938 const unsigned int borders,const unsigned int level)
3939{
3940 typedef struct _ColormapInfo
3941 {
3942 Colormap
3943 colormap;
3944
3945 XColor
3946 *colors;
3947
3948 struct _ColormapInfo
3949 *next;
3950 } ColormapInfo;
3951
3952 typedef struct _WindowInfo
3953 {
3954 Window
3955 window,
3956 parent;
3957
3958 Visual
3959 *visual;
3960
3961 Colormap
3962 colormap;
3963
3964 XSegment
3965 bounds;
3966
3967 RectangleInfo
3968 crop_info;
3969 } WindowInfo;
3970
3971 IndexPacket
3972 index;
3973
3974 int
3975 display_height,
3976 display_width,
3977 id,
3978 x_offset,
3979 y_offset;
3980
3981 RectangleInfo
3982 crop_info;
3983
3984 register IndexPacket
3985 *indexes;
3986
3987 register int
3988 i;
3989
3990 static ColormapInfo
3991 *colormap_info = (ColormapInfo *) NULL;
3992
3993 static int
3994 max_windows = 0,
3995 number_windows = 0;
3996
3997 static WindowInfo
3998 *window_info;
3999
4000 Status
4001 status;
4002
4003 Window
4004 child,
4005 root_window;
4006
4007 XWindowAttributes
4008 window_attributes;
4009
4010 /*
4011 Verify window is viewable.
4012 */
4013 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4014 assert(display != (Display *) NULL);
4015 status=XGetWindowAttributes(display,window,&window_attributes);
4016 if ((status == False) || (window_attributes.map_state != IsViewable))
4017 return((Image *) NULL);
4018 /*
4019 Cropping rectangle is relative to root window.
4020 */
4021 root_window=XRootWindow(display,XDefaultScreen(display));
4022 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4023 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004024 crop_info.x=(ssize_t) x_offset;
4025 crop_info.y=(ssize_t) y_offset;
4026 crop_info.width=(size_t) window_attributes.width;
4027 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004028 if (borders != MagickFalse)
4029 {
4030 /*
4031 Include border in image.
4032 */
cristybb503372010-05-27 20:51:26 +00004033 crop_info.x-=(ssize_t) window_attributes.border_width;
4034 crop_info.y-=(ssize_t) window_attributes.border_width;
4035 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4036 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004037 }
4038 /*
4039 Crop to root window.
4040 */
4041 if (crop_info.x < 0)
4042 {
4043 crop_info.width+=crop_info.x;
4044 crop_info.x=0;
4045 }
4046 if (crop_info.y < 0)
4047 {
4048 crop_info.height+=crop_info.y;
4049 crop_info.y=0;
4050 }
4051 display_width=XDisplayWidth(display,XDefaultScreen(display));
4052 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004053 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004054 display_height=XDisplayHeight(display,XDefaultScreen(display));
4055 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004056 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004057 /*
4058 Initialize window info attributes.
4059 */
4060 if (number_windows >= max_windows)
4061 {
4062 /*
4063 Allocate or resize window info buffer.
4064 */
4065 max_windows+=1024;
4066 if (window_info == (WindowInfo *) NULL)
4067 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4068 sizeof(*window_info));
4069 else
4070 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4071 max_windows,sizeof(*window_info));
4072 }
4073 if (window_info == (WindowInfo *) NULL)
4074 {
4075 ThrowXWindowFatalException(ResourceLimitError,
4076 "MemoryAllocationFailed","...");
4077 return((Image *) NULL);
4078 }
4079 id=number_windows++;
4080 window_info[id].window=window;
4081 window_info[id].visual=window_attributes.visual;
4082 window_info[id].colormap=window_attributes.colormap;
4083 window_info[id].bounds.x1=(short) crop_info.x;
4084 window_info[id].bounds.y1=(short) crop_info.y;
4085 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4086 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4087 crop_info.x-=x_offset;
4088 crop_info.y-=y_offset;
4089 window_info[id].crop_info=crop_info;
4090 if (level != 0)
4091 {
4092 unsigned int
4093 number_children;
4094
4095 Window
4096 *children;
4097
4098 /*
4099 Descend the window hierarchy.
4100 */
4101 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4102 &children,&number_children);
4103 for (i=0; i < id; i++)
4104 if ((window_info[i].window == window_info[id].parent) &&
4105 (window_info[i].visual == window_info[id].visual) &&
4106 (window_info[i].colormap == window_info[id].colormap))
4107 {
4108 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4109 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4110 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4111 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4112 {
4113 /*
4114 Eliminate windows not circumscribed by their parent.
4115 */
4116 number_windows--;
4117 break;
4118 }
4119 }
4120 if ((status == True) && (number_children != 0))
4121 {
4122 for (i=0; i < (int) number_children; i++)
4123 (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4124 (void) XFree((void *) children);
4125 }
4126 }
4127 if (level <= 1)
4128 {
cristyc57f6942010-11-12 01:47:39 +00004129 CacheView
4130 *composite_view;
4131
cristy3ed852e2009-09-05 21:47:34 +00004132 ColormapInfo
4133 *next;
4134
4135 ExceptionInfo
4136 *exception;
4137
4138 Image
4139 *composite_image,
4140 *image;
4141
4142 int
4143 y;
4144
4145 MagickBooleanType
4146 import;
4147
4148 register int
4149 j,
4150 x;
4151
4152 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00004153 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004154
cristybb503372010-05-27 20:51:26 +00004155 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004156 pixel;
4157
4158 unsigned int
4159 number_colors;
4160
4161 XColor
4162 *colors;
4163
4164 XImage
4165 *ximage;
4166
4167 /*
4168 Get X image for each window in the list.
4169 */
4170 image=NewImageList();
4171 for (id=0; id < number_windows; id++)
4172 {
4173 /*
4174 Does target window intersect top level window?
4175 */
4176 import=
4177 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4178 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4179 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4180 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4181 MagickTrue : MagickFalse;
4182 /*
4183 Is target window contained by another window with the same colormap?
4184 */
4185 for (j=0; j < id; j++)
4186 if ((window_info[id].visual == window_info[j].visual) &&
4187 (window_info[id].colormap == window_info[j].colormap))
4188 {
4189 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4190 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4191 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4192 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4193 import=MagickFalse;
4194 }
4195 else
4196 if ((window_info[id].visual != window_info[j].visual) ||
4197 (window_info[id].colormap != window_info[j].colormap))
4198 {
4199 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4200 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4201 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4202 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4203 import=MagickTrue;
4204 }
4205 if (import == MagickFalse)
4206 continue;
4207 /*
4208 Get X image.
4209 */
4210 ximage=XGetImage(display,window_info[id].window,(int)
4211 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4212 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4213 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4214 if (ximage == (XImage *) NULL)
4215 continue;
4216 /*
4217 Initialize window colormap.
4218 */
4219 number_colors=0;
4220 colors=(XColor *) NULL;
4221 if (window_info[id].colormap != (Colormap) NULL)
4222 {
4223 ColormapInfo
4224 *p;
4225
4226 /*
4227 Search colormap list for window colormap.
4228 */
4229 number_colors=(unsigned int) window_info[id].visual->map_entries;
4230 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4231 if (p->colormap == window_info[id].colormap)
4232 break;
4233 if (p == (ColormapInfo *) NULL)
4234 {
4235 /*
4236 Get the window colormap.
4237 */
4238 colors=(XColor *) AcquireQuantumMemory(number_colors,
4239 sizeof(*colors));
4240 if (colors == (XColor *) NULL)
4241 {
4242 XDestroyImage(ximage);
4243 return((Image *) NULL);
4244 }
4245 if ((window_info[id].visual->klass != DirectColor) &&
4246 (window_info[id].visual->klass != TrueColor))
4247 for (i=0; i < (int) number_colors; i++)
4248 {
cristybb503372010-05-27 20:51:26 +00004249 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004250 colors[i].pad='\0';
4251 }
4252 else
4253 {
cristybb503372010-05-27 20:51:26 +00004254 size_t
cristy3ed852e2009-09-05 21:47:34 +00004255 blue,
4256 blue_bit,
4257 green,
4258 green_bit,
4259 red,
4260 red_bit;
4261
4262 /*
4263 DirectColor or TrueColor visual.
4264 */
4265 red=0;
4266 green=0;
4267 blue=0;
4268 red_bit=window_info[id].visual->red_mask &
4269 (~(window_info[id].visual->red_mask)+1);
4270 green_bit=window_info[id].visual->green_mask &
4271 (~(window_info[id].visual->green_mask)+1);
4272 blue_bit=window_info[id].visual->blue_mask &
4273 (~(window_info[id].visual->blue_mask)+1);
4274 for (i=0; i < (int) number_colors; i++)
4275 {
cristy8891f9c2010-06-04 23:32:17 +00004276 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004277 colors[i].pad='\0';
4278 red+=red_bit;
4279 if (red > window_info[id].visual->red_mask)
4280 red=0;
4281 green+=green_bit;
4282 if (green > window_info[id].visual->green_mask)
4283 green=0;
4284 blue+=blue_bit;
4285 if (blue > window_info[id].visual->blue_mask)
4286 blue=0;
4287 }
4288 }
4289 (void) XQueryColors(display,window_info[id].colormap,colors,
4290 (int) number_colors);
4291 /*
4292 Append colormap to colormap list.
4293 */
cristy73bd4a52010-10-05 11:24:23 +00004294 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004295 if (p == (ColormapInfo *) NULL)
4296 return((Image *) NULL);
4297 p->colormap=window_info[id].colormap;
4298 p->colors=colors;
4299 p->next=colormap_info;
4300 colormap_info=p;
4301 }
4302 colors=p->colors;
4303 }
4304 /*
4305 Allocate image structure.
4306 */
4307 composite_image=AcquireImage((ImageInfo *) NULL);
4308 if (composite_image == (Image *) NULL)
4309 {
4310 XDestroyImage(ximage);
4311 return((Image *) NULL);
4312 }
4313 /*
4314 Convert X image to MIFF format.
4315 */
4316 if ((window_info[id].visual->klass != TrueColor) &&
4317 (window_info[id].visual->klass != DirectColor))
4318 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004319 composite_image->columns=(size_t) ximage->width;
4320 composite_image->rows=(size_t) ximage->height;
cristy3ed852e2009-09-05 21:47:34 +00004321 exception=(&composite_image->exception);
cristyc57f6942010-11-12 01:47:39 +00004322 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004323 switch (composite_image->storage_class)
4324 {
4325 case DirectClass:
4326 default:
4327 {
cristybb503372010-05-27 20:51:26 +00004328 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004329 color,
4330 index;
4331
cristybb503372010-05-27 20:51:26 +00004332 size_t
cristy3ed852e2009-09-05 21:47:34 +00004333 blue_mask,
4334 blue_shift,
4335 green_mask,
4336 green_shift,
4337 red_mask,
4338 red_shift;
4339
4340 /*
4341 Determine shift and mask for red, green, and blue.
4342 */
4343 red_mask=window_info[id].visual->red_mask;
4344 red_shift=0;
4345 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4346 {
4347 red_mask>>=1;
4348 red_shift++;
4349 }
4350 green_mask=window_info[id].visual->green_mask;
4351 green_shift=0;
4352 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4353 {
4354 green_mask>>=1;
4355 green_shift++;
4356 }
4357 blue_mask=window_info[id].visual->blue_mask;
4358 blue_shift=0;
4359 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4360 {
4361 blue_mask>>=1;
4362 blue_shift++;
4363 }
4364 /*
4365 Convert X image to DirectClass packets.
4366 */
4367 if ((number_colors != 0) &&
4368 (window_info[id].visual->klass == DirectColor))
4369 for (y=0; y < (int) composite_image->rows; y++)
4370 {
cristyc57f6942010-11-12 01:47:39 +00004371 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004372 composite_image->columns,1,exception);
4373 if (q == (PixelPacket *) NULL)
4374 break;
4375 for (x=0; x < (int) composite_image->columns; x++)
4376 {
4377 pixel=XGetPixel(ximage,x,y);
4378 index=(pixel >> red_shift) & red_mask;
4379 q->red=ScaleShortToQuantum(colors[index].red);
4380 index=(pixel >> green_shift) & green_mask;
4381 q->green=ScaleShortToQuantum(colors[index].green);
4382 index=(pixel >> blue_shift) & blue_mask;
4383 q->blue=ScaleShortToQuantum(colors[index].blue);
4384 q++;
4385 }
cristyc57f6942010-11-12 01:47:39 +00004386 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004387 break;
4388 }
4389 else
4390 for (y=0; y < (int) composite_image->rows; y++)
4391 {
cristyc57f6942010-11-12 01:47:39 +00004392 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004393 composite_image->columns,1,exception);
4394 if (q == (PixelPacket *) NULL)
4395 break;
4396 for (x=0; x < (int) composite_image->columns; x++)
4397 {
4398 pixel=XGetPixel(ximage,x,y);
4399 color=(pixel >> red_shift) & red_mask;
4400 color=(65535UL*color)/red_mask;
4401 q->red=ScaleShortToQuantum((unsigned short) color);
4402 color=(pixel >> green_shift) & green_mask;
4403 color=(65535UL*color)/green_mask;
4404 q->green=ScaleShortToQuantum((unsigned short) color);
4405 color=(pixel >> blue_shift) & blue_mask;
4406 color=(65535UL*color)/blue_mask;
4407 q->blue=ScaleShortToQuantum((unsigned short) color);
4408 q++;
4409 }
cristyc57f6942010-11-12 01:47:39 +00004410 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004411 break;
4412 }
4413 break;
4414 }
4415 case PseudoClass:
4416 {
4417 /*
4418 Create colormap.
4419 */
4420 if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
4421 {
4422 XDestroyImage(ximage);
4423 composite_image=DestroyImage(composite_image);
4424 return((Image *) NULL);
4425 }
4426 for (i=0; i < (int) composite_image->colors; i++)
4427 {
4428 composite_image->colormap[colors[i].pixel].red=
4429 ScaleShortToQuantum(colors[i].red);
4430 composite_image->colormap[colors[i].pixel].green=
4431 ScaleShortToQuantum(colors[i].green);
4432 composite_image->colormap[colors[i].pixel].blue=
4433 ScaleShortToQuantum(colors[i].blue);
4434 }
4435 /*
4436 Convert X image to PseudoClass packets.
4437 */
4438 for (y=0; y < (int) composite_image->rows; y++)
4439 {
cristyc57f6942010-11-12 01:47:39 +00004440 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4441 composite_image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00004442 if (q == (PixelPacket *) NULL)
4443 break;
cristyc57f6942010-11-12 01:47:39 +00004444 indexes=GetCacheViewAuthenticIndexQueue(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004445 for (x=0; x < (int) composite_image->columns; x++)
4446 {
4447 index=(IndexPacket) XGetPixel(ximage,x,y);
4448 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +00004449 *q++=composite_image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +00004450 }
cristyc57f6942010-11-12 01:47:39 +00004451 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004452 break;
4453 }
4454 break;
4455 }
4456 }
cristyc57f6942010-11-12 01:47:39 +00004457 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004458 XDestroyImage(ximage);
4459 if (image == (Image *) NULL)
4460 {
4461 image=composite_image;
4462 continue;
4463 }
4464 /*
4465 Composite any children in back-to-front order.
4466 */
4467 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4468 &x_offset,&y_offset,&child);
4469 x_offset-=(int) crop_info.x;
4470 if (x_offset < 0)
4471 x_offset=0;
4472 y_offset-=(int) crop_info.y;
4473 if (y_offset < 0)
4474 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004475 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
4476 x_offset,(ssize_t) y_offset);
cristy3ed852e2009-09-05 21:47:34 +00004477 }
4478 /*
4479 Relinquish resources.
4480 */
4481 while (colormap_info != (ColormapInfo *) NULL)
4482 {
4483 next=colormap_info->next;
4484 colormap_info->colors=(XColor *)
4485 RelinquishMagickMemory(colormap_info->colors);
4486 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4487 colormap_info=next;
4488 }
4489 /*
4490 Relinquish resources and restore initial state.
4491 */
4492 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4493 max_windows=0;
4494 number_windows=0;
4495 colormap_info=(ColormapInfo *) NULL;
4496 return(image);
4497 }
4498 return((Image *) NULL);
4499}
4500
4501/*
4502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4503% %
4504% %
4505% %
4506% X G e t W i n d o w I n f o %
4507% %
4508% %
4509% %
4510%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4511%
4512% XGetWindowInfo() initializes the XWindowInfo structure.
4513%
4514% The format of the XGetWindowInfo method is:
4515%
4516% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4517% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4518% XResourceInfo *resource_info,XWindowInfo *window)
4519% resource_info,window)
4520%
4521% A description of each parameter follows:
4522%
4523% o display: Specifies a connection to an X server; returned from
4524% XOpenDisplay.
4525%
4526% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4527% returned from XGetVisualInfo.
4528%
4529% o map_info: If map_type is specified, this structure is initialized
4530% with info from the Standard Colormap.
4531%
4532% o pixel: Specifies a pointer to a XPixelInfo structure.
4533%
4534% o font_info: Specifies a pointer to a XFontStruct structure.
4535%
4536% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4537%
4538*/
4539MagickExport void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4540 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4541 XResourceInfo *resource_info,XWindowInfo *window)
4542{
4543 /*
4544 Initialize window info.
4545 */
4546 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4547 assert(display != (Display *) NULL);
4548 assert(visual_info != (XVisualInfo *) NULL);
4549 assert(map_info != (XStandardColormap *) NULL);
4550 assert(pixel != (XPixelInfo *) NULL);
4551 assert(resource_info != (XResourceInfo *) NULL);
4552 assert(window != (XWindowInfo *) NULL);
4553 if (window->id != (Window) NULL)
4554 {
4555 if (window->cursor != (Cursor) NULL)
4556 (void) XFreeCursor(display,window->cursor);
4557 if (window->busy_cursor != (Cursor) NULL)
4558 (void) XFreeCursor(display,window->busy_cursor);
4559 if (window->highlight_stipple != (Pixmap) NULL)
4560 (void) XFreePixmap(display,window->highlight_stipple);
4561 if (window->shadow_stipple != (Pixmap) NULL)
4562 (void) XFreePixmap(display,window->shadow_stipple);
4563 if (window->name == (char *) NULL)
4564 window->name=AcquireString("");
4565 if (window->icon_name == (char *) NULL)
4566 window->icon_name=AcquireString("");
4567 }
4568 else
4569 {
4570 /*
4571 Initialize these attributes just once.
4572 */
4573 window->id=(Window) NULL;
4574 if (window->name == (char *) NULL)
4575 window->name=AcquireString("");
4576 if (window->icon_name == (char *) NULL)
4577 window->icon_name=AcquireString("");
4578 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4579 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4580 window->ximage=(XImage *) NULL;
4581 window->matte_image=(XImage *) NULL;
4582 window->pixmap=(Pixmap) NULL;
4583 window->matte_pixmap=(Pixmap) NULL;
4584 window->mapped=MagickFalse;
4585 window->stasis=MagickFalse;
4586 window->shared_memory=MagickTrue;
4587 window->segment_info=(void *) NULL;
4588#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4589 {
4590 XShmSegmentInfo
4591 *segment_info;
4592
4593 if (window->segment_info == (void *) NULL)
4594 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4595 segment_info=(XShmSegmentInfo *) window->segment_info;
4596 segment_info[0].shmid=(-1);
4597 segment_info[0].shmaddr=(char *) NULL;
4598 segment_info[1].shmid=(-1);
4599 segment_info[1].shmaddr=(char *) NULL;
4600 }
4601#endif
4602 }
4603 /*
4604 Initialize these attributes every time function is called.
4605 */
4606 window->screen=visual_info->screen;
4607 window->root=XRootWindow(display,visual_info->screen);
4608 window->visual=visual_info->visual;
4609 window->storage_class=(unsigned int) visual_info->klass;
4610 window->depth=(unsigned int) visual_info->depth;
4611 window->visual_info=visual_info;
4612 window->map_info=map_info;
4613 window->pixel_info=pixel;
4614 window->font_info=font_info;
4615 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4616 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4617 window->geometry=(char *) NULL;
4618 window->icon_geometry=(char *) NULL;
4619 if (resource_info->icon_geometry != (char *) NULL)
4620 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4621 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004622 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004623 window->width=1;
4624 window->height=1;
4625 window->min_width=1;
4626 window->min_height=1;
4627 window->width_inc=1;
4628 window->height_inc=1;
4629 window->border_width=resource_info->border_width;
4630 window->annotate_context=pixel->annotate_context;
4631 window->highlight_context=pixel->highlight_context;
4632 window->widget_context=pixel->widget_context;
4633 window->shadow_stipple=(Pixmap) NULL;
4634 window->highlight_stipple=(Pixmap) NULL;
4635 window->use_pixmap=MagickTrue;
4636 window->immutable=MagickFalse;
4637 window->shape=MagickFalse;
4638 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004639 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004640 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4641 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4642 window->attributes.background_pixel=pixel->background_color.pixel;
4643 window->attributes.background_pixmap=(Pixmap) NULL;
4644 window->attributes.bit_gravity=ForgetGravity;
4645 window->attributes.backing_store=WhenMapped;
4646 window->attributes.save_under=MagickTrue;
4647 window->attributes.border_pixel=pixel->border_color.pixel;
4648 window->attributes.colormap=map_info->colormap;
4649 window->attributes.cursor=window->cursor;
4650 window->attributes.do_not_propagate_mask=NoEventMask;
4651 window->attributes.event_mask=NoEventMask;
4652 window->attributes.override_redirect=MagickFalse;
4653 window->attributes.win_gravity=NorthWestGravity;
4654 window->orphan=MagickFalse;
4655}
4656
4657/*
4658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4659% %
4660% %
4661% %
4662% X H i g h l i g h t E l l i p s e %
4663% %
4664% %
4665% %
4666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4667%
4668% XHighlightEllipse() puts a border on the X server around a region defined by
4669% highlight_info.
4670%
4671% The format of the XHighlightEllipse method is:
4672%
4673% void XHighlightEllipse(Display *display,Window window,
4674% GC annotate_context,const RectangleInfo *highlight_info)
4675%
4676% A description of each parameter follows:
4677%
4678% o display: Specifies a connection to an X server; returned from
4679% XOpenDisplay.
4680%
4681% o window: Specifies a pointer to a Window structure.
4682%
4683% o annotate_context: Specifies a pointer to a GC structure.
4684%
4685% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4686% contains the extents of any highlighting rectangle.
4687%
4688*/
4689MagickExport void XHighlightEllipse(Display *display,Window window,
4690 GC annotate_context,const RectangleInfo *highlight_info)
4691{
4692 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4693 assert(display != (Display *) NULL);
4694 assert(window != (Window) NULL);
4695 assert(annotate_context != (GC) NULL);
4696 assert(highlight_info != (RectangleInfo *) NULL);
4697 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4698 return;
4699 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4700 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4701 (unsigned int) highlight_info->height-1,0,360*64);
4702 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4703 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4704 (unsigned int) highlight_info->height-3,0,360*64);
4705}
4706
4707/*
4708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4709% %
4710% %
4711% %
4712% X H i g h l i g h t L i n e %
4713% %
4714% %
4715% %
4716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4717%
4718% XHighlightLine() puts a border on the X server around a region defined by
4719% highlight_info.
4720%
4721% The format of the XHighlightLine method is:
4722%
4723% void XHighlightLine(Display *display,Window window,GC annotate_context,
4724% const XSegment *highlight_info)
4725%
4726% A description of each parameter follows:
4727%
4728% o display: Specifies a connection to an X server; returned from
4729% XOpenDisplay.
4730%
4731% o window: Specifies a pointer to a Window structure.
4732%
4733% o annotate_context: Specifies a pointer to a GC structure.
4734%
4735% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4736% contains the extents of any highlighting rectangle.
4737%
4738*/
4739MagickExport void XHighlightLine(Display *display,Window window,
4740 GC annotate_context,const XSegment *highlight_info)
4741{
4742 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4743 assert(display != (Display *) NULL);
4744 assert(window != (Window) NULL);
4745 assert(annotate_context != (GC) NULL);
4746 assert(highlight_info != (XSegment *) NULL);
4747 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4748 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4749}
4750
4751/*
4752%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4753% %
4754% %
4755% %
4756% X H i g h l i g h t R e c t a n g l e %
4757% %
4758% %
4759% %
4760%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4761%
4762% XHighlightRectangle() puts a border on the X server around a region defined
4763% by highlight_info.
4764%
4765% The format of the XHighlightRectangle method is:
4766%
4767% void XHighlightRectangle(Display *display,Window window,
4768% GC annotate_context,const RectangleInfo *highlight_info)
4769%
4770% A description of each parameter follows:
4771%
4772% o display: Specifies a connection to an X server; returned from
4773% XOpenDisplay.
4774%
4775% o window: Specifies a pointer to a Window structure.
4776%
4777% o annotate_context: Specifies a pointer to a GC structure.
4778%
4779% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4780% contains the extents of any highlighting rectangle.
4781%
4782*/
4783MagickExport void XHighlightRectangle(Display *display,Window window,
4784 GC annotate_context,const RectangleInfo *highlight_info)
4785{
4786 assert(display != (Display *) NULL);
4787 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4788 assert(window != (Window) NULL);
4789 assert(annotate_context != (GC) NULL);
4790 assert(highlight_info != (RectangleInfo *) NULL);
4791 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4792 return;
4793 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4794 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4795 (unsigned int) highlight_info->height-1);
4796 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4797 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4798 (unsigned int) highlight_info->height-3);
4799}
4800
4801/*
4802%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4803% %
4804% %
4805% %
4806% X I m p o r t I m a g e %
4807% %
4808% %
4809% %
4810%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4811%
4812% XImportImage() reads an image from an X window.
4813%
4814% The format of the XImportImage method is:
4815%
4816% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4817%
4818% A description of each parameter follows:
4819%
4820% o image_info: the image info.
4821%
4822% o ximage_info: Specifies a pointer to an XImportInfo structure.
4823%
4824*/
4825MagickExport Image *XImportImage(const ImageInfo *image_info,
4826 XImportInfo *ximage_info)
4827{
4828 Colormap
4829 *colormaps;
4830
4831 Display
4832 *display;
4833
4834 Image
4835 *image;
4836
4837 int
4838 number_colormaps,
4839 number_windows,
4840 x;
4841
4842 RectangleInfo
4843 crop_info;
4844
4845 Status
4846 status;
4847
4848 Window
4849 *children,
4850 client,
4851 prior_target,
4852 root,
4853 target;
4854
4855 XTextProperty
4856 window_name;
4857
4858 /*
4859 Open X server connection.
4860 */
4861 assert(image_info != (const ImageInfo *) NULL);
4862 assert(image_info->signature == MagickSignature);
4863 if (image_info->debug != MagickFalse)
4864 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4865 image_info->filename);
4866 assert(ximage_info != (XImportInfo *) NULL);
4867 display=XOpenDisplay(image_info->server_name);
4868 if (display == (Display *) NULL)
4869 {
4870 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4871 XDisplayName(image_info->server_name));
4872 return((Image *) NULL);
4873 }
4874 /*
4875 Set our forgiving exception handler.
4876 */
4877 (void) XSetErrorHandler(XError);
4878 /*
4879 Select target window.
4880 */
4881 crop_info.x=0;
4882 crop_info.y=0;
4883 crop_info.width=0;
4884 crop_info.height=0;
4885 root=XRootWindow(display,XDefaultScreen(display));
4886 target=(Window) NULL;
4887 if ((image_info->filename != (char *) NULL) &&
4888 (*image_info->filename != '\0'))
4889 {
4890 if (LocaleCompare(image_info->filename,"root") == 0)
4891 target=root;
4892 else
4893 {
4894 /*
4895 Select window by ID or name.
4896 */
4897 if (isdigit((unsigned char) *image_info->filename) != 0)
4898 target=XWindowByID(display,root,(Window)
4899 strtol(image_info->filename,(char **) NULL,0));
4900 if (target == (Window) NULL)
4901 target=XWindowByName(display,root,image_info->filename);
4902 if (target == (Window) NULL)
4903 ThrowXWindowFatalException(XServerError,
4904 "NoWindowWithSpecifiedIDExists",image_info->filename);
4905 }
4906 }
4907 /*
4908 If target window is not defined, interactively select one.
4909 */
4910 prior_target=target;
4911 if (target == (Window) NULL)
4912 target=XSelectWindow(display,&crop_info);
4913 if (target == (Window) NULL)
4914 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4915 image_info->filename);
4916 client=target; /* obsolete */
4917 if (target != root)
4918 {
4919 unsigned int
4920 d;
4921
4922 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4923 if (status != False)
4924 {
4925 for ( ; ; )
4926 {
4927 Window
4928 parent;
4929
4930 /*
4931 Find window manager frame.
4932 */
4933 status=XQueryTree(display,target,&root,&parent,&children,&d);
4934 if ((status != False) && (children != (Window *) NULL))
4935 (void) XFree((char *) children);
4936 if ((status == False) || (parent == (Window) NULL) ||
4937 (parent == root))
4938 break;
4939 target=parent;
4940 }
4941 /*
4942 Get client window.
4943 */
4944 client=XClientWindow(display,target);
4945 if (ximage_info->frame == MagickFalse)
4946 target=client;
4947 if ((ximage_info->frame == MagickFalse) &&
4948 (prior_target != MagickFalse))
4949 target=prior_target;
4950 XDelay(display,SuspendTime << 4);
4951 }
4952 }
4953 if (ximage_info->screen)
4954 {
4955 int
4956 y;
4957
4958 Window
4959 child;
4960
4961 XWindowAttributes
4962 window_attributes;
4963
4964 /*
4965 Obtain window image directly from screen.
4966 */
4967 status=XGetWindowAttributes(display,target,&window_attributes);
4968 if (status == False)
4969 {
4970 ThrowXWindowFatalException(XServerError,
4971 "UnableToReadXWindowAttributes",image_info->filename);
4972 (void) XCloseDisplay(display);
4973 return((Image *) NULL);
4974 }
4975 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00004976 crop_info.x=(ssize_t) x;
4977 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00004978 crop_info.width=(size_t) window_attributes.width;
4979 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00004980 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00004981 {
4982 /*
4983 Include border in image.
4984 */
4985 crop_info.x-=window_attributes.border_width;
4986 crop_info.y-=window_attributes.border_width;
4987 crop_info.width+=window_attributes.border_width << 1;
4988 crop_info.height+=window_attributes.border_width << 1;
4989 }
4990 target=root;
4991 }
4992 /*
4993 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
4994 */
4995 number_windows=0;
4996 status=XGetWMColormapWindows(display,target,&children,&number_windows);
4997 if ((status == True) && (number_windows > 0))
4998 {
4999 ximage_info->descend=MagickTrue;
5000 (void) XFree ((char *) children);
5001 }
5002 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5003 if (number_colormaps > 0)
5004 {
5005 if (number_colormaps > 1)
5006 ximage_info->descend=MagickTrue;
5007 (void) XFree((char *) colormaps);
5008 }
5009 /*
5010 Alert the user not to alter the screen.
5011 */
5012 if (ximage_info->silent == MagickFalse)
5013 (void) XBell(display,0);
5014 /*
5015 Get image by window id.
5016 */
5017 (void) XGrabServer(display);
5018 image=XGetWindowImage(display,target,ximage_info->borders,
5019 ximage_info->descend ? 1U : 0U);
5020 (void) XUngrabServer(display);
5021 if (image == (Image *) NULL)
5022 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5023 image_info->filename)
5024 else
5025 {
5026 (void) CopyMagickString(image->filename,image_info->filename,
5027 MaxTextExtent);
5028 if ((crop_info.width != 0) && (crop_info.height != 0))
5029 {
5030 Image
5031 *clone_image,
5032 *crop_image;
5033
5034 /*
5035 Crop image as defined by the cropping rectangle.
5036 */
5037 clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5038 if (clone_image != (Image *) NULL)
5039 {
5040 crop_image=CropImage(clone_image,&crop_info,&image->exception);
5041 if (crop_image != (Image *) NULL)
5042 {
5043 image=DestroyImage(image);
5044 image=crop_image;
5045 }
5046 }
5047 }
5048 status=XGetWMName(display,target,&window_name);
5049 if (status == True)
5050 {
5051 if ((image_info->filename != (char *) NULL) &&
5052 (*image_info->filename == '\0'))
5053 (void) CopyMagickString(image->filename,(char *) window_name.value,
5054 (size_t) window_name.nitems+1);
5055 (void) XFree((void *) window_name.value);
5056 }
5057 }
5058 if (ximage_info->silent == MagickFalse)
5059 {
5060 /*
5061 Alert the user we're done.
5062 */
5063 (void) XBell(display,0);
5064 (void) XBell(display,0);
5065 }
5066 (void) XCloseDisplay(display);
5067 return(image);
5068}
5069
5070/*
5071%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5072% %
5073% %
5074% %
5075% X I n i t i a l i z e W i n d o w s %
5076% %
5077% %
5078% %
5079%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5080%
5081% XInitializeWindows() initializes the XWindows structure.
5082%
5083% The format of the XInitializeWindows method is:
5084%
5085% XWindows *XInitializeWindows(Display *display,
5086% XResourceInfo *resource_info)
5087%
5088% A description of each parameter follows:
5089%
5090% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5091%
5092% o display: Specifies a connection to an X server; returned from
5093% XOpenDisplay.
5094%
5095% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5096%
5097*/
5098MagickExport XWindows *XInitializeWindows(Display *display,
5099 XResourceInfo *resource_info)
5100{
5101 Window
5102 root_window;
5103
5104 XWindows
5105 *windows;
5106
5107 /*
5108 Allocate windows structure.
5109 */
cristy73bd4a52010-10-05 11:24:23 +00005110 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005111 if (windows == (XWindows *) NULL)
5112 {
5113 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5114 "...");
5115 return((XWindows *) NULL);
5116 }
5117 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5118 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5119 sizeof(*windows->pixel_info));
5120 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5121 sizeof(*windows->icon_pixel));
5122 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5123 sizeof(*windows->icon_resources));
5124 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5125 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5126 (windows->icon_resources == (XResourceInfo *) NULL))
5127 {
5128 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5129 "...");
5130 return((XWindows *) NULL);
5131 }
5132 /*
5133 Initialize windows structure.
5134 */
5135 windows->display=display;
5136 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5137 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5138 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5139 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5140 windows->im_remote_command=
5141 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5142 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5143 windows->im_update_colormap=
5144 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5145 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5146 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5147 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5148 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5149 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005150#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005151 (void) XSynchronize(display,IsWindows95());
5152#endif
5153 if (IsEventLogging())
5154 {
5155 (void) XSynchronize(display,MagickTrue);
5156 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005157 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005158 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5159 (void) LogMagickEvent(X11Event,GetMagickModule(),
5160 " Window Manager: 0x%lx",windows->wm_protocols);
5161 (void) LogMagickEvent(X11Event,GetMagickModule(),
5162 " delete window: 0x%lx",windows->wm_delete_window);
5163 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5164 windows->wm_take_focus);
5165 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5166 windows->im_protocols);
5167 (void) LogMagickEvent(X11Event,GetMagickModule(),
5168 " remote command: 0x%lx",windows->im_remote_command);
5169 (void) LogMagickEvent(X11Event,GetMagickModule(),
5170 " update widget: 0x%lx",windows->im_update_widget);
5171 (void) LogMagickEvent(X11Event,GetMagickModule(),
5172 " update colormap: 0x%lx",windows->im_update_colormap);
5173 (void) LogMagickEvent(X11Event,GetMagickModule(),
5174 " former image: 0x%lx",windows->im_former_image);
5175 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5176 windows->im_next_image);
5177 (void) LogMagickEvent(X11Event,GetMagickModule(),
5178 " retain colors: 0x%lx",windows->im_retain_colors);
5179 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5180 windows->im_exit);
5181 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5182 windows->dnd_protocols);
5183 }
5184 /*
5185 Allocate standard colormap.
5186 */
5187 windows->map_info=XAllocStandardColormap();
5188 windows->icon_map=XAllocStandardColormap();
5189 if ((windows->map_info == (XStandardColormap *) NULL) ||
5190 (windows->icon_map == (XStandardColormap *) NULL))
5191 ThrowXWindowFatalException(ResourceLimitFatalError,
5192 "MemoryAllocationFailed","...");
5193 windows->map_info->colormap=(Colormap) NULL;
5194 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005195 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005196 windows->pixel_info->annotate_context=(GC) NULL;
5197 windows->pixel_info->highlight_context=(GC) NULL;
5198 windows->pixel_info->widget_context=(GC) NULL;
5199 windows->font_info=(XFontStruct *) NULL;
5200 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005201 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005202 /*
5203 Allocate visual.
5204 */
5205 *windows->icon_resources=(*resource_info);
5206 windows->icon_resources->visual_type=(char *) "default";
5207 windows->icon_resources->colormap=SharedColormap;
5208 windows->visual_info=
5209 XBestVisualInfo(display,windows->map_info,resource_info);
5210 windows->icon_visual=
5211 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5212 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5213 (windows->icon_visual == (XVisualInfo *) NULL))
5214 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5215 resource_info->visual_type);
5216 if (IsEventLogging())
5217 {
5218 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5219 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5220 windows->visual_info->visualid);
5221 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5222 XVisualClassName(windows->visual_info->klass));
5223 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5224 windows->visual_info->depth);
5225 (void) LogMagickEvent(X11Event,GetMagickModule(),
5226 " size of colormap: %d entries",windows->visual_info->colormap_size);
5227 (void) LogMagickEvent(X11Event,GetMagickModule(),
5228 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5229 windows->visual_info->red_mask,windows->visual_info->green_mask,
5230 windows->visual_info->blue_mask);
5231 (void) LogMagickEvent(X11Event,GetMagickModule(),
5232 " significant bits in color: %d bits",
5233 windows->visual_info->bits_per_rgb);
5234 }
5235 /*
5236 Allocate class and manager hints.
5237 */
5238 windows->class_hints=XAllocClassHint();
5239 windows->manager_hints=XAllocWMHints();
5240 if ((windows->class_hints == (XClassHint *) NULL) ||
5241 (windows->manager_hints == (XWMHints *) NULL))
5242 ThrowXWindowFatalException(ResourceLimitFatalError,
5243 "MemoryAllocationFailed","...");
5244 /*
5245 Determine group leader if we have one.
5246 */
5247 root_window=XRootWindow(display,windows->visual_info->screen);
5248 windows->group_leader.id=(Window) NULL;
5249 if (resource_info->window_group != (char *) NULL)
5250 {
5251 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5252 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5253 strtol((char *) resource_info->window_group,(char **) NULL,0));
5254 if (windows->group_leader.id == (Window) NULL)
5255 windows->group_leader.id=
5256 XWindowByName(display,root_window,resource_info->window_group);
5257 }
5258 return(windows);
5259}
5260
5261/*
5262%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5263% %
5264% %
5265% %
5266% X M a k e C u r s o r %
5267% %
5268% %
5269% %
5270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5271%
5272% XMakeCursor() creates a crosshairs X11 cursor.
5273%
5274% The format of the XMakeCursor method is:
5275%
5276% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5277% char *background_color,char *foreground_color)
5278%
5279% A description of each parameter follows:
5280%
5281% o display: Specifies a connection to an X server; returned from
5282% XOpenDisplay.
5283%
5284% o window: Specifies the ID of the window for which the cursor is
5285% assigned.
5286%
5287% o colormap: Specifies the ID of the colormap from which the background
5288% and foreground color will be retrieved.
5289%
5290% o background_color: Specifies the color to use for the cursor background.
5291%
5292% o foreground_color: Specifies the color to use for the cursor foreground.
5293%
5294*/
5295MagickExport Cursor XMakeCursor(Display *display,Window window,
5296 Colormap colormap,char *background_color,char *foreground_color)
5297{
5298#define scope_height 17
5299#define scope_x_hot 8
5300#define scope_y_hot 8
5301#define scope_width 17
5302
5303 static const unsigned char
5304 scope_bits[] =
5305 {
5306 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5307 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5308 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5309 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5310 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5311 },
5312 scope_mask_bits[] =
5313 {
5314 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5315 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5316 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5317 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5318 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5319 };
5320
5321 Cursor
5322 cursor;
5323
5324 Pixmap
5325 mask,
5326 source;
5327
5328 XColor
5329 background,
5330 foreground;
5331
5332 assert(display != (Display *) NULL);
5333 assert(window != (Window) NULL);
5334 assert(colormap != (Colormap) NULL);
5335 assert(background_color != (char *) NULL);
5336 assert(foreground_color != (char *) NULL);
5337 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5338 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5339 scope_height);
5340 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5341 scope_width,scope_height);
5342 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5343 {
5344 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5345 return((Cursor) NULL);
5346 }
5347 (void) XParseColor(display,colormap,background_color,&background);
5348 (void) XParseColor(display,colormap,foreground_color,&foreground);
5349 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5350 scope_x_hot,scope_y_hot);
5351 (void) XFreePixmap(display,source);
5352 (void) XFreePixmap(display,mask);
5353 return(cursor);
5354}
5355
5356/*
5357%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5358% %
5359% %
5360% %
5361% X M a k e I m a g e %
5362% %
5363% %
5364% %
5365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5366%
5367% XMakeImage() creates an X11 image. If the image size differs from the X11
5368% image size, the image is first resized.
5369%
5370% The format of the XMakeImage method is:
5371%
5372% MagickBooleanType XMakeImage(Display *display,
5373% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5374% unsigned int width,unsigned int height)
5375%
5376% A description of each parameter follows:
5377%
5378% o display: Specifies a connection to an X server; returned from
5379% XOpenDisplay.
5380%
5381% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5382%
5383% o window: Specifies a pointer to a XWindowInfo structure.
5384%
5385% o image: the image.
5386%
5387% o width: Specifies the width in pixels of the rectangular area to
5388% display.
5389%
5390% o height: Specifies the height in pixels of the rectangular area to
5391% display.
5392%
5393*/
5394MagickExport MagickBooleanType XMakeImage(Display *display,
5395 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5396 unsigned int width,unsigned int height)
5397{
5398#define CheckOverflowException(length,width,height) \
5399 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5400
5401 int
5402 depth,
5403 format;
5404
5405 size_t
5406 length;
5407
5408 XImage
5409 *matte_image,
5410 *ximage;
5411
5412 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5413 assert(display != (Display *) NULL);
5414 assert(resource_info != (XResourceInfo *) NULL);
5415 assert(window != (XWindowInfo *) NULL);
5416 assert(width != 0);
5417 assert(height != 0);
5418 if ((window->width == 0) || (window->height == 0))
5419 return(MagickFalse);
5420 /*
5421 Apply user transforms to the image.
5422 */
5423 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5424 (void) XFlush(display);
5425 depth=(int) window->depth;
5426 if (window->destroy)
5427 window->image=DestroyImage(window->image);
5428 window->image=image;
5429 window->destroy=MagickFalse;
5430 if (window->image != (Image *) NULL)
5431 {
5432 if (window->crop_geometry != (char *) NULL)
5433 {
5434 Image
5435 *crop_image;
5436
5437 RectangleInfo
5438 crop_info;
5439
5440 /*
5441 Crop image.
5442 */
5443 window->image->page.x=0;
5444 window->image->page.y=0;
5445 (void) ParsePageGeometry(window->image,window->crop_geometry,
5446 &crop_info,&image->exception);
5447 crop_image=CropImage(window->image,&crop_info,&image->exception);
5448 if (crop_image != (Image *) NULL)
5449 {
5450 if (window->image != image)
5451 window->image=DestroyImage(window->image);
5452 window->image=crop_image;
5453 window->destroy=MagickTrue;
5454 }
5455 }
5456 if ((width != (unsigned int) window->image->columns) ||
5457 (height != (unsigned int) window->image->rows))
5458 {
5459 Image
5460 *resize_image;
5461
5462 /*
5463 Resize image.
5464 */
5465 resize_image=NewImageList();
5466 if (window->pixel_info->colors != 0)
5467 resize_image=SampleImage(window->image,width,height,
5468 &image->exception);
5469 else
5470 resize_image=ThumbnailImage(window->image,width,height,
5471 &image->exception);
5472 if (resize_image != (Image *) NULL)
5473 {
5474 if (window->image != image)
5475 window->image=DestroyImage(window->image);
5476 window->image=resize_image;
5477 window->destroy=MagickTrue;
5478 }
5479 }
5480 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005481 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005482 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005483 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005484 }
5485 /*
5486 Create X image.
5487 */
5488 ximage=(XImage *) NULL;
5489 format=(depth == 1) ? XYBitmap : ZPixmap;
5490#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5491 if (window->shared_memory != MagickFalse)
5492 {
5493 XShmSegmentInfo
5494 *segment_info;
5495
5496 segment_info=(XShmSegmentInfo *) window->segment_info;
5497 segment_info[1].shmid=(-1);
5498 segment_info[1].shmaddr=(char *) NULL;
5499 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5500 (char *) NULL,&segment_info[1],width,height);
5501 if (ximage == (XImage *) NULL)
5502 window->shared_memory=MagickFalse;
5503 length=(size_t) ximage->bytes_per_line*ximage->height;
5504 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5505 window->shared_memory=MagickFalse;
5506 if (window->shared_memory != MagickFalse)
5507 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5508 if (window->shared_memory != MagickFalse)
5509 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5510 if (segment_info[1].shmid < 0)
5511 window->shared_memory=MagickFalse;
5512 if (window->shared_memory != MagickFalse)
5513 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5514 else
5515 {
5516 if (ximage != (XImage *) NULL)
5517 XDestroyImage(ximage);
5518 ximage=(XImage *) NULL;
5519 if (segment_info[1].shmaddr)
5520 {
5521 (void) shmdt(segment_info[1].shmaddr);
5522 segment_info[1].shmaddr=(char *) NULL;
5523 }
5524 if (segment_info[1].shmid >= 0)
5525 {
5526 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5527 segment_info[1].shmid=(-1);
5528 }
5529 }
5530 }
5531#endif
5532 /*
5533 Allocate X image pixel data.
5534 */
5535#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5536 if (window->shared_memory)
5537 {
5538 Status
5539 status;
5540
5541 XShmSegmentInfo
5542 *segment_info;
5543
5544 (void) XSync(display,MagickFalse);
5545 xerror_alert=MagickFalse;
5546 segment_info=(XShmSegmentInfo *) window->segment_info;
5547 ximage->data=segment_info[1].shmaddr;
5548 segment_info[1].readOnly=MagickFalse;
5549 status=XShmAttach(display,&segment_info[1]);
5550 if (status != False)
5551 (void) XSync(display,MagickFalse);
5552 if ((status == False) || (xerror_alert != MagickFalse))
5553 {
5554 window->shared_memory=MagickFalse;
5555 if (status != False)
5556 XShmDetach(display,&segment_info[1]);
5557 if (ximage != (XImage *) NULL)
5558 {
5559 ximage->data=NULL;
5560 XDestroyImage(ximage);
5561 ximage=(XImage *) NULL;
5562 }
5563 if (segment_info[1].shmid >= 0)
5564 {
5565 if (segment_info[1].shmaddr != NULL)
5566 (void) shmdt(segment_info[1].shmaddr);
5567 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5568 segment_info[1].shmid=(-1);
5569 segment_info[1].shmaddr=(char *) NULL;
5570 }
5571 }
5572 }
5573#endif
5574 if (window->shared_memory == MagickFalse)
5575 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5576 (char *) NULL,width,height,XBitmapPad(display),0);
5577 if (ximage == (XImage *) NULL)
5578 {
5579 /*
5580 Unable to create X image.
5581 */
5582 (void) XCheckDefineCursor(display,window->id,window->cursor);
5583 return(MagickFalse);
5584 }
5585 length=(size_t) ximage->bytes_per_line*ximage->height;
5586 if (IsEventLogging())
5587 {
5588 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5589 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5590 ximage->width,ximage->height);
5591 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5592 ximage->format);
5593 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5594 ximage->byte_order);
5595 (void) LogMagickEvent(X11Event,GetMagickModule(),
5596 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5597 ximage->bitmap_bit_order,ximage->bitmap_pad);
5598 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5599 ximage->depth);
5600 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5601 ximage->bytes_per_line);
5602 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5603 ximage->bits_per_pixel);
5604 (void) LogMagickEvent(X11Event,GetMagickModule(),
5605 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5606 ximage->green_mask,ximage->blue_mask);
5607 }
5608 if (window->shared_memory == MagickFalse)
5609 {
5610 if (ximage->format != XYBitmap)
5611 ximage->data=(char *) AcquireQuantumMemory((size_t)
5612 ximage->bytes_per_line,(size_t) ximage->height);
5613 else
5614 ximage->data=(char *) AcquireQuantumMemory((size_t)
5615 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5616 }
5617 if (ximage->data == (char *) NULL)
5618 {
5619 /*
5620 Unable to allocate pixel data.
5621 */
5622 XDestroyImage(ximage);
5623 ximage=(XImage *) NULL;
5624 (void) XCheckDefineCursor(display,window->id,window->cursor);
5625 return(MagickFalse);
5626 }
5627 if (window->ximage != (XImage *) NULL)
5628 {
5629 /*
5630 Destroy previous X image.
5631 */
5632 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5633#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5634 if (window->segment_info != (XShmSegmentInfo *) NULL)
5635 {
5636 XShmSegmentInfo
5637 *segment_info;
5638
5639 segment_info=(XShmSegmentInfo *) window->segment_info;
5640 if (segment_info[0].shmid >= 0)
5641 {
5642 (void) XSync(display,MagickFalse);
5643 (void) XShmDetach(display,&segment_info[0]);
5644 (void) XSync(display,MagickFalse);
5645 if (segment_info[0].shmaddr != (char *) NULL)
5646 (void) shmdt(segment_info[0].shmaddr);
5647 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5648 segment_info[0].shmid=(-1);
5649 segment_info[0].shmaddr=(char *) NULL;
5650 window->ximage->data=(char *) NULL;
5651 }
5652 }
5653#endif
5654 if (window->ximage->data != (char *) NULL)
5655 free(window->ximage->data);
5656 window->ximage->data=(char *) NULL;
5657 XDestroyImage(window->ximage);
5658 window->ximage=(XImage *) NULL;
5659 }
5660#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5661 if (window->segment_info != (XShmSegmentInfo *) NULL)
5662 {
5663 XShmSegmentInfo
5664 *segment_info;
5665
5666 segment_info=(XShmSegmentInfo *) window->segment_info;
5667 segment_info[0]=segment_info[1];
5668 }
5669#endif
5670 window->ximage=ximage;
5671 matte_image=(XImage *) NULL;
5672 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5673 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005674 ((int) width <= XDisplayWidth(display,window->screen)) &&
5675 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005676 {
5677 /*
5678 Create matte image.
5679 */
5680 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5681 (char *) NULL,width,height,XBitmapPad(display),0);
5682 if (IsEventLogging())
5683 {
5684 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5685 (void) LogMagickEvent(X11Event,GetMagickModule(),
5686 " width, height: %dx%d",matte_image->width,matte_image->height);
5687 }
5688 if (matte_image != (XImage *) NULL)
5689 {
5690 /*
5691 Allocate matte image pixel data.
5692 */
5693 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5694 matte_image->bytes_per_line*matte_image->depth,
5695 (size_t) matte_image->height);
5696 if (matte_image->data == (char *) NULL)
5697 {
5698 XDestroyImage(matte_image);
5699 matte_image=(XImage *) NULL;
5700 }
5701 }
5702 }
5703 if (window->matte_image != (XImage *) NULL)
5704 {
5705 /*
5706 Free matte image.
5707 */
5708 if (window->matte_image->data != (char *) NULL)
5709 free(window->matte_image->data);
5710 window->matte_image->data=(char *) NULL;
5711 XDestroyImage(window->matte_image);
5712 window->matte_image=(XImage *) NULL;
5713 }
5714 window->matte_image=matte_image;
5715 if (window->matte_pixmap != (Pixmap) NULL)
5716 {
5717 (void) XFreePixmap(display,window->matte_pixmap);
5718 window->matte_pixmap=(Pixmap) NULL;
5719#if defined(MAGICKCORE_HAVE_SHAPE)
5720 if (window->shape != MagickFalse)
5721 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5722#endif
5723 }
5724 window->stasis=MagickFalse;
5725 /*
5726 Convert pixels to X image data.
5727 */
5728 if (window->image != (Image *) NULL)
5729 {
5730 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5731 (ximage->bitmap_bit_order == LSBFirst)))
5732 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5733 matte_image);
5734 else
5735 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5736 matte_image);
5737 }
5738 if (window->matte_image != (XImage *) NULL)
5739 {
5740 /*
5741 Create matte pixmap.
5742 */
5743 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5744 if (window->matte_pixmap != (Pixmap) NULL)
5745 {
5746 GC
5747 graphics_context;
5748
5749 XGCValues
5750 context_values;
5751
5752 /*
5753 Copy matte image to matte pixmap.
5754 */
5755 context_values.background=1;
5756 context_values.foreground=0;
5757 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005758 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005759 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5760 window->matte_image,0,0,0,0,width,height);
5761 (void) XFreeGC(display,graphics_context);
5762#if defined(MAGICKCORE_HAVE_SHAPE)
5763 if (window->shape != MagickFalse)
5764 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5765 window->matte_pixmap,ShapeSet);
5766#endif
5767 }
5768 }
5769 (void) XMakePixmap(display,resource_info,window);
5770 /*
5771 Restore cursor.
5772 */
5773 (void) XCheckDefineCursor(display,window->id,window->cursor);
5774 return(MagickTrue);
5775}
5776
5777/*
5778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5779% %
5780% %
5781% %
5782+ X M a k e I m a g e L S B F i r s t %
5783% %
5784% %
5785% %
5786%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5787%
5788% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5789% pixels are copied in least-significant bit and byte first order. The
5790% server's scanline pad is respected. Rather than using one or two general
5791% cases, many special cases are found here to help speed up the image
5792% conversion.
5793%
5794% The format of the XMakeImageLSBFirst method is:
5795%
5796% void XMakeImageLSBFirst(Display *display,XWindows *windows)
5797%
5798% A description of each parameter follows:
5799%
5800% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5801%
5802% o window: Specifies a pointer to a XWindowInfo structure.
5803%
5804% o image: the image.
5805%
5806% o ximage: Specifies a pointer to a XImage structure; returned from
5807% XCreateImage.
5808%
5809% o matte_image: Specifies a pointer to a XImage structure; returned from
5810% XCreateImage.
5811%
5812*/
5813static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5814 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5815{
cristyc57f6942010-11-12 01:47:39 +00005816 CacheView
5817 *canvas_view;
5818
cristy3ed852e2009-09-05 21:47:34 +00005819 Image
5820 *canvas;
5821
5822 int
5823 y;
5824
5825 register const IndexPacket
5826 *indexes;
5827
5828 register const PixelPacket
5829 *p;
5830
5831 register int
5832 x;
5833
5834 register unsigned char
5835 *q;
5836
5837 unsigned char
5838 bit,
5839 byte;
5840
5841 unsigned int
5842 scanline_pad;
5843
cristyf2faecf2010-05-28 19:19:36 +00005844 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005845 pixel,
5846 *pixels;
5847
5848 XStandardColormap
5849 *map_info;
5850
5851 assert(resource_info != (XResourceInfo *) NULL);
5852 assert(window != (XWindowInfo *) NULL);
5853 assert(image != (Image *) NULL);
5854 if (image->debug != MagickFalse)
5855 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5856 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005857 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005858 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005859 {
5860 char
5861 size[MaxTextExtent];
5862
5863 Image
5864 *pattern;
5865
5866 ImageInfo
5867 *image_info;
5868
5869 image_info=AcquireImageInfo();
5870 (void) CopyMagickString(image_info->filename,
5871 resource_info->image_info->texture != (char *) NULL ?
5872 resource_info->image_info->texture : "pattern:checkerboard",
5873 MaxTextExtent);
cristye8c25f92010-06-03 00:53:06 +00005874 (void) FormatMagickString(size,MaxTextExtent,"%.20gx%.20g",(double)
5875 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005876 image_info->size=ConstantString(size);
5877 pattern=ReadImage(image_info,&image->exception);
5878 image_info=DestroyImageInfo(image_info);
5879 if (pattern != (Image *) NULL)
5880 {
5881 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5882 if (canvas != (Image *) NULL)
5883 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5884 pattern=DestroyImage(pattern);
5885 }
5886 }
5887 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5888 ximage->bits_per_pixel) >> 3));
5889 map_info=window->map_info;
5890 pixels=window->pixel_info->pixels;
5891 q=(unsigned char *) ximage->data;
5892 x=0;
cristyc57f6942010-11-12 01:47:39 +00005893 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005894 if (ximage->format == XYBitmap)
5895 {
5896 register unsigned short
5897 polarity;
5898
5899 unsigned char
5900 background,
5901 foreground;
5902
5903 /*
5904 Convert canvas to big-endian bitmap.
5905 */
5906 background=(unsigned char)
5907 (XPixelIntensity(&window->pixel_info->foreground_color) <
5908 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5909 foreground=(unsigned char)
5910 (XPixelIntensity(&window->pixel_info->background_color) <
5911 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5912 polarity=(unsigned short) ((PixelIntensityToQuantum(
5913 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5914 if (canvas->colors == 2)
5915 polarity=PixelIntensity(&canvas->colormap[0]) <
5916 PixelIntensity(&canvas->colormap[1]);
5917 for (y=0; y < (int) canvas->rows; y++)
5918 {
cristyc57f6942010-11-12 01:47:39 +00005919 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5920 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00005921 if (p == (const PixelPacket *) NULL)
5922 break;
cristyc57f6942010-11-12 01:47:39 +00005923 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00005924 bit=0;
5925 byte=0;
5926 for (x=0; x < (int) canvas->columns; x++)
5927 {
5928 byte>>=1;
5929 if (indexes[x] == (IndexPacket) polarity)
5930 byte|=foreground;
5931 else
5932 byte|=background;
5933 bit++;
5934 if (bit == 8)
5935 {
5936 *q++=byte;
5937 bit=0;
5938 byte=0;
5939 }
5940 }
5941 if (bit != 0)
5942 *q=byte >> (8-bit);
5943 q+=scanline_pad;
5944 }
5945 }
5946 else
5947 if (window->pixel_info->colors != 0)
5948 switch (ximage->bits_per_pixel)
5949 {
5950 case 2:
5951 {
5952 register unsigned int
5953 nibble;
5954
5955 /*
5956 Convert to 2 bit color-mapped X canvas.
5957 */
5958 for (y=0; y < (int) canvas->rows; y++)
5959 {
cristyc57f6942010-11-12 01:47:39 +00005960 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5961 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00005962 if (p == (const PixelPacket *) NULL)
5963 break;
cristyc57f6942010-11-12 01:47:39 +00005964 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00005965 nibble=0;
5966 for (x=0; x < (int) canvas->columns; x++)
5967 {
cristybb503372010-05-27 20:51:26 +00005968 pixel=pixels[(ssize_t) indexes[x]] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00005969 switch (nibble)
5970 {
5971 case 0:
5972 {
5973 *q=(unsigned char) pixel;
5974 nibble++;
5975 break;
5976 }
5977 case 1:
5978 {
5979 *q|=(unsigned char) (pixel << 2);
5980 nibble++;
5981 break;
5982 }
5983 case 2:
5984 {
5985 *q|=(unsigned char) (pixel << 4);
5986 nibble++;
5987 break;
5988 }
5989 case 3:
5990 {
5991 *q|=(unsigned char) (pixel << 6);
5992 q++;
5993 nibble=0;
5994 break;
5995 }
5996 }
5997 }
5998 q+=scanline_pad;
5999 }
6000 break;
6001 }
6002 case 4:
6003 {
6004 register unsigned int
6005 nibble;
6006
6007 /*
6008 Convert to 4 bit color-mapped X canvas.
6009 */
6010 for (y=0; y < (int) canvas->rows; y++)
6011 {
cristyc57f6942010-11-12 01:47:39 +00006012 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6013 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006014 if (p == (const PixelPacket *) NULL)
6015 break;
cristyc57f6942010-11-12 01:47:39 +00006016 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006017 nibble=0;
6018 for (x=0; x < (int) canvas->columns; x++)
6019 {
cristybb503372010-05-27 20:51:26 +00006020 pixel=pixels[(ssize_t) indexes[x]] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006021 switch (nibble)
6022 {
6023 case 0:
6024 {
6025 *q=(unsigned char) pixel;
6026 nibble++;
6027 break;
6028 }
6029 case 1:
6030 {
6031 *q|=(unsigned char) (pixel << 4);
6032 q++;
6033 nibble=0;
6034 break;
6035 }
6036 }
6037 }
6038 q+=scanline_pad;
6039 }
6040 break;
6041 }
6042 case 6:
6043 case 8:
6044 {
6045 /*
6046 Convert to 8 bit color-mapped X canvas.
6047 */
6048 if (resource_info->color_recovery &&
6049 resource_info->quantize_info->dither)
6050 {
6051 XDitherImage(canvas,ximage);
6052 break;
6053 }
6054 for (y=0; y < (int) canvas->rows; y++)
6055 {
cristyc57f6942010-11-12 01:47:39 +00006056 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6057 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006058 if (p == (const PixelPacket *) NULL)
6059 break;
cristyc57f6942010-11-12 01:47:39 +00006060 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006061 for (x=0; x < (int) canvas->columns; x++)
6062 {
cristybb503372010-05-27 20:51:26 +00006063 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006064 *q++=(unsigned char) pixel;
6065 }
6066 q+=scanline_pad;
6067 }
6068 break;
6069 }
6070 default:
6071 {
6072 register int
6073 k;
6074
6075 register unsigned int
6076 bytes_per_pixel;
6077
6078 unsigned char
cristybb503372010-05-27 20:51:26 +00006079 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006080
6081 /*
6082 Convert to multi-byte color-mapped X canvas.
6083 */
6084 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6085 for (y=0; y < (int) canvas->rows; y++)
6086 {
cristyc57f6942010-11-12 01:47:39 +00006087 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6088 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006089 if (p == (const PixelPacket *) NULL)
6090 break;
cristyc57f6942010-11-12 01:47:39 +00006091 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006092 for (x=0; x < (int) canvas->columns; x++)
6093 {
cristybb503372010-05-27 20:51:26 +00006094 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006095 for (k=0; k < (int) bytes_per_pixel; k++)
6096 {
6097 channel[k]=(unsigned char) pixel;
6098 pixel>>=8;
6099 }
6100 for (k=0; k < (int) bytes_per_pixel; k++)
6101 *q++=channel[k];
6102 }
6103 q+=scanline_pad;
6104 }
6105 break;
6106 }
6107 }
6108 else
6109 switch (ximage->bits_per_pixel)
6110 {
6111 case 2:
6112 {
6113 register unsigned int
6114 nibble;
6115
6116 /*
6117 Convert to contiguous 2 bit continuous-tone X canvas.
6118 */
6119 for (y=0; y < (int) canvas->rows; y++)
6120 {
6121 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006122 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6123 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006124 if (p == (const PixelPacket *) NULL)
6125 break;
6126 for (x=0; x < (int) canvas->columns; x++)
6127 {
6128 pixel=XGammaPixel(map_info,p);
6129 pixel&=0xf;
6130 switch (nibble)
6131 {
6132 case 0:
6133 {
6134 *q=(unsigned char) pixel;
6135 nibble++;
6136 break;
6137 }
6138 case 1:
6139 {
6140 *q|=(unsigned char) (pixel << 2);
6141 nibble++;
6142 break;
6143 }
6144 case 2:
6145 {
6146 *q|=(unsigned char) (pixel << 4);
6147 nibble++;
6148 break;
6149 }
6150 case 3:
6151 {
6152 *q|=(unsigned char) (pixel << 6);
6153 q++;
6154 nibble=0;
6155 break;
6156 }
6157 }
6158 p++;
6159 }
6160 q+=scanline_pad;
6161 }
6162 break;
6163 }
6164 case 4:
6165 {
6166 register unsigned int
6167 nibble;
6168
6169 /*
6170 Convert to contiguous 4 bit continuous-tone X canvas.
6171 */
6172 for (y=0; y < (int) canvas->rows; y++)
6173 {
cristyc57f6942010-11-12 01:47:39 +00006174 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6175 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006176 if (p == (const PixelPacket *) NULL)
6177 break;
6178 nibble=0;
6179 for (x=0; x < (int) canvas->columns; x++)
6180 {
6181 pixel=XGammaPixel(map_info,p);
6182 pixel&=0xf;
6183 switch (nibble)
6184 {
6185 case 0:
6186 {
6187 *q=(unsigned char) pixel;
6188 nibble++;
6189 break;
6190 }
6191 case 1:
6192 {
6193 *q|=(unsigned char) (pixel << 4);
6194 q++;
6195 nibble=0;
6196 break;
6197 }
6198 }
6199 p++;
6200 }
6201 q+=scanline_pad;
6202 }
6203 break;
6204 }
6205 case 6:
6206 case 8:
6207 {
6208 /*
6209 Convert to contiguous 8 bit continuous-tone X canvas.
6210 */
6211 if (resource_info->color_recovery &&
6212 resource_info->quantize_info->dither)
6213 {
6214 XDitherImage(canvas,ximage);
6215 break;
6216 }
6217 for (y=0; y < (int) canvas->rows; y++)
6218 {
cristyc57f6942010-11-12 01:47:39 +00006219 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6220 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006221 if (p == (const PixelPacket *) NULL)
6222 break;
6223 for (x=0; x < (int) canvas->columns; x++)
6224 {
6225 pixel=XGammaPixel(map_info,p);
6226 *q++=(unsigned char) pixel;
6227 p++;
6228 }
6229 q+=scanline_pad;
6230 }
6231 break;
6232 }
6233 default:
6234 {
6235 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6236 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6237 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6238 (map_info->blue_mult == 1))
6239 {
6240 /*
6241 Convert to 32 bit continuous-tone X canvas.
6242 */
6243 for (y=0; y < (int) canvas->rows; y++)
6244 {
cristyc57f6942010-11-12 01:47:39 +00006245 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6246 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006247 if (p == (const PixelPacket *) NULL)
6248 break;
6249 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6250 (blue_gamma != 1.0))
6251 {
6252 /*
6253 Gamma correct canvas.
6254 */
6255 for (x=(int) canvas->columns-1; x >= 0; x--)
6256 {
cristyccf844f2010-02-03 23:28:16 +00006257 *q++=ScaleQuantumToChar(XBlueGamma(
6258 GetBluePixelComponent(p)));
6259 *q++=ScaleQuantumToChar(XGreenGamma(
6260 GetGreenPixelComponent(p)));
6261 *q++=ScaleQuantumToChar(XRedGamma(
6262 GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006263 *q++=0;
6264 p++;
6265 }
6266 continue;
6267 }
6268 for (x=(int) canvas->columns-1; x >= 0; x--)
6269 {
cristyce70c172010-01-07 17:15:30 +00006270 *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
6271 *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6272 *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006273 *q++=0;
6274 p++;
6275 }
6276 }
6277 }
6278 else
6279 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6280 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6281 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6282 (map_info->blue_mult == 65536L))
6283 {
6284 /*
6285 Convert to 32 bit continuous-tone X canvas.
6286 */
6287 for (y=0; y < (int) canvas->rows; y++)
6288 {
cristyc57f6942010-11-12 01:47:39 +00006289 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6290 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006291 if (p == (const PixelPacket *) NULL)
6292 break;
6293 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6294 (blue_gamma != 1.0))
6295 {
6296 /*
6297 Gamma correct canvas.
6298 */
6299 for (x=(int) canvas->columns-1; x >= 0; x--)
6300 {
cristyccf844f2010-02-03 23:28:16 +00006301 *q++=ScaleQuantumToChar(XRedGamma(
6302 GetRedPixelComponent(p)));
6303 *q++=ScaleQuantumToChar(XGreenGamma(
6304 GetGreenPixelComponent(p)));
6305 *q++=ScaleQuantumToChar(XBlueGamma(
6306 GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006307 *q++=0;
6308 p++;
6309 }
6310 continue;
6311 }
6312 for (x=(int) canvas->columns-1; x >= 0; x--)
6313 {
cristyccf844f2010-02-03 23:28:16 +00006314 *q++=ScaleQuantumToChar((Quantum)
6315 GetRedPixelComponent(p));
6316 *q++=ScaleQuantumToChar((Quantum)
6317 GetGreenPixelComponent(p));
6318 *q++=ScaleQuantumToChar((Quantum)
6319 GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006320 *q++=0;
6321 p++;
6322 }
6323 }
6324 }
6325 else
6326 {
6327 register int
6328 k;
6329
6330 register unsigned int
6331 bytes_per_pixel;
6332
6333 unsigned char
cristybb503372010-05-27 20:51:26 +00006334 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006335
6336 /*
6337 Convert to multi-byte continuous-tone X canvas.
6338 */
6339 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6340 for (y=0; y < (int) canvas->rows; y++)
6341 {
cristyc57f6942010-11-12 01:47:39 +00006342 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6343 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006344 if (p == (PixelPacket *) NULL)
6345 break;
cristyc57f6942010-11-12 01:47:39 +00006346 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006347 {
6348 pixel=XGammaPixel(map_info,p);
6349 for (k=0; k < (int) bytes_per_pixel; k++)
6350 {
6351 channel[k]=(unsigned char) pixel;
6352 pixel>>=8;
6353 }
6354 for (k=0; k < (int) bytes_per_pixel; k++)
6355 *q++=channel[k];
6356 p++;
6357 }
6358 q+=scanline_pad;
6359 }
6360 }
6361 break;
6362 }
6363 }
6364 if (matte_image != (XImage *) NULL)
6365 {
6366 /*
6367 Initialize matte canvas.
6368 */
6369 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6370 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6371 q=(unsigned char *) matte_image->data;
6372 for (y=0; y < (int) canvas->rows; y++)
6373 {
cristyc57f6942010-11-12 01:47:39 +00006374 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6375 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006376 if (p == (const PixelPacket *) NULL)
6377 break;
6378 bit=0;
6379 byte=0;
6380 for (x=(int) canvas->columns-1; x >= 0; x--)
6381 {
6382 byte>>=1;
cristyc57f6942010-11-12 01:47:39 +00006383 if (p->opacity > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006384 byte|=0x80;
6385 bit++;
6386 if (bit == 8)
6387 {
6388 *q++=byte;
6389 bit=0;
6390 byte=0;
6391 }
6392 p++;
6393 }
6394 if (bit != 0)
6395 *q=byte >> (8-bit);
6396 q+=scanline_pad;
6397 }
6398 }
cristyc57f6942010-11-12 01:47:39 +00006399 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006400 if (canvas != image)
6401 canvas=DestroyImage(canvas);
6402}
6403
6404/*
6405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6406% %
6407% %
6408% %
6409+ X M a k e I m a g e M S B F i r s t %
6410% %
6411% %
6412% %
6413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6414%
6415% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6416% image pixels are copied in most-significant bit and byte first order. The
6417% server's scanline pad is also respected. Rather than using one or two
6418% general cases, many special cases are found here to help speed up the image
6419% conversion.
6420%
6421% The format of the XMakeImageMSBFirst method is:
6422%
6423% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6424%
6425% A description of each parameter follows:
6426%
6427% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6428%
6429% o window: Specifies a pointer to a XWindowInfo structure.
6430%
6431% o image: the image.
6432%
6433% o ximage: Specifies a pointer to a XImage structure; returned from
6434% XCreateImage.
6435%
6436% o matte_image: Specifies a pointer to a XImage structure; returned from
6437% XCreateImage.
6438%
cristy3ed852e2009-09-05 21:47:34 +00006439*/
6440static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6441 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6442{
cristyc57f6942010-11-12 01:47:39 +00006443 CacheView
6444 *canvas_view;
6445
cristy3ed852e2009-09-05 21:47:34 +00006446 Image
6447 *canvas;
6448
6449 int
6450 y;
6451
6452 register int
6453 x;
6454
6455 register const IndexPacket
6456 *indexes;
6457
6458 register const PixelPacket
6459 *p;
6460
6461 register unsigned char
6462 *q;
6463
6464 unsigned char
6465 bit,
6466 byte;
6467
6468 unsigned int
6469 scanline_pad;
6470
cristyf2faecf2010-05-28 19:19:36 +00006471 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006472 pixel,
6473 *pixels;
6474
6475 XStandardColormap
6476 *map_info;
6477
6478 assert(resource_info != (XResourceInfo *) NULL);
6479 assert(window != (XWindowInfo *) NULL);
6480 assert(image != (Image *) NULL);
6481 if (image->debug != MagickFalse)
6482 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6483 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006484 if ((window->immutable != MagickFalse) &&
6485 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006486 {
6487 char
6488 size[MaxTextExtent];
6489
6490 Image
6491 *pattern;
6492
6493 ImageInfo
6494 *image_info;
6495
6496 image_info=AcquireImageInfo();
6497 (void) CopyMagickString(image_info->filename,
6498 resource_info->image_info->texture != (char *) NULL ?
6499 resource_info->image_info->texture : "pattern:checkerboard",
6500 MaxTextExtent);
cristye8c25f92010-06-03 00:53:06 +00006501 (void) FormatMagickString(size,MaxTextExtent,"%.20gx%.20g",(double)
6502 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006503 image_info->size=ConstantString(size);
6504 pattern=ReadImage(image_info,&image->exception);
6505 image_info=DestroyImageInfo(image_info);
6506 if (pattern != (Image *) NULL)
6507 {
6508 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6509 if (canvas != (Image *) NULL)
6510 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6511 pattern=DestroyImage(pattern);
6512 }
6513 }
6514 scanline_pad=(unsigned int) (ximage->bytes_per_line-
6515 ((ximage->width*ximage->bits_per_pixel) >> 3));
6516 map_info=window->map_info;
6517 pixels=window->pixel_info->pixels;
6518 q=(unsigned char *) ximage->data;
6519 x=0;
cristyc57f6942010-11-12 01:47:39 +00006520 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006521 if (ximage->format == XYBitmap)
6522 {
6523 register unsigned short
6524 polarity;
6525
6526 unsigned char
6527 background,
6528 foreground;
6529
6530 /*
6531 Convert canvas to big-endian bitmap.
6532 */
6533 background=(unsigned char)
6534 (XPixelIntensity(&window->pixel_info->foreground_color) <
6535 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6536 foreground=(unsigned char)
6537 (XPixelIntensity(&window->pixel_info->background_color) <
6538 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
6539 polarity=(unsigned short) ((PixelIntensityToQuantum(
6540 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6541 if (canvas->colors == 2)
6542 polarity=PixelIntensity(&canvas->colormap[0]) <
6543 PixelIntensity(&canvas->colormap[1]);
6544 for (y=0; y < (int) canvas->rows; y++)
6545 {
cristyc57f6942010-11-12 01:47:39 +00006546 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6547 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006548 if (p == (const PixelPacket *) NULL)
6549 break;
cristyc57f6942010-11-12 01:47:39 +00006550 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006551 bit=0;
6552 byte=0;
6553 for (x=(int) canvas->columns-1; x >= 0; x--)
6554 {
6555 byte<<=1;
6556 if (indexes[x] == (IndexPacket) polarity)
6557 byte|=foreground;
6558 else
6559 byte|=background;
6560 bit++;
6561 if (bit == 8)
6562 {
6563 *q++=byte;
6564 bit=0;
6565 byte=0;
6566 }
6567 }
6568 if (bit != 0)
6569 *q=byte << (8-bit);
6570 q+=scanline_pad;
6571 }
6572 }
6573 else
6574 if (window->pixel_info->colors != 0)
6575 switch (ximage->bits_per_pixel)
6576 {
6577 case 2:
6578 {
6579 register unsigned int
6580 nibble;
6581
6582 /*
6583 Convert to 2 bit color-mapped X canvas.
6584 */
6585 for (y=0; y < (int) canvas->rows; y++)
6586 {
cristyc57f6942010-11-12 01:47:39 +00006587 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6588 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006589 if (p == (const PixelPacket *) NULL)
6590 break;
cristyc57f6942010-11-12 01:47:39 +00006591 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006592 nibble=0;
6593 for (x=0; x < (int) canvas->columns; x++)
6594 {
cristybb503372010-05-27 20:51:26 +00006595 pixel=pixels[(ssize_t) indexes[x]] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006596 switch (nibble)
6597 {
6598 case 0:
6599 {
6600 *q=(unsigned char) (pixel << 6);
6601 nibble++;
6602 break;
6603 }
6604 case 1:
6605 {
6606 *q|=(unsigned char) (pixel << 4);
6607 nibble++;
6608 break;
6609 }
6610 case 2:
6611 {
6612 *q|=(unsigned char) (pixel << 2);
6613 nibble++;
6614 break;
6615 }
6616 case 3:
6617 {
6618 *q|=(unsigned char) pixel;
6619 q++;
6620 nibble=0;
6621 break;
6622 }
6623 }
6624 }
6625 q+=scanline_pad;
6626 }
6627 break;
6628 }
6629 case 4:
6630 {
6631 register unsigned int
6632 nibble;
6633
6634 /*
6635 Convert to 4 bit color-mapped X canvas.
6636 */
6637 for (y=0; y < (int) canvas->rows; y++)
6638 {
cristyc57f6942010-11-12 01:47:39 +00006639 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6640 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006641 if (p == (const PixelPacket *) NULL)
6642 break;
cristyc57f6942010-11-12 01:47:39 +00006643 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006644 nibble=0;
6645 for (x=0; x < (int) canvas->columns; x++)
6646 {
cristybb503372010-05-27 20:51:26 +00006647 pixel=pixels[(ssize_t) indexes[x]] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006648 switch (nibble)
6649 {
6650 case 0:
6651 {
6652 *q=(unsigned char) (pixel << 4);
6653 nibble++;
6654 break;
6655 }
6656 case 1:
6657 {
6658 *q|=(unsigned char) pixel;
6659 q++;
6660 nibble=0;
6661 break;
6662 }
6663 }
6664 }
6665 q+=scanline_pad;
6666 }
6667 break;
6668 }
6669 case 6:
6670 case 8:
6671 {
6672 /*
6673 Convert to 8 bit color-mapped X canvas.
6674 */
6675 if (resource_info->color_recovery &&
6676 resource_info->quantize_info->dither)
6677 {
6678 XDitherImage(canvas,ximage);
6679 break;
6680 }
6681 for (y=0; y < (int) canvas->rows; y++)
6682 {
cristyc57f6942010-11-12 01:47:39 +00006683 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6684 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006685 if (p == (const PixelPacket *) NULL)
6686 break;
cristyc57f6942010-11-12 01:47:39 +00006687 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006688 for (x=0; x < (int) canvas->columns; x++)
6689 {
cristybb503372010-05-27 20:51:26 +00006690 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006691 *q++=(unsigned char) pixel;
6692 }
6693 q+=scanline_pad;
6694 }
6695 break;
6696 }
6697 default:
6698 {
6699 register int
6700 k;
6701
6702 register unsigned int
6703 bytes_per_pixel;
6704
6705 unsigned char
cristybb503372010-05-27 20:51:26 +00006706 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006707
6708 /*
6709 Convert to 8 bit color-mapped X canvas.
6710 */
6711 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6712 for (y=0; y < (int) canvas->rows; y++)
6713 {
cristyc57f6942010-11-12 01:47:39 +00006714 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6715 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006716 if (p == (const PixelPacket *) NULL)
6717 break;
cristyc57f6942010-11-12 01:47:39 +00006718 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006719 for (x=0; x < (int) canvas->columns; x++)
6720 {
cristybb503372010-05-27 20:51:26 +00006721 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006722 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6723 {
6724 channel[k]=(unsigned char) pixel;
6725 pixel>>=8;
6726 }
6727 for (k=0; k < (int) bytes_per_pixel; k++)
6728 *q++=channel[k];
6729 }
6730 q+=scanline_pad;
6731 }
6732 break;
6733 }
6734 }
6735 else
6736 switch (ximage->bits_per_pixel)
6737 {
6738 case 2:
6739 {
6740 register unsigned int
6741 nibble;
6742
6743 /*
6744 Convert to 4 bit continuous-tone X canvas.
6745 */
6746 for (y=0; y < (int) canvas->rows; y++)
6747 {
cristyc57f6942010-11-12 01:47:39 +00006748 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6749 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006750 if (p == (const PixelPacket *) NULL)
6751 break;
6752 nibble=0;
6753 for (x=(int) canvas->columns-1; x >= 0; x--)
6754 {
6755 pixel=XGammaPixel(map_info,p);
6756 pixel&=0xf;
6757 switch (nibble)
6758 {
6759 case 0:
6760 {
6761 *q=(unsigned char) (pixel << 6);
6762 nibble++;
6763 break;
6764 }
6765 case 1:
6766 {
6767 *q|=(unsigned char) (pixel << 4);
6768 nibble++;
6769 break;
6770 }
6771 case 2:
6772 {
6773 *q|=(unsigned char) (pixel << 2);
6774 nibble++;
6775 break;
6776 }
6777 case 3:
6778 {
6779 *q|=(unsigned char) pixel;
6780 q++;
6781 nibble=0;
6782 break;
6783 }
6784 }
6785 p++;
6786 }
6787 q+=scanline_pad;
6788 }
6789 break;
6790 }
6791 case 4:
6792 {
6793 register unsigned int
6794 nibble;
6795
6796 /*
6797 Convert to 4 bit continuous-tone X canvas.
6798 */
6799 for (y=0; y < (int) canvas->rows; y++)
6800 {
cristyc57f6942010-11-12 01:47:39 +00006801 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6802 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006803 if (p == (const PixelPacket *) NULL)
6804 break;
6805 nibble=0;
6806 for (x=(int) canvas->columns-1; x >= 0; x--)
6807 {
6808 pixel=XGammaPixel(map_info,p);
6809 pixel&=0xf;
6810 switch (nibble)
6811 {
6812 case 0:
6813 {
6814 *q=(unsigned char) (pixel << 4);
6815 nibble++;
6816 break;
6817 }
6818 case 1:
6819 {
6820 *q|=(unsigned char) pixel;
6821 q++;
6822 nibble=0;
6823 break;
6824 }
6825 }
6826 p++;
6827 }
6828 q+=scanline_pad;
6829 }
6830 break;
6831 }
6832 case 6:
6833 case 8:
6834 {
6835 /*
6836 Convert to 8 bit continuous-tone X canvas.
6837 */
6838 if (resource_info->color_recovery &&
6839 resource_info->quantize_info->dither)
6840 {
6841 XDitherImage(canvas,ximage);
6842 break;
6843 }
6844 for (y=0; y < (int) canvas->rows; y++)
6845 {
cristyc57f6942010-11-12 01:47:39 +00006846 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6847 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006848 if (p == (const PixelPacket *) NULL)
6849 break;
6850 for (x=(int) canvas->columns-1; x >= 0; x--)
6851 {
6852 pixel=XGammaPixel(map_info,p);
6853 *q++=(unsigned char) pixel;
6854 p++;
6855 }
6856 q+=scanline_pad;
6857 }
6858 break;
6859 }
6860 default:
6861 {
6862 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6863 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6864 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6865 (map_info->blue_mult == 1))
6866 {
6867 /*
6868 Convert to 32 bit continuous-tone X canvas.
6869 */
6870 for (y=0; y < (int) canvas->rows; y++)
6871 {
cristyc57f6942010-11-12 01:47:39 +00006872 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6873 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006874 if (p == (const PixelPacket *) NULL)
6875 break;
6876 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6877 (blue_gamma != 1.0))
6878 {
6879 /*
6880 Gamma correct canvas.
6881 */
6882 for (x=(int) canvas->columns-1; x >= 0; x--)
6883 {
6884 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006885 *q++=ScaleQuantumToChar(XRedGamma(
6886 GetRedPixelComponent(p)));
6887 *q++=ScaleQuantumToChar(XGreenGamma(
6888 GetGreenPixelComponent(p)));
6889 *q++=ScaleQuantumToChar(XBlueGamma(
6890 GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006891 p++;
6892 }
6893 continue;
6894 }
6895 for (x=(int) canvas->columns-1; x >= 0; x--)
6896 {
6897 *q++=0;
cristyce70c172010-01-07 17:15:30 +00006898 *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
6899 *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6900 *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006901 p++;
6902 }
6903 }
6904 }
6905 else
6906 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6907 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6908 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6909 (map_info->blue_mult == 65536L))
6910 {
6911 /*
6912 Convert to 32 bit continuous-tone X canvas.
6913 */
6914 for (y=0; y < (int) canvas->rows; y++)
6915 {
cristyc57f6942010-11-12 01:47:39 +00006916 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6917 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006918 if (p == (const PixelPacket *) NULL)
6919 break;
6920 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6921 (blue_gamma != 1.0))
6922 {
6923 /*
6924 Gamma correct canvas.
6925 */
6926 for (x=(int) canvas->columns-1; x >= 0; x--)
6927 {
6928 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006929 *q++=ScaleQuantumToChar(XBlueGamma(
6930 GetBluePixelComponent(p)));
6931 *q++=ScaleQuantumToChar(XGreenGamma(
6932 GetGreenPixelComponent(p)));
6933 *q++=ScaleQuantumToChar(XRedGamma(
6934 GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006935 p++;
6936 }
6937 continue;
6938 }
6939 for (x=(int) canvas->columns-1; x >= 0; x--)
6940 {
6941 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006942 *q++=ScaleQuantumToChar((Quantum)
6943 GetBluePixelComponent(p));
6944 *q++=ScaleQuantumToChar((Quantum)
6945 GetGreenPixelComponent(p));
6946 *q++=ScaleQuantumToChar((Quantum)
6947 GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006948 p++;
6949 }
6950 }
6951 }
6952 else
6953 {
6954 register int
6955 k;
6956
6957 register unsigned int
6958 bytes_per_pixel;
6959
6960 unsigned char
cristybb503372010-05-27 20:51:26 +00006961 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006962
6963 /*
6964 Convert to multi-byte continuous-tone X canvas.
6965 */
6966 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6967 for (y=0; y < (int) canvas->rows; y++)
6968 {
cristyc57f6942010-11-12 01:47:39 +00006969 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6970 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006971 if (p == (const PixelPacket *) NULL)
6972 break;
6973 for (x=(int) canvas->columns-1; x >= 0; x--)
6974 {
6975 pixel=XGammaPixel(map_info,p);
6976 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6977 {
6978 channel[k]=(unsigned char) pixel;
6979 pixel>>=8;
6980 }
6981 for (k=0; k < (int) bytes_per_pixel; k++)
6982 *q++=channel[k];
6983 p++;
6984 }
6985 q+=scanline_pad;
6986 }
6987 }
6988 break;
6989 }
6990 }
6991 if (matte_image != (XImage *) NULL)
6992 {
6993 /*
6994 Initialize matte canvas.
6995 */
6996 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6997 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6998 q=(unsigned char *) matte_image->data;
6999 for (y=0; y < (int) canvas->rows; y++)
7000 {
cristyc57f6942010-11-12 01:47:39 +00007001 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7002 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00007003 if (p == (const PixelPacket *) NULL)
7004 break;
7005 bit=0;
7006 byte=0;
7007 for (x=(int) canvas->columns-1; x >= 0; x--)
7008 {
7009 byte<<=1;
cristyc57f6942010-11-12 01:47:39 +00007010 if (p->opacity > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007011 byte|=0x01;
7012 bit++;
7013 if (bit == 8)
7014 {
7015 *q++=byte;
7016 bit=0;
7017 byte=0;
7018 }
7019 p++;
7020 }
7021 if (bit != 0)
7022 *q=byte << (8-bit);
7023 q+=scanline_pad;
7024 }
7025 }
cristyc57f6942010-11-12 01:47:39 +00007026 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007027 if (canvas != image)
7028 canvas=DestroyImage(canvas);
7029}
7030
7031/*
7032%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7033% %
7034% %
7035% %
7036% X M a k e M a g n i f y I m a g e %
7037% %
7038% %
7039% %
7040%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7041%
7042% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7043%
7044% The format of the XMakeMagnifyImage method is:
7045%
7046% void XMakeMagnifyImage(display,windows)
7047%
7048% A description of each parameter follows:
7049%
7050% o display: Specifies a connection to an X server; returned from
7051% XOpenDisplay.
7052%
7053% o windows: Specifies a pointer to a XWindows structure.
7054%
7055*/
7056MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
7057{
7058 char
7059 tuple[MaxTextExtent];
7060
7061 int
7062 y;
7063
cristybb503372010-05-27 20:51:26 +00007064 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007065 n;
7066
7067 MagickPixelPacket
7068 pixel;
7069
7070 register int
7071 x;
7072
cristybb503372010-05-27 20:51:26 +00007073 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007074 i;
7075
7076 register unsigned char
7077 *p,
7078 *q;
7079
7080 static unsigned int
7081 previous_magnify = 0;
7082
7083 static XWindowInfo
7084 magnify_window;
7085
7086 unsigned int
7087 height,
7088 j,
7089 k,
7090 l,
7091 magnify,
7092 scanline_pad,
7093 width;
7094
7095 XImage
7096 *ximage;
7097
7098 /*
7099 Check boundary conditions.
7100 */
7101 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7102 assert(display != (Display *) NULL);
7103 assert(windows != (XWindows *) NULL);
7104 magnify=1;
cristybb503372010-05-27 20:51:26 +00007105 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007106 magnify<<=1;
7107 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7108 magnify<<=1;
7109 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7110 magnify<<=1;
7111 while (magnify > windows->magnify.width)
7112 magnify>>=1;
7113 while (magnify > windows->magnify.height)
7114 magnify>>=1;
7115 if (magnify != previous_magnify)
7116 {
7117 Status
7118 status;
7119
7120 XTextProperty
7121 window_name;
7122
7123 /*
7124 New magnify factor: update magnify window name.
7125 */
7126 i=0;
7127 while ((1 << i) <= (int) magnify)
7128 i++;
7129 (void) FormatMagickString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007130 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007131 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7132 if (status != False)
7133 {
7134 XSetWMName(display,windows->magnify.id,&window_name);
7135 XSetWMIconName(display,windows->magnify.id,&window_name);
7136 (void) XFree((void *) window_name.value);
7137 }
7138 }
7139 previous_magnify=magnify;
7140 ximage=windows->image.ximage;
7141 width=(unsigned int) windows->magnify.ximage->width;
7142 height=(unsigned int) windows->magnify.ximage->height;
7143 if ((windows->magnify.x < 0) ||
7144 (windows->magnify.x >= windows->image.ximage->width))
7145 windows->magnify.x=windows->image.ximage->width >> 1;
7146 x=windows->magnify.x-((width/magnify) >> 1);
7147 if (x < 0)
7148 x=0;
7149 else
7150 if (x > (int) (ximage->width-(width/magnify)))
7151 x=ximage->width-width/magnify;
7152 if ((windows->magnify.y < 0) ||
7153 (windows->magnify.y >= windows->image.ximage->height))
7154 windows->magnify.y=windows->image.ximage->height >> 1;
7155 y=windows->magnify.y-((height/magnify) >> 1);
7156 if (y < 0)
7157 y=0;
7158 else
7159 if (y > (int) (ximage->height-(height/magnify)))
7160 y=ximage->height-height/magnify;
7161 q=(unsigned char *) windows->magnify.ximage->data;
7162 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7163 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7164 if (ximage->bits_per_pixel < 8)
7165 {
7166 register unsigned char
7167 background,
7168 byte,
7169 foreground,
7170 p_bit,
7171 q_bit;
7172
7173 register unsigned int
7174 plane;
7175
7176 XPixelInfo
7177 *pixel_info;
7178
7179 pixel_info=windows->magnify.pixel_info;
7180 switch (ximage->bitmap_bit_order)
7181 {
7182 case LSBFirst:
7183 {
7184 /*
7185 Magnify little-endian bitmap.
7186 */
7187 background=0x00;
7188 foreground=0x80;
7189 if (ximage->format == XYBitmap)
7190 {
7191 background=(unsigned char)
7192 (XPixelIntensity(&pixel_info->foreground_color) <
7193 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7194 foreground=(unsigned char)
7195 (XPixelIntensity(&pixel_info->background_color) <
7196 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7197 if (windows->magnify.depth > 1)
7198 Swap(background,foreground);
7199 }
cristybb503372010-05-27 20:51:26 +00007200 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007201 {
7202 /*
7203 Propogate pixel magnify rows.
7204 */
7205 for (j=0; j < magnify; j++)
7206 {
7207 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7208 ((x*ximage->bits_per_pixel) >> 3);
7209 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7210 q_bit=0;
7211 byte=0;
7212 for (k=0; k < width; k+=magnify)
7213 {
7214 /*
7215 Propogate pixel magnify columns.
7216 */
7217 for (l=0; l < magnify; l++)
7218 {
7219 /*
7220 Propogate each bit plane.
7221 */
7222 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7223 {
7224 byte>>=1;
7225 if (*p & (0x01 << (p_bit+plane)))
7226 byte|=foreground;
7227 else
7228 byte|=background;
7229 q_bit++;
7230 if (q_bit == 8)
7231 {
7232 *q++=byte;
7233 q_bit=0;
7234 byte=0;
7235 }
7236 }
7237 }
7238 p_bit+=ximage->bits_per_pixel;
7239 if (p_bit == 8)
7240 {
7241 p++;
7242 p_bit=0;
7243 }
7244 if (q_bit != 0)
7245 *q=byte >> (8-q_bit);
7246 q+=scanline_pad;
7247 }
7248 }
7249 y++;
7250 }
7251 break;
7252 }
7253 case MSBFirst:
7254 default:
7255 {
7256 /*
7257 Magnify big-endian bitmap.
7258 */
7259 background=0x00;
7260 foreground=0x01;
7261 if (ximage->format == XYBitmap)
7262 {
7263 background=(unsigned char)
7264 (XPixelIntensity(&pixel_info->foreground_color) <
7265 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7266 foreground=(unsigned char)
7267 (XPixelIntensity(&pixel_info->background_color) <
7268 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7269 if (windows->magnify.depth > 1)
7270 Swap(background,foreground);
7271 }
cristybb503372010-05-27 20:51:26 +00007272 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007273 {
7274 /*
7275 Propogate pixel magnify rows.
7276 */
7277 for (j=0; j < magnify; j++)
7278 {
7279 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7280 ((x*ximage->bits_per_pixel) >> 3);
7281 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7282 q_bit=0;
7283 byte=0;
7284 for (k=0; k < width; k+=magnify)
7285 {
7286 /*
7287 Propogate pixel magnify columns.
7288 */
7289 for (l=0; l < magnify; l++)
7290 {
7291 /*
7292 Propogate each bit plane.
7293 */
7294 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7295 {
7296 byte<<=1;
7297 if (*p & (0x80 >> (p_bit+plane)))
7298 byte|=foreground;
7299 else
7300 byte|=background;
7301 q_bit++;
7302 if (q_bit == 8)
7303 {
7304 *q++=byte;
7305 q_bit=0;
7306 byte=0;
7307 }
7308 }
7309 }
7310 p_bit+=ximage->bits_per_pixel;
7311 if (p_bit == 8)
7312 {
7313 p++;
7314 p_bit=0;
7315 }
7316 if (q_bit != 0)
7317 *q=byte << (8-q_bit);
7318 q+=scanline_pad;
7319 }
7320 }
7321 y++;
7322 }
7323 break;
7324 }
7325 }
7326 }
7327 else
7328 switch (ximage->bits_per_pixel)
7329 {
7330 case 6:
7331 case 8:
7332 {
7333 /*
7334 Magnify 8 bit X image.
7335 */
cristybb503372010-05-27 20:51:26 +00007336 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007337 {
7338 /*
7339 Propogate pixel magnify rows.
7340 */
7341 for (j=0; j < magnify; j++)
7342 {
7343 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7344 ((x*ximage->bits_per_pixel) >> 3);
7345 for (k=0; k < width; k+=magnify)
7346 {
7347 /*
7348 Propogate pixel magnify columns.
7349 */
7350 for (l=0; l < magnify; l++)
7351 *q++=(*p);
7352 p++;
7353 }
7354 q+=scanline_pad;
7355 }
7356 y++;
7357 }
7358 break;
7359 }
7360 default:
7361 {
7362 register unsigned int
7363 bytes_per_pixel,
7364 m;
7365
7366 /*
7367 Magnify multi-byte X image.
7368 */
7369 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007370 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007371 {
7372 /*
7373 Propogate pixel magnify rows.
7374 */
7375 for (j=0; j < magnify; j++)
7376 {
7377 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7378 ((x*ximage->bits_per_pixel) >> 3);
7379 for (k=0; k < width; k+=magnify)
7380 {
7381 /*
7382 Propogate pixel magnify columns.
7383 */
7384 for (l=0; l < magnify; l++)
7385 for (m=0; m < bytes_per_pixel; m++)
7386 *q++=(*(p+m));
7387 p+=bytes_per_pixel;
7388 }
7389 q+=scanline_pad;
7390 }
7391 y++;
7392 }
7393 break;
7394 }
7395 }
7396 /*
7397 Copy X image to magnify pixmap.
7398 */
7399 x=windows->magnify.x-((width/magnify) >> 1);
7400 if (x < 0)
7401 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7402 else
7403 if (x > (int) (ximage->width-(width/magnify)))
7404 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7405 else
7406 x=0;
7407 y=windows->magnify.y-((height/magnify) >> 1);
7408 if (y < 0)
7409 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7410 else
7411 if (y > (int) (ximage->height-(height/magnify)))
7412 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7413 else
7414 y=0;
7415 if ((x != 0) || (y != 0))
7416 (void) XFillRectangle(display,windows->magnify.pixmap,
7417 windows->magnify.annotate_context,0,0,width,height);
7418 (void) XPutImage(display,windows->magnify.pixmap,
7419 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7420 height-y);
7421 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7422 (magnify <= (height >> 1))))
7423 {
7424 RectangleInfo
7425 highlight_info;
7426
7427 /*
7428 Highlight center pixel.
7429 */
cristybb503372010-05-27 20:51:26 +00007430 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7431 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007432 highlight_info.width=magnify;
7433 highlight_info.height=magnify;
7434 (void) XDrawRectangle(display,windows->magnify.pixmap,
7435 windows->magnify.highlight_context,(int) highlight_info.x,
7436 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7437 (unsigned int) highlight_info.height-1);
7438 if (magnify > 2)
7439 (void) XDrawRectangle(display,windows->magnify.pixmap,
7440 windows->magnify.annotate_context,(int) highlight_info.x+1,
7441 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7442 (unsigned int) highlight_info.height-3);
7443 }
7444 /*
7445 Show center pixel color.
7446 */
cristyc57f6942010-11-12 01:47:39 +00007447 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7448 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7449 &windows->image.image->exception);
cristy3ed852e2009-09-05 21:47:34 +00007450 (void) FormatMagickString(tuple,MaxTextExtent,"%d,%d: ",
7451 windows->magnify.x,windows->magnify.y);
7452 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7453 ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
7454 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7455 ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
7456 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7457 ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
7458 if (pixel.colorspace == CMYKColorspace)
7459 {
7460 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7461 ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
7462 }
7463 if (pixel.matte != MagickFalse)
7464 {
7465 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7466 ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
7467 }
7468 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7469 height=(unsigned int) windows->magnify.font_info->ascent+
7470 windows->magnify.font_info->descent;
7471 x=windows->magnify.font_info->max_bounds.width >> 1;
7472 y=windows->magnify.font_info->ascent+(height >> 2);
7473 (void) XDrawImageString(display,windows->magnify.pixmap,
7474 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7475 GetColorTuple(&pixel,MagickTrue,tuple);
7476 y+=height;
7477 (void) XDrawImageString(display,windows->magnify.pixmap,
7478 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7479 (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7480 &windows->image.image->exception);
7481 y+=height;
7482 (void) XDrawImageString(display,windows->magnify.pixmap,
7483 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7484 /*
7485 Refresh magnify window.
7486 */
7487 magnify_window=windows->magnify;
7488 magnify_window.x=0;
7489 magnify_window.y=0;
7490 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7491}
7492
7493/*
7494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7495% %
7496% %
7497% %
7498% X M a k e P i x m a p %
7499% %
7500% %
7501% %
7502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7503%
7504% XMakePixmap() creates an X11 pixmap.
7505%
7506% The format of the XMakePixmap method is:
7507%
7508% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7509% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7510% XPixelInfo *pixel)
7511%
7512% A description of each parameter follows:
7513%
7514% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7515%
7516% o display: Specifies a connection to an X server; returned from
7517% XOpenDisplay.
7518%
7519% o window: Specifies a pointer to a XWindowInfo structure.
7520%
cristy3ed852e2009-09-05 21:47:34 +00007521*/
7522static MagickBooleanType XMakePixmap(Display *display,
7523 const XResourceInfo *resource_info,XWindowInfo *window)
7524{
7525 unsigned int
7526 height,
7527 width;
7528
7529 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7530 assert(display != (Display *) NULL);
7531 assert(resource_info != (XResourceInfo *) NULL);
7532 assert(window != (XWindowInfo *) NULL);
7533 if (window->pixmap != (Pixmap) NULL)
7534 {
7535 /*
7536 Destroy previous X pixmap.
7537 */
7538 (void) XFreePixmap(display,window->pixmap);
7539 window->pixmap=(Pixmap) NULL;
7540 }
7541 if (window->use_pixmap == MagickFalse)
7542 return(MagickFalse);
7543 if (window->ximage == (XImage *) NULL)
7544 return(MagickFalse);
7545 /*
7546 Display busy cursor.
7547 */
7548 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7549 (void) XFlush(display);
7550 /*
7551 Create pixmap.
7552 */
7553 width=(unsigned int) window->ximage->width;
7554 height=(unsigned int) window->ximage->height;
7555 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7556 if (window->pixmap == (Pixmap) NULL)
7557 {
7558 /*
7559 Unable to allocate pixmap.
7560 */
7561 (void) XCheckDefineCursor(display,window->id,window->cursor);
7562 return(MagickFalse);
7563 }
7564 /*
7565 Copy X image to pixmap.
7566 */
7567#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7568 if (window->shared_memory)
7569 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7570 window->ximage,0,0,0,0,width,height,MagickTrue);
7571#endif
7572 if (window->shared_memory == MagickFalse)
7573 (void) XPutImage(display,window->pixmap,window->annotate_context,
7574 window->ximage,0,0,0,0,width,height);
7575 if (IsEventLogging())
7576 {
7577 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7578 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7579 width,height);
7580 }
7581 /*
7582 Restore cursor.
7583 */
7584 (void) XCheckDefineCursor(display,window->id,window->cursor);
7585 return(MagickTrue);
7586}
7587
7588/*
7589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7590% %
7591% %
7592% %
7593% X M a k e S t a n d a r d C o l o r m a p %
7594% %
7595% %
7596% %
7597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7598%
7599% XMakeStandardColormap() creates an X11 Standard Colormap.
7600%
7601% The format of the XMakeStandardColormap method is:
7602%
7603% XMakeStandardColormap(display,visual_info,resource_info,image,
7604% map_info,pixel)
7605%
7606% A description of each parameter follows:
7607%
7608% o display: Specifies a connection to an X server; returned from
7609% XOpenDisplay.
7610%
7611% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7612% returned from XGetVisualInfo.
7613%
7614% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7615%
7616% o image: the image.
7617%
7618% o map_info: If a Standard Colormap type is specified, this structure is
7619% initialized with info from the Standard Colormap.
7620%
7621% o pixel: Specifies a pointer to a XPixelInfo structure.
7622%
cristy3ed852e2009-09-05 21:47:34 +00007623*/
7624
7625#if defined(__cplusplus) || defined(c_plusplus)
7626extern "C" {
7627#endif
7628
7629static inline MagickRealType DiversityPixelIntensity(
7630 const DiversityPacket *pixel)
7631{
7632 MagickRealType
7633 intensity;
7634
7635 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7636 return(intensity);
7637}
7638
7639static int IntensityCompare(const void *x,const void *y)
7640{
7641 DiversityPacket
7642 *color_1,
7643 *color_2;
7644
7645 int
7646 diversity;
7647
7648 color_1=(DiversityPacket *) x;
7649 color_2=(DiversityPacket *) y;
7650 diversity=(int) (DiversityPixelIntensity(color_2)-
7651 DiversityPixelIntensity(color_1));
7652 return(diversity);
7653}
7654
7655static int PopularityCompare(const void *x,const void *y)
7656{
7657 DiversityPacket
7658 *color_1,
7659 *color_2;
7660
7661 color_1=(DiversityPacket *) x;
7662 color_2=(DiversityPacket *) y;
7663 return((int) color_2->count-(int) color_1->count);
7664}
7665
7666#if defined(__cplusplus) || defined(c_plusplus)
7667}
7668#endif
7669
cristybb503372010-05-27 20:51:26 +00007670static inline Quantum ScaleXToQuantum(const size_t x,
7671 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007672{
7673 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7674}
7675
7676MagickExport void XMakeStandardColormap(Display *display,
7677 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7678 XStandardColormap *map_info,XPixelInfo *pixel)
7679{
7680 Colormap
7681 colormap;
7682
7683 ExceptionInfo
7684 *exception;
7685
7686 register IndexPacket
7687 *indexes;
7688
cristybb503372010-05-27 20:51:26 +00007689 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007690 i;
7691
7692 Status
7693 status;
7694
cristybb503372010-05-27 20:51:26 +00007695 size_t
cristy3ed852e2009-09-05 21:47:34 +00007696 number_colors,
7697 retain_colors;
7698
7699 unsigned short
7700 gray_value;
7701
7702 XColor
7703 color,
7704 *colors,
7705 *p;
7706
7707 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7708 assert(display != (Display *) NULL);
7709 assert(visual_info != (XVisualInfo *) NULL);
7710 assert(map_info != (XStandardColormap *) NULL);
7711 assert(resource_info != (XResourceInfo *) NULL);
7712 assert(pixel != (XPixelInfo *) NULL);
7713 exception=(&image->exception);
7714 if (resource_info->map_type != (char *) NULL)
7715 {
7716 /*
7717 Standard Colormap is already defined (i.e. xstdcmap).
7718 */
7719 XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7720 pixel);
7721 number_colors=(unsigned int) (map_info->base_pixel+
7722 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7723 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7724 if ((image->matte == MagickFalse) &&
7725 (resource_info->color_recovery == MagickFalse) &&
7726 resource_info->quantize_info->dither &&
7727 (number_colors < MaxColormapSize))
7728 {
7729 Image
7730 *affinity_image;
7731
7732 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00007733 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007734
7735 /*
7736 Improve image appearance with error diffusion.
7737 */
7738 affinity_image=AcquireImage((ImageInfo *) NULL);
7739 if (affinity_image == (Image *) NULL)
7740 ThrowXWindowFatalException(ResourceLimitFatalError,
7741 "UnableToDitherImage",image->filename);
7742 affinity_image->columns=number_colors;
7743 affinity_image->rows=1;
7744 /*
7745 Initialize colormap image.
7746 */
7747 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7748 1,exception);
7749 if (q != (PixelPacket *) NULL)
7750 {
cristybb503372010-05-27 20:51:26 +00007751 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007752 {
7753 q->red=(Quantum) 0;
7754 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00007755 q->red=ScaleXToQuantum((size_t) (i/
cristy3ed852e2009-09-05 21:47:34 +00007756 map_info->red_mult),map_info->red_max);
7757 q->green=(Quantum) 0;
7758 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00007759 q->green=ScaleXToQuantum((size_t) ((i/
cristy3ed852e2009-09-05 21:47:34 +00007760 map_info->green_mult) % (map_info->green_max+1)),
7761 map_info->green_max);
7762 q->blue=(Quantum) 0;
7763 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00007764 q->blue=ScaleXToQuantum((size_t) (i %
cristy3ed852e2009-09-05 21:47:34 +00007765 map_info->green_mult),map_info->blue_max);
7766 q->opacity=(Quantum) TransparentOpacity;
7767 q++;
7768 }
7769 (void) SyncAuthenticPixels(affinity_image,exception);
7770 (void) RemapImage(resource_info->quantize_info,image,
7771 affinity_image);
7772 }
7773 XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7774 pixel);
7775 (void) SetImageStorageClass(image,DirectClass);
7776 affinity_image=DestroyImage(affinity_image);
7777 }
7778 if (IsEventLogging())
7779 {
7780 (void) LogMagickEvent(X11Event,GetMagickModule(),
7781 "Standard Colormap:");
7782 (void) LogMagickEvent(X11Event,GetMagickModule(),
7783 " colormap id: 0x%lx",map_info->colormap);
7784 (void) LogMagickEvent(X11Event,GetMagickModule(),
7785 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7786 map_info->green_max,map_info->blue_max);
7787 (void) LogMagickEvent(X11Event,GetMagickModule(),
7788 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7789 map_info->green_mult,map_info->blue_mult);
7790 }
7791 return;
7792 }
7793 if ((visual_info->klass != DirectColor) &&
7794 (visual_info->klass != TrueColor))
7795 if ((image->storage_class == DirectClass) ||
7796 ((int) image->colors > visual_info->colormap_size))
7797 {
7798 QuantizeInfo
7799 quantize_info;
7800
7801 /*
7802 Image has more colors than the visual supports.
7803 */
7804 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007805 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00007806 (void) QuantizeImage(&quantize_info,image);
7807 }
7808 /*
7809 Free previous and create new colormap.
7810 */
7811 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7812 colormap=XDefaultColormap(display,visual_info->screen);
7813 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7814 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7815 visual_info->visual,visual_info->klass == DirectColor ?
7816 AllocAll : AllocNone);
7817 if (colormap == (Colormap) NULL)
7818 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7819 image->filename);
7820 /*
7821 Initialize the map and pixel info structures.
7822 */
7823 XGetMapInfo(visual_info,colormap,map_info);
7824 XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
7825 /*
7826 Allocating colors in server colormap is based on visual class.
7827 */
7828 switch (visual_info->klass)
7829 {
7830 case StaticGray:
7831 case StaticColor:
7832 {
7833 /*
7834 Define Standard Colormap for StaticGray or StaticColor visual.
7835 */
7836 number_colors=image->colors;
7837 colors=(XColor *) AcquireQuantumMemory((size_t)
7838 visual_info->colormap_size,sizeof(*colors));
7839 if (colors == (XColor *) NULL)
7840 ThrowXWindowFatalException(ResourceLimitFatalError,
7841 "UnableToCreateColormap",image->filename);
7842 p=colors;
7843 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007844 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007845 {
7846 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7847 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7848 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7849 if (visual_info->klass != StaticColor)
7850 {
7851 gray_value=(unsigned short) XPixelIntensity(&color);
7852 color.red=gray_value;
7853 color.green=gray_value;
7854 color.blue=gray_value;
7855 }
7856 status=XAllocColor(display,colormap,&color);
7857 if (status == False)
7858 {
7859 colormap=XCopyColormapAndFree(display,colormap);
7860 (void) XAllocColor(display,colormap,&color);
7861 }
7862 pixel->pixels[i]=color.pixel;
7863 *p++=color;
7864 }
7865 break;
7866 }
7867 case GrayScale:
7868 case PseudoColor:
7869 {
7870 unsigned int
7871 colormap_type;
7872
7873 /*
7874 Define Standard Colormap for GrayScale or PseudoColor visual.
7875 */
7876 number_colors=image->colors;
7877 colors=(XColor *) AcquireQuantumMemory((size_t)
7878 visual_info->colormap_size,sizeof(*colors));
7879 if (colors == (XColor *) NULL)
7880 ThrowXWindowFatalException(ResourceLimitFatalError,
7881 "UnableToCreateColormap",image->filename);
7882 /*
7883 Preallocate our GUI colors.
7884 */
7885 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7886 (void) XAllocColor(display,colormap,&pixel->background_color);
7887 (void) XAllocColor(display,colormap,&pixel->border_color);
7888 (void) XAllocColor(display,colormap,&pixel->matte_color);
7889 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7890 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7891 (void) XAllocColor(display,colormap,&pixel->depth_color);
7892 (void) XAllocColor(display,colormap,&pixel->trough_color);
7893 for (i=0; i < MaxNumberPens; i++)
7894 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7895 /*
7896 Determine if image colors will "fit" into X server colormap.
7897 */
7898 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007899 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007900 NULL,0,pixel->pixels,(unsigned int) image->colors);
7901 if (status != False)
7902 colormap_type=PrivateColormap;
7903 if (colormap_type == SharedColormap)
7904 {
cristyc57f6942010-11-12 01:47:39 +00007905 CacheView
7906 *image_view;
7907
cristy3ed852e2009-09-05 21:47:34 +00007908 DiversityPacket
7909 *diversity;
7910
7911 int
7912 y;
7913
7914 register int
7915 x;
7916
7917 unsigned short
7918 index;
7919
7920 XColor
7921 *server_colors;
7922
7923 /*
7924 Define Standard colormap for shared GrayScale or PseudoColor visual.
7925 */
7926 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7927 sizeof(*diversity));
7928 if (diversity == (DiversityPacket *) NULL)
7929 ThrowXWindowFatalException(ResourceLimitFatalError,
7930 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007931 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007932 {
7933 diversity[i].red=image->colormap[i].red;
7934 diversity[i].green=image->colormap[i].green;
7935 diversity[i].blue=image->colormap[i].blue;
7936 diversity[i].index=(unsigned short) i;
7937 diversity[i].count=0;
7938 }
cristyc57f6942010-11-12 01:47:39 +00007939 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00007940 for (y=0; y < (int) image->rows; y++)
7941 {
cristyc57f6942010-11-12 01:47:39 +00007942 register int
cristy3ed852e2009-09-05 21:47:34 +00007943 x;
7944
cristyc57f6942010-11-12 01:47:39 +00007945 register const PixelPacket
7946 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007947
cristyc57f6942010-11-12 01:47:39 +00007948 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7949 image->columns,1,exception);
7950 if (p == (const PixelPacket *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007951 break;
cristyc57f6942010-11-12 01:47:39 +00007952 indexes=GetCacheViewAuthenticIndexQueue(image_view);
7953 for (x=(int) image->columns-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00007954 diversity[(ssize_t) indexes[x]].count++;
cristy3ed852e2009-09-05 21:47:34 +00007955 }
cristyc57f6942010-11-12 01:47:39 +00007956 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00007957 /*
7958 Sort colors by decreasing intensity.
7959 */
7960 qsort((void *) diversity,image->colors,sizeof(*diversity),
7961 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00007962 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00007963 {
7964 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00007965 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00007966 }
7967 diversity[image->colors-1].count<<=4;
7968 qsort((void *) diversity,image->colors,sizeof(*diversity),
7969 PopularityCompare);
7970 /*
7971 Allocate colors.
7972 */
7973 p=colors;
7974 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007975 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007976 {
7977 index=diversity[i].index;
7978 color.red=
7979 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7980 color.green=
7981 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7982 color.blue=
7983 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7984 if (visual_info->klass != PseudoColor)
7985 {
7986 gray_value=(unsigned short) XPixelIntensity(&color);
7987 color.red=gray_value;
7988 color.green=gray_value;
7989 color.blue=gray_value;
7990 }
7991 status=XAllocColor(display,colormap,&color);
7992 if (status == False)
7993 break;
7994 pixel->pixels[index]=color.pixel;
7995 *p++=color;
7996 }
7997 /*
7998 Read X server colormap.
7999 */
8000 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8001 visual_info->colormap_size,sizeof(*server_colors));
8002 if (server_colors == (XColor *) NULL)
8003 ThrowXWindowFatalException(ResourceLimitFatalError,
8004 "UnableToCreateColormap",image->filename);
8005 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008006 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008007 (void) XQueryColors(display,colormap,server_colors,
8008 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8009 /*
8010 Select remaining colors from X server colormap.
8011 */
cristybb503372010-05-27 20:51:26 +00008012 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008013 {
8014 index=diversity[i].index;
8015 color.red=
8016 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8017 color.green=
8018 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8019 color.blue=
8020 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8021 if (visual_info->klass != PseudoColor)
8022 {
8023 gray_value=(unsigned short) XPixelIntensity(&color);
8024 color.red=gray_value;
8025 color.green=gray_value;
8026 color.blue=gray_value;
8027 }
8028 XBestPixel(display,colormap,server_colors,(unsigned int)
8029 visual_info->colormap_size,&color);
8030 pixel->pixels[index]=color.pixel;
8031 *p++=color;
8032 }
8033 if ((int) image->colors < visual_info->colormap_size)
8034 {
8035 /*
8036 Fill up colors array-- more choices for pen colors.
8037 */
8038 retain_colors=MagickMin((unsigned int)
8039 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008040 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008041 *p++=server_colors[i];
8042 number_colors+=retain_colors;
8043 }
8044 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8045 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8046 break;
8047 }
8048 /*
8049 Define Standard colormap for private GrayScale or PseudoColor visual.
8050 */
8051 if (status == False)
8052 {
8053 /*
8054 Not enough colormap entries in the colormap-- Create a new colormap.
8055 */
8056 colormap=XCreateColormap(display,
8057 XRootWindow(display,visual_info->screen),visual_info->visual,
8058 AllocNone);
8059 if (colormap == (Colormap) NULL)
8060 ThrowXWindowFatalException(ResourceLimitFatalError,
8061 "UnableToCreateColormap",image->filename);
8062 map_info->colormap=colormap;
8063 if ((int) image->colors < visual_info->colormap_size)
8064 {
8065 /*
8066 Retain colors from the default colormap to help lessens the
8067 effects of colormap flashing.
8068 */
8069 retain_colors=MagickMin((unsigned int)
8070 (visual_info->colormap_size-image->colors),256);
8071 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008072 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008073 {
cristyc57f6942010-11-12 01:47:39 +00008074 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008075 p++;
8076 }
8077 (void) XQueryColors(display,
8078 XDefaultColormap(display,visual_info->screen),
8079 colors+image->colors,(int) retain_colors);
8080 /*
8081 Transfer colors from default to private colormap.
8082 */
8083 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008084 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008085 retain_colors);
8086 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008087 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008088 {
8089 p->pixel=pixel->pixels[i];
8090 p++;
8091 }
8092 (void) XStoreColors(display,colormap,colors+image->colors,
8093 (int) retain_colors);
8094 number_colors+=retain_colors;
8095 }
8096 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008097 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008098 image->colors);
8099 }
8100 /*
8101 Store the image colormap.
8102 */
8103 p=colors;
8104 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008105 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008106 {
8107 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8108 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8109 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8110 if (visual_info->klass != PseudoColor)
8111 {
8112 gray_value=(unsigned short) XPixelIntensity(&color);
8113 color.red=gray_value;
8114 color.green=gray_value;
8115 color.blue=gray_value;
8116 }
8117 color.pixel=pixel->pixels[i];
8118 *p++=color;
8119 }
8120 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8121 break;
8122 }
8123 case TrueColor:
8124 case DirectColor:
8125 default:
8126 {
8127 MagickBooleanType
8128 linear_colormap;
8129
8130 /*
8131 Define Standard Colormap for TrueColor or DirectColor visual.
8132 */
8133 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8134 (map_info->green_max*map_info->green_mult)+
8135 (map_info->blue_max*map_info->blue_mult)+1);
8136 linear_colormap=(number_colors > 4096) ||
8137 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8138 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8139 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8140 MagickTrue : MagickFalse;
8141 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008142 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008143 /*
8144 Allocate color array.
8145 */
8146 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8147 if (colors == (XColor *) NULL)
8148 ThrowXWindowFatalException(ResourceLimitFatalError,
8149 "UnableToCreateColormap",image->filename);
8150 /*
8151 Initialize linear color ramp.
8152 */
8153 p=colors;
8154 color.flags=(char) (DoRed | DoGreen | DoBlue);
8155 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008156 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008157 {
8158 color.blue=(unsigned short) 0;
8159 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008160 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008161 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8162 color.green=color.blue;
8163 color.red=color.blue;
8164 color.pixel=XStandardPixel(map_info,&color);
8165 *p++=color;
8166 }
8167 else
cristybb503372010-05-27 20:51:26 +00008168 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008169 {
8170 color.red=(unsigned short) 0;
8171 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008172 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008173 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8174 color.green=(unsigned int) 0;
8175 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008176 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008177 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8178 map_info->green_max));
8179 color.blue=(unsigned short) 0;
8180 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008181 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008182 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8183 color.pixel=XStandardPixel(map_info,&color);
8184 *p++=color;
8185 }
8186 if ((visual_info->klass == DirectColor) &&
8187 (colormap != XDefaultColormap(display,visual_info->screen)))
8188 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8189 else
cristybb503372010-05-27 20:51:26 +00008190 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008191 (void) XAllocColor(display,colormap,&colors[i]);
8192 break;
8193 }
8194 }
8195 if ((visual_info->klass != DirectColor) &&
8196 (visual_info->klass != TrueColor))
8197 {
8198 /*
8199 Set foreground, background, border, etc. pixels.
8200 */
8201 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8202 &pixel->foreground_color);
8203 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8204 &pixel->background_color);
8205 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8206 {
8207 /*
8208 Foreground and background colors must differ.
8209 */
8210 pixel->background_color.red=(~pixel->foreground_color.red);
8211 pixel->background_color.green=
8212 (~pixel->foreground_color.green);
8213 pixel->background_color.blue=
8214 (~pixel->foreground_color.blue);
8215 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8216 &pixel->background_color);
8217 }
8218 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8219 &pixel->border_color);
8220 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8221 &pixel->matte_color);
8222 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8223 &pixel->highlight_color);
8224 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8225 &pixel->shadow_color);
8226 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8227 &pixel->depth_color);
8228 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8229 &pixel->trough_color);
8230 for (i=0; i < MaxNumberPens; i++)
8231 {
8232 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8233 &pixel->pen_colors[i]);
8234 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8235 }
cristyc57f6942010-11-12 01:47:39 +00008236 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008237 }
8238 colors=(XColor *) RelinquishMagickMemory(colors);
8239 if (IsEventLogging())
8240 {
8241 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8242 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8243 map_info->colormap);
8244 (void) LogMagickEvent(X11Event,GetMagickModule(),
8245 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8246 map_info->green_max,map_info->blue_max);
8247 (void) LogMagickEvent(X11Event,GetMagickModule(),
8248 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8249 map_info->green_mult,map_info->blue_mult);
8250 }
8251}
8252
8253/*
8254%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8255% %
8256% %
8257% %
8258% X M a k e W i n d o w %
8259% %
8260% %
8261% %
8262%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8263%
8264% XMakeWindow() creates an X11 window.
8265%
8266% The format of the XMakeWindow method is:
8267%
8268% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8269% XClassHint *class_hint,XWMHints *manager_hints,
8270% XWindowInfo *window_info)
8271%
8272% A description of each parameter follows:
8273%
8274% o display: Specifies a connection to an X server; returned from
8275% XOpenDisplay.
8276%
8277% o parent: Specifies the parent window_info.
8278%
8279% o argv: Specifies the application's argument list.
8280%
8281% o argc: Specifies the number of arguments.
8282%
8283% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8284%
8285% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8286%
8287% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8288%
8289*/
8290MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8291 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8292 XWindowInfo *window_info)
8293{
8294#define MinWindowSize 64
8295
8296 Atom
8297 atom_list[2];
8298
8299 int
8300 gravity;
8301
8302 static XTextProperty
8303 icon_name,
8304 window_name;
8305
8306 Status
8307 status;
8308
8309 XSizeHints
8310 *size_hints;
8311
8312 /*
8313 Set window info hints.
8314 */
8315 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8316 assert(display != (Display *) NULL);
8317 assert(window_info != (XWindowInfo *) NULL);
8318 size_hints=XAllocSizeHints();
8319 if (size_hints == (XSizeHints *) NULL)
8320 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008321 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008322 size_hints->x=window_info->x;
8323 size_hints->y=window_info->y;
8324 size_hints->width=(int) window_info->width;
8325 size_hints->height=(int) window_info->height;
8326 if (window_info->immutable != MagickFalse)
8327 {
8328 /*
8329 Window size cannot be changed.
8330 */
8331 size_hints->min_width=size_hints->width;
8332 size_hints->min_height=size_hints->height;
8333 size_hints->max_width=size_hints->width;
8334 size_hints->max_height=size_hints->height;
8335 size_hints->flags|=PMinSize;
8336 size_hints->flags|=PMaxSize;
8337 }
8338 else
8339 {
8340 /*
8341 Window size can be changed.
8342 */
8343 size_hints->min_width=(int) window_info->min_width;
8344 size_hints->min_height=(int) window_info->min_height;
8345 size_hints->flags|=PResizeInc;
8346 size_hints->width_inc=(int) window_info->width_inc;
8347 size_hints->height_inc=(int) window_info->height_inc;
8348#if !defined(PRE_R4_ICCCM)
8349 size_hints->flags|=PBaseSize;
8350 size_hints->base_width=size_hints->width_inc;
8351 size_hints->base_height=size_hints->height_inc;
8352#endif
8353 }
8354 gravity=NorthWestGravity;
8355 if (window_info->geometry != (char *) NULL)
8356 {
8357 char
8358 default_geometry[MaxTextExtent],
8359 geometry[MaxTextExtent];
8360
8361 int
8362 flags;
8363
8364 register char
8365 *p;
8366
8367 /*
8368 User specified geometry.
8369 */
8370 (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
8371 size_hints->width,size_hints->height);
8372 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8373 p=geometry;
8374 while (strlen(p) != 0)
8375 {
8376 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8377 p++;
8378 else
8379 (void) CopyMagickString(p,p+1,MaxTextExtent);
8380 }
8381 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8382 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8383 &size_hints->width,&size_hints->height,&gravity);
8384 if ((flags & WidthValue) && (flags & HeightValue))
8385 size_hints->flags|=USSize;
8386 if ((flags & XValue) && (flags & YValue))
8387 {
8388 size_hints->flags|=USPosition;
8389 window_info->x=size_hints->x;
8390 window_info->y=size_hints->y;
8391 }
8392 }
8393#if !defined(PRE_R4_ICCCM)
8394 size_hints->win_gravity=gravity;
8395 size_hints->flags|=PWinGravity;
8396#endif
8397 if (window_info->id == (Window) NULL)
8398 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8399 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8400 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008401 window_info->visual,(unsigned long) window_info->mask,
8402 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008403 else
8404 {
8405 MagickStatusType
8406 mask;
8407
8408 XEvent
8409 sans_event;
8410
8411 XWindowChanges
8412 window_changes;
8413
8414 /*
8415 Window already exists; change relevant attributes.
8416 */
cristyc57f6942010-11-12 01:47:39 +00008417 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8418 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008419 mask=ConfigureNotify;
8420 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8421 window_changes.x=window_info->x;
8422 window_changes.y=window_info->y;
8423 window_changes.width=(int) window_info->width;
8424 window_changes.height=(int) window_info->height;
8425 mask=(MagickStatusType) (CWWidth | CWHeight);
8426 if (window_info->flags & USPosition)
8427 mask|=CWX | CWY;
8428 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8429 mask,&window_changes);
8430 }
8431 if (window_info->id == (Window) NULL)
8432 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8433 window_info->name);
8434 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8435 if (status == False)
8436 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8437 window_info->name);
8438 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8439 if (status == False)
8440 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8441 window_info->icon_name);
8442 if (window_info->icon_geometry != (char *) NULL)
8443 {
8444 int
8445 flags,
8446 height,
8447 width;
8448
8449 /*
8450 User specified icon geometry.
8451 */
8452 size_hints->flags|=USPosition;
8453 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8454 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8455 &manager_hints->icon_y,&width,&height,&gravity);
8456 if ((flags & XValue) && (flags & YValue))
8457 manager_hints->flags|=IconPositionHint;
8458 }
8459 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8460 size_hints,manager_hints,class_hint);
8461 if (window_name.value != (void *) NULL)
8462 {
8463 (void) XFree((void *) window_name.value);
8464 window_name.value=(unsigned char *) NULL;
8465 window_name.nitems=0;
8466 }
8467 if (icon_name.value != (void *) NULL)
8468 {
8469 (void) XFree((void *) icon_name.value);
8470 icon_name.value=(unsigned char *) NULL;
8471 icon_name.nitems=0;
8472 }
8473 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8474 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8475 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8476 (void) XFree((void *) size_hints);
8477 if (window_info->shape != MagickFalse)
8478 {
8479#if defined(MAGICKCORE_HAVE_SHAPE)
8480 int
8481 error_base,
8482 event_base;
8483
8484 /*
8485 Can we apply a non-rectangular shaping mask?
8486 */
8487 error_base=0;
8488 event_base=0;
8489 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8490 window_info->shape=MagickFalse;
8491#else
8492 window_info->shape=MagickFalse;
8493#endif
8494 }
8495 if (window_info->shared_memory)
8496 {
8497#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8498 /*
8499 Can we use shared memory with this window?
8500 */
8501 if (XShmQueryExtension(display) == 0)
8502 window_info->shared_memory=MagickFalse;
8503#else
8504 window_info->shared_memory=MagickFalse;
8505#endif
8506 }
8507 window_info->image=NewImageList();
8508 window_info->destroy=MagickFalse;
8509}
8510
8511/*
8512%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8513% %
8514% %
8515% %
8516% X M a g i c k P r o g r e s s M o n i t o r %
8517% %
8518% %
8519% %
8520%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8521%
8522% XMagickProgressMonitor() displays the progress a task is making in
8523% completing a task.
8524%
8525% The format of the XMagickProgressMonitor method is:
8526%
8527% void XMagickProgressMonitor(const char *task,
8528% const MagickOffsetType quantum,const MagickSizeType span,
8529% void *client_data)
8530%
8531% A description of each parameter follows:
8532%
8533% o task: Identifies the task in progress.
8534%
8535% o quantum: Specifies the quantum position within the span which represents
8536% how much progress has been made in completing a task.
8537%
8538% o span: Specifies the span relative to completing a task.
8539%
8540% o client_data: Pointer to any client data.
8541%
8542*/
8543
8544static const char *GetLocaleMonitorMessage(const char *text)
8545{
8546 char
8547 message[MaxTextExtent],
8548 tag[MaxTextExtent];
8549
8550 const char
8551 *locale_message;
8552
8553 register char
8554 *p;
8555
8556 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8557 p=strrchr(tag,'/');
8558 if (p != (char *) NULL)
8559 *p='\0';
8560 (void) FormatMagickString(message,MaxTextExtent,"Monitor/%s",tag);
8561 locale_message=GetLocaleMessage(message);
8562 if (locale_message == message)
8563 return(text);
8564 return(locale_message);
8565}
8566
8567MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8568 const MagickOffsetType quantum,const MagickSizeType span,
8569 void *magick_unused(client_data))
8570{
8571 XWindows
8572 *windows;
8573
8574 windows=XSetWindows((XWindows *) ~0);
8575 if (windows == (XWindows *) NULL)
8576 return(MagickTrue);
8577 if (windows->info.mapped != MagickFalse)
8578 XProgressMonitorWidget(windows->display,windows,
8579 GetLocaleMonitorMessage(tag),quantum,span);
8580 return(MagickTrue);
8581}
8582
8583/*
8584%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8585% %
8586% %
8587% %
8588% X Q u e r y C o l o r D a t a b a s e %
8589% %
8590% %
8591% %
8592%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8593%
8594% XQueryColorDatabase() looks up a RGB values for a color given in the target
8595% string.
8596%
8597% The format of the XQueryColorDatabase method is:
8598%
8599% MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8600%
8601% A description of each parameter follows:
8602%
8603% o target: Specifies the color to lookup in the X color database.
8604%
8605% o color: A pointer to an PixelPacket structure. The RGB value of the target
8606% color is returned as this value.
8607%
8608*/
8609MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8610 XColor *color)
8611{
8612 Colormap
8613 colormap;
8614
8615 static Display
8616 *display = (Display *) NULL;
8617
8618 Status
8619 status;
8620
8621 XColor
8622 xcolor;
8623
8624 /*
8625 Initialize color return value.
8626 */
8627 assert(color != (XColor *) NULL);
8628 color->red=0;
8629 color->green=0;
8630 color->blue=0;
8631 color->flags=(char) (DoRed | DoGreen | DoBlue);
8632 if ((target == (char *) NULL) || (*target == '\0'))
8633 target="#ffffffffffff";
8634 /*
8635 Let the X server define the color for us.
8636 */
8637 if (display == (Display *) NULL)
8638 display=XOpenDisplay((char *) NULL);
8639 if (display == (Display *) NULL)
8640 {
8641 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8642 return(MagickFalse);
8643 }
8644 colormap=XDefaultColormap(display,XDefaultScreen(display));
8645 status=XParseColor(display,colormap,(char *) target,&xcolor);
8646 if (status == False)
8647 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8648 else
8649 {
8650 color->red=xcolor.red;
8651 color->green=xcolor.green;
8652 color->blue=xcolor.blue;
8653 color->flags=xcolor.flags;
8654 }
8655 return(status != False ? MagickTrue : MagickFalse);
8656}
8657
8658/*
8659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8660% %
8661% %
8662% %
8663% X Q u e r y P o s i t i o n %
8664% %
8665% %
8666% %
8667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8668%
8669% XQueryPosition() gets the pointer coordinates relative to a window.
8670%
8671% The format of the XQueryPosition method is:
8672%
8673% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8674%
8675% A description of each parameter follows:
8676%
8677% o display: Specifies a connection to an X server; returned from
8678% XOpenDisplay.
8679%
8680% o window: Specifies a pointer to a Window.
8681%
8682% o x: Return the x coordinate of the pointer relative to the origin of the
8683% window.
8684%
8685% o y: Return the y coordinate of the pointer relative to the origin of the
8686% window.
8687%
8688*/
8689MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8690{
8691 int
8692 x_root,
8693 y_root;
8694
8695 unsigned int
8696 mask;
8697
8698 Window
8699 root_window;
8700
8701 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8702 assert(display != (Display *) NULL);
8703 assert(window != (Window) NULL);
8704 assert(x != (int *) NULL);
8705 assert(y != (int *) NULL);
8706 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8707 x,y,&mask);
8708}
8709
8710/*
8711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8712% %
8713% %
8714% %
8715% X R e f r e s h W i n d o w %
8716% %
8717% %
8718% %
8719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8720%
8721% XRefreshWindow() refreshes an image in a X window.
8722%
8723% The format of the XRefreshWindow method is:
8724%
8725% void XRefreshWindow(Display *display,const XWindowInfo *window,
8726% const XEvent *event)
8727%
8728% A description of each parameter follows:
8729%
8730% o display: Specifies a connection to an X server; returned from
8731% XOpenDisplay.
8732%
8733% o window: Specifies a pointer to a XWindowInfo structure.
8734%
8735% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8736% the entire image is refreshed.
8737%
8738*/
8739MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8740 const XEvent *event)
8741{
8742 int
8743 x,
8744 y;
8745
8746 unsigned int
8747 height,
8748 width;
8749
8750 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8751 assert(display != (Display *) NULL);
8752 assert(window != (XWindowInfo *) NULL);
8753 if (window->ximage == (XImage *) NULL)
8754 return;
8755 if (event != (XEvent *) NULL)
8756 {
8757 /*
8758 Determine geometry from expose event.
8759 */
8760 x=event->xexpose.x;
8761 y=event->xexpose.y;
8762 width=(unsigned int) event->xexpose.width;
8763 height=(unsigned int) event->xexpose.height;
8764 }
8765 else
8766 {
8767 XEvent
8768 sans_event;
8769
8770 /*
8771 Refresh entire window; discard outstanding expose events.
8772 */
8773 x=0;
8774 y=0;
8775 width=window->width;
8776 height=window->height;
8777 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008778 if (window->matte_pixmap != (Pixmap) NULL)
8779 {
8780#if defined(MAGICKCORE_HAVE_SHAPE)
8781 if (window->shape != MagickFalse)
8782 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8783 window->matte_pixmap,ShapeSet);
8784#endif
8785 }
cristy3ed852e2009-09-05 21:47:34 +00008786 }
8787 /*
8788 Check boundary conditions.
8789 */
8790 if ((window->ximage->width-(x+window->x)) < (int) width)
8791 width=(unsigned int) (window->ximage->width-(x+window->x));
8792 if ((window->ximage->height-(y+window->y)) < (int) height)
8793 height=(unsigned int) (window->ximage->height-(y+window->y));
8794 /*
8795 Refresh image.
8796 */
8797 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008798 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008799 if (window->pixmap != (Pixmap) NULL)
8800 {
8801 if (window->depth > 1)
8802 (void) XCopyArea(display,window->pixmap,window->id,
8803 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8804 else
8805 (void) XCopyPlane(display,window->pixmap,window->id,
8806 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8807 1L);
8808 }
8809 else
8810 {
8811#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8812 if (window->shared_memory)
8813 (void) XShmPutImage(display,window->id,window->annotate_context,
8814 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8815#endif
8816 if (window->shared_memory == MagickFalse)
8817 (void) XPutImage(display,window->id,window->annotate_context,
8818 window->ximage,x+window->x,y+window->y,x,y,width,height);
8819 }
8820 if (window->matte_pixmap != (Pixmap) NULL)
8821 (void) XSetClipMask(display,window->annotate_context,None);
8822 (void) XFlush(display);
8823}
8824
8825/*
8826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8827% %
8828% %
8829% %
8830% X R e m o t e C o m m a n d %
8831% %
8832% %
8833% %
8834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8835%
8836% XRemoteCommand() forces a remote display(1) to display the specified
8837% image filename.
8838%
8839% The format of the XRemoteCommand method is:
8840%
8841% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8842% const char *filename)
8843%
8844% A description of each parameter follows:
8845%
8846% o display: Specifies a connection to an X server; returned from
8847% XOpenDisplay.
8848%
8849% o window: Specifies the name or id of an X window.
8850%
8851% o filename: the name of the image filename to display.
8852%
8853*/
8854MagickExport MagickBooleanType XRemoteCommand(Display *display,
8855 const char *window,const char *filename)
8856{
8857 Atom
8858 remote_atom;
8859
8860 Window
8861 remote_window,
8862 root_window;
8863
8864 assert(filename != (char *) NULL);
8865 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8866 if (display == (Display *) NULL)
8867 display=XOpenDisplay((char *) NULL);
8868 if (display == (Display *) NULL)
8869 {
8870 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8871 return(MagickFalse);
8872 }
8873 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8874 remote_window=(Window) NULL;
8875 root_window=XRootWindow(display,XDefaultScreen(display));
8876 if (window != (char *) NULL)
8877 {
8878 /*
8879 Search window hierarchy and identify any clients by name or ID.
8880 */
8881 if (isdigit((unsigned char) *window) != 0)
8882 remote_window=XWindowByID(display,root_window,(Window)
8883 strtol((char *) window,(char **) NULL,0));
8884 if (remote_window == (Window) NULL)
8885 remote_window=XWindowByName(display,root_window,window);
8886 }
8887 if (remote_window == (Window) NULL)
8888 remote_window=XWindowByProperty(display,root_window,remote_atom);
8889 if (remote_window == (Window) NULL)
8890 {
8891 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8892 filename);
8893 return(MagickFalse);
8894 }
8895 /*
8896 Send remote command.
8897 */
8898 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8899 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8900 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8901 (void) XSync(display,MagickFalse);
8902 return(MagickTrue);
8903}
8904
8905/*
8906%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8907% %
8908% %
8909% %
8910% X R e t a i n W i n d o w C o l o r s %
8911% %
8912% %
8913% %
8914%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8915%
8916% XRetainWindowColors() sets X11 color resources on a window. This preserves
8917% the colors associated with an image displayed on the window.
8918%
8919% The format of the XRetainWindowColors method is:
8920%
8921% void XRetainWindowColors(Display *display,const Window window)
8922%
8923% A description of each parameter follows:
8924%
8925% o display: Specifies a connection to an X server; returned from
8926% XOpenDisplay.
8927%
8928% o window: Specifies a pointer to a XWindowInfo structure.
8929%
8930*/
8931MagickExport void XRetainWindowColors(Display *display,const Window window)
8932{
8933 Atom
8934 property;
8935
8936 Pixmap
8937 pixmap;
8938
8939 /*
8940 Put property on the window.
8941 */
8942 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8943 assert(display != (Display *) NULL);
8944 assert(window != (Window) NULL);
8945 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8946 if (property == (Atom) NULL)
8947 {
8948 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8949 "_XSETROOT_ID");
8950 return;
8951 }
8952 pixmap=XCreatePixmap(display,window,1,1,1);
8953 if (pixmap == (Pixmap) NULL)
8954 {
8955 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8956 return;
8957 }
8958 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8959 (unsigned char *) &pixmap,1);
8960 (void) XSetCloseDownMode(display,RetainPermanent);
8961}
8962
8963/*
8964%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8965% %
8966% %
8967% %
8968% X S e l e c t W i n d o w %
8969% %
8970% %
8971% %
8972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8973%
8974% XSelectWindow() allows a user to select a window using the mouse. If the
8975% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
8976% is returned in the crop_info structure.
8977%
8978% The format of the XSelectWindow function is:
8979%
8980% target_window=XSelectWindow(display,crop_info)
8981%
8982% A description of each parameter follows:
8983%
8984% o window: XSelectWindow returns the window id.
8985%
8986% o display: Specifies a pointer to the Display structure; returned from
8987% XOpenDisplay.
8988%
8989% o crop_info: Specifies a pointer to a RectangleInfo structure. It
8990% contains the extents of any cropping rectangle.
8991%
cristy3ed852e2009-09-05 21:47:34 +00008992*/
8993static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
8994{
8995#define MinimumCropArea (unsigned int) 9
8996
8997 Cursor
8998 target_cursor;
8999
9000 GC
9001 annotate_context;
9002
9003 int
9004 presses,
9005 x_offset,
9006 y_offset;
9007
9008 Status
9009 status;
9010
9011 Window
9012 root_window,
9013 target_window;
9014
9015 XEvent
9016 event;
9017
9018 XGCValues
9019 context_values;
9020
9021 /*
9022 Initialize graphic context.
9023 */
9024 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9025 assert(display != (Display *) NULL);
9026 assert(crop_info != (RectangleInfo *) NULL);
9027 root_window=XRootWindow(display,XDefaultScreen(display));
9028 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9029 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9030 context_values.function=GXinvert;
9031 context_values.plane_mask=
9032 context_values.background ^ context_values.foreground;
9033 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009034 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009035 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9036 if (annotate_context == (GC) NULL)
9037 return(MagickFalse);
9038 /*
9039 Grab the pointer using target cursor.
9040 */
9041 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9042 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9043 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9044 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9045 GrabModeAsync,root_window,target_cursor,CurrentTime);
9046 if (status != GrabSuccess)
9047 {
9048 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9049 return((Window) NULL);
9050 }
9051 /*
9052 Select a window.
9053 */
9054 crop_info->width=0;
9055 crop_info->height=0;
9056 presses=0;
9057 target_window=(Window) NULL;
9058 x_offset=0;
9059 y_offset=0;
9060 do
9061 {
9062 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9063 (void) XDrawRectangle(display,root_window,annotate_context,
9064 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9065 (unsigned int) crop_info->height-1);
9066 /*
9067 Allow another event.
9068 */
9069 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9070 (void) XWindowEvent(display,root_window,ButtonPressMask |
9071 ButtonReleaseMask | ButtonMotionMask,&event);
9072 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9073 (void) XDrawRectangle(display,root_window,annotate_context,
9074 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9075 (unsigned int) crop_info->height-1);
9076 switch (event.type)
9077 {
9078 case ButtonPress:
9079 {
9080 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9081 event.xbutton.x,event.xbutton.y);
9082 if (target_window == (Window) NULL)
9083 target_window=root_window;
9084 x_offset=event.xbutton.x_root;
9085 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009086 crop_info->x=(ssize_t) x_offset;
9087 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009088 crop_info->width=0;
9089 crop_info->height=0;
9090 presses++;
9091 break;
9092 }
9093 case ButtonRelease:
9094 {
9095 presses--;
9096 break;
9097 }
9098 case MotionNotify:
9099 {
9100 /*
9101 Discard pending button motion events.
9102 */
9103 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009104 crop_info->x=(ssize_t) event.xmotion.x;
9105 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009106 /*
9107 Check boundary conditions.
9108 */
9109 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009110 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009111 else
9112 {
cristyecd0ab52010-05-30 14:59:20 +00009113 crop_info->width=(size_t) (crop_info->x-x_offset);
9114 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009115 }
9116 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009117 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009118 else
9119 {
cristyecd0ab52010-05-30 14:59:20 +00009120 crop_info->height=(size_t) (crop_info->y-y_offset);
9121 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009122 }
9123 }
9124 default:
9125 break;
9126 }
9127 } while ((target_window == (Window) NULL) || (presses > 0));
9128 (void) XUngrabPointer(display,CurrentTime);
9129 (void) XFreeCursor(display,target_cursor);
9130 (void) XFreeGC(display,annotate_context);
9131 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9132 {
9133 crop_info->width=0;
9134 crop_info->height=0;
9135 }
9136 if ((crop_info->width != 0) && (crop_info->height != 0))
9137 target_window=root_window;
9138 return(target_window);
9139}
9140
9141/*
9142%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9143% %
9144% %
9145% %
9146% X S e t C u r s o r S t a t e %
9147% %
9148% %
9149% %
9150%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9151%
9152% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9153% reset to their default.
9154%
9155% The format of the XXSetCursorState method is:
9156%
9157% XSetCursorState(display,windows,const MagickStatusType state)
9158%
9159% A description of each parameter follows:
9160%
9161% o display: Specifies a connection to an X server; returned from
9162% XOpenDisplay.
9163%
9164% o windows: Specifies a pointer to a XWindows structure.
9165%
9166% o state: An unsigned integer greater than 0 sets the cursor state
9167% to busy, otherwise the cursor are reset to their default.
9168%
9169*/
9170MagickExport void XSetCursorState(Display *display,XWindows *windows,
9171 const MagickStatusType state)
9172{
9173 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9174 assert(display != (Display *) NULL);
9175 assert(windows != (XWindows *) NULL);
9176 if (state)
9177 {
9178 (void) XCheckDefineCursor(display,windows->image.id,
9179 windows->image.busy_cursor);
9180 (void) XCheckDefineCursor(display,windows->pan.id,
9181 windows->pan.busy_cursor);
9182 (void) XCheckDefineCursor(display,windows->magnify.id,
9183 windows->magnify.busy_cursor);
9184 (void) XCheckDefineCursor(display,windows->command.id,
9185 windows->command.busy_cursor);
9186 }
9187 else
9188 {
9189 (void) XCheckDefineCursor(display,windows->image.id,
9190 windows->image.cursor);
9191 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9192 (void) XCheckDefineCursor(display,windows->magnify.id,
9193 windows->magnify.cursor);
9194 (void) XCheckDefineCursor(display,windows->command.id,
9195 windows->command.cursor);
9196 (void) XCheckDefineCursor(display,windows->command.id,
9197 windows->widget.cursor);
9198 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9199 }
9200 windows->info.mapped=MagickFalse;
9201}
9202
9203/*
9204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9205% %
9206% %
9207% %
9208% X S e t W i n d o w s %
9209% %
9210% %
9211% %
9212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9213%
9214% XSetWindows() sets the X windows structure if the windows info is specified.
9215% Otherwise the current windows structure is returned.
9216%
9217% The format of the XSetWindows method is:
9218%
9219% XWindows *XSetWindows(XWindows *windows_info)
9220%
9221% A description of each parameter follows:
9222%
9223% o windows_info: Initialize the Windows structure with this information.
9224%
9225*/
9226MagickExport XWindows *XSetWindows(XWindows *windows_info)
9227{
9228 static XWindows
9229 *windows = (XWindows *) NULL;
9230
9231 if (windows_info != (XWindows *) ~0)
9232 {
9233 windows=(XWindows *) RelinquishMagickMemory(windows);
9234 windows=windows_info;
9235 }
9236 return(windows);
9237}
9238/*
9239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9240% %
9241% %
9242% %
9243% X U s e r P r e f e r e n c e s %
9244% %
9245% %
9246% %
9247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9248%
9249% XUserPreferences() saves the preferences in a configuration file in the
9250% users' home directory.
9251%
9252% The format of the XUserPreferences method is:
9253%
9254% void XUserPreferences(XResourceInfo *resource_info)
9255%
9256% A description of each parameter follows:
9257%
9258% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9259%
9260*/
9261MagickExport void XUserPreferences(XResourceInfo *resource_info)
9262{
9263#if defined(X11_PREFERENCES_PATH)
9264 char
9265 cache[MaxTextExtent],
9266 filename[MaxTextExtent],
9267 specifier[MaxTextExtent];
9268
9269 const char
cristy104cea82009-10-25 02:26:51 +00009270 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009271 *value;
9272
9273 XrmDatabase
9274 preferences_database;
9275
9276 /*
9277 Save user preferences to the client configuration file.
9278 */
9279 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009280 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009281 preferences_database=XrmGetStringDatabase("");
cristy104cea82009-10-25 02:26:51 +00009282 (void) FormatMagickString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009283 value=resource_info->backdrop ? "True" : "False";
9284 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009285 (void) FormatMagickString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009286 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9287 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9288 (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009289 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009290 value=resource_info->confirm_exit ? "True" : "False";
9291 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9292 (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009293 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009294 value=resource_info->confirm_edit ? "True" : "False";
9295 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9296 (void) FormatMagickString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009297 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009298 value=resource_info->display_warnings ? "True" : "False";
9299 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009300 (void) FormatMagickString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009301 value=resource_info->quantize_info->dither ? "True" : "False";
9302 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9303 (void) FormatMagickString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009304 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009305 value=resource_info->gamma_correct ? "True" : "False";
9306 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009307 (void) FormatMagickString(specifier,MaxTextExtent,"%s.undoCache",client_name);
cristye8c25f92010-06-03 00:53:06 +00009308 (void) FormatMagickString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009309 resource_info->undo_cache);
9310 XrmPutStringResource(&preferences_database,specifier,cache);
cristy104cea82009-10-25 02:26:51 +00009311 (void) FormatMagickString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009312 value=resource_info->use_pixmap ? "True" : "False";
9313 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9314 (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009315 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009316 ExpandFilename(filename);
9317 XrmPutFileDatabase(preferences_database,filename);
9318#endif
9319}
9320
9321/*
9322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9323% %
9324% %
9325% %
9326% X V i s u a l C l a s s N a m e %
9327% %
9328% %
9329% %
9330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9331%
9332% XVisualClassName() returns the visual class name as a character string.
9333%
9334% The format of the XVisualClassName method is:
9335%
9336% char *XVisualClassName(const int visual_class)
9337%
9338% A description of each parameter follows:
9339%
9340% o visual_type: XVisualClassName returns the visual class as a character
9341% string.
9342%
9343% o class: Specifies the visual class.
9344%
cristy3ed852e2009-09-05 21:47:34 +00009345*/
9346static const char *XVisualClassName(const int visual_class)
9347{
9348 switch (visual_class)
9349 {
9350 case StaticGray: return("StaticGray");
9351 case GrayScale: return("GrayScale");
9352 case StaticColor: return("StaticColor");
9353 case PseudoColor: return("PseudoColor");
9354 case TrueColor: return("TrueColor");
9355 case DirectColor: return("DirectColor");
9356 }
9357 return("unknown visual class");
9358}
9359
9360/*
9361%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9362% %
9363% %
9364% %
9365% X W a r n i n g %
9366% %
9367% %
9368% %
9369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9370%
9371% XWarning() displays a warning reason in a Notice widget.
9372%
9373% The format of the XWarning method is:
9374%
9375% void XWarning(const unsigned int warning,const char *reason,
9376% const char *description)
9377%
9378% A description of each parameter follows:
9379%
9380% o warning: Specifies the numeric warning category.
9381%
9382% o reason: Specifies the reason to display before terminating the
9383% program.
9384%
9385% o description: Specifies any description to the reason.
9386%
9387*/
9388MagickExport void XWarning(const ExceptionType magick_unused(warning),
9389 const char *reason,const char *description)
9390{
9391 char
9392 text[MaxTextExtent];
9393
9394 XWindows
9395 *windows;
9396
9397 if (reason == (char *) NULL)
9398 return;
9399 (void) CopyMagickString(text,reason,MaxTextExtent);
9400 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9401 windows=XSetWindows((XWindows *) ~0);
9402 XNoticeWidget(windows->display,windows,text,(char *) description);
9403}
9404
9405/*
9406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9407% %
9408% %
9409% %
9410% X W i n d o w B y I D %
9411% %
9412% %
9413% %
9414%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9415%
9416% XWindowByID() locates a child window with a given ID. If not window with
9417% the given name is found, 0 is returned. Only the window specified and its
9418% subwindows are searched.
9419%
9420% The format of the XWindowByID function is:
9421%
9422% child=XWindowByID(display,window,id)
9423%
9424% A description of each parameter follows:
9425%
9426% o child: XWindowByID returns the window with the specified
9427% id. If no windows are found, XWindowByID returns 0.
9428%
9429% o display: Specifies a pointer to the Display structure; returned from
9430% XOpenDisplay.
9431%
9432% o id: Specifies the id of the window to locate.
9433%
9434*/
9435MagickExport Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009436 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009437{
9438 RectangleInfo
9439 rectangle_info;
9440
9441 register int
9442 i;
9443
9444 Status
9445 status;
9446
9447 unsigned int
9448 number_children;
9449
9450 Window
9451 child,
9452 *children,
9453 window;
9454
9455 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9456 assert(display != (Display *) NULL);
9457 assert(root_window != (Window) NULL);
9458 if (id == 0)
9459 return(XSelectWindow(display,&rectangle_info));
9460 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009461 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009462 status=XQueryTree(display,root_window,&child,&child,&children,
9463 &number_children);
9464 if (status == False)
9465 return((Window) NULL);
9466 window=(Window) NULL;
9467 for (i=0; i < (int) number_children; i++)
9468 {
9469 /*
9470 Search each child and their children.
9471 */
9472 window=XWindowByID(display,children[i],id);
9473 if (window != (Window) NULL)
9474 break;
9475 }
9476 if (children != (Window *) NULL)
9477 (void) XFree((void *) children);
9478 return(window);
9479}
9480
9481/*
9482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9483% %
9484% %
9485% %
9486% X W i n d o w B y N a m e %
9487% %
9488% %
9489% %
9490%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9491%
9492% XWindowByName() locates a window with a given name on a display. If no
9493% window with the given name is found, 0 is returned. If more than one window
9494% has the given name, the first one is returned. Only root and its children
9495% are searched.
9496%
9497% The format of the XWindowByName function is:
9498%
9499% window=XWindowByName(display,root_window,name)
9500%
9501% A description of each parameter follows:
9502%
9503% o window: XWindowByName returns the window id.
9504%
9505% o display: Specifies a pointer to the Display structure; returned from
9506% XOpenDisplay.
9507%
9508% o root_window: Specifies the id of the root window.
9509%
9510% o name: Specifies the name of the window to locate.
9511%
9512*/
9513MagickExport Window XWindowByName(Display *display,const Window root_window,
9514 const char *name)
9515{
9516 register int
9517 i;
9518
9519 Status
9520 status;
9521
9522 unsigned int
9523 number_children;
9524
9525 Window
9526 *children,
9527 child,
9528 window;
9529
9530 XTextProperty
9531 window_name;
9532
9533 assert(display != (Display *) NULL);
9534 assert(root_window != (Window) NULL);
9535 assert(name != (char *) NULL);
9536 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9537 if (XGetWMName(display,root_window,&window_name) != 0)
9538 if (LocaleCompare((char *) window_name.value,name) == 0)
9539 return(root_window);
9540 status=XQueryTree(display,root_window,&child,&child,&children,
9541 &number_children);
9542 if (status == False)
9543 return((Window) NULL);
9544 window=(Window) NULL;
9545 for (i=0; i < (int) number_children; i++)
9546 {
9547 /*
9548 Search each child and their children.
9549 */
9550 window=XWindowByName(display,children[i],name);
9551 if (window != (Window) NULL)
9552 break;
9553 }
9554 if (children != (Window *) NULL)
9555 (void) XFree((void *) children);
9556 return(window);
9557}
9558
9559/*
9560%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9561% %
9562% %
9563% %
9564% X W i n d o w B y P r o p e r y %
9565% %
9566% %
9567% %
9568%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9569%
9570% XWindowByProperty() locates a child window with a given property. If not
9571% window with the given name is found, 0 is returned. If more than one window
9572% has the given property, the first one is returned. Only the window
9573% specified and its subwindows are searched.
9574%
9575% The format of the XWindowByProperty function is:
9576%
9577% child=XWindowByProperty(display,window,property)
9578%
9579% A description of each parameter follows:
9580%
9581% o child: XWindowByProperty returns the window id with the specified
9582% property. If no windows are found, XWindowByProperty returns 0.
9583%
9584% o display: Specifies a pointer to the Display structure; returned from
9585% XOpenDisplay.
9586%
9587% o property: Specifies the property of the window to locate.
9588%
9589*/
9590MagickExport Window XWindowByProperty(Display *display,const Window window,
9591 const Atom property)
9592{
9593 Atom
9594 type;
9595
9596 int
9597 format;
9598
9599 Status
9600 status;
9601
9602 unsigned char
9603 *data;
9604
9605 unsigned int
9606 i,
9607 number_children;
9608
cristyf2faecf2010-05-28 19:19:36 +00009609 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009610 after,
9611 number_items;
9612
9613 Window
9614 child,
9615 *children,
9616 parent,
9617 root;
9618
9619 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9620 assert(display != (Display *) NULL);
9621 assert(window != (Window) NULL);
9622 assert(property != (Atom) NULL);
9623 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9624 if (status == False)
9625 return((Window) NULL);
9626 type=(Atom) NULL;
9627 child=(Window) NULL;
9628 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9629 {
9630 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9631 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9632 if (data != NULL)
9633 (void) XFree((void *) data);
9634 if ((status == Success) && (type != (Atom) NULL))
9635 child=children[i];
9636 }
9637 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9638 child=XWindowByProperty(display,children[i],property);
9639 if (children != (Window *) NULL)
9640 (void) XFree((void *) children);
9641 return(child);
9642}
9643#else
9644
9645/*
9646%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9647% %
9648% %
9649% %
9650% X I m p o r t I m a g e %
9651% %
9652% %
9653% %
9654%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9655%
9656% XImportImage() reads an image from an X window.
9657%
9658% The format of the XImportImage method is:
9659%
9660% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9661%
9662% A description of each parameter follows:
9663%
9664% o image_info: the image info..
9665%
9666% o ximage_info: Specifies a pointer to an XImportInfo structure.
9667%
9668*/
9669MagickExport Image *XImportImage(const ImageInfo *image_info,
9670 XImportInfo *ximage_info)
9671{
9672 assert(image_info != (const ImageInfo *) NULL);
9673 assert(image_info->signature == MagickSignature);
9674 if (image_info->debug != MagickFalse)
9675 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9676 image_info->filename);
9677 assert(ximage_info != (XImportInfo *) NULL);
9678 return((Image *) NULL);
9679}
9680#endif
9681
9682/*
9683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9684% %
9685% %
9686% %
cristy576974e2009-10-25 20:45:31 +00009687+ X C o m p o n e n t G e n e s i s %
9688% %
9689% %
9690% %
9691%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9692%
9693% XComponentGenesis() instantiates the X component.
9694%
9695% The format of the XComponentGenesis method is:
9696%
9697% MagickBooleanType XComponentGenesis(void)
9698%
9699*/
9700MagickExport MagickBooleanType XComponentGenesis(void)
9701{
9702 return(MagickTrue);
9703}
9704
9705/*
9706%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9707% %
9708% %
9709% %
cristy3ed852e2009-09-05 21:47:34 +00009710% X G e t I m p o r t I n f o %
9711% %
9712% %
9713% %
9714%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9715%
9716% XGetImportInfo() initializes the XImportInfo structure.
9717%
9718% The format of the XGetImportInfo method is:
9719%
9720% void XGetImportInfo(XImportInfo *ximage_info)
9721%
9722% A description of each parameter follows:
9723%
9724% o ximage_info: Specifies a pointer to an ImageInfo structure.
9725%
9726*/
9727MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9728{
9729 assert(ximage_info != (XImportInfo *) NULL);
9730 ximage_info->frame=MagickFalse;
9731 ximage_info->borders=MagickFalse;
9732 ximage_info->screen=MagickFalse;
9733 ximage_info->descend=MagickTrue;
9734 ximage_info->silent=MagickFalse;
9735}