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