blob: ee23c3f09f052d6c780d7886c45bcce2b66ab140 [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*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/animate.h"
44#include "MagickCore/artifact.h"
45#include "MagickCore/blob.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/client.h"
48#include "MagickCore/color.h"
49#include "MagickCore/color-private.h"
50#include "MagickCore/colormap.h"
51#include "MagickCore/composite.h"
52#include "MagickCore/display.h"
53#include "MagickCore/exception.h"
54#include "MagickCore/exception-private.h"
55#include "MagickCore/geometry.h"
56#include "MagickCore/identify.h"
57#include "MagickCore/image.h"
58#include "MagickCore/image-private.h"
59#include "MagickCore/list.h"
60#include "MagickCore/locale_.h"
61#include "MagickCore/log.h"
62#include "MagickCore/magick.h"
63#include "MagickCore/memory_.h"
64#include "MagickCore/monitor.h"
65#include "MagickCore/option.h"
66#include "MagickCore/pixel-accessor.h"
67#include "MagickCore/PreRvIcccm.h"
68#include "MagickCore/quantize.h"
69#include "MagickCore/quantum.h"
70#include "MagickCore/quantum-private.h"
71#include "MagickCore/resource_.h"
72#include "MagickCore/resize.h"
73#include "MagickCore/shear.h"
74#include "MagickCore/statistic.h"
75#include "MagickCore/string_.h"
76#include "MagickCore/string-private.h"
77#include "MagickCore/transform.h"
78#include "MagickCore/utility.h"
79#include "MagickCore/widget.h"
80#include "MagickCore/xwindow.h"
81#include "MagickCore/xwindow-private.h"
82#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000083#if defined(__BEOS__)
84#include <OS.h>
85#endif
86#if defined(MAGICKCORE_X11_DELEGATE)
87#include <X11/Xproto.h>
88#include <X11/Xlocale.h>
89#if defined(MAGICK_HAVE_POLL)
90# include <sys/poll.h>
91#endif
92#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
93#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
94# include <machine/param.h>
95#endif
96#include <sys/ipc.h>
97#include <sys/shm.h>
98#include <X11/extensions/XShm.h>
99#endif
100#if defined(MAGICKCORE_HAVE_SHAPE)
101#include <X11/extensions/shape.h>
102#endif
103
104/*
105 X defines.
106*/
cristyce70c172010-01-07 17:15:30 +0000107#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000108 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
109 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000110#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000111 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
112 map->red_mult)+ \
113 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
114 map->green_mult)+ \
115 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
116 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000117#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
118 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
119 map->red_mult)+ \
120 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
121 map->green_mult)+ \
122 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
123 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000124#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000125 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
126 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000127#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000128 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
129 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000130#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000131 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
132 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
133 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000134
135#define AccentuateModulate ScaleCharToQuantum(80)
136#define HighlightModulate ScaleCharToQuantum(125)
137#define ShadowModulate ScaleCharToQuantum(135)
138#define DepthModulate ScaleCharToQuantum(185)
139#define TroughModulate ScaleCharToQuantum(110)
140
141#define XLIB_ILLEGAL_ACCESS 1
142#undef ForgetGravity
143#undef NorthWestGravity
144#undef NorthGravity
145#undef NorthEastGravity
146#undef WestGravity
147#undef CenterGravity
148#undef EastGravity
149#undef SouthWestGravity
150#undef SouthGravity
151#undef SouthEastGravity
152#undef StaticGravity
153
154#undef index
155#if defined(hpux9)
156#define XFD_SET int
157#else
158#define XFD_SET fd_set
159#endif
160
161/*
162 Enumeration declarations.
163*/
164typedef enum
165{
166#undef DoRed
167 DoRed = 0x0001,
168#undef DoGreen
169 DoGreen = 0x0002,
170#undef DoBlue
171 DoBlue = 0x0004,
172 DoMatte = 0x0008
173} XColorFlags;
174
175/*
176 Typedef declarations.
177*/
178typedef struct _DiversityPacket
179{
180 Quantum
181 red,
182 green,
183 blue;
184
185 unsigned short
186 index;
187
cristybb503372010-05-27 20:51:26 +0000188 size_t
cristy3ed852e2009-09-05 21:47:34 +0000189 count;
190} DiversityPacket;
191
192/*
193 Constant declaractions.
194*/
195static MagickBooleanType
196 xerror_alert = MagickFalse;
197
198/*
199 Method prototypes.
200*/
201static const char
202 *XVisualClassName(const int);
203
204static MagickRealType
205 blue_gamma = 1.0,
206 green_gamma = 1.0,
207 red_gamma = 1.0;
208
209static MagickBooleanType
210 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
211
212static void
213 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
214 XImage *,XImage *),
215 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
216 XImage *,XImage *);
217
218static Window
219 XSelectWindow(Display *,RectangleInfo *);
220
221/*
222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223% %
224% %
225% %
226% D e s t r o y X R e s o u r c e s %
227% %
228% %
229% %
230%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231%
232% DestroyXResources() destroys any X resources.
233%
234% The format of the DestroyXResources method is:
235%
236% void DestroyXResources()
237%
238% A description of each parameter follows:
239%
240*/
241MagickExport void DestroyXResources(void)
242{
243 register int
244 i;
245
246 unsigned int
247 number_windows;
248
249 XWindowInfo
250 *magick_windows[MaxXWindows];
251
252 XWindows
253 *windows;
254
255 DestroyXWidget();
256 windows=XSetWindows((XWindows *) ~0);
257 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
258 return;
259 number_windows=0;
260 magick_windows[number_windows++]=(&windows->context);
261 magick_windows[number_windows++]=(&windows->group_leader);
262 magick_windows[number_windows++]=(&windows->backdrop);
263 magick_windows[number_windows++]=(&windows->icon);
264 magick_windows[number_windows++]=(&windows->image);
265 magick_windows[number_windows++]=(&windows->info);
266 magick_windows[number_windows++]=(&windows->magnify);
267 magick_windows[number_windows++]=(&windows->pan);
268 magick_windows[number_windows++]=(&windows->command);
269 magick_windows[number_windows++]=(&windows->widget);
270 magick_windows[number_windows++]=(&windows->popup);
271 magick_windows[number_windows++]=(&windows->context);
272 for (i=0; i < (int) number_windows; i++)
273 {
274 if (magick_windows[i]->mapped != MagickFalse)
275 {
276 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
277 magick_windows[i]->screen);
278 magick_windows[i]->mapped=MagickFalse;
279 }
280 if (magick_windows[i]->name != (char *) NULL)
281 magick_windows[i]->name=(char *)
282 RelinquishMagickMemory(magick_windows[i]->name);
283 if (magick_windows[i]->icon_name != (char *) NULL)
284 magick_windows[i]->icon_name=(char *)
285 RelinquishMagickMemory(magick_windows[i]->icon_name);
286 if (magick_windows[i]->cursor != (Cursor) NULL)
287 {
288 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
289 magick_windows[i]->cursor=(Cursor) NULL;
290 }
291 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
292 {
293 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
294 magick_windows[i]->busy_cursor=(Cursor) NULL;
295 }
296 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
297 {
298 (void) XFreePixmap(windows->display,
299 magick_windows[i]->highlight_stipple);
300 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
301 }
302 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
303 {
304 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
305 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
306 }
307 if (magick_windows[i]->ximage != (XImage *) NULL)
308 {
309 XDestroyImage(magick_windows[i]->ximage);
310 magick_windows[i]->ximage=(XImage *) NULL;
311 }
312 if (magick_windows[i]->pixmap != (Pixmap) NULL)
313 {
314 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
315 magick_windows[i]->pixmap=(Pixmap) NULL;
316 }
317 if (magick_windows[i]->id != (Window) NULL)
318 {
319 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
320 magick_windows[i]->id=(Window) NULL;
321 }
322 if (magick_windows[i]->destroy != MagickFalse)
323 {
324 if (magick_windows[i]->image != (Image *) NULL)
325 {
326 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
327 magick_windows[i]->image=NewImageList();
328 }
329 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
330 {
331 (void) XFreePixmap(windows->display,
332 magick_windows[i]->matte_pixmap);
333 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
334 }
335 }
336 if (magick_windows[i]->segment_info != (void *) NULL)
337 {
338#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
339 XShmSegmentInfo
340 *segment_info;
341
342 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
343 if (segment_info != (XShmSegmentInfo *) NULL)
344 if (segment_info[0].shmid >= 0)
345 {
346 if (segment_info[0].shmaddr != NULL)
347 (void) shmdt(segment_info[0].shmaddr);
348 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
349 segment_info[0].shmaddr=NULL;
350 segment_info[0].shmid=(-1);
351 }
352#endif
353 magick_windows[i]->segment_info=(void *)
354 RelinquishMagickMemory(magick_windows[i]->segment_info);
355 }
356 }
357 windows->icon_resources=(XResourceInfo *)
358 RelinquishMagickMemory(windows->icon_resources);
359 if (windows->icon_pixel != (XPixelInfo *) NULL)
360 {
cristyf2faecf2010-05-28 19:19:36 +0000361 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
362 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000363 RelinquishMagickMemory(windows->icon_pixel->pixels);
364 if (windows->icon_pixel->annotate_context != (GC) NULL)
365 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
366 windows->icon_pixel=(XPixelInfo *)
367 RelinquishMagickMemory(windows->icon_pixel);
368 }
369 if (windows->pixel_info != (XPixelInfo *) NULL)
370 {
cristyf2faecf2010-05-28 19:19:36 +0000371 if (windows->pixel_info->pixels != (unsigned long *) NULL)
372 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000373 RelinquishMagickMemory(windows->pixel_info->pixels);
374 if (windows->pixel_info->annotate_context != (GC) NULL)
375 XFreeGC(windows->display,windows->pixel_info->annotate_context);
376 if (windows->pixel_info->widget_context != (GC) NULL)
377 XFreeGC(windows->display,windows->pixel_info->widget_context);
378 if (windows->pixel_info->highlight_context != (GC) NULL)
379 XFreeGC(windows->display,windows->pixel_info->highlight_context);
380 windows->pixel_info=(XPixelInfo *)
381 RelinquishMagickMemory(windows->pixel_info);
382 }
383 if (windows->font_info != (XFontStruct *) NULL)
384 {
385 XFreeFont(windows->display,windows->font_info);
386 windows->font_info=(XFontStruct *) NULL;
387 }
388 if (windows->class_hints != (XClassHint *) NULL)
389 {
390 if (windows->class_hints->res_name != (char *) NULL)
391 XFree(windows->class_hints->res_name);
392 if (windows->class_hints->res_class != (char *) NULL)
393 XFree(windows->class_hints->res_class);
394 XFree(windows->class_hints);
395 windows->class_hints=(XClassHint *) NULL;
396 }
397 if (windows->manager_hints != (XWMHints *) NULL)
398 {
399 XFree(windows->manager_hints);
400 windows->manager_hints=(XWMHints *) NULL;
401 }
402 if (windows->map_info != (XStandardColormap *) NULL)
403 {
404 XFree(windows->map_info);
405 windows->map_info=(XStandardColormap *) NULL;
406 }
407 if (windows->icon_map != (XStandardColormap *) NULL)
408 {
409 XFree(windows->icon_map);
410 windows->icon_map=(XStandardColormap *) NULL;
411 }
412 if (windows->visual_info != (XVisualInfo *) NULL)
413 {
414 XFree(windows->visual_info);
415 windows->visual_info=(XVisualInfo *) NULL;
416 }
417 if (windows->icon_visual != (XVisualInfo *) NULL)
418 {
419 XFree(windows->icon_visual);
420 windows->icon_visual=(XVisualInfo *) NULL;
421 }
422 (void) XSetWindows((XWindows *) NULL);
423}
424
425/*
426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427% %
428% %
429% %
430% X A n n o t a t e I m a g e %
431% %
432% %
433% %
434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435%
436% XAnnotateImage() annotates the image with text.
437%
438% The format of the XAnnotateImage method is:
439%
440% MagickBooleanType XAnnotateImage(Display *display,
441% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
442%
443% A description of each parameter follows:
444%
445% o display: Specifies a connection to an X server; returned from
446% XOpenDisplay.
447%
448% o pixel: Specifies a pointer to a XPixelInfo structure.
449%
450% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
451%
452% o image: the image.
453%
454*/
455MagickExport MagickBooleanType XAnnotateImage(Display *display,
456 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
457{
cristyc57f6942010-11-12 01:47:39 +0000458 CacheView
459 *annotate_view;
460
cristy3ed852e2009-09-05 21:47:34 +0000461 GC
462 annotate_context;
463
464 ExceptionInfo
465 *exception;
466
467 Image
468 *annotate_image;
469
470 int
471 x,
472 y;
473
474 MagickBooleanType
475 matte;
476
477 Pixmap
478 annotate_pixmap;
479
480 unsigned int
481 depth,
482 height,
483 width;
484
485 Window
486 root_window;
487
488 XGCValues
489 context_values;
490
491 XImage
492 *annotate_ximage;
493
494 /*
495 Initialize annotated image.
496 */
497 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
498 assert(display != (Display *) NULL);
499 assert(pixel != (XPixelInfo *) NULL);
500 assert(annotate_info != (XAnnotateInfo *) NULL);
501 assert(image != (Image *) NULL);
502 /*
503 Initialize annotated pixmap.
504 */
505 root_window=XRootWindow(display,XDefaultScreen(display));
506 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
507 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
508 annotate_info->height,depth);
509 if (annotate_pixmap == (Pixmap) NULL)
510 return(MagickFalse);
511 /*
512 Initialize graphics info.
513 */
514 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000515 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000516 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000517 annotate_context=XCreateGC(display,root_window,(unsigned long)
518 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000519 if (annotate_context == (GC) NULL)
520 return(MagickFalse);
521 /*
522 Draw text to pixmap.
523 */
524 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
525 (int) annotate_info->font_info->ascent,annotate_info->text,
526 (int) strlen(annotate_info->text));
527 (void) XFreeGC(display,annotate_context);
528 /*
529 Initialize annotated X image.
530 */
531 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
532 annotate_info->height,AllPlanes,ZPixmap);
533 if (annotate_ximage == (XImage *) NULL)
534 return(MagickFalse);
535 (void) XFreePixmap(display,annotate_pixmap);
536 /*
537 Initialize annotated image.
538 */
539 annotate_image=AcquireImage((ImageInfo *) NULL);
540 if (annotate_image == (Image *) NULL)
541 return(MagickFalse);
542 annotate_image->columns=annotate_info->width;
543 annotate_image->rows=annotate_info->height;
544 /*
545 Transfer annotated X image to image.
546 */
547 width=(unsigned int) image->columns;
548 height=(unsigned int) image->rows;
549 x=0;
550 y=0;
551 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +0000552 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
553 &annotate_image->background_color,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +0000554 if (annotate_info->stencil == ForegroundStencil)
555 annotate_image->matte=MagickTrue;
556 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +0000557 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000558 for (y=0; y < (int) annotate_image->rows; y++)
559 {
cristyc57f6942010-11-12 01:47:39 +0000560 register int
cristy3ed852e2009-09-05 21:47:34 +0000561 x;
562
cristy4c08aed2011-07-01 19:47:50 +0000563 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000564 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000565
cristyc57f6942010-11-12 01:47:39 +0000566 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
567 annotate_image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000568 if (q == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000569 break;
cristyc57f6942010-11-12 01:47:39 +0000570 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000571 {
cristy4c08aed2011-07-01 19:47:50 +0000572 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000573 if (XGetPixel(annotate_ximage,x,y) == 0)
574 {
575 /*
576 Set this pixel to the background color.
577 */
cristy4c08aed2011-07-01 19:47:50 +0000578 SetPixelRed(annotate_image,ScaleShortToQuantum(
579 pixel->box_color.red),q);
580 SetPixelGreen(annotate_image,ScaleShortToQuantum(
581 pixel->box_color.green),q);
582 SetPixelBlue(annotate_image,ScaleShortToQuantum(
583 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000584 if ((annotate_info->stencil == ForegroundStencil) ||
585 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000586 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000587 }
588 else
589 {
590 /*
591 Set this pixel to the pen color.
592 */
cristy4c08aed2011-07-01 19:47:50 +0000593 SetPixelRed(annotate_image,ScaleShortToQuantum(
594 pixel->pen_color.red),q);
595 SetPixelGreen(annotate_image,ScaleShortToQuantum(
596 pixel->pen_color.green),q);
597 SetPixelBlue(annotate_image,ScaleShortToQuantum(
598 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000599 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000600 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000601 }
cristyed231572011-07-14 02:18:59 +0000602 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000603 }
cristyc57f6942010-11-12 01:47:39 +0000604 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000605 break;
606 }
cristyc57f6942010-11-12 01:47:39 +0000607 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000608 XDestroyImage(annotate_ximage);
609 /*
610 Determine annotate geometry.
611 */
612 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
613 if ((width != (unsigned int) annotate_image->columns) ||
614 (height != (unsigned int) annotate_image->rows))
615 {
616 char
617 image_geometry[MaxTextExtent];
618
619 /*
620 Scale image.
621 */
cristyb51dff52011-05-19 16:55:47 +0000622 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000623 width,height);
624 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
625 }
626 if (annotate_info->degrees != 0.0)
627 {
628 Image
629 *rotate_image;
630
631 int
632 rotations;
633
634 MagickRealType
635 normalized_degrees;
636
637 /*
638 Rotate image.
639 */
640 rotate_image=
641 RotateImage(annotate_image,annotate_info->degrees,&image->exception);
642 if (rotate_image == (Image *) NULL)
643 return(MagickFalse);
644 annotate_image=DestroyImage(annotate_image);
645 annotate_image=rotate_image;
646 /*
647 Annotation is relative to the degree of rotation.
648 */
649 normalized_degrees=annotate_info->degrees;
650 while (normalized_degrees < -45.0)
651 normalized_degrees+=360.0;
652 for (rotations=0; normalized_degrees > 45.0; rotations++)
653 normalized_degrees-=90.0;
654 switch (rotations % 4)
655 {
656 default:
657 case 0:
658 break;
659 case 1:
660 {
661 /*
662 Rotate 90 degrees.
663 */
664 x-=(int) annotate_image->columns/2;
665 y+=(int) annotate_image->columns/2;
666 break;
667 }
668 case 2:
669 {
670 /*
671 Rotate 180 degrees.
672 */
673 x=x-(int) annotate_image->columns;
674 break;
675 }
676 case 3:
677 {
678 /*
679 Rotate 270 degrees.
680 */
681 x=x-(int) annotate_image->columns/2;
682 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
683 break;
684 }
685 }
686 }
687 /*
688 Composite text onto the image.
689 */
690 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
691 matte=image->matte;
692 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristyc57f6942010-11-12 01:47:39 +0000693 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +0000694 image->matte=matte;
695 annotate_image=DestroyImage(annotate_image);
696 return(MagickTrue);
697}
698
699/*
700%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
701% %
702% %
703% %
704% X B e s t F o n t %
705% %
706% %
707% %
708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
709%
710% XBestFont() returns the "best" font. "Best" is defined as a font specified
711% in the X resource database or a font such that the text width displayed
712% with the font does not exceed the specified maximum width.
713%
714% The format of the XBestFont method is:
715%
716% XFontStruct *XBestFont(Display *display,
717% const XResourceInfo *resource_info,const MagickBooleanType text_font)
718%
719% A description of each parameter follows:
720%
721% o font: XBestFont returns a pointer to a XFontStruct structure.
722%
723% o display: Specifies a connection to an X server; returned from
724% XOpenDisplay.
725%
726% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
727%
728% o text_font: True is font should be mono-spaced (typewriter style).
729%
cristy3ed852e2009-09-05 21:47:34 +0000730*/
731
732static char **FontToList(char *font)
733{
734 char
735 **fontlist;
736
737 register char
738 *p,
739 *q;
740
741 register int
742 i;
743
744 unsigned int
745 fonts;
746
747 if (font == (char *) NULL)
748 return((char **) NULL);
749 /*
750 Convert string to an ASCII list.
751 */
752 fonts=1U;
753 for (p=font; *p != '\0'; p++)
754 if ((*p == ':') || (*p == ';') || (*p == ','))
755 fonts++;
756 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
757 if (fontlist == (char **) NULL)
758 {
759 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
760 font);
761 return((char **) NULL);
762 }
763 p=font;
764 for (i=0; i < (int) fonts; i++)
765 {
766 for (q=p; *q != '\0'; q++)
767 if ((*q == ':') || (*q == ';') || (*q == ','))
768 break;
769 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
770 sizeof(*fontlist[i]));
771 if (fontlist[i] == (char *) NULL)
772 {
773 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
774 font);
775 return((char **) NULL);
776 }
777 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
778 p=q+1;
779 }
780 fontlist[i]=(char *) NULL;
781 return(fontlist);
782}
783
784MagickExport XFontStruct *XBestFont(Display *display,
785 const XResourceInfo *resource_info,const MagickBooleanType text_font)
786{
787 static const char
788 *Fonts[]=
789 {
790 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
791 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
792 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
793 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
794 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
795 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
796 "variable",
797 "fixed",
798 (char *) NULL
799 },
800 *TextFonts[]=
801 {
802 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
803 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
804 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
805 "fixed",
806 (char *) NULL
807 };
808
809 char
810 *font_name;
811
812 register const char
813 **p;
814
815 XFontStruct
816 *font_info;
817
818 font_info=(XFontStruct *) NULL;
819 font_name=resource_info->font;
820 if (text_font != MagickFalse)
821 font_name=resource_info->text_font;
822 if ((font_name != (char *) NULL) && (*font_name != '\0'))
823 {
824 char
825 **fontlist;
826
827 register int
828 i;
829
830 /*
831 Load preferred font specified in the X resource database.
832 */
833 fontlist=FontToList(font_name);
834 if (fontlist != (char **) NULL)
835 {
836 for (i=0; fontlist[i] != (char *) NULL; i++)
837 {
838 if (font_info == (XFontStruct *) NULL)
839 font_info=XLoadQueryFont(display,fontlist[i]);
840 fontlist[i]=DestroyString(fontlist[i]);
841 }
842 fontlist=(char **) RelinquishMagickMemory(fontlist);
843 }
844 if (font_info == (XFontStruct *) NULL)
845 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
846 }
847 /*
848 Load fonts from list of fonts until one is found.
849 */
850 p=Fonts;
851 if (text_font != MagickFalse)
852 p=TextFonts;
853 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
854 p++;
855 while (*p != (char *) NULL)
856 {
857 if (font_info != (XFontStruct *) NULL)
858 break;
859 font_info=XLoadQueryFont(display,(char *) *p);
860 p++;
861 }
862 return(font_info);
863}
864
865/*
866%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
867% %
868% %
869% %
870% X B e s t I c o n S i z e %
871% %
872% %
873% %
874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875%
876% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
877% size that maintains the aspect ratio of the image. If the window manager
878% has preferred icon sizes, one of the preferred sizes is used.
879%
880% The format of the XBestIconSize method is:
881%
882% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
883%
884% A description of each parameter follows:
885%
886% o display: Specifies a connection to an X server; returned from
887% XOpenDisplay.
888%
889% o image: the image.
890%
891*/
892MagickExport void XBestIconSize(Display *display,XWindowInfo *window,
893 Image *image)
894{
895 int
896 i,
897 number_sizes;
898
899 MagickRealType
900 scale_factor;
901
902 unsigned int
903 height,
904 icon_height,
905 icon_width,
906 width;
907
908 Window
909 root_window;
910
911 XIconSize
912 *icon_size,
913 *size_list;
914
915 /*
916 Determine if the window manager has specified preferred icon sizes.
917 */
918 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
919 assert(display != (Display *) NULL);
920 assert(window != (XWindowInfo *) NULL);
921 assert(image != (Image *) NULL);
922 window->width=MaxIconSize;
923 window->height=MaxIconSize;
924 icon_size=(XIconSize *) NULL;
925 number_sizes=0;
926 root_window=XRootWindow(display,window->screen);
927 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
928 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
929 icon_size=size_list;
930 if (icon_size == (XIconSize *) NULL)
931 {
932 /*
933 Window manager does not restrict icon size.
934 */
935 icon_size=XAllocIconSize();
936 if (icon_size == (XIconSize *) NULL)
937 {
938 ThrowXWindowFatalException(ResourceLimitError,
939 "MemoryAllocationFailed",image->filename);
940 return;
941 }
942 icon_size->min_width=1;
943 icon_size->max_width=MaxIconSize;
944 icon_size->min_height=1;
945 icon_size->max_height=MaxIconSize;
946 icon_size->width_inc=1;
947 icon_size->height_inc=1;
948 }
949 /*
950 Determine aspect ratio of image.
951 */
952 width=(unsigned int) image->columns;
953 height=(unsigned int) image->rows;
954 i=0;
955 if (window->crop_geometry)
956 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
957 /*
958 Look for an icon size that maintains the aspect ratio of image.
959 */
960 scale_factor=(MagickRealType) icon_size->max_width/width;
961 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
962 scale_factor=(MagickRealType) icon_size->max_height/height;
963 icon_width=(unsigned int) icon_size->min_width;
964 while ((int) icon_width < icon_size->max_width)
965 {
966 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
967 break;
968 icon_width+=icon_size->width_inc;
969 }
970 icon_height=(unsigned int) icon_size->min_height;
971 while ((int) icon_height < icon_size->max_height)
972 {
973 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
974 break;
975 icon_height+=icon_size->height_inc;
976 }
977 (void) XFree((void *) icon_size);
978 window->width=icon_width;
979 window->height=icon_height;
980}
981
982/*
983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
984% %
985% %
986% %
987% X B e s t P i x e l %
988% %
989% %
990% %
991%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992%
993% XBestPixel() returns a pixel from an array of pixels that is closest to the
994% requested color. If the color array is NULL, the colors are obtained from
995% the X server.
996%
997% The format of the XBestPixel method is:
998%
999% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1000% unsigned int number_colors,XColor *color)
1001%
1002% A description of each parameter follows:
1003%
1004% o pixel: XBestPixel returns the pixel value closest to the requested
1005% color.
1006%
1007% o display: Specifies a connection to an X server; returned from
1008% XOpenDisplay.
1009%
1010% o colormap: Specifies the ID of the X server colormap.
1011%
1012% o colors: Specifies an array of XColor structures.
1013%
1014% o number_colors: Specifies the number of XColor structures in the
1015% color definition array.
1016%
1017% o color: Specifies the desired RGB value to find in the colors array.
1018%
1019*/
1020MagickExport void XBestPixel(Display *display,const Colormap colormap,
1021 XColor *colors,unsigned int number_colors,XColor *color)
1022{
1023 MagickBooleanType
1024 query_server;
1025
cristy4c08aed2011-07-01 19:47:50 +00001026 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001027 pixel;
1028
1029 MagickRealType
1030 min_distance;
1031
1032 register MagickRealType
1033 distance;
1034
1035 register int
1036 i,
1037 j;
1038
1039 Status
1040 status;
1041
1042 /*
1043 Find closest representation for the requested RGB color.
1044 */
1045 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1046 assert(display != (Display *) NULL);
1047 assert(color != (XColor *) NULL);
1048 status=XAllocColor(display,colormap,color);
1049 if (status != False)
1050 return;
1051 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1052 if (query_server != MagickFalse)
1053 {
1054 /*
1055 Read X server colormap.
1056 */
1057 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1058 if (colors == (XColor *) NULL)
1059 {
1060 ThrowXWindowFatalException(ResourceLimitError,
1061 "MemoryAllocationFailed","...");
1062 return;
1063 }
1064 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001065 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001066 if (number_colors > 256)
1067 number_colors=256;
1068 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1069 }
1070 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1071 QuantumRange+1.0);
1072 j=0;
1073 for (i=0; i < (int) number_colors; i++)
1074 {
1075 pixel.red=colors[i].red-(MagickRealType) color->red;
1076 distance=pixel.red*pixel.red;
1077 if (distance > min_distance)
1078 continue;
1079 pixel.green=colors[i].green-(MagickRealType) color->green;
1080 distance+=pixel.green*pixel.green;
1081 if (distance > min_distance)
1082 continue;
1083 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1084 distance+=pixel.blue*pixel.blue;
1085 if (distance > min_distance)
1086 continue;
1087 min_distance=distance;
1088 color->pixel=colors[i].pixel;
1089 j=i;
1090 }
1091 (void) XAllocColor(display,colormap,&colors[j]);
1092 if (query_server != MagickFalse)
1093 colors=(XColor *) RelinquishMagickMemory(colors);
1094}
1095
1096/*
1097%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1098% %
1099% %
1100% %
1101% X B e s t V i s u a l I n f o %
1102% %
1103% %
1104% %
1105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1106%
1107% XBestVisualInfo() returns visual information for a visual that is the "best"
1108% the server supports. "Best" is defined as:
1109%
1110% 1. Restrict the visual list to those supported by the default screen.
1111%
1112% 2. If a visual type is specified, restrict the visual list to those of
1113% that type.
1114%
1115% 3. If a map type is specified, choose the visual that matches the id
1116% specified by the Standard Colormap.
1117%
1118% 4 From the list of visuals, choose one that can display the most
1119% simultaneous colors. If more than one visual can display the same
1120% number of simultaneous colors, one is chosen based on a rank.
1121%
1122% The format of the XBestVisualInfo method is:
1123%
1124% XVisualInfo *XBestVisualInfo(Display *display,
1125% XStandardColormap *map_info,XResourceInfo *resource_info)
1126%
1127% A description of each parameter follows:
1128%
1129% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1130% structure.
1131%
1132% o display: Specifies a connection to an X server; returned from
1133% XOpenDisplay.
1134%
1135% o map_info: If map_type is specified, this structure is initialized
1136% with info from the Standard Colormap.
1137%
1138% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1139%
1140*/
1141
1142static inline int MagickMax(const int x,const int y)
1143{
1144 if (x > y)
1145 return(x);
1146 return(y);
1147}
1148
cristybb503372010-05-27 20:51:26 +00001149static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001150 const unsigned int y)
1151{
1152 if (x < y)
1153 return(x);
1154 return(y);
1155}
1156
1157MagickExport XVisualInfo *XBestVisualInfo(Display *display,
1158 XStandardColormap *map_info,XResourceInfo *resource_info)
1159{
1160#define MaxStandardColormaps 7
1161#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1162 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1163 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1164 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1165
1166 char
1167 *map_type,
1168 *visual_type;
1169
cristyc57f6942010-11-12 01:47:39 +00001170 int
1171 visual_mask;
1172
cristy3ed852e2009-09-05 21:47:34 +00001173 register int
1174 i;
1175
cristy8891f9c2010-06-04 23:32:17 +00001176 size_t
1177 one;
1178
cristy3ed852e2009-09-05 21:47:34 +00001179 static int
1180 number_visuals;
1181
1182 static XVisualInfo
1183 visual_template;
1184
1185 XVisualInfo
1186 *visual_info,
1187 *visual_list;
1188
1189 /*
1190 Restrict visual search by screen number.
1191 */
1192 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1193 assert(display != (Display *) NULL);
1194 assert(map_info != (XStandardColormap *) NULL);
1195 assert(resource_info != (XResourceInfo *) NULL);
1196 map_type=resource_info->map_type;
1197 visual_type=resource_info->visual_type;
1198 visual_mask=VisualScreenMask;
1199 visual_template.screen=XDefaultScreen(display);
1200 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001201 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001202 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001203 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001204 visual_mask|=VisualDepthMask;
1205 if (visual_type != (char *) NULL)
1206 {
1207 /*
1208 Restrict visual search by class or visual id.
1209 */
1210 if (LocaleCompare("staticgray",visual_type) == 0)
1211 {
1212 visual_mask|=VisualClassMask;
1213 visual_template.klass=StaticGray;
1214 }
1215 else
1216 if (LocaleCompare("grayscale",visual_type) == 0)
1217 {
1218 visual_mask|=VisualClassMask;
1219 visual_template.klass=GrayScale;
1220 }
1221 else
1222 if (LocaleCompare("staticcolor",visual_type) == 0)
1223 {
1224 visual_mask|=VisualClassMask;
1225 visual_template.klass=StaticColor;
1226 }
1227 else
1228 if (LocaleCompare("pseudocolor",visual_type) == 0)
1229 {
1230 visual_mask|=VisualClassMask;
1231 visual_template.klass=PseudoColor;
1232 }
1233 else
1234 if (LocaleCompare("truecolor",visual_type) == 0)
1235 {
1236 visual_mask|=VisualClassMask;
1237 visual_template.klass=TrueColor;
1238 }
1239 else
1240 if (LocaleCompare("directcolor",visual_type) == 0)
1241 {
1242 visual_mask|=VisualClassMask;
1243 visual_template.klass=DirectColor;
1244 }
1245 else
1246 if (LocaleCompare("default",visual_type) == 0)
1247 {
1248 visual_mask|=VisualIDMask;
1249 visual_template.visualid=XVisualIDFromVisual(
1250 XDefaultVisual(display,XDefaultScreen(display)));
1251 }
1252 else
1253 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1254 {
1255 visual_mask|=VisualIDMask;
1256 visual_template.visualid=
1257 strtol(visual_type,(char **) NULL,0);
1258 }
1259 else
1260 ThrowXWindowFatalException(XServerError,
1261 "UnrecognizedVisualSpecifier",visual_type);
1262 }
1263 /*
1264 Get all visuals that meet our criteria so far.
1265 */
1266 number_visuals=0;
1267 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1268 &number_visuals);
1269 visual_mask=VisualScreenMask | VisualIDMask;
1270 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1271 {
1272 /*
1273 Failed to get visual; try using the default visual.
1274 */
1275 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1276 visual_type);
1277 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1278 XDefaultScreen(display)));
1279 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1280 &number_visuals);
1281 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1282 return((XVisualInfo *) NULL);
1283 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1284 XVisualClassName(visual_list->klass));
1285 }
1286 resource_info->color_recovery=MagickFalse;
1287 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1288 {
1289 Atom
1290 map_property;
1291
1292 char
1293 map_name[MaxTextExtent];
1294
1295 int
1296 j,
1297 number_maps;
1298
1299 Status
1300 status;
1301
1302 Window
1303 root_window;
1304
1305 XStandardColormap
1306 *map_list;
1307
1308 /*
1309 Choose a visual associated with a standard colormap.
1310 */
1311 root_window=XRootWindow(display,XDefaultScreen(display));
1312 status=False;
1313 if (LocaleCompare(map_type,"list") != 0)
1314 {
1315 /*
1316 User specified Standard Colormap.
1317 */
cristyb51dff52011-05-19 16:55:47 +00001318 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001319 "RGB_%s_MAP",map_type);
1320 LocaleUpper(map_name);
1321 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1322 if (map_property != (Atom) NULL)
1323 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1324 map_property);
1325 }
1326 else
1327 {
1328 static const char
1329 *colormap[MaxStandardColormaps]=
1330 {
1331 "_HP_RGB_SMOOTH_MAP_LIST",
1332 "RGB_BEST_MAP",
1333 "RGB_DEFAULT_MAP",
1334 "RGB_GRAY_MAP",
1335 "RGB_RED_MAP",
1336 "RGB_GREEN_MAP",
1337 "RGB_BLUE_MAP",
1338 };
1339
1340 /*
1341 Choose a standard colormap from a list.
1342 */
1343 for (i=0; i < MaxStandardColormaps; i++)
1344 {
1345 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1346 if (map_property == (Atom) NULL)
1347 continue;
1348 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1349 map_property);
1350 if (status != False)
1351 break;
1352 }
1353 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1354 }
1355 if (status == False)
1356 {
1357 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1358 map_type);
1359 return((XVisualInfo *) NULL);
1360 }
1361 /*
1362 Search all Standard Colormaps and visuals for ids that match.
1363 */
1364 *map_info=map_list[0];
1365#if !defined(PRE_R4_ICCCM)
1366 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1367 for (i=0; i < number_maps; i++)
1368 for (j=0; j < number_visuals; j++)
1369 if (map_list[i].visualid ==
1370 XVisualIDFromVisual(visual_list[j].visual))
1371 {
1372 *map_info=map_list[i];
1373 visual_template.visualid=XVisualIDFromVisual(
1374 visual_list[j].visual);
1375 break;
1376 }
1377 if (map_info->visualid != visual_template.visualid)
1378 {
1379 ThrowXWindowFatalException(XServerError,
1380 "UnableToMatchVisualToStandardColormap",map_type);
1381 return((XVisualInfo *) NULL);
1382 }
1383#endif
1384 if (map_info->colormap == (Colormap) NULL)
1385 {
1386 ThrowXWindowFatalException(XServerError,
1387 "StandardColormapIsNotInitialized",map_type);
1388 return((XVisualInfo *) NULL);
1389 }
1390 (void) XFree((void *) map_list);
1391 }
1392 else
1393 {
1394 static const unsigned int
1395 rank[]=
1396 {
1397 StaticGray,
1398 GrayScale,
1399 StaticColor,
1400 DirectColor,
1401 TrueColor,
1402 PseudoColor
1403 };
1404
1405 XVisualInfo
1406 *p;
1407
1408 /*
1409 Pick one visual that displays the most simultaneous colors.
1410 */
1411 visual_info=visual_list;
1412 p=visual_list;
1413 for (i=1; i < number_visuals; i++)
1414 {
1415 p++;
1416 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1417 visual_info=p;
1418 else
1419 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1420 if (rank[p->klass] > rank[visual_info->klass])
1421 visual_info=p;
1422 }
1423 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1424 }
1425 (void) XFree((void *) visual_list);
1426 /*
1427 Retrieve only one visual by its screen & id number.
1428 */
1429 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1430 &number_visuals);
1431 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1432 return((XVisualInfo *) NULL);
1433 return(visual_info);
1434}
1435
1436/*
1437%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1438% %
1439% %
1440% %
1441% X C h e c k D e f i n e C u r s o r %
1442% %
1443% %
1444% %
1445%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1446%
1447% XCheckDefineCursor() prevents cursor changes on the root window.
1448%
1449% The format of the XXCheckDefineCursor method is:
1450%
1451% XCheckDefineCursor(display,window,cursor)
1452%
1453% A description of each parameter follows:
1454%
1455% o display: Specifies a connection to an X server; returned from
1456% XOpenDisplay.
1457%
1458% o window: the window.
1459%
1460% o cursor: the cursor.
1461%
1462*/
1463MagickExport int XCheckDefineCursor(Display *display,Window window,
1464 Cursor cursor)
1465{
1466 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1467 assert(display != (Display *) NULL);
1468 if (window == XRootWindow(display,XDefaultScreen(display)))
1469 return(0);
1470 return(XDefineCursor(display,window,cursor));
1471}
1472
1473/*
1474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1475% %
1476% %
1477% %
1478% X C h e c k R e f r e s h W i n d o w s %
1479% %
1480% %
1481% %
1482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1483%
1484% XCheckRefreshWindows() checks the X server for exposure events for a
1485% particular window and updates the areassociated with the exposure event.
1486%
1487% The format of the XCheckRefreshWindows method is:
1488%
1489% void XCheckRefreshWindows(Display *display,XWindows *windows)
1490%
1491% A description of each parameter follows:
1492%
1493% o display: Specifies a connection to an X server; returned from
1494% XOpenDisplay.
1495%
1496% o windows: Specifies a pointer to a XWindows structure.
1497%
1498*/
1499MagickExport void XCheckRefreshWindows(Display *display,XWindows *windows)
1500{
1501 Window
1502 id;
1503
1504 XEvent
1505 event;
1506
1507 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1508 assert(display != (Display *) NULL);
1509 assert(windows != (XWindows *) NULL);
1510 XDelay(display,SuspendTime);
1511 id=windows->command.id;
1512 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1513 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1514 id=windows->image.id;
1515 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1516 XRefreshWindow(display,&windows->image,&event);
1517 XDelay(display,SuspendTime << 1);
1518 id=windows->command.id;
1519 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1520 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1521 id=windows->image.id;
1522 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1523 XRefreshWindow(display,&windows->image,&event);
1524}
1525
1526/*
1527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1528% %
1529% %
1530% %
1531% X C l i e n t M e s s a g e %
1532% %
1533% %
1534% %
1535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1536%
1537% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1538% initialized with a particular protocol type and atom.
1539%
1540% The format of the XClientMessage function is:
1541%
1542% XClientMessage(display,window,protocol,reason,timestamp)
1543%
1544% A description of each parameter follows:
1545%
1546% o display: Specifies a pointer to the Display structure; returned from
1547% XOpenDisplay.
1548%
1549% o window: Specifies a pointer to a Window structure.
1550%
1551% o protocol: Specifies an atom value.
1552%
1553% o reason: Specifies an atom value which is the reason to send.
1554%
1555% o timestamp: Specifies a value of type Time.
1556%
1557*/
1558MagickExport void XClientMessage(Display *display,const Window window,
1559 const Atom protocol,const Atom reason,const Time timestamp)
1560{
1561 XClientMessageEvent
1562 client_event;
1563
1564 assert(display != (Display *) NULL);
1565 client_event.type=ClientMessage;
1566 client_event.window=window;
1567 client_event.message_type=protocol;
1568 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001569 client_event.data.l[0]=(long) reason;
1570 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001571 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1572}
1573
1574/*
1575%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1576% %
1577% %
1578% %
1579+ X C l i e n t W i n d o w %
1580% %
1581% %
1582% %
1583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1584%
1585% XClientWindow() finds a window, at or below the specified window, which has
1586% a WM_STATE property. If such a window is found, it is returned, otherwise
1587% the argument window is returned.
1588%
1589% The format of the XClientWindow function is:
1590%
1591% client_window=XClientWindow(display,target_window)
1592%
1593% A description of each parameter follows:
1594%
1595% o client_window: XClientWindow returns a window, at or below the specified
1596% window, which has a WM_STATE property otherwise the argument
1597% target_window is returned.
1598%
1599% o display: Specifies a pointer to the Display structure; returned from
1600% XOpenDisplay.
1601%
1602% o target_window: Specifies the window to find a WM_STATE property.
1603%
cristy3ed852e2009-09-05 21:47:34 +00001604*/
1605static Window XClientWindow(Display *display,Window target_window)
1606{
1607 Atom
1608 state,
1609 type;
1610
1611 int
1612 format;
1613
1614 Status
1615 status;
1616
1617 unsigned char
1618 *data;
1619
cristyf2faecf2010-05-28 19:19:36 +00001620 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001621 after,
1622 number_items;
1623
1624 Window
1625 client_window;
1626
1627 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1628 assert(display != (Display *) NULL);
1629 state=XInternAtom(display,"WM_STATE",MagickTrue);
1630 if (state == (Atom) NULL)
1631 return(target_window);
1632 type=(Atom) NULL;
1633 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1634 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1635 if ((status == Success) && (type != (Atom) NULL))
1636 return(target_window);
1637 client_window=XWindowByProperty(display,target_window,state);
1638 if (client_window == (Window) NULL)
1639 return(target_window);
1640 return(client_window);
1641}
1642
1643/*
1644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1645% %
1646% %
1647% %
cristyf34a1452009-10-24 22:29:27 +00001648+ X C o m p o n e n t T e r m i n u s %
1649% %
1650% %
1651% %
1652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1653%
1654% XComponentTerminus() destroys the module component.
1655%
1656% The format of the XComponentTerminus method is:
1657%
1658% XComponentTerminus(void)
1659%
1660*/
1661MagickExport void XComponentTerminus(void)
1662{
1663 DestroyXResources();
1664}
1665
1666/*
1667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1668% %
1669% %
1670% %
cristy3ed852e2009-09-05 21:47:34 +00001671% X C o n f i g u r e I m a g e C o l o r m a p %
1672% %
1673% %
1674% %
1675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1676%
1677% XConfigureImageColormap() creates a new X colormap.
1678%
1679% The format of the XConfigureImageColormap method is:
1680%
1681% void XConfigureImageColormap(Display *display,
1682% XResourceInfo *resource_info,XWindows *windows,Image *image)
1683%
1684% A description of each parameter follows:
1685%
1686% o display: Specifies a connection to an X server; returned from
1687% XOpenDisplay.
1688%
1689% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1690%
1691% o windows: Specifies a pointer to a XWindows structure.
1692%
1693% o image: the image.
1694%
1695*/
1696MagickExport void XConfigureImageColormap(Display *display,
1697 XResourceInfo *resource_info,XWindows *windows,Image *image)
1698{
1699 Colormap
1700 colormap;
1701
1702 /*
1703 Make standard colormap.
1704 */
1705 XSetCursorState(display,windows,MagickTrue);
1706 XCheckRefreshWindows(display,windows);
1707 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1708 windows->map_info,windows->pixel_info);
1709 colormap=windows->map_info->colormap;
1710 (void) XSetWindowColormap(display,windows->image.id,colormap);
1711 (void) XSetWindowColormap(display,windows->command.id,colormap);
1712 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1713 if (windows->magnify.mapped != MagickFalse)
1714 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1715 if (windows->pan.mapped != MagickFalse)
1716 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1717 XSetCursorState(display,windows,MagickFalse);
1718 XClientMessage(display,windows->image.id,windows->im_protocols,
1719 windows->im_update_colormap,CurrentTime);
1720}
1721
1722/*
1723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1724% %
1725% %
1726% %
1727% X C o n s t r a i n W i n d o w P o s i t i o n %
1728% %
1729% %
1730% %
1731%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1732%
1733% XConstrainWindowPosition() assures a window is positioned within the X
1734% server boundaries.
1735%
1736% The format of the XConstrainWindowPosition method is:
1737%
1738% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1739%
1740% A description of each parameter follows:
1741%
1742% o display: Specifies a pointer to the Display structure; returned from
1743% XOpenDisplay.
1744%
1745% o window_info: Specifies a pointer to a XWindowInfo structure.
1746%
1747*/
1748MagickExport void XConstrainWindowPosition(Display *display,
1749 XWindowInfo *window_info)
1750{
1751 int
1752 limit;
1753
1754 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1755 assert(display != (Display *) NULL);
1756 assert(window_info != (XWindowInfo *) NULL);
1757 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1758 if (window_info->x < 0)
1759 window_info->x=0;
1760 else
1761 if (window_info->x > (int) limit)
1762 window_info->x=(int) limit;
1763 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1764 if (window_info->y < 0)
1765 window_info->y=0;
1766 else
1767 if (window_info->y > limit)
1768 window_info->y=limit;
1769}
1770
1771/*
1772%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1773% %
1774% %
1775% %
1776% X D e l a y %
1777% %
1778% %
1779% %
1780%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1781%
1782% XDelay() suspends program execution for the number of milliseconds
1783% specified.
1784%
1785% The format of the Delay method is:
1786%
cristybb503372010-05-27 20:51:26 +00001787% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001788%
1789% A description of each parameter follows:
1790%
1791% o display: Specifies a pointer to the Display structure; returned from
1792% XOpenDisplay.
1793%
1794% o milliseconds: Specifies the number of milliseconds to delay before
1795% returning.
1796%
1797*/
cristybb503372010-05-27 20:51:26 +00001798MagickExport void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001799{
1800 assert(display != (Display *) NULL);
1801 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001802 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001803}
1804
1805/*
1806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1807% %
1808% %
1809% %
1810% X D e s t r o y R e s o u r c e I n f o %
1811% %
1812% %
1813% %
1814%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1815%
1816% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1817% structure.
1818%
1819% The format of the XDestroyResourceInfo method is:
1820%
1821% void XDestroyResourceInfo(XResourceInfo *resource_info)
1822%
1823% A description of each parameter follows:
1824%
1825% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1826%
1827*/
1828MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1829{
1830 if (resource_info->image_geometry != (char *) NULL)
1831 resource_info->image_geometry=(char *)
1832 RelinquishMagickMemory(resource_info->image_geometry);
1833 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1834 resource_info->quantize_info=DestroyQuantizeInfo(
1835 resource_info->quantize_info);
1836 if (resource_info->client_name != (char *) NULL)
1837 resource_info->client_name=(char *)
1838 RelinquishMagickMemory(resource_info->client_name);
1839 if (resource_info->name != (char *) NULL)
1840 resource_info->name=DestroyString(resource_info->name);
1841 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1842}
1843
1844/*
1845%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1846% %
1847% %
1848% %
1849% X D e s t r o y W i n d o w C o l o r s %
1850% %
1851% %
1852% %
1853%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1854%
1855% XDestroyWindowColors() frees X11 color resources previously saved on a
1856% window by XRetainWindowColors or programs like xsetroot.
1857%
1858% The format of the XDestroyWindowColors method is:
1859%
1860% void XDestroyWindowColors(Display *display,Window window)
1861%
1862% A description of each parameter follows:
1863%
1864% o display: Specifies a connection to an X server; returned from
1865% XOpenDisplay.
1866%
1867% o window: Specifies a pointer to a Window structure.
1868%
1869*/
1870MagickExport void XDestroyWindowColors(Display *display,Window window)
1871{
1872 Atom
1873 property,
1874 type;
1875
1876 int
1877 format;
1878
1879 Status
1880 status;
1881
1882 unsigned char
1883 *data;
1884
cristyf2faecf2010-05-28 19:19:36 +00001885 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001886 after,
1887 length;
1888
1889 /*
1890 If there are previous resources on the root window, destroy them.
1891 */
1892 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1893 assert(display != (Display *) NULL);
1894 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1895 if (property == (Atom) NULL)
1896 {
1897 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1898 "_XSETROOT_ID");
1899 return;
1900 }
1901 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1902 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1903 if (status != Success)
1904 return;
1905 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1906 {
1907 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1908 (void) XDeleteProperty(display,window,property);
1909 }
1910 if (type != None)
1911 (void) XFree((void *) data);
1912}
1913
1914/*
1915%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1916% %
1917% %
1918% %
1919% X D i s p l a y I m a g e I n f o %
1920% %
1921% %
1922% %
1923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1924%
1925% XDisplayImageInfo() displays information about an X image.
1926%
1927% The format of the XDisplayImageInfo method is:
1928%
1929% void XDisplayImageInfo(Display *display,
1930% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1931% Image *image)
1932%
1933% A description of each parameter follows:
1934%
1935% o display: Specifies a connection to an X server; returned from
1936% XOpenDisplay.
1937%
1938% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1939%
1940% o windows: Specifies a pointer to a XWindows structure.
1941%
1942% o undo_image: the undo image.
1943%
1944% o image: the image.
1945%
1946*/
1947MagickExport void XDisplayImageInfo(Display *display,
1948 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1949 Image *image)
1950{
1951 char
1952 filename[MaxTextExtent],
1953 *text,
1954 **textlist;
1955
1956 FILE
1957 *file;
1958
1959 int
1960 unique_file;
1961
cristybb503372010-05-27 20:51:26 +00001962 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001963 i;
1964
cristybb503372010-05-27 20:51:26 +00001965 size_t
cristy3ed852e2009-09-05 21:47:34 +00001966 number_pixels;
1967
cristy9d314ff2011-03-09 01:30:28 +00001968 ssize_t
1969 bytes;
1970
1971 unsigned int
1972 levels;
1973
cristy3ed852e2009-09-05 21:47:34 +00001974 /*
1975 Write info about the X server to a file.
1976 */
1977 assert(display != (Display *) NULL);
1978 assert(resource_info != (XResourceInfo *) NULL);
1979 assert(windows != (XWindows *) NULL);
1980 assert(image != (Image *) NULL);
1981 if (image->debug)
1982 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1983 file=(FILE *) NULL;
1984 unique_file=AcquireUniqueFileResource(filename);
1985 if (unique_file != -1)
1986 file=fdopen(unique_file,"w");
1987 if ((unique_file == -1) || (file == (FILE *) NULL))
1988 {
1989 XNoticeWidget(display,windows,"Unable to display image info",filename);
1990 return;
1991 }
1992 if (resource_info->gamma_correct != MagickFalse)
1993 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00001994 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00001995 resource_info->display_gamma);
1996 /*
1997 Write info about the X image to a file.
1998 */
cristyb51dff52011-05-19 16:55:47 +00001999 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002000 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002001 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002002 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002003 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002004 windows->visual_info->colormap_size);
2005 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002006 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002007 else
cristyb51dff52011-05-19 16:55:47 +00002008 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002009 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2010 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002011 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002012 (void) FormatLocaleFile(file," crop geometry: %s\n",
2013 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002014 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002015 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002016 else
cristyb51dff52011-05-19 16:55:47 +00002017 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002018 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002019 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002020 else
cristyb51dff52011-05-19 16:55:47 +00002021 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002022 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002023 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002024 else
cristyb51dff52011-05-19 16:55:47 +00002025 (void) FormatLocaleFile(file," shared memory: False\n");
2026 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002027 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002028 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002029 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002030 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002031 /*
2032 Write info about the undo cache to a file.
2033 */
2034 bytes=0;
2035 for (levels=0; undo_image != (Image *) NULL; levels++)
2036 {
2037 number_pixels=undo_image->list->columns*undo_image->list->rows;
2038 bytes+=number_pixels*sizeof(PixelPacket);
2039 undo_image=GetPreviousImageInList(undo_image);
2040 }
cristyb51dff52011-05-19 16:55:47 +00002041 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002042 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2043 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002044 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002045 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002046 /*
2047 Write info about the image to a file.
2048 */
cristya4037272011-08-28 15:11:39 +00002049 (void) IdentifyImage(image,file,MagickTrue,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002050 (void) fclose(file);
2051 text=FileToString(filename,~0,&image->exception);
2052 (void) RelinquishUniqueFileResource(filename);
2053 if (text == (char *) NULL)
2054 {
2055 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2056 "UnableToDisplayImageInfo");
2057 return;
2058 }
2059 textlist=StringToList(text);
2060 if (textlist != (char **) NULL)
2061 {
2062 char
2063 title[MaxTextExtent];
2064
2065 /*
2066 Display information about the image in the Text View widget.
2067 */
2068 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002069 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002070 image->filename);
2071 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2072 (char const **) textlist);
2073 for (i=0; textlist[i] != (char *) NULL; i++)
2074 textlist[i]=DestroyString(textlist[i]);
2075 textlist=(char **) RelinquishMagickMemory(textlist);
2076 }
2077 text=DestroyString(text);
2078}
2079
2080/*
2081%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2082% %
2083% %
2084% %
2085+ X D i t h e r I m a g e %
2086% %
2087% %
2088% %
2089%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2090%
2091% XDitherImage() dithers the reference image as required by the HP Color
2092% Recovery algorithm. The color values are quantized to 3 bits of red and
2093% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2094% standard colormap.
2095%
2096% The format of the XDitherImage method is:
2097%
2098% void XDitherImage(Image *image,XImage *ximage)
2099%
2100% A description of each parameter follows:
2101%
2102% o image: the image.
2103%
2104% o ximage: Specifies a pointer to a XImage structure; returned from
2105% XCreateImage.
2106%
cristy3ed852e2009-09-05 21:47:34 +00002107*/
2108static void XDitherImage(Image *image,XImage *ximage)
2109{
2110 static const short int
2111 dither_red[2][16]=
2112 {
2113 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2114 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2115 },
2116 dither_green[2][16]=
2117 {
2118 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2119 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2120 },
2121 dither_blue[2][16]=
2122 {
2123 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2124 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2125 };
2126
cristyc57f6942010-11-12 01:47:39 +00002127 CacheView
2128 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002129
2130 int
cristyc57f6942010-11-12 01:47:39 +00002131 value,
cristy3ed852e2009-09-05 21:47:34 +00002132 y;
2133
cristyc57f6942010-11-12 01:47:39 +00002134 PixelPacket
2135 color;
cristy3ed852e2009-09-05 21:47:34 +00002136
2137 register char
2138 *q;
2139
cristy4c08aed2011-07-01 19:47:50 +00002140 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002141 *p;
2142
2143 register int
2144 i,
2145 j,
2146 x;
2147
2148 unsigned int
2149 scanline_pad;
2150
cristybb503372010-05-27 20:51:26 +00002151 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002152 pixel;
2153
2154 unsigned char
2155 *blue_map[2][16],
2156 *green_map[2][16],
2157 *red_map[2][16];
2158
2159 /*
2160 Allocate and initialize dither maps.
2161 */
2162 for (i=0; i < 2; i++)
2163 for (j=0; j < 16; j++)
2164 {
2165 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2166 sizeof(*red_map));
2167 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2168 sizeof(*green_map));
2169 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2170 sizeof(*blue_map));
2171 if ((red_map[i][j] == (unsigned char *) NULL) ||
2172 (green_map[i][j] == (unsigned char *) NULL) ||
2173 (blue_map[i][j] == (unsigned char *) NULL))
2174 {
2175 ThrowXWindowFatalException(ResourceLimitError,
2176 "MemoryAllocationFailed",image->filename);
2177 return;
2178 }
2179 }
2180 /*
2181 Initialize dither tables.
2182 */
2183 for (i=0; i < 2; i++)
2184 for (j=0; j < 16; j++)
2185 for (x=0; x < 256; x++)
2186 {
2187 value=x-16;
2188 if (x < 48)
2189 value=x/2+8;
2190 value+=dither_red[i][j];
2191 red_map[i][j][x]=(unsigned char)
2192 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2193 value=x-16;
2194 if (x < 48)
2195 value=x/2+8;
2196 value+=dither_green[i][j];
2197 green_map[i][j][x]=(unsigned char)
2198 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2199 value=x-32;
2200 if (x < 112)
2201 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002202 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002203 blue_map[i][j][x]=(unsigned char)
2204 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2205 }
2206 /*
2207 Dither image.
2208 */
2209 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002210 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002211 i=0;
2212 j=0;
2213 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002214 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002215 for (y=0; y < (int) image->rows; y++)
2216 {
cristyc57f6942010-11-12 01:47:39 +00002217 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2218 &image->exception);
cristy4c08aed2011-07-01 19:47:50 +00002219 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002220 break;
2221 for (x=0; x < (int) image->columns; x++)
2222 {
cristyce70c172010-01-07 17:15:30 +00002223 color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002224 ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002225 color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002226 ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002227 color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002228 ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002229 pixel=(size_t) (((size_t) color.red & 0xe0) |
2230 (((size_t) color.green & 0xe0) >> 3) |
2231 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002232 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002233 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002234 j++;
2235 if (j == 16)
2236 j=0;
2237 }
2238 q+=scanline_pad;
2239 i++;
2240 if (i == 2)
2241 i=0;
2242 }
cristyc57f6942010-11-12 01:47:39 +00002243 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002244 /*
2245 Free allocated memory.
2246 */
2247 for (i=0; i < 2; i++)
2248 for (j=0; j < 16; j++)
2249 {
2250 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2251 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2252 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2253 }
2254}
2255
2256/*
2257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2258% %
2259% %
2260% %
2261% X D r a w I m a g e %
2262% %
2263% %
2264% %
2265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2266%
2267% XDrawImage() draws a line on the image.
2268%
2269% The format of the XDrawImage method is:
2270%
2271% MagickBooleanType XDrawImage(display,pixel,draw_info,image)
2272%
2273% A description of each parameter follows:
2274%
2275% o display: Specifies a connection to an X server; returned from
2276% XOpenDisplay.
2277%
2278% o pixel: Specifies a pointer to a XPixelInfo structure.
2279%
2280% o draw_info: Specifies a pointer to a XDrawInfo structure.
2281%
2282% o image: the image.
2283%
2284*/
2285MagickExport MagickBooleanType XDrawImage(Display *display,
2286 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
2287{
cristyc57f6942010-11-12 01:47:39 +00002288 CacheView
2289 *draw_view;
2290
cristy3ed852e2009-09-05 21:47:34 +00002291 ExceptionInfo
2292 *exception;
2293
2294 GC
2295 draw_context;
2296
2297 Image
2298 *draw_image;
2299
2300 int
2301 x,
2302 y;
2303
2304 MagickBooleanType
2305 matte;
2306
2307 Pixmap
2308 draw_pixmap;
2309
2310 unsigned int
2311 depth,
2312 height,
2313 width;
2314
2315 Window
2316 root_window;
2317
2318 XGCValues
2319 context_values;
2320
2321 XImage
2322 *draw_ximage;
2323
2324 /*
2325 Initialize drawd image.
2326 */
2327 assert(display != (Display *) NULL);
2328 assert(pixel != (XPixelInfo *) NULL);
2329 assert(draw_info != (XDrawInfo *) NULL);
2330 assert(image != (Image *) NULL);
2331 if (image->debug != MagickFalse)
2332 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2333 /*
2334 Initialize drawd pixmap.
2335 */
2336 root_window=XRootWindow(display,XDefaultScreen(display));
2337 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2338 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2339 draw_info->height,depth);
2340 if (draw_pixmap == (Pixmap) NULL)
2341 return(MagickFalse);
2342 /*
2343 Initialize graphics info.
2344 */
cristybb503372010-05-27 20:51:26 +00002345 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002346 context_values.foreground=0;
2347 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002348 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002349 (GCBackground | GCForeground | GCLineWidth),&context_values);
2350 if (draw_context == (GC) NULL)
2351 return(MagickFalse);
2352 /*
2353 Clear pixmap.
2354 */
2355 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2356 draw_info->height);
2357 /*
2358 Draw line to pixmap.
2359 */
2360 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002361 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002362 if (draw_info->stipple != (Pixmap) NULL)
2363 {
2364 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2365 (void) XSetStipple(display,draw_context,draw_info->stipple);
2366 }
cristy3ed852e2009-09-05 21:47:34 +00002367 switch (draw_info->element)
2368 {
2369 case PointElement:
2370 default:
2371 {
2372 (void) XDrawLines(display,draw_pixmap,draw_context,
2373 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2374 CoordModeOrigin);
2375 break;
2376 }
2377 case LineElement:
2378 {
2379 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2380 draw_info->line_info.y1,draw_info->line_info.x2,
2381 draw_info->line_info.y2);
2382 break;
2383 }
2384 case RectangleElement:
2385 {
2386 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2387 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2388 (unsigned int) draw_info->rectangle_info.width,
2389 (unsigned int) draw_info->rectangle_info.height);
2390 break;
2391 }
2392 case FillRectangleElement:
2393 {
2394 (void) XFillRectangle(display,draw_pixmap,draw_context,
2395 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2396 (unsigned int) draw_info->rectangle_info.width,
2397 (unsigned int) draw_info->rectangle_info.height);
2398 break;
2399 }
2400 case CircleElement:
2401 case EllipseElement:
2402 {
2403 (void) XDrawArc(display,draw_pixmap,draw_context,
2404 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2405 (unsigned int) draw_info->rectangle_info.width,
2406 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2407 break;
2408 }
2409 case FillCircleElement:
2410 case FillEllipseElement:
2411 {
2412 (void) XFillArc(display,draw_pixmap,draw_context,
2413 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2414 (unsigned int) draw_info->rectangle_info.width,
2415 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2416 break;
2417 }
2418 case PolygonElement:
2419 {
2420 XPoint
2421 *coordinate_info;
2422
2423 coordinate_info=draw_info->coordinate_info;
2424 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2425 (int) draw_info->number_coordinates,CoordModeOrigin);
2426 (void) XDrawLine(display,draw_pixmap,draw_context,
2427 coordinate_info[draw_info->number_coordinates-1].x,
2428 coordinate_info[draw_info->number_coordinates-1].y,
2429 coordinate_info[0].x,coordinate_info[0].y);
2430 break;
2431 }
2432 case FillPolygonElement:
2433 {
2434 (void) XFillPolygon(display,draw_pixmap,draw_context,
2435 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2436 CoordModeOrigin);
2437 break;
2438 }
2439 }
2440 (void) XFreeGC(display,draw_context);
2441 /*
2442 Initialize X image.
2443 */
2444 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2445 draw_info->height,AllPlanes,ZPixmap);
2446 if (draw_ximage == (XImage *) NULL)
2447 return(MagickFalse);
2448 (void) XFreePixmap(display,draw_pixmap);
2449 /*
2450 Initialize draw image.
2451 */
2452 draw_image=AcquireImage((ImageInfo *) NULL);
2453 if (draw_image == (Image *) NULL)
2454 return(MagickFalse);
2455 draw_image->columns=draw_info->width;
2456 draw_image->rows=draw_info->height;
2457 /*
2458 Transfer drawn X image to image.
2459 */
2460 width=(unsigned int) image->columns;
2461 height=(unsigned int) image->rows;
2462 x=0;
2463 y=0;
2464 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +00002465 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
2466 &draw_image->background_color,&image->exception);
cristy574cc262011-08-05 01:23:58 +00002467 if (SetImageStorageClass(draw_image,DirectClass,&image->exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002468 return(MagickFalse);
2469 draw_image->matte=MagickTrue;
2470 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +00002471 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002472 for (y=0; y < (int) draw_image->rows; y++)
2473 {
cristyc57f6942010-11-12 01:47:39 +00002474 register int
cristy3ed852e2009-09-05 21:47:34 +00002475 x;
2476
cristy4c08aed2011-07-01 19:47:50 +00002477 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002478 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002479
cristyc57f6942010-11-12 01:47:39 +00002480 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2481 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00002482 if (q == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002483 break;
cristyc57f6942010-11-12 01:47:39 +00002484 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002485 {
2486 if (XGetPixel(draw_ximage,x,y) == 0)
2487 {
2488 /*
2489 Set this pixel to the background color.
2490 */
cristy4c08aed2011-07-01 19:47:50 +00002491 SetPixelPacket(draw_image,&draw_image->background_color,q);
2492 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2493 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002494 }
2495 else
2496 {
2497 /*
2498 Set this pixel to the pen color.
2499 */
cristy4c08aed2011-07-01 19:47:50 +00002500 SetPixelRed(draw_image,ScaleShortToQuantum(
2501 pixel->pen_color.red),q);
2502 SetPixelGreen(draw_image,ScaleShortToQuantum(
2503 pixel->pen_color.green),q);
2504 SetPixelBlue(draw_image,ScaleShortToQuantum(
2505 pixel->pen_color.blue),q);
2506 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2507 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002508 }
cristyed231572011-07-14 02:18:59 +00002509 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002510 }
cristyc57f6942010-11-12 01:47:39 +00002511 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002512 break;
2513 }
cristyc57f6942010-11-12 01:47:39 +00002514 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002515 XDestroyImage(draw_ximage);
2516 /*
2517 Determine draw geometry.
2518 */
2519 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2520 if ((width != (unsigned int) draw_image->columns) ||
2521 (height != (unsigned int) draw_image->rows))
2522 {
2523 char
2524 image_geometry[MaxTextExtent];
2525
2526 /*
2527 Scale image.
2528 */
cristyb51dff52011-05-19 16:55:47 +00002529 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002530 width,height);
2531 (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
2532 }
2533 if (draw_info->degrees != 0.0)
2534 {
2535 Image
2536 *rotate_image;
2537
2538 int
2539 rotations;
2540
2541 MagickRealType
2542 normalized_degrees;
2543
2544 /*
2545 Rotate image.
2546 */
2547 rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
2548 if (rotate_image == (Image *) NULL)
2549 return(MagickFalse);
2550 draw_image=DestroyImage(draw_image);
2551 draw_image=rotate_image;
2552 /*
2553 Annotation is relative to the degree of rotation.
2554 */
2555 normalized_degrees=draw_info->degrees;
2556 while (normalized_degrees < -45.0)
2557 normalized_degrees+=360.0;
2558 for (rotations=0; normalized_degrees > 45.0; rotations++)
2559 normalized_degrees-=90.0;
2560 switch (rotations % 4)
2561 {
2562 default:
2563 case 0:
2564 break;
2565 case 1:
2566 {
2567 /*
2568 Rotate 90 degrees.
2569 */
2570 x=x-(int) draw_image->columns/2;
2571 y=y+(int) draw_image->columns/2;
2572 break;
2573 }
2574 case 2:
2575 {
2576 /*
2577 Rotate 180 degrees.
2578 */
2579 x=x-(int) draw_image->columns;
2580 break;
2581 }
2582 case 3:
2583 {
2584 /*
2585 Rotate 270 degrees.
2586 */
2587 x=x-(int) draw_image->columns/2;
2588 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2589 break;
2590 }
2591 }
2592 }
2593 /*
2594 Composite text onto the image.
2595 */
cristyc57f6942010-11-12 01:47:39 +00002596 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002597 for (y=0; y < (int) draw_image->rows; y++)
2598 {
cristyc57f6942010-11-12 01:47:39 +00002599 register int
cristy3ed852e2009-09-05 21:47:34 +00002600 x;
2601
cristy4c08aed2011-07-01 19:47:50 +00002602 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002603 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002604
cristyc57f6942010-11-12 01:47:39 +00002605 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2606 exception);
cristy4c08aed2011-07-01 19:47:50 +00002607 if (q == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002608 break;
cristyc57f6942010-11-12 01:47:39 +00002609 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002610 {
cristy4c08aed2011-07-01 19:47:50 +00002611 if (GetPixelAlpha(image,q) != TransparentAlpha)
2612 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002613 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002614 }
cristyc57f6942010-11-12 01:47:39 +00002615 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002616 break;
2617 }
cristyc57f6942010-11-12 01:47:39 +00002618 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002619 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2620 if (draw_info->stencil == TransparentStencil)
cristyc57f6942010-11-12 01:47:39 +00002621 (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,(ssize_t) x,
2622 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002623 else
2624 {
2625 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002626 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
2627 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002628 image->matte=matte;
2629 }
2630 draw_image=DestroyImage(draw_image);
2631 return(MagickTrue);
2632}
2633
2634/*
2635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2636% %
2637% %
2638% %
2639% X E r r o r %
2640% %
2641% %
2642% %
2643%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2644%
2645% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2646% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
2647% for XQueryColor. It returns MagickFalse in those cases. Otherwise it returns
2648% True.
2649%
2650% The format of the XError function is:
2651%
2652% XError(display,error)
2653%
2654% A description of each parameter follows:
2655%
2656% o display: Specifies a pointer to the Display structure; returned from
2657% XOpenDisplay.
2658%
2659% o error: Specifies the error event.
2660%
2661*/
2662
2663#if defined(__cplusplus) || defined(c_plusplus)
2664extern "C" {
2665#endif
2666
2667MagickExport int XError(Display *display,XErrorEvent *error)
2668{
2669 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2670 assert(display != (Display *) NULL);
2671 assert(error != (XErrorEvent *) NULL);
2672 xerror_alert=MagickTrue;
2673 switch (error->request_code)
2674 {
2675 case X_GetGeometry:
2676 {
2677 if ((int) error->error_code == BadDrawable)
2678 return(MagickFalse);
2679 break;
2680 }
2681 case X_GetWindowAttributes:
2682 case X_QueryTree:
2683 {
2684 if ((int) error->error_code == BadWindow)
2685 return(MagickFalse);
2686 break;
2687 }
2688 case X_QueryColors:
2689 {
2690 if ((int) error->error_code == BadValue)
2691 return(MagickFalse);
2692 break;
2693 }
2694 }
2695 return(MagickTrue);
2696}
2697
2698#if defined(__cplusplus) || defined(c_plusplus)
2699}
2700#endif
2701
2702/*
2703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2704% %
2705% %
2706% %
2707% X F r e e R e s o u r c e s %
2708% %
2709% %
2710% %
2711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2712%
2713% XFreeResources() frees X11 resources.
2714%
2715% The format of the XFreeResources method is:
2716%
2717% void XFreeResources(Display *display,XVisualInfo *visual_info,
2718% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2719% XResourceInfo *resource_info,XWindowInfo *window_info)
2720% resource_info,window_info)
2721%
2722% A description of each parameter follows:
2723%
2724% o display: Specifies a connection to an X server; returned from
2725% XOpenDisplay.
2726%
2727% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2728% returned from XGetVisualInfo.
2729%
2730% o map_info: If map_type is specified, this structure is initialized
2731% with info from the Standard Colormap.
2732%
2733% o pixel: Specifies a pointer to a XPixelInfo structure.
2734%
2735% o font_info: Specifies a pointer to a XFontStruct structure.
2736%
2737% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2738%
2739% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2740%
2741*/
2742MagickExport void XFreeResources(Display *display,XVisualInfo *visual_info,
2743 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2744 XResourceInfo *resource_info,XWindowInfo *window_info)
2745{
2746 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2747 assert(display != (Display *) NULL);
2748 assert(resource_info != (XResourceInfo *) NULL);
2749 if (window_info != (XWindowInfo *) NULL)
2750 {
2751 /*
2752 Free X image.
2753 */
2754 if (window_info->ximage != (XImage *) NULL)
2755 XDestroyImage(window_info->ximage);
2756 if (window_info->id != (Window) NULL)
2757 {
2758 /*
2759 Free destroy window and free cursors.
2760 */
2761 if (window_info->id != XRootWindow(display,visual_info->screen))
2762 (void) XDestroyWindow(display,window_info->id);
2763 if (window_info->annotate_context != (GC) NULL)
2764 (void) XFreeGC(display,window_info->annotate_context);
2765 if (window_info->highlight_context != (GC) NULL)
2766 (void) XFreeGC(display,window_info->highlight_context);
2767 if (window_info->widget_context != (GC) NULL)
2768 (void) XFreeGC(display,window_info->widget_context);
2769 if (window_info->cursor != (Cursor) NULL)
2770 (void) XFreeCursor(display,window_info->cursor);
2771 window_info->cursor=(Cursor) NULL;
2772 if (window_info->busy_cursor != (Cursor) NULL)
2773 (void) XFreeCursor(display,window_info->busy_cursor);
2774 window_info->busy_cursor=(Cursor) NULL;
2775 }
2776 }
2777 /*
2778 Free font.
2779 */
2780 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002781 {
2782 (void) XFreeFont(display,font_info);
2783 font_info=(XFontStruct *) NULL;
2784 }
cristy3ed852e2009-09-05 21:47:34 +00002785 if (map_info != (XStandardColormap *) NULL)
2786 {
2787 /*
2788 Free X Standard Colormap.
2789 */
2790 if (resource_info->map_type == (char *) NULL)
2791 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2792 (void) XFree((void *) map_info);
2793 }
2794 /*
2795 Free X visual info.
2796 */
2797 if (visual_info != (XVisualInfo *) NULL)
2798 (void) XFree((void *) visual_info);
2799 if (resource_info->close_server != MagickFalse)
2800 (void) XCloseDisplay(display);
2801}
2802
2803/*
2804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2805% %
2806% %
2807% %
2808% X F r e e S t a n d a r d C o l o r m a p %
2809% %
2810% %
2811% %
2812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2813%
2814% XFreeStandardColormap() frees an X11 colormap.
2815%
2816% The format of the XFreeStandardColormap method is:
2817%
2818% void XFreeStandardColormap(Display *display,
2819% const XVisualInfo *visual_info,XStandardColormap *map_info,
2820% XPixelInfo *pixel)
2821%
2822% A description of each parameter follows:
2823%
2824% o display: Specifies a connection to an X server; returned from
2825% XOpenDisplay.
2826%
2827% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2828% returned from XGetVisualInfo.
2829%
2830% o map_info: If map_type is specified, this structure is initialized
2831% with info from the Standard Colormap.
2832%
2833% o pixel: Specifies a pointer to a XPixelInfo structure.
2834%
2835*/
2836MagickExport void XFreeStandardColormap(Display *display,
2837 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2838{
2839 /*
2840 Free colormap.
2841 */
2842 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2843 assert(display != (Display *) NULL);
2844 assert(visual_info != (XVisualInfo *) NULL);
2845 assert(map_info != (XStandardColormap *) NULL);
2846 (void) XFlush(display);
2847 if (map_info->colormap != (Colormap) NULL)
2848 {
2849 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2850 (void) XFreeColormap(display,map_info->colormap);
2851 else
2852 if (pixel != (XPixelInfo *) NULL)
2853 if ((visual_info->klass != TrueColor) &&
2854 (visual_info->klass != DirectColor))
2855 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2856 (int) pixel->colors,0);
2857 }
2858 map_info->colormap=(Colormap) NULL;
2859 if (pixel != (XPixelInfo *) NULL)
2860 {
cristyf2faecf2010-05-28 19:19:36 +00002861 if (pixel->pixels != (unsigned long *) NULL)
2862 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2863 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002864 }
2865}
2866
2867/*
2868%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2869% %
2870% %
2871% %
2872% X G e t A n n o t a t e I n f o %
2873% %
2874% %
2875% %
2876%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2877%
2878% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2879%
2880% The format of the XGetAnnotateInfo method is:
2881%
2882% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2883%
2884% A description of each parameter follows:
2885%
2886% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2887%
2888*/
2889MagickExport void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2890{
2891 /*
2892 Initialize annotate structure.
2893 */
2894 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2895 assert(annotate_info != (XAnnotateInfo *) NULL);
2896 annotate_info->x=0;
2897 annotate_info->y=0;
2898 annotate_info->width=0;
2899 annotate_info->height=0;
2900 annotate_info->stencil=ForegroundStencil;
2901 annotate_info->degrees=0.0;
2902 annotate_info->font_info=(XFontStruct *) NULL;
2903 annotate_info->text=(char *) NULL;
2904 *annotate_info->geometry='\0';
2905 annotate_info->previous=(XAnnotateInfo *) NULL;
2906 annotate_info->next=(XAnnotateInfo *) NULL;
2907 (void) XSupportsLocale();
2908 (void) XSetLocaleModifiers("");
2909}
2910
2911/*
2912%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2913% %
2914% %
2915% %
2916% X G e t M a p I n f o %
2917% %
2918% %
2919% %
2920%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2921%
2922% XGetMapInfo() initializes the XStandardColormap structure.
2923%
2924% The format of the XStandardColormap method is:
2925%
2926% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2927% XStandardColormap *map_info)
2928%
2929% A description of each parameter follows:
2930%
2931% o colormap: Specifies the ID of the X server colormap.
2932%
2933% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2934% returned from XGetVisualInfo.
2935%
2936% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2937%
2938*/
2939MagickExport void XGetMapInfo(const XVisualInfo *visual_info,
2940 const Colormap colormap,XStandardColormap *map_info)
2941{
2942 /*
2943 Initialize map info.
2944 */
2945 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2946 assert(visual_info != (XVisualInfo *) NULL);
2947 assert(map_info != (XStandardColormap *) NULL);
2948 map_info->colormap=colormap;
2949 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002950 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002951 if (map_info->red_max != 0)
2952 while ((map_info->red_max & 0x01) == 0)
2953 {
2954 map_info->red_max>>=1;
2955 map_info->red_mult<<=1;
2956 }
2957 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002958 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002959 if (map_info->green_max != 0)
2960 while ((map_info->green_max & 0x01) == 0)
2961 {
2962 map_info->green_max>>=1;
2963 map_info->green_mult<<=1;
2964 }
2965 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002966 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002967 if (map_info->blue_max != 0)
2968 while ((map_info->blue_max & 0x01) == 0)
2969 {
2970 map_info->blue_max>>=1;
2971 map_info->blue_mult<<=1;
2972 }
2973 map_info->base_pixel=0;
2974}
2975
2976/*
2977%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2978% %
2979% %
2980% %
2981% X G e t P i x e l I n f o %
2982% %
2983% %
2984% %
2985%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2986%
cristy4c08aed2011-07-01 19:47:50 +00002987% XGetPixelInfo() initializes the PixelPacket structure.
cristy3ed852e2009-09-05 21:47:34 +00002988%
cristy4c08aed2011-07-01 19:47:50 +00002989% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00002990%
cristy4c08aed2011-07-01 19:47:50 +00002991% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002992% const XStandardColormap *map_info,const XResourceInfo *resource_info,
2993% Image *image,XPixelInfo *pixel)
2994% pixel)
2995%
2996% A description of each parameter follows:
2997%
2998% o display: Specifies a connection to an X server; returned from
2999% XOpenDisplay.
3000%
3001% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3002% returned from XGetVisualInfo.
3003%
3004% o map_info: If map_type is specified, this structure is initialized
3005% with info from the Standard Colormap.
3006%
3007% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3008%
3009% o image: the image.
3010%
3011% o pixel: Specifies a pointer to a XPixelInfo structure.
3012%
3013*/
cristy4c08aed2011-07-01 19:47:50 +00003014MagickExport void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003015 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3016 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3017{
3018 static const char
3019 *PenColors[MaxNumberPens]=
3020 {
3021 "#000000000000", /* black */
3022 "#00000000ffff", /* blue */
3023 "#0000ffffffff", /* cyan */
3024 "#0000ffff0000", /* green */
3025 "#bdbdbdbdbdbd", /* gray */
3026 "#ffff00000000", /* red */
3027 "#ffff0000ffff", /* magenta */
3028 "#ffffffff0000", /* yellow */
3029 "#ffffffffffff", /* white */
3030 "#bdbdbdbdbdbd", /* gray */
3031 "#bdbdbdbdbdbd" /* gray */
3032 };
3033
3034 Colormap
3035 colormap;
3036
cristybb503372010-05-27 20:51:26 +00003037 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003038 i;
3039
3040 Status
3041 status;
3042
3043 unsigned int
3044 packets;
3045
3046 /*
3047 Initialize pixel info.
3048 */
3049 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3050 assert(display != (Display *) NULL);
3051 assert(visual_info != (XVisualInfo *) NULL);
3052 assert(map_info != (XStandardColormap *) NULL);
3053 assert(resource_info != (XResourceInfo *) NULL);
3054 assert(pixel != (XPixelInfo *) NULL);
3055 pixel->colors=0;
3056 if (image != (Image *) NULL)
3057 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003058 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003059 packets=(unsigned int)
3060 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003061 if (pixel->pixels != (unsigned long *) NULL)
3062 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3063 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003064 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003065 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003066 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3067 image->filename);
3068 /*
3069 Set foreground color.
3070 */
3071 colormap=map_info->colormap;
3072 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3073 &pixel->foreground_color);
3074 status=XParseColor(display,colormap,resource_info->foreground_color,
3075 &pixel->foreground_color);
3076 if (status == False)
3077 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3078 resource_info->foreground_color);
3079 pixel->foreground_color.pixel=
3080 XStandardPixel(map_info,&pixel->foreground_color);
3081 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3082 /*
3083 Set background color.
3084 */
3085 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3086 status=XParseColor(display,colormap,resource_info->background_color,
3087 &pixel->background_color);
3088 if (status == False)
3089 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3090 resource_info->background_color);
3091 pixel->background_color.pixel=
3092 XStandardPixel(map_info,&pixel->background_color);
3093 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3094 /*
3095 Set border color.
3096 */
3097 (void) XParseColor(display,colormap,(char *) BorderColor,
3098 &pixel->border_color);
3099 status=XParseColor(display,colormap,resource_info->border_color,
3100 &pixel->border_color);
3101 if (status == False)
3102 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3103 resource_info->border_color);
3104 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3105 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3106 /*
3107 Set matte color.
3108 */
3109 pixel->matte_color=pixel->background_color;
3110 if (resource_info->matte_color != (char *) NULL)
3111 {
3112 /*
3113 Matte color is specified as a X resource or command line argument.
3114 */
3115 status=XParseColor(display,colormap,resource_info->matte_color,
3116 &pixel->matte_color);
3117 if (status == False)
3118 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3119 resource_info->matte_color);
3120 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3121 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3122 }
3123 /*
3124 Set highlight color.
3125 */
3126 pixel->highlight_color.red=(unsigned short) ((
3127 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3128 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3129 pixel->highlight_color.green=(unsigned short) ((
3130 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3131 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3132 pixel->highlight_color.blue=(unsigned short) ((
3133 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3134 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3135 pixel->highlight_color.pixel=
3136 XStandardPixel(map_info,&pixel->highlight_color);
3137 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3138 /*
3139 Set shadow color.
3140 */
3141 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3142 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3143 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3144 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3145 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3146 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3147 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3148 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3149 /*
3150 Set depth color.
3151 */
3152 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3153 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3154 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3155 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3156 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3157 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3158 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3159 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3160 /*
3161 Set trough color.
3162 */
3163 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3164 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3165 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3166 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3167 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3168 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3169 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3170 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3171 /*
3172 Set pen color.
3173 */
3174 for (i=0; i < MaxNumberPens; i++)
3175 {
3176 (void) XParseColor(display,colormap,(char *) PenColors[i],
3177 &pixel->pen_colors[i]);
3178 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3179 &pixel->pen_colors[i]);
3180 if (status == False)
3181 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3182 resource_info->pen_colors[i]);
3183 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3184 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3185 }
3186 pixel->box_color=pixel->background_color;
3187 pixel->pen_color=pixel->foreground_color;
3188 pixel->box_index=0;
3189 pixel->pen_index=1;
3190 if (image != (Image *) NULL)
3191 {
3192 if ((resource_info->gamma_correct != MagickFalse) &&
3193 (image->gamma != 0.0))
3194 {
3195 GeometryInfo
3196 geometry_info;
3197
3198 MagickStatusType
3199 flags;
3200
3201 /*
3202 Initialize map relative to display and image gamma.
3203 */
3204 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3205 red_gamma=geometry_info.rho;
3206 green_gamma=geometry_info.sigma;
3207 if ((flags & SigmaValue) == 0)
3208 green_gamma=red_gamma;
3209 blue_gamma=geometry_info.xi;
3210 if ((flags & XiValue) == 0)
3211 blue_gamma=red_gamma;
3212 red_gamma*=image->gamma;
3213 green_gamma*=image->gamma;
3214 blue_gamma*=image->gamma;
3215 }
3216 if (image->storage_class == PseudoClass)
3217 {
3218 /*
3219 Initialize pixel array for images of type PseudoClass.
3220 */
cristybb503372010-05-27 20:51:26 +00003221 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003222 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003223 for (i=0; i < MaxNumberPens; i++)
3224 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3225 pixel->colors+=MaxNumberPens;
3226 }
3227 }
3228}
3229
3230/*
3231%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3232% %
3233% %
3234% %
3235% X G e t R e s o u r c e C l a s s %
3236% %
3237% %
3238% %
3239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3240%
3241% XGetResourceClass() queries the X server for the specified resource name or
3242% class. If the resource name or class is not defined in the database, the
3243% supplied default value is returned.
3244%
3245% The format of the XGetResourceClass method is:
3246%
3247% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3248% const char *keyword,char *resource_default)
3249%
3250% A description of each parameter follows:
3251%
3252% o database: Specifies a resource database; returned from
3253% XrmGetStringDatabase.
3254%
3255% o client_name: Specifies the application name used to retrieve resource
3256% info from the X server database.
3257%
3258% o keyword: Specifies the keyword of the value being retrieved.
3259%
3260% o resource_default: Specifies the default value to return if the query
3261% fails to find the specified keyword/class.
3262%
3263*/
3264MagickExport char *XGetResourceClass(XrmDatabase database,
3265 const char *client_name,const char *keyword,char *resource_default)
3266{
3267 char
3268 resource_class[MaxTextExtent],
3269 resource_name[MaxTextExtent];
3270
3271 static char
3272 *resource_type;
3273
3274 Status
3275 status;
3276
3277 XrmValue
3278 resource_value;
3279
3280 if (database == (XrmDatabase) NULL)
3281 return(resource_default);
3282 *resource_name='\0';
3283 *resource_class='\0';
3284 if (keyword != (char *) NULL)
3285 {
3286 int
3287 c,
3288 k;
3289
3290 /*
3291 Initialize resource keyword and class.
3292 */
cristyb51dff52011-05-19 16:55:47 +00003293 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003294 client_name,keyword);
3295 c=(int) (*client_name);
3296 if ((c >= XK_a) && (c <= XK_z))
3297 c-=(XK_a-XK_A);
3298 else
3299 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3300 c-=(XK_agrave-XK_Agrave);
3301 else
3302 if ((c >= XK_oslash) && (c <= XK_thorn))
3303 c-=(XK_oslash-XK_Ooblique);
3304 k=(int) (*keyword);
3305 if ((k >= XK_a) && (k <= XK_z))
3306 k-=(XK_a-XK_A);
3307 else
3308 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3309 k-=(XK_agrave-XK_Agrave);
3310 else
3311 if ((k >= XK_oslash) && (k <= XK_thorn))
3312 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003313 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003314 client_name+1,k,keyword+1);
3315 }
3316 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3317 &resource_value);
3318 if (status == False)
3319 return(resource_default);
3320 return(resource_value.addr);
3321}
3322
3323/*
3324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3325% %
3326% %
3327% %
3328% X G e t R e s o u r c e D a t a b a s e %
3329% %
3330% %
3331% %
3332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3333%
3334% XGetResourceDatabase() creates a new resource database and initializes it.
3335%
3336% The format of the XGetResourceDatabase method is:
3337%
3338% XrmDatabase XGetResourceDatabase(Display *display,
3339% const char *client_name)
3340%
3341% A description of each parameter follows:
3342%
3343% o database: XGetResourceDatabase() returns the database after it is
3344% initialized.
3345%
3346% o display: Specifies a connection to an X server; returned from
3347% XOpenDisplay.
3348%
3349% o client_name: Specifies the application name used to retrieve resource
3350% info from the X server database.
3351%
3352*/
3353MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3354 const char *client_name)
3355{
3356 char
3357 filename[MaxTextExtent];
3358
3359 int
3360 c;
3361
3362 register const char
3363 *p;
3364
3365 XrmDatabase
3366 resource_database,
3367 server_database;
3368
3369 if (display == (Display *) NULL)
3370 return((XrmDatabase) NULL);
3371 assert(client_name != (char *) NULL);
3372 /*
3373 Initialize resource database.
3374 */
3375 XrmInitialize();
3376 (void) XGetDefault(display,(char *) client_name,"dummy");
3377 resource_database=XrmGetDatabase(display);
3378 /*
3379 Combine application database.
3380 */
3381 if (client_name != (char *) NULL)
3382 {
3383 /*
3384 Get basename of client.
3385 */
3386 p=client_name+(strlen(client_name)-1);
3387 while ((p > client_name) && (*p != '/'))
3388 p--;
3389 if (*p == '/')
3390 client_name=p+1;
3391 }
3392 c=(int) (*client_name);
3393 if ((c >= XK_a) && (c <= XK_z))
3394 c-=(XK_a-XK_A);
3395 else
3396 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3397 c-=(XK_agrave-XK_Agrave);
3398 else
3399 if ((c >= XK_oslash) && (c <= XK_thorn))
3400 c-=(XK_oslash-XK_Ooblique);
3401#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003402 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003403 X11_APPLICATION_PATH,c,client_name+1);
3404 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3405#endif
3406 if (XResourceManagerString(display) != (char *) NULL)
3407 {
3408 /*
3409 Combine server database.
3410 */
3411 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3412 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3413 }
3414 /*
3415 Merge user preferences database.
3416 */
3417#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003418 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003419 X11_PREFERENCES_PATH,client_name);
3420 ExpandFilename(filename);
3421 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3422#endif
3423 return(resource_database);
3424}
3425
3426/*
3427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3428% %
3429% %
3430% %
3431% X G e t R e s o u r c e I n f o %
3432% %
3433% %
3434% %
3435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3436%
3437% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3438%
3439% The format of the XGetResourceInfo method is:
3440%
3441% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3442% const char *client_name,XResourceInfo *resource_info)
3443%
3444% A description of each parameter follows:
3445%
3446% o image_info: the image info.
3447%
3448% o database: Specifies a resource database; returned from
3449% XrmGetStringDatabase.
3450%
3451% o client_name: Specifies the application name used to retrieve
3452% resource info from the X server database.
3453%
3454% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3455%
3456*/
3457MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3458 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3459{
3460 char
cristy00976d82011-02-20 20:31:28 +00003461 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003462 *resource_value;
3463
3464 /*
3465 Initialize resource info fields.
3466 */
3467 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3468 assert(resource_info != (XResourceInfo *) NULL);
3469 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3470 resource_info->resource_database=database;
3471 resource_info->image_info=(ImageInfo *) image_info;
3472 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3473 XMagickProgressMonitor,(void *) NULL);
3474 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3475 resource_info->close_server=MagickTrue;
3476 resource_info->client_name=AcquireString(client_name);
3477 resource_value=XGetResourceClass(database,client_name,"backdrop",
3478 (char *) "False");
3479 resource_info->backdrop=IsMagickTrue(resource_value);
3480 resource_info->background_color=XGetResourceInstance(database,client_name,
3481 "background",(char *) "#d6d6d6d6d6d6");
3482 resource_info->border_color=XGetResourceInstance(database,client_name,
3483 "borderColor",BorderColor);
3484 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3485 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003486 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3487 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003488 resource_value=XGetResourceClass(database,client_name,"colormap",
3489 (char *) "shared");
3490 resource_info->colormap=UndefinedColormap;
3491 if (LocaleCompare("private",resource_value) == 0)
3492 resource_info->colormap=PrivateColormap;
3493 if (LocaleCompare("shared",resource_value) == 0)
3494 resource_info->colormap=SharedColormap;
3495 if (resource_info->colormap == UndefinedColormap)
3496 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3497 resource_value);
3498 resource_value=XGetResourceClass(database,client_name,
3499 "colorRecovery",(char *) "False");
3500 resource_info->color_recovery=IsMagickTrue(resource_value);
3501 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3502 (char *) "False");
3503 resource_info->confirm_exit=IsMagickTrue(resource_value);
3504 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3505 (char *) "False");
3506 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003507 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003508 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003509 resource_info->display_gamma=XGetResourceClass(database,client_name,
3510 "displayGamma",(char *) "2.2");
3511 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3512 (char *) "True");
3513 resource_info->display_warnings=IsMagickTrue(resource_value);
3514 resource_info->font=XGetResourceClass(database,client_name,"font",
3515 (char *) NULL);
3516 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3517 resource_info->font);
3518 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3519 (char *) "fixed");
3520 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3521 (char *) "variable");
3522 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3523 (char *) "5x8");
3524 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3525 (char *) "6x10");
3526 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3527 (char *) "7x13bold");
3528 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3529 (char *) "8x13bold");
3530 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3531 (char *) "9x15bold");
3532 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3533 (char *) "10x20");
3534 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3535 (char *) "12x24");
3536 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3537 (char *) "fixed");
3538 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3539 (char *) "fixed");
3540 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3541 "foreground",ForegroundColor);
3542 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3543 (char *) "True");
3544 resource_info->gamma_correct=IsMagickTrue(resource_value);
3545 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3546 client_name,"geometry",(char *) NULL));
3547 resource_value=XGetResourceClass(database,client_name,"gravity",
3548 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003549 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003550 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003551 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3552 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003553 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3554 "iconGeometry",(char *) NULL);
3555 resource_value=XGetResourceClass(database,client_name,"iconic",
3556 (char *) "False");
3557 resource_info->iconic=IsMagickTrue(resource_value);
3558 resource_value=XGetResourceClass(database,client_name,"immutable",
3559 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3560 (char *) "False");
3561 resource_info->immutable=IsMagickTrue(resource_value);
3562 resource_value=XGetResourceClass(database,client_name,"magnify",
3563 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003564 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003565 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3566 (char *) NULL);
3567 resource_info->matte_color=XGetResourceInstance(database,client_name,
3568 "mattecolor",(char *) NULL);
3569 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3570 "name",(char *) NULL));
3571 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3572 (char *) "black");
3573 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3574 (char *) "blue");
3575 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3576 (char *) "cyan");
3577 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3578 (char *) "green");
3579 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3580 (char *) "gray");
3581 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3582 (char *) "red");
3583 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3584 (char *) "magenta");
3585 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3586 (char *) "yellow");
3587 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3588 (char *) "white");
3589 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3590 (char *) "gray");
3591 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3592 (char *) "gray");
3593 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003594 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003595 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003596 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003597 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3598 "font",(char *) "fixed");
3599 resource_info->text_font=XGetResourceClass(database,client_name,
3600 "textFontList",resource_info->text_font);
3601 resource_info->title=XGetResourceClass(database,client_name,"title",
3602 (char *) NULL);
3603 resource_value=XGetResourceClass(database,client_name,"undoCache",
3604 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003605 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003606 resource_value=XGetResourceClass(database,client_name,"update",
3607 (char *) "False");
3608 resource_info->update=IsMagickTrue(resource_value);
3609 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3610 (char *) "True");
3611 resource_info->use_pixmap=IsMagickTrue(resource_value);
3612 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3613 (char *) "True");
3614 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3615 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3616 (char *) NULL);
3617 resource_info->window_group=XGetResourceClass(database,client_name,
3618 "windowGroup",(char *) NULL);
3619 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3620 (char *) NULL);
3621 resource_info->write_filename=XGetResourceClass(database,client_name,
3622 "writeFilename",(char *) NULL);
3623}
3624
3625/*
3626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3627% %
3628% %
3629% %
3630% X G e t R e s o u r c e I n s t a n c e %
3631% %
3632% %
3633% %
3634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3635%
3636% XGetResourceInstance() queries the X server for the specified resource name.
3637% If the resource name is not defined in the database, the supplied default
3638% value is returned.
3639%
3640% The format of the XGetResourceInstance method is:
3641%
3642% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3643% const char *keyword,const char *resource_default)
3644%
3645% A description of each parameter follows:
3646%
3647% o database: Specifies a resource database; returned from
3648% XrmGetStringDatabase.
3649%
3650% o client_name: Specifies the application name used to retrieve
3651% resource info from the X server database.
3652%
3653% o keyword: Specifies the keyword of the value being retrieved.
3654%
3655% o resource_default: Specifies the default value to return if the query
3656% fails to find the specified keyword/class.
3657%
3658*/
3659MagickExport char *XGetResourceInstance(XrmDatabase database,
3660 const char *client_name,const char *keyword,const char *resource_default)
3661{
3662 char
3663 *resource_type,
3664 resource_name[MaxTextExtent];
3665
3666 Status
3667 status;
3668
3669 XrmValue
3670 resource_value;
3671
3672 if (database == (XrmDatabase) NULL)
3673 return((char *) resource_default);
3674 *resource_name='\0';
3675 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003676 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003677 keyword);
3678 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3679 &resource_value);
3680 if (status == False)
3681 return((char *) resource_default);
3682 return(resource_value.addr);
3683}
3684
3685/*
3686%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3687% %
3688% %
3689% %
3690% X G e t S c r e e n D e n s i t y %
3691% %
3692% %
3693% %
3694%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3695%
3696% XGetScreenDensity() returns the density of the X server screen in
3697% dots-per-inch.
3698%
3699% The format of the XGetScreenDensity method is:
3700%
3701% char *XGetScreenDensity(Display *display)
3702%
3703% A description of each parameter follows:
3704%
3705% o density: XGetScreenDensity() returns the density of the X screen in
3706% dots-per-inch.
3707%
3708% o display: Specifies a connection to an X server; returned from
3709% XOpenDisplay.
3710%
3711*/
3712MagickExport char *XGetScreenDensity(Display *display)
3713{
3714 char
3715 density[MaxTextExtent];
3716
3717 double
3718 x_density,
3719 y_density;
3720
3721 /*
3722 Set density as determined by screen size.
3723 */
3724 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3725 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3726 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3727 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003728 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003729 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003730 return(GetPageGeometry(density));
3731}
3732
3733/*
3734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3735% %
3736% %
3737% %
3738+ X G e t S u b w i n d o w %
3739% %
3740% %
3741% %
3742%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3743%
3744% XGetSubwindow() returns the subwindow of a window chosen the user with the
3745% pointer and a button press.
3746%
3747% The format of the XGetSubwindow method is:
3748%
3749% Window XGetSubwindow(Display *display,Window window,int x,int y)
3750%
3751% A description of each parameter follows:
3752%
3753% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3754% otherwise the subwindow is returned.
3755%
3756% o display: Specifies a connection to an X server; returned from
3757% XOpenDisplay.
3758%
3759% o window: Specifies a pointer to a Window.
3760%
3761% o x: the x coordinate of the pointer relative to the origin of the
3762% window.
3763%
3764% o y: the y coordinate of the pointer relative to the origin of the
3765% window.
3766%
cristy3ed852e2009-09-05 21:47:34 +00003767*/
3768static Window XGetSubwindow(Display *display,Window window,int x,int y)
3769{
3770 int
3771 x_offset,
3772 y_offset;
3773
3774 Status
3775 status;
3776
3777 Window
3778 source_window,
3779 target_window;
3780
3781 assert(display != (Display *) NULL);
3782 source_window=XRootWindow(display,XDefaultScreen(display));
3783 if (window == (Window) NULL)
3784 return(source_window);
3785 target_window=window;
3786 for ( ; ; )
3787 {
3788 status=XTranslateCoordinates(display,source_window,window,x,y,
3789 &x_offset,&y_offset,&target_window);
3790 if (status != True)
3791 break;
3792 if (target_window == (Window) NULL)
3793 break;
3794 source_window=window;
3795 window=target_window;
3796 x=x_offset;
3797 y=y_offset;
3798 }
3799 if (target_window == (Window) NULL)
3800 target_window=window;
3801 return(target_window);
3802}
3803
3804/*
3805%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3806% %
3807% %
3808% %
3809% X G e t W i n d o w C o l o r %
3810% %
3811% %
3812% %
3813%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3814%
3815% XGetWindowColor() returns the color of a pixel interactively chosen from the
3816% X server.
3817%
3818% The format of the XGetWindowColor method is:
3819%
3820% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3821% char *name)
3822%
3823% A description of each parameter follows:
3824%
3825% o display: Specifies a connection to an X server; returned from
3826% XOpenDisplay.
3827%
3828% o windows: Specifies a pointer to a XWindows structure.
3829%
3830% o name: the name of the color if found in the X Color Database is
3831% returned in this character string.
3832%
3833*/
3834MagickExport MagickBooleanType XGetWindowColor(Display *display,
3835 XWindows *windows,char *name)
3836{
3837 int
3838 x,
3839 y;
3840
3841 PixelPacket
3842 pixel;
3843
3844 RectangleInfo
3845 crop_info;
3846
3847 Status
3848 status;
3849
3850 Window
3851 child,
3852 client_window,
3853 root_window,
3854 target_window;
3855
3856 XColor
3857 color;
3858
3859 XImage
3860 *ximage;
3861
3862 XWindowAttributes
3863 window_attributes;
3864
3865 /*
3866 Choose a pixel from the X server.
3867 */
3868 assert(display != (Display *) NULL);
3869 assert(name != (char *) NULL);
3870 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3871 *name='\0';
3872 target_window=XSelectWindow(display,&crop_info);
3873 if (target_window == (Window) NULL)
3874 return(MagickFalse);
3875 root_window=XRootWindow(display,XDefaultScreen(display));
3876 client_window=target_window;
3877 if (target_window != root_window)
3878 {
3879 unsigned int
3880 d;
3881
3882 /*
3883 Get client window.
3884 */
3885 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3886 if (status != False)
3887 {
3888 client_window=XClientWindow(display,target_window);
3889 target_window=client_window;
3890 }
3891 }
3892 /*
3893 Verify window is viewable.
3894 */
3895 status=XGetWindowAttributes(display,target_window,&window_attributes);
3896 if ((status == False) || (window_attributes.map_state != IsViewable))
3897 return(MagickFalse);
3898 /*
3899 Get window X image.
3900 */
3901 (void) XTranslateCoordinates(display,root_window,target_window,
3902 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3903 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3904 if (ximage == (XImage *) NULL)
3905 return(MagickFalse);
3906 color.pixel=XGetPixel(ximage,0,0);
3907 XDestroyImage(ximage);
3908 /*
3909 Match color against the color database.
3910 */
3911 (void) XQueryColor(display,window_attributes.colormap,&color);
3912 pixel.red=ScaleShortToQuantum(color.red);
3913 pixel.green=ScaleShortToQuantum(color.green);
3914 pixel.blue=ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003915 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003916 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3917 &windows->image.image->exception);
3918 return(MagickTrue);
3919}
3920
3921/*
3922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3923% %
3924% %
3925% %
3926+ X G e t W i n d o w I m a g e %
3927% %
3928% %
3929% %
3930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3931%
3932% XGetWindowImage() reads an image from the target X window and returns it.
3933% XGetWindowImage() optionally descends the window hierarchy and overlays the
3934% target image with each child image in an optimized fashion. Any child
3935% window that have the same visual, colormap, and are contained by its parent
3936% are exempted.
3937%
3938% The format of the XGetWindowImage method is:
3939%
3940% Image *XGetWindowImage(Display *display,const Window window,
3941% const unsigned int borders,const unsigned int level)
3942%
3943% A description of each parameter follows:
3944%
3945% o display: Specifies a connection to an X server; returned from
3946% XOpenDisplay.
3947%
3948% o window: Specifies the window to obtain the image from.
3949%
3950% o borders: Specifies whether borders pixels are to be saved with
3951% the image.
3952%
3953% o level: Specifies an unsigned integer representing the level of
3954% decent in the window hierarchy. This value must be zero or one on
3955% the initial call to XGetWindowImage. A value of zero returns after
3956% one call. A value of one causes the function to descend the window
3957% hierarchy and overlay the target image with each subwindow image.
3958%
cristy3ed852e2009-09-05 21:47:34 +00003959*/
3960static Image *XGetWindowImage(Display *display,const Window window,
3961 const unsigned int borders,const unsigned int level)
3962{
3963 typedef struct _ColormapInfo
3964 {
3965 Colormap
3966 colormap;
3967
3968 XColor
3969 *colors;
3970
3971 struct _ColormapInfo
3972 *next;
3973 } ColormapInfo;
3974
3975 typedef struct _WindowInfo
3976 {
3977 Window
3978 window,
3979 parent;
3980
3981 Visual
3982 *visual;
3983
3984 Colormap
3985 colormap;
3986
3987 XSegment
3988 bounds;
3989
3990 RectangleInfo
3991 crop_info;
3992 } WindowInfo;
3993
cristy3ed852e2009-09-05 21:47:34 +00003994 int
3995 display_height,
3996 display_width,
3997 id,
3998 x_offset,
3999 y_offset;
4000
cristy4c08aed2011-07-01 19:47:50 +00004001 Quantum
4002 index;
4003
cristy3ed852e2009-09-05 21:47:34 +00004004 RectangleInfo
4005 crop_info;
4006
cristy3ed852e2009-09-05 21:47:34 +00004007 register int
4008 i;
4009
4010 static ColormapInfo
4011 *colormap_info = (ColormapInfo *) NULL;
4012
4013 static int
4014 max_windows = 0,
4015 number_windows = 0;
4016
4017 static WindowInfo
4018 *window_info;
4019
4020 Status
4021 status;
4022
4023 Window
4024 child,
4025 root_window;
4026
4027 XWindowAttributes
4028 window_attributes;
4029
4030 /*
4031 Verify window is viewable.
4032 */
4033 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4034 assert(display != (Display *) NULL);
4035 status=XGetWindowAttributes(display,window,&window_attributes);
4036 if ((status == False) || (window_attributes.map_state != IsViewable))
4037 return((Image *) NULL);
4038 /*
4039 Cropping rectangle is relative to root window.
4040 */
4041 root_window=XRootWindow(display,XDefaultScreen(display));
4042 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4043 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004044 crop_info.x=(ssize_t) x_offset;
4045 crop_info.y=(ssize_t) y_offset;
4046 crop_info.width=(size_t) window_attributes.width;
4047 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004048 if (borders != MagickFalse)
4049 {
4050 /*
4051 Include border in image.
4052 */
cristybb503372010-05-27 20:51:26 +00004053 crop_info.x-=(ssize_t) window_attributes.border_width;
4054 crop_info.y-=(ssize_t) window_attributes.border_width;
4055 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4056 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004057 }
4058 /*
4059 Crop to root window.
4060 */
4061 if (crop_info.x < 0)
4062 {
4063 crop_info.width+=crop_info.x;
4064 crop_info.x=0;
4065 }
4066 if (crop_info.y < 0)
4067 {
4068 crop_info.height+=crop_info.y;
4069 crop_info.y=0;
4070 }
4071 display_width=XDisplayWidth(display,XDefaultScreen(display));
4072 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004073 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004074 display_height=XDisplayHeight(display,XDefaultScreen(display));
4075 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004076 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004077 /*
4078 Initialize window info attributes.
4079 */
4080 if (number_windows >= max_windows)
4081 {
4082 /*
4083 Allocate or resize window info buffer.
4084 */
4085 max_windows+=1024;
4086 if (window_info == (WindowInfo *) NULL)
4087 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4088 sizeof(*window_info));
4089 else
4090 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4091 max_windows,sizeof(*window_info));
4092 }
4093 if (window_info == (WindowInfo *) NULL)
4094 {
4095 ThrowXWindowFatalException(ResourceLimitError,
4096 "MemoryAllocationFailed","...");
4097 return((Image *) NULL);
4098 }
4099 id=number_windows++;
4100 window_info[id].window=window;
4101 window_info[id].visual=window_attributes.visual;
4102 window_info[id].colormap=window_attributes.colormap;
4103 window_info[id].bounds.x1=(short) crop_info.x;
4104 window_info[id].bounds.y1=(short) crop_info.y;
4105 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4106 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4107 crop_info.x-=x_offset;
4108 crop_info.y-=y_offset;
4109 window_info[id].crop_info=crop_info;
4110 if (level != 0)
4111 {
4112 unsigned int
4113 number_children;
4114
4115 Window
4116 *children;
4117
4118 /*
4119 Descend the window hierarchy.
4120 */
4121 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4122 &children,&number_children);
4123 for (i=0; i < id; i++)
4124 if ((window_info[i].window == window_info[id].parent) &&
4125 (window_info[i].visual == window_info[id].visual) &&
4126 (window_info[i].colormap == window_info[id].colormap))
4127 {
4128 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4129 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4130 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4131 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4132 {
4133 /*
4134 Eliminate windows not circumscribed by their parent.
4135 */
4136 number_windows--;
4137 break;
4138 }
4139 }
4140 if ((status == True) && (number_children != 0))
4141 {
4142 for (i=0; i < (int) number_children; i++)
4143 (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4144 (void) XFree((void *) children);
4145 }
4146 }
4147 if (level <= 1)
4148 {
cristyc57f6942010-11-12 01:47:39 +00004149 CacheView
4150 *composite_view;
4151
cristy3ed852e2009-09-05 21:47:34 +00004152 ColormapInfo
4153 *next;
4154
4155 ExceptionInfo
4156 *exception;
4157
4158 Image
4159 *composite_image,
4160 *image;
4161
4162 int
4163 y;
4164
4165 MagickBooleanType
4166 import;
4167
4168 register int
4169 j,
4170 x;
4171
cristy4c08aed2011-07-01 19:47:50 +00004172 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004173 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004174
cristybb503372010-05-27 20:51:26 +00004175 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004176 pixel;
4177
4178 unsigned int
4179 number_colors;
4180
4181 XColor
4182 *colors;
4183
4184 XImage
4185 *ximage;
4186
4187 /*
4188 Get X image for each window in the list.
4189 */
4190 image=NewImageList();
4191 for (id=0; id < number_windows; id++)
4192 {
4193 /*
4194 Does target window intersect top level window?
4195 */
4196 import=
4197 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4198 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4199 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4200 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4201 MagickTrue : MagickFalse;
4202 /*
4203 Is target window contained by another window with the same colormap?
4204 */
4205 for (j=0; j < id; j++)
4206 if ((window_info[id].visual == window_info[j].visual) &&
4207 (window_info[id].colormap == window_info[j].colormap))
4208 {
4209 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4210 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4211 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4212 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4213 import=MagickFalse;
4214 }
4215 else
4216 if ((window_info[id].visual != window_info[j].visual) ||
4217 (window_info[id].colormap != window_info[j].colormap))
4218 {
4219 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4220 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4221 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4222 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4223 import=MagickTrue;
4224 }
4225 if (import == MagickFalse)
4226 continue;
4227 /*
4228 Get X image.
4229 */
4230 ximage=XGetImage(display,window_info[id].window,(int)
4231 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4232 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4233 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4234 if (ximage == (XImage *) NULL)
4235 continue;
4236 /*
4237 Initialize window colormap.
4238 */
4239 number_colors=0;
4240 colors=(XColor *) NULL;
4241 if (window_info[id].colormap != (Colormap) NULL)
4242 {
4243 ColormapInfo
4244 *p;
4245
4246 /*
4247 Search colormap list for window colormap.
4248 */
4249 number_colors=(unsigned int) window_info[id].visual->map_entries;
4250 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4251 if (p->colormap == window_info[id].colormap)
4252 break;
4253 if (p == (ColormapInfo *) NULL)
4254 {
4255 /*
4256 Get the window colormap.
4257 */
4258 colors=(XColor *) AcquireQuantumMemory(number_colors,
4259 sizeof(*colors));
4260 if (colors == (XColor *) NULL)
4261 {
4262 XDestroyImage(ximage);
4263 return((Image *) NULL);
4264 }
4265 if ((window_info[id].visual->klass != DirectColor) &&
4266 (window_info[id].visual->klass != TrueColor))
4267 for (i=0; i < (int) number_colors; i++)
4268 {
cristybb503372010-05-27 20:51:26 +00004269 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004270 colors[i].pad='\0';
4271 }
4272 else
4273 {
cristybb503372010-05-27 20:51:26 +00004274 size_t
cristy3ed852e2009-09-05 21:47:34 +00004275 blue,
4276 blue_bit,
4277 green,
4278 green_bit,
4279 red,
4280 red_bit;
4281
4282 /*
4283 DirectColor or TrueColor visual.
4284 */
4285 red=0;
4286 green=0;
4287 blue=0;
4288 red_bit=window_info[id].visual->red_mask &
4289 (~(window_info[id].visual->red_mask)+1);
4290 green_bit=window_info[id].visual->green_mask &
4291 (~(window_info[id].visual->green_mask)+1);
4292 blue_bit=window_info[id].visual->blue_mask &
4293 (~(window_info[id].visual->blue_mask)+1);
4294 for (i=0; i < (int) number_colors; i++)
4295 {
cristy8891f9c2010-06-04 23:32:17 +00004296 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004297 colors[i].pad='\0';
4298 red+=red_bit;
4299 if (red > window_info[id].visual->red_mask)
4300 red=0;
4301 green+=green_bit;
4302 if (green > window_info[id].visual->green_mask)
4303 green=0;
4304 blue+=blue_bit;
4305 if (blue > window_info[id].visual->blue_mask)
4306 blue=0;
4307 }
4308 }
4309 (void) XQueryColors(display,window_info[id].colormap,colors,
4310 (int) number_colors);
4311 /*
4312 Append colormap to colormap list.
4313 */
cristy73bd4a52010-10-05 11:24:23 +00004314 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004315 if (p == (ColormapInfo *) NULL)
4316 return((Image *) NULL);
4317 p->colormap=window_info[id].colormap;
4318 p->colors=colors;
4319 p->next=colormap_info;
4320 colormap_info=p;
4321 }
4322 colors=p->colors;
4323 }
4324 /*
4325 Allocate image structure.
4326 */
4327 composite_image=AcquireImage((ImageInfo *) NULL);
4328 if (composite_image == (Image *) NULL)
4329 {
4330 XDestroyImage(ximage);
4331 return((Image *) NULL);
4332 }
4333 /*
4334 Convert X image to MIFF format.
4335 */
4336 if ((window_info[id].visual->klass != TrueColor) &&
4337 (window_info[id].visual->klass != DirectColor))
4338 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004339 composite_image->columns=(size_t) ximage->width;
4340 composite_image->rows=(size_t) ximage->height;
cristy3ed852e2009-09-05 21:47:34 +00004341 exception=(&composite_image->exception);
cristyc57f6942010-11-12 01:47:39 +00004342 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004343 switch (composite_image->storage_class)
4344 {
4345 case DirectClass:
4346 default:
4347 {
cristybb503372010-05-27 20:51:26 +00004348 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004349 color,
4350 index;
4351
cristybb503372010-05-27 20:51:26 +00004352 size_t
cristy3ed852e2009-09-05 21:47:34 +00004353 blue_mask,
4354 blue_shift,
4355 green_mask,
4356 green_shift,
4357 red_mask,
4358 red_shift;
4359
4360 /*
4361 Determine shift and mask for red, green, and blue.
4362 */
4363 red_mask=window_info[id].visual->red_mask;
4364 red_shift=0;
4365 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4366 {
4367 red_mask>>=1;
4368 red_shift++;
4369 }
4370 green_mask=window_info[id].visual->green_mask;
4371 green_shift=0;
4372 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4373 {
4374 green_mask>>=1;
4375 green_shift++;
4376 }
4377 blue_mask=window_info[id].visual->blue_mask;
4378 blue_shift=0;
4379 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4380 {
4381 blue_mask>>=1;
4382 blue_shift++;
4383 }
4384 /*
4385 Convert X image to DirectClass packets.
4386 */
4387 if ((number_colors != 0) &&
4388 (window_info[id].visual->klass == DirectColor))
4389 for (y=0; y < (int) composite_image->rows; y++)
4390 {
cristyc57f6942010-11-12 01:47:39 +00004391 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004392 composite_image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00004393 if (q == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004394 break;
4395 for (x=0; x < (int) composite_image->columns; x++)
4396 {
4397 pixel=XGetPixel(ximage,x,y);
4398 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004399 SetPixelRed(composite_image,
4400 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004401 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004402 SetPixelGreen(composite_image,
4403 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004404 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004405 SetPixelBlue(composite_image,
4406 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004407 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004408 }
cristyc57f6942010-11-12 01:47:39 +00004409 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004410 break;
4411 }
4412 else
4413 for (y=0; y < (int) composite_image->rows; y++)
4414 {
cristyc57f6942010-11-12 01:47:39 +00004415 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004416 composite_image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00004417 if (q == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004418 break;
4419 for (x=0; x < (int) composite_image->columns; x++)
4420 {
4421 pixel=XGetPixel(ximage,x,y);
4422 color=(pixel >> red_shift) & red_mask;
4423 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004424 SetPixelRed(composite_image,
4425 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004426 color=(pixel >> green_shift) & green_mask;
4427 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004428 SetPixelGreen(composite_image,
4429 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004430 color=(pixel >> blue_shift) & blue_mask;
4431 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004432 SetPixelBlue(composite_image,
4433 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004434 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004435 }
cristyc57f6942010-11-12 01:47:39 +00004436 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004437 break;
4438 }
4439 break;
4440 }
4441 case PseudoClass:
4442 {
4443 /*
4444 Create colormap.
4445 */
4446 if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
4447 {
4448 XDestroyImage(ximage);
4449 composite_image=DestroyImage(composite_image);
4450 return((Image *) NULL);
4451 }
4452 for (i=0; i < (int) composite_image->colors; i++)
4453 {
4454 composite_image->colormap[colors[i].pixel].red=
4455 ScaleShortToQuantum(colors[i].red);
4456 composite_image->colormap[colors[i].pixel].green=
4457 ScaleShortToQuantum(colors[i].green);
4458 composite_image->colormap[colors[i].pixel].blue=
4459 ScaleShortToQuantum(colors[i].blue);
4460 }
4461 /*
4462 Convert X image to PseudoClass packets.
4463 */
4464 for (y=0; y < (int) composite_image->rows; y++)
4465 {
cristyc57f6942010-11-12 01:47:39 +00004466 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4467 composite_image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00004468 if (q == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004469 break;
cristy3ed852e2009-09-05 21:47:34 +00004470 for (x=0; x < (int) composite_image->columns; x++)
4471 {
cristy4c08aed2011-07-01 19:47:50 +00004472 index=(Quantum) XGetPixel(ximage,x,y);
4473 SetPixelIndex(composite_image,index,q);
4474 SetPixelPacket(composite_image,
4475 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004476 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004477 }
cristyc57f6942010-11-12 01:47:39 +00004478 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004479 break;
4480 }
4481 break;
4482 }
4483 }
cristyc57f6942010-11-12 01:47:39 +00004484 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004485 XDestroyImage(ximage);
4486 if (image == (Image *) NULL)
4487 {
4488 image=composite_image;
4489 continue;
4490 }
4491 /*
4492 Composite any children in back-to-front order.
4493 */
4494 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4495 &x_offset,&y_offset,&child);
4496 x_offset-=(int) crop_info.x;
4497 if (x_offset < 0)
4498 x_offset=0;
4499 y_offset-=(int) crop_info.y;
4500 if (y_offset < 0)
4501 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004502 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
4503 x_offset,(ssize_t) y_offset);
cristy3ed852e2009-09-05 21:47:34 +00004504 }
4505 /*
4506 Relinquish resources.
4507 */
4508 while (colormap_info != (ColormapInfo *) NULL)
4509 {
4510 next=colormap_info->next;
4511 colormap_info->colors=(XColor *)
4512 RelinquishMagickMemory(colormap_info->colors);
4513 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4514 colormap_info=next;
4515 }
4516 /*
4517 Relinquish resources and restore initial state.
4518 */
4519 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4520 max_windows=0;
4521 number_windows=0;
4522 colormap_info=(ColormapInfo *) NULL;
4523 return(image);
4524 }
4525 return((Image *) NULL);
4526}
4527
4528/*
4529%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4530% %
4531% %
4532% %
4533% X G e t W i n d o w I n f o %
4534% %
4535% %
4536% %
4537%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4538%
4539% XGetWindowInfo() initializes the XWindowInfo structure.
4540%
4541% The format of the XGetWindowInfo method is:
4542%
4543% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4544% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4545% XResourceInfo *resource_info,XWindowInfo *window)
4546% resource_info,window)
4547%
4548% A description of each parameter follows:
4549%
4550% o display: Specifies a connection to an X server; returned from
4551% XOpenDisplay.
4552%
4553% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4554% returned from XGetVisualInfo.
4555%
4556% o map_info: If map_type is specified, this structure is initialized
4557% with info from the Standard Colormap.
4558%
4559% o pixel: Specifies a pointer to a XPixelInfo structure.
4560%
4561% o font_info: Specifies a pointer to a XFontStruct structure.
4562%
4563% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4564%
4565*/
4566MagickExport void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4567 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4568 XResourceInfo *resource_info,XWindowInfo *window)
4569{
4570 /*
4571 Initialize window info.
4572 */
4573 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4574 assert(display != (Display *) NULL);
4575 assert(visual_info != (XVisualInfo *) NULL);
4576 assert(map_info != (XStandardColormap *) NULL);
4577 assert(pixel != (XPixelInfo *) NULL);
4578 assert(resource_info != (XResourceInfo *) NULL);
4579 assert(window != (XWindowInfo *) NULL);
4580 if (window->id != (Window) NULL)
4581 {
4582 if (window->cursor != (Cursor) NULL)
4583 (void) XFreeCursor(display,window->cursor);
4584 if (window->busy_cursor != (Cursor) NULL)
4585 (void) XFreeCursor(display,window->busy_cursor);
4586 if (window->highlight_stipple != (Pixmap) NULL)
4587 (void) XFreePixmap(display,window->highlight_stipple);
4588 if (window->shadow_stipple != (Pixmap) NULL)
4589 (void) XFreePixmap(display,window->shadow_stipple);
4590 if (window->name == (char *) NULL)
4591 window->name=AcquireString("");
4592 if (window->icon_name == (char *) NULL)
4593 window->icon_name=AcquireString("");
4594 }
4595 else
4596 {
4597 /*
4598 Initialize these attributes just once.
4599 */
4600 window->id=(Window) NULL;
4601 if (window->name == (char *) NULL)
4602 window->name=AcquireString("");
4603 if (window->icon_name == (char *) NULL)
4604 window->icon_name=AcquireString("");
4605 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4606 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4607 window->ximage=(XImage *) NULL;
4608 window->matte_image=(XImage *) NULL;
4609 window->pixmap=(Pixmap) NULL;
4610 window->matte_pixmap=(Pixmap) NULL;
4611 window->mapped=MagickFalse;
4612 window->stasis=MagickFalse;
4613 window->shared_memory=MagickTrue;
4614 window->segment_info=(void *) NULL;
4615#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4616 {
4617 XShmSegmentInfo
4618 *segment_info;
4619
4620 if (window->segment_info == (void *) NULL)
4621 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4622 segment_info=(XShmSegmentInfo *) window->segment_info;
4623 segment_info[0].shmid=(-1);
4624 segment_info[0].shmaddr=(char *) NULL;
4625 segment_info[1].shmid=(-1);
4626 segment_info[1].shmaddr=(char *) NULL;
4627 }
4628#endif
4629 }
4630 /*
4631 Initialize these attributes every time function is called.
4632 */
4633 window->screen=visual_info->screen;
4634 window->root=XRootWindow(display,visual_info->screen);
4635 window->visual=visual_info->visual;
4636 window->storage_class=(unsigned int) visual_info->klass;
4637 window->depth=(unsigned int) visual_info->depth;
4638 window->visual_info=visual_info;
4639 window->map_info=map_info;
4640 window->pixel_info=pixel;
4641 window->font_info=font_info;
4642 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4643 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4644 window->geometry=(char *) NULL;
4645 window->icon_geometry=(char *) NULL;
4646 if (resource_info->icon_geometry != (char *) NULL)
4647 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4648 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004649 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004650 window->width=1;
4651 window->height=1;
4652 window->min_width=1;
4653 window->min_height=1;
4654 window->width_inc=1;
4655 window->height_inc=1;
4656 window->border_width=resource_info->border_width;
4657 window->annotate_context=pixel->annotate_context;
4658 window->highlight_context=pixel->highlight_context;
4659 window->widget_context=pixel->widget_context;
4660 window->shadow_stipple=(Pixmap) NULL;
4661 window->highlight_stipple=(Pixmap) NULL;
4662 window->use_pixmap=MagickTrue;
4663 window->immutable=MagickFalse;
4664 window->shape=MagickFalse;
4665 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004666 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004667 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4668 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4669 window->attributes.background_pixel=pixel->background_color.pixel;
4670 window->attributes.background_pixmap=(Pixmap) NULL;
4671 window->attributes.bit_gravity=ForgetGravity;
4672 window->attributes.backing_store=WhenMapped;
4673 window->attributes.save_under=MagickTrue;
4674 window->attributes.border_pixel=pixel->border_color.pixel;
4675 window->attributes.colormap=map_info->colormap;
4676 window->attributes.cursor=window->cursor;
4677 window->attributes.do_not_propagate_mask=NoEventMask;
4678 window->attributes.event_mask=NoEventMask;
4679 window->attributes.override_redirect=MagickFalse;
4680 window->attributes.win_gravity=NorthWestGravity;
4681 window->orphan=MagickFalse;
4682}
4683
4684/*
4685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4686% %
4687% %
4688% %
4689% X H i g h l i g h t E l l i p s e %
4690% %
4691% %
4692% %
4693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4694%
4695% XHighlightEllipse() puts a border on the X server around a region defined by
4696% highlight_info.
4697%
4698% The format of the XHighlightEllipse method is:
4699%
4700% void XHighlightEllipse(Display *display,Window window,
4701% GC annotate_context,const RectangleInfo *highlight_info)
4702%
4703% A description of each parameter follows:
4704%
4705% o display: Specifies a connection to an X server; returned from
4706% XOpenDisplay.
4707%
4708% o window: Specifies a pointer to a Window structure.
4709%
4710% o annotate_context: Specifies a pointer to a GC structure.
4711%
4712% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4713% contains the extents of any highlighting rectangle.
4714%
4715*/
4716MagickExport void XHighlightEllipse(Display *display,Window window,
4717 GC annotate_context,const RectangleInfo *highlight_info)
4718{
4719 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4720 assert(display != (Display *) NULL);
4721 assert(window != (Window) NULL);
4722 assert(annotate_context != (GC) NULL);
4723 assert(highlight_info != (RectangleInfo *) NULL);
4724 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4725 return;
4726 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4727 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4728 (unsigned int) highlight_info->height-1,0,360*64);
4729 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4730 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4731 (unsigned int) highlight_info->height-3,0,360*64);
4732}
4733
4734/*
4735%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4736% %
4737% %
4738% %
4739% X H i g h l i g h t L i n e %
4740% %
4741% %
4742% %
4743%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4744%
4745% XHighlightLine() puts a border on the X server around a region defined by
4746% highlight_info.
4747%
4748% The format of the XHighlightLine method is:
4749%
4750% void XHighlightLine(Display *display,Window window,GC annotate_context,
4751% const XSegment *highlight_info)
4752%
4753% A description of each parameter follows:
4754%
4755% o display: Specifies a connection to an X server; returned from
4756% XOpenDisplay.
4757%
4758% o window: Specifies a pointer to a Window structure.
4759%
4760% o annotate_context: Specifies a pointer to a GC structure.
4761%
4762% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4763% contains the extents of any highlighting rectangle.
4764%
4765*/
4766MagickExport void XHighlightLine(Display *display,Window window,
4767 GC annotate_context,const XSegment *highlight_info)
4768{
4769 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4770 assert(display != (Display *) NULL);
4771 assert(window != (Window) NULL);
4772 assert(annotate_context != (GC) NULL);
4773 assert(highlight_info != (XSegment *) NULL);
4774 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4775 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4776}
4777
4778/*
4779%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4780% %
4781% %
4782% %
4783% X H i g h l i g h t R e c t a n g l e %
4784% %
4785% %
4786% %
4787%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4788%
4789% XHighlightRectangle() puts a border on the X server around a region defined
4790% by highlight_info.
4791%
4792% The format of the XHighlightRectangle method is:
4793%
4794% void XHighlightRectangle(Display *display,Window window,
4795% GC annotate_context,const RectangleInfo *highlight_info)
4796%
4797% A description of each parameter follows:
4798%
4799% o display: Specifies a connection to an X server; returned from
4800% XOpenDisplay.
4801%
4802% o window: Specifies a pointer to a Window structure.
4803%
4804% o annotate_context: Specifies a pointer to a GC structure.
4805%
4806% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4807% contains the extents of any highlighting rectangle.
4808%
4809*/
4810MagickExport void XHighlightRectangle(Display *display,Window window,
4811 GC annotate_context,const RectangleInfo *highlight_info)
4812{
4813 assert(display != (Display *) NULL);
4814 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4815 assert(window != (Window) NULL);
4816 assert(annotate_context != (GC) NULL);
4817 assert(highlight_info != (RectangleInfo *) NULL);
4818 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4819 return;
4820 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4821 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4822 (unsigned int) highlight_info->height-1);
4823 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4824 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4825 (unsigned int) highlight_info->height-3);
4826}
4827
4828/*
4829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4830% %
4831% %
4832% %
4833% X I m p o r t I m a g e %
4834% %
4835% %
4836% %
4837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4838%
4839% XImportImage() reads an image from an X window.
4840%
4841% The format of the XImportImage method is:
4842%
4843% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4844%
4845% A description of each parameter follows:
4846%
4847% o image_info: the image info.
4848%
4849% o ximage_info: Specifies a pointer to an XImportInfo structure.
4850%
4851*/
4852MagickExport Image *XImportImage(const ImageInfo *image_info,
4853 XImportInfo *ximage_info)
4854{
4855 Colormap
4856 *colormaps;
4857
4858 Display
4859 *display;
4860
4861 Image
4862 *image;
4863
4864 int
4865 number_colormaps,
4866 number_windows,
4867 x;
4868
4869 RectangleInfo
4870 crop_info;
4871
4872 Status
4873 status;
4874
4875 Window
4876 *children,
4877 client,
4878 prior_target,
4879 root,
4880 target;
4881
4882 XTextProperty
4883 window_name;
4884
4885 /*
4886 Open X server connection.
4887 */
4888 assert(image_info != (const ImageInfo *) NULL);
4889 assert(image_info->signature == MagickSignature);
4890 if (image_info->debug != MagickFalse)
4891 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4892 image_info->filename);
4893 assert(ximage_info != (XImportInfo *) NULL);
4894 display=XOpenDisplay(image_info->server_name);
4895 if (display == (Display *) NULL)
4896 {
4897 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4898 XDisplayName(image_info->server_name));
4899 return((Image *) NULL);
4900 }
4901 /*
4902 Set our forgiving exception handler.
4903 */
4904 (void) XSetErrorHandler(XError);
4905 /*
4906 Select target window.
4907 */
4908 crop_info.x=0;
4909 crop_info.y=0;
4910 crop_info.width=0;
4911 crop_info.height=0;
4912 root=XRootWindow(display,XDefaultScreen(display));
4913 target=(Window) NULL;
4914 if ((image_info->filename != (char *) NULL) &&
4915 (*image_info->filename != '\0'))
4916 {
4917 if (LocaleCompare(image_info->filename,"root") == 0)
4918 target=root;
4919 else
4920 {
4921 /*
4922 Select window by ID or name.
4923 */
4924 if (isdigit((unsigned char) *image_info->filename) != 0)
4925 target=XWindowByID(display,root,(Window)
4926 strtol(image_info->filename,(char **) NULL,0));
4927 if (target == (Window) NULL)
4928 target=XWindowByName(display,root,image_info->filename);
4929 if (target == (Window) NULL)
4930 ThrowXWindowFatalException(XServerError,
4931 "NoWindowWithSpecifiedIDExists",image_info->filename);
4932 }
4933 }
4934 /*
4935 If target window is not defined, interactively select one.
4936 */
4937 prior_target=target;
4938 if (target == (Window) NULL)
4939 target=XSelectWindow(display,&crop_info);
4940 if (target == (Window) NULL)
4941 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4942 image_info->filename);
4943 client=target; /* obsolete */
4944 if (target != root)
4945 {
4946 unsigned int
4947 d;
4948
4949 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4950 if (status != False)
4951 {
4952 for ( ; ; )
4953 {
4954 Window
4955 parent;
4956
4957 /*
4958 Find window manager frame.
4959 */
4960 status=XQueryTree(display,target,&root,&parent,&children,&d);
4961 if ((status != False) && (children != (Window *) NULL))
4962 (void) XFree((char *) children);
4963 if ((status == False) || (parent == (Window) NULL) ||
4964 (parent == root))
4965 break;
4966 target=parent;
4967 }
4968 /*
4969 Get client window.
4970 */
4971 client=XClientWindow(display,target);
4972 if (ximage_info->frame == MagickFalse)
4973 target=client;
4974 if ((ximage_info->frame == MagickFalse) &&
4975 (prior_target != MagickFalse))
4976 target=prior_target;
4977 XDelay(display,SuspendTime << 4);
4978 }
4979 }
4980 if (ximage_info->screen)
4981 {
4982 int
4983 y;
4984
4985 Window
4986 child;
4987
4988 XWindowAttributes
4989 window_attributes;
4990
4991 /*
4992 Obtain window image directly from screen.
4993 */
4994 status=XGetWindowAttributes(display,target,&window_attributes);
4995 if (status == False)
4996 {
4997 ThrowXWindowFatalException(XServerError,
4998 "UnableToReadXWindowAttributes",image_info->filename);
4999 (void) XCloseDisplay(display);
5000 return((Image *) NULL);
5001 }
5002 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005003 crop_info.x=(ssize_t) x;
5004 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005005 crop_info.width=(size_t) window_attributes.width;
5006 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005007 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005008 {
5009 /*
5010 Include border in image.
5011 */
5012 crop_info.x-=window_attributes.border_width;
5013 crop_info.y-=window_attributes.border_width;
5014 crop_info.width+=window_attributes.border_width << 1;
5015 crop_info.height+=window_attributes.border_width << 1;
5016 }
5017 target=root;
5018 }
5019 /*
5020 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5021 */
5022 number_windows=0;
5023 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5024 if ((status == True) && (number_windows > 0))
5025 {
5026 ximage_info->descend=MagickTrue;
5027 (void) XFree ((char *) children);
5028 }
5029 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5030 if (number_colormaps > 0)
5031 {
5032 if (number_colormaps > 1)
5033 ximage_info->descend=MagickTrue;
5034 (void) XFree((char *) colormaps);
5035 }
5036 /*
5037 Alert the user not to alter the screen.
5038 */
5039 if (ximage_info->silent == MagickFalse)
5040 (void) XBell(display,0);
5041 /*
5042 Get image by window id.
5043 */
5044 (void) XGrabServer(display);
5045 image=XGetWindowImage(display,target,ximage_info->borders,
5046 ximage_info->descend ? 1U : 0U);
5047 (void) XUngrabServer(display);
5048 if (image == (Image *) NULL)
5049 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5050 image_info->filename)
5051 else
5052 {
5053 (void) CopyMagickString(image->filename,image_info->filename,
5054 MaxTextExtent);
5055 if ((crop_info.width != 0) && (crop_info.height != 0))
5056 {
5057 Image
5058 *clone_image,
5059 *crop_image;
5060
5061 /*
5062 Crop image as defined by the cropping rectangle.
5063 */
5064 clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5065 if (clone_image != (Image *) NULL)
5066 {
5067 crop_image=CropImage(clone_image,&crop_info,&image->exception);
5068 if (crop_image != (Image *) NULL)
5069 {
5070 image=DestroyImage(image);
5071 image=crop_image;
5072 }
5073 }
5074 }
5075 status=XGetWMName(display,target,&window_name);
5076 if (status == True)
5077 {
5078 if ((image_info->filename != (char *) NULL) &&
5079 (*image_info->filename == '\0'))
5080 (void) CopyMagickString(image->filename,(char *) window_name.value,
5081 (size_t) window_name.nitems+1);
5082 (void) XFree((void *) window_name.value);
5083 }
5084 }
5085 if (ximage_info->silent == MagickFalse)
5086 {
5087 /*
5088 Alert the user we're done.
5089 */
5090 (void) XBell(display,0);
5091 (void) XBell(display,0);
5092 }
5093 (void) XCloseDisplay(display);
5094 return(image);
5095}
5096
5097/*
5098%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5099% %
5100% %
5101% %
5102% X I n i t i a l i z e W i n d o w s %
5103% %
5104% %
5105% %
5106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5107%
5108% XInitializeWindows() initializes the XWindows structure.
5109%
5110% The format of the XInitializeWindows method is:
5111%
5112% XWindows *XInitializeWindows(Display *display,
5113% XResourceInfo *resource_info)
5114%
5115% A description of each parameter follows:
5116%
5117% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5118%
5119% o display: Specifies a connection to an X server; returned from
5120% XOpenDisplay.
5121%
5122% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5123%
5124*/
5125MagickExport XWindows *XInitializeWindows(Display *display,
5126 XResourceInfo *resource_info)
5127{
5128 Window
5129 root_window;
5130
5131 XWindows
5132 *windows;
5133
5134 /*
5135 Allocate windows structure.
5136 */
cristy73bd4a52010-10-05 11:24:23 +00005137 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005138 if (windows == (XWindows *) NULL)
5139 {
5140 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5141 "...");
5142 return((XWindows *) NULL);
5143 }
5144 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5145 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5146 sizeof(*windows->pixel_info));
5147 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5148 sizeof(*windows->icon_pixel));
5149 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5150 sizeof(*windows->icon_resources));
5151 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5152 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5153 (windows->icon_resources == (XResourceInfo *) NULL))
5154 {
5155 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5156 "...");
5157 return((XWindows *) NULL);
5158 }
5159 /*
5160 Initialize windows structure.
5161 */
5162 windows->display=display;
5163 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5164 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5165 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5166 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5167 windows->im_remote_command=
5168 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5169 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5170 windows->im_update_colormap=
5171 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5172 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5173 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5174 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5175 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5176 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005177#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005178 (void) XSynchronize(display,IsWindows95());
5179#endif
5180 if (IsEventLogging())
5181 {
5182 (void) XSynchronize(display,MagickTrue);
5183 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005184 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005185 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5186 (void) LogMagickEvent(X11Event,GetMagickModule(),
5187 " Window Manager: 0x%lx",windows->wm_protocols);
5188 (void) LogMagickEvent(X11Event,GetMagickModule(),
5189 " delete window: 0x%lx",windows->wm_delete_window);
5190 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5191 windows->wm_take_focus);
5192 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5193 windows->im_protocols);
5194 (void) LogMagickEvent(X11Event,GetMagickModule(),
5195 " remote command: 0x%lx",windows->im_remote_command);
5196 (void) LogMagickEvent(X11Event,GetMagickModule(),
5197 " update widget: 0x%lx",windows->im_update_widget);
5198 (void) LogMagickEvent(X11Event,GetMagickModule(),
5199 " update colormap: 0x%lx",windows->im_update_colormap);
5200 (void) LogMagickEvent(X11Event,GetMagickModule(),
5201 " former image: 0x%lx",windows->im_former_image);
5202 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5203 windows->im_next_image);
5204 (void) LogMagickEvent(X11Event,GetMagickModule(),
5205 " retain colors: 0x%lx",windows->im_retain_colors);
5206 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5207 windows->im_exit);
5208 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5209 windows->dnd_protocols);
5210 }
5211 /*
5212 Allocate standard colormap.
5213 */
5214 windows->map_info=XAllocStandardColormap();
5215 windows->icon_map=XAllocStandardColormap();
5216 if ((windows->map_info == (XStandardColormap *) NULL) ||
5217 (windows->icon_map == (XStandardColormap *) NULL))
5218 ThrowXWindowFatalException(ResourceLimitFatalError,
5219 "MemoryAllocationFailed","...");
5220 windows->map_info->colormap=(Colormap) NULL;
5221 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005222 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005223 windows->pixel_info->annotate_context=(GC) NULL;
5224 windows->pixel_info->highlight_context=(GC) NULL;
5225 windows->pixel_info->widget_context=(GC) NULL;
5226 windows->font_info=(XFontStruct *) NULL;
5227 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005228 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005229 /*
5230 Allocate visual.
5231 */
5232 *windows->icon_resources=(*resource_info);
5233 windows->icon_resources->visual_type=(char *) "default";
5234 windows->icon_resources->colormap=SharedColormap;
5235 windows->visual_info=
5236 XBestVisualInfo(display,windows->map_info,resource_info);
5237 windows->icon_visual=
5238 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5239 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5240 (windows->icon_visual == (XVisualInfo *) NULL))
5241 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5242 resource_info->visual_type);
5243 if (IsEventLogging())
5244 {
5245 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5246 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5247 windows->visual_info->visualid);
5248 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5249 XVisualClassName(windows->visual_info->klass));
5250 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5251 windows->visual_info->depth);
5252 (void) LogMagickEvent(X11Event,GetMagickModule(),
5253 " size of colormap: %d entries",windows->visual_info->colormap_size);
5254 (void) LogMagickEvent(X11Event,GetMagickModule(),
5255 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5256 windows->visual_info->red_mask,windows->visual_info->green_mask,
5257 windows->visual_info->blue_mask);
5258 (void) LogMagickEvent(X11Event,GetMagickModule(),
5259 " significant bits in color: %d bits",
5260 windows->visual_info->bits_per_rgb);
5261 }
5262 /*
5263 Allocate class and manager hints.
5264 */
5265 windows->class_hints=XAllocClassHint();
5266 windows->manager_hints=XAllocWMHints();
5267 if ((windows->class_hints == (XClassHint *) NULL) ||
5268 (windows->manager_hints == (XWMHints *) NULL))
5269 ThrowXWindowFatalException(ResourceLimitFatalError,
5270 "MemoryAllocationFailed","...");
5271 /*
5272 Determine group leader if we have one.
5273 */
5274 root_window=XRootWindow(display,windows->visual_info->screen);
5275 windows->group_leader.id=(Window) NULL;
5276 if (resource_info->window_group != (char *) NULL)
5277 {
5278 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5279 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5280 strtol((char *) resource_info->window_group,(char **) NULL,0));
5281 if (windows->group_leader.id == (Window) NULL)
5282 windows->group_leader.id=
5283 XWindowByName(display,root_window,resource_info->window_group);
5284 }
5285 return(windows);
5286}
5287
5288/*
5289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5290% %
5291% %
5292% %
5293% X M a k e C u r s o r %
5294% %
5295% %
5296% %
5297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5298%
5299% XMakeCursor() creates a crosshairs X11 cursor.
5300%
5301% The format of the XMakeCursor method is:
5302%
5303% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5304% char *background_color,char *foreground_color)
5305%
5306% A description of each parameter follows:
5307%
5308% o display: Specifies a connection to an X server; returned from
5309% XOpenDisplay.
5310%
5311% o window: Specifies the ID of the window for which the cursor is
5312% assigned.
5313%
5314% o colormap: Specifies the ID of the colormap from which the background
5315% and foreground color will be retrieved.
5316%
5317% o background_color: Specifies the color to use for the cursor background.
5318%
5319% o foreground_color: Specifies the color to use for the cursor foreground.
5320%
5321*/
5322MagickExport Cursor XMakeCursor(Display *display,Window window,
5323 Colormap colormap,char *background_color,char *foreground_color)
5324{
5325#define scope_height 17
5326#define scope_x_hot 8
5327#define scope_y_hot 8
5328#define scope_width 17
5329
5330 static const unsigned char
5331 scope_bits[] =
5332 {
5333 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5334 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5335 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5336 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5337 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5338 },
5339 scope_mask_bits[] =
5340 {
5341 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5342 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5343 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5344 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5345 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5346 };
5347
5348 Cursor
5349 cursor;
5350
5351 Pixmap
5352 mask,
5353 source;
5354
5355 XColor
5356 background,
5357 foreground;
5358
5359 assert(display != (Display *) NULL);
5360 assert(window != (Window) NULL);
5361 assert(colormap != (Colormap) NULL);
5362 assert(background_color != (char *) NULL);
5363 assert(foreground_color != (char *) NULL);
5364 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5365 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5366 scope_height);
5367 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5368 scope_width,scope_height);
5369 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5370 {
5371 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5372 return((Cursor) NULL);
5373 }
5374 (void) XParseColor(display,colormap,background_color,&background);
5375 (void) XParseColor(display,colormap,foreground_color,&foreground);
5376 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5377 scope_x_hot,scope_y_hot);
5378 (void) XFreePixmap(display,source);
5379 (void) XFreePixmap(display,mask);
5380 return(cursor);
5381}
5382
5383/*
5384%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5385% %
5386% %
5387% %
5388% X M a k e I m a g e %
5389% %
5390% %
5391% %
5392%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5393%
5394% XMakeImage() creates an X11 image. If the image size differs from the X11
5395% image size, the image is first resized.
5396%
5397% The format of the XMakeImage method is:
5398%
5399% MagickBooleanType XMakeImage(Display *display,
5400% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5401% unsigned int width,unsigned int height)
5402%
5403% A description of each parameter follows:
5404%
5405% o display: Specifies a connection to an X server; returned from
5406% XOpenDisplay.
5407%
5408% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5409%
5410% o window: Specifies a pointer to a XWindowInfo structure.
5411%
5412% o image: the image.
5413%
5414% o width: Specifies the width in pixels of the rectangular area to
5415% display.
5416%
5417% o height: Specifies the height in pixels of the rectangular area to
5418% display.
5419%
5420*/
5421MagickExport MagickBooleanType XMakeImage(Display *display,
5422 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5423 unsigned int width,unsigned int height)
5424{
5425#define CheckOverflowException(length,width,height) \
5426 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5427
5428 int
5429 depth,
5430 format;
5431
5432 size_t
5433 length;
5434
5435 XImage
5436 *matte_image,
5437 *ximage;
5438
5439 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5440 assert(display != (Display *) NULL);
5441 assert(resource_info != (XResourceInfo *) NULL);
5442 assert(window != (XWindowInfo *) NULL);
5443 assert(width != 0);
5444 assert(height != 0);
5445 if ((window->width == 0) || (window->height == 0))
5446 return(MagickFalse);
5447 /*
5448 Apply user transforms to the image.
5449 */
5450 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5451 (void) XFlush(display);
5452 depth=(int) window->depth;
5453 if (window->destroy)
5454 window->image=DestroyImage(window->image);
5455 window->image=image;
5456 window->destroy=MagickFalse;
5457 if (window->image != (Image *) NULL)
5458 {
5459 if (window->crop_geometry != (char *) NULL)
5460 {
5461 Image
5462 *crop_image;
5463
5464 RectangleInfo
5465 crop_info;
5466
5467 /*
5468 Crop image.
5469 */
5470 window->image->page.x=0;
5471 window->image->page.y=0;
5472 (void) ParsePageGeometry(window->image,window->crop_geometry,
5473 &crop_info,&image->exception);
5474 crop_image=CropImage(window->image,&crop_info,&image->exception);
5475 if (crop_image != (Image *) NULL)
5476 {
5477 if (window->image != image)
5478 window->image=DestroyImage(window->image);
5479 window->image=crop_image;
5480 window->destroy=MagickTrue;
5481 }
5482 }
5483 if ((width != (unsigned int) window->image->columns) ||
5484 (height != (unsigned int) window->image->rows))
5485 {
5486 Image
5487 *resize_image;
5488
5489 /*
5490 Resize image.
5491 */
5492 resize_image=NewImageList();
5493 if (window->pixel_info->colors != 0)
5494 resize_image=SampleImage(window->image,width,height,
5495 &image->exception);
5496 else
5497 resize_image=ThumbnailImage(window->image,width,height,
5498 &image->exception);
5499 if (resize_image != (Image *) NULL)
5500 {
5501 if (window->image != image)
5502 window->image=DestroyImage(window->image);
5503 window->image=resize_image;
5504 window->destroy=MagickTrue;
5505 }
5506 }
5507 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005508 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005509 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005510 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005511 }
5512 /*
5513 Create X image.
5514 */
5515 ximage=(XImage *) NULL;
5516 format=(depth == 1) ? XYBitmap : ZPixmap;
5517#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5518 if (window->shared_memory != MagickFalse)
5519 {
5520 XShmSegmentInfo
5521 *segment_info;
5522
5523 segment_info=(XShmSegmentInfo *) window->segment_info;
5524 segment_info[1].shmid=(-1);
5525 segment_info[1].shmaddr=(char *) NULL;
5526 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5527 (char *) NULL,&segment_info[1],width,height);
5528 if (ximage == (XImage *) NULL)
5529 window->shared_memory=MagickFalse;
5530 length=(size_t) ximage->bytes_per_line*ximage->height;
5531 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5532 window->shared_memory=MagickFalse;
5533 if (window->shared_memory != MagickFalse)
5534 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5535 if (window->shared_memory != MagickFalse)
5536 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5537 if (segment_info[1].shmid < 0)
5538 window->shared_memory=MagickFalse;
5539 if (window->shared_memory != MagickFalse)
5540 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5541 else
5542 {
5543 if (ximage != (XImage *) NULL)
5544 XDestroyImage(ximage);
5545 ximage=(XImage *) NULL;
5546 if (segment_info[1].shmaddr)
5547 {
5548 (void) shmdt(segment_info[1].shmaddr);
5549 segment_info[1].shmaddr=(char *) NULL;
5550 }
5551 if (segment_info[1].shmid >= 0)
5552 {
5553 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5554 segment_info[1].shmid=(-1);
5555 }
5556 }
5557 }
5558#endif
5559 /*
5560 Allocate X image pixel data.
5561 */
5562#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5563 if (window->shared_memory)
5564 {
5565 Status
5566 status;
5567
5568 XShmSegmentInfo
5569 *segment_info;
5570
5571 (void) XSync(display,MagickFalse);
5572 xerror_alert=MagickFalse;
5573 segment_info=(XShmSegmentInfo *) window->segment_info;
5574 ximage->data=segment_info[1].shmaddr;
5575 segment_info[1].readOnly=MagickFalse;
5576 status=XShmAttach(display,&segment_info[1]);
5577 if (status != False)
5578 (void) XSync(display,MagickFalse);
5579 if ((status == False) || (xerror_alert != MagickFalse))
5580 {
5581 window->shared_memory=MagickFalse;
5582 if (status != False)
5583 XShmDetach(display,&segment_info[1]);
5584 if (ximage != (XImage *) NULL)
5585 {
5586 ximage->data=NULL;
5587 XDestroyImage(ximage);
5588 ximage=(XImage *) NULL;
5589 }
5590 if (segment_info[1].shmid >= 0)
5591 {
5592 if (segment_info[1].shmaddr != NULL)
5593 (void) shmdt(segment_info[1].shmaddr);
5594 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5595 segment_info[1].shmid=(-1);
5596 segment_info[1].shmaddr=(char *) NULL;
5597 }
5598 }
5599 }
5600#endif
5601 if (window->shared_memory == MagickFalse)
5602 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5603 (char *) NULL,width,height,XBitmapPad(display),0);
5604 if (ximage == (XImage *) NULL)
5605 {
5606 /*
5607 Unable to create X image.
5608 */
5609 (void) XCheckDefineCursor(display,window->id,window->cursor);
5610 return(MagickFalse);
5611 }
5612 length=(size_t) ximage->bytes_per_line*ximage->height;
5613 if (IsEventLogging())
5614 {
5615 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5616 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5617 ximage->width,ximage->height);
5618 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5619 ximage->format);
5620 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5621 ximage->byte_order);
5622 (void) LogMagickEvent(X11Event,GetMagickModule(),
5623 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5624 ximage->bitmap_bit_order,ximage->bitmap_pad);
5625 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5626 ximage->depth);
5627 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5628 ximage->bytes_per_line);
5629 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5630 ximage->bits_per_pixel);
5631 (void) LogMagickEvent(X11Event,GetMagickModule(),
5632 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5633 ximage->green_mask,ximage->blue_mask);
5634 }
5635 if (window->shared_memory == MagickFalse)
5636 {
5637 if (ximage->format != XYBitmap)
5638 ximage->data=(char *) AcquireQuantumMemory((size_t)
5639 ximage->bytes_per_line,(size_t) ximage->height);
5640 else
5641 ximage->data=(char *) AcquireQuantumMemory((size_t)
5642 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5643 }
5644 if (ximage->data == (char *) NULL)
5645 {
5646 /*
5647 Unable to allocate pixel data.
5648 */
5649 XDestroyImage(ximage);
5650 ximage=(XImage *) NULL;
5651 (void) XCheckDefineCursor(display,window->id,window->cursor);
5652 return(MagickFalse);
5653 }
5654 if (window->ximage != (XImage *) NULL)
5655 {
5656 /*
5657 Destroy previous X image.
5658 */
5659 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5660#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5661 if (window->segment_info != (XShmSegmentInfo *) NULL)
5662 {
5663 XShmSegmentInfo
5664 *segment_info;
5665
5666 segment_info=(XShmSegmentInfo *) window->segment_info;
5667 if (segment_info[0].shmid >= 0)
5668 {
5669 (void) XSync(display,MagickFalse);
5670 (void) XShmDetach(display,&segment_info[0]);
5671 (void) XSync(display,MagickFalse);
5672 if (segment_info[0].shmaddr != (char *) NULL)
5673 (void) shmdt(segment_info[0].shmaddr);
5674 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5675 segment_info[0].shmid=(-1);
5676 segment_info[0].shmaddr=(char *) NULL;
5677 window->ximage->data=(char *) NULL;
5678 }
5679 }
5680#endif
5681 if (window->ximage->data != (char *) NULL)
5682 free(window->ximage->data);
5683 window->ximage->data=(char *) NULL;
5684 XDestroyImage(window->ximage);
5685 window->ximage=(XImage *) NULL;
5686 }
5687#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5688 if (window->segment_info != (XShmSegmentInfo *) NULL)
5689 {
5690 XShmSegmentInfo
5691 *segment_info;
5692
5693 segment_info=(XShmSegmentInfo *) window->segment_info;
5694 segment_info[0]=segment_info[1];
5695 }
5696#endif
5697 window->ximage=ximage;
5698 matte_image=(XImage *) NULL;
5699 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5700 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005701 ((int) width <= XDisplayWidth(display,window->screen)) &&
5702 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005703 {
5704 /*
5705 Create matte image.
5706 */
5707 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5708 (char *) NULL,width,height,XBitmapPad(display),0);
5709 if (IsEventLogging())
5710 {
5711 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5712 (void) LogMagickEvent(X11Event,GetMagickModule(),
5713 " width, height: %dx%d",matte_image->width,matte_image->height);
5714 }
5715 if (matte_image != (XImage *) NULL)
5716 {
5717 /*
5718 Allocate matte image pixel data.
5719 */
5720 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5721 matte_image->bytes_per_line*matte_image->depth,
5722 (size_t) matte_image->height);
5723 if (matte_image->data == (char *) NULL)
5724 {
5725 XDestroyImage(matte_image);
5726 matte_image=(XImage *) NULL;
5727 }
5728 }
5729 }
5730 if (window->matte_image != (XImage *) NULL)
5731 {
5732 /*
5733 Free matte image.
5734 */
5735 if (window->matte_image->data != (char *) NULL)
5736 free(window->matte_image->data);
5737 window->matte_image->data=(char *) NULL;
5738 XDestroyImage(window->matte_image);
5739 window->matte_image=(XImage *) NULL;
5740 }
5741 window->matte_image=matte_image;
5742 if (window->matte_pixmap != (Pixmap) NULL)
5743 {
5744 (void) XFreePixmap(display,window->matte_pixmap);
5745 window->matte_pixmap=(Pixmap) NULL;
5746#if defined(MAGICKCORE_HAVE_SHAPE)
5747 if (window->shape != MagickFalse)
5748 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5749#endif
5750 }
5751 window->stasis=MagickFalse;
5752 /*
5753 Convert pixels to X image data.
5754 */
5755 if (window->image != (Image *) NULL)
5756 {
5757 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5758 (ximage->bitmap_bit_order == LSBFirst)))
5759 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5760 matte_image);
5761 else
5762 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5763 matte_image);
5764 }
5765 if (window->matte_image != (XImage *) NULL)
5766 {
5767 /*
5768 Create matte pixmap.
5769 */
5770 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5771 if (window->matte_pixmap != (Pixmap) NULL)
5772 {
5773 GC
5774 graphics_context;
5775
5776 XGCValues
5777 context_values;
5778
5779 /*
5780 Copy matte image to matte pixmap.
5781 */
cristy4c08aed2011-07-01 19:47:50 +00005782 context_values.background=0;
5783 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005784 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005785 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005786 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5787 window->matte_image,0,0,0,0,width,height);
5788 (void) XFreeGC(display,graphics_context);
5789#if defined(MAGICKCORE_HAVE_SHAPE)
5790 if (window->shape != MagickFalse)
5791 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5792 window->matte_pixmap,ShapeSet);
5793#endif
5794 }
5795 }
5796 (void) XMakePixmap(display,resource_info,window);
5797 /*
5798 Restore cursor.
5799 */
5800 (void) XCheckDefineCursor(display,window->id,window->cursor);
5801 return(MagickTrue);
5802}
5803
5804/*
5805%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5806% %
5807% %
5808% %
5809+ X M a k e I m a g e L S B F i r s t %
5810% %
5811% %
5812% %
5813%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5814%
5815% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5816% pixels are copied in least-significant bit and byte first order. The
5817% server's scanline pad is respected. Rather than using one or two general
5818% cases, many special cases are found here to help speed up the image
5819% conversion.
5820%
5821% The format of the XMakeImageLSBFirst method is:
5822%
5823% void XMakeImageLSBFirst(Display *display,XWindows *windows)
5824%
5825% A description of each parameter follows:
5826%
5827% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5828%
5829% o window: Specifies a pointer to a XWindowInfo structure.
5830%
5831% o image: the image.
5832%
5833% o ximage: Specifies a pointer to a XImage structure; returned from
5834% XCreateImage.
5835%
5836% o matte_image: Specifies a pointer to a XImage structure; returned from
5837% XCreateImage.
5838%
5839*/
5840static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5841 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5842{
cristyc57f6942010-11-12 01:47:39 +00005843 CacheView
5844 *canvas_view;
5845
cristy3ed852e2009-09-05 21:47:34 +00005846 Image
5847 *canvas;
5848
5849 int
5850 y;
5851
cristy4c08aed2011-07-01 19:47:50 +00005852 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005853 *p;
5854
5855 register int
5856 x;
5857
5858 register unsigned char
5859 *q;
5860
5861 unsigned char
5862 bit,
5863 byte;
5864
5865 unsigned int
5866 scanline_pad;
5867
cristyf2faecf2010-05-28 19:19:36 +00005868 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005869 pixel,
5870 *pixels;
5871
5872 XStandardColormap
5873 *map_info;
5874
5875 assert(resource_info != (XResourceInfo *) NULL);
5876 assert(window != (XWindowInfo *) NULL);
5877 assert(image != (Image *) NULL);
5878 if (image->debug != MagickFalse)
5879 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5880 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005881 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005882 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005883 {
5884 char
5885 size[MaxTextExtent];
5886
5887 Image
5888 *pattern;
5889
5890 ImageInfo
5891 *image_info;
5892
5893 image_info=AcquireImageInfo();
5894 (void) CopyMagickString(image_info->filename,
5895 resource_info->image_info->texture != (char *) NULL ?
5896 resource_info->image_info->texture : "pattern:checkerboard",
5897 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005898 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005899 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005900 image_info->size=ConstantString(size);
5901 pattern=ReadImage(image_info,&image->exception);
5902 image_info=DestroyImageInfo(image_info);
5903 if (pattern != (Image *) NULL)
5904 {
5905 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5906 if (canvas != (Image *) NULL)
5907 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5908 pattern=DestroyImage(pattern);
5909 }
5910 }
5911 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5912 ximage->bits_per_pixel) >> 3));
5913 map_info=window->map_info;
5914 pixels=window->pixel_info->pixels;
5915 q=(unsigned char *) ximage->data;
5916 x=0;
cristyc57f6942010-11-12 01:47:39 +00005917 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005918 if (ximage->format == XYBitmap)
5919 {
5920 register unsigned short
5921 polarity;
5922
5923 unsigned char
5924 background,
5925 foreground;
5926
5927 /*
5928 Convert canvas to big-endian bitmap.
5929 */
5930 background=(unsigned char)
5931 (XPixelIntensity(&window->pixel_info->foreground_color) <
5932 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5933 foreground=(unsigned char)
5934 (XPixelIntensity(&window->pixel_info->background_color) <
5935 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00005936 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005937 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5938 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00005939 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
5940 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005941 for (y=0; y < (int) canvas->rows; y++)
5942 {
cristyc57f6942010-11-12 01:47:39 +00005943 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5944 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005945 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005946 break;
cristy3ed852e2009-09-05 21:47:34 +00005947 bit=0;
5948 byte=0;
5949 for (x=0; x < (int) canvas->columns; x++)
5950 {
5951 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005952 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005953 byte|=foreground;
5954 else
5955 byte|=background;
5956 bit++;
5957 if (bit == 8)
5958 {
5959 *q++=byte;
5960 bit=0;
5961 byte=0;
5962 }
cristyed231572011-07-14 02:18:59 +00005963 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005964 }
5965 if (bit != 0)
5966 *q=byte >> (8-bit);
5967 q+=scanline_pad;
5968 }
5969 }
5970 else
5971 if (window->pixel_info->colors != 0)
5972 switch (ximage->bits_per_pixel)
5973 {
5974 case 2:
5975 {
5976 register unsigned int
5977 nibble;
5978
5979 /*
5980 Convert to 2 bit color-mapped X canvas.
5981 */
5982 for (y=0; y < (int) canvas->rows; y++)
5983 {
cristyc57f6942010-11-12 01:47:39 +00005984 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5985 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005986 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005987 break;
cristy3ed852e2009-09-05 21:47:34 +00005988 nibble=0;
5989 for (x=0; x < (int) canvas->columns; x++)
5990 {
cristy4c08aed2011-07-01 19:47:50 +00005991 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00005992 switch (nibble)
5993 {
5994 case 0:
5995 {
5996 *q=(unsigned char) pixel;
5997 nibble++;
5998 break;
5999 }
6000 case 1:
6001 {
6002 *q|=(unsigned char) (pixel << 2);
6003 nibble++;
6004 break;
6005 }
6006 case 2:
6007 {
6008 *q|=(unsigned char) (pixel << 4);
6009 nibble++;
6010 break;
6011 }
6012 case 3:
6013 {
6014 *q|=(unsigned char) (pixel << 6);
6015 q++;
6016 nibble=0;
6017 break;
6018 }
6019 }
cristyed231572011-07-14 02:18:59 +00006020 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006021 }
6022 q+=scanline_pad;
6023 }
6024 break;
6025 }
6026 case 4:
6027 {
6028 register unsigned int
6029 nibble;
6030
6031 /*
6032 Convert to 4 bit color-mapped X canvas.
6033 */
6034 for (y=0; y < (int) canvas->rows; y++)
6035 {
cristyc57f6942010-11-12 01:47:39 +00006036 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6037 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006038 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006039 break;
cristy3ed852e2009-09-05 21:47:34 +00006040 nibble=0;
6041 for (x=0; x < (int) canvas->columns; x++)
6042 {
cristy4c08aed2011-07-01 19:47:50 +00006043 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006044 switch (nibble)
6045 {
6046 case 0:
6047 {
6048 *q=(unsigned char) pixel;
6049 nibble++;
6050 break;
6051 }
6052 case 1:
6053 {
6054 *q|=(unsigned char) (pixel << 4);
6055 q++;
6056 nibble=0;
6057 break;
6058 }
6059 }
cristyed231572011-07-14 02:18:59 +00006060 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006061 }
6062 q+=scanline_pad;
6063 }
6064 break;
6065 }
6066 case 6:
6067 case 8:
6068 {
6069 /*
6070 Convert to 8 bit color-mapped X canvas.
6071 */
6072 if (resource_info->color_recovery &&
6073 resource_info->quantize_info->dither)
6074 {
6075 XDitherImage(canvas,ximage);
6076 break;
6077 }
6078 for (y=0; y < (int) canvas->rows; y++)
6079 {
cristyc57f6942010-11-12 01:47:39 +00006080 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6081 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006082 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006083 break;
cristy3ed852e2009-09-05 21:47:34 +00006084 for (x=0; x < (int) canvas->columns; x++)
6085 {
cristy4c08aed2011-07-01 19:47:50 +00006086 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006087 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006088 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006089 }
6090 q+=scanline_pad;
6091 }
6092 break;
6093 }
6094 default:
6095 {
6096 register int
6097 k;
6098
6099 register unsigned int
6100 bytes_per_pixel;
6101
6102 unsigned char
cristybb503372010-05-27 20:51:26 +00006103 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006104
6105 /*
6106 Convert to multi-byte color-mapped X canvas.
6107 */
6108 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6109 for (y=0; y < (int) canvas->rows; y++)
6110 {
cristyc57f6942010-11-12 01:47:39 +00006111 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6112 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006113 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006114 break;
cristy3ed852e2009-09-05 21:47:34 +00006115 for (x=0; x < (int) canvas->columns; x++)
6116 {
cristy4c08aed2011-07-01 19:47:50 +00006117 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006118 for (k=0; k < (int) bytes_per_pixel; k++)
6119 {
6120 channel[k]=(unsigned char) pixel;
6121 pixel>>=8;
6122 }
6123 for (k=0; k < (int) bytes_per_pixel; k++)
6124 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006125 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006126 }
6127 q+=scanline_pad;
6128 }
6129 break;
6130 }
6131 }
6132 else
6133 switch (ximage->bits_per_pixel)
6134 {
6135 case 2:
6136 {
6137 register unsigned int
6138 nibble;
6139
6140 /*
6141 Convert to contiguous 2 bit continuous-tone X canvas.
6142 */
6143 for (y=0; y < (int) canvas->rows; y++)
6144 {
6145 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006146 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6147 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006148 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006149 break;
6150 for (x=0; x < (int) canvas->columns; x++)
6151 {
cristy4c08aed2011-07-01 19:47:50 +00006152 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006153 pixel&=0xf;
6154 switch (nibble)
6155 {
6156 case 0:
6157 {
6158 *q=(unsigned char) pixel;
6159 nibble++;
6160 break;
6161 }
6162 case 1:
6163 {
6164 *q|=(unsigned char) (pixel << 2);
6165 nibble++;
6166 break;
6167 }
6168 case 2:
6169 {
6170 *q|=(unsigned char) (pixel << 4);
6171 nibble++;
6172 break;
6173 }
6174 case 3:
6175 {
6176 *q|=(unsigned char) (pixel << 6);
6177 q++;
6178 nibble=0;
6179 break;
6180 }
6181 }
cristyed231572011-07-14 02:18:59 +00006182 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006183 }
6184 q+=scanline_pad;
6185 }
6186 break;
6187 }
6188 case 4:
6189 {
6190 register unsigned int
6191 nibble;
6192
6193 /*
6194 Convert to contiguous 4 bit continuous-tone X canvas.
6195 */
6196 for (y=0; y < (int) canvas->rows; y++)
6197 {
cristyc57f6942010-11-12 01:47:39 +00006198 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6199 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006200 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006201 break;
6202 nibble=0;
6203 for (x=0; x < (int) canvas->columns; x++)
6204 {
cristy4c08aed2011-07-01 19:47:50 +00006205 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006206 pixel&=0xf;
6207 switch (nibble)
6208 {
6209 case 0:
6210 {
6211 *q=(unsigned char) pixel;
6212 nibble++;
6213 break;
6214 }
6215 case 1:
6216 {
6217 *q|=(unsigned char) (pixel << 4);
6218 q++;
6219 nibble=0;
6220 break;
6221 }
6222 }
cristyed231572011-07-14 02:18:59 +00006223 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006224 }
6225 q+=scanline_pad;
6226 }
6227 break;
6228 }
6229 case 6:
6230 case 8:
6231 {
6232 /*
6233 Convert to contiguous 8 bit continuous-tone X canvas.
6234 */
6235 if (resource_info->color_recovery &&
6236 resource_info->quantize_info->dither)
6237 {
6238 XDitherImage(canvas,ximage);
6239 break;
6240 }
6241 for (y=0; y < (int) canvas->rows; y++)
6242 {
cristyc57f6942010-11-12 01:47:39 +00006243 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6244 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006245 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006246 break;
6247 for (x=0; x < (int) canvas->columns; x++)
6248 {
cristy4c08aed2011-07-01 19:47:50 +00006249 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006250 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006251 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006252 }
6253 q+=scanline_pad;
6254 }
6255 break;
6256 }
6257 default:
6258 {
6259 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6260 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6261 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6262 (map_info->blue_mult == 1))
6263 {
6264 /*
6265 Convert to 32 bit continuous-tone X canvas.
6266 */
6267 for (y=0; y < (int) canvas->rows; y++)
6268 {
cristyc57f6942010-11-12 01:47:39 +00006269 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6270 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006271 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006272 break;
6273 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6274 (blue_gamma != 1.0))
6275 {
6276 /*
6277 Gamma correct canvas.
6278 */
6279 for (x=(int) canvas->columns-1; x >= 0; x--)
6280 {
cristyccf844f2010-02-03 23:28:16 +00006281 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006282 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006283 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006284 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006285 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006286 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006287 *q++=0;
cristyed231572011-07-14 02:18:59 +00006288 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006289 }
6290 continue;
6291 }
6292 for (x=(int) canvas->columns-1; x >= 0; x--)
6293 {
cristy4c08aed2011-07-01 19:47:50 +00006294 *q++=ScaleQuantumToChar((Quantum)
6295 GetPixelBlue(canvas,p));
6296 *q++=ScaleQuantumToChar((Quantum)
6297 GetPixelGreen(canvas,p));
6298 *q++=ScaleQuantumToChar((Quantum)
6299 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006300 *q++=0;
cristyed231572011-07-14 02:18:59 +00006301 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006302 }
6303 }
6304 }
6305 else
6306 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6307 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6308 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6309 (map_info->blue_mult == 65536L))
6310 {
6311 /*
6312 Convert to 32 bit continuous-tone X canvas.
6313 */
6314 for (y=0; y < (int) canvas->rows; y++)
6315 {
cristyc57f6942010-11-12 01:47:39 +00006316 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6317 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006318 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006319 break;
6320 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6321 (blue_gamma != 1.0))
6322 {
6323 /*
6324 Gamma correct canvas.
6325 */
6326 for (x=(int) canvas->columns-1; x >= 0; x--)
6327 {
cristyccf844f2010-02-03 23:28:16 +00006328 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006329 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006330 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006331 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006332 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006333 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006334 *q++=0;
cristyed231572011-07-14 02:18:59 +00006335 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006336 }
6337 continue;
6338 }
6339 for (x=(int) canvas->columns-1; x >= 0; x--)
6340 {
cristyccf844f2010-02-03 23:28:16 +00006341 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006342 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006343 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006344 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006345 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006346 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006347 *q++=0;
cristyed231572011-07-14 02:18:59 +00006348 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006349 }
6350 }
6351 }
6352 else
6353 {
6354 register int
6355 k;
6356
6357 register unsigned int
6358 bytes_per_pixel;
6359
6360 unsigned char
cristybb503372010-05-27 20:51:26 +00006361 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006362
6363 /*
6364 Convert to multi-byte continuous-tone X canvas.
6365 */
6366 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6367 for (y=0; y < (int) canvas->rows; y++)
6368 {
cristyc57f6942010-11-12 01:47:39 +00006369 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6370 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006371 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006372 break;
cristyc57f6942010-11-12 01:47:39 +00006373 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006374 {
cristy4c08aed2011-07-01 19:47:50 +00006375 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006376 for (k=0; k < (int) bytes_per_pixel; k++)
6377 {
6378 channel[k]=(unsigned char) pixel;
6379 pixel>>=8;
6380 }
6381 for (k=0; k < (int) bytes_per_pixel; k++)
6382 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006383 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006384 }
6385 q+=scanline_pad;
6386 }
6387 }
6388 break;
6389 }
6390 }
6391 if (matte_image != (XImage *) NULL)
6392 {
6393 /*
6394 Initialize matte canvas.
6395 */
6396 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6397 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6398 q=(unsigned char *) matte_image->data;
6399 for (y=0; y < (int) canvas->rows; y++)
6400 {
cristyc57f6942010-11-12 01:47:39 +00006401 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6402 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006403 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006404 break;
6405 bit=0;
6406 byte=0;
6407 for (x=(int) canvas->columns-1; x >= 0; x--)
6408 {
6409 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006410 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006411 byte|=0x80;
6412 bit++;
6413 if (bit == 8)
6414 {
6415 *q++=byte;
6416 bit=0;
6417 byte=0;
6418 }
cristyed231572011-07-14 02:18:59 +00006419 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006420 }
6421 if (bit != 0)
6422 *q=byte >> (8-bit);
6423 q+=scanline_pad;
6424 }
6425 }
cristyc57f6942010-11-12 01:47:39 +00006426 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006427 if (canvas != image)
6428 canvas=DestroyImage(canvas);
6429}
6430
6431/*
6432%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6433% %
6434% %
6435% %
6436+ X M a k e I m a g e M S B F i r s t %
6437% %
6438% %
6439% %
6440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6441%
6442% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6443% image pixels are copied in most-significant bit and byte first order. The
6444% server's scanline pad is also respected. Rather than using one or two
6445% general cases, many special cases are found here to help speed up the image
6446% conversion.
6447%
6448% The format of the XMakeImageMSBFirst method is:
6449%
6450% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6451%
6452% A description of each parameter follows:
6453%
6454% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6455%
6456% o window: Specifies a pointer to a XWindowInfo structure.
6457%
6458% o image: the image.
6459%
6460% o ximage: Specifies a pointer to a XImage structure; returned from
6461% XCreateImage.
6462%
6463% o matte_image: Specifies a pointer to a XImage structure; returned from
6464% XCreateImage.
6465%
cristy3ed852e2009-09-05 21:47:34 +00006466*/
6467static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6468 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6469{
cristyc57f6942010-11-12 01:47:39 +00006470 CacheView
6471 *canvas_view;
6472
cristy3ed852e2009-09-05 21:47:34 +00006473 Image
6474 *canvas;
6475
6476 int
6477 y;
6478
6479 register int
6480 x;
6481
cristy4c08aed2011-07-01 19:47:50 +00006482 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006483 *p;
6484
6485 register unsigned char
6486 *q;
6487
6488 unsigned char
6489 bit,
6490 byte;
6491
6492 unsigned int
6493 scanline_pad;
6494
cristyf2faecf2010-05-28 19:19:36 +00006495 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006496 pixel,
6497 *pixels;
6498
6499 XStandardColormap
6500 *map_info;
6501
6502 assert(resource_info != (XResourceInfo *) NULL);
6503 assert(window != (XWindowInfo *) NULL);
6504 assert(image != (Image *) NULL);
6505 if (image->debug != MagickFalse)
6506 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6507 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006508 if ((window->immutable != MagickFalse) &&
6509 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006510 {
6511 char
6512 size[MaxTextExtent];
6513
6514 Image
6515 *pattern;
6516
6517 ImageInfo
6518 *image_info;
6519
6520 image_info=AcquireImageInfo();
6521 (void) CopyMagickString(image_info->filename,
6522 resource_info->image_info->texture != (char *) NULL ?
6523 resource_info->image_info->texture : "pattern:checkerboard",
6524 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006525 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006526 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006527 image_info->size=ConstantString(size);
6528 pattern=ReadImage(image_info,&image->exception);
6529 image_info=DestroyImageInfo(image_info);
6530 if (pattern != (Image *) NULL)
6531 {
6532 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6533 if (canvas != (Image *) NULL)
6534 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6535 pattern=DestroyImage(pattern);
6536 }
6537 }
cristy4c08aed2011-07-01 19:47:50 +00006538 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6539 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006540 map_info=window->map_info;
6541 pixels=window->pixel_info->pixels;
6542 q=(unsigned char *) ximage->data;
6543 x=0;
cristyc57f6942010-11-12 01:47:39 +00006544 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006545 if (ximage->format == XYBitmap)
6546 {
6547 register unsigned short
6548 polarity;
6549
6550 unsigned char
6551 background,
6552 foreground;
6553
6554 /*
6555 Convert canvas to big-endian bitmap.
6556 */
6557 background=(unsigned char)
6558 (XPixelIntensity(&window->pixel_info->foreground_color) <
6559 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6560 foreground=(unsigned char)
6561 (XPixelIntensity(&window->pixel_info->background_color) <
6562 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy4c08aed2011-07-01 19:47:50 +00006563 polarity=(unsigned short) ((GetPixelPacketIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006564 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6565 if (canvas->colors == 2)
cristy4c08aed2011-07-01 19:47:50 +00006566 polarity=GetPixelPacketIntensity(&canvas->colormap[0]) <
6567 GetPixelPacketIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006568 for (y=0; y < (int) canvas->rows; y++)
6569 {
cristyc57f6942010-11-12 01:47:39 +00006570 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6571 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006572 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006573 break;
cristy3ed852e2009-09-05 21:47:34 +00006574 bit=0;
6575 byte=0;
6576 for (x=(int) canvas->columns-1; x >= 0; x--)
6577 {
6578 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006579 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006580 byte|=foreground;
6581 else
6582 byte|=background;
6583 bit++;
6584 if (bit == 8)
6585 {
6586 *q++=byte;
6587 bit=0;
6588 byte=0;
6589 }
cristyed231572011-07-14 02:18:59 +00006590 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006591 }
6592 if (bit != 0)
6593 *q=byte << (8-bit);
6594 q+=scanline_pad;
6595 }
6596 }
6597 else
6598 if (window->pixel_info->colors != 0)
6599 switch (ximage->bits_per_pixel)
6600 {
6601 case 2:
6602 {
6603 register unsigned int
6604 nibble;
6605
6606 /*
6607 Convert to 2 bit color-mapped X canvas.
6608 */
6609 for (y=0; y < (int) canvas->rows; y++)
6610 {
cristyc57f6942010-11-12 01:47:39 +00006611 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6612 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006613 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006614 break;
cristy3ed852e2009-09-05 21:47:34 +00006615 nibble=0;
6616 for (x=0; x < (int) canvas->columns; x++)
6617 {
cristy4c08aed2011-07-01 19:47:50 +00006618 pixel=pixels[(ssize_t)
6619 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006620 switch (nibble)
6621 {
6622 case 0:
6623 {
6624 *q=(unsigned char) (pixel << 6);
6625 nibble++;
6626 break;
6627 }
6628 case 1:
6629 {
6630 *q|=(unsigned char) (pixel << 4);
6631 nibble++;
6632 break;
6633 }
6634 case 2:
6635 {
6636 *q|=(unsigned char) (pixel << 2);
6637 nibble++;
6638 break;
6639 }
6640 case 3:
6641 {
6642 *q|=(unsigned char) pixel;
6643 q++;
6644 nibble=0;
6645 break;
6646 }
6647 }
cristyed231572011-07-14 02:18:59 +00006648 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006649 }
6650 q+=scanline_pad;
6651 }
6652 break;
6653 }
6654 case 4:
6655 {
6656 register unsigned int
6657 nibble;
6658
6659 /*
6660 Convert to 4 bit color-mapped X canvas.
6661 */
6662 for (y=0; y < (int) canvas->rows; y++)
6663 {
cristyc57f6942010-11-12 01:47:39 +00006664 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6665 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006666 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006667 break;
cristy3ed852e2009-09-05 21:47:34 +00006668 nibble=0;
6669 for (x=0; x < (int) canvas->columns; x++)
6670 {
cristy4c08aed2011-07-01 19:47:50 +00006671 pixel=pixels[(ssize_t)
6672 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006673 switch (nibble)
6674 {
6675 case 0:
6676 {
6677 *q=(unsigned char) (pixel << 4);
6678 nibble++;
6679 break;
6680 }
6681 case 1:
6682 {
6683 *q|=(unsigned char) pixel;
6684 q++;
6685 nibble=0;
6686 break;
6687 }
6688 }
cristyed231572011-07-14 02:18:59 +00006689 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006690 }
6691 q+=scanline_pad;
6692 }
6693 break;
6694 }
6695 case 6:
6696 case 8:
6697 {
6698 /*
6699 Convert to 8 bit color-mapped X canvas.
6700 */
6701 if (resource_info->color_recovery &&
6702 resource_info->quantize_info->dither)
6703 {
6704 XDitherImage(canvas,ximage);
6705 break;
6706 }
6707 for (y=0; y < (int) canvas->rows; y++)
6708 {
cristyc57f6942010-11-12 01:47:39 +00006709 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6710 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006711 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006712 break;
cristy3ed852e2009-09-05 21:47:34 +00006713 for (x=0; x < (int) canvas->columns; x++)
6714 {
cristy4c08aed2011-07-01 19:47:50 +00006715 pixel=pixels[(ssize_t)
6716 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006717 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006718 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006719 }
6720 q+=scanline_pad;
6721 }
6722 break;
6723 }
6724 default:
6725 {
6726 register int
6727 k;
6728
6729 register unsigned int
6730 bytes_per_pixel;
6731
6732 unsigned char
cristybb503372010-05-27 20:51:26 +00006733 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006734
6735 /*
6736 Convert to 8 bit color-mapped X canvas.
6737 */
6738 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6739 for (y=0; y < (int) canvas->rows; y++)
6740 {
cristyc57f6942010-11-12 01:47:39 +00006741 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6742 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006743 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006744 break;
cristy3ed852e2009-09-05 21:47:34 +00006745 for (x=0; x < (int) canvas->columns; x++)
6746 {
cristy4c08aed2011-07-01 19:47:50 +00006747 pixel=pixels[(ssize_t)
6748 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006749 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6750 {
6751 channel[k]=(unsigned char) pixel;
6752 pixel>>=8;
6753 }
6754 for (k=0; k < (int) bytes_per_pixel; k++)
6755 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006756 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006757 }
6758 q+=scanline_pad;
6759 }
6760 break;
6761 }
6762 }
6763 else
6764 switch (ximage->bits_per_pixel)
6765 {
6766 case 2:
6767 {
6768 register unsigned int
6769 nibble;
6770
6771 /*
6772 Convert to 4 bit continuous-tone X canvas.
6773 */
6774 for (y=0; y < (int) canvas->rows; y++)
6775 {
cristyc57f6942010-11-12 01:47:39 +00006776 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6777 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006778 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006779 break;
6780 nibble=0;
6781 for (x=(int) canvas->columns-1; x >= 0; x--)
6782 {
cristy4c08aed2011-07-01 19:47:50 +00006783 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006784 pixel&=0xf;
6785 switch (nibble)
6786 {
6787 case 0:
6788 {
6789 *q=(unsigned char) (pixel << 6);
6790 nibble++;
6791 break;
6792 }
6793 case 1:
6794 {
6795 *q|=(unsigned char) (pixel << 4);
6796 nibble++;
6797 break;
6798 }
6799 case 2:
6800 {
6801 *q|=(unsigned char) (pixel << 2);
6802 nibble++;
6803 break;
6804 }
6805 case 3:
6806 {
6807 *q|=(unsigned char) pixel;
6808 q++;
6809 nibble=0;
6810 break;
6811 }
6812 }
cristyed231572011-07-14 02:18:59 +00006813 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006814 }
6815 q+=scanline_pad;
6816 }
6817 break;
6818 }
6819 case 4:
6820 {
6821 register unsigned int
6822 nibble;
6823
6824 /*
6825 Convert to 4 bit continuous-tone X canvas.
6826 */
6827 for (y=0; y < (int) canvas->rows; y++)
6828 {
cristyc57f6942010-11-12 01:47:39 +00006829 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6830 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006831 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006832 break;
6833 nibble=0;
6834 for (x=(int) canvas->columns-1; x >= 0; x--)
6835 {
cristy4c08aed2011-07-01 19:47:50 +00006836 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006837 pixel&=0xf;
6838 switch (nibble)
6839 {
6840 case 0:
6841 {
6842 *q=(unsigned char) (pixel << 4);
6843 nibble++;
6844 break;
6845 }
6846 case 1:
6847 {
6848 *q|=(unsigned char) pixel;
6849 q++;
6850 nibble=0;
6851 break;
6852 }
6853 }
cristyed231572011-07-14 02:18:59 +00006854 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006855 }
6856 q+=scanline_pad;
6857 }
6858 break;
6859 }
6860 case 6:
6861 case 8:
6862 {
6863 /*
6864 Convert to 8 bit continuous-tone X canvas.
6865 */
6866 if (resource_info->color_recovery &&
6867 resource_info->quantize_info->dither)
6868 {
6869 XDitherImage(canvas,ximage);
6870 break;
6871 }
6872 for (y=0; y < (int) canvas->rows; y++)
6873 {
cristyc57f6942010-11-12 01:47:39 +00006874 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6875 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006876 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006877 break;
6878 for (x=(int) canvas->columns-1; x >= 0; x--)
6879 {
cristy4c08aed2011-07-01 19:47:50 +00006880 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006881 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006882 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006883 }
6884 q+=scanline_pad;
6885 }
6886 break;
6887 }
6888 default:
6889 {
6890 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6891 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6892 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6893 (map_info->blue_mult == 1))
6894 {
6895 /*
6896 Convert to 32 bit continuous-tone X canvas.
6897 */
6898 for (y=0; y < (int) canvas->rows; y++)
6899 {
cristyc57f6942010-11-12 01:47:39 +00006900 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6901 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006902 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006903 break;
6904 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6905 (blue_gamma != 1.0))
6906 {
6907 /*
6908 Gamma correct canvas.
6909 */
6910 for (x=(int) canvas->columns-1; x >= 0; x--)
6911 {
6912 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006913 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006914 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006915 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006916 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006917 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006918 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006919 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006920 }
6921 continue;
6922 }
6923 for (x=(int) canvas->columns-1; x >= 0; x--)
6924 {
6925 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006926 *q++=ScaleQuantumToChar((Quantum)
6927 GetPixelRed(canvas,p));
6928 *q++=ScaleQuantumToChar((Quantum)
6929 GetPixelGreen(canvas,p));
6930 *q++=ScaleQuantumToChar((Quantum)
6931 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006932 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006933 }
6934 }
6935 }
6936 else
6937 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6938 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6939 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6940 (map_info->blue_mult == 65536L))
6941 {
6942 /*
6943 Convert to 32 bit continuous-tone X canvas.
6944 */
6945 for (y=0; y < (int) canvas->rows; y++)
6946 {
cristyc57f6942010-11-12 01:47:39 +00006947 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6948 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006949 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006950 break;
6951 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6952 (blue_gamma != 1.0))
6953 {
6954 /*
6955 Gamma correct canvas.
6956 */
6957 for (x=(int) canvas->columns-1; x >= 0; x--)
6958 {
6959 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006960 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006961 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006962 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006963 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006964 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006965 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006966 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006967 }
6968 continue;
6969 }
6970 for (x=(int) canvas->columns-1; x >= 0; x--)
6971 {
6972 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006973 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006974 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006975 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006976 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006977 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006978 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00006979 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006980 }
6981 }
6982 }
6983 else
6984 {
6985 register int
6986 k;
6987
6988 register unsigned int
6989 bytes_per_pixel;
6990
6991 unsigned char
cristybb503372010-05-27 20:51:26 +00006992 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006993
6994 /*
6995 Convert to multi-byte continuous-tone X canvas.
6996 */
6997 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6998 for (y=0; y < (int) canvas->rows; y++)
6999 {
cristyc57f6942010-11-12 01:47:39 +00007000 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
7001 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007002 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007003 break;
7004 for (x=(int) canvas->columns-1; x >= 0; x--)
7005 {
cristy4c08aed2011-07-01 19:47:50 +00007006 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007007 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7008 {
7009 channel[k]=(unsigned char) pixel;
7010 pixel>>=8;
7011 }
7012 for (k=0; k < (int) bytes_per_pixel; k++)
7013 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007014 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007015 }
7016 q+=scanline_pad;
7017 }
7018 }
7019 break;
7020 }
7021 }
7022 if (matte_image != (XImage *) NULL)
7023 {
7024 /*
7025 Initialize matte canvas.
7026 */
7027 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7028 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7029 q=(unsigned char *) matte_image->data;
7030 for (y=0; y < (int) canvas->rows; y++)
7031 {
cristyc57f6942010-11-12 01:47:39 +00007032 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7033 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007034 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007035 break;
7036 bit=0;
7037 byte=0;
7038 for (x=(int) canvas->columns-1; x >= 0; x--)
7039 {
7040 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007041 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007042 byte|=0x01;
7043 bit++;
7044 if (bit == 8)
7045 {
7046 *q++=byte;
7047 bit=0;
7048 byte=0;
7049 }
cristyed231572011-07-14 02:18:59 +00007050 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007051 }
7052 if (bit != 0)
7053 *q=byte << (8-bit);
7054 q+=scanline_pad;
7055 }
7056 }
cristyc57f6942010-11-12 01:47:39 +00007057 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007058 if (canvas != image)
7059 canvas=DestroyImage(canvas);
7060}
7061
7062/*
7063%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7064% %
7065% %
7066% %
7067% X M a k e M a g n i f y I m a g e %
7068% %
7069% %
7070% %
7071%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7072%
7073% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7074%
7075% The format of the XMakeMagnifyImage method is:
7076%
7077% void XMakeMagnifyImage(display,windows)
7078%
7079% A description of each parameter follows:
7080%
7081% o display: Specifies a connection to an X server; returned from
7082% XOpenDisplay.
7083%
7084% o windows: Specifies a pointer to a XWindows structure.
7085%
7086*/
7087MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
7088{
7089 char
7090 tuple[MaxTextExtent];
7091
7092 int
7093 y;
7094
cristy4c08aed2011-07-01 19:47:50 +00007095 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007096 pixel;
7097
7098 register int
7099 x;
7100
cristybb503372010-05-27 20:51:26 +00007101 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007102 i;
7103
7104 register unsigned char
7105 *p,
7106 *q;
7107
cristy9d314ff2011-03-09 01:30:28 +00007108 ssize_t
7109 n;
7110
cristy3ed852e2009-09-05 21:47:34 +00007111 static unsigned int
7112 previous_magnify = 0;
7113
7114 static XWindowInfo
7115 magnify_window;
7116
7117 unsigned int
7118 height,
7119 j,
7120 k,
7121 l,
7122 magnify,
7123 scanline_pad,
7124 width;
7125
7126 XImage
7127 *ximage;
7128
7129 /*
7130 Check boundary conditions.
7131 */
7132 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7133 assert(display != (Display *) NULL);
7134 assert(windows != (XWindows *) NULL);
7135 magnify=1;
cristybb503372010-05-27 20:51:26 +00007136 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007137 magnify<<=1;
7138 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7139 magnify<<=1;
7140 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7141 magnify<<=1;
7142 while (magnify > windows->magnify.width)
7143 magnify>>=1;
7144 while (magnify > windows->magnify.height)
7145 magnify>>=1;
7146 if (magnify != previous_magnify)
7147 {
7148 Status
7149 status;
7150
7151 XTextProperty
7152 window_name;
7153
7154 /*
7155 New magnify factor: update magnify window name.
7156 */
7157 i=0;
7158 while ((1 << i) <= (int) magnify)
7159 i++;
cristyb51dff52011-05-19 16:55:47 +00007160 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007161 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007162 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7163 if (status != False)
7164 {
7165 XSetWMName(display,windows->magnify.id,&window_name);
7166 XSetWMIconName(display,windows->magnify.id,&window_name);
7167 (void) XFree((void *) window_name.value);
7168 }
7169 }
7170 previous_magnify=magnify;
7171 ximage=windows->image.ximage;
7172 width=(unsigned int) windows->magnify.ximage->width;
7173 height=(unsigned int) windows->magnify.ximage->height;
7174 if ((windows->magnify.x < 0) ||
7175 (windows->magnify.x >= windows->image.ximage->width))
7176 windows->magnify.x=windows->image.ximage->width >> 1;
7177 x=windows->magnify.x-((width/magnify) >> 1);
7178 if (x < 0)
7179 x=0;
7180 else
7181 if (x > (int) (ximage->width-(width/magnify)))
7182 x=ximage->width-width/magnify;
7183 if ((windows->magnify.y < 0) ||
7184 (windows->magnify.y >= windows->image.ximage->height))
7185 windows->magnify.y=windows->image.ximage->height >> 1;
7186 y=windows->magnify.y-((height/magnify) >> 1);
7187 if (y < 0)
7188 y=0;
7189 else
7190 if (y > (int) (ximage->height-(height/magnify)))
7191 y=ximage->height-height/magnify;
7192 q=(unsigned char *) windows->magnify.ximage->data;
7193 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7194 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7195 if (ximage->bits_per_pixel < 8)
7196 {
7197 register unsigned char
7198 background,
7199 byte,
7200 foreground,
7201 p_bit,
7202 q_bit;
7203
7204 register unsigned int
7205 plane;
7206
7207 XPixelInfo
7208 *pixel_info;
7209
7210 pixel_info=windows->magnify.pixel_info;
7211 switch (ximage->bitmap_bit_order)
7212 {
7213 case LSBFirst:
7214 {
7215 /*
7216 Magnify little-endian bitmap.
7217 */
7218 background=0x00;
7219 foreground=0x80;
7220 if (ximage->format == XYBitmap)
7221 {
7222 background=(unsigned char)
7223 (XPixelIntensity(&pixel_info->foreground_color) <
7224 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7225 foreground=(unsigned char)
7226 (XPixelIntensity(&pixel_info->background_color) <
7227 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7228 if (windows->magnify.depth > 1)
7229 Swap(background,foreground);
7230 }
cristybb503372010-05-27 20:51:26 +00007231 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007232 {
7233 /*
7234 Propogate pixel magnify rows.
7235 */
7236 for (j=0; j < magnify; j++)
7237 {
7238 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7239 ((x*ximage->bits_per_pixel) >> 3);
7240 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7241 q_bit=0;
7242 byte=0;
7243 for (k=0; k < width; k+=magnify)
7244 {
7245 /*
7246 Propogate pixel magnify columns.
7247 */
7248 for (l=0; l < magnify; l++)
7249 {
7250 /*
7251 Propogate each bit plane.
7252 */
7253 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7254 {
7255 byte>>=1;
7256 if (*p & (0x01 << (p_bit+plane)))
7257 byte|=foreground;
7258 else
7259 byte|=background;
7260 q_bit++;
7261 if (q_bit == 8)
7262 {
7263 *q++=byte;
7264 q_bit=0;
7265 byte=0;
7266 }
7267 }
7268 }
7269 p_bit+=ximage->bits_per_pixel;
7270 if (p_bit == 8)
7271 {
7272 p++;
7273 p_bit=0;
7274 }
7275 if (q_bit != 0)
7276 *q=byte >> (8-q_bit);
7277 q+=scanline_pad;
7278 }
7279 }
7280 y++;
7281 }
7282 break;
7283 }
7284 case MSBFirst:
7285 default:
7286 {
7287 /*
7288 Magnify big-endian bitmap.
7289 */
7290 background=0x00;
7291 foreground=0x01;
7292 if (ximage->format == XYBitmap)
7293 {
7294 background=(unsigned char)
7295 (XPixelIntensity(&pixel_info->foreground_color) <
7296 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7297 foreground=(unsigned char)
7298 (XPixelIntensity(&pixel_info->background_color) <
7299 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7300 if (windows->magnify.depth > 1)
7301 Swap(background,foreground);
7302 }
cristybb503372010-05-27 20:51:26 +00007303 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007304 {
7305 /*
7306 Propogate pixel magnify rows.
7307 */
7308 for (j=0; j < magnify; j++)
7309 {
7310 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7311 ((x*ximage->bits_per_pixel) >> 3);
7312 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7313 q_bit=0;
7314 byte=0;
7315 for (k=0; k < width; k+=magnify)
7316 {
7317 /*
7318 Propogate pixel magnify columns.
7319 */
7320 for (l=0; l < magnify; l++)
7321 {
7322 /*
7323 Propogate each bit plane.
7324 */
7325 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7326 {
7327 byte<<=1;
7328 if (*p & (0x80 >> (p_bit+plane)))
7329 byte|=foreground;
7330 else
7331 byte|=background;
7332 q_bit++;
7333 if (q_bit == 8)
7334 {
7335 *q++=byte;
7336 q_bit=0;
7337 byte=0;
7338 }
7339 }
7340 }
7341 p_bit+=ximage->bits_per_pixel;
7342 if (p_bit == 8)
7343 {
7344 p++;
7345 p_bit=0;
7346 }
7347 if (q_bit != 0)
7348 *q=byte << (8-q_bit);
7349 q+=scanline_pad;
7350 }
7351 }
7352 y++;
7353 }
7354 break;
7355 }
7356 }
7357 }
7358 else
7359 switch (ximage->bits_per_pixel)
7360 {
7361 case 6:
7362 case 8:
7363 {
7364 /*
7365 Magnify 8 bit X image.
7366 */
cristybb503372010-05-27 20:51:26 +00007367 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007368 {
7369 /*
7370 Propogate pixel magnify rows.
7371 */
7372 for (j=0; j < magnify; j++)
7373 {
7374 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7375 ((x*ximage->bits_per_pixel) >> 3);
7376 for (k=0; k < width; k+=magnify)
7377 {
7378 /*
7379 Propogate pixel magnify columns.
7380 */
7381 for (l=0; l < magnify; l++)
7382 *q++=(*p);
7383 p++;
7384 }
7385 q+=scanline_pad;
7386 }
7387 y++;
7388 }
7389 break;
7390 }
7391 default:
7392 {
7393 register unsigned int
7394 bytes_per_pixel,
7395 m;
7396
7397 /*
7398 Magnify multi-byte X image.
7399 */
7400 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007401 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007402 {
7403 /*
7404 Propogate pixel magnify rows.
7405 */
7406 for (j=0; j < magnify; j++)
7407 {
7408 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7409 ((x*ximage->bits_per_pixel) >> 3);
7410 for (k=0; k < width; k+=magnify)
7411 {
7412 /*
7413 Propogate pixel magnify columns.
7414 */
7415 for (l=0; l < magnify; l++)
7416 for (m=0; m < bytes_per_pixel; m++)
7417 *q++=(*(p+m));
7418 p+=bytes_per_pixel;
7419 }
7420 q+=scanline_pad;
7421 }
7422 y++;
7423 }
7424 break;
7425 }
7426 }
7427 /*
7428 Copy X image to magnify pixmap.
7429 */
7430 x=windows->magnify.x-((width/magnify) >> 1);
7431 if (x < 0)
7432 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7433 else
7434 if (x > (int) (ximage->width-(width/magnify)))
7435 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7436 else
7437 x=0;
7438 y=windows->magnify.y-((height/magnify) >> 1);
7439 if (y < 0)
7440 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7441 else
7442 if (y > (int) (ximage->height-(height/magnify)))
7443 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7444 else
7445 y=0;
7446 if ((x != 0) || (y != 0))
7447 (void) XFillRectangle(display,windows->magnify.pixmap,
7448 windows->magnify.annotate_context,0,0,width,height);
7449 (void) XPutImage(display,windows->magnify.pixmap,
7450 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7451 height-y);
7452 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7453 (magnify <= (height >> 1))))
7454 {
7455 RectangleInfo
7456 highlight_info;
7457
7458 /*
7459 Highlight center pixel.
7460 */
cristybb503372010-05-27 20:51:26 +00007461 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7462 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007463 highlight_info.width=magnify;
7464 highlight_info.height=magnify;
7465 (void) XDrawRectangle(display,windows->magnify.pixmap,
7466 windows->magnify.highlight_context,(int) highlight_info.x,
7467 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7468 (unsigned int) highlight_info.height-1);
7469 if (magnify > 2)
7470 (void) XDrawRectangle(display,windows->magnify.pixmap,
7471 windows->magnify.annotate_context,(int) highlight_info.x+1,
7472 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7473 (unsigned int) highlight_info.height-3);
7474 }
7475 /*
7476 Show center pixel color.
7477 */
cristyc57f6942010-11-12 01:47:39 +00007478 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7479 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7480 &windows->image.image->exception);
cristyb51dff52011-05-19 16:55:47 +00007481 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007482 windows->magnify.x,windows->magnify.y);
7483 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007484 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007485 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007486 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007487 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007488 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007489 if (pixel.colorspace == CMYKColorspace)
7490 {
7491 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007492 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007493 }
7494 if (pixel.matte != MagickFalse)
7495 {
7496 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007497 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007498 }
7499 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7500 height=(unsigned int) windows->magnify.font_info->ascent+
7501 windows->magnify.font_info->descent;
7502 x=windows->magnify.font_info->max_bounds.width >> 1;
7503 y=windows->magnify.font_info->ascent+(height >> 2);
7504 (void) XDrawImageString(display,windows->magnify.pixmap,
7505 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7506 GetColorTuple(&pixel,MagickTrue,tuple);
7507 y+=height;
7508 (void) XDrawImageString(display,windows->magnify.pixmap,
7509 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7510 (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7511 &windows->image.image->exception);
7512 y+=height;
7513 (void) XDrawImageString(display,windows->magnify.pixmap,
7514 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7515 /*
7516 Refresh magnify window.
7517 */
7518 magnify_window=windows->magnify;
7519 magnify_window.x=0;
7520 magnify_window.y=0;
7521 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7522}
7523
7524/*
7525%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7526% %
7527% %
7528% %
7529% X M a k e P i x m a p %
7530% %
7531% %
7532% %
7533%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7534%
7535% XMakePixmap() creates an X11 pixmap.
7536%
7537% The format of the XMakePixmap method is:
7538%
7539% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7540% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7541% XPixelInfo *pixel)
7542%
7543% A description of each parameter follows:
7544%
7545% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7546%
7547% o display: Specifies a connection to an X server; returned from
7548% XOpenDisplay.
7549%
7550% o window: Specifies a pointer to a XWindowInfo structure.
7551%
cristy3ed852e2009-09-05 21:47:34 +00007552*/
7553static MagickBooleanType XMakePixmap(Display *display,
7554 const XResourceInfo *resource_info,XWindowInfo *window)
7555{
7556 unsigned int
7557 height,
7558 width;
7559
7560 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7561 assert(display != (Display *) NULL);
7562 assert(resource_info != (XResourceInfo *) NULL);
7563 assert(window != (XWindowInfo *) NULL);
7564 if (window->pixmap != (Pixmap) NULL)
7565 {
7566 /*
7567 Destroy previous X pixmap.
7568 */
7569 (void) XFreePixmap(display,window->pixmap);
7570 window->pixmap=(Pixmap) NULL;
7571 }
7572 if (window->use_pixmap == MagickFalse)
7573 return(MagickFalse);
7574 if (window->ximage == (XImage *) NULL)
7575 return(MagickFalse);
7576 /*
7577 Display busy cursor.
7578 */
7579 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7580 (void) XFlush(display);
7581 /*
7582 Create pixmap.
7583 */
7584 width=(unsigned int) window->ximage->width;
7585 height=(unsigned int) window->ximage->height;
7586 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7587 if (window->pixmap == (Pixmap) NULL)
7588 {
7589 /*
7590 Unable to allocate pixmap.
7591 */
7592 (void) XCheckDefineCursor(display,window->id,window->cursor);
7593 return(MagickFalse);
7594 }
7595 /*
7596 Copy X image to pixmap.
7597 */
7598#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7599 if (window->shared_memory)
7600 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7601 window->ximage,0,0,0,0,width,height,MagickTrue);
7602#endif
7603 if (window->shared_memory == MagickFalse)
7604 (void) XPutImage(display,window->pixmap,window->annotate_context,
7605 window->ximage,0,0,0,0,width,height);
7606 if (IsEventLogging())
7607 {
7608 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7609 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7610 width,height);
7611 }
7612 /*
7613 Restore cursor.
7614 */
7615 (void) XCheckDefineCursor(display,window->id,window->cursor);
7616 return(MagickTrue);
7617}
7618
7619/*
7620%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7621% %
7622% %
7623% %
7624% X M a k e S t a n d a r d C o l o r m a p %
7625% %
7626% %
7627% %
7628%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7629%
7630% XMakeStandardColormap() creates an X11 Standard Colormap.
7631%
7632% The format of the XMakeStandardColormap method is:
7633%
7634% XMakeStandardColormap(display,visual_info,resource_info,image,
7635% map_info,pixel)
7636%
7637% A description of each parameter follows:
7638%
7639% o display: Specifies a connection to an X server; returned from
7640% XOpenDisplay.
7641%
7642% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7643% returned from XGetVisualInfo.
7644%
7645% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7646%
7647% o image: the image.
7648%
7649% o map_info: If a Standard Colormap type is specified, this structure is
7650% initialized with info from the Standard Colormap.
7651%
7652% o pixel: Specifies a pointer to a XPixelInfo structure.
7653%
cristy3ed852e2009-09-05 21:47:34 +00007654*/
7655
7656#if defined(__cplusplus) || defined(c_plusplus)
7657extern "C" {
7658#endif
7659
7660static inline MagickRealType DiversityPixelIntensity(
7661 const DiversityPacket *pixel)
7662{
7663 MagickRealType
7664 intensity;
7665
7666 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7667 return(intensity);
7668}
7669
7670static int IntensityCompare(const void *x,const void *y)
7671{
7672 DiversityPacket
7673 *color_1,
7674 *color_2;
7675
7676 int
7677 diversity;
7678
7679 color_1=(DiversityPacket *) x;
7680 color_2=(DiversityPacket *) y;
7681 diversity=(int) (DiversityPixelIntensity(color_2)-
7682 DiversityPixelIntensity(color_1));
7683 return(diversity);
7684}
7685
7686static int PopularityCompare(const void *x,const void *y)
7687{
7688 DiversityPacket
7689 *color_1,
7690 *color_2;
7691
7692 color_1=(DiversityPacket *) x;
7693 color_2=(DiversityPacket *) y;
7694 return((int) color_2->count-(int) color_1->count);
7695}
7696
7697#if defined(__cplusplus) || defined(c_plusplus)
7698}
7699#endif
7700
cristybb503372010-05-27 20:51:26 +00007701static inline Quantum ScaleXToQuantum(const size_t x,
7702 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007703{
7704 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7705}
7706
7707MagickExport void XMakeStandardColormap(Display *display,
7708 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7709 XStandardColormap *map_info,XPixelInfo *pixel)
7710{
7711 Colormap
7712 colormap;
7713
7714 ExceptionInfo
7715 *exception;
7716
cristybb503372010-05-27 20:51:26 +00007717 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007718 i;
7719
7720 Status
7721 status;
7722
cristybb503372010-05-27 20:51:26 +00007723 size_t
cristy3ed852e2009-09-05 21:47:34 +00007724 number_colors,
7725 retain_colors;
7726
7727 unsigned short
7728 gray_value;
7729
7730 XColor
7731 color,
7732 *colors,
7733 *p;
7734
7735 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7736 assert(display != (Display *) NULL);
7737 assert(visual_info != (XVisualInfo *) NULL);
7738 assert(map_info != (XStandardColormap *) NULL);
7739 assert(resource_info != (XResourceInfo *) NULL);
7740 assert(pixel != (XPixelInfo *) NULL);
7741 exception=(&image->exception);
7742 if (resource_info->map_type != (char *) NULL)
7743 {
7744 /*
7745 Standard Colormap is already defined (i.e. xstdcmap).
7746 */
cristy4c08aed2011-07-01 19:47:50 +00007747 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007748 pixel);
7749 number_colors=(unsigned int) (map_info->base_pixel+
7750 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7751 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7752 if ((image->matte == MagickFalse) &&
7753 (resource_info->color_recovery == MagickFalse) &&
7754 resource_info->quantize_info->dither &&
7755 (number_colors < MaxColormapSize))
7756 {
7757 Image
7758 *affinity_image;
7759
cristy4c08aed2011-07-01 19:47:50 +00007760 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007761 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007762
7763 /*
7764 Improve image appearance with error diffusion.
7765 */
7766 affinity_image=AcquireImage((ImageInfo *) NULL);
7767 if (affinity_image == (Image *) NULL)
7768 ThrowXWindowFatalException(ResourceLimitFatalError,
7769 "UnableToDitherImage",image->filename);
7770 affinity_image->columns=number_colors;
7771 affinity_image->rows=1;
7772 /*
7773 Initialize colormap image.
7774 */
7775 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7776 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007777 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007778 {
cristybb503372010-05-27 20:51:26 +00007779 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007780 {
cristy4c08aed2011-07-01 19:47:50 +00007781 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007782 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007783 SetPixelRed(affinity_image,
7784 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7785 map_info->red_max),q);
7786 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007787 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007788 SetPixelGreen(affinity_image,
7789 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7790 (map_info->green_max+1)),map_info->green_max),q);
7791 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007792 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007793 SetPixelBlue(affinity_image,
7794 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7795 map_info->blue_max),q);
7796 SetPixelAlpha(affinity_image,
7797 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007798 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007799 }
7800 (void) SyncAuthenticPixels(affinity_image,exception);
7801 (void) RemapImage(resource_info->quantize_info,image,
7802 affinity_image);
7803 }
cristy4c08aed2011-07-01 19:47:50 +00007804 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007805 pixel);
cristy574cc262011-08-05 01:23:58 +00007806 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007807 affinity_image=DestroyImage(affinity_image);
7808 }
7809 if (IsEventLogging())
7810 {
7811 (void) LogMagickEvent(X11Event,GetMagickModule(),
7812 "Standard Colormap:");
7813 (void) LogMagickEvent(X11Event,GetMagickModule(),
7814 " colormap id: 0x%lx",map_info->colormap);
7815 (void) LogMagickEvent(X11Event,GetMagickModule(),
7816 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7817 map_info->green_max,map_info->blue_max);
7818 (void) LogMagickEvent(X11Event,GetMagickModule(),
7819 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7820 map_info->green_mult,map_info->blue_mult);
7821 }
7822 return;
7823 }
7824 if ((visual_info->klass != DirectColor) &&
7825 (visual_info->klass != TrueColor))
7826 if ((image->storage_class == DirectClass) ||
7827 ((int) image->colors > visual_info->colormap_size))
7828 {
7829 QuantizeInfo
7830 quantize_info;
7831
7832 /*
7833 Image has more colors than the visual supports.
7834 */
7835 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007836 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00007837 (void) QuantizeImage(&quantize_info,image);
7838 }
7839 /*
7840 Free previous and create new colormap.
7841 */
7842 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7843 colormap=XDefaultColormap(display,visual_info->screen);
7844 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7845 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7846 visual_info->visual,visual_info->klass == DirectColor ?
7847 AllocAll : AllocNone);
7848 if (colormap == (Colormap) NULL)
7849 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7850 image->filename);
7851 /*
7852 Initialize the map and pixel info structures.
7853 */
7854 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007855 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007856 /*
7857 Allocating colors in server colormap is based on visual class.
7858 */
7859 switch (visual_info->klass)
7860 {
7861 case StaticGray:
7862 case StaticColor:
7863 {
7864 /*
7865 Define Standard Colormap for StaticGray or StaticColor visual.
7866 */
7867 number_colors=image->colors;
7868 colors=(XColor *) AcquireQuantumMemory((size_t)
7869 visual_info->colormap_size,sizeof(*colors));
7870 if (colors == (XColor *) NULL)
7871 ThrowXWindowFatalException(ResourceLimitFatalError,
7872 "UnableToCreateColormap",image->filename);
7873 p=colors;
7874 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007875 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007876 {
7877 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7878 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7879 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7880 if (visual_info->klass != StaticColor)
7881 {
7882 gray_value=(unsigned short) XPixelIntensity(&color);
7883 color.red=gray_value;
7884 color.green=gray_value;
7885 color.blue=gray_value;
7886 }
7887 status=XAllocColor(display,colormap,&color);
7888 if (status == False)
7889 {
7890 colormap=XCopyColormapAndFree(display,colormap);
7891 (void) XAllocColor(display,colormap,&color);
7892 }
7893 pixel->pixels[i]=color.pixel;
7894 *p++=color;
7895 }
7896 break;
7897 }
7898 case GrayScale:
7899 case PseudoColor:
7900 {
7901 unsigned int
7902 colormap_type;
7903
7904 /*
7905 Define Standard Colormap for GrayScale or PseudoColor visual.
7906 */
7907 number_colors=image->colors;
7908 colors=(XColor *) AcquireQuantumMemory((size_t)
7909 visual_info->colormap_size,sizeof(*colors));
7910 if (colors == (XColor *) NULL)
7911 ThrowXWindowFatalException(ResourceLimitFatalError,
7912 "UnableToCreateColormap",image->filename);
7913 /*
7914 Preallocate our GUI colors.
7915 */
7916 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7917 (void) XAllocColor(display,colormap,&pixel->background_color);
7918 (void) XAllocColor(display,colormap,&pixel->border_color);
7919 (void) XAllocColor(display,colormap,&pixel->matte_color);
7920 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7921 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7922 (void) XAllocColor(display,colormap,&pixel->depth_color);
7923 (void) XAllocColor(display,colormap,&pixel->trough_color);
7924 for (i=0; i < MaxNumberPens; i++)
7925 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7926 /*
7927 Determine if image colors will "fit" into X server colormap.
7928 */
7929 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007930 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007931 NULL,0,pixel->pixels,(unsigned int) image->colors);
7932 if (status != False)
7933 colormap_type=PrivateColormap;
7934 if (colormap_type == SharedColormap)
7935 {
cristyc57f6942010-11-12 01:47:39 +00007936 CacheView
7937 *image_view;
7938
cristy3ed852e2009-09-05 21:47:34 +00007939 DiversityPacket
7940 *diversity;
7941
7942 int
7943 y;
7944
7945 register int
7946 x;
7947
7948 unsigned short
7949 index;
7950
7951 XColor
7952 *server_colors;
7953
7954 /*
7955 Define Standard colormap for shared GrayScale or PseudoColor visual.
7956 */
7957 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7958 sizeof(*diversity));
7959 if (diversity == (DiversityPacket *) NULL)
7960 ThrowXWindowFatalException(ResourceLimitFatalError,
7961 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007962 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007963 {
7964 diversity[i].red=image->colormap[i].red;
7965 diversity[i].green=image->colormap[i].green;
7966 diversity[i].blue=image->colormap[i].blue;
7967 diversity[i].index=(unsigned short) i;
7968 diversity[i].count=0;
7969 }
cristyc57f6942010-11-12 01:47:39 +00007970 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00007971 for (y=0; y < (int) image->rows; y++)
7972 {
cristyc57f6942010-11-12 01:47:39 +00007973 register int
cristy3ed852e2009-09-05 21:47:34 +00007974 x;
7975
cristy4c08aed2011-07-01 19:47:50 +00007976 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00007977 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007978
cristyc57f6942010-11-12 01:47:39 +00007979 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7980 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007981 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007982 break;
cristyc57f6942010-11-12 01:47:39 +00007983 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00007984 {
7985 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00007986 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00007987 }
cristy3ed852e2009-09-05 21:47:34 +00007988 }
cristyc57f6942010-11-12 01:47:39 +00007989 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00007990 /*
7991 Sort colors by decreasing intensity.
7992 */
7993 qsort((void *) diversity,image->colors,sizeof(*diversity),
7994 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00007995 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00007996 {
7997 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00007998 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00007999 }
8000 diversity[image->colors-1].count<<=4;
8001 qsort((void *) diversity,image->colors,sizeof(*diversity),
8002 PopularityCompare);
8003 /*
8004 Allocate colors.
8005 */
8006 p=colors;
8007 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008008 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008009 {
8010 index=diversity[i].index;
8011 color.red=
8012 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8013 color.green=
8014 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8015 color.blue=
8016 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8017 if (visual_info->klass != PseudoColor)
8018 {
8019 gray_value=(unsigned short) XPixelIntensity(&color);
8020 color.red=gray_value;
8021 color.green=gray_value;
8022 color.blue=gray_value;
8023 }
8024 status=XAllocColor(display,colormap,&color);
8025 if (status == False)
8026 break;
8027 pixel->pixels[index]=color.pixel;
8028 *p++=color;
8029 }
8030 /*
8031 Read X server colormap.
8032 */
8033 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8034 visual_info->colormap_size,sizeof(*server_colors));
8035 if (server_colors == (XColor *) NULL)
8036 ThrowXWindowFatalException(ResourceLimitFatalError,
8037 "UnableToCreateColormap",image->filename);
8038 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008039 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008040 (void) XQueryColors(display,colormap,server_colors,
8041 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8042 /*
8043 Select remaining colors from X server colormap.
8044 */
cristybb503372010-05-27 20:51:26 +00008045 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008046 {
8047 index=diversity[i].index;
8048 color.red=
8049 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8050 color.green=
8051 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8052 color.blue=
8053 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8054 if (visual_info->klass != PseudoColor)
8055 {
8056 gray_value=(unsigned short) XPixelIntensity(&color);
8057 color.red=gray_value;
8058 color.green=gray_value;
8059 color.blue=gray_value;
8060 }
8061 XBestPixel(display,colormap,server_colors,(unsigned int)
8062 visual_info->colormap_size,&color);
8063 pixel->pixels[index]=color.pixel;
8064 *p++=color;
8065 }
8066 if ((int) image->colors < visual_info->colormap_size)
8067 {
8068 /*
8069 Fill up colors array-- more choices for pen colors.
8070 */
8071 retain_colors=MagickMin((unsigned int)
8072 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008073 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008074 *p++=server_colors[i];
8075 number_colors+=retain_colors;
8076 }
8077 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8078 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8079 break;
8080 }
8081 /*
8082 Define Standard colormap for private GrayScale or PseudoColor visual.
8083 */
8084 if (status == False)
8085 {
8086 /*
8087 Not enough colormap entries in the colormap-- Create a new colormap.
8088 */
8089 colormap=XCreateColormap(display,
8090 XRootWindow(display,visual_info->screen),visual_info->visual,
8091 AllocNone);
8092 if (colormap == (Colormap) NULL)
8093 ThrowXWindowFatalException(ResourceLimitFatalError,
8094 "UnableToCreateColormap",image->filename);
8095 map_info->colormap=colormap;
8096 if ((int) image->colors < visual_info->colormap_size)
8097 {
8098 /*
8099 Retain colors from the default colormap to help lessens the
8100 effects of colormap flashing.
8101 */
8102 retain_colors=MagickMin((unsigned int)
8103 (visual_info->colormap_size-image->colors),256);
8104 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008105 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008106 {
cristyc57f6942010-11-12 01:47:39 +00008107 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008108 p++;
8109 }
8110 (void) XQueryColors(display,
8111 XDefaultColormap(display,visual_info->screen),
8112 colors+image->colors,(int) retain_colors);
8113 /*
8114 Transfer colors from default to private colormap.
8115 */
8116 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008117 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008118 retain_colors);
8119 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008120 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008121 {
8122 p->pixel=pixel->pixels[i];
8123 p++;
8124 }
8125 (void) XStoreColors(display,colormap,colors+image->colors,
8126 (int) retain_colors);
8127 number_colors+=retain_colors;
8128 }
8129 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008130 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008131 image->colors);
8132 }
8133 /*
8134 Store the image colormap.
8135 */
8136 p=colors;
8137 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008138 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008139 {
8140 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8141 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8142 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8143 if (visual_info->klass != PseudoColor)
8144 {
8145 gray_value=(unsigned short) XPixelIntensity(&color);
8146 color.red=gray_value;
8147 color.green=gray_value;
8148 color.blue=gray_value;
8149 }
8150 color.pixel=pixel->pixels[i];
8151 *p++=color;
8152 }
8153 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8154 break;
8155 }
8156 case TrueColor:
8157 case DirectColor:
8158 default:
8159 {
8160 MagickBooleanType
8161 linear_colormap;
8162
8163 /*
8164 Define Standard Colormap for TrueColor or DirectColor visual.
8165 */
8166 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8167 (map_info->green_max*map_info->green_mult)+
8168 (map_info->blue_max*map_info->blue_mult)+1);
8169 linear_colormap=(number_colors > 4096) ||
8170 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8171 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8172 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8173 MagickTrue : MagickFalse;
8174 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008175 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008176 /*
8177 Allocate color array.
8178 */
8179 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8180 if (colors == (XColor *) NULL)
8181 ThrowXWindowFatalException(ResourceLimitFatalError,
8182 "UnableToCreateColormap",image->filename);
8183 /*
8184 Initialize linear color ramp.
8185 */
8186 p=colors;
8187 color.flags=(char) (DoRed | DoGreen | DoBlue);
8188 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008189 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008190 {
8191 color.blue=(unsigned short) 0;
8192 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008193 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008194 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8195 color.green=color.blue;
8196 color.red=color.blue;
8197 color.pixel=XStandardPixel(map_info,&color);
8198 *p++=color;
8199 }
8200 else
cristybb503372010-05-27 20:51:26 +00008201 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008202 {
8203 color.red=(unsigned short) 0;
8204 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008205 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008206 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8207 color.green=(unsigned int) 0;
8208 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008209 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008210 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8211 map_info->green_max));
8212 color.blue=(unsigned short) 0;
8213 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008214 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008215 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8216 color.pixel=XStandardPixel(map_info,&color);
8217 *p++=color;
8218 }
8219 if ((visual_info->klass == DirectColor) &&
8220 (colormap != XDefaultColormap(display,visual_info->screen)))
8221 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8222 else
cristybb503372010-05-27 20:51:26 +00008223 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008224 (void) XAllocColor(display,colormap,&colors[i]);
8225 break;
8226 }
8227 }
8228 if ((visual_info->klass != DirectColor) &&
8229 (visual_info->klass != TrueColor))
8230 {
8231 /*
8232 Set foreground, background, border, etc. pixels.
8233 */
8234 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8235 &pixel->foreground_color);
8236 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8237 &pixel->background_color);
8238 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8239 {
8240 /*
8241 Foreground and background colors must differ.
8242 */
8243 pixel->background_color.red=(~pixel->foreground_color.red);
8244 pixel->background_color.green=
8245 (~pixel->foreground_color.green);
8246 pixel->background_color.blue=
8247 (~pixel->foreground_color.blue);
8248 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8249 &pixel->background_color);
8250 }
8251 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8252 &pixel->border_color);
8253 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8254 &pixel->matte_color);
8255 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8256 &pixel->highlight_color);
8257 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8258 &pixel->shadow_color);
8259 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8260 &pixel->depth_color);
8261 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8262 &pixel->trough_color);
8263 for (i=0; i < MaxNumberPens; i++)
8264 {
8265 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8266 &pixel->pen_colors[i]);
8267 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8268 }
cristyc57f6942010-11-12 01:47:39 +00008269 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008270 }
8271 colors=(XColor *) RelinquishMagickMemory(colors);
8272 if (IsEventLogging())
8273 {
8274 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8275 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8276 map_info->colormap);
8277 (void) LogMagickEvent(X11Event,GetMagickModule(),
8278 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8279 map_info->green_max,map_info->blue_max);
8280 (void) LogMagickEvent(X11Event,GetMagickModule(),
8281 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8282 map_info->green_mult,map_info->blue_mult);
8283 }
8284}
8285
8286/*
8287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8288% %
8289% %
8290% %
8291% X M a k e W i n d o w %
8292% %
8293% %
8294% %
8295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8296%
8297% XMakeWindow() creates an X11 window.
8298%
8299% The format of the XMakeWindow method is:
8300%
8301% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8302% XClassHint *class_hint,XWMHints *manager_hints,
8303% XWindowInfo *window_info)
8304%
8305% A description of each parameter follows:
8306%
8307% o display: Specifies a connection to an X server; returned from
8308% XOpenDisplay.
8309%
8310% o parent: Specifies the parent window_info.
8311%
8312% o argv: Specifies the application's argument list.
8313%
8314% o argc: Specifies the number of arguments.
8315%
8316% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8317%
8318% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8319%
8320% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8321%
8322*/
8323MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8324 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8325 XWindowInfo *window_info)
8326{
8327#define MinWindowSize 64
8328
8329 Atom
8330 atom_list[2];
8331
8332 int
8333 gravity;
8334
8335 static XTextProperty
8336 icon_name,
8337 window_name;
8338
8339 Status
8340 status;
8341
8342 XSizeHints
8343 *size_hints;
8344
8345 /*
8346 Set window info hints.
8347 */
8348 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8349 assert(display != (Display *) NULL);
8350 assert(window_info != (XWindowInfo *) NULL);
8351 size_hints=XAllocSizeHints();
8352 if (size_hints == (XSizeHints *) NULL)
8353 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008354 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008355 size_hints->x=window_info->x;
8356 size_hints->y=window_info->y;
8357 size_hints->width=(int) window_info->width;
8358 size_hints->height=(int) window_info->height;
8359 if (window_info->immutable != MagickFalse)
8360 {
8361 /*
8362 Window size cannot be changed.
8363 */
8364 size_hints->min_width=size_hints->width;
8365 size_hints->min_height=size_hints->height;
8366 size_hints->max_width=size_hints->width;
8367 size_hints->max_height=size_hints->height;
8368 size_hints->flags|=PMinSize;
8369 size_hints->flags|=PMaxSize;
8370 }
8371 else
8372 {
8373 /*
8374 Window size can be changed.
8375 */
8376 size_hints->min_width=(int) window_info->min_width;
8377 size_hints->min_height=(int) window_info->min_height;
8378 size_hints->flags|=PResizeInc;
8379 size_hints->width_inc=(int) window_info->width_inc;
8380 size_hints->height_inc=(int) window_info->height_inc;
8381#if !defined(PRE_R4_ICCCM)
8382 size_hints->flags|=PBaseSize;
8383 size_hints->base_width=size_hints->width_inc;
8384 size_hints->base_height=size_hints->height_inc;
8385#endif
8386 }
8387 gravity=NorthWestGravity;
8388 if (window_info->geometry != (char *) NULL)
8389 {
8390 char
8391 default_geometry[MaxTextExtent],
8392 geometry[MaxTextExtent];
8393
8394 int
8395 flags;
8396
8397 register char
8398 *p;
8399
8400 /*
8401 User specified geometry.
8402 */
cristyb51dff52011-05-19 16:55:47 +00008403 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008404 size_hints->width,size_hints->height);
8405 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8406 p=geometry;
8407 while (strlen(p) != 0)
8408 {
8409 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8410 p++;
8411 else
8412 (void) CopyMagickString(p,p+1,MaxTextExtent);
8413 }
8414 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8415 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8416 &size_hints->width,&size_hints->height,&gravity);
8417 if ((flags & WidthValue) && (flags & HeightValue))
8418 size_hints->flags|=USSize;
8419 if ((flags & XValue) && (flags & YValue))
8420 {
8421 size_hints->flags|=USPosition;
8422 window_info->x=size_hints->x;
8423 window_info->y=size_hints->y;
8424 }
8425 }
8426#if !defined(PRE_R4_ICCCM)
8427 size_hints->win_gravity=gravity;
8428 size_hints->flags|=PWinGravity;
8429#endif
8430 if (window_info->id == (Window) NULL)
8431 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8432 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8433 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008434 window_info->visual,(unsigned long) window_info->mask,
8435 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008436 else
8437 {
8438 MagickStatusType
8439 mask;
8440
8441 XEvent
8442 sans_event;
8443
8444 XWindowChanges
8445 window_changes;
8446
8447 /*
8448 Window already exists; change relevant attributes.
8449 */
cristyc57f6942010-11-12 01:47:39 +00008450 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8451 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008452 mask=ConfigureNotify;
8453 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8454 window_changes.x=window_info->x;
8455 window_changes.y=window_info->y;
8456 window_changes.width=(int) window_info->width;
8457 window_changes.height=(int) window_info->height;
8458 mask=(MagickStatusType) (CWWidth | CWHeight);
8459 if (window_info->flags & USPosition)
8460 mask|=CWX | CWY;
8461 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8462 mask,&window_changes);
8463 }
8464 if (window_info->id == (Window) NULL)
8465 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8466 window_info->name);
8467 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8468 if (status == False)
8469 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8470 window_info->name);
8471 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8472 if (status == False)
8473 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8474 window_info->icon_name);
8475 if (window_info->icon_geometry != (char *) NULL)
8476 {
8477 int
8478 flags,
8479 height,
8480 width;
8481
8482 /*
8483 User specified icon geometry.
8484 */
8485 size_hints->flags|=USPosition;
8486 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8487 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8488 &manager_hints->icon_y,&width,&height,&gravity);
8489 if ((flags & XValue) && (flags & YValue))
8490 manager_hints->flags|=IconPositionHint;
8491 }
8492 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8493 size_hints,manager_hints,class_hint);
8494 if (window_name.value != (void *) NULL)
8495 {
8496 (void) XFree((void *) window_name.value);
8497 window_name.value=(unsigned char *) NULL;
8498 window_name.nitems=0;
8499 }
8500 if (icon_name.value != (void *) NULL)
8501 {
8502 (void) XFree((void *) icon_name.value);
8503 icon_name.value=(unsigned char *) NULL;
8504 icon_name.nitems=0;
8505 }
8506 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8507 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8508 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8509 (void) XFree((void *) size_hints);
8510 if (window_info->shape != MagickFalse)
8511 {
8512#if defined(MAGICKCORE_HAVE_SHAPE)
8513 int
8514 error_base,
8515 event_base;
8516
8517 /*
8518 Can we apply a non-rectangular shaping mask?
8519 */
8520 error_base=0;
8521 event_base=0;
8522 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8523 window_info->shape=MagickFalse;
8524#else
8525 window_info->shape=MagickFalse;
8526#endif
8527 }
8528 if (window_info->shared_memory)
8529 {
8530#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8531 /*
8532 Can we use shared memory with this window?
8533 */
8534 if (XShmQueryExtension(display) == 0)
8535 window_info->shared_memory=MagickFalse;
8536#else
8537 window_info->shared_memory=MagickFalse;
8538#endif
8539 }
8540 window_info->image=NewImageList();
8541 window_info->destroy=MagickFalse;
8542}
8543
8544/*
8545%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8546% %
8547% %
8548% %
8549% X M a g i c k P r o g r e s s M o n i t o r %
8550% %
8551% %
8552% %
8553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8554%
8555% XMagickProgressMonitor() displays the progress a task is making in
8556% completing a task.
8557%
8558% The format of the XMagickProgressMonitor method is:
8559%
8560% void XMagickProgressMonitor(const char *task,
8561% const MagickOffsetType quantum,const MagickSizeType span,
8562% void *client_data)
8563%
8564% A description of each parameter follows:
8565%
8566% o task: Identifies the task in progress.
8567%
8568% o quantum: Specifies the quantum position within the span which represents
8569% how much progress has been made in completing a task.
8570%
8571% o span: Specifies the span relative to completing a task.
8572%
8573% o client_data: Pointer to any client data.
8574%
8575*/
8576
8577static const char *GetLocaleMonitorMessage(const char *text)
8578{
8579 char
8580 message[MaxTextExtent],
8581 tag[MaxTextExtent];
8582
8583 const char
8584 *locale_message;
8585
8586 register char
8587 *p;
8588
8589 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8590 p=strrchr(tag,'/');
8591 if (p != (char *) NULL)
8592 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008593 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008594 locale_message=GetLocaleMessage(message);
8595 if (locale_message == message)
8596 return(text);
8597 return(locale_message);
8598}
8599
8600MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8601 const MagickOffsetType quantum,const MagickSizeType span,
8602 void *magick_unused(client_data))
8603{
8604 XWindows
8605 *windows;
8606
8607 windows=XSetWindows((XWindows *) ~0);
8608 if (windows == (XWindows *) NULL)
8609 return(MagickTrue);
8610 if (windows->info.mapped != MagickFalse)
8611 XProgressMonitorWidget(windows->display,windows,
8612 GetLocaleMonitorMessage(tag),quantum,span);
8613 return(MagickTrue);
8614}
8615
8616/*
8617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8618% %
8619% %
8620% %
8621% X Q u e r y C o l o r D a t a b a s e %
8622% %
8623% %
8624% %
8625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8626%
8627% XQueryColorDatabase() looks up a RGB values for a color given in the target
8628% string.
8629%
8630% The format of the XQueryColorDatabase method is:
8631%
8632% MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8633%
8634% A description of each parameter follows:
8635%
8636% o target: Specifies the color to lookup in the X color database.
8637%
8638% o color: A pointer to an PixelPacket structure. The RGB value of the target
8639% color is returned as this value.
8640%
8641*/
8642MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8643 XColor *color)
8644{
8645 Colormap
8646 colormap;
8647
8648 static Display
8649 *display = (Display *) NULL;
8650
8651 Status
8652 status;
8653
8654 XColor
8655 xcolor;
8656
8657 /*
8658 Initialize color return value.
8659 */
8660 assert(color != (XColor *) NULL);
8661 color->red=0;
8662 color->green=0;
8663 color->blue=0;
8664 color->flags=(char) (DoRed | DoGreen | DoBlue);
8665 if ((target == (char *) NULL) || (*target == '\0'))
8666 target="#ffffffffffff";
8667 /*
8668 Let the X server define the color for us.
8669 */
8670 if (display == (Display *) NULL)
8671 display=XOpenDisplay((char *) NULL);
8672 if (display == (Display *) NULL)
8673 {
8674 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8675 return(MagickFalse);
8676 }
8677 colormap=XDefaultColormap(display,XDefaultScreen(display));
8678 status=XParseColor(display,colormap,(char *) target,&xcolor);
8679 if (status == False)
8680 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8681 else
8682 {
8683 color->red=xcolor.red;
8684 color->green=xcolor.green;
8685 color->blue=xcolor.blue;
8686 color->flags=xcolor.flags;
8687 }
8688 return(status != False ? MagickTrue : MagickFalse);
8689}
8690
8691/*
8692%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8693% %
8694% %
8695% %
8696% X Q u e r y P o s i t i o n %
8697% %
8698% %
8699% %
8700%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8701%
8702% XQueryPosition() gets the pointer coordinates relative to a window.
8703%
8704% The format of the XQueryPosition method is:
8705%
8706% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8707%
8708% A description of each parameter follows:
8709%
8710% o display: Specifies a connection to an X server; returned from
8711% XOpenDisplay.
8712%
8713% o window: Specifies a pointer to a Window.
8714%
8715% o x: Return the x coordinate of the pointer relative to the origin of the
8716% window.
8717%
8718% o y: Return the y coordinate of the pointer relative to the origin of the
8719% window.
8720%
8721*/
8722MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8723{
8724 int
8725 x_root,
8726 y_root;
8727
8728 unsigned int
8729 mask;
8730
8731 Window
8732 root_window;
8733
8734 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8735 assert(display != (Display *) NULL);
8736 assert(window != (Window) NULL);
8737 assert(x != (int *) NULL);
8738 assert(y != (int *) NULL);
8739 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8740 x,y,&mask);
8741}
8742
8743/*
8744%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8745% %
8746% %
8747% %
8748% X R e f r e s h W i n d o w %
8749% %
8750% %
8751% %
8752%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8753%
8754% XRefreshWindow() refreshes an image in a X window.
8755%
8756% The format of the XRefreshWindow method is:
8757%
8758% void XRefreshWindow(Display *display,const XWindowInfo *window,
8759% const XEvent *event)
8760%
8761% A description of each parameter follows:
8762%
8763% o display: Specifies a connection to an X server; returned from
8764% XOpenDisplay.
8765%
8766% o window: Specifies a pointer to a XWindowInfo structure.
8767%
8768% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8769% the entire image is refreshed.
8770%
8771*/
8772MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8773 const XEvent *event)
8774{
8775 int
8776 x,
8777 y;
8778
8779 unsigned int
8780 height,
8781 width;
8782
8783 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8784 assert(display != (Display *) NULL);
8785 assert(window != (XWindowInfo *) NULL);
8786 if (window->ximage == (XImage *) NULL)
8787 return;
8788 if (event != (XEvent *) NULL)
8789 {
8790 /*
8791 Determine geometry from expose event.
8792 */
8793 x=event->xexpose.x;
8794 y=event->xexpose.y;
8795 width=(unsigned int) event->xexpose.width;
8796 height=(unsigned int) event->xexpose.height;
8797 }
8798 else
8799 {
8800 XEvent
8801 sans_event;
8802
8803 /*
8804 Refresh entire window; discard outstanding expose events.
8805 */
8806 x=0;
8807 y=0;
8808 width=window->width;
8809 height=window->height;
8810 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008811 if (window->matte_pixmap != (Pixmap) NULL)
8812 {
8813#if defined(MAGICKCORE_HAVE_SHAPE)
8814 if (window->shape != MagickFalse)
8815 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8816 window->matte_pixmap,ShapeSet);
8817#endif
8818 }
cristy3ed852e2009-09-05 21:47:34 +00008819 }
8820 /*
8821 Check boundary conditions.
8822 */
8823 if ((window->ximage->width-(x+window->x)) < (int) width)
8824 width=(unsigned int) (window->ximage->width-(x+window->x));
8825 if ((window->ximage->height-(y+window->y)) < (int) height)
8826 height=(unsigned int) (window->ximage->height-(y+window->y));
8827 /*
8828 Refresh image.
8829 */
8830 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008831 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008832 if (window->pixmap != (Pixmap) NULL)
8833 {
8834 if (window->depth > 1)
8835 (void) XCopyArea(display,window->pixmap,window->id,
8836 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8837 else
8838 (void) XCopyPlane(display,window->pixmap,window->id,
8839 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8840 1L);
8841 }
8842 else
8843 {
8844#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8845 if (window->shared_memory)
8846 (void) XShmPutImage(display,window->id,window->annotate_context,
8847 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8848#endif
8849 if (window->shared_memory == MagickFalse)
8850 (void) XPutImage(display,window->id,window->annotate_context,
8851 window->ximage,x+window->x,y+window->y,x,y,width,height);
8852 }
8853 if (window->matte_pixmap != (Pixmap) NULL)
8854 (void) XSetClipMask(display,window->annotate_context,None);
8855 (void) XFlush(display);
8856}
8857
8858/*
8859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8860% %
8861% %
8862% %
8863% X R e m o t e C o m m a n d %
8864% %
8865% %
8866% %
8867%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8868%
8869% XRemoteCommand() forces a remote display(1) to display the specified
8870% image filename.
8871%
8872% The format of the XRemoteCommand method is:
8873%
8874% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8875% const char *filename)
8876%
8877% A description of each parameter follows:
8878%
8879% o display: Specifies a connection to an X server; returned from
8880% XOpenDisplay.
8881%
8882% o window: Specifies the name or id of an X window.
8883%
8884% o filename: the name of the image filename to display.
8885%
8886*/
8887MagickExport MagickBooleanType XRemoteCommand(Display *display,
8888 const char *window,const char *filename)
8889{
8890 Atom
8891 remote_atom;
8892
8893 Window
8894 remote_window,
8895 root_window;
8896
8897 assert(filename != (char *) NULL);
8898 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8899 if (display == (Display *) NULL)
8900 display=XOpenDisplay((char *) NULL);
8901 if (display == (Display *) NULL)
8902 {
8903 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8904 return(MagickFalse);
8905 }
8906 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8907 remote_window=(Window) NULL;
8908 root_window=XRootWindow(display,XDefaultScreen(display));
8909 if (window != (char *) NULL)
8910 {
8911 /*
8912 Search window hierarchy and identify any clients by name or ID.
8913 */
8914 if (isdigit((unsigned char) *window) != 0)
8915 remote_window=XWindowByID(display,root_window,(Window)
8916 strtol((char *) window,(char **) NULL,0));
8917 if (remote_window == (Window) NULL)
8918 remote_window=XWindowByName(display,root_window,window);
8919 }
8920 if (remote_window == (Window) NULL)
8921 remote_window=XWindowByProperty(display,root_window,remote_atom);
8922 if (remote_window == (Window) NULL)
8923 {
8924 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8925 filename);
8926 return(MagickFalse);
8927 }
8928 /*
8929 Send remote command.
8930 */
8931 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8932 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8933 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8934 (void) XSync(display,MagickFalse);
8935 return(MagickTrue);
8936}
8937
8938/*
8939%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8940% %
8941% %
8942% %
8943% X R e t a i n W i n d o w C o l o r s %
8944% %
8945% %
8946% %
8947%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8948%
8949% XRetainWindowColors() sets X11 color resources on a window. This preserves
8950% the colors associated with an image displayed on the window.
8951%
8952% The format of the XRetainWindowColors method is:
8953%
8954% void XRetainWindowColors(Display *display,const Window window)
8955%
8956% A description of each parameter follows:
8957%
8958% o display: Specifies a connection to an X server; returned from
8959% XOpenDisplay.
8960%
8961% o window: Specifies a pointer to a XWindowInfo structure.
8962%
8963*/
8964MagickExport void XRetainWindowColors(Display *display,const Window window)
8965{
8966 Atom
8967 property;
8968
8969 Pixmap
8970 pixmap;
8971
8972 /*
8973 Put property on the window.
8974 */
8975 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8976 assert(display != (Display *) NULL);
8977 assert(window != (Window) NULL);
8978 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8979 if (property == (Atom) NULL)
8980 {
8981 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8982 "_XSETROOT_ID");
8983 return;
8984 }
8985 pixmap=XCreatePixmap(display,window,1,1,1);
8986 if (pixmap == (Pixmap) NULL)
8987 {
8988 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8989 return;
8990 }
8991 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8992 (unsigned char *) &pixmap,1);
8993 (void) XSetCloseDownMode(display,RetainPermanent);
8994}
8995
8996/*
8997%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8998% %
8999% %
9000% %
9001% X S e l e c t W i n d o w %
9002% %
9003% %
9004% %
9005%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9006%
9007% XSelectWindow() allows a user to select a window using the mouse. If the
9008% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9009% is returned in the crop_info structure.
9010%
9011% The format of the XSelectWindow function is:
9012%
9013% target_window=XSelectWindow(display,crop_info)
9014%
9015% A description of each parameter follows:
9016%
9017% o window: XSelectWindow returns the window id.
9018%
9019% o display: Specifies a pointer to the Display structure; returned from
9020% XOpenDisplay.
9021%
9022% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9023% contains the extents of any cropping rectangle.
9024%
cristy3ed852e2009-09-05 21:47:34 +00009025*/
9026static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9027{
9028#define MinimumCropArea (unsigned int) 9
9029
9030 Cursor
9031 target_cursor;
9032
9033 GC
9034 annotate_context;
9035
9036 int
9037 presses,
9038 x_offset,
9039 y_offset;
9040
9041 Status
9042 status;
9043
9044 Window
9045 root_window,
9046 target_window;
9047
9048 XEvent
9049 event;
9050
9051 XGCValues
9052 context_values;
9053
9054 /*
9055 Initialize graphic context.
9056 */
9057 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9058 assert(display != (Display *) NULL);
9059 assert(crop_info != (RectangleInfo *) NULL);
9060 root_window=XRootWindow(display,XDefaultScreen(display));
9061 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9062 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9063 context_values.function=GXinvert;
9064 context_values.plane_mask=
9065 context_values.background ^ context_values.foreground;
9066 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009067 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009068 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9069 if (annotate_context == (GC) NULL)
9070 return(MagickFalse);
9071 /*
9072 Grab the pointer using target cursor.
9073 */
9074 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9075 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9076 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9077 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9078 GrabModeAsync,root_window,target_cursor,CurrentTime);
9079 if (status != GrabSuccess)
9080 {
9081 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9082 return((Window) NULL);
9083 }
9084 /*
9085 Select a window.
9086 */
9087 crop_info->width=0;
9088 crop_info->height=0;
9089 presses=0;
9090 target_window=(Window) NULL;
9091 x_offset=0;
9092 y_offset=0;
9093 do
9094 {
9095 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9096 (void) XDrawRectangle(display,root_window,annotate_context,
9097 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9098 (unsigned int) crop_info->height-1);
9099 /*
9100 Allow another event.
9101 */
9102 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9103 (void) XWindowEvent(display,root_window,ButtonPressMask |
9104 ButtonReleaseMask | ButtonMotionMask,&event);
9105 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9106 (void) XDrawRectangle(display,root_window,annotate_context,
9107 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9108 (unsigned int) crop_info->height-1);
9109 switch (event.type)
9110 {
9111 case ButtonPress:
9112 {
9113 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9114 event.xbutton.x,event.xbutton.y);
9115 if (target_window == (Window) NULL)
9116 target_window=root_window;
9117 x_offset=event.xbutton.x_root;
9118 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009119 crop_info->x=(ssize_t) x_offset;
9120 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009121 crop_info->width=0;
9122 crop_info->height=0;
9123 presses++;
9124 break;
9125 }
9126 case ButtonRelease:
9127 {
9128 presses--;
9129 break;
9130 }
9131 case MotionNotify:
9132 {
9133 /*
9134 Discard pending button motion events.
9135 */
9136 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009137 crop_info->x=(ssize_t) event.xmotion.x;
9138 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009139 /*
9140 Check boundary conditions.
9141 */
9142 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009143 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009144 else
9145 {
cristyecd0ab52010-05-30 14:59:20 +00009146 crop_info->width=(size_t) (crop_info->x-x_offset);
9147 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009148 }
9149 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009150 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009151 else
9152 {
cristyecd0ab52010-05-30 14:59:20 +00009153 crop_info->height=(size_t) (crop_info->y-y_offset);
9154 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009155 }
9156 }
9157 default:
9158 break;
9159 }
9160 } while ((target_window == (Window) NULL) || (presses > 0));
9161 (void) XUngrabPointer(display,CurrentTime);
9162 (void) XFreeCursor(display,target_cursor);
9163 (void) XFreeGC(display,annotate_context);
9164 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9165 {
9166 crop_info->width=0;
9167 crop_info->height=0;
9168 }
9169 if ((crop_info->width != 0) && (crop_info->height != 0))
9170 target_window=root_window;
9171 return(target_window);
9172}
9173
9174/*
9175%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9176% %
9177% %
9178% %
9179% X S e t C u r s o r S t a t e %
9180% %
9181% %
9182% %
9183%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9184%
9185% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9186% reset to their default.
9187%
9188% The format of the XXSetCursorState method is:
9189%
9190% XSetCursorState(display,windows,const MagickStatusType state)
9191%
9192% A description of each parameter follows:
9193%
9194% o display: Specifies a connection to an X server; returned from
9195% XOpenDisplay.
9196%
9197% o windows: Specifies a pointer to a XWindows structure.
9198%
9199% o state: An unsigned integer greater than 0 sets the cursor state
9200% to busy, otherwise the cursor are reset to their default.
9201%
9202*/
9203MagickExport void XSetCursorState(Display *display,XWindows *windows,
9204 const MagickStatusType state)
9205{
9206 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9207 assert(display != (Display *) NULL);
9208 assert(windows != (XWindows *) NULL);
9209 if (state)
9210 {
9211 (void) XCheckDefineCursor(display,windows->image.id,
9212 windows->image.busy_cursor);
9213 (void) XCheckDefineCursor(display,windows->pan.id,
9214 windows->pan.busy_cursor);
9215 (void) XCheckDefineCursor(display,windows->magnify.id,
9216 windows->magnify.busy_cursor);
9217 (void) XCheckDefineCursor(display,windows->command.id,
9218 windows->command.busy_cursor);
9219 }
9220 else
9221 {
9222 (void) XCheckDefineCursor(display,windows->image.id,
9223 windows->image.cursor);
9224 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9225 (void) XCheckDefineCursor(display,windows->magnify.id,
9226 windows->magnify.cursor);
9227 (void) XCheckDefineCursor(display,windows->command.id,
9228 windows->command.cursor);
9229 (void) XCheckDefineCursor(display,windows->command.id,
9230 windows->widget.cursor);
9231 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9232 }
9233 windows->info.mapped=MagickFalse;
9234}
9235
9236/*
9237%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9238% %
9239% %
9240% %
9241% X S e t W i n d o w s %
9242% %
9243% %
9244% %
9245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9246%
9247% XSetWindows() sets the X windows structure if the windows info is specified.
9248% Otherwise the current windows structure is returned.
9249%
9250% The format of the XSetWindows method is:
9251%
9252% XWindows *XSetWindows(XWindows *windows_info)
9253%
9254% A description of each parameter follows:
9255%
9256% o windows_info: Initialize the Windows structure with this information.
9257%
9258*/
9259MagickExport XWindows *XSetWindows(XWindows *windows_info)
9260{
9261 static XWindows
9262 *windows = (XWindows *) NULL;
9263
9264 if (windows_info != (XWindows *) ~0)
9265 {
9266 windows=(XWindows *) RelinquishMagickMemory(windows);
9267 windows=windows_info;
9268 }
9269 return(windows);
9270}
9271/*
9272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9273% %
9274% %
9275% %
9276% X U s e r P r e f e r e n c e s %
9277% %
9278% %
9279% %
9280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9281%
9282% XUserPreferences() saves the preferences in a configuration file in the
9283% users' home directory.
9284%
9285% The format of the XUserPreferences method is:
9286%
9287% void XUserPreferences(XResourceInfo *resource_info)
9288%
9289% A description of each parameter follows:
9290%
9291% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9292%
9293*/
9294MagickExport void XUserPreferences(XResourceInfo *resource_info)
9295{
9296#if defined(X11_PREFERENCES_PATH)
9297 char
9298 cache[MaxTextExtent],
9299 filename[MaxTextExtent],
9300 specifier[MaxTextExtent];
9301
9302 const char
cristy104cea82009-10-25 02:26:51 +00009303 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009304 *value;
9305
9306 XrmDatabase
9307 preferences_database;
9308
9309 /*
9310 Save user preferences to the client configuration file.
9311 */
9312 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009313 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009314 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009315 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009316 value=resource_info->backdrop ? "True" : "False";
9317 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009318 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009319 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9320 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009321 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009322 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009323 value=resource_info->confirm_exit ? "True" : "False";
9324 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009325 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009326 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009327 value=resource_info->confirm_edit ? "True" : "False";
9328 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009329 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009330 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009331 value=resource_info->display_warnings ? "True" : "False";
9332 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009333 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009334 value=resource_info->quantize_info->dither ? "True" : "False";
9335 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009336 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009337 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009338 value=resource_info->gamma_correct ? "True" : "False";
9339 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009340 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9341 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009342 resource_info->undo_cache);
9343 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009344 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009345 value=resource_info->use_pixmap ? "True" : "False";
9346 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009347 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009348 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009349 ExpandFilename(filename);
9350 XrmPutFileDatabase(preferences_database,filename);
9351#endif
9352}
9353
9354/*
9355%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9356% %
9357% %
9358% %
9359% X V i s u a l C l a s s N a m e %
9360% %
9361% %
9362% %
9363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9364%
9365% XVisualClassName() returns the visual class name as a character string.
9366%
9367% The format of the XVisualClassName method is:
9368%
9369% char *XVisualClassName(const int visual_class)
9370%
9371% A description of each parameter follows:
9372%
9373% o visual_type: XVisualClassName returns the visual class as a character
9374% string.
9375%
9376% o class: Specifies the visual class.
9377%
cristy3ed852e2009-09-05 21:47:34 +00009378*/
9379static const char *XVisualClassName(const int visual_class)
9380{
9381 switch (visual_class)
9382 {
9383 case StaticGray: return("StaticGray");
9384 case GrayScale: return("GrayScale");
9385 case StaticColor: return("StaticColor");
9386 case PseudoColor: return("PseudoColor");
9387 case TrueColor: return("TrueColor");
9388 case DirectColor: return("DirectColor");
9389 }
9390 return("unknown visual class");
9391}
9392
9393/*
9394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9395% %
9396% %
9397% %
9398% X W a r n i n g %
9399% %
9400% %
9401% %
9402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9403%
9404% XWarning() displays a warning reason in a Notice widget.
9405%
9406% The format of the XWarning method is:
9407%
9408% void XWarning(const unsigned int warning,const char *reason,
9409% const char *description)
9410%
9411% A description of each parameter follows:
9412%
9413% o warning: Specifies the numeric warning category.
9414%
9415% o reason: Specifies the reason to display before terminating the
9416% program.
9417%
9418% o description: Specifies any description to the reason.
9419%
9420*/
9421MagickExport void XWarning(const ExceptionType magick_unused(warning),
9422 const char *reason,const char *description)
9423{
9424 char
9425 text[MaxTextExtent];
9426
9427 XWindows
9428 *windows;
9429
9430 if (reason == (char *) NULL)
9431 return;
9432 (void) CopyMagickString(text,reason,MaxTextExtent);
9433 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9434 windows=XSetWindows((XWindows *) ~0);
9435 XNoticeWidget(windows->display,windows,text,(char *) description);
9436}
9437
9438/*
9439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9440% %
9441% %
9442% %
9443% X W i n d o w B y I D %
9444% %
9445% %
9446% %
9447%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9448%
9449% XWindowByID() locates a child window with a given ID. If not window with
9450% the given name is found, 0 is returned. Only the window specified and its
9451% subwindows are searched.
9452%
9453% The format of the XWindowByID function is:
9454%
9455% child=XWindowByID(display,window,id)
9456%
9457% A description of each parameter follows:
9458%
9459% o child: XWindowByID returns the window with the specified
9460% id. If no windows are found, XWindowByID returns 0.
9461%
9462% o display: Specifies a pointer to the Display structure; returned from
9463% XOpenDisplay.
9464%
9465% o id: Specifies the id of the window to locate.
9466%
9467*/
9468MagickExport Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009469 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009470{
9471 RectangleInfo
9472 rectangle_info;
9473
9474 register int
9475 i;
9476
9477 Status
9478 status;
9479
9480 unsigned int
9481 number_children;
9482
9483 Window
9484 child,
9485 *children,
9486 window;
9487
9488 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9489 assert(display != (Display *) NULL);
9490 assert(root_window != (Window) NULL);
9491 if (id == 0)
9492 return(XSelectWindow(display,&rectangle_info));
9493 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009494 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009495 status=XQueryTree(display,root_window,&child,&child,&children,
9496 &number_children);
9497 if (status == False)
9498 return((Window) NULL);
9499 window=(Window) NULL;
9500 for (i=0; i < (int) number_children; i++)
9501 {
9502 /*
9503 Search each child and their children.
9504 */
9505 window=XWindowByID(display,children[i],id);
9506 if (window != (Window) NULL)
9507 break;
9508 }
9509 if (children != (Window *) NULL)
9510 (void) XFree((void *) children);
9511 return(window);
9512}
9513
9514/*
9515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9516% %
9517% %
9518% %
9519% X W i n d o w B y N a m e %
9520% %
9521% %
9522% %
9523%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9524%
9525% XWindowByName() locates a window with a given name on a display. If no
9526% window with the given name is found, 0 is returned. If more than one window
9527% has the given name, the first one is returned. Only root and its children
9528% are searched.
9529%
9530% The format of the XWindowByName function is:
9531%
9532% window=XWindowByName(display,root_window,name)
9533%
9534% A description of each parameter follows:
9535%
9536% o window: XWindowByName returns the window id.
9537%
9538% o display: Specifies a pointer to the Display structure; returned from
9539% XOpenDisplay.
9540%
9541% o root_window: Specifies the id of the root window.
9542%
9543% o name: Specifies the name of the window to locate.
9544%
9545*/
9546MagickExport Window XWindowByName(Display *display,const Window root_window,
9547 const char *name)
9548{
9549 register int
9550 i;
9551
9552 Status
9553 status;
9554
9555 unsigned int
9556 number_children;
9557
9558 Window
9559 *children,
9560 child,
9561 window;
9562
9563 XTextProperty
9564 window_name;
9565
9566 assert(display != (Display *) NULL);
9567 assert(root_window != (Window) NULL);
9568 assert(name != (char *) NULL);
9569 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9570 if (XGetWMName(display,root_window,&window_name) != 0)
9571 if (LocaleCompare((char *) window_name.value,name) == 0)
9572 return(root_window);
9573 status=XQueryTree(display,root_window,&child,&child,&children,
9574 &number_children);
9575 if (status == False)
9576 return((Window) NULL);
9577 window=(Window) NULL;
9578 for (i=0; i < (int) number_children; i++)
9579 {
9580 /*
9581 Search each child and their children.
9582 */
9583 window=XWindowByName(display,children[i],name);
9584 if (window != (Window) NULL)
9585 break;
9586 }
9587 if (children != (Window *) NULL)
9588 (void) XFree((void *) children);
9589 return(window);
9590}
9591
9592/*
9593%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9594% %
9595% %
9596% %
9597% X W i n d o w B y P r o p e r y %
9598% %
9599% %
9600% %
9601%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9602%
9603% XWindowByProperty() locates a child window with a given property. If not
9604% window with the given name is found, 0 is returned. If more than one window
9605% has the given property, the first one is returned. Only the window
9606% specified and its subwindows are searched.
9607%
9608% The format of the XWindowByProperty function is:
9609%
9610% child=XWindowByProperty(display,window,property)
9611%
9612% A description of each parameter follows:
9613%
9614% o child: XWindowByProperty returns the window id with the specified
9615% property. If no windows are found, XWindowByProperty returns 0.
9616%
9617% o display: Specifies a pointer to the Display structure; returned from
9618% XOpenDisplay.
9619%
9620% o property: Specifies the property of the window to locate.
9621%
9622*/
9623MagickExport Window XWindowByProperty(Display *display,const Window window,
9624 const Atom property)
9625{
9626 Atom
9627 type;
9628
9629 int
9630 format;
9631
9632 Status
9633 status;
9634
9635 unsigned char
9636 *data;
9637
9638 unsigned int
9639 i,
9640 number_children;
9641
cristyf2faecf2010-05-28 19:19:36 +00009642 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009643 after,
9644 number_items;
9645
9646 Window
9647 child,
9648 *children,
9649 parent,
9650 root;
9651
9652 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9653 assert(display != (Display *) NULL);
9654 assert(window != (Window) NULL);
9655 assert(property != (Atom) NULL);
9656 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9657 if (status == False)
9658 return((Window) NULL);
9659 type=(Atom) NULL;
9660 child=(Window) NULL;
9661 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9662 {
9663 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9664 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9665 if (data != NULL)
9666 (void) XFree((void *) data);
9667 if ((status == Success) && (type != (Atom) NULL))
9668 child=children[i];
9669 }
9670 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9671 child=XWindowByProperty(display,children[i],property);
9672 if (children != (Window *) NULL)
9673 (void) XFree((void *) children);
9674 return(child);
9675}
9676#else
9677
9678/*
9679%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9680% %
9681% %
9682% %
9683% X I m p o r t I m a g e %
9684% %
9685% %
9686% %
9687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9688%
9689% XImportImage() reads an image from an X window.
9690%
9691% The format of the XImportImage method is:
9692%
9693% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9694%
9695% A description of each parameter follows:
9696%
9697% o image_info: the image info..
9698%
9699% o ximage_info: Specifies a pointer to an XImportInfo structure.
9700%
9701*/
9702MagickExport Image *XImportImage(const ImageInfo *image_info,
9703 XImportInfo *ximage_info)
9704{
9705 assert(image_info != (const ImageInfo *) NULL);
9706 assert(image_info->signature == MagickSignature);
9707 if (image_info->debug != MagickFalse)
9708 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9709 image_info->filename);
9710 assert(ximage_info != (XImportInfo *) NULL);
9711 return((Image *) NULL);
9712}
9713#endif
9714
9715/*
9716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9717% %
9718% %
9719% %
cristy576974e2009-10-25 20:45:31 +00009720+ X C o m p o n e n t G e n e s i s %
9721% %
9722% %
9723% %
9724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9725%
9726% XComponentGenesis() instantiates the X component.
9727%
9728% The format of the XComponentGenesis method is:
9729%
9730% MagickBooleanType XComponentGenesis(void)
9731%
9732*/
9733MagickExport MagickBooleanType XComponentGenesis(void)
9734{
9735 return(MagickTrue);
9736}
9737
9738/*
9739%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9740% %
9741% %
9742% %
cristy3ed852e2009-09-05 21:47:34 +00009743% X G e t I m p o r t I n f o %
9744% %
9745% %
9746% %
9747%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9748%
9749% XGetImportInfo() initializes the XImportInfo structure.
9750%
9751% The format of the XGetImportInfo method is:
9752%
9753% void XGetImportInfo(XImportInfo *ximage_info)
9754%
9755% A description of each parameter follows:
9756%
9757% o ximage_info: Specifies a pointer to an ImageInfo structure.
9758%
9759*/
9760MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9761{
9762 assert(ximage_info != (XImportInfo *) NULL);
9763 ximage_info->frame=MagickFalse;
9764 ximage_info->borders=MagickFalse;
9765 ximage_info->screen=MagickFalse;
9766 ximage_info->descend=MagickTrue;
9767 ximage_info->silent=MagickFalse;
9768}