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