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