blob: 3f22290eebc73fe42732dd05fa2f670ad1d4ba81 [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+ \
cristy7e9f2332011-04-22 23:12:22 +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+ \
cristy7e9f2332011-04-22 23:12:22 +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))
cristy3ed852e2009-09-05 21:47:34 +0000126
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 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001949 i;
1950
cristybb503372010-05-27 20:51:26 +00001951 size_t
cristy3ed852e2009-09-05 21:47:34 +00001952 number_pixels;
1953
cristy9d314ff2011-03-09 01:30:28 +00001954 ssize_t
1955 bytes;
1956
1957 unsigned int
1958 levels;
1959
cristy3ed852e2009-09-05 21:47:34 +00001960 /*
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)
cristyaafc1922011-03-04 16:59:40 +00002762 {
2763 (void) XFreeFont(display,font_info);
2764 font_info=(XFontStruct *) NULL;
2765 }
cristy3ed852e2009-09-05 21:47:34 +00002766 if (map_info != (XStandardColormap *) NULL)
2767 {
2768 /*
2769 Free X Standard Colormap.
2770 */
2771 if (resource_info->map_type == (char *) NULL)
2772 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2773 (void) XFree((void *) map_info);
2774 }
2775 /*
2776 Free X visual info.
2777 */
2778 if (visual_info != (XVisualInfo *) NULL)
2779 (void) XFree((void *) visual_info);
2780 if (resource_info->close_server != MagickFalse)
2781 (void) XCloseDisplay(display);
2782}
2783
2784/*
2785%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2786% %
2787% %
2788% %
2789% X F r e e S t a n d a r d C o l o r m a p %
2790% %
2791% %
2792% %
2793%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2794%
2795% XFreeStandardColormap() frees an X11 colormap.
2796%
2797% The format of the XFreeStandardColormap method is:
2798%
2799% void XFreeStandardColormap(Display *display,
2800% const XVisualInfo *visual_info,XStandardColormap *map_info,
2801% XPixelInfo *pixel)
2802%
2803% A description of each parameter follows:
2804%
2805% o display: Specifies a connection to an X server; returned from
2806% XOpenDisplay.
2807%
2808% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2809% returned from XGetVisualInfo.
2810%
2811% o map_info: If map_type is specified, this structure is initialized
2812% with info from the Standard Colormap.
2813%
2814% o pixel: Specifies a pointer to a XPixelInfo structure.
2815%
2816*/
2817MagickExport void XFreeStandardColormap(Display *display,
2818 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2819{
2820 /*
2821 Free colormap.
2822 */
2823 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2824 assert(display != (Display *) NULL);
2825 assert(visual_info != (XVisualInfo *) NULL);
2826 assert(map_info != (XStandardColormap *) NULL);
2827 (void) XFlush(display);
2828 if (map_info->colormap != (Colormap) NULL)
2829 {
2830 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2831 (void) XFreeColormap(display,map_info->colormap);
2832 else
2833 if (pixel != (XPixelInfo *) NULL)
2834 if ((visual_info->klass != TrueColor) &&
2835 (visual_info->klass != DirectColor))
2836 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2837 (int) pixel->colors,0);
2838 }
2839 map_info->colormap=(Colormap) NULL;
2840 if (pixel != (XPixelInfo *) NULL)
2841 {
cristyf2faecf2010-05-28 19:19:36 +00002842 if (pixel->pixels != (unsigned long *) NULL)
2843 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2844 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002845 }
2846}
2847
2848/*
2849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2850% %
2851% %
2852% %
2853% X G e t A n n o t a t e I n f o %
2854% %
2855% %
2856% %
2857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2858%
2859% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2860%
2861% The format of the XGetAnnotateInfo method is:
2862%
2863% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2864%
2865% A description of each parameter follows:
2866%
2867% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2868%
2869*/
2870MagickExport void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2871{
2872 /*
2873 Initialize annotate structure.
2874 */
2875 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2876 assert(annotate_info != (XAnnotateInfo *) NULL);
2877 annotate_info->x=0;
2878 annotate_info->y=0;
2879 annotate_info->width=0;
2880 annotate_info->height=0;
2881 annotate_info->stencil=ForegroundStencil;
2882 annotate_info->degrees=0.0;
2883 annotate_info->font_info=(XFontStruct *) NULL;
2884 annotate_info->text=(char *) NULL;
2885 *annotate_info->geometry='\0';
2886 annotate_info->previous=(XAnnotateInfo *) NULL;
2887 annotate_info->next=(XAnnotateInfo *) NULL;
2888 (void) XSupportsLocale();
2889 (void) XSetLocaleModifiers("");
2890}
2891
2892/*
2893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2894% %
2895% %
2896% %
2897% X G e t M a p I n f o %
2898% %
2899% %
2900% %
2901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2902%
2903% XGetMapInfo() initializes the XStandardColormap structure.
2904%
2905% The format of the XStandardColormap method is:
2906%
2907% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2908% XStandardColormap *map_info)
2909%
2910% A description of each parameter follows:
2911%
2912% o colormap: Specifies the ID of the X server colormap.
2913%
2914% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2915% returned from XGetVisualInfo.
2916%
2917% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2918%
2919*/
2920MagickExport void XGetMapInfo(const XVisualInfo *visual_info,
2921 const Colormap colormap,XStandardColormap *map_info)
2922{
2923 /*
2924 Initialize map info.
2925 */
2926 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2927 assert(visual_info != (XVisualInfo *) NULL);
2928 assert(map_info != (XStandardColormap *) NULL);
2929 map_info->colormap=colormap;
2930 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002931 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002932 if (map_info->red_max != 0)
2933 while ((map_info->red_max & 0x01) == 0)
2934 {
2935 map_info->red_max>>=1;
2936 map_info->red_mult<<=1;
2937 }
2938 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002939 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002940 if (map_info->green_max != 0)
2941 while ((map_info->green_max & 0x01) == 0)
2942 {
2943 map_info->green_max>>=1;
2944 map_info->green_mult<<=1;
2945 }
2946 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002947 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002948 if (map_info->blue_max != 0)
2949 while ((map_info->blue_max & 0x01) == 0)
2950 {
2951 map_info->blue_max>>=1;
2952 map_info->blue_mult<<=1;
2953 }
2954 map_info->base_pixel=0;
2955}
2956
2957/*
2958%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2959% %
2960% %
2961% %
2962% X G e t P i x e l I n f o %
2963% %
2964% %
2965% %
2966%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2967%
2968% XGetPixelPacket() initializes the PixelPacket structure.
2969%
2970% The format of the XGetPixelPacket method is:
2971%
2972% void XGetPixelPacket(Display *display,const XVisualInfo *visual_info,
2973% const XStandardColormap *map_info,const XResourceInfo *resource_info,
2974% Image *image,XPixelInfo *pixel)
2975% pixel)
2976%
2977% A description of each parameter follows:
2978%
2979% o display: Specifies a connection to an X server; returned from
2980% XOpenDisplay.
2981%
2982% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2983% returned from XGetVisualInfo.
2984%
2985% o map_info: If map_type is specified, this structure is initialized
2986% with info from the Standard Colormap.
2987%
2988% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2989%
2990% o image: the image.
2991%
2992% o pixel: Specifies a pointer to a XPixelInfo structure.
2993%
2994*/
2995MagickExport void XGetPixelPacket(Display *display,
2996 const XVisualInfo *visual_info,const XStandardColormap *map_info,
2997 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
2998{
2999 static const char
3000 *PenColors[MaxNumberPens]=
3001 {
3002 "#000000000000", /* black */
3003 "#00000000ffff", /* blue */
3004 "#0000ffffffff", /* cyan */
3005 "#0000ffff0000", /* green */
3006 "#bdbdbdbdbdbd", /* gray */
3007 "#ffff00000000", /* red */
3008 "#ffff0000ffff", /* magenta */
3009 "#ffffffff0000", /* yellow */
3010 "#ffffffffffff", /* white */
3011 "#bdbdbdbdbdbd", /* gray */
3012 "#bdbdbdbdbdbd" /* gray */
3013 };
3014
3015 Colormap
3016 colormap;
3017
cristybb503372010-05-27 20:51:26 +00003018 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003019 i;
3020
3021 Status
3022 status;
3023
3024 unsigned int
3025 packets;
3026
3027 /*
3028 Initialize pixel info.
3029 */
3030 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3031 assert(display != (Display *) NULL);
3032 assert(visual_info != (XVisualInfo *) NULL);
3033 assert(map_info != (XStandardColormap *) NULL);
3034 assert(resource_info != (XResourceInfo *) NULL);
3035 assert(pixel != (XPixelInfo *) NULL);
3036 pixel->colors=0;
3037 if (image != (Image *) NULL)
3038 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003039 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003040 packets=(unsigned int)
3041 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003042 if (pixel->pixels != (unsigned long *) NULL)
3043 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3044 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003045 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003046 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003047 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3048 image->filename);
3049 /*
3050 Set foreground color.
3051 */
3052 colormap=map_info->colormap;
3053 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3054 &pixel->foreground_color);
3055 status=XParseColor(display,colormap,resource_info->foreground_color,
3056 &pixel->foreground_color);
3057 if (status == False)
3058 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3059 resource_info->foreground_color);
3060 pixel->foreground_color.pixel=
3061 XStandardPixel(map_info,&pixel->foreground_color);
3062 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3063 /*
3064 Set background color.
3065 */
3066 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3067 status=XParseColor(display,colormap,resource_info->background_color,
3068 &pixel->background_color);
3069 if (status == False)
3070 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3071 resource_info->background_color);
3072 pixel->background_color.pixel=
3073 XStandardPixel(map_info,&pixel->background_color);
3074 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3075 /*
3076 Set border color.
3077 */
3078 (void) XParseColor(display,colormap,(char *) BorderColor,
3079 &pixel->border_color);
3080 status=XParseColor(display,colormap,resource_info->border_color,
3081 &pixel->border_color);
3082 if (status == False)
3083 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3084 resource_info->border_color);
3085 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3086 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3087 /*
3088 Set matte color.
3089 */
3090 pixel->matte_color=pixel->background_color;
3091 if (resource_info->matte_color != (char *) NULL)
3092 {
3093 /*
3094 Matte color is specified as a X resource or command line argument.
3095 */
3096 status=XParseColor(display,colormap,resource_info->matte_color,
3097 &pixel->matte_color);
3098 if (status == False)
3099 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3100 resource_info->matte_color);
3101 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3102 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3103 }
3104 /*
3105 Set highlight color.
3106 */
3107 pixel->highlight_color.red=(unsigned short) ((
3108 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3109 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3110 pixel->highlight_color.green=(unsigned short) ((
3111 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3112 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3113 pixel->highlight_color.blue=(unsigned short) ((
3114 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3115 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3116 pixel->highlight_color.pixel=
3117 XStandardPixel(map_info,&pixel->highlight_color);
3118 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3119 /*
3120 Set shadow color.
3121 */
3122 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3123 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3124 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3125 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3126 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3127 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3128 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3129 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3130 /*
3131 Set depth color.
3132 */
3133 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3134 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3135 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3136 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3137 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3138 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3139 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3140 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3141 /*
3142 Set trough color.
3143 */
3144 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3145 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3146 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3147 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3148 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3149 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3150 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3151 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3152 /*
3153 Set pen color.
3154 */
3155 for (i=0; i < MaxNumberPens; i++)
3156 {
3157 (void) XParseColor(display,colormap,(char *) PenColors[i],
3158 &pixel->pen_colors[i]);
3159 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3160 &pixel->pen_colors[i]);
3161 if (status == False)
3162 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3163 resource_info->pen_colors[i]);
3164 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3165 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3166 }
3167 pixel->box_color=pixel->background_color;
3168 pixel->pen_color=pixel->foreground_color;
3169 pixel->box_index=0;
3170 pixel->pen_index=1;
3171 if (image != (Image *) NULL)
3172 {
3173 if ((resource_info->gamma_correct != MagickFalse) &&
3174 (image->gamma != 0.0))
3175 {
3176 GeometryInfo
3177 geometry_info;
3178
3179 MagickStatusType
3180 flags;
3181
3182 /*
3183 Initialize map relative to display and image gamma.
3184 */
3185 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3186 red_gamma=geometry_info.rho;
3187 green_gamma=geometry_info.sigma;
3188 if ((flags & SigmaValue) == 0)
3189 green_gamma=red_gamma;
3190 blue_gamma=geometry_info.xi;
3191 if ((flags & XiValue) == 0)
3192 blue_gamma=red_gamma;
3193 red_gamma*=image->gamma;
3194 green_gamma*=image->gamma;
3195 blue_gamma*=image->gamma;
3196 }
3197 if (image->storage_class == PseudoClass)
3198 {
3199 /*
3200 Initialize pixel array for images of type PseudoClass.
3201 */
cristybb503372010-05-27 20:51:26 +00003202 for (i=0; i < (ssize_t) image->colors; i++)
cristy7e9f2332011-04-22 23:12:22 +00003203 pixel->pixels[i]=XGammaPixel(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003204 for (i=0; i < MaxNumberPens; i++)
3205 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3206 pixel->colors+=MaxNumberPens;
3207 }
3208 }
3209}
3210
3211/*
3212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3213% %
3214% %
3215% %
3216% X G e t R e s o u r c e C l a s s %
3217% %
3218% %
3219% %
3220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3221%
3222% XGetResourceClass() queries the X server for the specified resource name or
3223% class. If the resource name or class is not defined in the database, the
3224% supplied default value is returned.
3225%
3226% The format of the XGetResourceClass method is:
3227%
3228% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3229% const char *keyword,char *resource_default)
3230%
3231% A description of each parameter follows:
3232%
3233% o database: Specifies a resource database; returned from
3234% XrmGetStringDatabase.
3235%
3236% o client_name: Specifies the application name used to retrieve resource
3237% info from the X server database.
3238%
3239% o keyword: Specifies the keyword of the value being retrieved.
3240%
3241% o resource_default: Specifies the default value to return if the query
3242% fails to find the specified keyword/class.
3243%
3244*/
3245MagickExport char *XGetResourceClass(XrmDatabase database,
3246 const char *client_name,const char *keyword,char *resource_default)
3247{
3248 char
3249 resource_class[MaxTextExtent],
3250 resource_name[MaxTextExtent];
3251
3252 static char
3253 *resource_type;
3254
3255 Status
3256 status;
3257
3258 XrmValue
3259 resource_value;
3260
3261 if (database == (XrmDatabase) NULL)
3262 return(resource_default);
3263 *resource_name='\0';
3264 *resource_class='\0';
3265 if (keyword != (char *) NULL)
3266 {
3267 int
3268 c,
3269 k;
3270
3271 /*
3272 Initialize resource keyword and class.
3273 */
3274 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",
3275 client_name,keyword);
3276 c=(int) (*client_name);
3277 if ((c >= XK_a) && (c <= XK_z))
3278 c-=(XK_a-XK_A);
3279 else
3280 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3281 c-=(XK_agrave-XK_Agrave);
3282 else
3283 if ((c >= XK_oslash) && (c <= XK_thorn))
3284 c-=(XK_oslash-XK_Ooblique);
3285 k=(int) (*keyword);
3286 if ((k >= XK_a) && (k <= XK_z))
3287 k-=(XK_a-XK_A);
3288 else
3289 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3290 k-=(XK_agrave-XK_Agrave);
3291 else
3292 if ((k >= XK_oslash) && (k <= XK_thorn))
3293 k-=(XK_oslash-XK_Ooblique);
3294 (void) FormatMagickString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
3295 client_name+1,k,keyword+1);
3296 }
3297 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3298 &resource_value);
3299 if (status == False)
3300 return(resource_default);
3301 return(resource_value.addr);
3302}
3303
3304/*
3305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3306% %
3307% %
3308% %
3309% X G e t R e s o u r c e D a t a b a s e %
3310% %
3311% %
3312% %
3313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3314%
3315% XGetResourceDatabase() creates a new resource database and initializes it.
3316%
3317% The format of the XGetResourceDatabase method is:
3318%
3319% XrmDatabase XGetResourceDatabase(Display *display,
3320% const char *client_name)
3321%
3322% A description of each parameter follows:
3323%
3324% o database: XGetResourceDatabase() returns the database after it is
3325% initialized.
3326%
3327% o display: Specifies a connection to an X server; returned from
3328% XOpenDisplay.
3329%
3330% o client_name: Specifies the application name used to retrieve resource
3331% info from the X server database.
3332%
3333*/
3334MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3335 const char *client_name)
3336{
3337 char
3338 filename[MaxTextExtent];
3339
3340 int
3341 c;
3342
3343 register const char
3344 *p;
3345
3346 XrmDatabase
3347 resource_database,
3348 server_database;
3349
3350 if (display == (Display *) NULL)
3351 return((XrmDatabase) NULL);
3352 assert(client_name != (char *) NULL);
3353 /*
3354 Initialize resource database.
3355 */
3356 XrmInitialize();
3357 (void) XGetDefault(display,(char *) client_name,"dummy");
3358 resource_database=XrmGetDatabase(display);
3359 /*
3360 Combine application database.
3361 */
3362 if (client_name != (char *) NULL)
3363 {
3364 /*
3365 Get basename of client.
3366 */
3367 p=client_name+(strlen(client_name)-1);
3368 while ((p > client_name) && (*p != '/'))
3369 p--;
3370 if (*p == '/')
3371 client_name=p+1;
3372 }
3373 c=(int) (*client_name);
3374 if ((c >= XK_a) && (c <= XK_z))
3375 c-=(XK_a-XK_A);
3376 else
3377 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3378 c-=(XK_agrave-XK_Agrave);
3379 else
3380 if ((c >= XK_oslash) && (c <= XK_thorn))
3381 c-=(XK_oslash-XK_Ooblique);
3382#if defined(X11_APPLICATION_PATH)
3383 (void) FormatMagickString(filename,MaxTextExtent,"%s%c%s",
3384 X11_APPLICATION_PATH,c,client_name+1);
3385 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3386#endif
3387 if (XResourceManagerString(display) != (char *) NULL)
3388 {
3389 /*
3390 Combine server database.
3391 */
3392 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3393 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3394 }
3395 /*
3396 Merge user preferences database.
3397 */
3398#if defined(X11_PREFERENCES_PATH)
3399 (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
3400 X11_PREFERENCES_PATH,client_name);
3401 ExpandFilename(filename);
3402 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3403#endif
3404 return(resource_database);
3405}
3406
3407/*
3408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3409% %
3410% %
3411% %
3412% X G e t R e s o u r c e I n f o %
3413% %
3414% %
3415% %
3416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3417%
3418% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3419%
3420% The format of the XGetResourceInfo method is:
3421%
3422% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3423% const char *client_name,XResourceInfo *resource_info)
3424%
3425% A description of each parameter follows:
3426%
3427% o image_info: the image info.
3428%
3429% o database: Specifies a resource database; returned from
3430% XrmGetStringDatabase.
3431%
3432% o client_name: Specifies the application name used to retrieve
3433% resource info from the X server database.
3434%
3435% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3436%
3437*/
3438MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3439 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3440{
3441 char
cristy00976d82011-02-20 20:31:28 +00003442 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003443 *resource_value;
3444
3445 /*
3446 Initialize resource info fields.
3447 */
3448 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3449 assert(resource_info != (XResourceInfo *) NULL);
3450 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3451 resource_info->resource_database=database;
3452 resource_info->image_info=(ImageInfo *) image_info;
3453 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3454 XMagickProgressMonitor,(void *) NULL);
3455 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3456 resource_info->close_server=MagickTrue;
3457 resource_info->client_name=AcquireString(client_name);
3458 resource_value=XGetResourceClass(database,client_name,"backdrop",
3459 (char *) "False");
3460 resource_info->backdrop=IsMagickTrue(resource_value);
3461 resource_info->background_color=XGetResourceInstance(database,client_name,
3462 "background",(char *) "#d6d6d6d6d6d6");
3463 resource_info->border_color=XGetResourceInstance(database,client_name,
3464 "borderColor",BorderColor);
3465 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3466 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003467 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3468 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003469 resource_value=XGetResourceClass(database,client_name,"colormap",
3470 (char *) "shared");
3471 resource_info->colormap=UndefinedColormap;
3472 if (LocaleCompare("private",resource_value) == 0)
3473 resource_info->colormap=PrivateColormap;
3474 if (LocaleCompare("shared",resource_value) == 0)
3475 resource_info->colormap=SharedColormap;
3476 if (resource_info->colormap == UndefinedColormap)
3477 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3478 resource_value);
3479 resource_value=XGetResourceClass(database,client_name,
3480 "colorRecovery",(char *) "False");
3481 resource_info->color_recovery=IsMagickTrue(resource_value);
3482 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3483 (char *) "False");
3484 resource_info->confirm_exit=IsMagickTrue(resource_value);
3485 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3486 (char *) "False");
3487 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003488 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003489 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003490 resource_info->display_gamma=XGetResourceClass(database,client_name,
3491 "displayGamma",(char *) "2.2");
3492 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3493 (char *) "True");
3494 resource_info->display_warnings=IsMagickTrue(resource_value);
3495 resource_info->font=XGetResourceClass(database,client_name,"font",
3496 (char *) NULL);
3497 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3498 resource_info->font);
3499 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3500 (char *) "fixed");
3501 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3502 (char *) "variable");
3503 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3504 (char *) "5x8");
3505 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3506 (char *) "6x10");
3507 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3508 (char *) "7x13bold");
3509 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3510 (char *) "8x13bold");
3511 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3512 (char *) "9x15bold");
3513 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3514 (char *) "10x20");
3515 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3516 (char *) "12x24");
3517 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3518 (char *) "fixed");
3519 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3520 (char *) "fixed");
3521 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3522 "foreground",ForegroundColor);
3523 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3524 (char *) "True");
3525 resource_info->gamma_correct=IsMagickTrue(resource_value);
3526 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3527 client_name,"geometry",(char *) NULL));
3528 resource_value=XGetResourceClass(database,client_name,"gravity",
3529 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003530 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003531 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003532 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3533 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003534 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3535 "iconGeometry",(char *) NULL);
3536 resource_value=XGetResourceClass(database,client_name,"iconic",
3537 (char *) "False");
3538 resource_info->iconic=IsMagickTrue(resource_value);
3539 resource_value=XGetResourceClass(database,client_name,"immutable",
3540 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3541 (char *) "False");
3542 resource_info->immutable=IsMagickTrue(resource_value);
3543 resource_value=XGetResourceClass(database,client_name,"magnify",
3544 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003545 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003546 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3547 (char *) NULL);
3548 resource_info->matte_color=XGetResourceInstance(database,client_name,
3549 "mattecolor",(char *) NULL);
3550 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3551 "name",(char *) NULL));
3552 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3553 (char *) "black");
3554 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3555 (char *) "blue");
3556 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3557 (char *) "cyan");
3558 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3559 (char *) "green");
3560 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3561 (char *) "gray");
3562 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3563 (char *) "red");
3564 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3565 (char *) "magenta");
3566 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3567 (char *) "yellow");
3568 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3569 (char *) "white");
3570 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3571 (char *) "gray");
3572 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3573 (char *) "gray");
3574 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003575 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003576 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003577 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003578 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3579 "font",(char *) "fixed");
3580 resource_info->text_font=XGetResourceClass(database,client_name,
3581 "textFontList",resource_info->text_font);
3582 resource_info->title=XGetResourceClass(database,client_name,"title",
3583 (char *) NULL);
3584 resource_value=XGetResourceClass(database,client_name,"undoCache",
3585 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003586 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003587 resource_value=XGetResourceClass(database,client_name,"update",
3588 (char *) "False");
3589 resource_info->update=IsMagickTrue(resource_value);
3590 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3591 (char *) "True");
3592 resource_info->use_pixmap=IsMagickTrue(resource_value);
3593 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3594 (char *) "True");
3595 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3596 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3597 (char *) NULL);
3598 resource_info->window_group=XGetResourceClass(database,client_name,
3599 "windowGroup",(char *) NULL);
3600 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3601 (char *) NULL);
3602 resource_info->write_filename=XGetResourceClass(database,client_name,
3603 "writeFilename",(char *) NULL);
3604}
3605
3606/*
3607%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3608% %
3609% %
3610% %
3611% X G e t R e s o u r c e I n s t a n c e %
3612% %
3613% %
3614% %
3615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3616%
3617% XGetResourceInstance() queries the X server for the specified resource name.
3618% If the resource name is not defined in the database, the supplied default
3619% value is returned.
3620%
3621% The format of the XGetResourceInstance method is:
3622%
3623% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3624% const char *keyword,const char *resource_default)
3625%
3626% A description of each parameter follows:
3627%
3628% o database: Specifies a resource database; returned from
3629% XrmGetStringDatabase.
3630%
3631% o client_name: Specifies the application name used to retrieve
3632% resource info from the X server database.
3633%
3634% o keyword: Specifies the keyword of the value being retrieved.
3635%
3636% o resource_default: Specifies the default value to return if the query
3637% fails to find the specified keyword/class.
3638%
3639*/
3640MagickExport char *XGetResourceInstance(XrmDatabase database,
3641 const char *client_name,const char *keyword,const char *resource_default)
3642{
3643 char
3644 *resource_type,
3645 resource_name[MaxTextExtent];
3646
3647 Status
3648 status;
3649
3650 XrmValue
3651 resource_value;
3652
3653 if (database == (XrmDatabase) NULL)
3654 return((char *) resource_default);
3655 *resource_name='\0';
3656 if (keyword != (char *) NULL)
3657 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",client_name,
3658 keyword);
3659 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3660 &resource_value);
3661 if (status == False)
3662 return((char *) resource_default);
3663 return(resource_value.addr);
3664}
3665
3666/*
3667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3668% %
3669% %
3670% %
3671% X G e t S c r e e n D e n s i t y %
3672% %
3673% %
3674% %
3675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3676%
3677% XGetScreenDensity() returns the density of the X server screen in
3678% dots-per-inch.
3679%
3680% The format of the XGetScreenDensity method is:
3681%
3682% char *XGetScreenDensity(Display *display)
3683%
3684% A description of each parameter follows:
3685%
3686% o density: XGetScreenDensity() returns the density of the X screen in
3687% dots-per-inch.
3688%
3689% o display: Specifies a connection to an X server; returned from
3690% XOpenDisplay.
3691%
3692*/
3693MagickExport char *XGetScreenDensity(Display *display)
3694{
3695 char
3696 density[MaxTextExtent];
3697
3698 double
3699 x_density,
3700 y_density;
3701
3702 /*
3703 Set density as determined by screen size.
3704 */
3705 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3706 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3707 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3708 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristye7f51092010-01-17 00:39:37 +00003709 (void) FormatMagickString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003710 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003711 return(GetPageGeometry(density));
3712}
3713
3714/*
3715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3716% %
3717% %
3718% %
3719+ X G e t S u b w i n d o w %
3720% %
3721% %
3722% %
3723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3724%
3725% XGetSubwindow() returns the subwindow of a window chosen the user with the
3726% pointer and a button press.
3727%
3728% The format of the XGetSubwindow method is:
3729%
3730% Window XGetSubwindow(Display *display,Window window,int x,int y)
3731%
3732% A description of each parameter follows:
3733%
3734% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3735% otherwise the subwindow is returned.
3736%
3737% o display: Specifies a connection to an X server; returned from
3738% XOpenDisplay.
3739%
3740% o window: Specifies a pointer to a Window.
3741%
3742% o x: the x coordinate of the pointer relative to the origin of the
3743% window.
3744%
3745% o y: the y coordinate of the pointer relative to the origin of the
3746% window.
3747%
cristy3ed852e2009-09-05 21:47:34 +00003748*/
3749static Window XGetSubwindow(Display *display,Window window,int x,int y)
3750{
3751 int
3752 x_offset,
3753 y_offset;
3754
3755 Status
3756 status;
3757
3758 Window
3759 source_window,
3760 target_window;
3761
3762 assert(display != (Display *) NULL);
3763 source_window=XRootWindow(display,XDefaultScreen(display));
3764 if (window == (Window) NULL)
3765 return(source_window);
3766 target_window=window;
3767 for ( ; ; )
3768 {
3769 status=XTranslateCoordinates(display,source_window,window,x,y,
3770 &x_offset,&y_offset,&target_window);
3771 if (status != True)
3772 break;
3773 if (target_window == (Window) NULL)
3774 break;
3775 source_window=window;
3776 window=target_window;
3777 x=x_offset;
3778 y=y_offset;
3779 }
3780 if (target_window == (Window) NULL)
3781 target_window=window;
3782 return(target_window);
3783}
3784
3785/*
3786%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3787% %
3788% %
3789% %
3790% X G e t W i n d o w C o l o r %
3791% %
3792% %
3793% %
3794%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3795%
3796% XGetWindowColor() returns the color of a pixel interactively chosen from the
3797% X server.
3798%
3799% The format of the XGetWindowColor method is:
3800%
3801% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3802% char *name)
3803%
3804% A description of each parameter follows:
3805%
3806% o display: Specifies a connection to an X server; returned from
3807% XOpenDisplay.
3808%
3809% o windows: Specifies a pointer to a XWindows structure.
3810%
3811% o name: the name of the color if found in the X Color Database is
3812% returned in this character string.
3813%
3814*/
3815MagickExport MagickBooleanType XGetWindowColor(Display *display,
3816 XWindows *windows,char *name)
3817{
3818 int
3819 x,
3820 y;
3821
3822 PixelPacket
3823 pixel;
3824
3825 RectangleInfo
3826 crop_info;
3827
3828 Status
3829 status;
3830
3831 Window
3832 child,
3833 client_window,
3834 root_window,
3835 target_window;
3836
3837 XColor
3838 color;
3839
3840 XImage
3841 *ximage;
3842
3843 XWindowAttributes
3844 window_attributes;
3845
3846 /*
3847 Choose a pixel from the X server.
3848 */
3849 assert(display != (Display *) NULL);
3850 assert(name != (char *) NULL);
3851 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3852 *name='\0';
3853 target_window=XSelectWindow(display,&crop_info);
3854 if (target_window == (Window) NULL)
3855 return(MagickFalse);
3856 root_window=XRootWindow(display,XDefaultScreen(display));
3857 client_window=target_window;
3858 if (target_window != root_window)
3859 {
3860 unsigned int
3861 d;
3862
3863 /*
3864 Get client window.
3865 */
3866 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3867 if (status != False)
3868 {
3869 client_window=XClientWindow(display,target_window);
3870 target_window=client_window;
3871 }
3872 }
3873 /*
3874 Verify window is viewable.
3875 */
3876 status=XGetWindowAttributes(display,target_window,&window_attributes);
3877 if ((status == False) || (window_attributes.map_state != IsViewable))
3878 return(MagickFalse);
3879 /*
3880 Get window X image.
3881 */
3882 (void) XTranslateCoordinates(display,root_window,target_window,
3883 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3884 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3885 if (ximage == (XImage *) NULL)
3886 return(MagickFalse);
3887 color.pixel=XGetPixel(ximage,0,0);
3888 XDestroyImage(ximage);
3889 /*
3890 Match color against the color database.
3891 */
3892 (void) XQueryColor(display,window_attributes.colormap,&color);
3893 pixel.red=ScaleShortToQuantum(color.red);
3894 pixel.green=ScaleShortToQuantum(color.green);
3895 pixel.blue=ScaleShortToQuantum(color.blue);
3896 pixel.opacity=OpaqueOpacity;
3897 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3898 &windows->image.image->exception);
3899 return(MagickTrue);
3900}
3901
3902/*
3903%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3904% %
3905% %
3906% %
3907+ X G e t W i n d o w I m a g e %
3908% %
3909% %
3910% %
3911%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3912%
3913% XGetWindowImage() reads an image from the target X window and returns it.
3914% XGetWindowImage() optionally descends the window hierarchy and overlays the
3915% target image with each child image in an optimized fashion. Any child
3916% window that have the same visual, colormap, and are contained by its parent
3917% are exempted.
3918%
3919% The format of the XGetWindowImage method is:
3920%
3921% Image *XGetWindowImage(Display *display,const Window window,
3922% const unsigned int borders,const unsigned int level)
3923%
3924% A description of each parameter follows:
3925%
3926% o display: Specifies a connection to an X server; returned from
3927% XOpenDisplay.
3928%
3929% o window: Specifies the window to obtain the image from.
3930%
3931% o borders: Specifies whether borders pixels are to be saved with
3932% the image.
3933%
3934% o level: Specifies an unsigned integer representing the level of
3935% decent in the window hierarchy. This value must be zero or one on
3936% the initial call to XGetWindowImage. A value of zero returns after
3937% one call. A value of one causes the function to descend the window
3938% hierarchy and overlay the target image with each subwindow image.
3939%
cristy3ed852e2009-09-05 21:47:34 +00003940*/
3941static Image *XGetWindowImage(Display *display,const Window window,
3942 const unsigned int borders,const unsigned int level)
3943{
3944 typedef struct _ColormapInfo
3945 {
3946 Colormap
3947 colormap;
3948
3949 XColor
3950 *colors;
3951
3952 struct _ColormapInfo
3953 *next;
3954 } ColormapInfo;
3955
3956 typedef struct _WindowInfo
3957 {
3958 Window
3959 window,
3960 parent;
3961
3962 Visual
3963 *visual;
3964
3965 Colormap
3966 colormap;
3967
3968 XSegment
3969 bounds;
3970
3971 RectangleInfo
3972 crop_info;
3973 } WindowInfo;
3974
3975 IndexPacket
3976 index;
3977
3978 int
3979 display_height,
3980 display_width,
3981 id,
3982 x_offset,
3983 y_offset;
3984
3985 RectangleInfo
3986 crop_info;
3987
3988 register IndexPacket
3989 *indexes;
3990
3991 register int
3992 i;
3993
3994 static ColormapInfo
3995 *colormap_info = (ColormapInfo *) NULL;
3996
3997 static int
3998 max_windows = 0,
3999 number_windows = 0;
4000
4001 static WindowInfo
4002 *window_info;
4003
4004 Status
4005 status;
4006
4007 Window
4008 child,
4009 root_window;
4010
4011 XWindowAttributes
4012 window_attributes;
4013
4014 /*
4015 Verify window is viewable.
4016 */
4017 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4018 assert(display != (Display *) NULL);
4019 status=XGetWindowAttributes(display,window,&window_attributes);
4020 if ((status == False) || (window_attributes.map_state != IsViewable))
4021 return((Image *) NULL);
4022 /*
4023 Cropping rectangle is relative to root window.
4024 */
4025 root_window=XRootWindow(display,XDefaultScreen(display));
4026 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4027 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004028 crop_info.x=(ssize_t) x_offset;
4029 crop_info.y=(ssize_t) y_offset;
4030 crop_info.width=(size_t) window_attributes.width;
4031 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004032 if (borders != MagickFalse)
4033 {
4034 /*
4035 Include border in image.
4036 */
cristybb503372010-05-27 20:51:26 +00004037 crop_info.x-=(ssize_t) window_attributes.border_width;
4038 crop_info.y-=(ssize_t) window_attributes.border_width;
4039 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4040 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004041 }
4042 /*
4043 Crop to root window.
4044 */
4045 if (crop_info.x < 0)
4046 {
4047 crop_info.width+=crop_info.x;
4048 crop_info.x=0;
4049 }
4050 if (crop_info.y < 0)
4051 {
4052 crop_info.height+=crop_info.y;
4053 crop_info.y=0;
4054 }
4055 display_width=XDisplayWidth(display,XDefaultScreen(display));
4056 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004057 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004058 display_height=XDisplayHeight(display,XDefaultScreen(display));
4059 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004060 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004061 /*
4062 Initialize window info attributes.
4063 */
4064 if (number_windows >= max_windows)
4065 {
4066 /*
4067 Allocate or resize window info buffer.
4068 */
4069 max_windows+=1024;
4070 if (window_info == (WindowInfo *) NULL)
4071 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4072 sizeof(*window_info));
4073 else
4074 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4075 max_windows,sizeof(*window_info));
4076 }
4077 if (window_info == (WindowInfo *) NULL)
4078 {
4079 ThrowXWindowFatalException(ResourceLimitError,
4080 "MemoryAllocationFailed","...");
4081 return((Image *) NULL);
4082 }
4083 id=number_windows++;
4084 window_info[id].window=window;
4085 window_info[id].visual=window_attributes.visual;
4086 window_info[id].colormap=window_attributes.colormap;
4087 window_info[id].bounds.x1=(short) crop_info.x;
4088 window_info[id].bounds.y1=(short) crop_info.y;
4089 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4090 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4091 crop_info.x-=x_offset;
4092 crop_info.y-=y_offset;
4093 window_info[id].crop_info=crop_info;
4094 if (level != 0)
4095 {
4096 unsigned int
4097 number_children;
4098
4099 Window
4100 *children;
4101
4102 /*
4103 Descend the window hierarchy.
4104 */
4105 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4106 &children,&number_children);
4107 for (i=0; i < id; i++)
4108 if ((window_info[i].window == window_info[id].parent) &&
4109 (window_info[i].visual == window_info[id].visual) &&
4110 (window_info[i].colormap == window_info[id].colormap))
4111 {
4112 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4113 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4114 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4115 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4116 {
4117 /*
4118 Eliminate windows not circumscribed by their parent.
4119 */
4120 number_windows--;
4121 break;
4122 }
4123 }
4124 if ((status == True) && (number_children != 0))
4125 {
4126 for (i=0; i < (int) number_children; i++)
4127 (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4128 (void) XFree((void *) children);
4129 }
4130 }
4131 if (level <= 1)
4132 {
cristyc57f6942010-11-12 01:47:39 +00004133 CacheView
4134 *composite_view;
4135
cristy3ed852e2009-09-05 21:47:34 +00004136 ColormapInfo
4137 *next;
4138
4139 ExceptionInfo
4140 *exception;
4141
4142 Image
4143 *composite_image,
4144 *image;
4145
4146 int
4147 y;
4148
4149 MagickBooleanType
4150 import;
4151
4152 register int
4153 j,
4154 x;
4155
4156 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00004157 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004158
cristybb503372010-05-27 20:51:26 +00004159 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004160 pixel;
4161
4162 unsigned int
4163 number_colors;
4164
4165 XColor
4166 *colors;
4167
4168 XImage
4169 *ximage;
4170
4171 /*
4172 Get X image for each window in the list.
4173 */
4174 image=NewImageList();
4175 for (id=0; id < number_windows; id++)
4176 {
4177 /*
4178 Does target window intersect top level window?
4179 */
4180 import=
4181 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4182 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4183 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4184 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4185 MagickTrue : MagickFalse;
4186 /*
4187 Is target window contained by another window with the same colormap?
4188 */
4189 for (j=0; j < id; j++)
4190 if ((window_info[id].visual == window_info[j].visual) &&
4191 (window_info[id].colormap == window_info[j].colormap))
4192 {
4193 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4194 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4195 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4196 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4197 import=MagickFalse;
4198 }
4199 else
4200 if ((window_info[id].visual != window_info[j].visual) ||
4201 (window_info[id].colormap != window_info[j].colormap))
4202 {
4203 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4204 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4205 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4206 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4207 import=MagickTrue;
4208 }
4209 if (import == MagickFalse)
4210 continue;
4211 /*
4212 Get X image.
4213 */
4214 ximage=XGetImage(display,window_info[id].window,(int)
4215 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4216 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4217 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4218 if (ximage == (XImage *) NULL)
4219 continue;
4220 /*
4221 Initialize window colormap.
4222 */
4223 number_colors=0;
4224 colors=(XColor *) NULL;
4225 if (window_info[id].colormap != (Colormap) NULL)
4226 {
4227 ColormapInfo
4228 *p;
4229
4230 /*
4231 Search colormap list for window colormap.
4232 */
4233 number_colors=(unsigned int) window_info[id].visual->map_entries;
4234 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4235 if (p->colormap == window_info[id].colormap)
4236 break;
4237 if (p == (ColormapInfo *) NULL)
4238 {
4239 /*
4240 Get the window colormap.
4241 */
4242 colors=(XColor *) AcquireQuantumMemory(number_colors,
4243 sizeof(*colors));
4244 if (colors == (XColor *) NULL)
4245 {
4246 XDestroyImage(ximage);
4247 return((Image *) NULL);
4248 }
4249 if ((window_info[id].visual->klass != DirectColor) &&
4250 (window_info[id].visual->klass != TrueColor))
4251 for (i=0; i < (int) number_colors; i++)
4252 {
cristybb503372010-05-27 20:51:26 +00004253 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004254 colors[i].pad='\0';
4255 }
4256 else
4257 {
cristybb503372010-05-27 20:51:26 +00004258 size_t
cristy3ed852e2009-09-05 21:47:34 +00004259 blue,
4260 blue_bit,
4261 green,
4262 green_bit,
4263 red,
4264 red_bit;
4265
4266 /*
4267 DirectColor or TrueColor visual.
4268 */
4269 red=0;
4270 green=0;
4271 blue=0;
4272 red_bit=window_info[id].visual->red_mask &
4273 (~(window_info[id].visual->red_mask)+1);
4274 green_bit=window_info[id].visual->green_mask &
4275 (~(window_info[id].visual->green_mask)+1);
4276 blue_bit=window_info[id].visual->blue_mask &
4277 (~(window_info[id].visual->blue_mask)+1);
4278 for (i=0; i < (int) number_colors; i++)
4279 {
cristy8891f9c2010-06-04 23:32:17 +00004280 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004281 colors[i].pad='\0';
4282 red+=red_bit;
4283 if (red > window_info[id].visual->red_mask)
4284 red=0;
4285 green+=green_bit;
4286 if (green > window_info[id].visual->green_mask)
4287 green=0;
4288 blue+=blue_bit;
4289 if (blue > window_info[id].visual->blue_mask)
4290 blue=0;
4291 }
4292 }
4293 (void) XQueryColors(display,window_info[id].colormap,colors,
4294 (int) number_colors);
4295 /*
4296 Append colormap to colormap list.
4297 */
cristy73bd4a52010-10-05 11:24:23 +00004298 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004299 if (p == (ColormapInfo *) NULL)
4300 return((Image *) NULL);
4301 p->colormap=window_info[id].colormap;
4302 p->colors=colors;
4303 p->next=colormap_info;
4304 colormap_info=p;
4305 }
4306 colors=p->colors;
4307 }
4308 /*
4309 Allocate image structure.
4310 */
4311 composite_image=AcquireImage((ImageInfo *) NULL);
4312 if (composite_image == (Image *) NULL)
4313 {
4314 XDestroyImage(ximage);
4315 return((Image *) NULL);
4316 }
4317 /*
4318 Convert X image to MIFF format.
4319 */
4320 if ((window_info[id].visual->klass != TrueColor) &&
4321 (window_info[id].visual->klass != DirectColor))
4322 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004323 composite_image->columns=(size_t) ximage->width;
4324 composite_image->rows=(size_t) ximage->height;
cristy3ed852e2009-09-05 21:47:34 +00004325 exception=(&composite_image->exception);
cristyc57f6942010-11-12 01:47:39 +00004326 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004327 switch (composite_image->storage_class)
4328 {
4329 case DirectClass:
4330 default:
4331 {
cristybb503372010-05-27 20:51:26 +00004332 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004333 color,
4334 index;
4335
cristybb503372010-05-27 20:51:26 +00004336 size_t
cristy3ed852e2009-09-05 21:47:34 +00004337 blue_mask,
4338 blue_shift,
4339 green_mask,
4340 green_shift,
4341 red_mask,
4342 red_shift;
4343
4344 /*
4345 Determine shift and mask for red, green, and blue.
4346 */
4347 red_mask=window_info[id].visual->red_mask;
4348 red_shift=0;
4349 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4350 {
4351 red_mask>>=1;
4352 red_shift++;
4353 }
4354 green_mask=window_info[id].visual->green_mask;
4355 green_shift=0;
4356 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4357 {
4358 green_mask>>=1;
4359 green_shift++;
4360 }
4361 blue_mask=window_info[id].visual->blue_mask;
4362 blue_shift=0;
4363 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4364 {
4365 blue_mask>>=1;
4366 blue_shift++;
4367 }
4368 /*
4369 Convert X image to DirectClass packets.
4370 */
4371 if ((number_colors != 0) &&
4372 (window_info[id].visual->klass == DirectColor))
4373 for (y=0; y < (int) composite_image->rows; y++)
4374 {
cristyc57f6942010-11-12 01:47:39 +00004375 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004376 composite_image->columns,1,exception);
4377 if (q == (PixelPacket *) NULL)
4378 break;
4379 for (x=0; x < (int) composite_image->columns; x++)
4380 {
4381 pixel=XGetPixel(ximage,x,y);
4382 index=(pixel >> red_shift) & red_mask;
4383 q->red=ScaleShortToQuantum(colors[index].red);
4384 index=(pixel >> green_shift) & green_mask;
4385 q->green=ScaleShortToQuantum(colors[index].green);
4386 index=(pixel >> blue_shift) & blue_mask;
4387 q->blue=ScaleShortToQuantum(colors[index].blue);
4388 q++;
4389 }
cristyc57f6942010-11-12 01:47:39 +00004390 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004391 break;
4392 }
4393 else
4394 for (y=0; y < (int) composite_image->rows; y++)
4395 {
cristyc57f6942010-11-12 01:47:39 +00004396 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004397 composite_image->columns,1,exception);
4398 if (q == (PixelPacket *) NULL)
4399 break;
4400 for (x=0; x < (int) composite_image->columns; x++)
4401 {
4402 pixel=XGetPixel(ximage,x,y);
4403 color=(pixel >> red_shift) & red_mask;
4404 color=(65535UL*color)/red_mask;
4405 q->red=ScaleShortToQuantum((unsigned short) color);
4406 color=(pixel >> green_shift) & green_mask;
4407 color=(65535UL*color)/green_mask;
4408 q->green=ScaleShortToQuantum((unsigned short) color);
4409 color=(pixel >> blue_shift) & blue_mask;
4410 color=(65535UL*color)/blue_mask;
4411 q->blue=ScaleShortToQuantum((unsigned short) color);
4412 q++;
4413 }
cristyc57f6942010-11-12 01:47:39 +00004414 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004415 break;
4416 }
4417 break;
4418 }
4419 case PseudoClass:
4420 {
4421 /*
4422 Create colormap.
4423 */
4424 if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
4425 {
4426 XDestroyImage(ximage);
4427 composite_image=DestroyImage(composite_image);
4428 return((Image *) NULL);
4429 }
4430 for (i=0; i < (int) composite_image->colors; i++)
4431 {
4432 composite_image->colormap[colors[i].pixel].red=
4433 ScaleShortToQuantum(colors[i].red);
4434 composite_image->colormap[colors[i].pixel].green=
4435 ScaleShortToQuantum(colors[i].green);
4436 composite_image->colormap[colors[i].pixel].blue=
4437 ScaleShortToQuantum(colors[i].blue);
4438 }
4439 /*
4440 Convert X image to PseudoClass packets.
4441 */
4442 for (y=0; y < (int) composite_image->rows; y++)
4443 {
cristyc57f6942010-11-12 01:47:39 +00004444 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4445 composite_image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00004446 if (q == (PixelPacket *) NULL)
4447 break;
cristyc57f6942010-11-12 01:47:39 +00004448 indexes=GetCacheViewAuthenticIndexQueue(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004449 for (x=0; x < (int) composite_image->columns; x++)
4450 {
4451 index=(IndexPacket) XGetPixel(ximage,x,y);
4452 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +00004453 *q++=composite_image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +00004454 }
cristyc57f6942010-11-12 01:47:39 +00004455 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004456 break;
4457 }
4458 break;
4459 }
4460 }
cristyc57f6942010-11-12 01:47:39 +00004461 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004462 XDestroyImage(ximage);
4463 if (image == (Image *) NULL)
4464 {
4465 image=composite_image;
4466 continue;
4467 }
4468 /*
4469 Composite any children in back-to-front order.
4470 */
4471 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4472 &x_offset,&y_offset,&child);
4473 x_offset-=(int) crop_info.x;
4474 if (x_offset < 0)
4475 x_offset=0;
4476 y_offset-=(int) crop_info.y;
4477 if (y_offset < 0)
4478 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004479 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
4480 x_offset,(ssize_t) y_offset);
cristy3ed852e2009-09-05 21:47:34 +00004481 }
4482 /*
4483 Relinquish resources.
4484 */
4485 while (colormap_info != (ColormapInfo *) NULL)
4486 {
4487 next=colormap_info->next;
4488 colormap_info->colors=(XColor *)
4489 RelinquishMagickMemory(colormap_info->colors);
4490 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4491 colormap_info=next;
4492 }
4493 /*
4494 Relinquish resources and restore initial state.
4495 */
4496 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4497 max_windows=0;
4498 number_windows=0;
4499 colormap_info=(ColormapInfo *) NULL;
4500 return(image);
4501 }
4502 return((Image *) NULL);
4503}
4504
4505/*
4506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4507% %
4508% %
4509% %
4510% X G e t W i n d o w I n f o %
4511% %
4512% %
4513% %
4514%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4515%
4516% XGetWindowInfo() initializes the XWindowInfo structure.
4517%
4518% The format of the XGetWindowInfo method is:
4519%
4520% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4521% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4522% XResourceInfo *resource_info,XWindowInfo *window)
4523% resource_info,window)
4524%
4525% A description of each parameter follows:
4526%
4527% o display: Specifies a connection to an X server; returned from
4528% XOpenDisplay.
4529%
4530% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4531% returned from XGetVisualInfo.
4532%
4533% o map_info: If map_type is specified, this structure is initialized
4534% with info from the Standard Colormap.
4535%
4536% o pixel: Specifies a pointer to a XPixelInfo structure.
4537%
4538% o font_info: Specifies a pointer to a XFontStruct structure.
4539%
4540% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4541%
4542*/
4543MagickExport void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4544 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4545 XResourceInfo *resource_info,XWindowInfo *window)
4546{
4547 /*
4548 Initialize window info.
4549 */
4550 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4551 assert(display != (Display *) NULL);
4552 assert(visual_info != (XVisualInfo *) NULL);
4553 assert(map_info != (XStandardColormap *) NULL);
4554 assert(pixel != (XPixelInfo *) NULL);
4555 assert(resource_info != (XResourceInfo *) NULL);
4556 assert(window != (XWindowInfo *) NULL);
4557 if (window->id != (Window) NULL)
4558 {
4559 if (window->cursor != (Cursor) NULL)
4560 (void) XFreeCursor(display,window->cursor);
4561 if (window->busy_cursor != (Cursor) NULL)
4562 (void) XFreeCursor(display,window->busy_cursor);
4563 if (window->highlight_stipple != (Pixmap) NULL)
4564 (void) XFreePixmap(display,window->highlight_stipple);
4565 if (window->shadow_stipple != (Pixmap) NULL)
4566 (void) XFreePixmap(display,window->shadow_stipple);
4567 if (window->name == (char *) NULL)
4568 window->name=AcquireString("");
4569 if (window->icon_name == (char *) NULL)
4570 window->icon_name=AcquireString("");
4571 }
4572 else
4573 {
4574 /*
4575 Initialize these attributes just once.
4576 */
4577 window->id=(Window) NULL;
4578 if (window->name == (char *) NULL)
4579 window->name=AcquireString("");
4580 if (window->icon_name == (char *) NULL)
4581 window->icon_name=AcquireString("");
4582 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4583 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4584 window->ximage=(XImage *) NULL;
4585 window->matte_image=(XImage *) NULL;
4586 window->pixmap=(Pixmap) NULL;
4587 window->matte_pixmap=(Pixmap) NULL;
4588 window->mapped=MagickFalse;
4589 window->stasis=MagickFalse;
4590 window->shared_memory=MagickTrue;
4591 window->segment_info=(void *) NULL;
4592#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4593 {
4594 XShmSegmentInfo
4595 *segment_info;
4596
4597 if (window->segment_info == (void *) NULL)
4598 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4599 segment_info=(XShmSegmentInfo *) window->segment_info;
4600 segment_info[0].shmid=(-1);
4601 segment_info[0].shmaddr=(char *) NULL;
4602 segment_info[1].shmid=(-1);
4603 segment_info[1].shmaddr=(char *) NULL;
4604 }
4605#endif
4606 }
4607 /*
4608 Initialize these attributes every time function is called.
4609 */
4610 window->screen=visual_info->screen;
4611 window->root=XRootWindow(display,visual_info->screen);
4612 window->visual=visual_info->visual;
4613 window->storage_class=(unsigned int) visual_info->klass;
4614 window->depth=(unsigned int) visual_info->depth;
4615 window->visual_info=visual_info;
4616 window->map_info=map_info;
4617 window->pixel_info=pixel;
4618 window->font_info=font_info;
4619 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4620 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4621 window->geometry=(char *) NULL;
4622 window->icon_geometry=(char *) NULL;
4623 if (resource_info->icon_geometry != (char *) NULL)
4624 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4625 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004626 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004627 window->width=1;
4628 window->height=1;
4629 window->min_width=1;
4630 window->min_height=1;
4631 window->width_inc=1;
4632 window->height_inc=1;
4633 window->border_width=resource_info->border_width;
4634 window->annotate_context=pixel->annotate_context;
4635 window->highlight_context=pixel->highlight_context;
4636 window->widget_context=pixel->widget_context;
4637 window->shadow_stipple=(Pixmap) NULL;
4638 window->highlight_stipple=(Pixmap) NULL;
4639 window->use_pixmap=MagickTrue;
4640 window->immutable=MagickFalse;
4641 window->shape=MagickFalse;
4642 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004643 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004644 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4645 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4646 window->attributes.background_pixel=pixel->background_color.pixel;
4647 window->attributes.background_pixmap=(Pixmap) NULL;
4648 window->attributes.bit_gravity=ForgetGravity;
4649 window->attributes.backing_store=WhenMapped;
4650 window->attributes.save_under=MagickTrue;
4651 window->attributes.border_pixel=pixel->border_color.pixel;
4652 window->attributes.colormap=map_info->colormap;
4653 window->attributes.cursor=window->cursor;
4654 window->attributes.do_not_propagate_mask=NoEventMask;
4655 window->attributes.event_mask=NoEventMask;
4656 window->attributes.override_redirect=MagickFalse;
4657 window->attributes.win_gravity=NorthWestGravity;
4658 window->orphan=MagickFalse;
4659}
4660
4661/*
4662%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4663% %
4664% %
4665% %
4666% X H i g h l i g h t E l l i p s e %
4667% %
4668% %
4669% %
4670%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4671%
4672% XHighlightEllipse() puts a border on the X server around a region defined by
4673% highlight_info.
4674%
4675% The format of the XHighlightEllipse method is:
4676%
4677% void XHighlightEllipse(Display *display,Window window,
4678% GC annotate_context,const RectangleInfo *highlight_info)
4679%
4680% A description of each parameter follows:
4681%
4682% o display: Specifies a connection to an X server; returned from
4683% XOpenDisplay.
4684%
4685% o window: Specifies a pointer to a Window structure.
4686%
4687% o annotate_context: Specifies a pointer to a GC structure.
4688%
4689% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4690% contains the extents of any highlighting rectangle.
4691%
4692*/
4693MagickExport void XHighlightEllipse(Display *display,Window window,
4694 GC annotate_context,const RectangleInfo *highlight_info)
4695{
4696 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4697 assert(display != (Display *) NULL);
4698 assert(window != (Window) NULL);
4699 assert(annotate_context != (GC) NULL);
4700 assert(highlight_info != (RectangleInfo *) NULL);
4701 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4702 return;
4703 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4704 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4705 (unsigned int) highlight_info->height-1,0,360*64);
4706 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4707 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4708 (unsigned int) highlight_info->height-3,0,360*64);
4709}
4710
4711/*
4712%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4713% %
4714% %
4715% %
4716% X H i g h l i g h t L i n e %
4717% %
4718% %
4719% %
4720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4721%
4722% XHighlightLine() puts a border on the X server around a region defined by
4723% highlight_info.
4724%
4725% The format of the XHighlightLine method is:
4726%
4727% void XHighlightLine(Display *display,Window window,GC annotate_context,
4728% const XSegment *highlight_info)
4729%
4730% A description of each parameter follows:
4731%
4732% o display: Specifies a connection to an X server; returned from
4733% XOpenDisplay.
4734%
4735% o window: Specifies a pointer to a Window structure.
4736%
4737% o annotate_context: Specifies a pointer to a GC structure.
4738%
4739% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4740% contains the extents of any highlighting rectangle.
4741%
4742*/
4743MagickExport void XHighlightLine(Display *display,Window window,
4744 GC annotate_context,const XSegment *highlight_info)
4745{
4746 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4747 assert(display != (Display *) NULL);
4748 assert(window != (Window) NULL);
4749 assert(annotate_context != (GC) NULL);
4750 assert(highlight_info != (XSegment *) NULL);
4751 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4752 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4753}
4754
4755/*
4756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4757% %
4758% %
4759% %
4760% X H i g h l i g h t R e c t a n g l e %
4761% %
4762% %
4763% %
4764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4765%
4766% XHighlightRectangle() puts a border on the X server around a region defined
4767% by highlight_info.
4768%
4769% The format of the XHighlightRectangle method is:
4770%
4771% void XHighlightRectangle(Display *display,Window window,
4772% GC annotate_context,const RectangleInfo *highlight_info)
4773%
4774% A description of each parameter follows:
4775%
4776% o display: Specifies a connection to an X server; returned from
4777% XOpenDisplay.
4778%
4779% o window: Specifies a pointer to a Window structure.
4780%
4781% o annotate_context: Specifies a pointer to a GC structure.
4782%
4783% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4784% contains the extents of any highlighting rectangle.
4785%
4786*/
4787MagickExport void XHighlightRectangle(Display *display,Window window,
4788 GC annotate_context,const RectangleInfo *highlight_info)
4789{
4790 assert(display != (Display *) NULL);
4791 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4792 assert(window != (Window) NULL);
4793 assert(annotate_context != (GC) NULL);
4794 assert(highlight_info != (RectangleInfo *) NULL);
4795 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4796 return;
4797 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4798 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4799 (unsigned int) highlight_info->height-1);
4800 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4801 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4802 (unsigned int) highlight_info->height-3);
4803}
4804
4805/*
4806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4807% %
4808% %
4809% %
4810% X I m p o r t I m a g e %
4811% %
4812% %
4813% %
4814%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4815%
4816% XImportImage() reads an image from an X window.
4817%
4818% The format of the XImportImage method is:
4819%
4820% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4821%
4822% A description of each parameter follows:
4823%
4824% o image_info: the image info.
4825%
4826% o ximage_info: Specifies a pointer to an XImportInfo structure.
4827%
4828*/
4829MagickExport Image *XImportImage(const ImageInfo *image_info,
4830 XImportInfo *ximage_info)
4831{
4832 Colormap
4833 *colormaps;
4834
4835 Display
4836 *display;
4837
4838 Image
4839 *image;
4840
4841 int
4842 number_colormaps,
4843 number_windows,
4844 x;
4845
4846 RectangleInfo
4847 crop_info;
4848
4849 Status
4850 status;
4851
4852 Window
4853 *children,
4854 client,
4855 prior_target,
4856 root,
4857 target;
4858
4859 XTextProperty
4860 window_name;
4861
4862 /*
4863 Open X server connection.
4864 */
4865 assert(image_info != (const ImageInfo *) NULL);
4866 assert(image_info->signature == MagickSignature);
4867 if (image_info->debug != MagickFalse)
4868 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4869 image_info->filename);
4870 assert(ximage_info != (XImportInfo *) NULL);
4871 display=XOpenDisplay(image_info->server_name);
4872 if (display == (Display *) NULL)
4873 {
4874 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4875 XDisplayName(image_info->server_name));
4876 return((Image *) NULL);
4877 }
4878 /*
4879 Set our forgiving exception handler.
4880 */
4881 (void) XSetErrorHandler(XError);
4882 /*
4883 Select target window.
4884 */
4885 crop_info.x=0;
4886 crop_info.y=0;
4887 crop_info.width=0;
4888 crop_info.height=0;
4889 root=XRootWindow(display,XDefaultScreen(display));
4890 target=(Window) NULL;
4891 if ((image_info->filename != (char *) NULL) &&
4892 (*image_info->filename != '\0'))
4893 {
4894 if (LocaleCompare(image_info->filename,"root") == 0)
4895 target=root;
4896 else
4897 {
4898 /*
4899 Select window by ID or name.
4900 */
4901 if (isdigit((unsigned char) *image_info->filename) != 0)
4902 target=XWindowByID(display,root,(Window)
4903 strtol(image_info->filename,(char **) NULL,0));
4904 if (target == (Window) NULL)
4905 target=XWindowByName(display,root,image_info->filename);
4906 if (target == (Window) NULL)
4907 ThrowXWindowFatalException(XServerError,
4908 "NoWindowWithSpecifiedIDExists",image_info->filename);
4909 }
4910 }
4911 /*
4912 If target window is not defined, interactively select one.
4913 */
4914 prior_target=target;
4915 if (target == (Window) NULL)
4916 target=XSelectWindow(display,&crop_info);
4917 if (target == (Window) NULL)
4918 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4919 image_info->filename);
4920 client=target; /* obsolete */
4921 if (target != root)
4922 {
4923 unsigned int
4924 d;
4925
4926 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4927 if (status != False)
4928 {
4929 for ( ; ; )
4930 {
4931 Window
4932 parent;
4933
4934 /*
4935 Find window manager frame.
4936 */
4937 status=XQueryTree(display,target,&root,&parent,&children,&d);
4938 if ((status != False) && (children != (Window *) NULL))
4939 (void) XFree((char *) children);
4940 if ((status == False) || (parent == (Window) NULL) ||
4941 (parent == root))
4942 break;
4943 target=parent;
4944 }
4945 /*
4946 Get client window.
4947 */
4948 client=XClientWindow(display,target);
4949 if (ximage_info->frame == MagickFalse)
4950 target=client;
4951 if ((ximage_info->frame == MagickFalse) &&
4952 (prior_target != MagickFalse))
4953 target=prior_target;
4954 XDelay(display,SuspendTime << 4);
4955 }
4956 }
4957 if (ximage_info->screen)
4958 {
4959 int
4960 y;
4961
4962 Window
4963 child;
4964
4965 XWindowAttributes
4966 window_attributes;
4967
4968 /*
4969 Obtain window image directly from screen.
4970 */
4971 status=XGetWindowAttributes(display,target,&window_attributes);
4972 if (status == False)
4973 {
4974 ThrowXWindowFatalException(XServerError,
4975 "UnableToReadXWindowAttributes",image_info->filename);
4976 (void) XCloseDisplay(display);
4977 return((Image *) NULL);
4978 }
4979 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00004980 crop_info.x=(ssize_t) x;
4981 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00004982 crop_info.width=(size_t) window_attributes.width;
4983 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00004984 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00004985 {
4986 /*
4987 Include border in image.
4988 */
4989 crop_info.x-=window_attributes.border_width;
4990 crop_info.y-=window_attributes.border_width;
4991 crop_info.width+=window_attributes.border_width << 1;
4992 crop_info.height+=window_attributes.border_width << 1;
4993 }
4994 target=root;
4995 }
4996 /*
4997 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
4998 */
4999 number_windows=0;
5000 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5001 if ((status == True) && (number_windows > 0))
5002 {
5003 ximage_info->descend=MagickTrue;
5004 (void) XFree ((char *) children);
5005 }
5006 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5007 if (number_colormaps > 0)
5008 {
5009 if (number_colormaps > 1)
5010 ximage_info->descend=MagickTrue;
5011 (void) XFree((char *) colormaps);
5012 }
5013 /*
5014 Alert the user not to alter the screen.
5015 */
5016 if (ximage_info->silent == MagickFalse)
5017 (void) XBell(display,0);
5018 /*
5019 Get image by window id.
5020 */
5021 (void) XGrabServer(display);
5022 image=XGetWindowImage(display,target,ximage_info->borders,
5023 ximage_info->descend ? 1U : 0U);
5024 (void) XUngrabServer(display);
5025 if (image == (Image *) NULL)
5026 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5027 image_info->filename)
5028 else
5029 {
5030 (void) CopyMagickString(image->filename,image_info->filename,
5031 MaxTextExtent);
5032 if ((crop_info.width != 0) && (crop_info.height != 0))
5033 {
5034 Image
5035 *clone_image,
5036 *crop_image;
5037
5038 /*
5039 Crop image as defined by the cropping rectangle.
5040 */
5041 clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5042 if (clone_image != (Image *) NULL)
5043 {
5044 crop_image=CropImage(clone_image,&crop_info,&image->exception);
5045 if (crop_image != (Image *) NULL)
5046 {
5047 image=DestroyImage(image);
5048 image=crop_image;
5049 }
5050 }
5051 }
5052 status=XGetWMName(display,target,&window_name);
5053 if (status == True)
5054 {
5055 if ((image_info->filename != (char *) NULL) &&
5056 (*image_info->filename == '\0'))
5057 (void) CopyMagickString(image->filename,(char *) window_name.value,
5058 (size_t) window_name.nitems+1);
5059 (void) XFree((void *) window_name.value);
5060 }
5061 }
5062 if (ximage_info->silent == MagickFalse)
5063 {
5064 /*
5065 Alert the user we're done.
5066 */
5067 (void) XBell(display,0);
5068 (void) XBell(display,0);
5069 }
5070 (void) XCloseDisplay(display);
5071 return(image);
5072}
5073
5074/*
5075%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5076% %
5077% %
5078% %
5079% X I n i t i a l i z e W i n d o w s %
5080% %
5081% %
5082% %
5083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5084%
5085% XInitializeWindows() initializes the XWindows structure.
5086%
5087% The format of the XInitializeWindows method is:
5088%
5089% XWindows *XInitializeWindows(Display *display,
5090% XResourceInfo *resource_info)
5091%
5092% A description of each parameter follows:
5093%
5094% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5095%
5096% o display: Specifies a connection to an X server; returned from
5097% XOpenDisplay.
5098%
5099% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5100%
5101*/
5102MagickExport XWindows *XInitializeWindows(Display *display,
5103 XResourceInfo *resource_info)
5104{
5105 Window
5106 root_window;
5107
5108 XWindows
5109 *windows;
5110
5111 /*
5112 Allocate windows structure.
5113 */
cristy73bd4a52010-10-05 11:24:23 +00005114 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005115 if (windows == (XWindows *) NULL)
5116 {
5117 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5118 "...");
5119 return((XWindows *) NULL);
5120 }
5121 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5122 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5123 sizeof(*windows->pixel_info));
5124 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5125 sizeof(*windows->icon_pixel));
5126 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5127 sizeof(*windows->icon_resources));
5128 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5129 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5130 (windows->icon_resources == (XResourceInfo *) NULL))
5131 {
5132 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5133 "...");
5134 return((XWindows *) NULL);
5135 }
5136 /*
5137 Initialize windows structure.
5138 */
5139 windows->display=display;
5140 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5141 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5142 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5143 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5144 windows->im_remote_command=
5145 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5146 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5147 windows->im_update_colormap=
5148 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5149 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5150 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5151 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5152 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5153 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005154#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005155 (void) XSynchronize(display,IsWindows95());
5156#endif
5157 if (IsEventLogging())
5158 {
5159 (void) XSynchronize(display,MagickTrue);
5160 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005161 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005162 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5163 (void) LogMagickEvent(X11Event,GetMagickModule(),
5164 " Window Manager: 0x%lx",windows->wm_protocols);
5165 (void) LogMagickEvent(X11Event,GetMagickModule(),
5166 " delete window: 0x%lx",windows->wm_delete_window);
5167 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5168 windows->wm_take_focus);
5169 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5170 windows->im_protocols);
5171 (void) LogMagickEvent(X11Event,GetMagickModule(),
5172 " remote command: 0x%lx",windows->im_remote_command);
5173 (void) LogMagickEvent(X11Event,GetMagickModule(),
5174 " update widget: 0x%lx",windows->im_update_widget);
5175 (void) LogMagickEvent(X11Event,GetMagickModule(),
5176 " update colormap: 0x%lx",windows->im_update_colormap);
5177 (void) LogMagickEvent(X11Event,GetMagickModule(),
5178 " former image: 0x%lx",windows->im_former_image);
5179 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5180 windows->im_next_image);
5181 (void) LogMagickEvent(X11Event,GetMagickModule(),
5182 " retain colors: 0x%lx",windows->im_retain_colors);
5183 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5184 windows->im_exit);
5185 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5186 windows->dnd_protocols);
5187 }
5188 /*
5189 Allocate standard colormap.
5190 */
5191 windows->map_info=XAllocStandardColormap();
5192 windows->icon_map=XAllocStandardColormap();
5193 if ((windows->map_info == (XStandardColormap *) NULL) ||
5194 (windows->icon_map == (XStandardColormap *) NULL))
5195 ThrowXWindowFatalException(ResourceLimitFatalError,
5196 "MemoryAllocationFailed","...");
5197 windows->map_info->colormap=(Colormap) NULL;
5198 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005199 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005200 windows->pixel_info->annotate_context=(GC) NULL;
5201 windows->pixel_info->highlight_context=(GC) NULL;
5202 windows->pixel_info->widget_context=(GC) NULL;
5203 windows->font_info=(XFontStruct *) NULL;
5204 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005205 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005206 /*
5207 Allocate visual.
5208 */
5209 *windows->icon_resources=(*resource_info);
5210 windows->icon_resources->visual_type=(char *) "default";
5211 windows->icon_resources->colormap=SharedColormap;
5212 windows->visual_info=
5213 XBestVisualInfo(display,windows->map_info,resource_info);
5214 windows->icon_visual=
5215 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5216 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5217 (windows->icon_visual == (XVisualInfo *) NULL))
5218 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5219 resource_info->visual_type);
5220 if (IsEventLogging())
5221 {
5222 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5223 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5224 windows->visual_info->visualid);
5225 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5226 XVisualClassName(windows->visual_info->klass));
5227 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5228 windows->visual_info->depth);
5229 (void) LogMagickEvent(X11Event,GetMagickModule(),
5230 " size of colormap: %d entries",windows->visual_info->colormap_size);
5231 (void) LogMagickEvent(X11Event,GetMagickModule(),
5232 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5233 windows->visual_info->red_mask,windows->visual_info->green_mask,
5234 windows->visual_info->blue_mask);
5235 (void) LogMagickEvent(X11Event,GetMagickModule(),
5236 " significant bits in color: %d bits",
5237 windows->visual_info->bits_per_rgb);
5238 }
5239 /*
5240 Allocate class and manager hints.
5241 */
5242 windows->class_hints=XAllocClassHint();
5243 windows->manager_hints=XAllocWMHints();
5244 if ((windows->class_hints == (XClassHint *) NULL) ||
5245 (windows->manager_hints == (XWMHints *) NULL))
5246 ThrowXWindowFatalException(ResourceLimitFatalError,
5247 "MemoryAllocationFailed","...");
5248 /*
5249 Determine group leader if we have one.
5250 */
5251 root_window=XRootWindow(display,windows->visual_info->screen);
5252 windows->group_leader.id=(Window) NULL;
5253 if (resource_info->window_group != (char *) NULL)
5254 {
5255 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5256 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5257 strtol((char *) resource_info->window_group,(char **) NULL,0));
5258 if (windows->group_leader.id == (Window) NULL)
5259 windows->group_leader.id=
5260 XWindowByName(display,root_window,resource_info->window_group);
5261 }
5262 return(windows);
5263}
5264
5265/*
5266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5267% %
5268% %
5269% %
5270% X M a k e C u r s o r %
5271% %
5272% %
5273% %
5274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5275%
5276% XMakeCursor() creates a crosshairs X11 cursor.
5277%
5278% The format of the XMakeCursor method is:
5279%
5280% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5281% char *background_color,char *foreground_color)
5282%
5283% A description of each parameter follows:
5284%
5285% o display: Specifies a connection to an X server; returned from
5286% XOpenDisplay.
5287%
5288% o window: Specifies the ID of the window for which the cursor is
5289% assigned.
5290%
5291% o colormap: Specifies the ID of the colormap from which the background
5292% and foreground color will be retrieved.
5293%
5294% o background_color: Specifies the color to use for the cursor background.
5295%
5296% o foreground_color: Specifies the color to use for the cursor foreground.
5297%
5298*/
5299MagickExport Cursor XMakeCursor(Display *display,Window window,
5300 Colormap colormap,char *background_color,char *foreground_color)
5301{
5302#define scope_height 17
5303#define scope_x_hot 8
5304#define scope_y_hot 8
5305#define scope_width 17
5306
5307 static const unsigned char
5308 scope_bits[] =
5309 {
5310 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5311 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5312 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5313 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5314 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5315 },
5316 scope_mask_bits[] =
5317 {
5318 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5319 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5320 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5321 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5322 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5323 };
5324
5325 Cursor
5326 cursor;
5327
5328 Pixmap
5329 mask,
5330 source;
5331
5332 XColor
5333 background,
5334 foreground;
5335
5336 assert(display != (Display *) NULL);
5337 assert(window != (Window) NULL);
5338 assert(colormap != (Colormap) NULL);
5339 assert(background_color != (char *) NULL);
5340 assert(foreground_color != (char *) NULL);
5341 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5342 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5343 scope_height);
5344 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5345 scope_width,scope_height);
5346 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5347 {
5348 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5349 return((Cursor) NULL);
5350 }
5351 (void) XParseColor(display,colormap,background_color,&background);
5352 (void) XParseColor(display,colormap,foreground_color,&foreground);
5353 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5354 scope_x_hot,scope_y_hot);
5355 (void) XFreePixmap(display,source);
5356 (void) XFreePixmap(display,mask);
5357 return(cursor);
5358}
5359
5360/*
5361%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5362% %
5363% %
5364% %
5365% X M a k e I m a g e %
5366% %
5367% %
5368% %
5369%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5370%
5371% XMakeImage() creates an X11 image. If the image size differs from the X11
5372% image size, the image is first resized.
5373%
5374% The format of the XMakeImage method is:
5375%
5376% MagickBooleanType XMakeImage(Display *display,
5377% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5378% unsigned int width,unsigned int height)
5379%
5380% A description of each parameter follows:
5381%
5382% o display: Specifies a connection to an X server; returned from
5383% XOpenDisplay.
5384%
5385% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5386%
5387% o window: Specifies a pointer to a XWindowInfo structure.
5388%
5389% o image: the image.
5390%
5391% o width: Specifies the width in pixels of the rectangular area to
5392% display.
5393%
5394% o height: Specifies the height in pixels of the rectangular area to
5395% display.
5396%
5397*/
5398MagickExport MagickBooleanType XMakeImage(Display *display,
5399 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5400 unsigned int width,unsigned int height)
5401{
5402#define CheckOverflowException(length,width,height) \
5403 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5404
5405 int
5406 depth,
5407 format;
5408
5409 size_t
5410 length;
5411
5412 XImage
5413 *matte_image,
5414 *ximage;
5415
5416 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5417 assert(display != (Display *) NULL);
5418 assert(resource_info != (XResourceInfo *) NULL);
5419 assert(window != (XWindowInfo *) NULL);
5420 assert(width != 0);
5421 assert(height != 0);
5422 if ((window->width == 0) || (window->height == 0))
5423 return(MagickFalse);
5424 /*
5425 Apply user transforms to the image.
5426 */
5427 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5428 (void) XFlush(display);
5429 depth=(int) window->depth;
5430 if (window->destroy)
5431 window->image=DestroyImage(window->image);
5432 window->image=image;
5433 window->destroy=MagickFalse;
5434 if (window->image != (Image *) NULL)
5435 {
5436 if (window->crop_geometry != (char *) NULL)
5437 {
5438 Image
5439 *crop_image;
5440
5441 RectangleInfo
5442 crop_info;
5443
5444 /*
5445 Crop image.
5446 */
5447 window->image->page.x=0;
5448 window->image->page.y=0;
5449 (void) ParsePageGeometry(window->image,window->crop_geometry,
5450 &crop_info,&image->exception);
5451 crop_image=CropImage(window->image,&crop_info,&image->exception);
5452 if (crop_image != (Image *) NULL)
5453 {
5454 if (window->image != image)
5455 window->image=DestroyImage(window->image);
5456 window->image=crop_image;
5457 window->destroy=MagickTrue;
5458 }
5459 }
5460 if ((width != (unsigned int) window->image->columns) ||
5461 (height != (unsigned int) window->image->rows))
5462 {
5463 Image
5464 *resize_image;
5465
5466 /*
5467 Resize image.
5468 */
5469 resize_image=NewImageList();
5470 if (window->pixel_info->colors != 0)
5471 resize_image=SampleImage(window->image,width,height,
5472 &image->exception);
5473 else
5474 resize_image=ThumbnailImage(window->image,width,height,
5475 &image->exception);
5476 if (resize_image != (Image *) NULL)
5477 {
5478 if (window->image != image)
5479 window->image=DestroyImage(window->image);
5480 window->image=resize_image;
5481 window->destroy=MagickTrue;
5482 }
5483 }
5484 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005485 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005486 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005487 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005488 }
5489 /*
5490 Create X image.
5491 */
5492 ximage=(XImage *) NULL;
5493 format=(depth == 1) ? XYBitmap : ZPixmap;
5494#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5495 if (window->shared_memory != MagickFalse)
5496 {
5497 XShmSegmentInfo
5498 *segment_info;
5499
5500 segment_info=(XShmSegmentInfo *) window->segment_info;
5501 segment_info[1].shmid=(-1);
5502 segment_info[1].shmaddr=(char *) NULL;
5503 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5504 (char *) NULL,&segment_info[1],width,height);
5505 if (ximage == (XImage *) NULL)
5506 window->shared_memory=MagickFalse;
5507 length=(size_t) ximage->bytes_per_line*ximage->height;
5508 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5509 window->shared_memory=MagickFalse;
5510 if (window->shared_memory != MagickFalse)
5511 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5512 if (window->shared_memory != MagickFalse)
5513 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5514 if (segment_info[1].shmid < 0)
5515 window->shared_memory=MagickFalse;
5516 if (window->shared_memory != MagickFalse)
5517 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5518 else
5519 {
5520 if (ximage != (XImage *) NULL)
5521 XDestroyImage(ximage);
5522 ximage=(XImage *) NULL;
5523 if (segment_info[1].shmaddr)
5524 {
5525 (void) shmdt(segment_info[1].shmaddr);
5526 segment_info[1].shmaddr=(char *) NULL;
5527 }
5528 if (segment_info[1].shmid >= 0)
5529 {
5530 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5531 segment_info[1].shmid=(-1);
5532 }
5533 }
5534 }
5535#endif
5536 /*
5537 Allocate X image pixel data.
5538 */
5539#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5540 if (window->shared_memory)
5541 {
5542 Status
5543 status;
5544
5545 XShmSegmentInfo
5546 *segment_info;
5547
5548 (void) XSync(display,MagickFalse);
5549 xerror_alert=MagickFalse;
5550 segment_info=(XShmSegmentInfo *) window->segment_info;
5551 ximage->data=segment_info[1].shmaddr;
5552 segment_info[1].readOnly=MagickFalse;
5553 status=XShmAttach(display,&segment_info[1]);
5554 if (status != False)
5555 (void) XSync(display,MagickFalse);
5556 if ((status == False) || (xerror_alert != MagickFalse))
5557 {
5558 window->shared_memory=MagickFalse;
5559 if (status != False)
5560 XShmDetach(display,&segment_info[1]);
5561 if (ximage != (XImage *) NULL)
5562 {
5563 ximage->data=NULL;
5564 XDestroyImage(ximage);
5565 ximage=(XImage *) NULL;
5566 }
5567 if (segment_info[1].shmid >= 0)
5568 {
5569 if (segment_info[1].shmaddr != NULL)
5570 (void) shmdt(segment_info[1].shmaddr);
5571 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5572 segment_info[1].shmid=(-1);
5573 segment_info[1].shmaddr=(char *) NULL;
5574 }
5575 }
5576 }
5577#endif
5578 if (window->shared_memory == MagickFalse)
5579 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5580 (char *) NULL,width,height,XBitmapPad(display),0);
5581 if (ximage == (XImage *) NULL)
5582 {
5583 /*
5584 Unable to create X image.
5585 */
5586 (void) XCheckDefineCursor(display,window->id,window->cursor);
5587 return(MagickFalse);
5588 }
5589 length=(size_t) ximage->bytes_per_line*ximage->height;
5590 if (IsEventLogging())
5591 {
5592 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5593 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5594 ximage->width,ximage->height);
5595 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5596 ximage->format);
5597 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5598 ximage->byte_order);
5599 (void) LogMagickEvent(X11Event,GetMagickModule(),
5600 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5601 ximage->bitmap_bit_order,ximage->bitmap_pad);
5602 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5603 ximage->depth);
5604 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5605 ximage->bytes_per_line);
5606 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5607 ximage->bits_per_pixel);
5608 (void) LogMagickEvent(X11Event,GetMagickModule(),
5609 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5610 ximage->green_mask,ximage->blue_mask);
5611 }
5612 if (window->shared_memory == MagickFalse)
5613 {
5614 if (ximage->format != XYBitmap)
5615 ximage->data=(char *) AcquireQuantumMemory((size_t)
5616 ximage->bytes_per_line,(size_t) ximage->height);
5617 else
5618 ximage->data=(char *) AcquireQuantumMemory((size_t)
5619 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5620 }
5621 if (ximage->data == (char *) NULL)
5622 {
5623 /*
5624 Unable to allocate pixel data.
5625 */
5626 XDestroyImage(ximage);
5627 ximage=(XImage *) NULL;
5628 (void) XCheckDefineCursor(display,window->id,window->cursor);
5629 return(MagickFalse);
5630 }
5631 if (window->ximage != (XImage *) NULL)
5632 {
5633 /*
5634 Destroy previous X image.
5635 */
5636 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5637#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5638 if (window->segment_info != (XShmSegmentInfo *) NULL)
5639 {
5640 XShmSegmentInfo
5641 *segment_info;
5642
5643 segment_info=(XShmSegmentInfo *) window->segment_info;
5644 if (segment_info[0].shmid >= 0)
5645 {
5646 (void) XSync(display,MagickFalse);
5647 (void) XShmDetach(display,&segment_info[0]);
5648 (void) XSync(display,MagickFalse);
5649 if (segment_info[0].shmaddr != (char *) NULL)
5650 (void) shmdt(segment_info[0].shmaddr);
5651 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5652 segment_info[0].shmid=(-1);
5653 segment_info[0].shmaddr=(char *) NULL;
5654 window->ximage->data=(char *) NULL;
5655 }
5656 }
5657#endif
5658 if (window->ximage->data != (char *) NULL)
5659 free(window->ximage->data);
5660 window->ximage->data=(char *) NULL;
5661 XDestroyImage(window->ximage);
5662 window->ximage=(XImage *) NULL;
5663 }
5664#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5665 if (window->segment_info != (XShmSegmentInfo *) NULL)
5666 {
5667 XShmSegmentInfo
5668 *segment_info;
5669
5670 segment_info=(XShmSegmentInfo *) window->segment_info;
5671 segment_info[0]=segment_info[1];
5672 }
5673#endif
5674 window->ximage=ximage;
5675 matte_image=(XImage *) NULL;
5676 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5677 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005678 ((int) width <= XDisplayWidth(display,window->screen)) &&
5679 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005680 {
5681 /*
5682 Create matte image.
5683 */
5684 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5685 (char *) NULL,width,height,XBitmapPad(display),0);
5686 if (IsEventLogging())
5687 {
5688 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5689 (void) LogMagickEvent(X11Event,GetMagickModule(),
5690 " width, height: %dx%d",matte_image->width,matte_image->height);
5691 }
5692 if (matte_image != (XImage *) NULL)
5693 {
5694 /*
5695 Allocate matte image pixel data.
5696 */
5697 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5698 matte_image->bytes_per_line*matte_image->depth,
5699 (size_t) matte_image->height);
5700 if (matte_image->data == (char *) NULL)
5701 {
5702 XDestroyImage(matte_image);
5703 matte_image=(XImage *) NULL;
5704 }
5705 }
5706 }
5707 if (window->matte_image != (XImage *) NULL)
5708 {
5709 /*
5710 Free matte image.
5711 */
5712 if (window->matte_image->data != (char *) NULL)
5713 free(window->matte_image->data);
5714 window->matte_image->data=(char *) NULL;
5715 XDestroyImage(window->matte_image);
5716 window->matte_image=(XImage *) NULL;
5717 }
5718 window->matte_image=matte_image;
5719 if (window->matte_pixmap != (Pixmap) NULL)
5720 {
5721 (void) XFreePixmap(display,window->matte_pixmap);
5722 window->matte_pixmap=(Pixmap) NULL;
5723#if defined(MAGICKCORE_HAVE_SHAPE)
5724 if (window->shape != MagickFalse)
5725 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5726#endif
5727 }
5728 window->stasis=MagickFalse;
5729 /*
5730 Convert pixels to X image data.
5731 */
5732 if (window->image != (Image *) NULL)
5733 {
5734 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5735 (ximage->bitmap_bit_order == LSBFirst)))
5736 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5737 matte_image);
5738 else
5739 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5740 matte_image);
5741 }
5742 if (window->matte_image != (XImage *) NULL)
5743 {
5744 /*
5745 Create matte pixmap.
5746 */
5747 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5748 if (window->matte_pixmap != (Pixmap) NULL)
5749 {
5750 GC
5751 graphics_context;
5752
5753 XGCValues
5754 context_values;
5755
5756 /*
5757 Copy matte image to matte pixmap.
5758 */
5759 context_values.background=1;
5760 context_values.foreground=0;
5761 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005762 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005763 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5764 window->matte_image,0,0,0,0,width,height);
5765 (void) XFreeGC(display,graphics_context);
5766#if defined(MAGICKCORE_HAVE_SHAPE)
5767 if (window->shape != MagickFalse)
5768 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5769 window->matte_pixmap,ShapeSet);
5770#endif
5771 }
5772 }
5773 (void) XMakePixmap(display,resource_info,window);
5774 /*
5775 Restore cursor.
5776 */
5777 (void) XCheckDefineCursor(display,window->id,window->cursor);
5778 return(MagickTrue);
5779}
5780
5781/*
5782%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5783% %
5784% %
5785% %
5786+ X M a k e I m a g e L S B F i r s t %
5787% %
5788% %
5789% %
5790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5791%
5792% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5793% pixels are copied in least-significant bit and byte first order. The
5794% server's scanline pad is respected. Rather than using one or two general
5795% cases, many special cases are found here to help speed up the image
5796% conversion.
5797%
5798% The format of the XMakeImageLSBFirst method is:
5799%
5800% void XMakeImageLSBFirst(Display *display,XWindows *windows)
5801%
5802% A description of each parameter follows:
5803%
5804% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5805%
5806% o window: Specifies a pointer to a XWindowInfo structure.
5807%
5808% o image: the image.
5809%
5810% o ximage: Specifies a pointer to a XImage structure; returned from
5811% XCreateImage.
5812%
5813% o matte_image: Specifies a pointer to a XImage structure; returned from
5814% XCreateImage.
5815%
5816*/
5817static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5818 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5819{
cristyc57f6942010-11-12 01:47:39 +00005820 CacheView
5821 *canvas_view;
5822
cristy3ed852e2009-09-05 21:47:34 +00005823 Image
5824 *canvas;
5825
5826 int
5827 y;
5828
5829 register const IndexPacket
5830 *indexes;
5831
5832 register const PixelPacket
5833 *p;
5834
5835 register int
5836 x;
5837
5838 register unsigned char
5839 *q;
5840
5841 unsigned char
5842 bit,
5843 byte;
5844
5845 unsigned int
5846 scanline_pad;
5847
cristyf2faecf2010-05-28 19:19:36 +00005848 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005849 pixel,
5850 *pixels;
5851
5852 XStandardColormap
5853 *map_info;
5854
5855 assert(resource_info != (XResourceInfo *) NULL);
5856 assert(window != (XWindowInfo *) NULL);
5857 assert(image != (Image *) NULL);
5858 if (image->debug != MagickFalse)
5859 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5860 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005861 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005862 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005863 {
5864 char
5865 size[MaxTextExtent];
5866
5867 Image
5868 *pattern;
5869
5870 ImageInfo
5871 *image_info;
5872
5873 image_info=AcquireImageInfo();
5874 (void) CopyMagickString(image_info->filename,
5875 resource_info->image_info->texture != (char *) NULL ?
5876 resource_info->image_info->texture : "pattern:checkerboard",
5877 MaxTextExtent);
cristye8c25f92010-06-03 00:53:06 +00005878 (void) FormatMagickString(size,MaxTextExtent,"%.20gx%.20g",(double)
5879 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005880 image_info->size=ConstantString(size);
5881 pattern=ReadImage(image_info,&image->exception);
5882 image_info=DestroyImageInfo(image_info);
5883 if (pattern != (Image *) NULL)
5884 {
5885 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5886 if (canvas != (Image *) NULL)
5887 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5888 pattern=DestroyImage(pattern);
5889 }
5890 }
5891 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5892 ximage->bits_per_pixel) >> 3));
5893 map_info=window->map_info;
5894 pixels=window->pixel_info->pixels;
5895 q=(unsigned char *) ximage->data;
5896 x=0;
cristyc57f6942010-11-12 01:47:39 +00005897 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005898 if (ximage->format == XYBitmap)
5899 {
5900 register unsigned short
5901 polarity;
5902
5903 unsigned char
5904 background,
5905 foreground;
5906
5907 /*
5908 Convert canvas to big-endian bitmap.
5909 */
5910 background=(unsigned char)
5911 (XPixelIntensity(&window->pixel_info->foreground_color) <
5912 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5913 foreground=(unsigned char)
5914 (XPixelIntensity(&window->pixel_info->background_color) <
5915 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5916 polarity=(unsigned short) ((PixelIntensityToQuantum(
5917 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5918 if (canvas->colors == 2)
5919 polarity=PixelIntensity(&canvas->colormap[0]) <
5920 PixelIntensity(&canvas->colormap[1]);
5921 for (y=0; y < (int) canvas->rows; y++)
5922 {
cristyc57f6942010-11-12 01:47:39 +00005923 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5924 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00005925 if (p == (const PixelPacket *) NULL)
5926 break;
cristyc57f6942010-11-12 01:47:39 +00005927 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00005928 bit=0;
5929 byte=0;
5930 for (x=0; x < (int) canvas->columns; x++)
5931 {
5932 byte>>=1;
5933 if (indexes[x] == (IndexPacket) polarity)
5934 byte|=foreground;
5935 else
5936 byte|=background;
5937 bit++;
5938 if (bit == 8)
5939 {
5940 *q++=byte;
5941 bit=0;
5942 byte=0;
5943 }
5944 }
5945 if (bit != 0)
5946 *q=byte >> (8-bit);
5947 q+=scanline_pad;
5948 }
5949 }
5950 else
5951 if (window->pixel_info->colors != 0)
5952 switch (ximage->bits_per_pixel)
5953 {
5954 case 2:
5955 {
5956 register unsigned int
5957 nibble;
5958
5959 /*
5960 Convert to 2 bit color-mapped X canvas.
5961 */
5962 for (y=0; y < (int) canvas->rows; y++)
5963 {
cristyc57f6942010-11-12 01:47:39 +00005964 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5965 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00005966 if (p == (const PixelPacket *) NULL)
5967 break;
cristyc57f6942010-11-12 01:47:39 +00005968 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00005969 nibble=0;
5970 for (x=0; x < (int) canvas->columns; x++)
5971 {
cristybb503372010-05-27 20:51:26 +00005972 pixel=pixels[(ssize_t) indexes[x]] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00005973 switch (nibble)
5974 {
5975 case 0:
5976 {
5977 *q=(unsigned char) pixel;
5978 nibble++;
5979 break;
5980 }
5981 case 1:
5982 {
5983 *q|=(unsigned char) (pixel << 2);
5984 nibble++;
5985 break;
5986 }
5987 case 2:
5988 {
5989 *q|=(unsigned char) (pixel << 4);
5990 nibble++;
5991 break;
5992 }
5993 case 3:
5994 {
5995 *q|=(unsigned char) (pixel << 6);
5996 q++;
5997 nibble=0;
5998 break;
5999 }
6000 }
6001 }
6002 q+=scanline_pad;
6003 }
6004 break;
6005 }
6006 case 4:
6007 {
6008 register unsigned int
6009 nibble;
6010
6011 /*
6012 Convert to 4 bit color-mapped X canvas.
6013 */
6014 for (y=0; y < (int) canvas->rows; y++)
6015 {
cristyc57f6942010-11-12 01:47:39 +00006016 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6017 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006018 if (p == (const PixelPacket *) NULL)
6019 break;
cristyc57f6942010-11-12 01:47:39 +00006020 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006021 nibble=0;
6022 for (x=0; x < (int) canvas->columns; x++)
6023 {
cristybb503372010-05-27 20:51:26 +00006024 pixel=pixels[(ssize_t) indexes[x]] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006025 switch (nibble)
6026 {
6027 case 0:
6028 {
6029 *q=(unsigned char) pixel;
6030 nibble++;
6031 break;
6032 }
6033 case 1:
6034 {
6035 *q|=(unsigned char) (pixel << 4);
6036 q++;
6037 nibble=0;
6038 break;
6039 }
6040 }
6041 }
6042 q+=scanline_pad;
6043 }
6044 break;
6045 }
6046 case 6:
6047 case 8:
6048 {
6049 /*
6050 Convert to 8 bit color-mapped X canvas.
6051 */
6052 if (resource_info->color_recovery &&
6053 resource_info->quantize_info->dither)
6054 {
6055 XDitherImage(canvas,ximage);
6056 break;
6057 }
6058 for (y=0; y < (int) canvas->rows; y++)
6059 {
cristyc57f6942010-11-12 01:47:39 +00006060 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6061 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006062 if (p == (const PixelPacket *) NULL)
6063 break;
cristyc57f6942010-11-12 01:47:39 +00006064 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006065 for (x=0; x < (int) canvas->columns; x++)
6066 {
cristybb503372010-05-27 20:51:26 +00006067 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006068 *q++=(unsigned char) pixel;
6069 }
6070 q+=scanline_pad;
6071 }
6072 break;
6073 }
6074 default:
6075 {
6076 register int
6077 k;
6078
6079 register unsigned int
6080 bytes_per_pixel;
6081
6082 unsigned char
cristybb503372010-05-27 20:51:26 +00006083 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006084
6085 /*
6086 Convert to multi-byte color-mapped X canvas.
6087 */
6088 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6089 for (y=0; y < (int) canvas->rows; y++)
6090 {
cristyc57f6942010-11-12 01:47:39 +00006091 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6092 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006093 if (p == (const PixelPacket *) NULL)
6094 break;
cristyc57f6942010-11-12 01:47:39 +00006095 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006096 for (x=0; x < (int) canvas->columns; x++)
6097 {
cristybb503372010-05-27 20:51:26 +00006098 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006099 for (k=0; k < (int) bytes_per_pixel; k++)
6100 {
6101 channel[k]=(unsigned char) pixel;
6102 pixel>>=8;
6103 }
6104 for (k=0; k < (int) bytes_per_pixel; k++)
6105 *q++=channel[k];
6106 }
6107 q+=scanline_pad;
6108 }
6109 break;
6110 }
6111 }
6112 else
6113 switch (ximage->bits_per_pixel)
6114 {
6115 case 2:
6116 {
6117 register unsigned int
6118 nibble;
6119
6120 /*
6121 Convert to contiguous 2 bit continuous-tone X canvas.
6122 */
6123 for (y=0; y < (int) canvas->rows; y++)
6124 {
6125 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006126 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6127 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006128 if (p == (const PixelPacket *) NULL)
6129 break;
6130 for (x=0; x < (int) canvas->columns; x++)
6131 {
6132 pixel=XGammaPixel(map_info,p);
6133 pixel&=0xf;
6134 switch (nibble)
6135 {
6136 case 0:
6137 {
6138 *q=(unsigned char) pixel;
6139 nibble++;
6140 break;
6141 }
6142 case 1:
6143 {
6144 *q|=(unsigned char) (pixel << 2);
6145 nibble++;
6146 break;
6147 }
6148 case 2:
6149 {
6150 *q|=(unsigned char) (pixel << 4);
6151 nibble++;
6152 break;
6153 }
6154 case 3:
6155 {
6156 *q|=(unsigned char) (pixel << 6);
6157 q++;
6158 nibble=0;
6159 break;
6160 }
6161 }
6162 p++;
6163 }
6164 q+=scanline_pad;
6165 }
6166 break;
6167 }
6168 case 4:
6169 {
6170 register unsigned int
6171 nibble;
6172
6173 /*
6174 Convert to contiguous 4 bit continuous-tone X canvas.
6175 */
6176 for (y=0; y < (int) canvas->rows; y++)
6177 {
cristyc57f6942010-11-12 01:47:39 +00006178 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6179 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006180 if (p == (const PixelPacket *) NULL)
6181 break;
6182 nibble=0;
6183 for (x=0; x < (int) canvas->columns; x++)
6184 {
6185 pixel=XGammaPixel(map_info,p);
6186 pixel&=0xf;
6187 switch (nibble)
6188 {
6189 case 0:
6190 {
6191 *q=(unsigned char) pixel;
6192 nibble++;
6193 break;
6194 }
6195 case 1:
6196 {
6197 *q|=(unsigned char) (pixel << 4);
6198 q++;
6199 nibble=0;
6200 break;
6201 }
6202 }
6203 p++;
6204 }
6205 q+=scanline_pad;
6206 }
6207 break;
6208 }
6209 case 6:
6210 case 8:
6211 {
6212 /*
6213 Convert to contiguous 8 bit continuous-tone X canvas.
6214 */
6215 if (resource_info->color_recovery &&
6216 resource_info->quantize_info->dither)
6217 {
6218 XDitherImage(canvas,ximage);
6219 break;
6220 }
6221 for (y=0; y < (int) canvas->rows; y++)
6222 {
cristyc57f6942010-11-12 01:47:39 +00006223 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6224 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006225 if (p == (const PixelPacket *) NULL)
6226 break;
6227 for (x=0; x < (int) canvas->columns; x++)
6228 {
6229 pixel=XGammaPixel(map_info,p);
6230 *q++=(unsigned char) pixel;
6231 p++;
6232 }
6233 q+=scanline_pad;
6234 }
6235 break;
6236 }
6237 default:
6238 {
6239 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6240 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6241 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6242 (map_info->blue_mult == 1))
6243 {
6244 /*
6245 Convert to 32 bit continuous-tone X canvas.
6246 */
6247 for (y=0; y < (int) canvas->rows; y++)
6248 {
cristyc57f6942010-11-12 01:47:39 +00006249 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6250 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006251 if (p == (const PixelPacket *) NULL)
6252 break;
6253 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6254 (blue_gamma != 1.0))
6255 {
6256 /*
6257 Gamma correct canvas.
6258 */
6259 for (x=(int) canvas->columns-1; x >= 0; x--)
6260 {
cristyccf844f2010-02-03 23:28:16 +00006261 *q++=ScaleQuantumToChar(XBlueGamma(
6262 GetBluePixelComponent(p)));
6263 *q++=ScaleQuantumToChar(XGreenGamma(
6264 GetGreenPixelComponent(p)));
6265 *q++=ScaleQuantumToChar(XRedGamma(
6266 GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006267 *q++=0;
6268 p++;
6269 }
6270 continue;
6271 }
6272 for (x=(int) canvas->columns-1; x >= 0; x--)
6273 {
cristyce70c172010-01-07 17:15:30 +00006274 *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
6275 *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6276 *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006277 *q++=0;
6278 p++;
6279 }
6280 }
6281 }
6282 else
6283 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6284 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6285 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6286 (map_info->blue_mult == 65536L))
6287 {
6288 /*
6289 Convert to 32 bit continuous-tone X canvas.
6290 */
6291 for (y=0; y < (int) canvas->rows; y++)
6292 {
cristyc57f6942010-11-12 01:47:39 +00006293 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6294 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006295 if (p == (const PixelPacket *) NULL)
6296 break;
6297 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6298 (blue_gamma != 1.0))
6299 {
6300 /*
6301 Gamma correct canvas.
6302 */
6303 for (x=(int) canvas->columns-1; x >= 0; x--)
6304 {
cristyccf844f2010-02-03 23:28:16 +00006305 *q++=ScaleQuantumToChar(XRedGamma(
6306 GetRedPixelComponent(p)));
6307 *q++=ScaleQuantumToChar(XGreenGamma(
6308 GetGreenPixelComponent(p)));
6309 *q++=ScaleQuantumToChar(XBlueGamma(
6310 GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006311 *q++=0;
6312 p++;
6313 }
6314 continue;
6315 }
6316 for (x=(int) canvas->columns-1; x >= 0; x--)
6317 {
cristyccf844f2010-02-03 23:28:16 +00006318 *q++=ScaleQuantumToChar((Quantum)
6319 GetRedPixelComponent(p));
6320 *q++=ScaleQuantumToChar((Quantum)
6321 GetGreenPixelComponent(p));
6322 *q++=ScaleQuantumToChar((Quantum)
6323 GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006324 *q++=0;
6325 p++;
6326 }
6327 }
6328 }
6329 else
6330 {
6331 register int
6332 k;
6333
6334 register unsigned int
6335 bytes_per_pixel;
6336
6337 unsigned char
cristybb503372010-05-27 20:51:26 +00006338 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006339
6340 /*
6341 Convert to multi-byte continuous-tone X canvas.
6342 */
6343 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6344 for (y=0; y < (int) canvas->rows; y++)
6345 {
cristyc57f6942010-11-12 01:47:39 +00006346 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6347 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006348 if (p == (PixelPacket *) NULL)
6349 break;
cristyc57f6942010-11-12 01:47:39 +00006350 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006351 {
6352 pixel=XGammaPixel(map_info,p);
6353 for (k=0; k < (int) bytes_per_pixel; k++)
6354 {
6355 channel[k]=(unsigned char) pixel;
6356 pixel>>=8;
6357 }
6358 for (k=0; k < (int) bytes_per_pixel; k++)
6359 *q++=channel[k];
6360 p++;
6361 }
6362 q+=scanline_pad;
6363 }
6364 }
6365 break;
6366 }
6367 }
6368 if (matte_image != (XImage *) NULL)
6369 {
6370 /*
6371 Initialize matte canvas.
6372 */
6373 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6374 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6375 q=(unsigned char *) matte_image->data;
6376 for (y=0; y < (int) canvas->rows; y++)
6377 {
cristyc57f6942010-11-12 01:47:39 +00006378 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6379 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006380 if (p == (const PixelPacket *) NULL)
6381 break;
6382 bit=0;
6383 byte=0;
6384 for (x=(int) canvas->columns-1; x >= 0; x--)
6385 {
6386 byte>>=1;
cristyd05ecd12011-04-22 20:44:42 +00006387 if (GetOpacityPixelComponent(p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006388 byte|=0x80;
6389 bit++;
6390 if (bit == 8)
6391 {
6392 *q++=byte;
6393 bit=0;
6394 byte=0;
6395 }
6396 p++;
6397 }
6398 if (bit != 0)
6399 *q=byte >> (8-bit);
6400 q+=scanline_pad;
6401 }
6402 }
cristyc57f6942010-11-12 01:47:39 +00006403 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006404 if (canvas != image)
6405 canvas=DestroyImage(canvas);
6406}
6407
6408/*
6409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6410% %
6411% %
6412% %
6413+ X M a k e I m a g e M S B F i r s t %
6414% %
6415% %
6416% %
6417%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6418%
6419% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6420% image pixels are copied in most-significant bit and byte first order. The
6421% server's scanline pad is also respected. Rather than using one or two
6422% general cases, many special cases are found here to help speed up the image
6423% conversion.
6424%
6425% The format of the XMakeImageMSBFirst method is:
6426%
6427% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6428%
6429% A description of each parameter follows:
6430%
6431% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6432%
6433% o window: Specifies a pointer to a XWindowInfo structure.
6434%
6435% o image: the image.
6436%
6437% o ximage: Specifies a pointer to a XImage structure; returned from
6438% XCreateImage.
6439%
6440% o matte_image: Specifies a pointer to a XImage structure; returned from
6441% XCreateImage.
6442%
cristy3ed852e2009-09-05 21:47:34 +00006443*/
6444static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6445 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6446{
cristyc57f6942010-11-12 01:47:39 +00006447 CacheView
6448 *canvas_view;
6449
cristy3ed852e2009-09-05 21:47:34 +00006450 Image
6451 *canvas;
6452
6453 int
6454 y;
6455
6456 register int
6457 x;
6458
6459 register const IndexPacket
6460 *indexes;
6461
6462 register const PixelPacket
6463 *p;
6464
6465 register unsigned char
6466 *q;
6467
6468 unsigned char
6469 bit,
6470 byte;
6471
6472 unsigned int
6473 scanline_pad;
6474
cristyf2faecf2010-05-28 19:19:36 +00006475 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006476 pixel,
6477 *pixels;
6478
6479 XStandardColormap
6480 *map_info;
6481
6482 assert(resource_info != (XResourceInfo *) NULL);
6483 assert(window != (XWindowInfo *) NULL);
6484 assert(image != (Image *) NULL);
6485 if (image->debug != MagickFalse)
6486 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6487 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006488 if ((window->immutable != MagickFalse) &&
6489 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006490 {
6491 char
6492 size[MaxTextExtent];
6493
6494 Image
6495 *pattern;
6496
6497 ImageInfo
6498 *image_info;
6499
6500 image_info=AcquireImageInfo();
6501 (void) CopyMagickString(image_info->filename,
6502 resource_info->image_info->texture != (char *) NULL ?
6503 resource_info->image_info->texture : "pattern:checkerboard",
6504 MaxTextExtent);
cristye8c25f92010-06-03 00:53:06 +00006505 (void) FormatMagickString(size,MaxTextExtent,"%.20gx%.20g",(double)
6506 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006507 image_info->size=ConstantString(size);
6508 pattern=ReadImage(image_info,&image->exception);
6509 image_info=DestroyImageInfo(image_info);
6510 if (pattern != (Image *) NULL)
6511 {
6512 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6513 if (canvas != (Image *) NULL)
6514 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6515 pattern=DestroyImage(pattern);
6516 }
6517 }
6518 scanline_pad=(unsigned int) (ximage->bytes_per_line-
6519 ((ximage->width*ximage->bits_per_pixel) >> 3));
6520 map_info=window->map_info;
6521 pixels=window->pixel_info->pixels;
6522 q=(unsigned char *) ximage->data;
6523 x=0;
cristyc57f6942010-11-12 01:47:39 +00006524 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006525 if (ximage->format == XYBitmap)
6526 {
6527 register unsigned short
6528 polarity;
6529
6530 unsigned char
6531 background,
6532 foreground;
6533
6534 /*
6535 Convert canvas to big-endian bitmap.
6536 */
6537 background=(unsigned char)
6538 (XPixelIntensity(&window->pixel_info->foreground_color) <
6539 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6540 foreground=(unsigned char)
6541 (XPixelIntensity(&window->pixel_info->background_color) <
6542 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
6543 polarity=(unsigned short) ((PixelIntensityToQuantum(
6544 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6545 if (canvas->colors == 2)
6546 polarity=PixelIntensity(&canvas->colormap[0]) <
6547 PixelIntensity(&canvas->colormap[1]);
6548 for (y=0; y < (int) canvas->rows; y++)
6549 {
cristyc57f6942010-11-12 01:47:39 +00006550 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6551 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006552 if (p == (const PixelPacket *) NULL)
6553 break;
cristyc57f6942010-11-12 01:47:39 +00006554 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006555 bit=0;
6556 byte=0;
6557 for (x=(int) canvas->columns-1; x >= 0; x--)
6558 {
6559 byte<<=1;
6560 if (indexes[x] == (IndexPacket) polarity)
6561 byte|=foreground;
6562 else
6563 byte|=background;
6564 bit++;
6565 if (bit == 8)
6566 {
6567 *q++=byte;
6568 bit=0;
6569 byte=0;
6570 }
6571 }
6572 if (bit != 0)
6573 *q=byte << (8-bit);
6574 q+=scanline_pad;
6575 }
6576 }
6577 else
6578 if (window->pixel_info->colors != 0)
6579 switch (ximage->bits_per_pixel)
6580 {
6581 case 2:
6582 {
6583 register unsigned int
6584 nibble;
6585
6586 /*
6587 Convert to 2 bit color-mapped X canvas.
6588 */
6589 for (y=0; y < (int) canvas->rows; y++)
6590 {
cristyc57f6942010-11-12 01:47:39 +00006591 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6592 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006593 if (p == (const PixelPacket *) NULL)
6594 break;
cristyc57f6942010-11-12 01:47:39 +00006595 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006596 nibble=0;
6597 for (x=0; x < (int) canvas->columns; x++)
6598 {
cristybb503372010-05-27 20:51:26 +00006599 pixel=pixels[(ssize_t) indexes[x]] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006600 switch (nibble)
6601 {
6602 case 0:
6603 {
6604 *q=(unsigned char) (pixel << 6);
6605 nibble++;
6606 break;
6607 }
6608 case 1:
6609 {
6610 *q|=(unsigned char) (pixel << 4);
6611 nibble++;
6612 break;
6613 }
6614 case 2:
6615 {
6616 *q|=(unsigned char) (pixel << 2);
6617 nibble++;
6618 break;
6619 }
6620 case 3:
6621 {
6622 *q|=(unsigned char) pixel;
6623 q++;
6624 nibble=0;
6625 break;
6626 }
6627 }
6628 }
6629 q+=scanline_pad;
6630 }
6631 break;
6632 }
6633 case 4:
6634 {
6635 register unsigned int
6636 nibble;
6637
6638 /*
6639 Convert to 4 bit color-mapped X canvas.
6640 */
6641 for (y=0; y < (int) canvas->rows; y++)
6642 {
cristyc57f6942010-11-12 01:47:39 +00006643 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6644 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006645 if (p == (const PixelPacket *) NULL)
6646 break;
cristyc57f6942010-11-12 01:47:39 +00006647 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006648 nibble=0;
6649 for (x=0; x < (int) canvas->columns; x++)
6650 {
cristybb503372010-05-27 20:51:26 +00006651 pixel=pixels[(ssize_t) indexes[x]] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006652 switch (nibble)
6653 {
6654 case 0:
6655 {
6656 *q=(unsigned char) (pixel << 4);
6657 nibble++;
6658 break;
6659 }
6660 case 1:
6661 {
6662 *q|=(unsigned char) pixel;
6663 q++;
6664 nibble=0;
6665 break;
6666 }
6667 }
6668 }
6669 q+=scanline_pad;
6670 }
6671 break;
6672 }
6673 case 6:
6674 case 8:
6675 {
6676 /*
6677 Convert to 8 bit color-mapped X canvas.
6678 */
6679 if (resource_info->color_recovery &&
6680 resource_info->quantize_info->dither)
6681 {
6682 XDitherImage(canvas,ximage);
6683 break;
6684 }
6685 for (y=0; y < (int) canvas->rows; y++)
6686 {
cristyc57f6942010-11-12 01:47:39 +00006687 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6688 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006689 if (p == (const PixelPacket *) NULL)
6690 break;
cristyc57f6942010-11-12 01:47:39 +00006691 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006692 for (x=0; x < (int) canvas->columns; x++)
6693 {
cristybb503372010-05-27 20:51:26 +00006694 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006695 *q++=(unsigned char) pixel;
6696 }
6697 q+=scanline_pad;
6698 }
6699 break;
6700 }
6701 default:
6702 {
6703 register int
6704 k;
6705
6706 register unsigned int
6707 bytes_per_pixel;
6708
6709 unsigned char
cristybb503372010-05-27 20:51:26 +00006710 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006711
6712 /*
6713 Convert to 8 bit color-mapped X canvas.
6714 */
6715 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6716 for (y=0; y < (int) canvas->rows; y++)
6717 {
cristyc57f6942010-11-12 01:47:39 +00006718 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6719 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006720 if (p == (const PixelPacket *) NULL)
6721 break;
cristyc57f6942010-11-12 01:47:39 +00006722 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006723 for (x=0; x < (int) canvas->columns; x++)
6724 {
cristybb503372010-05-27 20:51:26 +00006725 pixel=pixels[(ssize_t) indexes[x]];
cristy3ed852e2009-09-05 21:47:34 +00006726 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6727 {
6728 channel[k]=(unsigned char) pixel;
6729 pixel>>=8;
6730 }
6731 for (k=0; k < (int) bytes_per_pixel; k++)
6732 *q++=channel[k];
6733 }
6734 q+=scanline_pad;
6735 }
6736 break;
6737 }
6738 }
6739 else
6740 switch (ximage->bits_per_pixel)
6741 {
6742 case 2:
6743 {
6744 register unsigned int
6745 nibble;
6746
6747 /*
6748 Convert to 4 bit continuous-tone X canvas.
6749 */
6750 for (y=0; y < (int) canvas->rows; y++)
6751 {
cristyc57f6942010-11-12 01:47:39 +00006752 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6753 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006754 if (p == (const PixelPacket *) NULL)
6755 break;
6756 nibble=0;
6757 for (x=(int) canvas->columns-1; x >= 0; x--)
6758 {
6759 pixel=XGammaPixel(map_info,p);
6760 pixel&=0xf;
6761 switch (nibble)
6762 {
6763 case 0:
6764 {
6765 *q=(unsigned char) (pixel << 6);
6766 nibble++;
6767 break;
6768 }
6769 case 1:
6770 {
6771 *q|=(unsigned char) (pixel << 4);
6772 nibble++;
6773 break;
6774 }
6775 case 2:
6776 {
6777 *q|=(unsigned char) (pixel << 2);
6778 nibble++;
6779 break;
6780 }
6781 case 3:
6782 {
6783 *q|=(unsigned char) pixel;
6784 q++;
6785 nibble=0;
6786 break;
6787 }
6788 }
6789 p++;
6790 }
6791 q+=scanline_pad;
6792 }
6793 break;
6794 }
6795 case 4:
6796 {
6797 register unsigned int
6798 nibble;
6799
6800 /*
6801 Convert to 4 bit continuous-tone X canvas.
6802 */
6803 for (y=0; y < (int) canvas->rows; y++)
6804 {
cristyc57f6942010-11-12 01:47:39 +00006805 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6806 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006807 if (p == (const PixelPacket *) NULL)
6808 break;
6809 nibble=0;
6810 for (x=(int) canvas->columns-1; x >= 0; x--)
6811 {
6812 pixel=XGammaPixel(map_info,p);
6813 pixel&=0xf;
6814 switch (nibble)
6815 {
6816 case 0:
6817 {
6818 *q=(unsigned char) (pixel << 4);
6819 nibble++;
6820 break;
6821 }
6822 case 1:
6823 {
6824 *q|=(unsigned char) pixel;
6825 q++;
6826 nibble=0;
6827 break;
6828 }
6829 }
6830 p++;
6831 }
6832 q+=scanline_pad;
6833 }
6834 break;
6835 }
6836 case 6:
6837 case 8:
6838 {
6839 /*
6840 Convert to 8 bit continuous-tone X canvas.
6841 */
6842 if (resource_info->color_recovery &&
6843 resource_info->quantize_info->dither)
6844 {
6845 XDitherImage(canvas,ximage);
6846 break;
6847 }
6848 for (y=0; y < (int) canvas->rows; y++)
6849 {
cristyc57f6942010-11-12 01:47:39 +00006850 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6851 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006852 if (p == (const PixelPacket *) NULL)
6853 break;
6854 for (x=(int) canvas->columns-1; x >= 0; x--)
6855 {
6856 pixel=XGammaPixel(map_info,p);
6857 *q++=(unsigned char) pixel;
6858 p++;
6859 }
6860 q+=scanline_pad;
6861 }
6862 break;
6863 }
6864 default:
6865 {
6866 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6867 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6868 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6869 (map_info->blue_mult == 1))
6870 {
6871 /*
6872 Convert to 32 bit continuous-tone X canvas.
6873 */
6874 for (y=0; y < (int) canvas->rows; y++)
6875 {
cristyc57f6942010-11-12 01:47:39 +00006876 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6877 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006878 if (p == (const PixelPacket *) NULL)
6879 break;
6880 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6881 (blue_gamma != 1.0))
6882 {
6883 /*
6884 Gamma correct canvas.
6885 */
6886 for (x=(int) canvas->columns-1; x >= 0; x--)
6887 {
6888 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006889 *q++=ScaleQuantumToChar(XRedGamma(
6890 GetRedPixelComponent(p)));
6891 *q++=ScaleQuantumToChar(XGreenGamma(
6892 GetGreenPixelComponent(p)));
6893 *q++=ScaleQuantumToChar(XBlueGamma(
6894 GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006895 p++;
6896 }
6897 continue;
6898 }
6899 for (x=(int) canvas->columns-1; x >= 0; x--)
6900 {
6901 *q++=0;
cristyce70c172010-01-07 17:15:30 +00006902 *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
6903 *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6904 *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006905 p++;
6906 }
6907 }
6908 }
6909 else
6910 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6911 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6912 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6913 (map_info->blue_mult == 65536L))
6914 {
6915 /*
6916 Convert to 32 bit continuous-tone X canvas.
6917 */
6918 for (y=0; y < (int) canvas->rows; y++)
6919 {
cristyc57f6942010-11-12 01:47:39 +00006920 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6921 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006922 if (p == (const PixelPacket *) NULL)
6923 break;
6924 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6925 (blue_gamma != 1.0))
6926 {
6927 /*
6928 Gamma correct canvas.
6929 */
6930 for (x=(int) canvas->columns-1; x >= 0; x--)
6931 {
6932 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006933 *q++=ScaleQuantumToChar(XBlueGamma(
6934 GetBluePixelComponent(p)));
6935 *q++=ScaleQuantumToChar(XGreenGamma(
6936 GetGreenPixelComponent(p)));
6937 *q++=ScaleQuantumToChar(XRedGamma(
6938 GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006939 p++;
6940 }
6941 continue;
6942 }
6943 for (x=(int) canvas->columns-1; x >= 0; x--)
6944 {
6945 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006946 *q++=ScaleQuantumToChar((Quantum)
6947 GetBluePixelComponent(p));
6948 *q++=ScaleQuantumToChar((Quantum)
6949 GetGreenPixelComponent(p));
6950 *q++=ScaleQuantumToChar((Quantum)
6951 GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006952 p++;
6953 }
6954 }
6955 }
6956 else
6957 {
6958 register int
6959 k;
6960
6961 register unsigned int
6962 bytes_per_pixel;
6963
6964 unsigned char
cristybb503372010-05-27 20:51:26 +00006965 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006966
6967 /*
6968 Convert to multi-byte continuous-tone X canvas.
6969 */
6970 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6971 for (y=0; y < (int) canvas->rows; y++)
6972 {
cristyc57f6942010-11-12 01:47:39 +00006973 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6974 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006975 if (p == (const PixelPacket *) NULL)
6976 break;
6977 for (x=(int) canvas->columns-1; x >= 0; x--)
6978 {
6979 pixel=XGammaPixel(map_info,p);
6980 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6981 {
6982 channel[k]=(unsigned char) pixel;
6983 pixel>>=8;
6984 }
6985 for (k=0; k < (int) bytes_per_pixel; k++)
6986 *q++=channel[k];
6987 p++;
6988 }
6989 q+=scanline_pad;
6990 }
6991 }
6992 break;
6993 }
6994 }
6995 if (matte_image != (XImage *) NULL)
6996 {
6997 /*
6998 Initialize matte canvas.
6999 */
7000 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7001 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7002 q=(unsigned char *) matte_image->data;
7003 for (y=0; y < (int) canvas->rows; y++)
7004 {
cristyc57f6942010-11-12 01:47:39 +00007005 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7006 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00007007 if (p == (const PixelPacket *) NULL)
7008 break;
7009 bit=0;
7010 byte=0;
7011 for (x=(int) canvas->columns-1; x >= 0; x--)
7012 {
7013 byte<<=1;
cristyd05ecd12011-04-22 20:44:42 +00007014 if (GetOpacityPixelComponent(p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007015 byte|=0x01;
7016 bit++;
7017 if (bit == 8)
7018 {
7019 *q++=byte;
7020 bit=0;
7021 byte=0;
7022 }
7023 p++;
7024 }
7025 if (bit != 0)
7026 *q=byte << (8-bit);
7027 q+=scanline_pad;
7028 }
7029 }
cristyc57f6942010-11-12 01:47:39 +00007030 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007031 if (canvas != image)
7032 canvas=DestroyImage(canvas);
7033}
7034
7035/*
7036%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7037% %
7038% %
7039% %
7040% X M a k e M a g n i f y I m a g e %
7041% %
7042% %
7043% %
7044%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7045%
7046% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7047%
7048% The format of the XMakeMagnifyImage method is:
7049%
7050% void XMakeMagnifyImage(display,windows)
7051%
7052% A description of each parameter follows:
7053%
7054% o display: Specifies a connection to an X server; returned from
7055% XOpenDisplay.
7056%
7057% o windows: Specifies a pointer to a XWindows structure.
7058%
7059*/
7060MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
7061{
7062 char
7063 tuple[MaxTextExtent];
7064
7065 int
7066 y;
7067
cristy3ed852e2009-09-05 21:47:34 +00007068 MagickPixelPacket
7069 pixel;
7070
7071 register int
7072 x;
7073
cristybb503372010-05-27 20:51:26 +00007074 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007075 i;
7076
7077 register unsigned char
7078 *p,
7079 *q;
7080
cristy9d314ff2011-03-09 01:30:28 +00007081 ssize_t
7082 n;
7083
cristy3ed852e2009-09-05 21:47:34 +00007084 static unsigned int
7085 previous_magnify = 0;
7086
7087 static XWindowInfo
7088 magnify_window;
7089
7090 unsigned int
7091 height,
7092 j,
7093 k,
7094 l,
7095 magnify,
7096 scanline_pad,
7097 width;
7098
7099 XImage
7100 *ximage;
7101
7102 /*
7103 Check boundary conditions.
7104 */
7105 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7106 assert(display != (Display *) NULL);
7107 assert(windows != (XWindows *) NULL);
7108 magnify=1;
cristybb503372010-05-27 20:51:26 +00007109 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007110 magnify<<=1;
7111 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7112 magnify<<=1;
7113 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7114 magnify<<=1;
7115 while (magnify > windows->magnify.width)
7116 magnify>>=1;
7117 while (magnify > windows->magnify.height)
7118 magnify>>=1;
7119 if (magnify != previous_magnify)
7120 {
7121 Status
7122 status;
7123
7124 XTextProperty
7125 window_name;
7126
7127 /*
7128 New magnify factor: update magnify window name.
7129 */
7130 i=0;
7131 while ((1 << i) <= (int) magnify)
7132 i++;
7133 (void) FormatMagickString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007134 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007135 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7136 if (status != False)
7137 {
7138 XSetWMName(display,windows->magnify.id,&window_name);
7139 XSetWMIconName(display,windows->magnify.id,&window_name);
7140 (void) XFree((void *) window_name.value);
7141 }
7142 }
7143 previous_magnify=magnify;
7144 ximage=windows->image.ximage;
7145 width=(unsigned int) windows->magnify.ximage->width;
7146 height=(unsigned int) windows->magnify.ximage->height;
7147 if ((windows->magnify.x < 0) ||
7148 (windows->magnify.x >= windows->image.ximage->width))
7149 windows->magnify.x=windows->image.ximage->width >> 1;
7150 x=windows->magnify.x-((width/magnify) >> 1);
7151 if (x < 0)
7152 x=0;
7153 else
7154 if (x > (int) (ximage->width-(width/magnify)))
7155 x=ximage->width-width/magnify;
7156 if ((windows->magnify.y < 0) ||
7157 (windows->magnify.y >= windows->image.ximage->height))
7158 windows->magnify.y=windows->image.ximage->height >> 1;
7159 y=windows->magnify.y-((height/magnify) >> 1);
7160 if (y < 0)
7161 y=0;
7162 else
7163 if (y > (int) (ximage->height-(height/magnify)))
7164 y=ximage->height-height/magnify;
7165 q=(unsigned char *) windows->magnify.ximage->data;
7166 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7167 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7168 if (ximage->bits_per_pixel < 8)
7169 {
7170 register unsigned char
7171 background,
7172 byte,
7173 foreground,
7174 p_bit,
7175 q_bit;
7176
7177 register unsigned int
7178 plane;
7179
7180 XPixelInfo
7181 *pixel_info;
7182
7183 pixel_info=windows->magnify.pixel_info;
7184 switch (ximage->bitmap_bit_order)
7185 {
7186 case LSBFirst:
7187 {
7188 /*
7189 Magnify little-endian bitmap.
7190 */
7191 background=0x00;
7192 foreground=0x80;
7193 if (ximage->format == XYBitmap)
7194 {
7195 background=(unsigned char)
7196 (XPixelIntensity(&pixel_info->foreground_color) <
7197 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7198 foreground=(unsigned char)
7199 (XPixelIntensity(&pixel_info->background_color) <
7200 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7201 if (windows->magnify.depth > 1)
7202 Swap(background,foreground);
7203 }
cristybb503372010-05-27 20:51:26 +00007204 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007205 {
7206 /*
7207 Propogate pixel magnify rows.
7208 */
7209 for (j=0; j < magnify; j++)
7210 {
7211 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7212 ((x*ximage->bits_per_pixel) >> 3);
7213 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7214 q_bit=0;
7215 byte=0;
7216 for (k=0; k < width; k+=magnify)
7217 {
7218 /*
7219 Propogate pixel magnify columns.
7220 */
7221 for (l=0; l < magnify; l++)
7222 {
7223 /*
7224 Propogate each bit plane.
7225 */
7226 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7227 {
7228 byte>>=1;
7229 if (*p & (0x01 << (p_bit+plane)))
7230 byte|=foreground;
7231 else
7232 byte|=background;
7233 q_bit++;
7234 if (q_bit == 8)
7235 {
7236 *q++=byte;
7237 q_bit=0;
7238 byte=0;
7239 }
7240 }
7241 }
7242 p_bit+=ximage->bits_per_pixel;
7243 if (p_bit == 8)
7244 {
7245 p++;
7246 p_bit=0;
7247 }
7248 if (q_bit != 0)
7249 *q=byte >> (8-q_bit);
7250 q+=scanline_pad;
7251 }
7252 }
7253 y++;
7254 }
7255 break;
7256 }
7257 case MSBFirst:
7258 default:
7259 {
7260 /*
7261 Magnify big-endian bitmap.
7262 */
7263 background=0x00;
7264 foreground=0x01;
7265 if (ximage->format == XYBitmap)
7266 {
7267 background=(unsigned char)
7268 (XPixelIntensity(&pixel_info->foreground_color) <
7269 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7270 foreground=(unsigned char)
7271 (XPixelIntensity(&pixel_info->background_color) <
7272 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7273 if (windows->magnify.depth > 1)
7274 Swap(background,foreground);
7275 }
cristybb503372010-05-27 20:51:26 +00007276 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007277 {
7278 /*
7279 Propogate pixel magnify rows.
7280 */
7281 for (j=0; j < magnify; j++)
7282 {
7283 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7284 ((x*ximage->bits_per_pixel) >> 3);
7285 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7286 q_bit=0;
7287 byte=0;
7288 for (k=0; k < width; k+=magnify)
7289 {
7290 /*
7291 Propogate pixel magnify columns.
7292 */
7293 for (l=0; l < magnify; l++)
7294 {
7295 /*
7296 Propogate each bit plane.
7297 */
7298 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7299 {
7300 byte<<=1;
7301 if (*p & (0x80 >> (p_bit+plane)))
7302 byte|=foreground;
7303 else
7304 byte|=background;
7305 q_bit++;
7306 if (q_bit == 8)
7307 {
7308 *q++=byte;
7309 q_bit=0;
7310 byte=0;
7311 }
7312 }
7313 }
7314 p_bit+=ximage->bits_per_pixel;
7315 if (p_bit == 8)
7316 {
7317 p++;
7318 p_bit=0;
7319 }
7320 if (q_bit != 0)
7321 *q=byte << (8-q_bit);
7322 q+=scanline_pad;
7323 }
7324 }
7325 y++;
7326 }
7327 break;
7328 }
7329 }
7330 }
7331 else
7332 switch (ximage->bits_per_pixel)
7333 {
7334 case 6:
7335 case 8:
7336 {
7337 /*
7338 Magnify 8 bit X image.
7339 */
cristybb503372010-05-27 20:51:26 +00007340 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007341 {
7342 /*
7343 Propogate pixel magnify rows.
7344 */
7345 for (j=0; j < magnify; j++)
7346 {
7347 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7348 ((x*ximage->bits_per_pixel) >> 3);
7349 for (k=0; k < width; k+=magnify)
7350 {
7351 /*
7352 Propogate pixel magnify columns.
7353 */
7354 for (l=0; l < magnify; l++)
7355 *q++=(*p);
7356 p++;
7357 }
7358 q+=scanline_pad;
7359 }
7360 y++;
7361 }
7362 break;
7363 }
7364 default:
7365 {
7366 register unsigned int
7367 bytes_per_pixel,
7368 m;
7369
7370 /*
7371 Magnify multi-byte X image.
7372 */
7373 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007374 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007375 {
7376 /*
7377 Propogate pixel magnify rows.
7378 */
7379 for (j=0; j < magnify; j++)
7380 {
7381 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7382 ((x*ximage->bits_per_pixel) >> 3);
7383 for (k=0; k < width; k+=magnify)
7384 {
7385 /*
7386 Propogate pixel magnify columns.
7387 */
7388 for (l=0; l < magnify; l++)
7389 for (m=0; m < bytes_per_pixel; m++)
7390 *q++=(*(p+m));
7391 p+=bytes_per_pixel;
7392 }
7393 q+=scanline_pad;
7394 }
7395 y++;
7396 }
7397 break;
7398 }
7399 }
7400 /*
7401 Copy X image to magnify pixmap.
7402 */
7403 x=windows->magnify.x-((width/magnify) >> 1);
7404 if (x < 0)
7405 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7406 else
7407 if (x > (int) (ximage->width-(width/magnify)))
7408 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7409 else
7410 x=0;
7411 y=windows->magnify.y-((height/magnify) >> 1);
7412 if (y < 0)
7413 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7414 else
7415 if (y > (int) (ximage->height-(height/magnify)))
7416 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7417 else
7418 y=0;
7419 if ((x != 0) || (y != 0))
7420 (void) XFillRectangle(display,windows->magnify.pixmap,
7421 windows->magnify.annotate_context,0,0,width,height);
7422 (void) XPutImage(display,windows->magnify.pixmap,
7423 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7424 height-y);
7425 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7426 (magnify <= (height >> 1))))
7427 {
7428 RectangleInfo
7429 highlight_info;
7430
7431 /*
7432 Highlight center pixel.
7433 */
cristybb503372010-05-27 20:51:26 +00007434 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7435 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007436 highlight_info.width=magnify;
7437 highlight_info.height=magnify;
7438 (void) XDrawRectangle(display,windows->magnify.pixmap,
7439 windows->magnify.highlight_context,(int) highlight_info.x,
7440 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7441 (unsigned int) highlight_info.height-1);
7442 if (magnify > 2)
7443 (void) XDrawRectangle(display,windows->magnify.pixmap,
7444 windows->magnify.annotate_context,(int) highlight_info.x+1,
7445 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7446 (unsigned int) highlight_info.height-3);
7447 }
7448 /*
7449 Show center pixel color.
7450 */
cristyc57f6942010-11-12 01:47:39 +00007451 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7452 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7453 &windows->image.image->exception);
cristy3ed852e2009-09-05 21:47:34 +00007454 (void) FormatMagickString(tuple,MaxTextExtent,"%d,%d: ",
7455 windows->magnify.x,windows->magnify.y);
7456 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7457 ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
7458 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7459 ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
7460 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7461 ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
7462 if (pixel.colorspace == CMYKColorspace)
7463 {
7464 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7465 ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
7466 }
7467 if (pixel.matte != MagickFalse)
7468 {
7469 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7470 ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
7471 }
7472 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7473 height=(unsigned int) windows->magnify.font_info->ascent+
7474 windows->magnify.font_info->descent;
7475 x=windows->magnify.font_info->max_bounds.width >> 1;
7476 y=windows->magnify.font_info->ascent+(height >> 2);
7477 (void) XDrawImageString(display,windows->magnify.pixmap,
7478 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7479 GetColorTuple(&pixel,MagickTrue,tuple);
7480 y+=height;
7481 (void) XDrawImageString(display,windows->magnify.pixmap,
7482 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7483 (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7484 &windows->image.image->exception);
7485 y+=height;
7486 (void) XDrawImageString(display,windows->magnify.pixmap,
7487 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7488 /*
7489 Refresh magnify window.
7490 */
7491 magnify_window=windows->magnify;
7492 magnify_window.x=0;
7493 magnify_window.y=0;
7494 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7495}
7496
7497/*
7498%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7499% %
7500% %
7501% %
7502% X M a k e P i x m a p %
7503% %
7504% %
7505% %
7506%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7507%
7508% XMakePixmap() creates an X11 pixmap.
7509%
7510% The format of the XMakePixmap method is:
7511%
7512% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7513% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7514% XPixelInfo *pixel)
7515%
7516% A description of each parameter follows:
7517%
7518% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7519%
7520% o display: Specifies a connection to an X server; returned from
7521% XOpenDisplay.
7522%
7523% o window: Specifies a pointer to a XWindowInfo structure.
7524%
cristy3ed852e2009-09-05 21:47:34 +00007525*/
7526static MagickBooleanType XMakePixmap(Display *display,
7527 const XResourceInfo *resource_info,XWindowInfo *window)
7528{
7529 unsigned int
7530 height,
7531 width;
7532
7533 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7534 assert(display != (Display *) NULL);
7535 assert(resource_info != (XResourceInfo *) NULL);
7536 assert(window != (XWindowInfo *) NULL);
7537 if (window->pixmap != (Pixmap) NULL)
7538 {
7539 /*
7540 Destroy previous X pixmap.
7541 */
7542 (void) XFreePixmap(display,window->pixmap);
7543 window->pixmap=(Pixmap) NULL;
7544 }
7545 if (window->use_pixmap == MagickFalse)
7546 return(MagickFalse);
7547 if (window->ximage == (XImage *) NULL)
7548 return(MagickFalse);
7549 /*
7550 Display busy cursor.
7551 */
7552 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7553 (void) XFlush(display);
7554 /*
7555 Create pixmap.
7556 */
7557 width=(unsigned int) window->ximage->width;
7558 height=(unsigned int) window->ximage->height;
7559 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7560 if (window->pixmap == (Pixmap) NULL)
7561 {
7562 /*
7563 Unable to allocate pixmap.
7564 */
7565 (void) XCheckDefineCursor(display,window->id,window->cursor);
7566 return(MagickFalse);
7567 }
7568 /*
7569 Copy X image to pixmap.
7570 */
7571#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7572 if (window->shared_memory)
7573 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7574 window->ximage,0,0,0,0,width,height,MagickTrue);
7575#endif
7576 if (window->shared_memory == MagickFalse)
7577 (void) XPutImage(display,window->pixmap,window->annotate_context,
7578 window->ximage,0,0,0,0,width,height);
7579 if (IsEventLogging())
7580 {
7581 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7582 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7583 width,height);
7584 }
7585 /*
7586 Restore cursor.
7587 */
7588 (void) XCheckDefineCursor(display,window->id,window->cursor);
7589 return(MagickTrue);
7590}
7591
7592/*
7593%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7594% %
7595% %
7596% %
7597% X M a k e S t a n d a r d C o l o r m a p %
7598% %
7599% %
7600% %
7601%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7602%
7603% XMakeStandardColormap() creates an X11 Standard Colormap.
7604%
7605% The format of the XMakeStandardColormap method is:
7606%
7607% XMakeStandardColormap(display,visual_info,resource_info,image,
7608% map_info,pixel)
7609%
7610% A description of each parameter follows:
7611%
7612% o display: Specifies a connection to an X server; returned from
7613% XOpenDisplay.
7614%
7615% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7616% returned from XGetVisualInfo.
7617%
7618% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7619%
7620% o image: the image.
7621%
7622% o map_info: If a Standard Colormap type is specified, this structure is
7623% initialized with info from the Standard Colormap.
7624%
7625% o pixel: Specifies a pointer to a XPixelInfo structure.
7626%
cristy3ed852e2009-09-05 21:47:34 +00007627*/
7628
7629#if defined(__cplusplus) || defined(c_plusplus)
7630extern "C" {
7631#endif
7632
7633static inline MagickRealType DiversityPixelIntensity(
7634 const DiversityPacket *pixel)
7635{
7636 MagickRealType
7637 intensity;
7638
7639 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7640 return(intensity);
7641}
7642
7643static int IntensityCompare(const void *x,const void *y)
7644{
7645 DiversityPacket
7646 *color_1,
7647 *color_2;
7648
7649 int
7650 diversity;
7651
7652 color_1=(DiversityPacket *) x;
7653 color_2=(DiversityPacket *) y;
7654 diversity=(int) (DiversityPixelIntensity(color_2)-
7655 DiversityPixelIntensity(color_1));
7656 return(diversity);
7657}
7658
7659static int PopularityCompare(const void *x,const void *y)
7660{
7661 DiversityPacket
7662 *color_1,
7663 *color_2;
7664
7665 color_1=(DiversityPacket *) x;
7666 color_2=(DiversityPacket *) y;
7667 return((int) color_2->count-(int) color_1->count);
7668}
7669
7670#if defined(__cplusplus) || defined(c_plusplus)
7671}
7672#endif
7673
cristybb503372010-05-27 20:51:26 +00007674static inline Quantum ScaleXToQuantum(const size_t x,
7675 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007676{
7677 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7678}
7679
7680MagickExport void XMakeStandardColormap(Display *display,
7681 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7682 XStandardColormap *map_info,XPixelInfo *pixel)
7683{
7684 Colormap
7685 colormap;
7686
7687 ExceptionInfo
7688 *exception;
7689
7690 register IndexPacket
7691 *indexes;
7692
cristybb503372010-05-27 20:51:26 +00007693 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007694 i;
7695
7696 Status
7697 status;
7698
cristybb503372010-05-27 20:51:26 +00007699 size_t
cristy3ed852e2009-09-05 21:47:34 +00007700 number_colors,
7701 retain_colors;
7702
7703 unsigned short
7704 gray_value;
7705
7706 XColor
7707 color,
7708 *colors,
7709 *p;
7710
7711 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7712 assert(display != (Display *) NULL);
7713 assert(visual_info != (XVisualInfo *) NULL);
7714 assert(map_info != (XStandardColormap *) NULL);
7715 assert(resource_info != (XResourceInfo *) NULL);
7716 assert(pixel != (XPixelInfo *) NULL);
7717 exception=(&image->exception);
7718 if (resource_info->map_type != (char *) NULL)
7719 {
7720 /*
7721 Standard Colormap is already defined (i.e. xstdcmap).
7722 */
7723 XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7724 pixel);
7725 number_colors=(unsigned int) (map_info->base_pixel+
7726 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7727 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7728 if ((image->matte == MagickFalse) &&
7729 (resource_info->color_recovery == MagickFalse) &&
7730 resource_info->quantize_info->dither &&
7731 (number_colors < MaxColormapSize))
7732 {
7733 Image
7734 *affinity_image;
7735
7736 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00007737 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007738
7739 /*
7740 Improve image appearance with error diffusion.
7741 */
7742 affinity_image=AcquireImage((ImageInfo *) NULL);
7743 if (affinity_image == (Image *) NULL)
7744 ThrowXWindowFatalException(ResourceLimitFatalError,
7745 "UnableToDitherImage",image->filename);
7746 affinity_image->columns=number_colors;
7747 affinity_image->rows=1;
7748 /*
7749 Initialize colormap image.
7750 */
7751 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7752 1,exception);
7753 if (q != (PixelPacket *) NULL)
7754 {
cristybb503372010-05-27 20:51:26 +00007755 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007756 {
7757 q->red=(Quantum) 0;
7758 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00007759 q->red=ScaleXToQuantum((size_t) (i/
cristy3ed852e2009-09-05 21:47:34 +00007760 map_info->red_mult),map_info->red_max);
7761 q->green=(Quantum) 0;
7762 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00007763 q->green=ScaleXToQuantum((size_t) ((i/
cristy3ed852e2009-09-05 21:47:34 +00007764 map_info->green_mult) % (map_info->green_max+1)),
7765 map_info->green_max);
7766 q->blue=(Quantum) 0;
7767 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00007768 q->blue=ScaleXToQuantum((size_t) (i %
cristy3ed852e2009-09-05 21:47:34 +00007769 map_info->green_mult),map_info->blue_max);
7770 q->opacity=(Quantum) TransparentOpacity;
7771 q++;
7772 }
7773 (void) SyncAuthenticPixels(affinity_image,exception);
7774 (void) RemapImage(resource_info->quantize_info,image,
7775 affinity_image);
7776 }
7777 XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7778 pixel);
7779 (void) SetImageStorageClass(image,DirectClass);
7780 affinity_image=DestroyImage(affinity_image);
7781 }
7782 if (IsEventLogging())
7783 {
7784 (void) LogMagickEvent(X11Event,GetMagickModule(),
7785 "Standard Colormap:");
7786 (void) LogMagickEvent(X11Event,GetMagickModule(),
7787 " colormap id: 0x%lx",map_info->colormap);
7788 (void) LogMagickEvent(X11Event,GetMagickModule(),
7789 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7790 map_info->green_max,map_info->blue_max);
7791 (void) LogMagickEvent(X11Event,GetMagickModule(),
7792 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7793 map_info->green_mult,map_info->blue_mult);
7794 }
7795 return;
7796 }
7797 if ((visual_info->klass != DirectColor) &&
7798 (visual_info->klass != TrueColor))
7799 if ((image->storage_class == DirectClass) ||
7800 ((int) image->colors > visual_info->colormap_size))
7801 {
7802 QuantizeInfo
7803 quantize_info;
7804
7805 /*
7806 Image has more colors than the visual supports.
7807 */
7808 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007809 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00007810 (void) QuantizeImage(&quantize_info,image);
7811 }
7812 /*
7813 Free previous and create new colormap.
7814 */
7815 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7816 colormap=XDefaultColormap(display,visual_info->screen);
7817 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7818 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7819 visual_info->visual,visual_info->klass == DirectColor ?
7820 AllocAll : AllocNone);
7821 if (colormap == (Colormap) NULL)
7822 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7823 image->filename);
7824 /*
7825 Initialize the map and pixel info structures.
7826 */
7827 XGetMapInfo(visual_info,colormap,map_info);
7828 XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
7829 /*
7830 Allocating colors in server colormap is based on visual class.
7831 */
7832 switch (visual_info->klass)
7833 {
7834 case StaticGray:
7835 case StaticColor:
7836 {
7837 /*
7838 Define Standard Colormap for StaticGray or StaticColor visual.
7839 */
7840 number_colors=image->colors;
7841 colors=(XColor *) AcquireQuantumMemory((size_t)
7842 visual_info->colormap_size,sizeof(*colors));
7843 if (colors == (XColor *) NULL)
7844 ThrowXWindowFatalException(ResourceLimitFatalError,
7845 "UnableToCreateColormap",image->filename);
7846 p=colors;
7847 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007848 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007849 {
7850 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7851 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7852 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7853 if (visual_info->klass != StaticColor)
7854 {
7855 gray_value=(unsigned short) XPixelIntensity(&color);
7856 color.red=gray_value;
7857 color.green=gray_value;
7858 color.blue=gray_value;
7859 }
7860 status=XAllocColor(display,colormap,&color);
7861 if (status == False)
7862 {
7863 colormap=XCopyColormapAndFree(display,colormap);
7864 (void) XAllocColor(display,colormap,&color);
7865 }
7866 pixel->pixels[i]=color.pixel;
7867 *p++=color;
7868 }
7869 break;
7870 }
7871 case GrayScale:
7872 case PseudoColor:
7873 {
7874 unsigned int
7875 colormap_type;
7876
7877 /*
7878 Define Standard Colormap for GrayScale or PseudoColor visual.
7879 */
7880 number_colors=image->colors;
7881 colors=(XColor *) AcquireQuantumMemory((size_t)
7882 visual_info->colormap_size,sizeof(*colors));
7883 if (colors == (XColor *) NULL)
7884 ThrowXWindowFatalException(ResourceLimitFatalError,
7885 "UnableToCreateColormap",image->filename);
7886 /*
7887 Preallocate our GUI colors.
7888 */
7889 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7890 (void) XAllocColor(display,colormap,&pixel->background_color);
7891 (void) XAllocColor(display,colormap,&pixel->border_color);
7892 (void) XAllocColor(display,colormap,&pixel->matte_color);
7893 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7894 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7895 (void) XAllocColor(display,colormap,&pixel->depth_color);
7896 (void) XAllocColor(display,colormap,&pixel->trough_color);
7897 for (i=0; i < MaxNumberPens; i++)
7898 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7899 /*
7900 Determine if image colors will "fit" into X server colormap.
7901 */
7902 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007903 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007904 NULL,0,pixel->pixels,(unsigned int) image->colors);
7905 if (status != False)
7906 colormap_type=PrivateColormap;
7907 if (colormap_type == SharedColormap)
7908 {
cristyc57f6942010-11-12 01:47:39 +00007909 CacheView
7910 *image_view;
7911
cristy3ed852e2009-09-05 21:47:34 +00007912 DiversityPacket
7913 *diversity;
7914
7915 int
7916 y;
7917
7918 register int
7919 x;
7920
7921 unsigned short
7922 index;
7923
7924 XColor
7925 *server_colors;
7926
7927 /*
7928 Define Standard colormap for shared GrayScale or PseudoColor visual.
7929 */
7930 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7931 sizeof(*diversity));
7932 if (diversity == (DiversityPacket *) NULL)
7933 ThrowXWindowFatalException(ResourceLimitFatalError,
7934 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007935 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007936 {
7937 diversity[i].red=image->colormap[i].red;
7938 diversity[i].green=image->colormap[i].green;
7939 diversity[i].blue=image->colormap[i].blue;
7940 diversity[i].index=(unsigned short) i;
7941 diversity[i].count=0;
7942 }
cristyc57f6942010-11-12 01:47:39 +00007943 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00007944 for (y=0; y < (int) image->rows; y++)
7945 {
cristyc57f6942010-11-12 01:47:39 +00007946 register int
cristy3ed852e2009-09-05 21:47:34 +00007947 x;
7948
cristyc57f6942010-11-12 01:47:39 +00007949 register const PixelPacket
7950 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007951
cristyc57f6942010-11-12 01:47:39 +00007952 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7953 image->columns,1,exception);
7954 if (p == (const PixelPacket *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007955 break;
cristyc57f6942010-11-12 01:47:39 +00007956 indexes=GetCacheViewAuthenticIndexQueue(image_view);
7957 for (x=(int) image->columns-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00007958 diversity[(ssize_t) indexes[x]].count++;
cristy3ed852e2009-09-05 21:47:34 +00007959 }
cristyc57f6942010-11-12 01:47:39 +00007960 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00007961 /*
7962 Sort colors by decreasing intensity.
7963 */
7964 qsort((void *) diversity,image->colors,sizeof(*diversity),
7965 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00007966 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00007967 {
7968 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00007969 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00007970 }
7971 diversity[image->colors-1].count<<=4;
7972 qsort((void *) diversity,image->colors,sizeof(*diversity),
7973 PopularityCompare);
7974 /*
7975 Allocate colors.
7976 */
7977 p=colors;
7978 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007979 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007980 {
7981 index=diversity[i].index;
7982 color.red=
7983 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7984 color.green=
7985 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7986 color.blue=
7987 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7988 if (visual_info->klass != PseudoColor)
7989 {
7990 gray_value=(unsigned short) XPixelIntensity(&color);
7991 color.red=gray_value;
7992 color.green=gray_value;
7993 color.blue=gray_value;
7994 }
7995 status=XAllocColor(display,colormap,&color);
7996 if (status == False)
7997 break;
7998 pixel->pixels[index]=color.pixel;
7999 *p++=color;
8000 }
8001 /*
8002 Read X server colormap.
8003 */
8004 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8005 visual_info->colormap_size,sizeof(*server_colors));
8006 if (server_colors == (XColor *) NULL)
8007 ThrowXWindowFatalException(ResourceLimitFatalError,
8008 "UnableToCreateColormap",image->filename);
8009 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008010 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008011 (void) XQueryColors(display,colormap,server_colors,
8012 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8013 /*
8014 Select remaining colors from X server colormap.
8015 */
cristybb503372010-05-27 20:51:26 +00008016 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008017 {
8018 index=diversity[i].index;
8019 color.red=
8020 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8021 color.green=
8022 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8023 color.blue=
8024 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8025 if (visual_info->klass != PseudoColor)
8026 {
8027 gray_value=(unsigned short) XPixelIntensity(&color);
8028 color.red=gray_value;
8029 color.green=gray_value;
8030 color.blue=gray_value;
8031 }
8032 XBestPixel(display,colormap,server_colors,(unsigned int)
8033 visual_info->colormap_size,&color);
8034 pixel->pixels[index]=color.pixel;
8035 *p++=color;
8036 }
8037 if ((int) image->colors < visual_info->colormap_size)
8038 {
8039 /*
8040 Fill up colors array-- more choices for pen colors.
8041 */
8042 retain_colors=MagickMin((unsigned int)
8043 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008044 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008045 *p++=server_colors[i];
8046 number_colors+=retain_colors;
8047 }
8048 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8049 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8050 break;
8051 }
8052 /*
8053 Define Standard colormap for private GrayScale or PseudoColor visual.
8054 */
8055 if (status == False)
8056 {
8057 /*
8058 Not enough colormap entries in the colormap-- Create a new colormap.
8059 */
8060 colormap=XCreateColormap(display,
8061 XRootWindow(display,visual_info->screen),visual_info->visual,
8062 AllocNone);
8063 if (colormap == (Colormap) NULL)
8064 ThrowXWindowFatalException(ResourceLimitFatalError,
8065 "UnableToCreateColormap",image->filename);
8066 map_info->colormap=colormap;
8067 if ((int) image->colors < visual_info->colormap_size)
8068 {
8069 /*
8070 Retain colors from the default colormap to help lessens the
8071 effects of colormap flashing.
8072 */
8073 retain_colors=MagickMin((unsigned int)
8074 (visual_info->colormap_size-image->colors),256);
8075 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008076 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008077 {
cristyc57f6942010-11-12 01:47:39 +00008078 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008079 p++;
8080 }
8081 (void) XQueryColors(display,
8082 XDefaultColormap(display,visual_info->screen),
8083 colors+image->colors,(int) retain_colors);
8084 /*
8085 Transfer colors from default to private colormap.
8086 */
8087 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008088 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008089 retain_colors);
8090 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008091 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008092 {
8093 p->pixel=pixel->pixels[i];
8094 p++;
8095 }
8096 (void) XStoreColors(display,colormap,colors+image->colors,
8097 (int) retain_colors);
8098 number_colors+=retain_colors;
8099 }
8100 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008101 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008102 image->colors);
8103 }
8104 /*
8105 Store the image colormap.
8106 */
8107 p=colors;
8108 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008109 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008110 {
8111 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8112 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8113 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8114 if (visual_info->klass != PseudoColor)
8115 {
8116 gray_value=(unsigned short) XPixelIntensity(&color);
8117 color.red=gray_value;
8118 color.green=gray_value;
8119 color.blue=gray_value;
8120 }
8121 color.pixel=pixel->pixels[i];
8122 *p++=color;
8123 }
8124 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8125 break;
8126 }
8127 case TrueColor:
8128 case DirectColor:
8129 default:
8130 {
8131 MagickBooleanType
8132 linear_colormap;
8133
8134 /*
8135 Define Standard Colormap for TrueColor or DirectColor visual.
8136 */
8137 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8138 (map_info->green_max*map_info->green_mult)+
8139 (map_info->blue_max*map_info->blue_mult)+1);
8140 linear_colormap=(number_colors > 4096) ||
8141 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8142 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8143 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8144 MagickTrue : MagickFalse;
8145 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008146 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008147 /*
8148 Allocate color array.
8149 */
8150 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8151 if (colors == (XColor *) NULL)
8152 ThrowXWindowFatalException(ResourceLimitFatalError,
8153 "UnableToCreateColormap",image->filename);
8154 /*
8155 Initialize linear color ramp.
8156 */
8157 p=colors;
8158 color.flags=(char) (DoRed | DoGreen | DoBlue);
8159 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008160 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008161 {
8162 color.blue=(unsigned short) 0;
8163 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008164 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008165 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8166 color.green=color.blue;
8167 color.red=color.blue;
8168 color.pixel=XStandardPixel(map_info,&color);
8169 *p++=color;
8170 }
8171 else
cristybb503372010-05-27 20:51:26 +00008172 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008173 {
8174 color.red=(unsigned short) 0;
8175 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008176 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008177 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8178 color.green=(unsigned int) 0;
8179 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008180 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008181 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8182 map_info->green_max));
8183 color.blue=(unsigned short) 0;
8184 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008185 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008186 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8187 color.pixel=XStandardPixel(map_info,&color);
8188 *p++=color;
8189 }
8190 if ((visual_info->klass == DirectColor) &&
8191 (colormap != XDefaultColormap(display,visual_info->screen)))
8192 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8193 else
cristybb503372010-05-27 20:51:26 +00008194 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008195 (void) XAllocColor(display,colormap,&colors[i]);
8196 break;
8197 }
8198 }
8199 if ((visual_info->klass != DirectColor) &&
8200 (visual_info->klass != TrueColor))
8201 {
8202 /*
8203 Set foreground, background, border, etc. pixels.
8204 */
8205 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8206 &pixel->foreground_color);
8207 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8208 &pixel->background_color);
8209 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8210 {
8211 /*
8212 Foreground and background colors must differ.
8213 */
8214 pixel->background_color.red=(~pixel->foreground_color.red);
8215 pixel->background_color.green=
8216 (~pixel->foreground_color.green);
8217 pixel->background_color.blue=
8218 (~pixel->foreground_color.blue);
8219 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8220 &pixel->background_color);
8221 }
8222 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8223 &pixel->border_color);
8224 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8225 &pixel->matte_color);
8226 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8227 &pixel->highlight_color);
8228 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8229 &pixel->shadow_color);
8230 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8231 &pixel->depth_color);
8232 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8233 &pixel->trough_color);
8234 for (i=0; i < MaxNumberPens; i++)
8235 {
8236 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8237 &pixel->pen_colors[i]);
8238 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8239 }
cristyc57f6942010-11-12 01:47:39 +00008240 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008241 }
8242 colors=(XColor *) RelinquishMagickMemory(colors);
8243 if (IsEventLogging())
8244 {
8245 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8246 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8247 map_info->colormap);
8248 (void) LogMagickEvent(X11Event,GetMagickModule(),
8249 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8250 map_info->green_max,map_info->blue_max);
8251 (void) LogMagickEvent(X11Event,GetMagickModule(),
8252 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8253 map_info->green_mult,map_info->blue_mult);
8254 }
8255}
8256
8257/*
8258%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8259% %
8260% %
8261% %
8262% X M a k e W i n d o w %
8263% %
8264% %
8265% %
8266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8267%
8268% XMakeWindow() creates an X11 window.
8269%
8270% The format of the XMakeWindow method is:
8271%
8272% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8273% XClassHint *class_hint,XWMHints *manager_hints,
8274% XWindowInfo *window_info)
8275%
8276% A description of each parameter follows:
8277%
8278% o display: Specifies a connection to an X server; returned from
8279% XOpenDisplay.
8280%
8281% o parent: Specifies the parent window_info.
8282%
8283% o argv: Specifies the application's argument list.
8284%
8285% o argc: Specifies the number of arguments.
8286%
8287% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8288%
8289% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8290%
8291% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8292%
8293*/
8294MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8295 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8296 XWindowInfo *window_info)
8297{
8298#define MinWindowSize 64
8299
8300 Atom
8301 atom_list[2];
8302
8303 int
8304 gravity;
8305
8306 static XTextProperty
8307 icon_name,
8308 window_name;
8309
8310 Status
8311 status;
8312
8313 XSizeHints
8314 *size_hints;
8315
8316 /*
8317 Set window info hints.
8318 */
8319 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8320 assert(display != (Display *) NULL);
8321 assert(window_info != (XWindowInfo *) NULL);
8322 size_hints=XAllocSizeHints();
8323 if (size_hints == (XSizeHints *) NULL)
8324 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008325 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008326 size_hints->x=window_info->x;
8327 size_hints->y=window_info->y;
8328 size_hints->width=(int) window_info->width;
8329 size_hints->height=(int) window_info->height;
8330 if (window_info->immutable != MagickFalse)
8331 {
8332 /*
8333 Window size cannot be changed.
8334 */
8335 size_hints->min_width=size_hints->width;
8336 size_hints->min_height=size_hints->height;
8337 size_hints->max_width=size_hints->width;
8338 size_hints->max_height=size_hints->height;
8339 size_hints->flags|=PMinSize;
8340 size_hints->flags|=PMaxSize;
8341 }
8342 else
8343 {
8344 /*
8345 Window size can be changed.
8346 */
8347 size_hints->min_width=(int) window_info->min_width;
8348 size_hints->min_height=(int) window_info->min_height;
8349 size_hints->flags|=PResizeInc;
8350 size_hints->width_inc=(int) window_info->width_inc;
8351 size_hints->height_inc=(int) window_info->height_inc;
8352#if !defined(PRE_R4_ICCCM)
8353 size_hints->flags|=PBaseSize;
8354 size_hints->base_width=size_hints->width_inc;
8355 size_hints->base_height=size_hints->height_inc;
8356#endif
8357 }
8358 gravity=NorthWestGravity;
8359 if (window_info->geometry != (char *) NULL)
8360 {
8361 char
8362 default_geometry[MaxTextExtent],
8363 geometry[MaxTextExtent];
8364
8365 int
8366 flags;
8367
8368 register char
8369 *p;
8370
8371 /*
8372 User specified geometry.
8373 */
8374 (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
8375 size_hints->width,size_hints->height);
8376 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8377 p=geometry;
8378 while (strlen(p) != 0)
8379 {
8380 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8381 p++;
8382 else
8383 (void) CopyMagickString(p,p+1,MaxTextExtent);
8384 }
8385 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8386 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8387 &size_hints->width,&size_hints->height,&gravity);
8388 if ((flags & WidthValue) && (flags & HeightValue))
8389 size_hints->flags|=USSize;
8390 if ((flags & XValue) && (flags & YValue))
8391 {
8392 size_hints->flags|=USPosition;
8393 window_info->x=size_hints->x;
8394 window_info->y=size_hints->y;
8395 }
8396 }
8397#if !defined(PRE_R4_ICCCM)
8398 size_hints->win_gravity=gravity;
8399 size_hints->flags|=PWinGravity;
8400#endif
8401 if (window_info->id == (Window) NULL)
8402 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8403 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8404 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008405 window_info->visual,(unsigned long) window_info->mask,
8406 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008407 else
8408 {
8409 MagickStatusType
8410 mask;
8411
8412 XEvent
8413 sans_event;
8414
8415 XWindowChanges
8416 window_changes;
8417
8418 /*
8419 Window already exists; change relevant attributes.
8420 */
cristyc57f6942010-11-12 01:47:39 +00008421 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8422 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008423 mask=ConfigureNotify;
8424 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8425 window_changes.x=window_info->x;
8426 window_changes.y=window_info->y;
8427 window_changes.width=(int) window_info->width;
8428 window_changes.height=(int) window_info->height;
8429 mask=(MagickStatusType) (CWWidth | CWHeight);
8430 if (window_info->flags & USPosition)
8431 mask|=CWX | CWY;
8432 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8433 mask,&window_changes);
8434 }
8435 if (window_info->id == (Window) NULL)
8436 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8437 window_info->name);
8438 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8439 if (status == False)
8440 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8441 window_info->name);
8442 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8443 if (status == False)
8444 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8445 window_info->icon_name);
8446 if (window_info->icon_geometry != (char *) NULL)
8447 {
8448 int
8449 flags,
8450 height,
8451 width;
8452
8453 /*
8454 User specified icon geometry.
8455 */
8456 size_hints->flags|=USPosition;
8457 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8458 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8459 &manager_hints->icon_y,&width,&height,&gravity);
8460 if ((flags & XValue) && (flags & YValue))
8461 manager_hints->flags|=IconPositionHint;
8462 }
8463 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8464 size_hints,manager_hints,class_hint);
8465 if (window_name.value != (void *) NULL)
8466 {
8467 (void) XFree((void *) window_name.value);
8468 window_name.value=(unsigned char *) NULL;
8469 window_name.nitems=0;
8470 }
8471 if (icon_name.value != (void *) NULL)
8472 {
8473 (void) XFree((void *) icon_name.value);
8474 icon_name.value=(unsigned char *) NULL;
8475 icon_name.nitems=0;
8476 }
8477 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8478 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8479 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8480 (void) XFree((void *) size_hints);
8481 if (window_info->shape != MagickFalse)
8482 {
8483#if defined(MAGICKCORE_HAVE_SHAPE)
8484 int
8485 error_base,
8486 event_base;
8487
8488 /*
8489 Can we apply a non-rectangular shaping mask?
8490 */
8491 error_base=0;
8492 event_base=0;
8493 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8494 window_info->shape=MagickFalse;
8495#else
8496 window_info->shape=MagickFalse;
8497#endif
8498 }
8499 if (window_info->shared_memory)
8500 {
8501#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8502 /*
8503 Can we use shared memory with this window?
8504 */
8505 if (XShmQueryExtension(display) == 0)
8506 window_info->shared_memory=MagickFalse;
8507#else
8508 window_info->shared_memory=MagickFalse;
8509#endif
8510 }
8511 window_info->image=NewImageList();
8512 window_info->destroy=MagickFalse;
8513}
8514
8515/*
8516%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8517% %
8518% %
8519% %
8520% X M a g i c k P r o g r e s s M o n i t o r %
8521% %
8522% %
8523% %
8524%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8525%
8526% XMagickProgressMonitor() displays the progress a task is making in
8527% completing a task.
8528%
8529% The format of the XMagickProgressMonitor method is:
8530%
8531% void XMagickProgressMonitor(const char *task,
8532% const MagickOffsetType quantum,const MagickSizeType span,
8533% void *client_data)
8534%
8535% A description of each parameter follows:
8536%
8537% o task: Identifies the task in progress.
8538%
8539% o quantum: Specifies the quantum position within the span which represents
8540% how much progress has been made in completing a task.
8541%
8542% o span: Specifies the span relative to completing a task.
8543%
8544% o client_data: Pointer to any client data.
8545%
8546*/
8547
8548static const char *GetLocaleMonitorMessage(const char *text)
8549{
8550 char
8551 message[MaxTextExtent],
8552 tag[MaxTextExtent];
8553
8554 const char
8555 *locale_message;
8556
8557 register char
8558 *p;
8559
8560 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8561 p=strrchr(tag,'/');
8562 if (p != (char *) NULL)
8563 *p='\0';
8564 (void) FormatMagickString(message,MaxTextExtent,"Monitor/%s",tag);
8565 locale_message=GetLocaleMessage(message);
8566 if (locale_message == message)
8567 return(text);
8568 return(locale_message);
8569}
8570
8571MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8572 const MagickOffsetType quantum,const MagickSizeType span,
8573 void *magick_unused(client_data))
8574{
8575 XWindows
8576 *windows;
8577
8578 windows=XSetWindows((XWindows *) ~0);
8579 if (windows == (XWindows *) NULL)
8580 return(MagickTrue);
8581 if (windows->info.mapped != MagickFalse)
8582 XProgressMonitorWidget(windows->display,windows,
8583 GetLocaleMonitorMessage(tag),quantum,span);
8584 return(MagickTrue);
8585}
8586
8587/*
8588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8589% %
8590% %
8591% %
8592% X Q u e r y C o l o r D a t a b a s e %
8593% %
8594% %
8595% %
8596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8597%
8598% XQueryColorDatabase() looks up a RGB values for a color given in the target
8599% string.
8600%
8601% The format of the XQueryColorDatabase method is:
8602%
8603% MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8604%
8605% A description of each parameter follows:
8606%
8607% o target: Specifies the color to lookup in the X color database.
8608%
8609% o color: A pointer to an PixelPacket structure. The RGB value of the target
8610% color is returned as this value.
8611%
8612*/
8613MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8614 XColor *color)
8615{
8616 Colormap
8617 colormap;
8618
8619 static Display
8620 *display = (Display *) NULL;
8621
8622 Status
8623 status;
8624
8625 XColor
8626 xcolor;
8627
8628 /*
8629 Initialize color return value.
8630 */
8631 assert(color != (XColor *) NULL);
8632 color->red=0;
8633 color->green=0;
8634 color->blue=0;
8635 color->flags=(char) (DoRed | DoGreen | DoBlue);
8636 if ((target == (char *) NULL) || (*target == '\0'))
8637 target="#ffffffffffff";
8638 /*
8639 Let the X server define the color for us.
8640 */
8641 if (display == (Display *) NULL)
8642 display=XOpenDisplay((char *) NULL);
8643 if (display == (Display *) NULL)
8644 {
8645 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8646 return(MagickFalse);
8647 }
8648 colormap=XDefaultColormap(display,XDefaultScreen(display));
8649 status=XParseColor(display,colormap,(char *) target,&xcolor);
8650 if (status == False)
8651 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8652 else
8653 {
8654 color->red=xcolor.red;
8655 color->green=xcolor.green;
8656 color->blue=xcolor.blue;
8657 color->flags=xcolor.flags;
8658 }
8659 return(status != False ? MagickTrue : MagickFalse);
8660}
8661
8662/*
8663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8664% %
8665% %
8666% %
8667% X Q u e r y P o s i t i o n %
8668% %
8669% %
8670% %
8671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8672%
8673% XQueryPosition() gets the pointer coordinates relative to a window.
8674%
8675% The format of the XQueryPosition method is:
8676%
8677% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8678%
8679% A description of each parameter follows:
8680%
8681% o display: Specifies a connection to an X server; returned from
8682% XOpenDisplay.
8683%
8684% o window: Specifies a pointer to a Window.
8685%
8686% o x: Return the x coordinate of the pointer relative to the origin of the
8687% window.
8688%
8689% o y: Return the y coordinate of the pointer relative to the origin of the
8690% window.
8691%
8692*/
8693MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8694{
8695 int
8696 x_root,
8697 y_root;
8698
8699 unsigned int
8700 mask;
8701
8702 Window
8703 root_window;
8704
8705 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8706 assert(display != (Display *) NULL);
8707 assert(window != (Window) NULL);
8708 assert(x != (int *) NULL);
8709 assert(y != (int *) NULL);
8710 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8711 x,y,&mask);
8712}
8713
8714/*
8715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8716% %
8717% %
8718% %
8719% X R e f r e s h W i n d o w %
8720% %
8721% %
8722% %
8723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8724%
8725% XRefreshWindow() refreshes an image in a X window.
8726%
8727% The format of the XRefreshWindow method is:
8728%
8729% void XRefreshWindow(Display *display,const XWindowInfo *window,
8730% const XEvent *event)
8731%
8732% A description of each parameter follows:
8733%
8734% o display: Specifies a connection to an X server; returned from
8735% XOpenDisplay.
8736%
8737% o window: Specifies a pointer to a XWindowInfo structure.
8738%
8739% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8740% the entire image is refreshed.
8741%
8742*/
8743MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8744 const XEvent *event)
8745{
8746 int
8747 x,
8748 y;
8749
8750 unsigned int
8751 height,
8752 width;
8753
8754 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8755 assert(display != (Display *) NULL);
8756 assert(window != (XWindowInfo *) NULL);
8757 if (window->ximage == (XImage *) NULL)
8758 return;
8759 if (event != (XEvent *) NULL)
8760 {
8761 /*
8762 Determine geometry from expose event.
8763 */
8764 x=event->xexpose.x;
8765 y=event->xexpose.y;
8766 width=(unsigned int) event->xexpose.width;
8767 height=(unsigned int) event->xexpose.height;
8768 }
8769 else
8770 {
8771 XEvent
8772 sans_event;
8773
8774 /*
8775 Refresh entire window; discard outstanding expose events.
8776 */
8777 x=0;
8778 y=0;
8779 width=window->width;
8780 height=window->height;
8781 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008782 if (window->matte_pixmap != (Pixmap) NULL)
8783 {
8784#if defined(MAGICKCORE_HAVE_SHAPE)
8785 if (window->shape != MagickFalse)
8786 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8787 window->matte_pixmap,ShapeSet);
8788#endif
8789 }
cristy3ed852e2009-09-05 21:47:34 +00008790 }
8791 /*
8792 Check boundary conditions.
8793 */
8794 if ((window->ximage->width-(x+window->x)) < (int) width)
8795 width=(unsigned int) (window->ximage->width-(x+window->x));
8796 if ((window->ximage->height-(y+window->y)) < (int) height)
8797 height=(unsigned int) (window->ximage->height-(y+window->y));
8798 /*
8799 Refresh image.
8800 */
8801 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008802 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008803 if (window->pixmap != (Pixmap) NULL)
8804 {
8805 if (window->depth > 1)
8806 (void) XCopyArea(display,window->pixmap,window->id,
8807 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8808 else
8809 (void) XCopyPlane(display,window->pixmap,window->id,
8810 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8811 1L);
8812 }
8813 else
8814 {
8815#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8816 if (window->shared_memory)
8817 (void) XShmPutImage(display,window->id,window->annotate_context,
8818 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8819#endif
8820 if (window->shared_memory == MagickFalse)
8821 (void) XPutImage(display,window->id,window->annotate_context,
8822 window->ximage,x+window->x,y+window->y,x,y,width,height);
8823 }
8824 if (window->matte_pixmap != (Pixmap) NULL)
8825 (void) XSetClipMask(display,window->annotate_context,None);
8826 (void) XFlush(display);
8827}
8828
8829/*
8830%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8831% %
8832% %
8833% %
8834% X R e m o t e C o m m a n d %
8835% %
8836% %
8837% %
8838%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8839%
8840% XRemoteCommand() forces a remote display(1) to display the specified
8841% image filename.
8842%
8843% The format of the XRemoteCommand method is:
8844%
8845% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8846% const char *filename)
8847%
8848% A description of each parameter follows:
8849%
8850% o display: Specifies a connection to an X server; returned from
8851% XOpenDisplay.
8852%
8853% o window: Specifies the name or id of an X window.
8854%
8855% o filename: the name of the image filename to display.
8856%
8857*/
8858MagickExport MagickBooleanType XRemoteCommand(Display *display,
8859 const char *window,const char *filename)
8860{
8861 Atom
8862 remote_atom;
8863
8864 Window
8865 remote_window,
8866 root_window;
8867
8868 assert(filename != (char *) NULL);
8869 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8870 if (display == (Display *) NULL)
8871 display=XOpenDisplay((char *) NULL);
8872 if (display == (Display *) NULL)
8873 {
8874 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8875 return(MagickFalse);
8876 }
8877 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8878 remote_window=(Window) NULL;
8879 root_window=XRootWindow(display,XDefaultScreen(display));
8880 if (window != (char *) NULL)
8881 {
8882 /*
8883 Search window hierarchy and identify any clients by name or ID.
8884 */
8885 if (isdigit((unsigned char) *window) != 0)
8886 remote_window=XWindowByID(display,root_window,(Window)
8887 strtol((char *) window,(char **) NULL,0));
8888 if (remote_window == (Window) NULL)
8889 remote_window=XWindowByName(display,root_window,window);
8890 }
8891 if (remote_window == (Window) NULL)
8892 remote_window=XWindowByProperty(display,root_window,remote_atom);
8893 if (remote_window == (Window) NULL)
8894 {
8895 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8896 filename);
8897 return(MagickFalse);
8898 }
8899 /*
8900 Send remote command.
8901 */
8902 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8903 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8904 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8905 (void) XSync(display,MagickFalse);
8906 return(MagickTrue);
8907}
8908
8909/*
8910%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8911% %
8912% %
8913% %
8914% X R e t a i n W i n d o w C o l o r s %
8915% %
8916% %
8917% %
8918%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8919%
8920% XRetainWindowColors() sets X11 color resources on a window. This preserves
8921% the colors associated with an image displayed on the window.
8922%
8923% The format of the XRetainWindowColors method is:
8924%
8925% void XRetainWindowColors(Display *display,const Window window)
8926%
8927% A description of each parameter follows:
8928%
8929% o display: Specifies a connection to an X server; returned from
8930% XOpenDisplay.
8931%
8932% o window: Specifies a pointer to a XWindowInfo structure.
8933%
8934*/
8935MagickExport void XRetainWindowColors(Display *display,const Window window)
8936{
8937 Atom
8938 property;
8939
8940 Pixmap
8941 pixmap;
8942
8943 /*
8944 Put property on the window.
8945 */
8946 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8947 assert(display != (Display *) NULL);
8948 assert(window != (Window) NULL);
8949 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8950 if (property == (Atom) NULL)
8951 {
8952 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8953 "_XSETROOT_ID");
8954 return;
8955 }
8956 pixmap=XCreatePixmap(display,window,1,1,1);
8957 if (pixmap == (Pixmap) NULL)
8958 {
8959 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8960 return;
8961 }
8962 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8963 (unsigned char *) &pixmap,1);
8964 (void) XSetCloseDownMode(display,RetainPermanent);
8965}
8966
8967/*
8968%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8969% %
8970% %
8971% %
8972% X S e l e c t W i n d o w %
8973% %
8974% %
8975% %
8976%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8977%
8978% XSelectWindow() allows a user to select a window using the mouse. If the
8979% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
8980% is returned in the crop_info structure.
8981%
8982% The format of the XSelectWindow function is:
8983%
8984% target_window=XSelectWindow(display,crop_info)
8985%
8986% A description of each parameter follows:
8987%
8988% o window: XSelectWindow returns the window id.
8989%
8990% o display: Specifies a pointer to the Display structure; returned from
8991% XOpenDisplay.
8992%
8993% o crop_info: Specifies a pointer to a RectangleInfo structure. It
8994% contains the extents of any cropping rectangle.
8995%
cristy3ed852e2009-09-05 21:47:34 +00008996*/
8997static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
8998{
8999#define MinimumCropArea (unsigned int) 9
9000
9001 Cursor
9002 target_cursor;
9003
9004 GC
9005 annotate_context;
9006
9007 int
9008 presses,
9009 x_offset,
9010 y_offset;
9011
9012 Status
9013 status;
9014
9015 Window
9016 root_window,
9017 target_window;
9018
9019 XEvent
9020 event;
9021
9022 XGCValues
9023 context_values;
9024
9025 /*
9026 Initialize graphic context.
9027 */
9028 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9029 assert(display != (Display *) NULL);
9030 assert(crop_info != (RectangleInfo *) NULL);
9031 root_window=XRootWindow(display,XDefaultScreen(display));
9032 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9033 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9034 context_values.function=GXinvert;
9035 context_values.plane_mask=
9036 context_values.background ^ context_values.foreground;
9037 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009038 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009039 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9040 if (annotate_context == (GC) NULL)
9041 return(MagickFalse);
9042 /*
9043 Grab the pointer using target cursor.
9044 */
9045 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9046 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9047 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9048 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9049 GrabModeAsync,root_window,target_cursor,CurrentTime);
9050 if (status != GrabSuccess)
9051 {
9052 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9053 return((Window) NULL);
9054 }
9055 /*
9056 Select a window.
9057 */
9058 crop_info->width=0;
9059 crop_info->height=0;
9060 presses=0;
9061 target_window=(Window) NULL;
9062 x_offset=0;
9063 y_offset=0;
9064 do
9065 {
9066 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9067 (void) XDrawRectangle(display,root_window,annotate_context,
9068 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9069 (unsigned int) crop_info->height-1);
9070 /*
9071 Allow another event.
9072 */
9073 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9074 (void) XWindowEvent(display,root_window,ButtonPressMask |
9075 ButtonReleaseMask | ButtonMotionMask,&event);
9076 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9077 (void) XDrawRectangle(display,root_window,annotate_context,
9078 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9079 (unsigned int) crop_info->height-1);
9080 switch (event.type)
9081 {
9082 case ButtonPress:
9083 {
9084 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9085 event.xbutton.x,event.xbutton.y);
9086 if (target_window == (Window) NULL)
9087 target_window=root_window;
9088 x_offset=event.xbutton.x_root;
9089 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009090 crop_info->x=(ssize_t) x_offset;
9091 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009092 crop_info->width=0;
9093 crop_info->height=0;
9094 presses++;
9095 break;
9096 }
9097 case ButtonRelease:
9098 {
9099 presses--;
9100 break;
9101 }
9102 case MotionNotify:
9103 {
9104 /*
9105 Discard pending button motion events.
9106 */
9107 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009108 crop_info->x=(ssize_t) event.xmotion.x;
9109 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009110 /*
9111 Check boundary conditions.
9112 */
9113 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009114 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009115 else
9116 {
cristyecd0ab52010-05-30 14:59:20 +00009117 crop_info->width=(size_t) (crop_info->x-x_offset);
9118 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009119 }
9120 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009121 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009122 else
9123 {
cristyecd0ab52010-05-30 14:59:20 +00009124 crop_info->height=(size_t) (crop_info->y-y_offset);
9125 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009126 }
9127 }
9128 default:
9129 break;
9130 }
9131 } while ((target_window == (Window) NULL) || (presses > 0));
9132 (void) XUngrabPointer(display,CurrentTime);
9133 (void) XFreeCursor(display,target_cursor);
9134 (void) XFreeGC(display,annotate_context);
9135 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9136 {
9137 crop_info->width=0;
9138 crop_info->height=0;
9139 }
9140 if ((crop_info->width != 0) && (crop_info->height != 0))
9141 target_window=root_window;
9142 return(target_window);
9143}
9144
9145/*
9146%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9147% %
9148% %
9149% %
9150% X S e t C u r s o r S t a t e %
9151% %
9152% %
9153% %
9154%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9155%
9156% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9157% reset to their default.
9158%
9159% The format of the XXSetCursorState method is:
9160%
9161% XSetCursorState(display,windows,const MagickStatusType state)
9162%
9163% A description of each parameter follows:
9164%
9165% o display: Specifies a connection to an X server; returned from
9166% XOpenDisplay.
9167%
9168% o windows: Specifies a pointer to a XWindows structure.
9169%
9170% o state: An unsigned integer greater than 0 sets the cursor state
9171% to busy, otherwise the cursor are reset to their default.
9172%
9173*/
9174MagickExport void XSetCursorState(Display *display,XWindows *windows,
9175 const MagickStatusType state)
9176{
9177 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9178 assert(display != (Display *) NULL);
9179 assert(windows != (XWindows *) NULL);
9180 if (state)
9181 {
9182 (void) XCheckDefineCursor(display,windows->image.id,
9183 windows->image.busy_cursor);
9184 (void) XCheckDefineCursor(display,windows->pan.id,
9185 windows->pan.busy_cursor);
9186 (void) XCheckDefineCursor(display,windows->magnify.id,
9187 windows->magnify.busy_cursor);
9188 (void) XCheckDefineCursor(display,windows->command.id,
9189 windows->command.busy_cursor);
9190 }
9191 else
9192 {
9193 (void) XCheckDefineCursor(display,windows->image.id,
9194 windows->image.cursor);
9195 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9196 (void) XCheckDefineCursor(display,windows->magnify.id,
9197 windows->magnify.cursor);
9198 (void) XCheckDefineCursor(display,windows->command.id,
9199 windows->command.cursor);
9200 (void) XCheckDefineCursor(display,windows->command.id,
9201 windows->widget.cursor);
9202 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9203 }
9204 windows->info.mapped=MagickFalse;
9205}
9206
9207/*
9208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9209% %
9210% %
9211% %
9212% X S e t W i n d o w s %
9213% %
9214% %
9215% %
9216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9217%
9218% XSetWindows() sets the X windows structure if the windows info is specified.
9219% Otherwise the current windows structure is returned.
9220%
9221% The format of the XSetWindows method is:
9222%
9223% XWindows *XSetWindows(XWindows *windows_info)
9224%
9225% A description of each parameter follows:
9226%
9227% o windows_info: Initialize the Windows structure with this information.
9228%
9229*/
9230MagickExport XWindows *XSetWindows(XWindows *windows_info)
9231{
9232 static XWindows
9233 *windows = (XWindows *) NULL;
9234
9235 if (windows_info != (XWindows *) ~0)
9236 {
9237 windows=(XWindows *) RelinquishMagickMemory(windows);
9238 windows=windows_info;
9239 }
9240 return(windows);
9241}
9242/*
9243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9244% %
9245% %
9246% %
9247% X U s e r P r e f e r e n c e s %
9248% %
9249% %
9250% %
9251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9252%
9253% XUserPreferences() saves the preferences in a configuration file in the
9254% users' home directory.
9255%
9256% The format of the XUserPreferences method is:
9257%
9258% void XUserPreferences(XResourceInfo *resource_info)
9259%
9260% A description of each parameter follows:
9261%
9262% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9263%
9264*/
9265MagickExport void XUserPreferences(XResourceInfo *resource_info)
9266{
9267#if defined(X11_PREFERENCES_PATH)
9268 char
9269 cache[MaxTextExtent],
9270 filename[MaxTextExtent],
9271 specifier[MaxTextExtent];
9272
9273 const char
cristy104cea82009-10-25 02:26:51 +00009274 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009275 *value;
9276
9277 XrmDatabase
9278 preferences_database;
9279
9280 /*
9281 Save user preferences to the client configuration file.
9282 */
9283 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009284 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009285 preferences_database=XrmGetStringDatabase("");
cristy104cea82009-10-25 02:26:51 +00009286 (void) FormatMagickString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009287 value=resource_info->backdrop ? "True" : "False";
9288 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009289 (void) FormatMagickString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009290 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9291 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9292 (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009293 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009294 value=resource_info->confirm_exit ? "True" : "False";
9295 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9296 (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009297 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009298 value=resource_info->confirm_edit ? "True" : "False";
9299 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9300 (void) FormatMagickString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009301 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009302 value=resource_info->display_warnings ? "True" : "False";
9303 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009304 (void) FormatMagickString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009305 value=resource_info->quantize_info->dither ? "True" : "False";
9306 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9307 (void) FormatMagickString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009308 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009309 value=resource_info->gamma_correct ? "True" : "False";
9310 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009311 (void) FormatMagickString(specifier,MaxTextExtent,"%s.undoCache",client_name);
cristye8c25f92010-06-03 00:53:06 +00009312 (void) FormatMagickString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009313 resource_info->undo_cache);
9314 XrmPutStringResource(&preferences_database,specifier,cache);
cristy104cea82009-10-25 02:26:51 +00009315 (void) FormatMagickString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009316 value=resource_info->use_pixmap ? "True" : "False";
9317 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9318 (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009319 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009320 ExpandFilename(filename);
9321 XrmPutFileDatabase(preferences_database,filename);
9322#endif
9323}
9324
9325/*
9326%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9327% %
9328% %
9329% %
9330% X V i s u a l C l a s s N a m e %
9331% %
9332% %
9333% %
9334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9335%
9336% XVisualClassName() returns the visual class name as a character string.
9337%
9338% The format of the XVisualClassName method is:
9339%
9340% char *XVisualClassName(const int visual_class)
9341%
9342% A description of each parameter follows:
9343%
9344% o visual_type: XVisualClassName returns the visual class as a character
9345% string.
9346%
9347% o class: Specifies the visual class.
9348%
cristy3ed852e2009-09-05 21:47:34 +00009349*/
9350static const char *XVisualClassName(const int visual_class)
9351{
9352 switch (visual_class)
9353 {
9354 case StaticGray: return("StaticGray");
9355 case GrayScale: return("GrayScale");
9356 case StaticColor: return("StaticColor");
9357 case PseudoColor: return("PseudoColor");
9358 case TrueColor: return("TrueColor");
9359 case DirectColor: return("DirectColor");
9360 }
9361 return("unknown visual class");
9362}
9363
9364/*
9365%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9366% %
9367% %
9368% %
9369% X W a r n i n g %
9370% %
9371% %
9372% %
9373%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9374%
9375% XWarning() displays a warning reason in a Notice widget.
9376%
9377% The format of the XWarning method is:
9378%
9379% void XWarning(const unsigned int warning,const char *reason,
9380% const char *description)
9381%
9382% A description of each parameter follows:
9383%
9384% o warning: Specifies the numeric warning category.
9385%
9386% o reason: Specifies the reason to display before terminating the
9387% program.
9388%
9389% o description: Specifies any description to the reason.
9390%
9391*/
9392MagickExport void XWarning(const ExceptionType magick_unused(warning),
9393 const char *reason,const char *description)
9394{
9395 char
9396 text[MaxTextExtent];
9397
9398 XWindows
9399 *windows;
9400
9401 if (reason == (char *) NULL)
9402 return;
9403 (void) CopyMagickString(text,reason,MaxTextExtent);
9404 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9405 windows=XSetWindows((XWindows *) ~0);
9406 XNoticeWidget(windows->display,windows,text,(char *) description);
9407}
9408
9409/*
9410%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9411% %
9412% %
9413% %
9414% X W i n d o w B y I D %
9415% %
9416% %
9417% %
9418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9419%
9420% XWindowByID() locates a child window with a given ID. If not window with
9421% the given name is found, 0 is returned. Only the window specified and its
9422% subwindows are searched.
9423%
9424% The format of the XWindowByID function is:
9425%
9426% child=XWindowByID(display,window,id)
9427%
9428% A description of each parameter follows:
9429%
9430% o child: XWindowByID returns the window with the specified
9431% id. If no windows are found, XWindowByID returns 0.
9432%
9433% o display: Specifies a pointer to the Display structure; returned from
9434% XOpenDisplay.
9435%
9436% o id: Specifies the id of the window to locate.
9437%
9438*/
9439MagickExport Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009440 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009441{
9442 RectangleInfo
9443 rectangle_info;
9444
9445 register int
9446 i;
9447
9448 Status
9449 status;
9450
9451 unsigned int
9452 number_children;
9453
9454 Window
9455 child,
9456 *children,
9457 window;
9458
9459 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9460 assert(display != (Display *) NULL);
9461 assert(root_window != (Window) NULL);
9462 if (id == 0)
9463 return(XSelectWindow(display,&rectangle_info));
9464 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009465 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009466 status=XQueryTree(display,root_window,&child,&child,&children,
9467 &number_children);
9468 if (status == False)
9469 return((Window) NULL);
9470 window=(Window) NULL;
9471 for (i=0; i < (int) number_children; i++)
9472 {
9473 /*
9474 Search each child and their children.
9475 */
9476 window=XWindowByID(display,children[i],id);
9477 if (window != (Window) NULL)
9478 break;
9479 }
9480 if (children != (Window *) NULL)
9481 (void) XFree((void *) children);
9482 return(window);
9483}
9484
9485/*
9486%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9487% %
9488% %
9489% %
9490% X W i n d o w B y N a m e %
9491% %
9492% %
9493% %
9494%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9495%
9496% XWindowByName() locates a window with a given name on a display. If no
9497% window with the given name is found, 0 is returned. If more than one window
9498% has the given name, the first one is returned. Only root and its children
9499% are searched.
9500%
9501% The format of the XWindowByName function is:
9502%
9503% window=XWindowByName(display,root_window,name)
9504%
9505% A description of each parameter follows:
9506%
9507% o window: XWindowByName returns the window id.
9508%
9509% o display: Specifies a pointer to the Display structure; returned from
9510% XOpenDisplay.
9511%
9512% o root_window: Specifies the id of the root window.
9513%
9514% o name: Specifies the name of the window to locate.
9515%
9516*/
9517MagickExport Window XWindowByName(Display *display,const Window root_window,
9518 const char *name)
9519{
9520 register int
9521 i;
9522
9523 Status
9524 status;
9525
9526 unsigned int
9527 number_children;
9528
9529 Window
9530 *children,
9531 child,
9532 window;
9533
9534 XTextProperty
9535 window_name;
9536
9537 assert(display != (Display *) NULL);
9538 assert(root_window != (Window) NULL);
9539 assert(name != (char *) NULL);
9540 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9541 if (XGetWMName(display,root_window,&window_name) != 0)
9542 if (LocaleCompare((char *) window_name.value,name) == 0)
9543 return(root_window);
9544 status=XQueryTree(display,root_window,&child,&child,&children,
9545 &number_children);
9546 if (status == False)
9547 return((Window) NULL);
9548 window=(Window) NULL;
9549 for (i=0; i < (int) number_children; i++)
9550 {
9551 /*
9552 Search each child and their children.
9553 */
9554 window=XWindowByName(display,children[i],name);
9555 if (window != (Window) NULL)
9556 break;
9557 }
9558 if (children != (Window *) NULL)
9559 (void) XFree((void *) children);
9560 return(window);
9561}
9562
9563/*
9564%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9565% %
9566% %
9567% %
9568% X W i n d o w B y P r o p e r y %
9569% %
9570% %
9571% %
9572%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9573%
9574% XWindowByProperty() locates a child window with a given property. If not
9575% window with the given name is found, 0 is returned. If more than one window
9576% has the given property, the first one is returned. Only the window
9577% specified and its subwindows are searched.
9578%
9579% The format of the XWindowByProperty function is:
9580%
9581% child=XWindowByProperty(display,window,property)
9582%
9583% A description of each parameter follows:
9584%
9585% o child: XWindowByProperty returns the window id with the specified
9586% property. If no windows are found, XWindowByProperty returns 0.
9587%
9588% o display: Specifies a pointer to the Display structure; returned from
9589% XOpenDisplay.
9590%
9591% o property: Specifies the property of the window to locate.
9592%
9593*/
9594MagickExport Window XWindowByProperty(Display *display,const Window window,
9595 const Atom property)
9596{
9597 Atom
9598 type;
9599
9600 int
9601 format;
9602
9603 Status
9604 status;
9605
9606 unsigned char
9607 *data;
9608
9609 unsigned int
9610 i,
9611 number_children;
9612
cristyf2faecf2010-05-28 19:19:36 +00009613 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009614 after,
9615 number_items;
9616
9617 Window
9618 child,
9619 *children,
9620 parent,
9621 root;
9622
9623 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9624 assert(display != (Display *) NULL);
9625 assert(window != (Window) NULL);
9626 assert(property != (Atom) NULL);
9627 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9628 if (status == False)
9629 return((Window) NULL);
9630 type=(Atom) NULL;
9631 child=(Window) NULL;
9632 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9633 {
9634 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9635 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9636 if (data != NULL)
9637 (void) XFree((void *) data);
9638 if ((status == Success) && (type != (Atom) NULL))
9639 child=children[i];
9640 }
9641 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9642 child=XWindowByProperty(display,children[i],property);
9643 if (children != (Window *) NULL)
9644 (void) XFree((void *) children);
9645 return(child);
9646}
9647#else
9648
9649/*
9650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9651% %
9652% %
9653% %
9654% X I m p o r t I m a g e %
9655% %
9656% %
9657% %
9658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9659%
9660% XImportImage() reads an image from an X window.
9661%
9662% The format of the XImportImage method is:
9663%
9664% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9665%
9666% A description of each parameter follows:
9667%
9668% o image_info: the image info..
9669%
9670% o ximage_info: Specifies a pointer to an XImportInfo structure.
9671%
9672*/
9673MagickExport Image *XImportImage(const ImageInfo *image_info,
9674 XImportInfo *ximage_info)
9675{
9676 assert(image_info != (const ImageInfo *) NULL);
9677 assert(image_info->signature == MagickSignature);
9678 if (image_info->debug != MagickFalse)
9679 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9680 image_info->filename);
9681 assert(ximage_info != (XImportInfo *) NULL);
9682 return((Image *) NULL);
9683}
9684#endif
9685
9686/*
9687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9688% %
9689% %
9690% %
cristy576974e2009-10-25 20:45:31 +00009691+ X C o m p o n e n t G e n e s i s %
9692% %
9693% %
9694% %
9695%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9696%
9697% XComponentGenesis() instantiates the X component.
9698%
9699% The format of the XComponentGenesis method is:
9700%
9701% MagickBooleanType XComponentGenesis(void)
9702%
9703*/
9704MagickExport MagickBooleanType XComponentGenesis(void)
9705{
9706 return(MagickTrue);
9707}
9708
9709/*
9710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9711% %
9712% %
9713% %
cristy3ed852e2009-09-05 21:47:34 +00009714% X G e t I m p o r t I n f o %
9715% %
9716% %
9717% %
9718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9719%
9720% XGetImportInfo() initializes the XImportInfo structure.
9721%
9722% The format of the XGetImportInfo method is:
9723%
9724% void XGetImportInfo(XImportInfo *ximage_info)
9725%
9726% A description of each parameter follows:
9727%
9728% o ximage_info: Specifies a pointer to an ImageInfo structure.
9729%
9730*/
9731MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9732{
9733 assert(ximage_info != (XImportInfo *) NULL);
9734 ximage_info->frame=MagickFalse;
9735 ximage_info->borders=MagickFalse;
9736 ximage_info->screen=MagickFalse;
9737 ximage_info->descend=MagickTrue;
9738 ximage_info->silent=MagickFalse;
9739}