blob: 4649415735d1e6630c9d051806991062db05b1d9 [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"
cristy0740a982011-10-13 15:01:01 +000065#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000066#include "MagickCore/option.h"
67#include "MagickCore/pixel-accessor.h"
68#include "MagickCore/PreRvIcccm.h"
69#include "MagickCore/quantize.h"
70#include "MagickCore/quantum.h"
71#include "MagickCore/quantum-private.h"
72#include "MagickCore/resource_.h"
73#include "MagickCore/resize.h"
74#include "MagickCore/shear.h"
75#include "MagickCore/statistic.h"
76#include "MagickCore/string_.h"
77#include "MagickCore/string-private.h"
78#include "MagickCore/transform.h"
79#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000080#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000081#include "MagickCore/widget.h"
cristybcbda3f2011-09-03 13:01:22 +000082#include "MagickCore/widget-private.h"
cristy4c08aed2011-07-01 19:47:50 +000083#include "MagickCore/xwindow.h"
84#include "MagickCore/xwindow-private.h"
85#include "MagickCore/version.h"
cristy3ed852e2009-09-05 21:47:34 +000086#if defined(__BEOS__)
87#include <OS.h>
88#endif
89#if defined(MAGICKCORE_X11_DELEGATE)
90#include <X11/Xproto.h>
91#include <X11/Xlocale.h>
92#if defined(MAGICK_HAVE_POLL)
93# include <sys/poll.h>
94#endif
95#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
96#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
97# include <machine/param.h>
98#endif
99#include <sys/ipc.h>
100#include <sys/shm.h>
101#include <X11/extensions/XShm.h>
102#endif
103#if defined(MAGICKCORE_HAVE_SHAPE)
104#include <X11/extensions/shape.h>
105#endif
106
107/*
108 X defines.
109*/
cristyce70c172010-01-07 17:15:30 +0000110#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000111 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
112 QuantumRange)))
cristy4c08aed2011-07-01 19:47:50 +0000113#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000114 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
115 map->red_mult)+ \
116 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
117 map->green_mult)+ \
118 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
119 map->blue_mult))
cristy4c08aed2011-07-01 19:47:50 +0000120#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
121 ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
122 map->red_mult)+ \
123 ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
124 map->green_mult)+ \
125 ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
126 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000127#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000128 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
129 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000130#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000131 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
132 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000133#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000134 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
135 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
136 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000137
138#define AccentuateModulate ScaleCharToQuantum(80)
139#define HighlightModulate ScaleCharToQuantum(125)
140#define ShadowModulate ScaleCharToQuantum(135)
141#define DepthModulate ScaleCharToQuantum(185)
142#define TroughModulate ScaleCharToQuantum(110)
143
144#define XLIB_ILLEGAL_ACCESS 1
145#undef ForgetGravity
146#undef NorthWestGravity
147#undef NorthGravity
148#undef NorthEastGravity
149#undef WestGravity
150#undef CenterGravity
151#undef EastGravity
152#undef SouthWestGravity
153#undef SouthGravity
154#undef SouthEastGravity
155#undef StaticGravity
156
157#undef index
158#if defined(hpux9)
159#define XFD_SET int
160#else
161#define XFD_SET fd_set
162#endif
163
164/*
165 Enumeration declarations.
166*/
167typedef enum
168{
169#undef DoRed
170 DoRed = 0x0001,
171#undef DoGreen
172 DoGreen = 0x0002,
173#undef DoBlue
174 DoBlue = 0x0004,
175 DoMatte = 0x0008
176} XColorFlags;
177
178/*
179 Typedef declarations.
180*/
181typedef struct _DiversityPacket
182{
183 Quantum
184 red,
185 green,
186 blue;
187
188 unsigned short
189 index;
190
cristybb503372010-05-27 20:51:26 +0000191 size_t
cristy3ed852e2009-09-05 21:47:34 +0000192 count;
193} DiversityPacket;
194
195/*
196 Constant declaractions.
197*/
198static MagickBooleanType
199 xerror_alert = MagickFalse;
200
201/*
202 Method prototypes.
203*/
204static const char
205 *XVisualClassName(const int);
206
207static MagickRealType
208 blue_gamma = 1.0,
209 green_gamma = 1.0,
210 red_gamma = 1.0;
211
212static MagickBooleanType
213 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
214
215static void
216 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000217 XImage *,XImage *,ExceptionInfo *),
cristy3ed852e2009-09-05 21:47:34 +0000218 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
cristye941a752011-10-15 01:52:48 +0000219 XImage *,XImage *,ExceptionInfo *);
cristy3ed852e2009-09-05 21:47:34 +0000220
221static Window
222 XSelectWindow(Display *,RectangleInfo *);
223
224/*
225%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226% %
227% %
228% %
229% D e s t r o y X R e s o u r c e s %
230% %
231% %
232% %
233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234%
235% DestroyXResources() destroys any X resources.
236%
237% The format of the DestroyXResources method is:
238%
239% void DestroyXResources()
240%
241% A description of each parameter follows:
242%
243*/
244MagickExport void DestroyXResources(void)
245{
246 register int
247 i;
248
249 unsigned int
250 number_windows;
251
252 XWindowInfo
253 *magick_windows[MaxXWindows];
254
255 XWindows
256 *windows;
257
258 DestroyXWidget();
259 windows=XSetWindows((XWindows *) ~0);
260 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
261 return;
262 number_windows=0;
263 magick_windows[number_windows++]=(&windows->context);
264 magick_windows[number_windows++]=(&windows->group_leader);
265 magick_windows[number_windows++]=(&windows->backdrop);
266 magick_windows[number_windows++]=(&windows->icon);
267 magick_windows[number_windows++]=(&windows->image);
268 magick_windows[number_windows++]=(&windows->info);
269 magick_windows[number_windows++]=(&windows->magnify);
270 magick_windows[number_windows++]=(&windows->pan);
271 magick_windows[number_windows++]=(&windows->command);
272 magick_windows[number_windows++]=(&windows->widget);
273 magick_windows[number_windows++]=(&windows->popup);
274 magick_windows[number_windows++]=(&windows->context);
275 for (i=0; i < (int) number_windows; i++)
276 {
277 if (magick_windows[i]->mapped != MagickFalse)
278 {
279 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
280 magick_windows[i]->screen);
281 magick_windows[i]->mapped=MagickFalse;
282 }
283 if (magick_windows[i]->name != (char *) NULL)
284 magick_windows[i]->name=(char *)
285 RelinquishMagickMemory(magick_windows[i]->name);
286 if (magick_windows[i]->icon_name != (char *) NULL)
287 magick_windows[i]->icon_name=(char *)
288 RelinquishMagickMemory(magick_windows[i]->icon_name);
289 if (magick_windows[i]->cursor != (Cursor) NULL)
290 {
291 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
292 magick_windows[i]->cursor=(Cursor) NULL;
293 }
294 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
295 {
296 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
297 magick_windows[i]->busy_cursor=(Cursor) NULL;
298 }
299 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
300 {
301 (void) XFreePixmap(windows->display,
302 magick_windows[i]->highlight_stipple);
303 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
304 }
305 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
306 {
307 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
308 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
309 }
310 if (magick_windows[i]->ximage != (XImage *) NULL)
311 {
312 XDestroyImage(magick_windows[i]->ximage);
313 magick_windows[i]->ximage=(XImage *) NULL;
314 }
315 if (magick_windows[i]->pixmap != (Pixmap) NULL)
316 {
317 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
318 magick_windows[i]->pixmap=(Pixmap) NULL;
319 }
320 if (magick_windows[i]->id != (Window) NULL)
321 {
322 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
323 magick_windows[i]->id=(Window) NULL;
324 }
325 if (magick_windows[i]->destroy != MagickFalse)
326 {
327 if (magick_windows[i]->image != (Image *) NULL)
328 {
329 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
330 magick_windows[i]->image=NewImageList();
331 }
332 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
333 {
334 (void) XFreePixmap(windows->display,
335 magick_windows[i]->matte_pixmap);
336 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
337 }
338 }
339 if (magick_windows[i]->segment_info != (void *) NULL)
340 {
341#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
342 XShmSegmentInfo
343 *segment_info;
344
345 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
346 if (segment_info != (XShmSegmentInfo *) NULL)
347 if (segment_info[0].shmid >= 0)
348 {
349 if (segment_info[0].shmaddr != NULL)
350 (void) shmdt(segment_info[0].shmaddr);
351 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
352 segment_info[0].shmaddr=NULL;
353 segment_info[0].shmid=(-1);
354 }
355#endif
356 magick_windows[i]->segment_info=(void *)
357 RelinquishMagickMemory(magick_windows[i]->segment_info);
358 }
359 }
360 windows->icon_resources=(XResourceInfo *)
361 RelinquishMagickMemory(windows->icon_resources);
362 if (windows->icon_pixel != (XPixelInfo *) NULL)
363 {
cristyf2faecf2010-05-28 19:19:36 +0000364 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
365 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000366 RelinquishMagickMemory(windows->icon_pixel->pixels);
367 if (windows->icon_pixel->annotate_context != (GC) NULL)
368 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
369 windows->icon_pixel=(XPixelInfo *)
370 RelinquishMagickMemory(windows->icon_pixel);
371 }
372 if (windows->pixel_info != (XPixelInfo *) NULL)
373 {
cristyf2faecf2010-05-28 19:19:36 +0000374 if (windows->pixel_info->pixels != (unsigned long *) NULL)
375 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000376 RelinquishMagickMemory(windows->pixel_info->pixels);
377 if (windows->pixel_info->annotate_context != (GC) NULL)
378 XFreeGC(windows->display,windows->pixel_info->annotate_context);
379 if (windows->pixel_info->widget_context != (GC) NULL)
380 XFreeGC(windows->display,windows->pixel_info->widget_context);
381 if (windows->pixel_info->highlight_context != (GC) NULL)
382 XFreeGC(windows->display,windows->pixel_info->highlight_context);
383 windows->pixel_info=(XPixelInfo *)
384 RelinquishMagickMemory(windows->pixel_info);
385 }
386 if (windows->font_info != (XFontStruct *) NULL)
387 {
388 XFreeFont(windows->display,windows->font_info);
389 windows->font_info=(XFontStruct *) NULL;
390 }
391 if (windows->class_hints != (XClassHint *) NULL)
392 {
cristyc9cc4a72011-09-18 02:12:41 +0000393 if (windows->class_hints->res_name != (char *) NULL)
394 windows->class_hints->res_name=DestroyString(
395 windows->class_hints->res_name);
396 if (windows->class_hints->res_class != (char *) NULL)
397 windows->class_hints->res_class=DestroyString(
398 windows->class_hints->res_class);
cristy3ed852e2009-09-05 21:47:34 +0000399 XFree(windows->class_hints);
400 windows->class_hints=(XClassHint *) NULL;
401 }
402 if (windows->manager_hints != (XWMHints *) NULL)
403 {
404 XFree(windows->manager_hints);
405 windows->manager_hints=(XWMHints *) NULL;
406 }
407 if (windows->map_info != (XStandardColormap *) NULL)
408 {
409 XFree(windows->map_info);
410 windows->map_info=(XStandardColormap *) NULL;
411 }
412 if (windows->icon_map != (XStandardColormap *) NULL)
413 {
414 XFree(windows->icon_map);
415 windows->icon_map=(XStandardColormap *) NULL;
416 }
417 if (windows->visual_info != (XVisualInfo *) NULL)
418 {
419 XFree(windows->visual_info);
420 windows->visual_info=(XVisualInfo *) NULL;
421 }
422 if (windows->icon_visual != (XVisualInfo *) NULL)
423 {
424 XFree(windows->icon_visual);
425 windows->icon_visual=(XVisualInfo *) NULL;
426 }
427 (void) XSetWindows((XWindows *) NULL);
428}
429
430/*
431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432% %
433% %
434% %
435% X A n n o t a t e I m a g e %
436% %
437% %
438% %
439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440%
441% XAnnotateImage() annotates the image with text.
442%
443% The format of the XAnnotateImage method is:
444%
445% MagickBooleanType XAnnotateImage(Display *display,
446% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
447%
448% A description of each parameter follows:
449%
450% o display: Specifies a connection to an X server; returned from
451% XOpenDisplay.
452%
453% o pixel: Specifies a pointer to a XPixelInfo structure.
454%
455% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
456%
457% o image: the image.
458%
459*/
cristybcbda3f2011-09-03 13:01:22 +0000460MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000461 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
462{
cristyc57f6942010-11-12 01:47:39 +0000463 CacheView
464 *annotate_view;
465
cristy3ed852e2009-09-05 21:47:34 +0000466 GC
467 annotate_context;
468
469 ExceptionInfo
470 *exception;
471
472 Image
473 *annotate_image;
474
475 int
476 x,
477 y;
478
479 MagickBooleanType
480 matte;
481
482 Pixmap
483 annotate_pixmap;
484
cristy2ed42f62011-10-02 19:49:57 +0000485 Quantum
486 virtual_pixel[MaxPixelChannels];
487
cristy3ed852e2009-09-05 21:47:34 +0000488 unsigned int
489 depth,
490 height,
491 width;
492
493 Window
494 root_window;
495
496 XGCValues
497 context_values;
498
499 XImage
500 *annotate_ximage;
501
502 /*
503 Initialize annotated image.
504 */
505 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
506 assert(display != (Display *) NULL);
507 assert(pixel != (XPixelInfo *) NULL);
508 assert(annotate_info != (XAnnotateInfo *) NULL);
509 assert(image != (Image *) NULL);
510 /*
511 Initialize annotated pixmap.
512 */
513 root_window=XRootWindow(display,XDefaultScreen(display));
514 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
515 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
516 annotate_info->height,depth);
517 if (annotate_pixmap == (Pixmap) NULL)
518 return(MagickFalse);
519 /*
520 Initialize graphics info.
521 */
522 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000523 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000524 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000525 annotate_context=XCreateGC(display,root_window,(unsigned long)
526 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000527 if (annotate_context == (GC) NULL)
528 return(MagickFalse);
529 /*
530 Draw text to pixmap.
531 */
532 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
533 (int) annotate_info->font_info->ascent,annotate_info->text,
534 (int) strlen(annotate_info->text));
535 (void) XFreeGC(display,annotate_context);
536 /*
537 Initialize annotated X image.
538 */
539 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
540 annotate_info->height,AllPlanes,ZPixmap);
541 if (annotate_ximage == (XImage *) NULL)
542 return(MagickFalse);
543 (void) XFreePixmap(display,annotate_pixmap);
544 /*
545 Initialize annotated image.
546 */
cristy9950d572011-10-01 18:22:35 +0000547 annotate_image=AcquireImage((ImageInfo *) NULL,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +0000548 if (annotate_image == (Image *) NULL)
549 return(MagickFalse);
550 annotate_image->columns=annotate_info->width;
551 annotate_image->rows=annotate_info->height;
552 /*
553 Transfer annotated X image to image.
554 */
555 width=(unsigned int) image->columns;
556 height=(unsigned int) image->rows;
557 x=0;
558 y=0;
559 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristy2ed42f62011-10-02 19:49:57 +0000560 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,virtual_pixel,
561 &image->exception);
562 annotate_image->background_color.red=virtual_pixel[RedPixelChannel];
563 annotate_image->background_color.green=virtual_pixel[GreenPixelChannel];
564 annotate_image->background_color.blue=virtual_pixel[BluePixelChannel];
565 annotate_image->background_color.alpha=virtual_pixel[AlphaPixelChannel];
cristy3ed852e2009-09-05 21:47:34 +0000566 if (annotate_info->stencil == ForegroundStencil)
567 annotate_image->matte=MagickTrue;
568 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +0000569 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000570 for (y=0; y < (int) annotate_image->rows; y++)
571 {
cristyc57f6942010-11-12 01:47:39 +0000572 register int
cristy3ed852e2009-09-05 21:47:34 +0000573 x;
574
cristy4c08aed2011-07-01 19:47:50 +0000575 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000576 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000577
cristyc57f6942010-11-12 01:47:39 +0000578 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
579 annotate_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000580 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000581 break;
cristyc57f6942010-11-12 01:47:39 +0000582 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000583 {
cristy4c08aed2011-07-01 19:47:50 +0000584 SetPixelAlpha(annotate_image,OpaqueAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000585 if (XGetPixel(annotate_ximage,x,y) == 0)
586 {
587 /*
588 Set this pixel to the background color.
589 */
cristy4c08aed2011-07-01 19:47:50 +0000590 SetPixelRed(annotate_image,ScaleShortToQuantum(
591 pixel->box_color.red),q);
592 SetPixelGreen(annotate_image,ScaleShortToQuantum(
593 pixel->box_color.green),q);
594 SetPixelBlue(annotate_image,ScaleShortToQuantum(
595 pixel->box_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000596 if ((annotate_info->stencil == ForegroundStencil) ||
597 (annotate_info->stencil == OpaqueStencil))
cristy4c08aed2011-07-01 19:47:50 +0000598 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000599 }
600 else
601 {
602 /*
603 Set this pixel to the pen color.
604 */
cristy4c08aed2011-07-01 19:47:50 +0000605 SetPixelRed(annotate_image,ScaleShortToQuantum(
606 pixel->pen_color.red),q);
607 SetPixelGreen(annotate_image,ScaleShortToQuantum(
608 pixel->pen_color.green),q);
609 SetPixelBlue(annotate_image,ScaleShortToQuantum(
610 pixel->pen_color.blue),q);
cristy3ed852e2009-09-05 21:47:34 +0000611 if (annotate_info->stencil == BackgroundStencil)
cristy4c08aed2011-07-01 19:47:50 +0000612 SetPixelAlpha(annotate_image,TransparentAlpha,q);
cristy3ed852e2009-09-05 21:47:34 +0000613 }
cristyed231572011-07-14 02:18:59 +0000614 q+=GetPixelChannels(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000615 }
cristyc57f6942010-11-12 01:47:39 +0000616 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000617 break;
618 }
cristyc57f6942010-11-12 01:47:39 +0000619 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000620 XDestroyImage(annotate_ximage);
621 /*
622 Determine annotate geometry.
623 */
624 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
625 if ((width != (unsigned int) annotate_image->columns) ||
626 (height != (unsigned int) annotate_image->rows))
627 {
628 char
629 image_geometry[MaxTextExtent];
630
631 /*
632 Scale image.
633 */
cristyb51dff52011-05-19 16:55:47 +0000634 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +0000635 width,height);
cristye941a752011-10-15 01:52:48 +0000636 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
637 exception);
cristy3ed852e2009-09-05 21:47:34 +0000638 }
639 if (annotate_info->degrees != 0.0)
640 {
641 Image
642 *rotate_image;
643
644 int
645 rotations;
646
647 MagickRealType
648 normalized_degrees;
649
650 /*
651 Rotate image.
652 */
653 rotate_image=
654 RotateImage(annotate_image,annotate_info->degrees,&image->exception);
655 if (rotate_image == (Image *) NULL)
656 return(MagickFalse);
657 annotate_image=DestroyImage(annotate_image);
658 annotate_image=rotate_image;
659 /*
660 Annotation is relative to the degree of rotation.
661 */
662 normalized_degrees=annotate_info->degrees;
663 while (normalized_degrees < -45.0)
664 normalized_degrees+=360.0;
665 for (rotations=0; normalized_degrees > 45.0; rotations++)
666 normalized_degrees-=90.0;
667 switch (rotations % 4)
668 {
669 default:
670 case 0:
671 break;
672 case 1:
673 {
674 /*
675 Rotate 90 degrees.
676 */
677 x-=(int) annotate_image->columns/2;
678 y+=(int) annotate_image->columns/2;
679 break;
680 }
681 case 2:
682 {
683 /*
684 Rotate 180 degrees.
685 */
686 x=x-(int) annotate_image->columns;
687 break;
688 }
689 case 3:
690 {
691 /*
692 Rotate 270 degrees.
693 */
694 x=x-(int) annotate_image->columns/2;
695 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
696 break;
697 }
698 }
699 }
700 /*
701 Composite text onto the image.
702 */
703 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
704 matte=image->matte;
705 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristye941a752011-10-15 01:52:48 +0000706 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y,
707 exception);
cristy3ed852e2009-09-05 21:47:34 +0000708 image->matte=matte;
709 annotate_image=DestroyImage(annotate_image);
710 return(MagickTrue);
711}
712
713/*
714%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715% %
716% %
717% %
718% X B e s t F o n t %
719% %
720% %
721% %
722%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723%
724% XBestFont() returns the "best" font. "Best" is defined as a font specified
725% in the X resource database or a font such that the text width displayed
726% with the font does not exceed the specified maximum width.
727%
728% The format of the XBestFont method is:
729%
730% XFontStruct *XBestFont(Display *display,
731% const XResourceInfo *resource_info,const MagickBooleanType text_font)
732%
733% A description of each parameter follows:
734%
735% o font: XBestFont returns a pointer to a XFontStruct structure.
736%
737% o display: Specifies a connection to an X server; returned from
738% XOpenDisplay.
739%
740% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
741%
742% o text_font: True is font should be mono-spaced (typewriter style).
743%
cristy3ed852e2009-09-05 21:47:34 +0000744*/
745
746static char **FontToList(char *font)
747{
748 char
749 **fontlist;
750
751 register char
752 *p,
753 *q;
754
755 register int
756 i;
757
758 unsigned int
759 fonts;
760
761 if (font == (char *) NULL)
762 return((char **) NULL);
763 /*
764 Convert string to an ASCII list.
765 */
766 fonts=1U;
767 for (p=font; *p != '\0'; p++)
768 if ((*p == ':') || (*p == ';') || (*p == ','))
769 fonts++;
770 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
771 if (fontlist == (char **) NULL)
772 {
773 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
774 font);
775 return((char **) NULL);
776 }
777 p=font;
778 for (i=0; i < (int) fonts; i++)
779 {
780 for (q=p; *q != '\0'; q++)
781 if ((*q == ':') || (*q == ';') || (*q == ','))
782 break;
783 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
784 sizeof(*fontlist[i]));
785 if (fontlist[i] == (char *) NULL)
786 {
787 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
788 font);
789 return((char **) NULL);
790 }
791 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
792 p=q+1;
793 }
794 fontlist[i]=(char *) NULL;
795 return(fontlist);
796}
797
cristybcbda3f2011-09-03 13:01:22 +0000798MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000799 const XResourceInfo *resource_info,const MagickBooleanType text_font)
800{
801 static const char
802 *Fonts[]=
803 {
804 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
805 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
806 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
807 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
808 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
809 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
810 "variable",
811 "fixed",
812 (char *) NULL
813 },
814 *TextFonts[]=
815 {
816 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
817 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
818 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
819 "fixed",
820 (char *) NULL
821 };
822
823 char
824 *font_name;
825
826 register const char
827 **p;
828
829 XFontStruct
830 *font_info;
831
832 font_info=(XFontStruct *) NULL;
833 font_name=resource_info->font;
834 if (text_font != MagickFalse)
835 font_name=resource_info->text_font;
836 if ((font_name != (char *) NULL) && (*font_name != '\0'))
837 {
838 char
839 **fontlist;
840
841 register int
842 i;
843
844 /*
845 Load preferred font specified in the X resource database.
846 */
847 fontlist=FontToList(font_name);
848 if (fontlist != (char **) NULL)
849 {
850 for (i=0; fontlist[i] != (char *) NULL; i++)
851 {
852 if (font_info == (XFontStruct *) NULL)
853 font_info=XLoadQueryFont(display,fontlist[i]);
854 fontlist[i]=DestroyString(fontlist[i]);
855 }
856 fontlist=(char **) RelinquishMagickMemory(fontlist);
857 }
858 if (font_info == (XFontStruct *) NULL)
859 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
860 }
861 /*
862 Load fonts from list of fonts until one is found.
863 */
864 p=Fonts;
865 if (text_font != MagickFalse)
866 p=TextFonts;
867 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
868 p++;
869 while (*p != (char *) NULL)
870 {
871 if (font_info != (XFontStruct *) NULL)
872 break;
873 font_info=XLoadQueryFont(display,(char *) *p);
874 p++;
875 }
876 return(font_info);
877}
878
879/*
880%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881% %
882% %
883% %
884% X B e s t I c o n S i z e %
885% %
886% %
887% %
888%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
889%
890% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
891% size that maintains the aspect ratio of the image. If the window manager
892% has preferred icon sizes, one of the preferred sizes is used.
893%
894% The format of the XBestIconSize method is:
895%
896% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
897%
898% A description of each parameter follows:
899%
900% o display: Specifies a connection to an X server; returned from
901% XOpenDisplay.
902%
903% o image: the image.
904%
905*/
cristybcbda3f2011-09-03 13:01:22 +0000906MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000907 Image *image)
908{
909 int
910 i,
911 number_sizes;
912
913 MagickRealType
914 scale_factor;
915
916 unsigned int
917 height,
918 icon_height,
919 icon_width,
920 width;
921
922 Window
923 root_window;
924
925 XIconSize
926 *icon_size,
927 *size_list;
928
929 /*
930 Determine if the window manager has specified preferred icon sizes.
931 */
932 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
933 assert(display != (Display *) NULL);
934 assert(window != (XWindowInfo *) NULL);
935 assert(image != (Image *) NULL);
936 window->width=MaxIconSize;
937 window->height=MaxIconSize;
938 icon_size=(XIconSize *) NULL;
939 number_sizes=0;
940 root_window=XRootWindow(display,window->screen);
941 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
942 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
943 icon_size=size_list;
944 if (icon_size == (XIconSize *) NULL)
945 {
946 /*
947 Window manager does not restrict icon size.
948 */
949 icon_size=XAllocIconSize();
950 if (icon_size == (XIconSize *) NULL)
951 {
952 ThrowXWindowFatalException(ResourceLimitError,
953 "MemoryAllocationFailed",image->filename);
954 return;
955 }
956 icon_size->min_width=1;
957 icon_size->max_width=MaxIconSize;
958 icon_size->min_height=1;
959 icon_size->max_height=MaxIconSize;
960 icon_size->width_inc=1;
961 icon_size->height_inc=1;
962 }
963 /*
964 Determine aspect ratio of image.
965 */
966 width=(unsigned int) image->columns;
967 height=(unsigned int) image->rows;
968 i=0;
969 if (window->crop_geometry)
970 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
971 /*
972 Look for an icon size that maintains the aspect ratio of image.
973 */
974 scale_factor=(MagickRealType) icon_size->max_width/width;
975 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
976 scale_factor=(MagickRealType) icon_size->max_height/height;
977 icon_width=(unsigned int) icon_size->min_width;
978 while ((int) icon_width < icon_size->max_width)
979 {
980 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
981 break;
982 icon_width+=icon_size->width_inc;
983 }
984 icon_height=(unsigned int) icon_size->min_height;
985 while ((int) icon_height < icon_size->max_height)
986 {
987 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
988 break;
989 icon_height+=icon_size->height_inc;
990 }
991 (void) XFree((void *) icon_size);
992 window->width=icon_width;
993 window->height=icon_height;
994}
995
996/*
997%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
998% %
999% %
1000% %
1001% X B e s t P i x e l %
1002% %
1003% %
1004% %
1005%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1006%
1007% XBestPixel() returns a pixel from an array of pixels that is closest to the
1008% requested color. If the color array is NULL, the colors are obtained from
1009% the X server.
1010%
1011% The format of the XBestPixel method is:
1012%
1013% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1014% unsigned int number_colors,XColor *color)
1015%
1016% A description of each parameter follows:
1017%
1018% o pixel: XBestPixel returns the pixel value closest to the requested
1019% color.
1020%
1021% o display: Specifies a connection to an X server; returned from
1022% XOpenDisplay.
1023%
1024% o colormap: Specifies the ID of the X server colormap.
1025%
1026% o colors: Specifies an array of XColor structures.
1027%
1028% o number_colors: Specifies the number of XColor structures in the
1029% color definition array.
1030%
1031% o color: Specifies the desired RGB value to find in the colors array.
1032%
1033*/
cristybcbda3f2011-09-03 13:01:22 +00001034MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001035 XColor *colors,unsigned int number_colors,XColor *color)
1036{
1037 MagickBooleanType
1038 query_server;
1039
cristy4c08aed2011-07-01 19:47:50 +00001040 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001041 pixel;
1042
1043 MagickRealType
1044 min_distance;
1045
1046 register MagickRealType
1047 distance;
1048
1049 register int
1050 i,
1051 j;
1052
1053 Status
1054 status;
1055
1056 /*
1057 Find closest representation for the requested RGB color.
1058 */
1059 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1060 assert(display != (Display *) NULL);
1061 assert(color != (XColor *) NULL);
1062 status=XAllocColor(display,colormap,color);
1063 if (status != False)
1064 return;
1065 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1066 if (query_server != MagickFalse)
1067 {
1068 /*
1069 Read X server colormap.
1070 */
1071 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1072 if (colors == (XColor *) NULL)
1073 {
1074 ThrowXWindowFatalException(ResourceLimitError,
1075 "MemoryAllocationFailed","...");
1076 return;
1077 }
1078 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001079 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001080 if (number_colors > 256)
1081 number_colors=256;
1082 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1083 }
1084 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1085 QuantumRange+1.0);
1086 j=0;
1087 for (i=0; i < (int) number_colors; i++)
1088 {
1089 pixel.red=colors[i].red-(MagickRealType) color->red;
1090 distance=pixel.red*pixel.red;
1091 if (distance > min_distance)
1092 continue;
1093 pixel.green=colors[i].green-(MagickRealType) color->green;
1094 distance+=pixel.green*pixel.green;
1095 if (distance > min_distance)
1096 continue;
1097 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1098 distance+=pixel.blue*pixel.blue;
1099 if (distance > min_distance)
1100 continue;
1101 min_distance=distance;
1102 color->pixel=colors[i].pixel;
1103 j=i;
1104 }
1105 (void) XAllocColor(display,colormap,&colors[j]);
1106 if (query_server != MagickFalse)
1107 colors=(XColor *) RelinquishMagickMemory(colors);
1108}
1109
1110/*
1111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1112% %
1113% %
1114% %
1115% X B e s t V i s u a l I n f o %
1116% %
1117% %
1118% %
1119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1120%
1121% XBestVisualInfo() returns visual information for a visual that is the "best"
1122% the server supports. "Best" is defined as:
1123%
1124% 1. Restrict the visual list to those supported by the default screen.
1125%
1126% 2. If a visual type is specified, restrict the visual list to those of
1127% that type.
1128%
1129% 3. If a map type is specified, choose the visual that matches the id
1130% specified by the Standard Colormap.
1131%
1132% 4 From the list of visuals, choose one that can display the most
1133% simultaneous colors. If more than one visual can display the same
1134% number of simultaneous colors, one is chosen based on a rank.
1135%
1136% The format of the XBestVisualInfo method is:
1137%
1138% XVisualInfo *XBestVisualInfo(Display *display,
1139% XStandardColormap *map_info,XResourceInfo *resource_info)
1140%
1141% A description of each parameter follows:
1142%
1143% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1144% structure.
1145%
1146% o display: Specifies a connection to an X server; returned from
1147% XOpenDisplay.
1148%
1149% o map_info: If map_type is specified, this structure is initialized
1150% with info from the Standard Colormap.
1151%
1152% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1153%
1154*/
1155
1156static inline int MagickMax(const int x,const int y)
1157{
1158 if (x > y)
1159 return(x);
1160 return(y);
1161}
1162
cristybb503372010-05-27 20:51:26 +00001163static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001164 const unsigned int y)
1165{
1166 if (x < y)
1167 return(x);
1168 return(y);
1169}
1170
cristybcbda3f2011-09-03 13:01:22 +00001171MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001172 XStandardColormap *map_info,XResourceInfo *resource_info)
1173{
1174#define MaxStandardColormaps 7
1175#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1176 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1177 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1178 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1179
1180 char
1181 *map_type,
1182 *visual_type;
1183
cristyc57f6942010-11-12 01:47:39 +00001184 int
1185 visual_mask;
1186
cristy3ed852e2009-09-05 21:47:34 +00001187 register int
1188 i;
1189
cristy8891f9c2010-06-04 23:32:17 +00001190 size_t
1191 one;
1192
cristy3ed852e2009-09-05 21:47:34 +00001193 static int
1194 number_visuals;
1195
1196 static XVisualInfo
1197 visual_template;
1198
1199 XVisualInfo
1200 *visual_info,
1201 *visual_list;
1202
1203 /*
1204 Restrict visual search by screen number.
1205 */
1206 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1207 assert(display != (Display *) NULL);
1208 assert(map_info != (XStandardColormap *) NULL);
1209 assert(resource_info != (XResourceInfo *) NULL);
1210 map_type=resource_info->map_type;
1211 visual_type=resource_info->visual_type;
1212 visual_mask=VisualScreenMask;
1213 visual_template.screen=XDefaultScreen(display);
1214 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001215 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001216 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001217 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001218 visual_mask|=VisualDepthMask;
1219 if (visual_type != (char *) NULL)
1220 {
1221 /*
1222 Restrict visual search by class or visual id.
1223 */
1224 if (LocaleCompare("staticgray",visual_type) == 0)
1225 {
1226 visual_mask|=VisualClassMask;
1227 visual_template.klass=StaticGray;
1228 }
1229 else
1230 if (LocaleCompare("grayscale",visual_type) == 0)
1231 {
1232 visual_mask|=VisualClassMask;
1233 visual_template.klass=GrayScale;
1234 }
1235 else
1236 if (LocaleCompare("staticcolor",visual_type) == 0)
1237 {
1238 visual_mask|=VisualClassMask;
1239 visual_template.klass=StaticColor;
1240 }
1241 else
1242 if (LocaleCompare("pseudocolor",visual_type) == 0)
1243 {
1244 visual_mask|=VisualClassMask;
1245 visual_template.klass=PseudoColor;
1246 }
1247 else
1248 if (LocaleCompare("truecolor",visual_type) == 0)
1249 {
1250 visual_mask|=VisualClassMask;
1251 visual_template.klass=TrueColor;
1252 }
1253 else
1254 if (LocaleCompare("directcolor",visual_type) == 0)
1255 {
1256 visual_mask|=VisualClassMask;
1257 visual_template.klass=DirectColor;
1258 }
1259 else
1260 if (LocaleCompare("default",visual_type) == 0)
1261 {
1262 visual_mask|=VisualIDMask;
1263 visual_template.visualid=XVisualIDFromVisual(
1264 XDefaultVisual(display,XDefaultScreen(display)));
1265 }
1266 else
1267 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1268 {
1269 visual_mask|=VisualIDMask;
1270 visual_template.visualid=
1271 strtol(visual_type,(char **) NULL,0);
1272 }
1273 else
1274 ThrowXWindowFatalException(XServerError,
1275 "UnrecognizedVisualSpecifier",visual_type);
1276 }
1277 /*
1278 Get all visuals that meet our criteria so far.
1279 */
1280 number_visuals=0;
1281 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1282 &number_visuals);
1283 visual_mask=VisualScreenMask | VisualIDMask;
1284 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1285 {
1286 /*
1287 Failed to get visual; try using the default visual.
1288 */
1289 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1290 visual_type);
1291 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1292 XDefaultScreen(display)));
1293 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1294 &number_visuals);
1295 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1296 return((XVisualInfo *) NULL);
1297 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1298 XVisualClassName(visual_list->klass));
1299 }
1300 resource_info->color_recovery=MagickFalse;
1301 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1302 {
1303 Atom
1304 map_property;
1305
1306 char
1307 map_name[MaxTextExtent];
1308
1309 int
1310 j,
1311 number_maps;
1312
1313 Status
1314 status;
1315
1316 Window
1317 root_window;
1318
1319 XStandardColormap
1320 *map_list;
1321
1322 /*
1323 Choose a visual associated with a standard colormap.
1324 */
1325 root_window=XRootWindow(display,XDefaultScreen(display));
1326 status=False;
1327 if (LocaleCompare(map_type,"list") != 0)
1328 {
1329 /*
1330 User specified Standard Colormap.
1331 */
cristyb51dff52011-05-19 16:55:47 +00001332 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001333 "RGB_%s_MAP",map_type);
1334 LocaleUpper(map_name);
1335 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1336 if (map_property != (Atom) NULL)
1337 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1338 map_property);
1339 }
1340 else
1341 {
1342 static const char
1343 *colormap[MaxStandardColormaps]=
1344 {
1345 "_HP_RGB_SMOOTH_MAP_LIST",
1346 "RGB_BEST_MAP",
1347 "RGB_DEFAULT_MAP",
1348 "RGB_GRAY_MAP",
1349 "RGB_RED_MAP",
1350 "RGB_GREEN_MAP",
1351 "RGB_BLUE_MAP",
1352 };
1353
1354 /*
1355 Choose a standard colormap from a list.
1356 */
1357 for (i=0; i < MaxStandardColormaps; i++)
1358 {
1359 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1360 if (map_property == (Atom) NULL)
1361 continue;
1362 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1363 map_property);
1364 if (status != False)
1365 break;
1366 }
1367 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1368 }
1369 if (status == False)
1370 {
1371 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1372 map_type);
1373 return((XVisualInfo *) NULL);
1374 }
1375 /*
1376 Search all Standard Colormaps and visuals for ids that match.
1377 */
1378 *map_info=map_list[0];
1379#if !defined(PRE_R4_ICCCM)
1380 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1381 for (i=0; i < number_maps; i++)
1382 for (j=0; j < number_visuals; j++)
1383 if (map_list[i].visualid ==
1384 XVisualIDFromVisual(visual_list[j].visual))
1385 {
1386 *map_info=map_list[i];
1387 visual_template.visualid=XVisualIDFromVisual(
1388 visual_list[j].visual);
1389 break;
1390 }
1391 if (map_info->visualid != visual_template.visualid)
1392 {
1393 ThrowXWindowFatalException(XServerError,
1394 "UnableToMatchVisualToStandardColormap",map_type);
1395 return((XVisualInfo *) NULL);
1396 }
1397#endif
1398 if (map_info->colormap == (Colormap) NULL)
1399 {
1400 ThrowXWindowFatalException(XServerError,
1401 "StandardColormapIsNotInitialized",map_type);
1402 return((XVisualInfo *) NULL);
1403 }
1404 (void) XFree((void *) map_list);
1405 }
1406 else
1407 {
1408 static const unsigned int
1409 rank[]=
1410 {
1411 StaticGray,
1412 GrayScale,
1413 StaticColor,
1414 DirectColor,
1415 TrueColor,
1416 PseudoColor
1417 };
1418
1419 XVisualInfo
1420 *p;
1421
1422 /*
1423 Pick one visual that displays the most simultaneous colors.
1424 */
1425 visual_info=visual_list;
1426 p=visual_list;
1427 for (i=1; i < number_visuals; i++)
1428 {
1429 p++;
1430 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1431 visual_info=p;
1432 else
1433 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1434 if (rank[p->klass] > rank[visual_info->klass])
1435 visual_info=p;
1436 }
1437 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1438 }
1439 (void) XFree((void *) visual_list);
1440 /*
1441 Retrieve only one visual by its screen & id number.
1442 */
1443 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1444 &number_visuals);
1445 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1446 return((XVisualInfo *) NULL);
1447 return(visual_info);
1448}
1449
1450/*
1451%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1452% %
1453% %
1454% %
1455% X C h e c k D e f i n e C u r s o r %
1456% %
1457% %
1458% %
1459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1460%
1461% XCheckDefineCursor() prevents cursor changes on the root window.
1462%
1463% The format of the XXCheckDefineCursor method is:
1464%
1465% XCheckDefineCursor(display,window,cursor)
1466%
1467% A description of each parameter follows:
1468%
1469% o display: Specifies a connection to an X server; returned from
1470% XOpenDisplay.
1471%
1472% o window: the window.
1473%
1474% o cursor: the cursor.
1475%
1476*/
cristybcbda3f2011-09-03 13:01:22 +00001477MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001478 Cursor cursor)
1479{
1480 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1481 assert(display != (Display *) NULL);
1482 if (window == XRootWindow(display,XDefaultScreen(display)))
1483 return(0);
1484 return(XDefineCursor(display,window,cursor));
1485}
1486
1487/*
1488%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1489% %
1490% %
1491% %
1492% X C h e c k R e f r e s h W i n d o w s %
1493% %
1494% %
1495% %
1496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1497%
1498% XCheckRefreshWindows() checks the X server for exposure events for a
1499% particular window and updates the areassociated with the exposure event.
1500%
1501% The format of the XCheckRefreshWindows method is:
1502%
1503% void XCheckRefreshWindows(Display *display,XWindows *windows)
1504%
1505% A description of each parameter follows:
1506%
1507% o display: Specifies a connection to an X server; returned from
1508% XOpenDisplay.
1509%
1510% o windows: Specifies a pointer to a XWindows structure.
1511%
1512*/
cristybcbda3f2011-09-03 13:01:22 +00001513MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001514{
1515 Window
1516 id;
1517
1518 XEvent
1519 event;
1520
1521 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1522 assert(display != (Display *) NULL);
1523 assert(windows != (XWindows *) NULL);
1524 XDelay(display,SuspendTime);
1525 id=windows->command.id;
1526 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1527 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1528 id=windows->image.id;
1529 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1530 XRefreshWindow(display,&windows->image,&event);
1531 XDelay(display,SuspendTime << 1);
1532 id=windows->command.id;
1533 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1534 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1535 id=windows->image.id;
1536 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1537 XRefreshWindow(display,&windows->image,&event);
1538}
1539
1540/*
1541%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1542% %
1543% %
1544% %
1545% X C l i e n t M e s s a g e %
1546% %
1547% %
1548% %
1549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1550%
1551% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1552% initialized with a particular protocol type and atom.
1553%
1554% The format of the XClientMessage function is:
1555%
1556% XClientMessage(display,window,protocol,reason,timestamp)
1557%
1558% A description of each parameter follows:
1559%
1560% o display: Specifies a pointer to the Display structure; returned from
1561% XOpenDisplay.
1562%
1563% o window: Specifies a pointer to a Window structure.
1564%
1565% o protocol: Specifies an atom value.
1566%
1567% o reason: Specifies an atom value which is the reason to send.
1568%
1569% o timestamp: Specifies a value of type Time.
1570%
1571*/
cristybcbda3f2011-09-03 13:01:22 +00001572MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001573 const Atom protocol,const Atom reason,const Time timestamp)
1574{
1575 XClientMessageEvent
1576 client_event;
1577
1578 assert(display != (Display *) NULL);
1579 client_event.type=ClientMessage;
1580 client_event.window=window;
1581 client_event.message_type=protocol;
1582 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001583 client_event.data.l[0]=(long) reason;
1584 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001585 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1586}
1587
1588/*
1589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1590% %
1591% %
1592% %
1593+ X C l i e n t W i n d o w %
1594% %
1595% %
1596% %
1597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1598%
1599% XClientWindow() finds a window, at or below the specified window, which has
1600% a WM_STATE property. If such a window is found, it is returned, otherwise
1601% the argument window is returned.
1602%
1603% The format of the XClientWindow function is:
1604%
1605% client_window=XClientWindow(display,target_window)
1606%
1607% A description of each parameter follows:
1608%
1609% o client_window: XClientWindow returns a window, at or below the specified
1610% window, which has a WM_STATE property otherwise the argument
1611% target_window is returned.
1612%
1613% o display: Specifies a pointer to the Display structure; returned from
1614% XOpenDisplay.
1615%
1616% o target_window: Specifies the window to find a WM_STATE property.
1617%
cristy3ed852e2009-09-05 21:47:34 +00001618*/
1619static Window XClientWindow(Display *display,Window target_window)
1620{
1621 Atom
1622 state,
1623 type;
1624
1625 int
1626 format;
1627
1628 Status
1629 status;
1630
1631 unsigned char
1632 *data;
1633
cristyf2faecf2010-05-28 19:19:36 +00001634 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001635 after,
1636 number_items;
1637
1638 Window
1639 client_window;
1640
1641 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1642 assert(display != (Display *) NULL);
1643 state=XInternAtom(display,"WM_STATE",MagickTrue);
1644 if (state == (Atom) NULL)
1645 return(target_window);
1646 type=(Atom) NULL;
1647 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1648 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1649 if ((status == Success) && (type != (Atom) NULL))
1650 return(target_window);
1651 client_window=XWindowByProperty(display,target_window,state);
1652 if (client_window == (Window) NULL)
1653 return(target_window);
1654 return(client_window);
1655}
1656
1657/*
1658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1659% %
1660% %
1661% %
cristyf34a1452009-10-24 22:29:27 +00001662+ X C o m p o n e n t T e r m i n u s %
1663% %
1664% %
1665% %
1666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1667%
1668% XComponentTerminus() destroys the module component.
1669%
1670% The format of the XComponentTerminus method is:
1671%
1672% XComponentTerminus(void)
1673%
1674*/
cristy5ff4eaf2011-09-03 01:38:02 +00001675MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001676{
1677 DestroyXResources();
1678}
1679
1680/*
1681%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1682% %
1683% %
1684% %
cristy3ed852e2009-09-05 21:47:34 +00001685% X C o n f i g u r e I m a g e C o l o r m a p %
1686% %
1687% %
1688% %
1689%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1690%
1691% XConfigureImageColormap() creates a new X colormap.
1692%
1693% The format of the XConfigureImageColormap method is:
1694%
1695% void XConfigureImageColormap(Display *display,
1696% XResourceInfo *resource_info,XWindows *windows,Image *image)
1697%
1698% A description of each parameter follows:
1699%
1700% o display: Specifies a connection to an X server; returned from
1701% XOpenDisplay.
1702%
1703% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1704%
1705% o windows: Specifies a pointer to a XWindows structure.
1706%
1707% o image: the image.
1708%
1709*/
cristybcbda3f2011-09-03 13:01:22 +00001710MagickPrivate void XConfigureImageColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001711 XResourceInfo *resource_info,XWindows *windows,Image *image)
1712{
1713 Colormap
1714 colormap;
1715
1716 /*
1717 Make standard colormap.
1718 */
1719 XSetCursorState(display,windows,MagickTrue);
1720 XCheckRefreshWindows(display,windows);
1721 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1722 windows->map_info,windows->pixel_info);
1723 colormap=windows->map_info->colormap;
1724 (void) XSetWindowColormap(display,windows->image.id,colormap);
1725 (void) XSetWindowColormap(display,windows->command.id,colormap);
1726 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1727 if (windows->magnify.mapped != MagickFalse)
1728 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1729 if (windows->pan.mapped != MagickFalse)
1730 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1731 XSetCursorState(display,windows,MagickFalse);
1732 XClientMessage(display,windows->image.id,windows->im_protocols,
1733 windows->im_update_colormap,CurrentTime);
1734}
1735
1736/*
1737%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1738% %
1739% %
1740% %
1741% X C o n s t r a i n W i n d o w P o s i t i o n %
1742% %
1743% %
1744% %
1745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1746%
1747% XConstrainWindowPosition() assures a window is positioned within the X
1748% server boundaries.
1749%
1750% The format of the XConstrainWindowPosition method is:
1751%
1752% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1753%
1754% A description of each parameter follows:
1755%
1756% o display: Specifies a pointer to the Display structure; returned from
1757% XOpenDisplay.
1758%
1759% o window_info: Specifies a pointer to a XWindowInfo structure.
1760%
1761*/
cristybcbda3f2011-09-03 13:01:22 +00001762MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001763 XWindowInfo *window_info)
1764{
1765 int
1766 limit;
1767
1768 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1769 assert(display != (Display *) NULL);
1770 assert(window_info != (XWindowInfo *) NULL);
1771 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1772 if (window_info->x < 0)
1773 window_info->x=0;
1774 else
1775 if (window_info->x > (int) limit)
1776 window_info->x=(int) limit;
1777 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1778 if (window_info->y < 0)
1779 window_info->y=0;
1780 else
1781 if (window_info->y > limit)
1782 window_info->y=limit;
1783}
1784
1785/*
1786%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1787% %
1788% %
1789% %
1790% X D e l a y %
1791% %
1792% %
1793% %
1794%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1795%
1796% XDelay() suspends program execution for the number of milliseconds
1797% specified.
1798%
1799% The format of the Delay method is:
1800%
cristybb503372010-05-27 20:51:26 +00001801% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001802%
1803% A description of each parameter follows:
1804%
1805% o display: Specifies a pointer to the Display structure; returned from
1806% XOpenDisplay.
1807%
1808% o milliseconds: Specifies the number of milliseconds to delay before
1809% returning.
1810%
1811*/
cristybcbda3f2011-09-03 13:01:22 +00001812MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001813{
1814 assert(display != (Display *) NULL);
1815 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001816 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001817}
1818
1819/*
1820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1821% %
1822% %
1823% %
1824% X D e s t r o y R e s o u r c e I n f o %
1825% %
1826% %
1827% %
1828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1829%
1830% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1831% structure.
1832%
1833% The format of the XDestroyResourceInfo method is:
1834%
1835% void XDestroyResourceInfo(XResourceInfo *resource_info)
1836%
1837% A description of each parameter follows:
1838%
1839% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1840%
1841*/
1842MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1843{
1844 if (resource_info->image_geometry != (char *) NULL)
1845 resource_info->image_geometry=(char *)
1846 RelinquishMagickMemory(resource_info->image_geometry);
1847 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1848 resource_info->quantize_info=DestroyQuantizeInfo(
1849 resource_info->quantize_info);
1850 if (resource_info->client_name != (char *) NULL)
1851 resource_info->client_name=(char *)
1852 RelinquishMagickMemory(resource_info->client_name);
1853 if (resource_info->name != (char *) NULL)
1854 resource_info->name=DestroyString(resource_info->name);
1855 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1856}
1857
1858/*
1859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1860% %
1861% %
1862% %
1863% X D e s t r o y W i n d o w C o l o r s %
1864% %
1865% %
1866% %
1867%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1868%
1869% XDestroyWindowColors() frees X11 color resources previously saved on a
1870% window by XRetainWindowColors or programs like xsetroot.
1871%
1872% The format of the XDestroyWindowColors method is:
1873%
1874% void XDestroyWindowColors(Display *display,Window window)
1875%
1876% A description of each parameter follows:
1877%
1878% o display: Specifies a connection to an X server; returned from
1879% XOpenDisplay.
1880%
1881% o window: Specifies a pointer to a Window structure.
1882%
1883*/
cristybcbda3f2011-09-03 13:01:22 +00001884MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001885{
1886 Atom
1887 property,
1888 type;
1889
1890 int
1891 format;
1892
1893 Status
1894 status;
1895
1896 unsigned char
1897 *data;
1898
cristyf2faecf2010-05-28 19:19:36 +00001899 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001900 after,
1901 length;
1902
1903 /*
1904 If there are previous resources on the root window, destroy them.
1905 */
1906 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1907 assert(display != (Display *) NULL);
1908 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1909 if (property == (Atom) NULL)
1910 {
1911 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1912 "_XSETROOT_ID");
1913 return;
1914 }
1915 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1916 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1917 if (status != Success)
1918 return;
1919 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1920 {
1921 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1922 (void) XDeleteProperty(display,window,property);
1923 }
1924 if (type != None)
1925 (void) XFree((void *) data);
1926}
1927
1928/*
1929%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1930% %
1931% %
1932% %
1933% X D i s p l a y I m a g e I n f o %
1934% %
1935% %
1936% %
1937%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1938%
1939% XDisplayImageInfo() displays information about an X image.
1940%
1941% The format of the XDisplayImageInfo method is:
1942%
1943% void XDisplayImageInfo(Display *display,
1944% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1945% Image *image)
1946%
1947% A description of each parameter follows:
1948%
1949% o display: Specifies a connection to an X server; returned from
1950% XOpenDisplay.
1951%
1952% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1953%
1954% o windows: Specifies a pointer to a XWindows structure.
1955%
1956% o undo_image: the undo image.
1957%
1958% o image: the image.
1959%
1960*/
cristybcbda3f2011-09-03 13:01:22 +00001961MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001962 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1963 Image *image)
1964{
1965 char
1966 filename[MaxTextExtent],
1967 *text,
1968 **textlist;
1969
1970 FILE
1971 *file;
1972
1973 int
1974 unique_file;
1975
cristybb503372010-05-27 20:51:26 +00001976 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001977 i;
1978
cristybb503372010-05-27 20:51:26 +00001979 size_t
cristy3ed852e2009-09-05 21:47:34 +00001980 number_pixels;
1981
cristy9d314ff2011-03-09 01:30:28 +00001982 ssize_t
1983 bytes;
1984
1985 unsigned int
1986 levels;
1987
cristy3ed852e2009-09-05 21:47:34 +00001988 /*
1989 Write info about the X server to a file.
1990 */
1991 assert(display != (Display *) NULL);
1992 assert(resource_info != (XResourceInfo *) NULL);
1993 assert(windows != (XWindows *) NULL);
1994 assert(image != (Image *) NULL);
1995 if (image->debug)
1996 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1997 file=(FILE *) NULL;
1998 unique_file=AcquireUniqueFileResource(filename);
1999 if (unique_file != -1)
2000 file=fdopen(unique_file,"w");
2001 if ((unique_file == -1) || (file == (FILE *) NULL))
2002 {
2003 XNoticeWidget(display,windows,"Unable to display image info",filename);
2004 return;
2005 }
2006 if (resource_info->gamma_correct != MagickFalse)
2007 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002008 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002009 resource_info->display_gamma);
2010 /*
2011 Write info about the X image to a file.
2012 */
cristyb51dff52011-05-19 16:55:47 +00002013 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002014 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002015 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002016 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002017 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002018 windows->visual_info->colormap_size);
2019 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002020 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002021 else
cristyb51dff52011-05-19 16:55:47 +00002022 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002023 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2024 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002025 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002026 (void) FormatLocaleFile(file," crop geometry: %s\n",
2027 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002028 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002029 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002030 else
cristyb51dff52011-05-19 16:55:47 +00002031 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002032 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002033 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002034 else
cristyb51dff52011-05-19 16:55:47 +00002035 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002036 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002037 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002038 else
cristyb51dff52011-05-19 16:55:47 +00002039 (void) FormatLocaleFile(file," shared memory: False\n");
2040 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002041 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002042 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002043 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002044 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002045 /*
2046 Write info about the undo cache to a file.
2047 */
2048 bytes=0;
2049 for (levels=0; undo_image != (Image *) NULL; levels++)
2050 {
2051 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002052 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002053 undo_image=GetPreviousImageInList(undo_image);
2054 }
cristyb51dff52011-05-19 16:55:47 +00002055 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002056 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2057 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002058 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002059 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002060 /*
2061 Write info about the image to a file.
2062 */
cristya4037272011-08-28 15:11:39 +00002063 (void) IdentifyImage(image,file,MagickTrue,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002064 (void) fclose(file);
2065 text=FileToString(filename,~0,&image->exception);
2066 (void) RelinquishUniqueFileResource(filename);
2067 if (text == (char *) NULL)
2068 {
2069 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2070 "UnableToDisplayImageInfo");
2071 return;
2072 }
2073 textlist=StringToList(text);
2074 if (textlist != (char **) NULL)
2075 {
2076 char
2077 title[MaxTextExtent];
2078
2079 /*
2080 Display information about the image in the Text View widget.
2081 */
2082 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002083 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002084 image->filename);
2085 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2086 (char const **) textlist);
2087 for (i=0; textlist[i] != (char *) NULL; i++)
2088 textlist[i]=DestroyString(textlist[i]);
2089 textlist=(char **) RelinquishMagickMemory(textlist);
2090 }
2091 text=DestroyString(text);
2092}
2093
2094/*
2095%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2096% %
2097% %
2098% %
2099+ X D i t h e r I m a g e %
2100% %
2101% %
2102% %
2103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2104%
2105% XDitherImage() dithers the reference image as required by the HP Color
2106% Recovery algorithm. The color values are quantized to 3 bits of red and
2107% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2108% standard colormap.
2109%
2110% The format of the XDitherImage method is:
2111%
2112% void XDitherImage(Image *image,XImage *ximage)
2113%
2114% A description of each parameter follows:
2115%
2116% o image: the image.
2117%
2118% o ximage: Specifies a pointer to a XImage structure; returned from
2119% XCreateImage.
2120%
cristy3ed852e2009-09-05 21:47:34 +00002121*/
2122static void XDitherImage(Image *image,XImage *ximage)
2123{
2124 static const short int
2125 dither_red[2][16]=
2126 {
2127 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2128 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2129 },
2130 dither_green[2][16]=
2131 {
2132 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2133 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2134 },
2135 dither_blue[2][16]=
2136 {
2137 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2138 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2139 };
2140
cristyc57f6942010-11-12 01:47:39 +00002141 CacheView
2142 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002143
2144 int
cristyc57f6942010-11-12 01:47:39 +00002145 value,
cristy3ed852e2009-09-05 21:47:34 +00002146 y;
2147
cristy101ab702011-10-13 13:06:32 +00002148 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002149 color;
cristy3ed852e2009-09-05 21:47:34 +00002150
2151 register char
2152 *q;
2153
cristy4c08aed2011-07-01 19:47:50 +00002154 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002155 *p;
2156
2157 register int
2158 i,
2159 j,
2160 x;
2161
2162 unsigned int
2163 scanline_pad;
2164
cristybb503372010-05-27 20:51:26 +00002165 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002166 pixel;
2167
2168 unsigned char
2169 *blue_map[2][16],
2170 *green_map[2][16],
2171 *red_map[2][16];
2172
2173 /*
2174 Allocate and initialize dither maps.
2175 */
2176 for (i=0; i < 2; i++)
2177 for (j=0; j < 16; j++)
2178 {
2179 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2180 sizeof(*red_map));
2181 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2182 sizeof(*green_map));
2183 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2184 sizeof(*blue_map));
2185 if ((red_map[i][j] == (unsigned char *) NULL) ||
2186 (green_map[i][j] == (unsigned char *) NULL) ||
2187 (blue_map[i][j] == (unsigned char *) NULL))
2188 {
2189 ThrowXWindowFatalException(ResourceLimitError,
2190 "MemoryAllocationFailed",image->filename);
2191 return;
2192 }
2193 }
2194 /*
2195 Initialize dither tables.
2196 */
2197 for (i=0; i < 2; i++)
2198 for (j=0; j < 16; j++)
2199 for (x=0; x < 256; x++)
2200 {
2201 value=x-16;
2202 if (x < 48)
2203 value=x/2+8;
2204 value+=dither_red[i][j];
2205 red_map[i][j][x]=(unsigned char)
2206 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2207 value=x-16;
2208 if (x < 48)
2209 value=x/2+8;
2210 value+=dither_green[i][j];
2211 green_map[i][j][x]=(unsigned char)
2212 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2213 value=x-32;
2214 if (x < 112)
2215 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002216 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002217 blue_map[i][j][x]=(unsigned char)
2218 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2219 }
2220 /*
2221 Dither image.
2222 */
2223 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002224 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002225 i=0;
2226 j=0;
2227 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002228 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002229 for (y=0; y < (int) image->rows; y++)
2230 {
cristyc57f6942010-11-12 01:47:39 +00002231 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2232 &image->exception);
cristy4c08aed2011-07-01 19:47:50 +00002233 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002234 break;
2235 for (x=0; x < (int) image->columns; x++)
2236 {
cristyce70c172010-01-07 17:15:30 +00002237 color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002238 ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002239 color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002240 ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002241 color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002242 ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002243 pixel=(size_t) (((size_t) color.red & 0xe0) |
2244 (((size_t) color.green & 0xe0) >> 3) |
2245 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002246 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002247 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002248 j++;
2249 if (j == 16)
2250 j=0;
2251 }
2252 q+=scanline_pad;
2253 i++;
2254 if (i == 2)
2255 i=0;
2256 }
cristyc57f6942010-11-12 01:47:39 +00002257 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002258 /*
2259 Free allocated memory.
2260 */
2261 for (i=0; i < 2; i++)
2262 for (j=0; j < 16; j++)
2263 {
2264 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2265 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2266 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2267 }
2268}
2269
2270/*
2271%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2272% %
2273% %
2274% %
2275% X D r a w I m a g e %
2276% %
2277% %
2278% %
2279%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2280%
2281% XDrawImage() draws a line on the image.
2282%
2283% The format of the XDrawImage method is:
2284%
2285% MagickBooleanType XDrawImage(display,pixel,draw_info,image)
2286%
2287% A description of each parameter follows:
2288%
2289% o display: Specifies a connection to an X server; returned from
2290% XOpenDisplay.
2291%
2292% o pixel: Specifies a pointer to a XPixelInfo structure.
2293%
2294% o draw_info: Specifies a pointer to a XDrawInfo structure.
2295%
2296% o image: the image.
2297%
2298*/
cristybcbda3f2011-09-03 13:01:22 +00002299MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002300 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
2301{
cristyc57f6942010-11-12 01:47:39 +00002302 CacheView
2303 *draw_view;
2304
cristy3ed852e2009-09-05 21:47:34 +00002305 ExceptionInfo
2306 *exception;
2307
2308 GC
2309 draw_context;
2310
2311 Image
2312 *draw_image;
2313
2314 int
2315 x,
2316 y;
2317
2318 MagickBooleanType
2319 matte;
2320
cristy2ed42f62011-10-02 19:49:57 +00002321 Quantum
2322 virtual_pixel[MaxPixelChannels];
2323
cristy3ed852e2009-09-05 21:47:34 +00002324 Pixmap
2325 draw_pixmap;
2326
2327 unsigned int
2328 depth,
2329 height,
2330 width;
2331
2332 Window
2333 root_window;
2334
2335 XGCValues
2336 context_values;
2337
2338 XImage
2339 *draw_ximage;
2340
2341 /*
2342 Initialize drawd image.
2343 */
2344 assert(display != (Display *) NULL);
2345 assert(pixel != (XPixelInfo *) NULL);
2346 assert(draw_info != (XDrawInfo *) NULL);
2347 assert(image != (Image *) NULL);
2348 if (image->debug != MagickFalse)
2349 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2350 /*
2351 Initialize drawd pixmap.
2352 */
2353 root_window=XRootWindow(display,XDefaultScreen(display));
2354 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2355 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2356 draw_info->height,depth);
2357 if (draw_pixmap == (Pixmap) NULL)
2358 return(MagickFalse);
2359 /*
2360 Initialize graphics info.
2361 */
cristybb503372010-05-27 20:51:26 +00002362 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002363 context_values.foreground=0;
2364 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002365 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002366 (GCBackground | GCForeground | GCLineWidth),&context_values);
2367 if (draw_context == (GC) NULL)
2368 return(MagickFalse);
2369 /*
2370 Clear pixmap.
2371 */
2372 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2373 draw_info->height);
2374 /*
2375 Draw line to pixmap.
2376 */
2377 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002378 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002379 if (draw_info->stipple != (Pixmap) NULL)
2380 {
2381 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2382 (void) XSetStipple(display,draw_context,draw_info->stipple);
2383 }
cristy3ed852e2009-09-05 21:47:34 +00002384 switch (draw_info->element)
2385 {
2386 case PointElement:
2387 default:
2388 {
2389 (void) XDrawLines(display,draw_pixmap,draw_context,
2390 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2391 CoordModeOrigin);
2392 break;
2393 }
2394 case LineElement:
2395 {
2396 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2397 draw_info->line_info.y1,draw_info->line_info.x2,
2398 draw_info->line_info.y2);
2399 break;
2400 }
2401 case RectangleElement:
2402 {
2403 (void) XDrawRectangle(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);
2407 break;
2408 }
2409 case FillRectangleElement:
2410 {
2411 (void) XFillRectangle(display,draw_pixmap,draw_context,
2412 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2413 (unsigned int) draw_info->rectangle_info.width,
2414 (unsigned int) draw_info->rectangle_info.height);
2415 break;
2416 }
2417 case CircleElement:
2418 case EllipseElement:
2419 {
2420 (void) XDrawArc(display,draw_pixmap,draw_context,
2421 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2422 (unsigned int) draw_info->rectangle_info.width,
2423 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2424 break;
2425 }
2426 case FillCircleElement:
2427 case FillEllipseElement:
2428 {
2429 (void) XFillArc(display,draw_pixmap,draw_context,
2430 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2431 (unsigned int) draw_info->rectangle_info.width,
2432 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2433 break;
2434 }
2435 case PolygonElement:
2436 {
2437 XPoint
2438 *coordinate_info;
2439
2440 coordinate_info=draw_info->coordinate_info;
2441 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2442 (int) draw_info->number_coordinates,CoordModeOrigin);
2443 (void) XDrawLine(display,draw_pixmap,draw_context,
2444 coordinate_info[draw_info->number_coordinates-1].x,
2445 coordinate_info[draw_info->number_coordinates-1].y,
2446 coordinate_info[0].x,coordinate_info[0].y);
2447 break;
2448 }
2449 case FillPolygonElement:
2450 {
2451 (void) XFillPolygon(display,draw_pixmap,draw_context,
2452 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2453 CoordModeOrigin);
2454 break;
2455 }
2456 }
2457 (void) XFreeGC(display,draw_context);
2458 /*
2459 Initialize X image.
2460 */
2461 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2462 draw_info->height,AllPlanes,ZPixmap);
2463 if (draw_ximage == (XImage *) NULL)
2464 return(MagickFalse);
2465 (void) XFreePixmap(display,draw_pixmap);
2466 /*
2467 Initialize draw image.
2468 */
cristy9950d572011-10-01 18:22:35 +00002469 draw_image=AcquireImage((ImageInfo *) NULL,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002470 if (draw_image == (Image *) NULL)
2471 return(MagickFalse);
2472 draw_image->columns=draw_info->width;
2473 draw_image->rows=draw_info->height;
2474 /*
2475 Transfer drawn X image to image.
2476 */
2477 width=(unsigned int) image->columns;
2478 height=(unsigned int) image->rows;
2479 x=0;
2480 y=0;
2481 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristy2ed42f62011-10-02 19:49:57 +00002482 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,virtual_pixel,
2483 &image->exception);
2484 draw_image->background_color.red=virtual_pixel[RedPixelChannel];
2485 draw_image->background_color.green=virtual_pixel[GreenPixelChannel];
2486 draw_image->background_color.blue=virtual_pixel[BluePixelChannel];
2487 draw_image->background_color.alpha=virtual_pixel[AlphaPixelChannel];
cristy574cc262011-08-05 01:23:58 +00002488 if (SetImageStorageClass(draw_image,DirectClass,&image->exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002489 return(MagickFalse);
2490 draw_image->matte=MagickTrue;
2491 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +00002492 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002493 for (y=0; y < (int) draw_image->rows; y++)
2494 {
cristyc57f6942010-11-12 01:47:39 +00002495 register int
cristy3ed852e2009-09-05 21:47:34 +00002496 x;
2497
cristy4c08aed2011-07-01 19:47:50 +00002498 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002499 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002500
cristyc57f6942010-11-12 01:47:39 +00002501 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2502 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002503 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002504 break;
cristyc57f6942010-11-12 01:47:39 +00002505 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002506 {
2507 if (XGetPixel(draw_ximage,x,y) == 0)
2508 {
2509 /*
2510 Set this pixel to the background color.
2511 */
cristy101ab702011-10-13 13:06:32 +00002512 SetPixelPixelInfo(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002513 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002514 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002515 }
2516 else
2517 {
2518 /*
2519 Set this pixel to the pen color.
2520 */
cristy4c08aed2011-07-01 19:47:50 +00002521 SetPixelRed(draw_image,ScaleShortToQuantum(
2522 pixel->pen_color.red),q);
2523 SetPixelGreen(draw_image,ScaleShortToQuantum(
2524 pixel->pen_color.green),q);
2525 SetPixelBlue(draw_image,ScaleShortToQuantum(
2526 pixel->pen_color.blue),q);
2527 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2528 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002529 }
cristyed231572011-07-14 02:18:59 +00002530 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002531 }
cristyc57f6942010-11-12 01:47:39 +00002532 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002533 break;
2534 }
cristyc57f6942010-11-12 01:47:39 +00002535 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002536 XDestroyImage(draw_ximage);
2537 /*
2538 Determine draw geometry.
2539 */
2540 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2541 if ((width != (unsigned int) draw_image->columns) ||
2542 (height != (unsigned int) draw_image->rows))
2543 {
2544 char
2545 image_geometry[MaxTextExtent];
2546
2547 /*
2548 Scale image.
2549 */
cristyb51dff52011-05-19 16:55:47 +00002550 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002551 width,height);
cristye941a752011-10-15 01:52:48 +00002552 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2553 exception);
cristy3ed852e2009-09-05 21:47:34 +00002554 }
2555 if (draw_info->degrees != 0.0)
2556 {
2557 Image
2558 *rotate_image;
2559
2560 int
2561 rotations;
2562
2563 MagickRealType
2564 normalized_degrees;
2565
2566 /*
2567 Rotate image.
2568 */
2569 rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
2570 if (rotate_image == (Image *) NULL)
2571 return(MagickFalse);
2572 draw_image=DestroyImage(draw_image);
2573 draw_image=rotate_image;
2574 /*
2575 Annotation is relative to the degree of rotation.
2576 */
2577 normalized_degrees=draw_info->degrees;
2578 while (normalized_degrees < -45.0)
2579 normalized_degrees+=360.0;
2580 for (rotations=0; normalized_degrees > 45.0; rotations++)
2581 normalized_degrees-=90.0;
2582 switch (rotations % 4)
2583 {
2584 default:
2585 case 0:
2586 break;
2587 case 1:
2588 {
2589 /*
2590 Rotate 90 degrees.
2591 */
2592 x=x-(int) draw_image->columns/2;
2593 y=y+(int) draw_image->columns/2;
2594 break;
2595 }
2596 case 2:
2597 {
2598 /*
2599 Rotate 180 degrees.
2600 */
2601 x=x-(int) draw_image->columns;
2602 break;
2603 }
2604 case 3:
2605 {
2606 /*
2607 Rotate 270 degrees.
2608 */
2609 x=x-(int) draw_image->columns/2;
2610 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2611 break;
2612 }
2613 }
2614 }
2615 /*
2616 Composite text onto the image.
2617 */
cristyc57f6942010-11-12 01:47:39 +00002618 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002619 for (y=0; y < (int) draw_image->rows; y++)
2620 {
cristyc57f6942010-11-12 01:47:39 +00002621 register int
cristy3ed852e2009-09-05 21:47:34 +00002622 x;
2623
cristy4c08aed2011-07-01 19:47:50 +00002624 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002625 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002626
cristyc57f6942010-11-12 01:47:39 +00002627 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2628 exception);
cristyacd2ed22011-08-30 01:44:23 +00002629 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002630 break;
cristyc57f6942010-11-12 01:47:39 +00002631 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002632 {
cristy4c08aed2011-07-01 19:47:50 +00002633 if (GetPixelAlpha(image,q) != TransparentAlpha)
2634 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002635 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002636 }
cristyc57f6942010-11-12 01:47:39 +00002637 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002638 break;
2639 }
cristyc57f6942010-11-12 01:47:39 +00002640 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002641 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2642 if (draw_info->stencil == TransparentStencil)
cristyc57f6942010-11-12 01:47:39 +00002643 (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,(ssize_t) x,
cristye941a752011-10-15 01:52:48 +00002644 (ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002645 else
2646 {
2647 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002648 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
cristye941a752011-10-15 01:52:48 +00002649 (ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002650 image->matte=matte;
2651 }
2652 draw_image=DestroyImage(draw_image);
2653 return(MagickTrue);
2654}
2655
2656/*
2657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2658% %
2659% %
2660% %
2661% X E r r o r %
2662% %
2663% %
2664% %
2665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2666%
2667% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2668% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002669% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2670% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002671%
2672% The format of the XError function is:
2673%
cristybcbda3f2011-09-03 13:01:22 +00002674% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002675%
2676% A description of each parameter follows:
2677%
2678% o display: Specifies a pointer to the Display structure; returned from
2679% XOpenDisplay.
2680%
2681% o error: Specifies the error event.
2682%
2683*/
2684
2685#if defined(__cplusplus) || defined(c_plusplus)
2686extern "C" {
2687#endif
2688
2689MagickExport int XError(Display *display,XErrorEvent *error)
2690{
2691 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2692 assert(display != (Display *) NULL);
2693 assert(error != (XErrorEvent *) NULL);
2694 xerror_alert=MagickTrue;
2695 switch (error->request_code)
2696 {
2697 case X_GetGeometry:
2698 {
2699 if ((int) error->error_code == BadDrawable)
2700 return(MagickFalse);
2701 break;
2702 }
2703 case X_GetWindowAttributes:
2704 case X_QueryTree:
2705 {
2706 if ((int) error->error_code == BadWindow)
2707 return(MagickFalse);
2708 break;
2709 }
2710 case X_QueryColors:
2711 {
2712 if ((int) error->error_code == BadValue)
2713 return(MagickFalse);
2714 break;
2715 }
2716 }
2717 return(MagickTrue);
2718}
2719
2720#if defined(__cplusplus) || defined(c_plusplus)
2721}
2722#endif
2723
2724/*
2725%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2726% %
2727% %
2728% %
2729% X F r e e R e s o u r c e s %
2730% %
2731% %
2732% %
2733%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2734%
2735% XFreeResources() frees X11 resources.
2736%
2737% The format of the XFreeResources method is:
2738%
2739% void XFreeResources(Display *display,XVisualInfo *visual_info,
2740% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2741% XResourceInfo *resource_info,XWindowInfo *window_info)
2742% resource_info,window_info)
2743%
2744% A description of each parameter follows:
2745%
2746% o display: Specifies a connection to an X server; returned from
2747% XOpenDisplay.
2748%
2749% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2750% returned from XGetVisualInfo.
2751%
2752% o map_info: If map_type is specified, this structure is initialized
2753% with info from the Standard Colormap.
2754%
2755% o pixel: Specifies a pointer to a XPixelInfo structure.
2756%
2757% o font_info: Specifies a pointer to a XFontStruct structure.
2758%
2759% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2760%
2761% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2762%
2763*/
cristybcbda3f2011-09-03 13:01:22 +00002764MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002765 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2766 XResourceInfo *resource_info,XWindowInfo *window_info)
2767{
2768 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2769 assert(display != (Display *) NULL);
2770 assert(resource_info != (XResourceInfo *) NULL);
2771 if (window_info != (XWindowInfo *) NULL)
2772 {
2773 /*
2774 Free X image.
2775 */
2776 if (window_info->ximage != (XImage *) NULL)
2777 XDestroyImage(window_info->ximage);
2778 if (window_info->id != (Window) NULL)
2779 {
2780 /*
2781 Free destroy window and free cursors.
2782 */
2783 if (window_info->id != XRootWindow(display,visual_info->screen))
2784 (void) XDestroyWindow(display,window_info->id);
2785 if (window_info->annotate_context != (GC) NULL)
2786 (void) XFreeGC(display,window_info->annotate_context);
2787 if (window_info->highlight_context != (GC) NULL)
2788 (void) XFreeGC(display,window_info->highlight_context);
2789 if (window_info->widget_context != (GC) NULL)
2790 (void) XFreeGC(display,window_info->widget_context);
2791 if (window_info->cursor != (Cursor) NULL)
2792 (void) XFreeCursor(display,window_info->cursor);
2793 window_info->cursor=(Cursor) NULL;
2794 if (window_info->busy_cursor != (Cursor) NULL)
2795 (void) XFreeCursor(display,window_info->busy_cursor);
2796 window_info->busy_cursor=(Cursor) NULL;
2797 }
2798 }
2799 /*
2800 Free font.
2801 */
2802 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002803 {
2804 (void) XFreeFont(display,font_info);
2805 font_info=(XFontStruct *) NULL;
2806 }
cristy3ed852e2009-09-05 21:47:34 +00002807 if (map_info != (XStandardColormap *) NULL)
2808 {
2809 /*
2810 Free X Standard Colormap.
2811 */
2812 if (resource_info->map_type == (char *) NULL)
2813 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2814 (void) XFree((void *) map_info);
2815 }
2816 /*
2817 Free X visual info.
2818 */
2819 if (visual_info != (XVisualInfo *) NULL)
2820 (void) XFree((void *) visual_info);
2821 if (resource_info->close_server != MagickFalse)
2822 (void) XCloseDisplay(display);
2823}
2824
2825/*
2826%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2827% %
2828% %
2829% %
2830% X F r e e S t a n d a r d C o l o r m a p %
2831% %
2832% %
2833% %
2834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2835%
2836% XFreeStandardColormap() frees an X11 colormap.
2837%
2838% The format of the XFreeStandardColormap method is:
2839%
2840% void XFreeStandardColormap(Display *display,
2841% const XVisualInfo *visual_info,XStandardColormap *map_info,
2842% XPixelInfo *pixel)
2843%
2844% A description of each parameter follows:
2845%
2846% o display: Specifies a connection to an X server; returned from
2847% XOpenDisplay.
2848%
2849% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2850% returned from XGetVisualInfo.
2851%
2852% o map_info: If map_type is specified, this structure is initialized
2853% with info from the Standard Colormap.
2854%
2855% o pixel: Specifies a pointer to a XPixelInfo structure.
2856%
2857*/
cristybcbda3f2011-09-03 13:01:22 +00002858MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002859 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2860{
2861 /*
2862 Free colormap.
2863 */
2864 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2865 assert(display != (Display *) NULL);
2866 assert(visual_info != (XVisualInfo *) NULL);
2867 assert(map_info != (XStandardColormap *) NULL);
2868 (void) XFlush(display);
2869 if (map_info->colormap != (Colormap) NULL)
2870 {
2871 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2872 (void) XFreeColormap(display,map_info->colormap);
2873 else
2874 if (pixel != (XPixelInfo *) NULL)
2875 if ((visual_info->klass != TrueColor) &&
2876 (visual_info->klass != DirectColor))
2877 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2878 (int) pixel->colors,0);
2879 }
2880 map_info->colormap=(Colormap) NULL;
2881 if (pixel != (XPixelInfo *) NULL)
2882 {
cristyf2faecf2010-05-28 19:19:36 +00002883 if (pixel->pixels != (unsigned long *) NULL)
2884 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2885 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002886 }
2887}
2888
2889/*
2890%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2891% %
2892% %
2893% %
2894% X G e t A n n o t a t e I n f o %
2895% %
2896% %
2897% %
2898%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2899%
2900% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2901%
2902% The format of the XGetAnnotateInfo method is:
2903%
2904% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2905%
2906% A description of each parameter follows:
2907%
2908% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2909%
2910*/
cristybcbda3f2011-09-03 13:01:22 +00002911MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002912{
2913 /*
2914 Initialize annotate structure.
2915 */
2916 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2917 assert(annotate_info != (XAnnotateInfo *) NULL);
2918 annotate_info->x=0;
2919 annotate_info->y=0;
2920 annotate_info->width=0;
2921 annotate_info->height=0;
2922 annotate_info->stencil=ForegroundStencil;
2923 annotate_info->degrees=0.0;
2924 annotate_info->font_info=(XFontStruct *) NULL;
2925 annotate_info->text=(char *) NULL;
2926 *annotate_info->geometry='\0';
2927 annotate_info->previous=(XAnnotateInfo *) NULL;
2928 annotate_info->next=(XAnnotateInfo *) NULL;
2929 (void) XSupportsLocale();
2930 (void) XSetLocaleModifiers("");
2931}
2932
2933/*
2934%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2935% %
2936% %
2937% %
2938% X G e t M a p I n f o %
2939% %
2940% %
2941% %
2942%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2943%
2944% XGetMapInfo() initializes the XStandardColormap structure.
2945%
2946% The format of the XStandardColormap method is:
2947%
2948% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2949% XStandardColormap *map_info)
2950%
2951% A description of each parameter follows:
2952%
2953% o colormap: Specifies the ID of the X server colormap.
2954%
2955% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2956% returned from XGetVisualInfo.
2957%
2958% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2959%
2960*/
cristybcbda3f2011-09-03 13:01:22 +00002961MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002962 const Colormap colormap,XStandardColormap *map_info)
2963{
2964 /*
2965 Initialize map info.
2966 */
2967 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2968 assert(visual_info != (XVisualInfo *) NULL);
2969 assert(map_info != (XStandardColormap *) NULL);
2970 map_info->colormap=colormap;
2971 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002972 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002973 if (map_info->red_max != 0)
2974 while ((map_info->red_max & 0x01) == 0)
2975 {
2976 map_info->red_max>>=1;
2977 map_info->red_mult<<=1;
2978 }
2979 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002980 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002981 if (map_info->green_max != 0)
2982 while ((map_info->green_max & 0x01) == 0)
2983 {
2984 map_info->green_max>>=1;
2985 map_info->green_mult<<=1;
2986 }
2987 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002988 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002989 if (map_info->blue_max != 0)
2990 while ((map_info->blue_max & 0x01) == 0)
2991 {
2992 map_info->blue_max>>=1;
2993 map_info->blue_mult<<=1;
2994 }
2995 map_info->base_pixel=0;
2996}
2997
2998/*
2999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3000% %
3001% %
3002% %
3003% X G e t P i x e l I n f o %
3004% %
3005% %
3006% %
3007%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3008%
cristy101ab702011-10-13 13:06:32 +00003009% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00003010%
cristy4c08aed2011-07-01 19:47:50 +00003011% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00003012%
cristy4c08aed2011-07-01 19:47:50 +00003013% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00003014% const XStandardColormap *map_info,const XResourceInfo *resource_info,
3015% Image *image,XPixelInfo *pixel)
3016% pixel)
3017%
3018% A description of each parameter follows:
3019%
3020% o display: Specifies a connection to an X server; returned from
3021% XOpenDisplay.
3022%
3023% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3024% returned from XGetVisualInfo.
3025%
3026% o map_info: If map_type is specified, this structure is initialized
3027% with info from the Standard Colormap.
3028%
3029% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3030%
3031% o image: the image.
3032%
3033% o pixel: Specifies a pointer to a XPixelInfo structure.
3034%
3035*/
cristybcbda3f2011-09-03 13:01:22 +00003036MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003037 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3038 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3039{
3040 static const char
3041 *PenColors[MaxNumberPens]=
3042 {
3043 "#000000000000", /* black */
3044 "#00000000ffff", /* blue */
3045 "#0000ffffffff", /* cyan */
3046 "#0000ffff0000", /* green */
3047 "#bdbdbdbdbdbd", /* gray */
3048 "#ffff00000000", /* red */
3049 "#ffff0000ffff", /* magenta */
3050 "#ffffffff0000", /* yellow */
3051 "#ffffffffffff", /* white */
3052 "#bdbdbdbdbdbd", /* gray */
3053 "#bdbdbdbdbdbd" /* gray */
3054 };
3055
3056 Colormap
3057 colormap;
3058
cristybb503372010-05-27 20:51:26 +00003059 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003060 i;
3061
3062 Status
3063 status;
3064
3065 unsigned int
3066 packets;
3067
3068 /*
3069 Initialize pixel info.
3070 */
3071 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3072 assert(display != (Display *) NULL);
3073 assert(visual_info != (XVisualInfo *) NULL);
3074 assert(map_info != (XStandardColormap *) NULL);
3075 assert(resource_info != (XResourceInfo *) NULL);
3076 assert(pixel != (XPixelInfo *) NULL);
3077 pixel->colors=0;
3078 if (image != (Image *) NULL)
3079 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003080 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003081 packets=(unsigned int)
3082 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003083 if (pixel->pixels != (unsigned long *) NULL)
3084 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3085 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003086 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003087 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003088 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3089 image->filename);
3090 /*
3091 Set foreground color.
3092 */
3093 colormap=map_info->colormap;
3094 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3095 &pixel->foreground_color);
3096 status=XParseColor(display,colormap,resource_info->foreground_color,
3097 &pixel->foreground_color);
3098 if (status == False)
3099 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3100 resource_info->foreground_color);
3101 pixel->foreground_color.pixel=
3102 XStandardPixel(map_info,&pixel->foreground_color);
3103 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3104 /*
3105 Set background color.
3106 */
3107 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3108 status=XParseColor(display,colormap,resource_info->background_color,
3109 &pixel->background_color);
3110 if (status == False)
3111 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3112 resource_info->background_color);
3113 pixel->background_color.pixel=
3114 XStandardPixel(map_info,&pixel->background_color);
3115 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3116 /*
3117 Set border color.
3118 */
3119 (void) XParseColor(display,colormap,(char *) BorderColor,
3120 &pixel->border_color);
3121 status=XParseColor(display,colormap,resource_info->border_color,
3122 &pixel->border_color);
3123 if (status == False)
3124 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3125 resource_info->border_color);
3126 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3127 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3128 /*
3129 Set matte color.
3130 */
3131 pixel->matte_color=pixel->background_color;
3132 if (resource_info->matte_color != (char *) NULL)
3133 {
3134 /*
3135 Matte color is specified as a X resource or command line argument.
3136 */
3137 status=XParseColor(display,colormap,resource_info->matte_color,
3138 &pixel->matte_color);
3139 if (status == False)
3140 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3141 resource_info->matte_color);
3142 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3143 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3144 }
3145 /*
3146 Set highlight color.
3147 */
3148 pixel->highlight_color.red=(unsigned short) ((
3149 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3150 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3151 pixel->highlight_color.green=(unsigned short) ((
3152 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3153 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3154 pixel->highlight_color.blue=(unsigned short) ((
3155 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3156 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3157 pixel->highlight_color.pixel=
3158 XStandardPixel(map_info,&pixel->highlight_color);
3159 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3160 /*
3161 Set shadow color.
3162 */
3163 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3164 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3165 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3166 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3167 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3168 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3169 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3170 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3171 /*
3172 Set depth color.
3173 */
3174 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3175 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3176 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3177 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3178 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3179 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3180 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3181 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3182 /*
3183 Set trough color.
3184 */
3185 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3186 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3187 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3188 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3189 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3190 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3191 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3192 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3193 /*
3194 Set pen color.
3195 */
3196 for (i=0; i < MaxNumberPens; i++)
3197 {
3198 (void) XParseColor(display,colormap,(char *) PenColors[i],
3199 &pixel->pen_colors[i]);
3200 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3201 &pixel->pen_colors[i]);
3202 if (status == False)
3203 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3204 resource_info->pen_colors[i]);
3205 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3206 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3207 }
3208 pixel->box_color=pixel->background_color;
3209 pixel->pen_color=pixel->foreground_color;
3210 pixel->box_index=0;
3211 pixel->pen_index=1;
3212 if (image != (Image *) NULL)
3213 {
3214 if ((resource_info->gamma_correct != MagickFalse) &&
3215 (image->gamma != 0.0))
3216 {
3217 GeometryInfo
3218 geometry_info;
3219
3220 MagickStatusType
3221 flags;
3222
3223 /*
3224 Initialize map relative to display and image gamma.
3225 */
3226 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3227 red_gamma=geometry_info.rho;
3228 green_gamma=geometry_info.sigma;
3229 if ((flags & SigmaValue) == 0)
3230 green_gamma=red_gamma;
3231 blue_gamma=geometry_info.xi;
3232 if ((flags & XiValue) == 0)
3233 blue_gamma=red_gamma;
3234 red_gamma*=image->gamma;
3235 green_gamma*=image->gamma;
3236 blue_gamma*=image->gamma;
3237 }
3238 if (image->storage_class == PseudoClass)
3239 {
3240 /*
3241 Initialize pixel array for images of type PseudoClass.
3242 */
cristybb503372010-05-27 20:51:26 +00003243 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003244 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003245 for (i=0; i < MaxNumberPens; i++)
3246 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3247 pixel->colors+=MaxNumberPens;
3248 }
3249 }
3250}
3251
3252/*
3253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3254% %
3255% %
3256% %
3257% X G e t R e s o u r c e C l a s s %
3258% %
3259% %
3260% %
3261%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3262%
3263% XGetResourceClass() queries the X server for the specified resource name or
3264% class. If the resource name or class is not defined in the database, the
3265% supplied default value is returned.
3266%
3267% The format of the XGetResourceClass method is:
3268%
3269% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3270% const char *keyword,char *resource_default)
3271%
3272% A description of each parameter follows:
3273%
3274% o database: Specifies a resource database; returned from
3275% XrmGetStringDatabase.
3276%
3277% o client_name: Specifies the application name used to retrieve resource
3278% info from the X server database.
3279%
3280% o keyword: Specifies the keyword of the value being retrieved.
3281%
3282% o resource_default: Specifies the default value to return if the query
3283% fails to find the specified keyword/class.
3284%
3285*/
3286MagickExport char *XGetResourceClass(XrmDatabase database,
3287 const char *client_name,const char *keyword,char *resource_default)
3288{
3289 char
3290 resource_class[MaxTextExtent],
3291 resource_name[MaxTextExtent];
3292
3293 static char
3294 *resource_type;
3295
3296 Status
3297 status;
3298
3299 XrmValue
3300 resource_value;
3301
3302 if (database == (XrmDatabase) NULL)
3303 return(resource_default);
3304 *resource_name='\0';
3305 *resource_class='\0';
3306 if (keyword != (char *) NULL)
3307 {
3308 int
3309 c,
3310 k;
3311
3312 /*
3313 Initialize resource keyword and class.
3314 */
cristyb51dff52011-05-19 16:55:47 +00003315 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003316 client_name,keyword);
3317 c=(int) (*client_name);
3318 if ((c >= XK_a) && (c <= XK_z))
3319 c-=(XK_a-XK_A);
3320 else
3321 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3322 c-=(XK_agrave-XK_Agrave);
3323 else
3324 if ((c >= XK_oslash) && (c <= XK_thorn))
3325 c-=(XK_oslash-XK_Ooblique);
3326 k=(int) (*keyword);
3327 if ((k >= XK_a) && (k <= XK_z))
3328 k-=(XK_a-XK_A);
3329 else
3330 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3331 k-=(XK_agrave-XK_Agrave);
3332 else
3333 if ((k >= XK_oslash) && (k <= XK_thorn))
3334 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003335 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003336 client_name+1,k,keyword+1);
3337 }
3338 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3339 &resource_value);
3340 if (status == False)
3341 return(resource_default);
3342 return(resource_value.addr);
3343}
3344
3345/*
3346%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3347% %
3348% %
3349% %
3350% X G e t R e s o u r c e D a t a b a s e %
3351% %
3352% %
3353% %
3354%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3355%
3356% XGetResourceDatabase() creates a new resource database and initializes it.
3357%
3358% The format of the XGetResourceDatabase method is:
3359%
3360% XrmDatabase XGetResourceDatabase(Display *display,
3361% const char *client_name)
3362%
3363% A description of each parameter follows:
3364%
3365% o database: XGetResourceDatabase() returns the database after it is
3366% initialized.
3367%
3368% o display: Specifies a connection to an X server; returned from
3369% XOpenDisplay.
3370%
3371% o client_name: Specifies the application name used to retrieve resource
3372% info from the X server database.
3373%
3374*/
3375MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3376 const char *client_name)
3377{
3378 char
3379 filename[MaxTextExtent];
3380
3381 int
3382 c;
3383
3384 register const char
3385 *p;
3386
3387 XrmDatabase
3388 resource_database,
3389 server_database;
3390
3391 if (display == (Display *) NULL)
3392 return((XrmDatabase) NULL);
3393 assert(client_name != (char *) NULL);
3394 /*
3395 Initialize resource database.
3396 */
3397 XrmInitialize();
3398 (void) XGetDefault(display,(char *) client_name,"dummy");
3399 resource_database=XrmGetDatabase(display);
3400 /*
3401 Combine application database.
3402 */
3403 if (client_name != (char *) NULL)
3404 {
3405 /*
3406 Get basename of client.
3407 */
3408 p=client_name+(strlen(client_name)-1);
3409 while ((p > client_name) && (*p != '/'))
3410 p--;
3411 if (*p == '/')
3412 client_name=p+1;
3413 }
3414 c=(int) (*client_name);
3415 if ((c >= XK_a) && (c <= XK_z))
3416 c-=(XK_a-XK_A);
3417 else
3418 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3419 c-=(XK_agrave-XK_Agrave);
3420 else
3421 if ((c >= XK_oslash) && (c <= XK_thorn))
3422 c-=(XK_oslash-XK_Ooblique);
3423#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003424 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003425 X11_APPLICATION_PATH,c,client_name+1);
3426 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3427#endif
3428 if (XResourceManagerString(display) != (char *) NULL)
3429 {
3430 /*
3431 Combine server database.
3432 */
3433 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3434 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3435 }
3436 /*
3437 Merge user preferences database.
3438 */
3439#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003440 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003441 X11_PREFERENCES_PATH,client_name);
3442 ExpandFilename(filename);
3443 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3444#endif
3445 return(resource_database);
3446}
3447
3448/*
3449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3450% %
3451% %
3452% %
3453% X G e t R e s o u r c e I n f o %
3454% %
3455% %
3456% %
3457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3458%
3459% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3460%
3461% The format of the XGetResourceInfo method is:
3462%
3463% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3464% const char *client_name,XResourceInfo *resource_info)
3465%
3466% A description of each parameter follows:
3467%
3468% o image_info: the image info.
3469%
3470% o database: Specifies a resource database; returned from
3471% XrmGetStringDatabase.
3472%
3473% o client_name: Specifies the application name used to retrieve
3474% resource info from the X server database.
3475%
3476% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3477%
3478*/
3479MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3480 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3481{
3482 char
cristy00976d82011-02-20 20:31:28 +00003483 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003484 *resource_value;
3485
3486 /*
3487 Initialize resource info fields.
3488 */
3489 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3490 assert(resource_info != (XResourceInfo *) NULL);
3491 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3492 resource_info->resource_database=database;
3493 resource_info->image_info=(ImageInfo *) image_info;
3494 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3495 XMagickProgressMonitor,(void *) NULL);
3496 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3497 resource_info->close_server=MagickTrue;
3498 resource_info->client_name=AcquireString(client_name);
3499 resource_value=XGetResourceClass(database,client_name,"backdrop",
3500 (char *) "False");
3501 resource_info->backdrop=IsMagickTrue(resource_value);
3502 resource_info->background_color=XGetResourceInstance(database,client_name,
3503 "background",(char *) "#d6d6d6d6d6d6");
3504 resource_info->border_color=XGetResourceInstance(database,client_name,
3505 "borderColor",BorderColor);
3506 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3507 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003508 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3509 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003510 resource_value=XGetResourceClass(database,client_name,"colormap",
3511 (char *) "shared");
3512 resource_info->colormap=UndefinedColormap;
3513 if (LocaleCompare("private",resource_value) == 0)
3514 resource_info->colormap=PrivateColormap;
3515 if (LocaleCompare("shared",resource_value) == 0)
3516 resource_info->colormap=SharedColormap;
3517 if (resource_info->colormap == UndefinedColormap)
3518 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3519 resource_value);
3520 resource_value=XGetResourceClass(database,client_name,
3521 "colorRecovery",(char *) "False");
3522 resource_info->color_recovery=IsMagickTrue(resource_value);
3523 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3524 (char *) "False");
3525 resource_info->confirm_exit=IsMagickTrue(resource_value);
3526 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3527 (char *) "False");
3528 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003529 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003530 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003531 resource_info->display_gamma=XGetResourceClass(database,client_name,
3532 "displayGamma",(char *) "2.2");
3533 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3534 (char *) "True");
3535 resource_info->display_warnings=IsMagickTrue(resource_value);
3536 resource_info->font=XGetResourceClass(database,client_name,"font",
3537 (char *) NULL);
3538 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3539 resource_info->font);
3540 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3541 (char *) "fixed");
3542 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3543 (char *) "variable");
3544 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3545 (char *) "5x8");
3546 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3547 (char *) "6x10");
3548 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3549 (char *) "7x13bold");
3550 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3551 (char *) "8x13bold");
3552 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3553 (char *) "9x15bold");
3554 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3555 (char *) "10x20");
3556 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3557 (char *) "12x24");
3558 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3559 (char *) "fixed");
3560 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3561 (char *) "fixed");
3562 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3563 "foreground",ForegroundColor);
3564 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3565 (char *) "True");
3566 resource_info->gamma_correct=IsMagickTrue(resource_value);
3567 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3568 client_name,"geometry",(char *) NULL));
3569 resource_value=XGetResourceClass(database,client_name,"gravity",
3570 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003571 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003572 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003573 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3574 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003575 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3576 "iconGeometry",(char *) NULL);
3577 resource_value=XGetResourceClass(database,client_name,"iconic",
3578 (char *) "False");
3579 resource_info->iconic=IsMagickTrue(resource_value);
3580 resource_value=XGetResourceClass(database,client_name,"immutable",
3581 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3582 (char *) "False");
3583 resource_info->immutable=IsMagickTrue(resource_value);
3584 resource_value=XGetResourceClass(database,client_name,"magnify",
3585 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003586 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003587 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3588 (char *) NULL);
3589 resource_info->matte_color=XGetResourceInstance(database,client_name,
3590 "mattecolor",(char *) NULL);
3591 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3592 "name",(char *) NULL));
3593 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3594 (char *) "black");
3595 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3596 (char *) "blue");
3597 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3598 (char *) "cyan");
3599 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3600 (char *) "green");
3601 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3602 (char *) "gray");
3603 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3604 (char *) "red");
3605 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3606 (char *) "magenta");
3607 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3608 (char *) "yellow");
3609 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3610 (char *) "white");
3611 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3612 (char *) "gray");
3613 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3614 (char *) "gray");
3615 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003616 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003617 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003618 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003619 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3620 "font",(char *) "fixed");
3621 resource_info->text_font=XGetResourceClass(database,client_name,
3622 "textFontList",resource_info->text_font);
3623 resource_info->title=XGetResourceClass(database,client_name,"title",
3624 (char *) NULL);
3625 resource_value=XGetResourceClass(database,client_name,"undoCache",
3626 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003627 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003628 resource_value=XGetResourceClass(database,client_name,"update",
3629 (char *) "False");
3630 resource_info->update=IsMagickTrue(resource_value);
3631 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3632 (char *) "True");
3633 resource_info->use_pixmap=IsMagickTrue(resource_value);
3634 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3635 (char *) "True");
3636 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3637 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3638 (char *) NULL);
3639 resource_info->window_group=XGetResourceClass(database,client_name,
3640 "windowGroup",(char *) NULL);
3641 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3642 (char *) NULL);
3643 resource_info->write_filename=XGetResourceClass(database,client_name,
3644 "writeFilename",(char *) NULL);
3645}
3646
3647/*
3648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3649% %
3650% %
3651% %
3652% X G e t R e s o u r c e I n s t a n c e %
3653% %
3654% %
3655% %
3656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3657%
3658% XGetResourceInstance() queries the X server for the specified resource name.
3659% If the resource name is not defined in the database, the supplied default
3660% value is returned.
3661%
3662% The format of the XGetResourceInstance method is:
3663%
3664% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3665% const char *keyword,const char *resource_default)
3666%
3667% A description of each parameter follows:
3668%
3669% o database: Specifies a resource database; returned from
3670% XrmGetStringDatabase.
3671%
3672% o client_name: Specifies the application name used to retrieve
3673% resource info from the X server database.
3674%
3675% o keyword: Specifies the keyword of the value being retrieved.
3676%
3677% o resource_default: Specifies the default value to return if the query
3678% fails to find the specified keyword/class.
3679%
3680*/
3681MagickExport char *XGetResourceInstance(XrmDatabase database,
3682 const char *client_name,const char *keyword,const char *resource_default)
3683{
3684 char
3685 *resource_type,
3686 resource_name[MaxTextExtent];
3687
3688 Status
3689 status;
3690
3691 XrmValue
3692 resource_value;
3693
3694 if (database == (XrmDatabase) NULL)
3695 return((char *) resource_default);
3696 *resource_name='\0';
3697 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003698 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003699 keyword);
3700 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3701 &resource_value);
3702 if (status == False)
3703 return((char *) resource_default);
3704 return(resource_value.addr);
3705}
3706
3707/*
3708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3709% %
3710% %
3711% %
3712% X G e t S c r e e n D e n s i t y %
3713% %
3714% %
3715% %
3716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3717%
3718% XGetScreenDensity() returns the density of the X server screen in
3719% dots-per-inch.
3720%
3721% The format of the XGetScreenDensity method is:
3722%
3723% char *XGetScreenDensity(Display *display)
3724%
3725% A description of each parameter follows:
3726%
3727% o density: XGetScreenDensity() returns the density of the X screen in
3728% dots-per-inch.
3729%
3730% o display: Specifies a connection to an X server; returned from
3731% XOpenDisplay.
3732%
3733*/
3734MagickExport char *XGetScreenDensity(Display *display)
3735{
3736 char
3737 density[MaxTextExtent];
3738
3739 double
3740 x_density,
3741 y_density;
3742
3743 /*
3744 Set density as determined by screen size.
3745 */
3746 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3747 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3748 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3749 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003750 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003751 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003752 return(GetPageGeometry(density));
3753}
3754
3755/*
3756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3757% %
3758% %
3759% %
3760+ X G e t S u b w i n d o w %
3761% %
3762% %
3763% %
3764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3765%
3766% XGetSubwindow() returns the subwindow of a window chosen the user with the
3767% pointer and a button press.
3768%
3769% The format of the XGetSubwindow method is:
3770%
3771% Window XGetSubwindow(Display *display,Window window,int x,int y)
3772%
3773% A description of each parameter follows:
3774%
3775% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3776% otherwise the subwindow is returned.
3777%
3778% o display: Specifies a connection to an X server; returned from
3779% XOpenDisplay.
3780%
3781% o window: Specifies a pointer to a Window.
3782%
3783% o x: the x coordinate of the pointer relative to the origin of the
3784% window.
3785%
3786% o y: the y coordinate of the pointer relative to the origin of the
3787% window.
3788%
cristy3ed852e2009-09-05 21:47:34 +00003789*/
3790static Window XGetSubwindow(Display *display,Window window,int x,int y)
3791{
3792 int
3793 x_offset,
3794 y_offset;
3795
3796 Status
3797 status;
3798
3799 Window
3800 source_window,
3801 target_window;
3802
3803 assert(display != (Display *) NULL);
3804 source_window=XRootWindow(display,XDefaultScreen(display));
3805 if (window == (Window) NULL)
3806 return(source_window);
3807 target_window=window;
3808 for ( ; ; )
3809 {
3810 status=XTranslateCoordinates(display,source_window,window,x,y,
3811 &x_offset,&y_offset,&target_window);
3812 if (status != True)
3813 break;
3814 if (target_window == (Window) NULL)
3815 break;
3816 source_window=window;
3817 window=target_window;
3818 x=x_offset;
3819 y=y_offset;
3820 }
3821 if (target_window == (Window) NULL)
3822 target_window=window;
3823 return(target_window);
3824}
3825
3826/*
3827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3828% %
3829% %
3830% %
3831% X G e t W i n d o w C o l o r %
3832% %
3833% %
3834% %
3835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3836%
3837% XGetWindowColor() returns the color of a pixel interactively chosen from the
3838% X server.
3839%
3840% The format of the XGetWindowColor method is:
3841%
3842% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3843% char *name)
3844%
3845% A description of each parameter follows:
3846%
3847% o display: Specifies a connection to an X server; returned from
3848% XOpenDisplay.
3849%
3850% o windows: Specifies a pointer to a XWindows structure.
3851%
3852% o name: the name of the color if found in the X Color Database is
3853% returned in this character string.
3854%
3855*/
cristybcbda3f2011-09-03 13:01:22 +00003856MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003857 XWindows *windows,char *name)
3858{
3859 int
3860 x,
3861 y;
3862
cristy101ab702011-10-13 13:06:32 +00003863 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003864 pixel;
3865
3866 RectangleInfo
3867 crop_info;
3868
3869 Status
3870 status;
3871
3872 Window
3873 child,
3874 client_window,
3875 root_window,
3876 target_window;
3877
3878 XColor
3879 color;
3880
3881 XImage
3882 *ximage;
3883
3884 XWindowAttributes
3885 window_attributes;
3886
3887 /*
3888 Choose a pixel from the X server.
3889 */
3890 assert(display != (Display *) NULL);
3891 assert(name != (char *) NULL);
3892 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3893 *name='\0';
3894 target_window=XSelectWindow(display,&crop_info);
3895 if (target_window == (Window) NULL)
3896 return(MagickFalse);
3897 root_window=XRootWindow(display,XDefaultScreen(display));
3898 client_window=target_window;
3899 if (target_window != root_window)
3900 {
3901 unsigned int
3902 d;
3903
3904 /*
3905 Get client window.
3906 */
3907 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3908 if (status != False)
3909 {
3910 client_window=XClientWindow(display,target_window);
3911 target_window=client_window;
3912 }
3913 }
3914 /*
3915 Verify window is viewable.
3916 */
3917 status=XGetWindowAttributes(display,target_window,&window_attributes);
3918 if ((status == False) || (window_attributes.map_state != IsViewable))
3919 return(MagickFalse);
3920 /*
3921 Get window X image.
3922 */
3923 (void) XTranslateCoordinates(display,root_window,target_window,
3924 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3925 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3926 if (ximage == (XImage *) NULL)
3927 return(MagickFalse);
3928 color.pixel=XGetPixel(ximage,0,0);
3929 XDestroyImage(ximage);
3930 /*
3931 Match color against the color database.
3932 */
3933 (void) XQueryColor(display,window_attributes.colormap,&color);
3934 pixel.red=ScaleShortToQuantum(color.red);
3935 pixel.green=ScaleShortToQuantum(color.green);
3936 pixel.blue=ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003937 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003938 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3939 &windows->image.image->exception);
3940 return(MagickTrue);
3941}
3942
3943/*
3944%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3945% %
3946% %
3947% %
3948+ X G e t W i n d o w I m a g e %
3949% %
3950% %
3951% %
3952%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3953%
3954% XGetWindowImage() reads an image from the target X window and returns it.
3955% XGetWindowImage() optionally descends the window hierarchy and overlays the
3956% target image with each child image in an optimized fashion. Any child
3957% window that have the same visual, colormap, and are contained by its parent
3958% are exempted.
3959%
3960% The format of the XGetWindowImage method is:
3961%
3962% Image *XGetWindowImage(Display *display,const Window window,
3963% const unsigned int borders,const unsigned int level)
3964%
3965% A description of each parameter follows:
3966%
3967% o display: Specifies a connection to an X server; returned from
3968% XOpenDisplay.
3969%
3970% o window: Specifies the window to obtain the image from.
3971%
3972% o borders: Specifies whether borders pixels are to be saved with
3973% the image.
3974%
3975% o level: Specifies an unsigned integer representing the level of
3976% decent in the window hierarchy. This value must be zero or one on
3977% the initial call to XGetWindowImage. A value of zero returns after
3978% one call. A value of one causes the function to descend the window
3979% hierarchy and overlay the target image with each subwindow image.
3980%
cristy3ed852e2009-09-05 21:47:34 +00003981*/
3982static Image *XGetWindowImage(Display *display,const Window window,
3983 const unsigned int borders,const unsigned int level)
3984{
3985 typedef struct _ColormapInfo
3986 {
3987 Colormap
3988 colormap;
3989
3990 XColor
3991 *colors;
3992
3993 struct _ColormapInfo
3994 *next;
3995 } ColormapInfo;
3996
3997 typedef struct _WindowInfo
3998 {
3999 Window
4000 window,
4001 parent;
4002
4003 Visual
4004 *visual;
4005
4006 Colormap
4007 colormap;
4008
4009 XSegment
4010 bounds;
4011
4012 RectangleInfo
4013 crop_info;
4014 } WindowInfo;
4015
cristy3ed852e2009-09-05 21:47:34 +00004016 int
4017 display_height,
4018 display_width,
4019 id,
4020 x_offset,
4021 y_offset;
4022
cristy4c08aed2011-07-01 19:47:50 +00004023 Quantum
4024 index;
4025
cristy3ed852e2009-09-05 21:47:34 +00004026 RectangleInfo
4027 crop_info;
4028
cristy3ed852e2009-09-05 21:47:34 +00004029 register int
4030 i;
4031
4032 static ColormapInfo
4033 *colormap_info = (ColormapInfo *) NULL;
4034
4035 static int
4036 max_windows = 0,
4037 number_windows = 0;
4038
4039 static WindowInfo
4040 *window_info;
4041
4042 Status
4043 status;
4044
4045 Window
4046 child,
4047 root_window;
4048
4049 XWindowAttributes
4050 window_attributes;
4051
4052 /*
4053 Verify window is viewable.
4054 */
4055 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4056 assert(display != (Display *) NULL);
4057 status=XGetWindowAttributes(display,window,&window_attributes);
4058 if ((status == False) || (window_attributes.map_state != IsViewable))
4059 return((Image *) NULL);
4060 /*
4061 Cropping rectangle is relative to root window.
4062 */
4063 root_window=XRootWindow(display,XDefaultScreen(display));
4064 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4065 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004066 crop_info.x=(ssize_t) x_offset;
4067 crop_info.y=(ssize_t) y_offset;
4068 crop_info.width=(size_t) window_attributes.width;
4069 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004070 if (borders != MagickFalse)
4071 {
4072 /*
4073 Include border in image.
4074 */
cristybb503372010-05-27 20:51:26 +00004075 crop_info.x-=(ssize_t) window_attributes.border_width;
4076 crop_info.y-=(ssize_t) window_attributes.border_width;
4077 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4078 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004079 }
4080 /*
4081 Crop to root window.
4082 */
4083 if (crop_info.x < 0)
4084 {
4085 crop_info.width+=crop_info.x;
4086 crop_info.x=0;
4087 }
4088 if (crop_info.y < 0)
4089 {
4090 crop_info.height+=crop_info.y;
4091 crop_info.y=0;
4092 }
4093 display_width=XDisplayWidth(display,XDefaultScreen(display));
4094 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004095 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004096 display_height=XDisplayHeight(display,XDefaultScreen(display));
4097 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004098 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004099 /*
4100 Initialize window info attributes.
4101 */
4102 if (number_windows >= max_windows)
4103 {
4104 /*
4105 Allocate or resize window info buffer.
4106 */
4107 max_windows+=1024;
4108 if (window_info == (WindowInfo *) NULL)
4109 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4110 sizeof(*window_info));
4111 else
4112 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4113 max_windows,sizeof(*window_info));
4114 }
4115 if (window_info == (WindowInfo *) NULL)
4116 {
4117 ThrowXWindowFatalException(ResourceLimitError,
4118 "MemoryAllocationFailed","...");
4119 return((Image *) NULL);
4120 }
4121 id=number_windows++;
4122 window_info[id].window=window;
4123 window_info[id].visual=window_attributes.visual;
4124 window_info[id].colormap=window_attributes.colormap;
4125 window_info[id].bounds.x1=(short) crop_info.x;
4126 window_info[id].bounds.y1=(short) crop_info.y;
4127 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4128 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4129 crop_info.x-=x_offset;
4130 crop_info.y-=y_offset;
4131 window_info[id].crop_info=crop_info;
4132 if (level != 0)
4133 {
4134 unsigned int
4135 number_children;
4136
4137 Window
4138 *children;
4139
4140 /*
4141 Descend the window hierarchy.
4142 */
4143 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4144 &children,&number_children);
4145 for (i=0; i < id; i++)
4146 if ((window_info[i].window == window_info[id].parent) &&
4147 (window_info[i].visual == window_info[id].visual) &&
4148 (window_info[i].colormap == window_info[id].colormap))
4149 {
4150 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4151 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4152 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4153 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4154 {
4155 /*
4156 Eliminate windows not circumscribed by their parent.
4157 */
4158 number_windows--;
4159 break;
4160 }
4161 }
4162 if ((status == True) && (number_children != 0))
4163 {
4164 for (i=0; i < (int) number_children; i++)
4165 (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4166 (void) XFree((void *) children);
4167 }
4168 }
4169 if (level <= 1)
4170 {
cristyc57f6942010-11-12 01:47:39 +00004171 CacheView
4172 *composite_view;
4173
cristy3ed852e2009-09-05 21:47:34 +00004174 ColormapInfo
4175 *next;
4176
4177 ExceptionInfo
4178 *exception;
4179
4180 Image
4181 *composite_image,
4182 *image;
4183
4184 int
4185 y;
4186
4187 MagickBooleanType
4188 import;
4189
4190 register int
4191 j,
4192 x;
4193
cristy4c08aed2011-07-01 19:47:50 +00004194 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004195 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004196
cristybb503372010-05-27 20:51:26 +00004197 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004198 pixel;
4199
4200 unsigned int
4201 number_colors;
4202
4203 XColor
4204 *colors;
4205
4206 XImage
4207 *ximage;
4208
4209 /*
4210 Get X image for each window in the list.
4211 */
4212 image=NewImageList();
4213 for (id=0; id < number_windows; id++)
4214 {
4215 /*
4216 Does target window intersect top level window?
4217 */
4218 import=
4219 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4220 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4221 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4222 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4223 MagickTrue : MagickFalse;
4224 /*
4225 Is target window contained by another window with the same colormap?
4226 */
4227 for (j=0; j < id; j++)
4228 if ((window_info[id].visual == window_info[j].visual) &&
4229 (window_info[id].colormap == window_info[j].colormap))
4230 {
4231 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4232 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4233 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4234 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4235 import=MagickFalse;
4236 }
4237 else
4238 if ((window_info[id].visual != window_info[j].visual) ||
4239 (window_info[id].colormap != window_info[j].colormap))
4240 {
4241 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4242 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4243 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4244 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4245 import=MagickTrue;
4246 }
4247 if (import == MagickFalse)
4248 continue;
4249 /*
4250 Get X image.
4251 */
4252 ximage=XGetImage(display,window_info[id].window,(int)
4253 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4254 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4255 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4256 if (ximage == (XImage *) NULL)
4257 continue;
4258 /*
4259 Initialize window colormap.
4260 */
4261 number_colors=0;
4262 colors=(XColor *) NULL;
4263 if (window_info[id].colormap != (Colormap) NULL)
4264 {
4265 ColormapInfo
4266 *p;
4267
4268 /*
4269 Search colormap list for window colormap.
4270 */
4271 number_colors=(unsigned int) window_info[id].visual->map_entries;
4272 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4273 if (p->colormap == window_info[id].colormap)
4274 break;
4275 if (p == (ColormapInfo *) NULL)
4276 {
4277 /*
4278 Get the window colormap.
4279 */
4280 colors=(XColor *) AcquireQuantumMemory(number_colors,
4281 sizeof(*colors));
4282 if (colors == (XColor *) NULL)
4283 {
4284 XDestroyImage(ximage);
4285 return((Image *) NULL);
4286 }
4287 if ((window_info[id].visual->klass != DirectColor) &&
4288 (window_info[id].visual->klass != TrueColor))
4289 for (i=0; i < (int) number_colors; i++)
4290 {
cristybb503372010-05-27 20:51:26 +00004291 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004292 colors[i].pad='\0';
4293 }
4294 else
4295 {
cristybb503372010-05-27 20:51:26 +00004296 size_t
cristy3ed852e2009-09-05 21:47:34 +00004297 blue,
4298 blue_bit,
4299 green,
4300 green_bit,
4301 red,
4302 red_bit;
4303
4304 /*
4305 DirectColor or TrueColor visual.
4306 */
4307 red=0;
4308 green=0;
4309 blue=0;
4310 red_bit=window_info[id].visual->red_mask &
4311 (~(window_info[id].visual->red_mask)+1);
4312 green_bit=window_info[id].visual->green_mask &
4313 (~(window_info[id].visual->green_mask)+1);
4314 blue_bit=window_info[id].visual->blue_mask &
4315 (~(window_info[id].visual->blue_mask)+1);
4316 for (i=0; i < (int) number_colors; i++)
4317 {
cristy8891f9c2010-06-04 23:32:17 +00004318 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004319 colors[i].pad='\0';
4320 red+=red_bit;
4321 if (red > window_info[id].visual->red_mask)
4322 red=0;
4323 green+=green_bit;
4324 if (green > window_info[id].visual->green_mask)
4325 green=0;
4326 blue+=blue_bit;
4327 if (blue > window_info[id].visual->blue_mask)
4328 blue=0;
4329 }
4330 }
4331 (void) XQueryColors(display,window_info[id].colormap,colors,
4332 (int) number_colors);
4333 /*
4334 Append colormap to colormap list.
4335 */
cristy73bd4a52010-10-05 11:24:23 +00004336 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004337 if (p == (ColormapInfo *) NULL)
4338 return((Image *) NULL);
4339 p->colormap=window_info[id].colormap;
4340 p->colors=colors;
4341 p->next=colormap_info;
4342 colormap_info=p;
4343 }
4344 colors=p->colors;
4345 }
4346 /*
4347 Allocate image structure.
4348 */
cristy9950d572011-10-01 18:22:35 +00004349 composite_image=AcquireImage((ImageInfo *) NULL,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00004350 if (composite_image == (Image *) NULL)
4351 {
4352 XDestroyImage(ximage);
4353 return((Image *) NULL);
4354 }
4355 /*
4356 Convert X image to MIFF format.
4357 */
4358 if ((window_info[id].visual->klass != TrueColor) &&
4359 (window_info[id].visual->klass != DirectColor))
4360 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004361 composite_image->columns=(size_t) ximage->width;
4362 composite_image->rows=(size_t) ximage->height;
cristy3ed852e2009-09-05 21:47:34 +00004363 exception=(&composite_image->exception);
cristyc57f6942010-11-12 01:47:39 +00004364 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004365 switch (composite_image->storage_class)
4366 {
4367 case DirectClass:
4368 default:
4369 {
cristybb503372010-05-27 20:51:26 +00004370 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004371 color,
4372 index;
4373
cristybb503372010-05-27 20:51:26 +00004374 size_t
cristy3ed852e2009-09-05 21:47:34 +00004375 blue_mask,
4376 blue_shift,
4377 green_mask,
4378 green_shift,
4379 red_mask,
4380 red_shift;
4381
4382 /*
4383 Determine shift and mask for red, green, and blue.
4384 */
4385 red_mask=window_info[id].visual->red_mask;
4386 red_shift=0;
4387 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4388 {
4389 red_mask>>=1;
4390 red_shift++;
4391 }
4392 green_mask=window_info[id].visual->green_mask;
4393 green_shift=0;
4394 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4395 {
4396 green_mask>>=1;
4397 green_shift++;
4398 }
4399 blue_mask=window_info[id].visual->blue_mask;
4400 blue_shift=0;
4401 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4402 {
4403 blue_mask>>=1;
4404 blue_shift++;
4405 }
4406 /*
4407 Convert X image to DirectClass packets.
4408 */
4409 if ((number_colors != 0) &&
4410 (window_info[id].visual->klass == DirectColor))
4411 for (y=0; y < (int) composite_image->rows; y++)
4412 {
cristyc57f6942010-11-12 01:47:39 +00004413 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004414 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004415 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004416 break;
4417 for (x=0; x < (int) composite_image->columns; x++)
4418 {
4419 pixel=XGetPixel(ximage,x,y);
4420 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004421 SetPixelRed(composite_image,
4422 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004423 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004424 SetPixelGreen(composite_image,
4425 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004426 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004427 SetPixelBlue(composite_image,
4428 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004429 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004430 }
cristyc57f6942010-11-12 01:47:39 +00004431 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004432 break;
4433 }
4434 else
4435 for (y=0; y < (int) composite_image->rows; y++)
4436 {
cristyc57f6942010-11-12 01:47:39 +00004437 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004438 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004439 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004440 break;
4441 for (x=0; x < (int) composite_image->columns; x++)
4442 {
4443 pixel=XGetPixel(ximage,x,y);
4444 color=(pixel >> red_shift) & red_mask;
4445 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004446 SetPixelRed(composite_image,
4447 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004448 color=(pixel >> green_shift) & green_mask;
4449 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004450 SetPixelGreen(composite_image,
4451 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004452 color=(pixel >> blue_shift) & blue_mask;
4453 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004454 SetPixelBlue(composite_image,
4455 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004456 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004457 }
cristyc57f6942010-11-12 01:47:39 +00004458 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004459 break;
4460 }
4461 break;
4462 }
4463 case PseudoClass:
4464 {
4465 /*
4466 Create colormap.
4467 */
cristy018f07f2011-09-04 21:15:19 +00004468 if (AcquireImageColormap(composite_image,number_colors,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004469 {
4470 XDestroyImage(ximage);
4471 composite_image=DestroyImage(composite_image);
4472 return((Image *) NULL);
4473 }
4474 for (i=0; i < (int) composite_image->colors; i++)
4475 {
4476 composite_image->colormap[colors[i].pixel].red=
4477 ScaleShortToQuantum(colors[i].red);
4478 composite_image->colormap[colors[i].pixel].green=
4479 ScaleShortToQuantum(colors[i].green);
4480 composite_image->colormap[colors[i].pixel].blue=
4481 ScaleShortToQuantum(colors[i].blue);
4482 }
4483 /*
4484 Convert X image to PseudoClass packets.
4485 */
4486 for (y=0; y < (int) composite_image->rows; y++)
4487 {
cristyc57f6942010-11-12 01:47:39 +00004488 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4489 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004490 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004491 break;
cristy3ed852e2009-09-05 21:47:34 +00004492 for (x=0; x < (int) composite_image->columns; x++)
4493 {
cristy4c08aed2011-07-01 19:47:50 +00004494 index=(Quantum) XGetPixel(ximage,x,y);
4495 SetPixelIndex(composite_image,index,q);
cristy101ab702011-10-13 13:06:32 +00004496 SetPixelPixelInfo(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004497 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004498 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004499 }
cristyc57f6942010-11-12 01:47:39 +00004500 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004501 break;
4502 }
4503 break;
4504 }
4505 }
cristyc57f6942010-11-12 01:47:39 +00004506 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004507 XDestroyImage(ximage);
4508 if (image == (Image *) NULL)
4509 {
4510 image=composite_image;
4511 continue;
4512 }
4513 /*
4514 Composite any children in back-to-front order.
4515 */
4516 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4517 &x_offset,&y_offset,&child);
4518 x_offset-=(int) crop_info.x;
4519 if (x_offset < 0)
4520 x_offset=0;
4521 y_offset-=(int) crop_info.y;
4522 if (y_offset < 0)
4523 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004524 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
cristye941a752011-10-15 01:52:48 +00004525 x_offset,(ssize_t) y_offset,exception);
cristy3ed852e2009-09-05 21:47:34 +00004526 }
4527 /*
4528 Relinquish resources.
4529 */
4530 while (colormap_info != (ColormapInfo *) NULL)
4531 {
4532 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004533 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4534 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004535 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4536 colormap_info=next;
4537 }
4538 /*
4539 Relinquish resources and restore initial state.
4540 */
4541 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4542 max_windows=0;
4543 number_windows=0;
4544 colormap_info=(ColormapInfo *) NULL;
4545 return(image);
4546 }
4547 return((Image *) NULL);
4548}
4549
4550/*
4551%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4552% %
4553% %
4554% %
4555% X G e t W i n d o w I n f o %
4556% %
4557% %
4558% %
4559%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4560%
4561% XGetWindowInfo() initializes the XWindowInfo structure.
4562%
4563% The format of the XGetWindowInfo method is:
4564%
4565% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4566% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4567% XResourceInfo *resource_info,XWindowInfo *window)
4568% resource_info,window)
4569%
4570% A description of each parameter follows:
4571%
4572% o display: Specifies a connection to an X server; returned from
4573% XOpenDisplay.
4574%
4575% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4576% returned from XGetVisualInfo.
4577%
4578% o map_info: If map_type is specified, this structure is initialized
4579% with info from the Standard Colormap.
4580%
4581% o pixel: Specifies a pointer to a XPixelInfo structure.
4582%
4583% o font_info: Specifies a pointer to a XFontStruct structure.
4584%
4585% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4586%
4587*/
cristybcbda3f2011-09-03 13:01:22 +00004588MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004589 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4590 XResourceInfo *resource_info,XWindowInfo *window)
4591{
4592 /*
4593 Initialize window info.
4594 */
4595 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4596 assert(display != (Display *) NULL);
4597 assert(visual_info != (XVisualInfo *) NULL);
4598 assert(map_info != (XStandardColormap *) NULL);
4599 assert(pixel != (XPixelInfo *) NULL);
4600 assert(resource_info != (XResourceInfo *) NULL);
4601 assert(window != (XWindowInfo *) NULL);
4602 if (window->id != (Window) NULL)
4603 {
4604 if (window->cursor != (Cursor) NULL)
4605 (void) XFreeCursor(display,window->cursor);
4606 if (window->busy_cursor != (Cursor) NULL)
4607 (void) XFreeCursor(display,window->busy_cursor);
4608 if (window->highlight_stipple != (Pixmap) NULL)
4609 (void) XFreePixmap(display,window->highlight_stipple);
4610 if (window->shadow_stipple != (Pixmap) NULL)
4611 (void) XFreePixmap(display,window->shadow_stipple);
4612 if (window->name == (char *) NULL)
4613 window->name=AcquireString("");
4614 if (window->icon_name == (char *) NULL)
4615 window->icon_name=AcquireString("");
4616 }
4617 else
4618 {
4619 /*
4620 Initialize these attributes just once.
4621 */
4622 window->id=(Window) NULL;
4623 if (window->name == (char *) NULL)
4624 window->name=AcquireString("");
4625 if (window->icon_name == (char *) NULL)
4626 window->icon_name=AcquireString("");
4627 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4628 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4629 window->ximage=(XImage *) NULL;
4630 window->matte_image=(XImage *) NULL;
4631 window->pixmap=(Pixmap) NULL;
4632 window->matte_pixmap=(Pixmap) NULL;
4633 window->mapped=MagickFalse;
4634 window->stasis=MagickFalse;
4635 window->shared_memory=MagickTrue;
4636 window->segment_info=(void *) NULL;
4637#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4638 {
4639 XShmSegmentInfo
4640 *segment_info;
4641
4642 if (window->segment_info == (void *) NULL)
4643 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4644 segment_info=(XShmSegmentInfo *) window->segment_info;
4645 segment_info[0].shmid=(-1);
4646 segment_info[0].shmaddr=(char *) NULL;
4647 segment_info[1].shmid=(-1);
4648 segment_info[1].shmaddr=(char *) NULL;
4649 }
4650#endif
4651 }
4652 /*
4653 Initialize these attributes every time function is called.
4654 */
4655 window->screen=visual_info->screen;
4656 window->root=XRootWindow(display,visual_info->screen);
4657 window->visual=visual_info->visual;
4658 window->storage_class=(unsigned int) visual_info->klass;
4659 window->depth=(unsigned int) visual_info->depth;
4660 window->visual_info=visual_info;
4661 window->map_info=map_info;
4662 window->pixel_info=pixel;
4663 window->font_info=font_info;
4664 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4665 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4666 window->geometry=(char *) NULL;
4667 window->icon_geometry=(char *) NULL;
4668 if (resource_info->icon_geometry != (char *) NULL)
4669 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4670 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004671 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004672 window->width=1;
4673 window->height=1;
4674 window->min_width=1;
4675 window->min_height=1;
4676 window->width_inc=1;
4677 window->height_inc=1;
4678 window->border_width=resource_info->border_width;
4679 window->annotate_context=pixel->annotate_context;
4680 window->highlight_context=pixel->highlight_context;
4681 window->widget_context=pixel->widget_context;
4682 window->shadow_stipple=(Pixmap) NULL;
4683 window->highlight_stipple=(Pixmap) NULL;
4684 window->use_pixmap=MagickTrue;
4685 window->immutable=MagickFalse;
4686 window->shape=MagickFalse;
4687 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004688 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004689 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4690 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4691 window->attributes.background_pixel=pixel->background_color.pixel;
4692 window->attributes.background_pixmap=(Pixmap) NULL;
4693 window->attributes.bit_gravity=ForgetGravity;
4694 window->attributes.backing_store=WhenMapped;
4695 window->attributes.save_under=MagickTrue;
4696 window->attributes.border_pixel=pixel->border_color.pixel;
4697 window->attributes.colormap=map_info->colormap;
4698 window->attributes.cursor=window->cursor;
4699 window->attributes.do_not_propagate_mask=NoEventMask;
4700 window->attributes.event_mask=NoEventMask;
4701 window->attributes.override_redirect=MagickFalse;
4702 window->attributes.win_gravity=NorthWestGravity;
4703 window->orphan=MagickFalse;
4704}
4705
4706/*
4707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4708% %
4709% %
4710% %
4711% X H i g h l i g h t E l l i p s e %
4712% %
4713% %
4714% %
4715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4716%
4717% XHighlightEllipse() puts a border on the X server around a region defined by
4718% highlight_info.
4719%
4720% The format of the XHighlightEllipse method is:
4721%
4722% void XHighlightEllipse(Display *display,Window window,
4723% GC annotate_context,const RectangleInfo *highlight_info)
4724%
4725% A description of each parameter follows:
4726%
4727% o display: Specifies a connection to an X server; returned from
4728% XOpenDisplay.
4729%
4730% o window: Specifies a pointer to a Window structure.
4731%
4732% o annotate_context: Specifies a pointer to a GC structure.
4733%
4734% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4735% contains the extents of any highlighting rectangle.
4736%
4737*/
cristybcbda3f2011-09-03 13:01:22 +00004738MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004739 GC annotate_context,const RectangleInfo *highlight_info)
4740{
4741 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4742 assert(display != (Display *) NULL);
4743 assert(window != (Window) NULL);
4744 assert(annotate_context != (GC) NULL);
4745 assert(highlight_info != (RectangleInfo *) NULL);
4746 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4747 return;
4748 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4749 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4750 (unsigned int) highlight_info->height-1,0,360*64);
4751 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4752 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4753 (unsigned int) highlight_info->height-3,0,360*64);
4754}
4755
4756/*
4757%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4758% %
4759% %
4760% %
4761% X H i g h l i g h t L i n e %
4762% %
4763% %
4764% %
4765%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4766%
4767% XHighlightLine() puts a border on the X server around a region defined by
4768% highlight_info.
4769%
4770% The format of the XHighlightLine method is:
4771%
4772% void XHighlightLine(Display *display,Window window,GC annotate_context,
4773% const XSegment *highlight_info)
4774%
4775% A description of each parameter follows:
4776%
4777% o display: Specifies a connection to an X server; returned from
4778% XOpenDisplay.
4779%
4780% o window: Specifies a pointer to a Window structure.
4781%
4782% o annotate_context: Specifies a pointer to a GC structure.
4783%
4784% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4785% contains the extents of any highlighting rectangle.
4786%
4787*/
cristybcbda3f2011-09-03 13:01:22 +00004788MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004789 GC annotate_context,const XSegment *highlight_info)
4790{
4791 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4792 assert(display != (Display *) NULL);
4793 assert(window != (Window) NULL);
4794 assert(annotate_context != (GC) NULL);
4795 assert(highlight_info != (XSegment *) NULL);
4796 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4797 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4798}
4799
4800/*
4801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4802% %
4803% %
4804% %
4805% X H i g h l i g h t R e c t a n g l e %
4806% %
4807% %
4808% %
4809%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4810%
4811% XHighlightRectangle() puts a border on the X server around a region defined
4812% by highlight_info.
4813%
4814% The format of the XHighlightRectangle method is:
4815%
4816% void XHighlightRectangle(Display *display,Window window,
4817% GC annotate_context,const RectangleInfo *highlight_info)
4818%
4819% A description of each parameter follows:
4820%
4821% o display: Specifies a connection to an X server; returned from
4822% XOpenDisplay.
4823%
4824% o window: Specifies a pointer to a Window structure.
4825%
4826% o annotate_context: Specifies a pointer to a GC structure.
4827%
4828% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4829% contains the extents of any highlighting rectangle.
4830%
4831*/
cristybcbda3f2011-09-03 13:01:22 +00004832MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004833 GC annotate_context,const RectangleInfo *highlight_info)
4834{
4835 assert(display != (Display *) NULL);
4836 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4837 assert(window != (Window) NULL);
4838 assert(annotate_context != (GC) NULL);
4839 assert(highlight_info != (RectangleInfo *) NULL);
4840 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4841 return;
4842 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4843 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4844 (unsigned int) highlight_info->height-1);
4845 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4846 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4847 (unsigned int) highlight_info->height-3);
4848}
4849
4850/*
4851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4852% %
4853% %
4854% %
4855% X I m p o r t I m a g e %
4856% %
4857% %
4858% %
4859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4860%
4861% XImportImage() reads an image from an X window.
4862%
4863% The format of the XImportImage method is:
4864%
4865% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4866%
4867% A description of each parameter follows:
4868%
4869% o image_info: the image info.
4870%
4871% o ximage_info: Specifies a pointer to an XImportInfo structure.
4872%
4873*/
4874MagickExport Image *XImportImage(const ImageInfo *image_info,
4875 XImportInfo *ximage_info)
4876{
4877 Colormap
4878 *colormaps;
4879
4880 Display
4881 *display;
4882
4883 Image
4884 *image;
4885
4886 int
4887 number_colormaps,
4888 number_windows,
4889 x;
4890
4891 RectangleInfo
4892 crop_info;
4893
4894 Status
4895 status;
4896
4897 Window
4898 *children,
4899 client,
4900 prior_target,
4901 root,
4902 target;
4903
4904 XTextProperty
4905 window_name;
4906
4907 /*
4908 Open X server connection.
4909 */
4910 assert(image_info != (const ImageInfo *) NULL);
4911 assert(image_info->signature == MagickSignature);
4912 if (image_info->debug != MagickFalse)
4913 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4914 image_info->filename);
4915 assert(ximage_info != (XImportInfo *) NULL);
4916 display=XOpenDisplay(image_info->server_name);
4917 if (display == (Display *) NULL)
4918 {
4919 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4920 XDisplayName(image_info->server_name));
4921 return((Image *) NULL);
4922 }
4923 /*
4924 Set our forgiving exception handler.
4925 */
4926 (void) XSetErrorHandler(XError);
4927 /*
4928 Select target window.
4929 */
4930 crop_info.x=0;
4931 crop_info.y=0;
4932 crop_info.width=0;
4933 crop_info.height=0;
4934 root=XRootWindow(display,XDefaultScreen(display));
4935 target=(Window) NULL;
4936 if ((image_info->filename != (char *) NULL) &&
4937 (*image_info->filename != '\0'))
4938 {
4939 if (LocaleCompare(image_info->filename,"root") == 0)
4940 target=root;
4941 else
4942 {
4943 /*
4944 Select window by ID or name.
4945 */
4946 if (isdigit((unsigned char) *image_info->filename) != 0)
4947 target=XWindowByID(display,root,(Window)
4948 strtol(image_info->filename,(char **) NULL,0));
4949 if (target == (Window) NULL)
4950 target=XWindowByName(display,root,image_info->filename);
4951 if (target == (Window) NULL)
4952 ThrowXWindowFatalException(XServerError,
4953 "NoWindowWithSpecifiedIDExists",image_info->filename);
4954 }
4955 }
4956 /*
4957 If target window is not defined, interactively select one.
4958 */
4959 prior_target=target;
4960 if (target == (Window) NULL)
4961 target=XSelectWindow(display,&crop_info);
4962 if (target == (Window) NULL)
4963 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4964 image_info->filename);
4965 client=target; /* obsolete */
4966 if (target != root)
4967 {
4968 unsigned int
4969 d;
4970
4971 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4972 if (status != False)
4973 {
4974 for ( ; ; )
4975 {
4976 Window
4977 parent;
4978
4979 /*
4980 Find window manager frame.
4981 */
4982 status=XQueryTree(display,target,&root,&parent,&children,&d);
4983 if ((status != False) && (children != (Window *) NULL))
4984 (void) XFree((char *) children);
4985 if ((status == False) || (parent == (Window) NULL) ||
4986 (parent == root))
4987 break;
4988 target=parent;
4989 }
4990 /*
4991 Get client window.
4992 */
4993 client=XClientWindow(display,target);
4994 if (ximage_info->frame == MagickFalse)
4995 target=client;
4996 if ((ximage_info->frame == MagickFalse) &&
4997 (prior_target != MagickFalse))
4998 target=prior_target;
4999 XDelay(display,SuspendTime << 4);
5000 }
5001 }
5002 if (ximage_info->screen)
5003 {
5004 int
5005 y;
5006
5007 Window
5008 child;
5009
5010 XWindowAttributes
5011 window_attributes;
5012
5013 /*
5014 Obtain window image directly from screen.
5015 */
5016 status=XGetWindowAttributes(display,target,&window_attributes);
5017 if (status == False)
5018 {
5019 ThrowXWindowFatalException(XServerError,
5020 "UnableToReadXWindowAttributes",image_info->filename);
5021 (void) XCloseDisplay(display);
5022 return((Image *) NULL);
5023 }
5024 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005025 crop_info.x=(ssize_t) x;
5026 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005027 crop_info.width=(size_t) window_attributes.width;
5028 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005029 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005030 {
5031 /*
5032 Include border in image.
5033 */
5034 crop_info.x-=window_attributes.border_width;
5035 crop_info.y-=window_attributes.border_width;
5036 crop_info.width+=window_attributes.border_width << 1;
5037 crop_info.height+=window_attributes.border_width << 1;
5038 }
5039 target=root;
5040 }
5041 /*
5042 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5043 */
5044 number_windows=0;
5045 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5046 if ((status == True) && (number_windows > 0))
5047 {
5048 ximage_info->descend=MagickTrue;
5049 (void) XFree ((char *) children);
5050 }
5051 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5052 if (number_colormaps > 0)
5053 {
5054 if (number_colormaps > 1)
5055 ximage_info->descend=MagickTrue;
5056 (void) XFree((char *) colormaps);
5057 }
5058 /*
5059 Alert the user not to alter the screen.
5060 */
5061 if (ximage_info->silent == MagickFalse)
5062 (void) XBell(display,0);
5063 /*
5064 Get image by window id.
5065 */
5066 (void) XGrabServer(display);
5067 image=XGetWindowImage(display,target,ximage_info->borders,
5068 ximage_info->descend ? 1U : 0U);
5069 (void) XUngrabServer(display);
5070 if (image == (Image *) NULL)
5071 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5072 image_info->filename)
5073 else
5074 {
5075 (void) CopyMagickString(image->filename,image_info->filename,
5076 MaxTextExtent);
5077 if ((crop_info.width != 0) && (crop_info.height != 0))
5078 {
5079 Image
5080 *clone_image,
5081 *crop_image;
5082
5083 /*
5084 Crop image as defined by the cropping rectangle.
5085 */
5086 clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5087 if (clone_image != (Image *) NULL)
5088 {
5089 crop_image=CropImage(clone_image,&crop_info,&image->exception);
5090 if (crop_image != (Image *) NULL)
5091 {
5092 image=DestroyImage(image);
5093 image=crop_image;
5094 }
5095 }
5096 }
5097 status=XGetWMName(display,target,&window_name);
5098 if (status == True)
5099 {
5100 if ((image_info->filename != (char *) NULL) &&
5101 (*image_info->filename == '\0'))
5102 (void) CopyMagickString(image->filename,(char *) window_name.value,
5103 (size_t) window_name.nitems+1);
5104 (void) XFree((void *) window_name.value);
5105 }
5106 }
5107 if (ximage_info->silent == MagickFalse)
5108 {
5109 /*
5110 Alert the user we're done.
5111 */
5112 (void) XBell(display,0);
5113 (void) XBell(display,0);
5114 }
5115 (void) XCloseDisplay(display);
5116 return(image);
5117}
5118
5119/*
5120%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5121% %
5122% %
5123% %
5124% X I n i t i a l i z e W i n d o w s %
5125% %
5126% %
5127% %
5128%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5129%
5130% XInitializeWindows() initializes the XWindows structure.
5131%
5132% The format of the XInitializeWindows method is:
5133%
5134% XWindows *XInitializeWindows(Display *display,
5135% XResourceInfo *resource_info)
5136%
5137% A description of each parameter follows:
5138%
5139% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5140%
5141% o display: Specifies a connection to an X server; returned from
5142% XOpenDisplay.
5143%
5144% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5145%
5146*/
cristybcbda3f2011-09-03 13:01:22 +00005147MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005148 XResourceInfo *resource_info)
5149{
5150 Window
5151 root_window;
5152
5153 XWindows
5154 *windows;
5155
5156 /*
5157 Allocate windows structure.
5158 */
cristy73bd4a52010-10-05 11:24:23 +00005159 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005160 if (windows == (XWindows *) NULL)
5161 {
5162 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5163 "...");
5164 return((XWindows *) NULL);
5165 }
5166 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5167 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5168 sizeof(*windows->pixel_info));
5169 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5170 sizeof(*windows->icon_pixel));
5171 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5172 sizeof(*windows->icon_resources));
5173 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5174 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5175 (windows->icon_resources == (XResourceInfo *) NULL))
5176 {
5177 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5178 "...");
5179 return((XWindows *) NULL);
5180 }
5181 /*
5182 Initialize windows structure.
5183 */
5184 windows->display=display;
5185 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5186 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5187 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5188 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5189 windows->im_remote_command=
5190 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5191 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5192 windows->im_update_colormap=
5193 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5194 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5195 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5196 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5197 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5198 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005199#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005200 (void) XSynchronize(display,IsWindows95());
5201#endif
5202 if (IsEventLogging())
5203 {
5204 (void) XSynchronize(display,MagickTrue);
5205 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005206 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005207 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5208 (void) LogMagickEvent(X11Event,GetMagickModule(),
5209 " Window Manager: 0x%lx",windows->wm_protocols);
5210 (void) LogMagickEvent(X11Event,GetMagickModule(),
5211 " delete window: 0x%lx",windows->wm_delete_window);
5212 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5213 windows->wm_take_focus);
5214 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5215 windows->im_protocols);
5216 (void) LogMagickEvent(X11Event,GetMagickModule(),
5217 " remote command: 0x%lx",windows->im_remote_command);
5218 (void) LogMagickEvent(X11Event,GetMagickModule(),
5219 " update widget: 0x%lx",windows->im_update_widget);
5220 (void) LogMagickEvent(X11Event,GetMagickModule(),
5221 " update colormap: 0x%lx",windows->im_update_colormap);
5222 (void) LogMagickEvent(X11Event,GetMagickModule(),
5223 " former image: 0x%lx",windows->im_former_image);
5224 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5225 windows->im_next_image);
5226 (void) LogMagickEvent(X11Event,GetMagickModule(),
5227 " retain colors: 0x%lx",windows->im_retain_colors);
5228 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5229 windows->im_exit);
5230 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5231 windows->dnd_protocols);
5232 }
5233 /*
5234 Allocate standard colormap.
5235 */
5236 windows->map_info=XAllocStandardColormap();
5237 windows->icon_map=XAllocStandardColormap();
5238 if ((windows->map_info == (XStandardColormap *) NULL) ||
5239 (windows->icon_map == (XStandardColormap *) NULL))
5240 ThrowXWindowFatalException(ResourceLimitFatalError,
5241 "MemoryAllocationFailed","...");
5242 windows->map_info->colormap=(Colormap) NULL;
5243 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005244 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005245 windows->pixel_info->annotate_context=(GC) NULL;
5246 windows->pixel_info->highlight_context=(GC) NULL;
5247 windows->pixel_info->widget_context=(GC) NULL;
5248 windows->font_info=(XFontStruct *) NULL;
5249 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005250 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005251 /*
5252 Allocate visual.
5253 */
5254 *windows->icon_resources=(*resource_info);
5255 windows->icon_resources->visual_type=(char *) "default";
5256 windows->icon_resources->colormap=SharedColormap;
5257 windows->visual_info=
5258 XBestVisualInfo(display,windows->map_info,resource_info);
5259 windows->icon_visual=
5260 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5261 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5262 (windows->icon_visual == (XVisualInfo *) NULL))
5263 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5264 resource_info->visual_type);
5265 if (IsEventLogging())
5266 {
5267 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5268 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5269 windows->visual_info->visualid);
5270 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5271 XVisualClassName(windows->visual_info->klass));
5272 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5273 windows->visual_info->depth);
5274 (void) LogMagickEvent(X11Event,GetMagickModule(),
5275 " size of colormap: %d entries",windows->visual_info->colormap_size);
5276 (void) LogMagickEvent(X11Event,GetMagickModule(),
5277 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5278 windows->visual_info->red_mask,windows->visual_info->green_mask,
5279 windows->visual_info->blue_mask);
5280 (void) LogMagickEvent(X11Event,GetMagickModule(),
5281 " significant bits in color: %d bits",
5282 windows->visual_info->bits_per_rgb);
5283 }
5284 /*
5285 Allocate class and manager hints.
5286 */
5287 windows->class_hints=XAllocClassHint();
5288 windows->manager_hints=XAllocWMHints();
5289 if ((windows->class_hints == (XClassHint *) NULL) ||
5290 (windows->manager_hints == (XWMHints *) NULL))
5291 ThrowXWindowFatalException(ResourceLimitFatalError,
5292 "MemoryAllocationFailed","...");
5293 /*
5294 Determine group leader if we have one.
5295 */
5296 root_window=XRootWindow(display,windows->visual_info->screen);
5297 windows->group_leader.id=(Window) NULL;
5298 if (resource_info->window_group != (char *) NULL)
5299 {
5300 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5301 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5302 strtol((char *) resource_info->window_group,(char **) NULL,0));
5303 if (windows->group_leader.id == (Window) NULL)
5304 windows->group_leader.id=
5305 XWindowByName(display,root_window,resource_info->window_group);
5306 }
5307 return(windows);
5308}
5309
5310/*
5311%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5312% %
5313% %
5314% %
5315% X M a k e C u r s o r %
5316% %
5317% %
5318% %
5319%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5320%
5321% XMakeCursor() creates a crosshairs X11 cursor.
5322%
5323% The format of the XMakeCursor method is:
5324%
5325% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5326% char *background_color,char *foreground_color)
5327%
5328% A description of each parameter follows:
5329%
5330% o display: Specifies a connection to an X server; returned from
5331% XOpenDisplay.
5332%
5333% o window: Specifies the ID of the window for which the cursor is
5334% assigned.
5335%
5336% o colormap: Specifies the ID of the colormap from which the background
5337% and foreground color will be retrieved.
5338%
5339% o background_color: Specifies the color to use for the cursor background.
5340%
5341% o foreground_color: Specifies the color to use for the cursor foreground.
5342%
5343*/
cristybcbda3f2011-09-03 13:01:22 +00005344MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005345 Colormap colormap,char *background_color,char *foreground_color)
5346{
5347#define scope_height 17
5348#define scope_x_hot 8
5349#define scope_y_hot 8
5350#define scope_width 17
5351
5352 static const unsigned char
5353 scope_bits[] =
5354 {
5355 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5356 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5357 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5358 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5359 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5360 },
5361 scope_mask_bits[] =
5362 {
5363 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5364 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5365 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5366 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5367 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5368 };
5369
5370 Cursor
5371 cursor;
5372
5373 Pixmap
5374 mask,
5375 source;
5376
5377 XColor
5378 background,
5379 foreground;
5380
5381 assert(display != (Display *) NULL);
5382 assert(window != (Window) NULL);
5383 assert(colormap != (Colormap) NULL);
5384 assert(background_color != (char *) NULL);
5385 assert(foreground_color != (char *) NULL);
5386 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5387 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5388 scope_height);
5389 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5390 scope_width,scope_height);
5391 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5392 {
5393 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5394 return((Cursor) NULL);
5395 }
5396 (void) XParseColor(display,colormap,background_color,&background);
5397 (void) XParseColor(display,colormap,foreground_color,&foreground);
5398 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5399 scope_x_hot,scope_y_hot);
5400 (void) XFreePixmap(display,source);
5401 (void) XFreePixmap(display,mask);
5402 return(cursor);
5403}
5404
5405/*
5406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5407% %
5408% %
5409% %
5410% X M a k e I m a g e %
5411% %
5412% %
5413% %
5414%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5415%
5416% XMakeImage() creates an X11 image. If the image size differs from the X11
5417% image size, the image is first resized.
5418%
5419% The format of the XMakeImage method is:
5420%
5421% MagickBooleanType XMakeImage(Display *display,
5422% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005423% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005424%
5425% A description of each parameter follows:
5426%
5427% o display: Specifies a connection to an X server; returned from
5428% XOpenDisplay.
5429%
5430% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5431%
5432% o window: Specifies a pointer to a XWindowInfo structure.
5433%
5434% o image: the image.
5435%
5436% o width: Specifies the width in pixels of the rectangular area to
5437% display.
5438%
5439% o height: Specifies the height in pixels of the rectangular area to
5440% display.
5441%
cristy051718b2011-08-28 22:49:25 +00005442% o exception: return any errors or warnings in this structure.
5443%
cristy3ed852e2009-09-05 21:47:34 +00005444*/
cristybcbda3f2011-09-03 13:01:22 +00005445MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005446 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005447 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005448{
5449#define CheckOverflowException(length,width,height) \
5450 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5451
5452 int
5453 depth,
5454 format;
5455
5456 size_t
5457 length;
5458
5459 XImage
5460 *matte_image,
5461 *ximage;
5462
5463 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5464 assert(display != (Display *) NULL);
5465 assert(resource_info != (XResourceInfo *) NULL);
5466 assert(window != (XWindowInfo *) NULL);
5467 assert(width != 0);
5468 assert(height != 0);
5469 if ((window->width == 0) || (window->height == 0))
5470 return(MagickFalse);
5471 /*
5472 Apply user transforms to the image.
5473 */
5474 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5475 (void) XFlush(display);
5476 depth=(int) window->depth;
5477 if (window->destroy)
5478 window->image=DestroyImage(window->image);
5479 window->image=image;
5480 window->destroy=MagickFalse;
5481 if (window->image != (Image *) NULL)
5482 {
5483 if (window->crop_geometry != (char *) NULL)
5484 {
5485 Image
5486 *crop_image;
5487
5488 RectangleInfo
5489 crop_info;
5490
5491 /*
5492 Crop image.
5493 */
5494 window->image->page.x=0;
5495 window->image->page.y=0;
5496 (void) ParsePageGeometry(window->image,window->crop_geometry,
5497 &crop_info,&image->exception);
5498 crop_image=CropImage(window->image,&crop_info,&image->exception);
5499 if (crop_image != (Image *) NULL)
5500 {
5501 if (window->image != image)
5502 window->image=DestroyImage(window->image);
5503 window->image=crop_image;
5504 window->destroy=MagickTrue;
5505 }
5506 }
5507 if ((width != (unsigned int) window->image->columns) ||
5508 (height != (unsigned int) window->image->rows))
5509 {
5510 Image
5511 *resize_image;
5512
5513 /*
5514 Resize image.
5515 */
5516 resize_image=NewImageList();
5517 if (window->pixel_info->colors != 0)
5518 resize_image=SampleImage(window->image,width,height,
5519 &image->exception);
5520 else
5521 resize_image=ThumbnailImage(window->image,width,height,
5522 &image->exception);
5523 if (resize_image != (Image *) NULL)
5524 {
5525 if (window->image != image)
5526 window->image=DestroyImage(window->image);
5527 window->image=resize_image;
5528 window->destroy=MagickTrue;
5529 }
5530 }
5531 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005532 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005533 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005534 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005535 }
5536 /*
5537 Create X image.
5538 */
5539 ximage=(XImage *) NULL;
5540 format=(depth == 1) ? XYBitmap : ZPixmap;
5541#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5542 if (window->shared_memory != MagickFalse)
5543 {
5544 XShmSegmentInfo
5545 *segment_info;
5546
5547 segment_info=(XShmSegmentInfo *) window->segment_info;
5548 segment_info[1].shmid=(-1);
5549 segment_info[1].shmaddr=(char *) NULL;
5550 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5551 (char *) NULL,&segment_info[1],width,height);
5552 if (ximage == (XImage *) NULL)
5553 window->shared_memory=MagickFalse;
5554 length=(size_t) ximage->bytes_per_line*ximage->height;
5555 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5556 window->shared_memory=MagickFalse;
5557 if (window->shared_memory != MagickFalse)
5558 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5559 if (window->shared_memory != MagickFalse)
5560 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5561 if (segment_info[1].shmid < 0)
5562 window->shared_memory=MagickFalse;
5563 if (window->shared_memory != MagickFalse)
5564 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5565 else
5566 {
5567 if (ximage != (XImage *) NULL)
5568 XDestroyImage(ximage);
5569 ximage=(XImage *) NULL;
5570 if (segment_info[1].shmaddr)
5571 {
5572 (void) shmdt(segment_info[1].shmaddr);
5573 segment_info[1].shmaddr=(char *) NULL;
5574 }
5575 if (segment_info[1].shmid >= 0)
5576 {
5577 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5578 segment_info[1].shmid=(-1);
5579 }
5580 }
5581 }
5582#endif
5583 /*
5584 Allocate X image pixel data.
5585 */
5586#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5587 if (window->shared_memory)
5588 {
5589 Status
5590 status;
5591
5592 XShmSegmentInfo
5593 *segment_info;
5594
5595 (void) XSync(display,MagickFalse);
5596 xerror_alert=MagickFalse;
5597 segment_info=(XShmSegmentInfo *) window->segment_info;
5598 ximage->data=segment_info[1].shmaddr;
5599 segment_info[1].readOnly=MagickFalse;
5600 status=XShmAttach(display,&segment_info[1]);
5601 if (status != False)
5602 (void) XSync(display,MagickFalse);
5603 if ((status == False) || (xerror_alert != MagickFalse))
5604 {
5605 window->shared_memory=MagickFalse;
5606 if (status != False)
5607 XShmDetach(display,&segment_info[1]);
5608 if (ximage != (XImage *) NULL)
5609 {
5610 ximage->data=NULL;
5611 XDestroyImage(ximage);
5612 ximage=(XImage *) NULL;
5613 }
5614 if (segment_info[1].shmid >= 0)
5615 {
5616 if (segment_info[1].shmaddr != NULL)
5617 (void) shmdt(segment_info[1].shmaddr);
5618 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5619 segment_info[1].shmid=(-1);
5620 segment_info[1].shmaddr=(char *) NULL;
5621 }
5622 }
5623 }
5624#endif
5625 if (window->shared_memory == MagickFalse)
5626 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5627 (char *) NULL,width,height,XBitmapPad(display),0);
5628 if (ximage == (XImage *) NULL)
5629 {
5630 /*
5631 Unable to create X image.
5632 */
5633 (void) XCheckDefineCursor(display,window->id,window->cursor);
5634 return(MagickFalse);
5635 }
5636 length=(size_t) ximage->bytes_per_line*ximage->height;
5637 if (IsEventLogging())
5638 {
5639 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5640 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5641 ximage->width,ximage->height);
5642 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5643 ximage->format);
5644 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5645 ximage->byte_order);
5646 (void) LogMagickEvent(X11Event,GetMagickModule(),
5647 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5648 ximage->bitmap_bit_order,ximage->bitmap_pad);
5649 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5650 ximage->depth);
5651 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5652 ximage->bytes_per_line);
5653 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5654 ximage->bits_per_pixel);
5655 (void) LogMagickEvent(X11Event,GetMagickModule(),
5656 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5657 ximage->green_mask,ximage->blue_mask);
5658 }
5659 if (window->shared_memory == MagickFalse)
5660 {
5661 if (ximage->format != XYBitmap)
5662 ximage->data=(char *) AcquireQuantumMemory((size_t)
5663 ximage->bytes_per_line,(size_t) ximage->height);
5664 else
5665 ximage->data=(char *) AcquireQuantumMemory((size_t)
5666 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5667 }
5668 if (ximage->data == (char *) NULL)
5669 {
5670 /*
5671 Unable to allocate pixel data.
5672 */
5673 XDestroyImage(ximage);
5674 ximage=(XImage *) NULL;
5675 (void) XCheckDefineCursor(display,window->id,window->cursor);
5676 return(MagickFalse);
5677 }
5678 if (window->ximage != (XImage *) NULL)
5679 {
5680 /*
5681 Destroy previous X image.
5682 */
5683 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5684#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5685 if (window->segment_info != (XShmSegmentInfo *) NULL)
5686 {
5687 XShmSegmentInfo
5688 *segment_info;
5689
5690 segment_info=(XShmSegmentInfo *) window->segment_info;
5691 if (segment_info[0].shmid >= 0)
5692 {
5693 (void) XSync(display,MagickFalse);
5694 (void) XShmDetach(display,&segment_info[0]);
5695 (void) XSync(display,MagickFalse);
5696 if (segment_info[0].shmaddr != (char *) NULL)
5697 (void) shmdt(segment_info[0].shmaddr);
5698 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5699 segment_info[0].shmid=(-1);
5700 segment_info[0].shmaddr=(char *) NULL;
5701 window->ximage->data=(char *) NULL;
5702 }
5703 }
5704#endif
5705 if (window->ximage->data != (char *) NULL)
5706 free(window->ximage->data);
5707 window->ximage->data=(char *) NULL;
5708 XDestroyImage(window->ximage);
5709 window->ximage=(XImage *) NULL;
5710 }
5711#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5712 if (window->segment_info != (XShmSegmentInfo *) NULL)
5713 {
5714 XShmSegmentInfo
5715 *segment_info;
5716
5717 segment_info=(XShmSegmentInfo *) window->segment_info;
5718 segment_info[0]=segment_info[1];
5719 }
5720#endif
5721 window->ximage=ximage;
5722 matte_image=(XImage *) NULL;
5723 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5724 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005725 ((int) width <= XDisplayWidth(display,window->screen)) &&
5726 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005727 {
5728 /*
5729 Create matte image.
5730 */
5731 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5732 (char *) NULL,width,height,XBitmapPad(display),0);
5733 if (IsEventLogging())
5734 {
5735 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5736 (void) LogMagickEvent(X11Event,GetMagickModule(),
5737 " width, height: %dx%d",matte_image->width,matte_image->height);
5738 }
5739 if (matte_image != (XImage *) NULL)
5740 {
5741 /*
5742 Allocate matte image pixel data.
5743 */
5744 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5745 matte_image->bytes_per_line*matte_image->depth,
5746 (size_t) matte_image->height);
5747 if (matte_image->data == (char *) NULL)
5748 {
5749 XDestroyImage(matte_image);
5750 matte_image=(XImage *) NULL;
5751 }
5752 }
5753 }
5754 if (window->matte_image != (XImage *) NULL)
5755 {
5756 /*
5757 Free matte image.
5758 */
5759 if (window->matte_image->data != (char *) NULL)
5760 free(window->matte_image->data);
5761 window->matte_image->data=(char *) NULL;
5762 XDestroyImage(window->matte_image);
5763 window->matte_image=(XImage *) NULL;
5764 }
5765 window->matte_image=matte_image;
5766 if (window->matte_pixmap != (Pixmap) NULL)
5767 {
5768 (void) XFreePixmap(display,window->matte_pixmap);
5769 window->matte_pixmap=(Pixmap) NULL;
5770#if defined(MAGICKCORE_HAVE_SHAPE)
5771 if (window->shape != MagickFalse)
5772 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5773#endif
5774 }
5775 window->stasis=MagickFalse;
5776 /*
5777 Convert pixels to X image data.
5778 */
5779 if (window->image != (Image *) NULL)
5780 {
5781 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5782 (ximage->bitmap_bit_order == LSBFirst)))
5783 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005784 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005785 else
5786 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005787 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005788 }
5789 if (window->matte_image != (XImage *) NULL)
5790 {
5791 /*
5792 Create matte pixmap.
5793 */
5794 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5795 if (window->matte_pixmap != (Pixmap) NULL)
5796 {
5797 GC
5798 graphics_context;
5799
5800 XGCValues
5801 context_values;
5802
5803 /*
5804 Copy matte image to matte pixmap.
5805 */
cristy4c08aed2011-07-01 19:47:50 +00005806 context_values.background=0;
5807 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005808 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005809 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005810 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5811 window->matte_image,0,0,0,0,width,height);
5812 (void) XFreeGC(display,graphics_context);
5813#if defined(MAGICKCORE_HAVE_SHAPE)
5814 if (window->shape != MagickFalse)
5815 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5816 window->matte_pixmap,ShapeSet);
5817#endif
5818 }
5819 }
5820 (void) XMakePixmap(display,resource_info,window);
5821 /*
5822 Restore cursor.
5823 */
5824 (void) XCheckDefineCursor(display,window->id,window->cursor);
5825 return(MagickTrue);
5826}
5827
5828/*
5829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5830% %
5831% %
5832% %
5833+ X M a k e I m a g e L S B F i r s t %
5834% %
5835% %
5836% %
5837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5838%
5839% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5840% pixels are copied in least-significant bit and byte first order. The
5841% server's scanline pad is respected. Rather than using one or two general
5842% cases, many special cases are found here to help speed up the image
5843% conversion.
5844%
5845% The format of the XMakeImageLSBFirst method is:
5846%
cristye941a752011-10-15 01:52:48 +00005847% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5848% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005849%
5850% A description of each parameter follows:
5851%
5852% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5853%
5854% o window: Specifies a pointer to a XWindowInfo structure.
5855%
5856% o image: the image.
5857%
5858% o ximage: Specifies a pointer to a XImage structure; returned from
5859% XCreateImage.
5860%
5861% o matte_image: Specifies a pointer to a XImage structure; returned from
5862% XCreateImage.
5863%
cristye941a752011-10-15 01:52:48 +00005864% o exception: return any errors or warnings in this structure.
5865%
cristy3ed852e2009-09-05 21:47:34 +00005866*/
5867static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005868 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5869 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005870{
cristyc57f6942010-11-12 01:47:39 +00005871 CacheView
5872 *canvas_view;
5873
cristy3ed852e2009-09-05 21:47:34 +00005874 Image
5875 *canvas;
5876
5877 int
5878 y;
5879
cristy4c08aed2011-07-01 19:47:50 +00005880 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005881 *p;
5882
5883 register int
5884 x;
5885
5886 register unsigned char
5887 *q;
5888
5889 unsigned char
5890 bit,
5891 byte;
5892
5893 unsigned int
5894 scanline_pad;
5895
cristyf2faecf2010-05-28 19:19:36 +00005896 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005897 pixel,
5898 *pixels;
5899
5900 XStandardColormap
5901 *map_info;
5902
5903 assert(resource_info != (XResourceInfo *) NULL);
5904 assert(window != (XWindowInfo *) NULL);
5905 assert(image != (Image *) NULL);
5906 if (image->debug != MagickFalse)
5907 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5908 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005909 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005910 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005911 {
5912 char
5913 size[MaxTextExtent];
5914
5915 Image
5916 *pattern;
5917
5918 ImageInfo
5919 *image_info;
5920
5921 image_info=AcquireImageInfo();
5922 (void) CopyMagickString(image_info->filename,
5923 resource_info->image_info->texture != (char *) NULL ?
5924 resource_info->image_info->texture : "pattern:checkerboard",
5925 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005926 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005927 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005928 image_info->size=ConstantString(size);
5929 pattern=ReadImage(image_info,&image->exception);
5930 image_info=DestroyImageInfo(image_info);
5931 if (pattern != (Image *) NULL)
5932 {
5933 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5934 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00005935 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
5936 exception);
cristy3ed852e2009-09-05 21:47:34 +00005937 pattern=DestroyImage(pattern);
5938 }
5939 }
5940 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5941 ximage->bits_per_pixel) >> 3));
5942 map_info=window->map_info;
5943 pixels=window->pixel_info->pixels;
5944 q=(unsigned char *) ximage->data;
5945 x=0;
cristyc57f6942010-11-12 01:47:39 +00005946 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005947 if (ximage->format == XYBitmap)
5948 {
5949 register unsigned short
5950 polarity;
5951
5952 unsigned char
5953 background,
5954 foreground;
5955
5956 /*
5957 Convert canvas to big-endian bitmap.
5958 */
5959 background=(unsigned char)
5960 (XPixelIntensity(&window->pixel_info->foreground_color) <
5961 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5962 foreground=(unsigned char)
5963 (XPixelIntensity(&window->pixel_info->background_color) <
5964 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005965 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005966 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5967 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005968 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5969 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005970 for (y=0; y < (int) canvas->rows; y++)
5971 {
cristyc57f6942010-11-12 01:47:39 +00005972 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5973 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00005974 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005975 break;
cristy3ed852e2009-09-05 21:47:34 +00005976 bit=0;
5977 byte=0;
5978 for (x=0; x < (int) canvas->columns; x++)
5979 {
5980 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005981 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005982 byte|=foreground;
5983 else
5984 byte|=background;
5985 bit++;
5986 if (bit == 8)
5987 {
5988 *q++=byte;
5989 bit=0;
5990 byte=0;
5991 }
cristyed231572011-07-14 02:18:59 +00005992 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005993 }
5994 if (bit != 0)
5995 *q=byte >> (8-bit);
5996 q+=scanline_pad;
5997 }
5998 }
5999 else
6000 if (window->pixel_info->colors != 0)
6001 switch (ximage->bits_per_pixel)
6002 {
6003 case 2:
6004 {
6005 register unsigned int
6006 nibble;
6007
6008 /*
6009 Convert to 2 bit color-mapped X canvas.
6010 */
6011 for (y=0; y < (int) canvas->rows; y++)
6012 {
cristyc57f6942010-11-12 01:47:39 +00006013 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6014 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006015 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006016 break;
cristy3ed852e2009-09-05 21:47:34 +00006017 nibble=0;
6018 for (x=0; x < (int) canvas->columns; x++)
6019 {
cristy4c08aed2011-07-01 19:47:50 +00006020 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006021 switch (nibble)
6022 {
6023 case 0:
6024 {
6025 *q=(unsigned char) pixel;
6026 nibble++;
6027 break;
6028 }
6029 case 1:
6030 {
6031 *q|=(unsigned char) (pixel << 2);
6032 nibble++;
6033 break;
6034 }
6035 case 2:
6036 {
6037 *q|=(unsigned char) (pixel << 4);
6038 nibble++;
6039 break;
6040 }
6041 case 3:
6042 {
6043 *q|=(unsigned char) (pixel << 6);
6044 q++;
6045 nibble=0;
6046 break;
6047 }
6048 }
cristyed231572011-07-14 02:18:59 +00006049 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006050 }
6051 q+=scanline_pad;
6052 }
6053 break;
6054 }
6055 case 4:
6056 {
6057 register unsigned int
6058 nibble;
6059
6060 /*
6061 Convert to 4 bit color-mapped X canvas.
6062 */
6063 for (y=0; y < (int) canvas->rows; y++)
6064 {
cristyc57f6942010-11-12 01:47:39 +00006065 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6066 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006067 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006068 break;
cristy3ed852e2009-09-05 21:47:34 +00006069 nibble=0;
6070 for (x=0; x < (int) canvas->columns; x++)
6071 {
cristy4c08aed2011-07-01 19:47:50 +00006072 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006073 switch (nibble)
6074 {
6075 case 0:
6076 {
6077 *q=(unsigned char) pixel;
6078 nibble++;
6079 break;
6080 }
6081 case 1:
6082 {
6083 *q|=(unsigned char) (pixel << 4);
6084 q++;
6085 nibble=0;
6086 break;
6087 }
6088 }
cristyed231572011-07-14 02:18:59 +00006089 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006090 }
6091 q+=scanline_pad;
6092 }
6093 break;
6094 }
6095 case 6:
6096 case 8:
6097 {
6098 /*
6099 Convert to 8 bit color-mapped X canvas.
6100 */
6101 if (resource_info->color_recovery &&
6102 resource_info->quantize_info->dither)
6103 {
6104 XDitherImage(canvas,ximage);
6105 break;
6106 }
6107 for (y=0; y < (int) canvas->rows; y++)
6108 {
cristyc57f6942010-11-12 01:47:39 +00006109 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6110 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006111 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006112 break;
cristy3ed852e2009-09-05 21:47:34 +00006113 for (x=0; x < (int) canvas->columns; x++)
6114 {
cristy4c08aed2011-07-01 19:47:50 +00006115 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006116 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006117 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006118 }
6119 q+=scanline_pad;
6120 }
6121 break;
6122 }
6123 default:
6124 {
6125 register int
6126 k;
6127
6128 register unsigned int
6129 bytes_per_pixel;
6130
6131 unsigned char
cristybb503372010-05-27 20:51:26 +00006132 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006133
6134 /*
6135 Convert to multi-byte color-mapped X canvas.
6136 */
6137 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6138 for (y=0; y < (int) canvas->rows; y++)
6139 {
cristyc57f6942010-11-12 01:47:39 +00006140 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6141 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006142 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006143 break;
cristy3ed852e2009-09-05 21:47:34 +00006144 for (x=0; x < (int) canvas->columns; x++)
6145 {
cristy4c08aed2011-07-01 19:47:50 +00006146 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006147 for (k=0; k < (int) bytes_per_pixel; k++)
6148 {
6149 channel[k]=(unsigned char) pixel;
6150 pixel>>=8;
6151 }
6152 for (k=0; k < (int) bytes_per_pixel; k++)
6153 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006154 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006155 }
6156 q+=scanline_pad;
6157 }
6158 break;
6159 }
6160 }
6161 else
6162 switch (ximage->bits_per_pixel)
6163 {
6164 case 2:
6165 {
6166 register unsigned int
6167 nibble;
6168
6169 /*
6170 Convert to contiguous 2 bit continuous-tone X canvas.
6171 */
6172 for (y=0; y < (int) canvas->rows; y++)
6173 {
6174 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006175 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6176 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006177 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006178 break;
6179 for (x=0; x < (int) canvas->columns; x++)
6180 {
cristy4c08aed2011-07-01 19:47:50 +00006181 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006182 pixel&=0xf;
6183 switch (nibble)
6184 {
6185 case 0:
6186 {
6187 *q=(unsigned char) pixel;
6188 nibble++;
6189 break;
6190 }
6191 case 1:
6192 {
6193 *q|=(unsigned char) (pixel << 2);
6194 nibble++;
6195 break;
6196 }
6197 case 2:
6198 {
6199 *q|=(unsigned char) (pixel << 4);
6200 nibble++;
6201 break;
6202 }
6203 case 3:
6204 {
6205 *q|=(unsigned char) (pixel << 6);
6206 q++;
6207 nibble=0;
6208 break;
6209 }
6210 }
cristyed231572011-07-14 02:18:59 +00006211 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006212 }
6213 q+=scanline_pad;
6214 }
6215 break;
6216 }
6217 case 4:
6218 {
6219 register unsigned int
6220 nibble;
6221
6222 /*
6223 Convert to contiguous 4 bit continuous-tone X canvas.
6224 */
6225 for (y=0; y < (int) canvas->rows; y++)
6226 {
cristyc57f6942010-11-12 01:47:39 +00006227 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6228 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006229 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006230 break;
6231 nibble=0;
6232 for (x=0; x < (int) canvas->columns; x++)
6233 {
cristy4c08aed2011-07-01 19:47:50 +00006234 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006235 pixel&=0xf;
6236 switch (nibble)
6237 {
6238 case 0:
6239 {
6240 *q=(unsigned char) pixel;
6241 nibble++;
6242 break;
6243 }
6244 case 1:
6245 {
6246 *q|=(unsigned char) (pixel << 4);
6247 q++;
6248 nibble=0;
6249 break;
6250 }
6251 }
cristyed231572011-07-14 02:18:59 +00006252 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006253 }
6254 q+=scanline_pad;
6255 }
6256 break;
6257 }
6258 case 6:
6259 case 8:
6260 {
6261 /*
6262 Convert to contiguous 8 bit continuous-tone X canvas.
6263 */
6264 if (resource_info->color_recovery &&
6265 resource_info->quantize_info->dither)
6266 {
6267 XDitherImage(canvas,ximage);
6268 break;
6269 }
6270 for (y=0; y < (int) canvas->rows; y++)
6271 {
cristyc57f6942010-11-12 01:47:39 +00006272 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6273 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006274 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006275 break;
6276 for (x=0; x < (int) canvas->columns; x++)
6277 {
cristy4c08aed2011-07-01 19:47:50 +00006278 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006279 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006280 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006281 }
6282 q+=scanline_pad;
6283 }
6284 break;
6285 }
6286 default:
6287 {
6288 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6289 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6290 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6291 (map_info->blue_mult == 1))
6292 {
6293 /*
6294 Convert to 32 bit continuous-tone X canvas.
6295 */
6296 for (y=0; y < (int) canvas->rows; y++)
6297 {
cristyc57f6942010-11-12 01:47:39 +00006298 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6299 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006300 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006301 break;
6302 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6303 (blue_gamma != 1.0))
6304 {
6305 /*
6306 Gamma correct canvas.
6307 */
6308 for (x=(int) canvas->columns-1; x >= 0; x--)
6309 {
cristyccf844f2010-02-03 23:28:16 +00006310 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006311 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006312 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006313 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006314 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006315 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006316 *q++=0;
cristyed231572011-07-14 02:18:59 +00006317 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006318 }
6319 continue;
6320 }
6321 for (x=(int) canvas->columns-1; x >= 0; x--)
6322 {
cristy4c08aed2011-07-01 19:47:50 +00006323 *q++=ScaleQuantumToChar((Quantum)
6324 GetPixelBlue(canvas,p));
6325 *q++=ScaleQuantumToChar((Quantum)
6326 GetPixelGreen(canvas,p));
6327 *q++=ScaleQuantumToChar((Quantum)
6328 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006329 *q++=0;
cristyed231572011-07-14 02:18:59 +00006330 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006331 }
6332 }
6333 }
6334 else
6335 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6336 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6337 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6338 (map_info->blue_mult == 65536L))
6339 {
6340 /*
6341 Convert to 32 bit continuous-tone X canvas.
6342 */
6343 for (y=0; y < (int) canvas->rows; y++)
6344 {
cristyc57f6942010-11-12 01:47:39 +00006345 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6346 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006347 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006348 break;
6349 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6350 (blue_gamma != 1.0))
6351 {
6352 /*
6353 Gamma correct canvas.
6354 */
6355 for (x=(int) canvas->columns-1; x >= 0; x--)
6356 {
cristyccf844f2010-02-03 23:28:16 +00006357 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006358 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006359 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006360 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006361 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006362 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006363 *q++=0;
cristyed231572011-07-14 02:18:59 +00006364 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006365 }
6366 continue;
6367 }
6368 for (x=(int) canvas->columns-1; x >= 0; x--)
6369 {
cristyccf844f2010-02-03 23:28:16 +00006370 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006371 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006372 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006373 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006374 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006375 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006376 *q++=0;
cristyed231572011-07-14 02:18:59 +00006377 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006378 }
6379 }
6380 }
6381 else
6382 {
6383 register int
6384 k;
6385
6386 register unsigned int
6387 bytes_per_pixel;
6388
6389 unsigned char
cristybb503372010-05-27 20:51:26 +00006390 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006391
6392 /*
6393 Convert to multi-byte continuous-tone X canvas.
6394 */
6395 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6396 for (y=0; y < (int) canvas->rows; y++)
6397 {
cristyc57f6942010-11-12 01:47:39 +00006398 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6399 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006400 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006401 break;
cristyc57f6942010-11-12 01:47:39 +00006402 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006403 {
cristy4c08aed2011-07-01 19:47:50 +00006404 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006405 for (k=0; k < (int) bytes_per_pixel; k++)
6406 {
6407 channel[k]=(unsigned char) pixel;
6408 pixel>>=8;
6409 }
6410 for (k=0; k < (int) bytes_per_pixel; k++)
6411 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006412 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006413 }
6414 q+=scanline_pad;
6415 }
6416 }
6417 break;
6418 }
6419 }
6420 if (matte_image != (XImage *) NULL)
6421 {
6422 /*
6423 Initialize matte canvas.
6424 */
6425 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6426 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6427 q=(unsigned char *) matte_image->data;
6428 for (y=0; y < (int) canvas->rows; y++)
6429 {
cristyc57f6942010-11-12 01:47:39 +00006430 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6431 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006432 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006433 break;
6434 bit=0;
6435 byte=0;
6436 for (x=(int) canvas->columns-1; x >= 0; x--)
6437 {
6438 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006439 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006440 byte|=0x80;
6441 bit++;
6442 if (bit == 8)
6443 {
6444 *q++=byte;
6445 bit=0;
6446 byte=0;
6447 }
cristyed231572011-07-14 02:18:59 +00006448 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006449 }
6450 if (bit != 0)
6451 *q=byte >> (8-bit);
6452 q+=scanline_pad;
6453 }
6454 }
cristyc57f6942010-11-12 01:47:39 +00006455 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006456 if (canvas != image)
6457 canvas=DestroyImage(canvas);
6458}
6459
6460/*
6461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6462% %
6463% %
6464% %
6465+ X M a k e I m a g e M S B F i r s t %
6466% %
6467% %
6468% %
6469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6470%
6471% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6472% image pixels are copied in most-significant bit and byte first order. The
6473% server's scanline pad is also respected. Rather than using one or two
6474% general cases, many special cases are found here to help speed up the image
6475% conversion.
6476%
6477% The format of the XMakeImageMSBFirst method is:
6478%
cristye941a752011-10-15 01:52:48 +00006479% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6480% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006481%
6482% A description of each parameter follows:
6483%
6484% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6485%
6486% o window: Specifies a pointer to a XWindowInfo structure.
6487%
6488% o image: the image.
6489%
6490% o ximage: Specifies a pointer to a XImage structure; returned from
6491% XCreateImage.
6492%
6493% o matte_image: Specifies a pointer to a XImage structure; returned from
6494% XCreateImage.
6495%
cristye941a752011-10-15 01:52:48 +00006496% o exception: return any errors or warnings in this structure.
6497%
cristy3ed852e2009-09-05 21:47:34 +00006498*/
6499static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006500 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6501 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006502{
cristyc57f6942010-11-12 01:47:39 +00006503 CacheView
6504 *canvas_view;
6505
cristy3ed852e2009-09-05 21:47:34 +00006506 Image
6507 *canvas;
6508
6509 int
6510 y;
6511
6512 register int
6513 x;
6514
cristy4c08aed2011-07-01 19:47:50 +00006515 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006516 *p;
6517
6518 register unsigned char
6519 *q;
6520
6521 unsigned char
6522 bit,
6523 byte;
6524
6525 unsigned int
6526 scanline_pad;
6527
cristyf2faecf2010-05-28 19:19:36 +00006528 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006529 pixel,
6530 *pixels;
6531
6532 XStandardColormap
6533 *map_info;
6534
6535 assert(resource_info != (XResourceInfo *) NULL);
6536 assert(window != (XWindowInfo *) NULL);
6537 assert(image != (Image *) NULL);
6538 if (image->debug != MagickFalse)
6539 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6540 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006541 if ((window->immutable != MagickFalse) &&
6542 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006543 {
6544 char
6545 size[MaxTextExtent];
6546
6547 Image
6548 *pattern;
6549
6550 ImageInfo
6551 *image_info;
6552
6553 image_info=AcquireImageInfo();
6554 (void) CopyMagickString(image_info->filename,
6555 resource_info->image_info->texture != (char *) NULL ?
6556 resource_info->image_info->texture : "pattern:checkerboard",
6557 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006558 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006559 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006560 image_info->size=ConstantString(size);
6561 pattern=ReadImage(image_info,&image->exception);
6562 image_info=DestroyImageInfo(image_info);
6563 if (pattern != (Image *) NULL)
6564 {
6565 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6566 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00006567 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
6568 exception);
cristy3ed852e2009-09-05 21:47:34 +00006569 pattern=DestroyImage(pattern);
6570 }
6571 }
cristy4c08aed2011-07-01 19:47:50 +00006572 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6573 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006574 map_info=window->map_info;
6575 pixels=window->pixel_info->pixels;
6576 q=(unsigned char *) ximage->data;
6577 x=0;
cristyc57f6942010-11-12 01:47:39 +00006578 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006579 if (ximage->format == XYBitmap)
6580 {
6581 register unsigned short
6582 polarity;
6583
6584 unsigned char
6585 background,
6586 foreground;
6587
6588 /*
6589 Convert canvas to big-endian bitmap.
6590 */
6591 background=(unsigned char)
6592 (XPixelIntensity(&window->pixel_info->foreground_color) <
6593 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6594 foreground=(unsigned char)
6595 (XPixelIntensity(&window->pixel_info->background_color) <
6596 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006597 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006598 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6599 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006600 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6601 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006602 for (y=0; y < (int) canvas->rows; y++)
6603 {
cristyc57f6942010-11-12 01:47:39 +00006604 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6605 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006606 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006607 break;
cristy3ed852e2009-09-05 21:47:34 +00006608 bit=0;
6609 byte=0;
6610 for (x=(int) canvas->columns-1; x >= 0; x--)
6611 {
6612 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006613 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006614 byte|=foreground;
6615 else
6616 byte|=background;
6617 bit++;
6618 if (bit == 8)
6619 {
6620 *q++=byte;
6621 bit=0;
6622 byte=0;
6623 }
cristyed231572011-07-14 02:18:59 +00006624 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006625 }
6626 if (bit != 0)
6627 *q=byte << (8-bit);
6628 q+=scanline_pad;
6629 }
6630 }
6631 else
6632 if (window->pixel_info->colors != 0)
6633 switch (ximage->bits_per_pixel)
6634 {
6635 case 2:
6636 {
6637 register unsigned int
6638 nibble;
6639
6640 /*
6641 Convert to 2 bit color-mapped X canvas.
6642 */
6643 for (y=0; y < (int) canvas->rows; y++)
6644 {
cristyc57f6942010-11-12 01:47:39 +00006645 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6646 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006647 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006648 break;
cristy3ed852e2009-09-05 21:47:34 +00006649 nibble=0;
6650 for (x=0; x < (int) canvas->columns; x++)
6651 {
cristy4c08aed2011-07-01 19:47:50 +00006652 pixel=pixels[(ssize_t)
6653 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006654 switch (nibble)
6655 {
6656 case 0:
6657 {
6658 *q=(unsigned char) (pixel << 6);
6659 nibble++;
6660 break;
6661 }
6662 case 1:
6663 {
6664 *q|=(unsigned char) (pixel << 4);
6665 nibble++;
6666 break;
6667 }
6668 case 2:
6669 {
6670 *q|=(unsigned char) (pixel << 2);
6671 nibble++;
6672 break;
6673 }
6674 case 3:
6675 {
6676 *q|=(unsigned char) pixel;
6677 q++;
6678 nibble=0;
6679 break;
6680 }
6681 }
cristyed231572011-07-14 02:18:59 +00006682 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006683 }
6684 q+=scanline_pad;
6685 }
6686 break;
6687 }
6688 case 4:
6689 {
6690 register unsigned int
6691 nibble;
6692
6693 /*
6694 Convert to 4 bit color-mapped X canvas.
6695 */
6696 for (y=0; y < (int) canvas->rows; y++)
6697 {
cristyc57f6942010-11-12 01:47:39 +00006698 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6699 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006700 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006701 break;
cristy3ed852e2009-09-05 21:47:34 +00006702 nibble=0;
6703 for (x=0; x < (int) canvas->columns; x++)
6704 {
cristy4c08aed2011-07-01 19:47:50 +00006705 pixel=pixels[(ssize_t)
6706 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006707 switch (nibble)
6708 {
6709 case 0:
6710 {
6711 *q=(unsigned char) (pixel << 4);
6712 nibble++;
6713 break;
6714 }
6715 case 1:
6716 {
6717 *q|=(unsigned char) pixel;
6718 q++;
6719 nibble=0;
6720 break;
6721 }
6722 }
cristyed231572011-07-14 02:18:59 +00006723 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006724 }
6725 q+=scanline_pad;
6726 }
6727 break;
6728 }
6729 case 6:
6730 case 8:
6731 {
6732 /*
6733 Convert to 8 bit color-mapped X canvas.
6734 */
6735 if (resource_info->color_recovery &&
6736 resource_info->quantize_info->dither)
6737 {
6738 XDitherImage(canvas,ximage);
6739 break;
6740 }
6741 for (y=0; y < (int) canvas->rows; y++)
6742 {
cristyc57f6942010-11-12 01:47:39 +00006743 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6744 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006745 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006746 break;
cristy3ed852e2009-09-05 21:47:34 +00006747 for (x=0; x < (int) canvas->columns; x++)
6748 {
cristy4c08aed2011-07-01 19:47:50 +00006749 pixel=pixels[(ssize_t)
6750 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006751 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006752 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006753 }
6754 q+=scanline_pad;
6755 }
6756 break;
6757 }
6758 default:
6759 {
6760 register int
6761 k;
6762
6763 register unsigned int
6764 bytes_per_pixel;
6765
6766 unsigned char
cristybb503372010-05-27 20:51:26 +00006767 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006768
6769 /*
6770 Convert to 8 bit color-mapped X canvas.
6771 */
6772 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6773 for (y=0; y < (int) canvas->rows; y++)
6774 {
cristyc57f6942010-11-12 01:47:39 +00006775 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6776 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006777 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006778 break;
cristy3ed852e2009-09-05 21:47:34 +00006779 for (x=0; x < (int) canvas->columns; x++)
6780 {
cristy4c08aed2011-07-01 19:47:50 +00006781 pixel=pixels[(ssize_t)
6782 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006783 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6784 {
6785 channel[k]=(unsigned char) pixel;
6786 pixel>>=8;
6787 }
6788 for (k=0; k < (int) bytes_per_pixel; k++)
6789 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006790 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006791 }
6792 q+=scanline_pad;
6793 }
6794 break;
6795 }
6796 }
6797 else
6798 switch (ximage->bits_per_pixel)
6799 {
6800 case 2:
6801 {
6802 register unsigned int
6803 nibble;
6804
6805 /*
6806 Convert to 4 bit continuous-tone X canvas.
6807 */
6808 for (y=0; y < (int) canvas->rows; y++)
6809 {
cristyc57f6942010-11-12 01:47:39 +00006810 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6811 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006812 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006813 break;
6814 nibble=0;
6815 for (x=(int) canvas->columns-1; x >= 0; x--)
6816 {
cristy4c08aed2011-07-01 19:47:50 +00006817 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006818 pixel&=0xf;
6819 switch (nibble)
6820 {
6821 case 0:
6822 {
6823 *q=(unsigned char) (pixel << 6);
6824 nibble++;
6825 break;
6826 }
6827 case 1:
6828 {
6829 *q|=(unsigned char) (pixel << 4);
6830 nibble++;
6831 break;
6832 }
6833 case 2:
6834 {
6835 *q|=(unsigned char) (pixel << 2);
6836 nibble++;
6837 break;
6838 }
6839 case 3:
6840 {
6841 *q|=(unsigned char) pixel;
6842 q++;
6843 nibble=0;
6844 break;
6845 }
6846 }
cristyed231572011-07-14 02:18:59 +00006847 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006848 }
6849 q+=scanline_pad;
6850 }
6851 break;
6852 }
6853 case 4:
6854 {
6855 register unsigned int
6856 nibble;
6857
6858 /*
6859 Convert to 4 bit continuous-tone X canvas.
6860 */
6861 for (y=0; y < (int) canvas->rows; y++)
6862 {
cristyc57f6942010-11-12 01:47:39 +00006863 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6864 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006865 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006866 break;
6867 nibble=0;
6868 for (x=(int) canvas->columns-1; x >= 0; x--)
6869 {
cristy4c08aed2011-07-01 19:47:50 +00006870 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006871 pixel&=0xf;
6872 switch (nibble)
6873 {
6874 case 0:
6875 {
6876 *q=(unsigned char) (pixel << 4);
6877 nibble++;
6878 break;
6879 }
6880 case 1:
6881 {
6882 *q|=(unsigned char) pixel;
6883 q++;
6884 nibble=0;
6885 break;
6886 }
6887 }
cristyed231572011-07-14 02:18:59 +00006888 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006889 }
6890 q+=scanline_pad;
6891 }
6892 break;
6893 }
6894 case 6:
6895 case 8:
6896 {
6897 /*
6898 Convert to 8 bit continuous-tone X canvas.
6899 */
6900 if (resource_info->color_recovery &&
6901 resource_info->quantize_info->dither)
6902 {
6903 XDitherImage(canvas,ximage);
6904 break;
6905 }
6906 for (y=0; y < (int) canvas->rows; y++)
6907 {
cristyc57f6942010-11-12 01:47:39 +00006908 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6909 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006910 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006911 break;
6912 for (x=(int) canvas->columns-1; x >= 0; x--)
6913 {
cristy4c08aed2011-07-01 19:47:50 +00006914 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006915 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006916 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006917 }
6918 q+=scanline_pad;
6919 }
6920 break;
6921 }
6922 default:
6923 {
6924 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6925 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6926 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6927 (map_info->blue_mult == 1))
6928 {
6929 /*
6930 Convert to 32 bit continuous-tone X canvas.
6931 */
6932 for (y=0; y < (int) canvas->rows; y++)
6933 {
cristyc57f6942010-11-12 01:47:39 +00006934 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6935 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006936 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006937 break;
6938 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6939 (blue_gamma != 1.0))
6940 {
6941 /*
6942 Gamma correct canvas.
6943 */
6944 for (x=(int) canvas->columns-1; x >= 0; x--)
6945 {
6946 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006947 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006948 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006949 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006950 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006951 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006952 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006953 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006954 }
6955 continue;
6956 }
6957 for (x=(int) canvas->columns-1; x >= 0; x--)
6958 {
6959 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006960 *q++=ScaleQuantumToChar((Quantum)
6961 GetPixelRed(canvas,p));
6962 *q++=ScaleQuantumToChar((Quantum)
6963 GetPixelGreen(canvas,p));
6964 *q++=ScaleQuantumToChar((Quantum)
6965 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006966 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006967 }
6968 }
6969 }
6970 else
6971 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6972 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6973 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6974 (map_info->blue_mult == 65536L))
6975 {
6976 /*
6977 Convert to 32 bit continuous-tone X canvas.
6978 */
6979 for (y=0; y < (int) canvas->rows; y++)
6980 {
cristyc57f6942010-11-12 01:47:39 +00006981 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6982 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00006983 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006984 break;
6985 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6986 (blue_gamma != 1.0))
6987 {
6988 /*
6989 Gamma correct canvas.
6990 */
6991 for (x=(int) canvas->columns-1; x >= 0; x--)
6992 {
6993 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006994 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006995 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006996 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006997 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006998 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006999 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00007000 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007001 }
7002 continue;
7003 }
7004 for (x=(int) canvas->columns-1; x >= 0; x--)
7005 {
7006 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007007 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007008 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007009 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007010 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007011 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007012 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00007013 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007014 }
7015 }
7016 }
7017 else
7018 {
7019 register int
7020 k;
7021
7022 register unsigned int
7023 bytes_per_pixel;
7024
7025 unsigned char
cristybb503372010-05-27 20:51:26 +00007026 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007027
7028 /*
7029 Convert to multi-byte continuous-tone X canvas.
7030 */
7031 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7032 for (y=0; y < (int) canvas->rows; y++)
7033 {
cristyc57f6942010-11-12 01:47:39 +00007034 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
7035 canvas->columns,1,&canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007036 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007037 break;
7038 for (x=(int) canvas->columns-1; x >= 0; x--)
7039 {
cristy4c08aed2011-07-01 19:47:50 +00007040 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007041 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7042 {
7043 channel[k]=(unsigned char) pixel;
7044 pixel>>=8;
7045 }
7046 for (k=0; k < (int) bytes_per_pixel; k++)
7047 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007048 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007049 }
7050 q+=scanline_pad;
7051 }
7052 }
7053 break;
7054 }
7055 }
7056 if (matte_image != (XImage *) NULL)
7057 {
7058 /*
7059 Initialize matte canvas.
7060 */
7061 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7062 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7063 q=(unsigned char *) matte_image->data;
7064 for (y=0; y < (int) canvas->rows; y++)
7065 {
cristyc57f6942010-11-12 01:47:39 +00007066 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7067 &canvas->exception);
cristy4c08aed2011-07-01 19:47:50 +00007068 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007069 break;
7070 bit=0;
7071 byte=0;
7072 for (x=(int) canvas->columns-1; x >= 0; x--)
7073 {
7074 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007075 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007076 byte|=0x01;
7077 bit++;
7078 if (bit == 8)
7079 {
7080 *q++=byte;
7081 bit=0;
7082 byte=0;
7083 }
cristyed231572011-07-14 02:18:59 +00007084 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007085 }
7086 if (bit != 0)
7087 *q=byte << (8-bit);
7088 q+=scanline_pad;
7089 }
7090 }
cristyc57f6942010-11-12 01:47:39 +00007091 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007092 if (canvas != image)
7093 canvas=DestroyImage(canvas);
7094}
7095
7096/*
7097%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7098% %
7099% %
7100% %
7101% X M a k e M a g n i f y I m a g e %
7102% %
7103% %
7104% %
7105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7106%
7107% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7108%
7109% The format of the XMakeMagnifyImage method is:
7110%
7111% void XMakeMagnifyImage(display,windows)
7112%
7113% A description of each parameter follows:
7114%
7115% o display: Specifies a connection to an X server; returned from
7116% XOpenDisplay.
7117%
7118% o windows: Specifies a pointer to a XWindows structure.
7119%
7120*/
cristybcbda3f2011-09-03 13:01:22 +00007121MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00007122{
7123 char
7124 tuple[MaxTextExtent];
7125
7126 int
7127 y;
7128
cristy4c08aed2011-07-01 19:47:50 +00007129 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007130 pixel;
7131
7132 register int
7133 x;
7134
cristybb503372010-05-27 20:51:26 +00007135 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007136 i;
7137
7138 register unsigned char
7139 *p,
7140 *q;
7141
cristy9d314ff2011-03-09 01:30:28 +00007142 ssize_t
7143 n;
7144
cristy3ed852e2009-09-05 21:47:34 +00007145 static unsigned int
7146 previous_magnify = 0;
7147
7148 static XWindowInfo
7149 magnify_window;
7150
7151 unsigned int
7152 height,
7153 j,
7154 k,
7155 l,
7156 magnify,
7157 scanline_pad,
7158 width;
7159
7160 XImage
7161 *ximage;
7162
7163 /*
7164 Check boundary conditions.
7165 */
7166 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7167 assert(display != (Display *) NULL);
7168 assert(windows != (XWindows *) NULL);
7169 magnify=1;
cristybb503372010-05-27 20:51:26 +00007170 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007171 magnify<<=1;
7172 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7173 magnify<<=1;
7174 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7175 magnify<<=1;
7176 while (magnify > windows->magnify.width)
7177 magnify>>=1;
7178 while (magnify > windows->magnify.height)
7179 magnify>>=1;
7180 if (magnify != previous_magnify)
7181 {
7182 Status
7183 status;
7184
7185 XTextProperty
7186 window_name;
7187
7188 /*
7189 New magnify factor: update magnify window name.
7190 */
7191 i=0;
7192 while ((1 << i) <= (int) magnify)
7193 i++;
cristyb51dff52011-05-19 16:55:47 +00007194 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007195 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007196 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7197 if (status != False)
7198 {
7199 XSetWMName(display,windows->magnify.id,&window_name);
7200 XSetWMIconName(display,windows->magnify.id,&window_name);
7201 (void) XFree((void *) window_name.value);
7202 }
7203 }
7204 previous_magnify=magnify;
7205 ximage=windows->image.ximage;
7206 width=(unsigned int) windows->magnify.ximage->width;
7207 height=(unsigned int) windows->magnify.ximage->height;
7208 if ((windows->magnify.x < 0) ||
7209 (windows->magnify.x >= windows->image.ximage->width))
7210 windows->magnify.x=windows->image.ximage->width >> 1;
7211 x=windows->magnify.x-((width/magnify) >> 1);
7212 if (x < 0)
7213 x=0;
7214 else
7215 if (x > (int) (ximage->width-(width/magnify)))
7216 x=ximage->width-width/magnify;
7217 if ((windows->magnify.y < 0) ||
7218 (windows->magnify.y >= windows->image.ximage->height))
7219 windows->magnify.y=windows->image.ximage->height >> 1;
7220 y=windows->magnify.y-((height/magnify) >> 1);
7221 if (y < 0)
7222 y=0;
7223 else
7224 if (y > (int) (ximage->height-(height/magnify)))
7225 y=ximage->height-height/magnify;
7226 q=(unsigned char *) windows->magnify.ximage->data;
7227 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7228 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7229 if (ximage->bits_per_pixel < 8)
7230 {
7231 register unsigned char
7232 background,
7233 byte,
7234 foreground,
7235 p_bit,
7236 q_bit;
7237
7238 register unsigned int
7239 plane;
7240
7241 XPixelInfo
7242 *pixel_info;
7243
7244 pixel_info=windows->magnify.pixel_info;
7245 switch (ximage->bitmap_bit_order)
7246 {
7247 case LSBFirst:
7248 {
7249 /*
7250 Magnify little-endian bitmap.
7251 */
7252 background=0x00;
7253 foreground=0x80;
7254 if (ximage->format == XYBitmap)
7255 {
7256 background=(unsigned char)
7257 (XPixelIntensity(&pixel_info->foreground_color) <
7258 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7259 foreground=(unsigned char)
7260 (XPixelIntensity(&pixel_info->background_color) <
7261 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7262 if (windows->magnify.depth > 1)
7263 Swap(background,foreground);
7264 }
cristybb503372010-05-27 20:51:26 +00007265 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007266 {
7267 /*
7268 Propogate pixel magnify rows.
7269 */
7270 for (j=0; j < magnify; j++)
7271 {
7272 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7273 ((x*ximage->bits_per_pixel) >> 3);
7274 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7275 q_bit=0;
7276 byte=0;
7277 for (k=0; k < width; k+=magnify)
7278 {
7279 /*
7280 Propogate pixel magnify columns.
7281 */
7282 for (l=0; l < magnify; l++)
7283 {
7284 /*
7285 Propogate each bit plane.
7286 */
7287 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7288 {
7289 byte>>=1;
7290 if (*p & (0x01 << (p_bit+plane)))
7291 byte|=foreground;
7292 else
7293 byte|=background;
7294 q_bit++;
7295 if (q_bit == 8)
7296 {
7297 *q++=byte;
7298 q_bit=0;
7299 byte=0;
7300 }
7301 }
7302 }
7303 p_bit+=ximage->bits_per_pixel;
7304 if (p_bit == 8)
7305 {
7306 p++;
7307 p_bit=0;
7308 }
7309 if (q_bit != 0)
7310 *q=byte >> (8-q_bit);
7311 q+=scanline_pad;
7312 }
7313 }
7314 y++;
7315 }
7316 break;
7317 }
7318 case MSBFirst:
7319 default:
7320 {
7321 /*
7322 Magnify big-endian bitmap.
7323 */
7324 background=0x00;
7325 foreground=0x01;
7326 if (ximage->format == XYBitmap)
7327 {
7328 background=(unsigned char)
7329 (XPixelIntensity(&pixel_info->foreground_color) <
7330 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7331 foreground=(unsigned char)
7332 (XPixelIntensity(&pixel_info->background_color) <
7333 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7334 if (windows->magnify.depth > 1)
7335 Swap(background,foreground);
7336 }
cristybb503372010-05-27 20:51:26 +00007337 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007338 {
7339 /*
7340 Propogate pixel magnify rows.
7341 */
7342 for (j=0; j < magnify; j++)
7343 {
7344 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7345 ((x*ximage->bits_per_pixel) >> 3);
7346 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7347 q_bit=0;
7348 byte=0;
7349 for (k=0; k < width; k+=magnify)
7350 {
7351 /*
7352 Propogate pixel magnify columns.
7353 */
7354 for (l=0; l < magnify; l++)
7355 {
7356 /*
7357 Propogate each bit plane.
7358 */
7359 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7360 {
7361 byte<<=1;
7362 if (*p & (0x80 >> (p_bit+plane)))
7363 byte|=foreground;
7364 else
7365 byte|=background;
7366 q_bit++;
7367 if (q_bit == 8)
7368 {
7369 *q++=byte;
7370 q_bit=0;
7371 byte=0;
7372 }
7373 }
7374 }
7375 p_bit+=ximage->bits_per_pixel;
7376 if (p_bit == 8)
7377 {
7378 p++;
7379 p_bit=0;
7380 }
7381 if (q_bit != 0)
7382 *q=byte << (8-q_bit);
7383 q+=scanline_pad;
7384 }
7385 }
7386 y++;
7387 }
7388 break;
7389 }
7390 }
7391 }
7392 else
7393 switch (ximage->bits_per_pixel)
7394 {
7395 case 6:
7396 case 8:
7397 {
7398 /*
7399 Magnify 8 bit X image.
7400 */
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 *q++=(*p);
7417 p++;
7418 }
7419 q+=scanline_pad;
7420 }
7421 y++;
7422 }
7423 break;
7424 }
7425 default:
7426 {
7427 register unsigned int
7428 bytes_per_pixel,
7429 m;
7430
7431 /*
7432 Magnify multi-byte X image.
7433 */
7434 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007435 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007436 {
7437 /*
7438 Propogate pixel magnify rows.
7439 */
7440 for (j=0; j < magnify; j++)
7441 {
7442 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7443 ((x*ximage->bits_per_pixel) >> 3);
7444 for (k=0; k < width; k+=magnify)
7445 {
7446 /*
7447 Propogate pixel magnify columns.
7448 */
7449 for (l=0; l < magnify; l++)
7450 for (m=0; m < bytes_per_pixel; m++)
7451 *q++=(*(p+m));
7452 p+=bytes_per_pixel;
7453 }
7454 q+=scanline_pad;
7455 }
7456 y++;
7457 }
7458 break;
7459 }
7460 }
7461 /*
7462 Copy X image to magnify pixmap.
7463 */
7464 x=windows->magnify.x-((width/magnify) >> 1);
7465 if (x < 0)
7466 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7467 else
7468 if (x > (int) (ximage->width-(width/magnify)))
7469 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7470 else
7471 x=0;
7472 y=windows->magnify.y-((height/magnify) >> 1);
7473 if (y < 0)
7474 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7475 else
7476 if (y > (int) (ximage->height-(height/magnify)))
7477 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7478 else
7479 y=0;
7480 if ((x != 0) || (y != 0))
7481 (void) XFillRectangle(display,windows->magnify.pixmap,
7482 windows->magnify.annotate_context,0,0,width,height);
7483 (void) XPutImage(display,windows->magnify.pixmap,
7484 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7485 height-y);
7486 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7487 (magnify <= (height >> 1))))
7488 {
7489 RectangleInfo
7490 highlight_info;
7491
7492 /*
7493 Highlight center pixel.
7494 */
cristybb503372010-05-27 20:51:26 +00007495 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7496 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007497 highlight_info.width=magnify;
7498 highlight_info.height=magnify;
7499 (void) XDrawRectangle(display,windows->magnify.pixmap,
7500 windows->magnify.highlight_context,(int) highlight_info.x,
7501 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7502 (unsigned int) highlight_info.height-1);
7503 if (magnify > 2)
7504 (void) XDrawRectangle(display,windows->magnify.pixmap,
7505 windows->magnify.annotate_context,(int) highlight_info.x+1,
7506 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7507 (unsigned int) highlight_info.height-3);
7508 }
7509 /*
7510 Show center pixel color.
7511 */
cristyc57f6942010-11-12 01:47:39 +00007512 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7513 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7514 &windows->image.image->exception);
cristyb51dff52011-05-19 16:55:47 +00007515 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007516 windows->magnify.x,windows->magnify.y);
7517 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007518 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007519 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007520 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007521 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007522 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007523 if (pixel.colorspace == CMYKColorspace)
7524 {
7525 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007526 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007527 }
7528 if (pixel.matte != MagickFalse)
7529 {
7530 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007531 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007532 }
7533 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7534 height=(unsigned int) windows->magnify.font_info->ascent+
7535 windows->magnify.font_info->descent;
7536 x=windows->magnify.font_info->max_bounds.width >> 1;
7537 y=windows->magnify.font_info->ascent+(height >> 2);
7538 (void) XDrawImageString(display,windows->magnify.pixmap,
7539 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7540 GetColorTuple(&pixel,MagickTrue,tuple);
7541 y+=height;
7542 (void) XDrawImageString(display,windows->magnify.pixmap,
7543 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007544 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy3ed852e2009-09-05 21:47:34 +00007545 &windows->image.image->exception);
7546 y+=height;
7547 (void) XDrawImageString(display,windows->magnify.pixmap,
7548 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7549 /*
7550 Refresh magnify window.
7551 */
7552 magnify_window=windows->magnify;
7553 magnify_window.x=0;
7554 magnify_window.y=0;
7555 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7556}
7557
7558/*
7559%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7560% %
7561% %
7562% %
7563% X M a k e P i x m a p %
7564% %
7565% %
7566% %
7567%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7568%
7569% XMakePixmap() creates an X11 pixmap.
7570%
7571% The format of the XMakePixmap method is:
7572%
7573% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7574% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7575% XPixelInfo *pixel)
7576%
7577% A description of each parameter follows:
7578%
7579% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7580%
7581% o display: Specifies a connection to an X server; returned from
7582% XOpenDisplay.
7583%
7584% o window: Specifies a pointer to a XWindowInfo structure.
7585%
cristy3ed852e2009-09-05 21:47:34 +00007586*/
7587static MagickBooleanType XMakePixmap(Display *display,
7588 const XResourceInfo *resource_info,XWindowInfo *window)
7589{
7590 unsigned int
7591 height,
7592 width;
7593
7594 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7595 assert(display != (Display *) NULL);
7596 assert(resource_info != (XResourceInfo *) NULL);
7597 assert(window != (XWindowInfo *) NULL);
7598 if (window->pixmap != (Pixmap) NULL)
7599 {
7600 /*
7601 Destroy previous X pixmap.
7602 */
7603 (void) XFreePixmap(display,window->pixmap);
7604 window->pixmap=(Pixmap) NULL;
7605 }
7606 if (window->use_pixmap == MagickFalse)
7607 return(MagickFalse);
7608 if (window->ximage == (XImage *) NULL)
7609 return(MagickFalse);
7610 /*
7611 Display busy cursor.
7612 */
7613 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7614 (void) XFlush(display);
7615 /*
7616 Create pixmap.
7617 */
7618 width=(unsigned int) window->ximage->width;
7619 height=(unsigned int) window->ximage->height;
7620 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7621 if (window->pixmap == (Pixmap) NULL)
7622 {
7623 /*
7624 Unable to allocate pixmap.
7625 */
7626 (void) XCheckDefineCursor(display,window->id,window->cursor);
7627 return(MagickFalse);
7628 }
7629 /*
7630 Copy X image to pixmap.
7631 */
7632#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7633 if (window->shared_memory)
7634 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7635 window->ximage,0,0,0,0,width,height,MagickTrue);
7636#endif
7637 if (window->shared_memory == MagickFalse)
7638 (void) XPutImage(display,window->pixmap,window->annotate_context,
7639 window->ximage,0,0,0,0,width,height);
7640 if (IsEventLogging())
7641 {
7642 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7643 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7644 width,height);
7645 }
7646 /*
7647 Restore cursor.
7648 */
7649 (void) XCheckDefineCursor(display,window->id,window->cursor);
7650 return(MagickTrue);
7651}
7652
7653/*
7654%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7655% %
7656% %
7657% %
7658% X M a k e S t a n d a r d C o l o r m a p %
7659% %
7660% %
7661% %
7662%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7663%
7664% XMakeStandardColormap() creates an X11 Standard Colormap.
7665%
7666% The format of the XMakeStandardColormap method is:
7667%
7668% XMakeStandardColormap(display,visual_info,resource_info,image,
7669% map_info,pixel)
7670%
7671% A description of each parameter follows:
7672%
7673% o display: Specifies a connection to an X server; returned from
7674% XOpenDisplay.
7675%
7676% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7677% returned from XGetVisualInfo.
7678%
7679% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7680%
7681% o image: the image.
7682%
7683% o map_info: If a Standard Colormap type is specified, this structure is
7684% initialized with info from the Standard Colormap.
7685%
7686% o pixel: Specifies a pointer to a XPixelInfo structure.
7687%
cristy3ed852e2009-09-05 21:47:34 +00007688*/
7689
7690#if defined(__cplusplus) || defined(c_plusplus)
7691extern "C" {
7692#endif
7693
7694static inline MagickRealType DiversityPixelIntensity(
7695 const DiversityPacket *pixel)
7696{
7697 MagickRealType
7698 intensity;
7699
7700 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7701 return(intensity);
7702}
7703
7704static int IntensityCompare(const void *x,const void *y)
7705{
7706 DiversityPacket
7707 *color_1,
7708 *color_2;
7709
7710 int
7711 diversity;
7712
7713 color_1=(DiversityPacket *) x;
7714 color_2=(DiversityPacket *) y;
7715 diversity=(int) (DiversityPixelIntensity(color_2)-
7716 DiversityPixelIntensity(color_1));
7717 return(diversity);
7718}
7719
7720static int PopularityCompare(const void *x,const void *y)
7721{
7722 DiversityPacket
7723 *color_1,
7724 *color_2;
7725
7726 color_1=(DiversityPacket *) x;
7727 color_2=(DiversityPacket *) y;
7728 return((int) color_2->count-(int) color_1->count);
7729}
7730
7731#if defined(__cplusplus) || defined(c_plusplus)
7732}
7733#endif
7734
cristybb503372010-05-27 20:51:26 +00007735static inline Quantum ScaleXToQuantum(const size_t x,
7736 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007737{
7738 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7739}
7740
cristybcbda3f2011-09-03 13:01:22 +00007741MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007742 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7743 XStandardColormap *map_info,XPixelInfo *pixel)
7744{
7745 Colormap
7746 colormap;
7747
7748 ExceptionInfo
7749 *exception;
7750
cristybb503372010-05-27 20:51:26 +00007751 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007752 i;
7753
7754 Status
7755 status;
7756
cristybb503372010-05-27 20:51:26 +00007757 size_t
cristy3ed852e2009-09-05 21:47:34 +00007758 number_colors,
7759 retain_colors;
7760
7761 unsigned short
7762 gray_value;
7763
7764 XColor
7765 color,
7766 *colors,
7767 *p;
7768
7769 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7770 assert(display != (Display *) NULL);
7771 assert(visual_info != (XVisualInfo *) NULL);
7772 assert(map_info != (XStandardColormap *) NULL);
7773 assert(resource_info != (XResourceInfo *) NULL);
7774 assert(pixel != (XPixelInfo *) NULL);
7775 exception=(&image->exception);
7776 if (resource_info->map_type != (char *) NULL)
7777 {
7778 /*
7779 Standard Colormap is already defined (i.e. xstdcmap).
7780 */
cristy4c08aed2011-07-01 19:47:50 +00007781 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007782 pixel);
7783 number_colors=(unsigned int) (map_info->base_pixel+
7784 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7785 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7786 if ((image->matte == MagickFalse) &&
7787 (resource_info->color_recovery == MagickFalse) &&
7788 resource_info->quantize_info->dither &&
7789 (number_colors < MaxColormapSize))
7790 {
7791 Image
7792 *affinity_image;
7793
cristy4c08aed2011-07-01 19:47:50 +00007794 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007795 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007796
7797 /*
7798 Improve image appearance with error diffusion.
7799 */
cristy9950d572011-10-01 18:22:35 +00007800 affinity_image=AcquireImage((ImageInfo *) NULL,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00007801 if (affinity_image == (Image *) NULL)
7802 ThrowXWindowFatalException(ResourceLimitFatalError,
7803 "UnableToDitherImage",image->filename);
7804 affinity_image->columns=number_colors;
7805 affinity_image->rows=1;
7806 /*
7807 Initialize colormap image.
7808 */
7809 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7810 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007811 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007812 {
cristybb503372010-05-27 20:51:26 +00007813 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007814 {
cristy4c08aed2011-07-01 19:47:50 +00007815 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007816 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007817 SetPixelRed(affinity_image,
7818 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7819 map_info->red_max),q);
7820 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007821 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007822 SetPixelGreen(affinity_image,
7823 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7824 (map_info->green_max+1)),map_info->green_max),q);
7825 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007826 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007827 SetPixelBlue(affinity_image,
7828 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7829 map_info->blue_max),q);
7830 SetPixelAlpha(affinity_image,
7831 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007832 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007833 }
7834 (void) SyncAuthenticPixels(affinity_image,exception);
7835 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007836 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007837 }
cristy4c08aed2011-07-01 19:47:50 +00007838 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007839 pixel);
cristy574cc262011-08-05 01:23:58 +00007840 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007841 affinity_image=DestroyImage(affinity_image);
7842 }
7843 if (IsEventLogging())
7844 {
7845 (void) LogMagickEvent(X11Event,GetMagickModule(),
7846 "Standard Colormap:");
7847 (void) LogMagickEvent(X11Event,GetMagickModule(),
7848 " colormap id: 0x%lx",map_info->colormap);
7849 (void) LogMagickEvent(X11Event,GetMagickModule(),
7850 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7851 map_info->green_max,map_info->blue_max);
7852 (void) LogMagickEvent(X11Event,GetMagickModule(),
7853 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7854 map_info->green_mult,map_info->blue_mult);
7855 }
7856 return;
7857 }
7858 if ((visual_info->klass != DirectColor) &&
7859 (visual_info->klass != TrueColor))
7860 if ((image->storage_class == DirectClass) ||
7861 ((int) image->colors > visual_info->colormap_size))
7862 {
7863 QuantizeInfo
7864 quantize_info;
7865
7866 /*
7867 Image has more colors than the visual supports.
7868 */
7869 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007870 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007871 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007872 }
7873 /*
7874 Free previous and create new colormap.
7875 */
7876 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7877 colormap=XDefaultColormap(display,visual_info->screen);
7878 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7879 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7880 visual_info->visual,visual_info->klass == DirectColor ?
7881 AllocAll : AllocNone);
7882 if (colormap == (Colormap) NULL)
7883 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7884 image->filename);
7885 /*
7886 Initialize the map and pixel info structures.
7887 */
7888 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007889 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007890 /*
7891 Allocating colors in server colormap is based on visual class.
7892 */
7893 switch (visual_info->klass)
7894 {
7895 case StaticGray:
7896 case StaticColor:
7897 {
7898 /*
7899 Define Standard Colormap for StaticGray or StaticColor visual.
7900 */
7901 number_colors=image->colors;
7902 colors=(XColor *) AcquireQuantumMemory((size_t)
7903 visual_info->colormap_size,sizeof(*colors));
7904 if (colors == (XColor *) NULL)
7905 ThrowXWindowFatalException(ResourceLimitFatalError,
7906 "UnableToCreateColormap",image->filename);
7907 p=colors;
7908 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007909 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007910 {
7911 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7912 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7913 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7914 if (visual_info->klass != StaticColor)
7915 {
7916 gray_value=(unsigned short) XPixelIntensity(&color);
7917 color.red=gray_value;
7918 color.green=gray_value;
7919 color.blue=gray_value;
7920 }
7921 status=XAllocColor(display,colormap,&color);
7922 if (status == False)
7923 {
7924 colormap=XCopyColormapAndFree(display,colormap);
7925 (void) XAllocColor(display,colormap,&color);
7926 }
7927 pixel->pixels[i]=color.pixel;
7928 *p++=color;
7929 }
7930 break;
7931 }
7932 case GrayScale:
7933 case PseudoColor:
7934 {
7935 unsigned int
7936 colormap_type;
7937
7938 /*
7939 Define Standard Colormap for GrayScale or PseudoColor visual.
7940 */
7941 number_colors=image->colors;
7942 colors=(XColor *) AcquireQuantumMemory((size_t)
7943 visual_info->colormap_size,sizeof(*colors));
7944 if (colors == (XColor *) NULL)
7945 ThrowXWindowFatalException(ResourceLimitFatalError,
7946 "UnableToCreateColormap",image->filename);
7947 /*
7948 Preallocate our GUI colors.
7949 */
7950 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7951 (void) XAllocColor(display,colormap,&pixel->background_color);
7952 (void) XAllocColor(display,colormap,&pixel->border_color);
7953 (void) XAllocColor(display,colormap,&pixel->matte_color);
7954 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7955 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7956 (void) XAllocColor(display,colormap,&pixel->depth_color);
7957 (void) XAllocColor(display,colormap,&pixel->trough_color);
7958 for (i=0; i < MaxNumberPens; i++)
7959 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7960 /*
7961 Determine if image colors will "fit" into X server colormap.
7962 */
7963 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007964 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007965 NULL,0,pixel->pixels,(unsigned int) image->colors);
7966 if (status != False)
7967 colormap_type=PrivateColormap;
7968 if (colormap_type == SharedColormap)
7969 {
cristyc57f6942010-11-12 01:47:39 +00007970 CacheView
7971 *image_view;
7972
cristy3ed852e2009-09-05 21:47:34 +00007973 DiversityPacket
7974 *diversity;
7975
7976 int
7977 y;
7978
7979 register int
7980 x;
7981
7982 unsigned short
7983 index;
7984
7985 XColor
7986 *server_colors;
7987
7988 /*
7989 Define Standard colormap for shared GrayScale or PseudoColor visual.
7990 */
7991 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7992 sizeof(*diversity));
7993 if (diversity == (DiversityPacket *) NULL)
7994 ThrowXWindowFatalException(ResourceLimitFatalError,
7995 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007996 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007997 {
7998 diversity[i].red=image->colormap[i].red;
7999 diversity[i].green=image->colormap[i].green;
8000 diversity[i].blue=image->colormap[i].blue;
8001 diversity[i].index=(unsigned short) i;
8002 diversity[i].count=0;
8003 }
cristyc57f6942010-11-12 01:47:39 +00008004 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00008005 for (y=0; y < (int) image->rows; y++)
8006 {
cristyc57f6942010-11-12 01:47:39 +00008007 register int
cristy3ed852e2009-09-05 21:47:34 +00008008 x;
8009
cristy4c08aed2011-07-01 19:47:50 +00008010 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00008011 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00008012
cristyc57f6942010-11-12 01:47:39 +00008013 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8014 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008015 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008016 break;
cristyc57f6942010-11-12 01:47:39 +00008017 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008018 {
8019 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008020 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008021 }
cristy3ed852e2009-09-05 21:47:34 +00008022 }
cristyc57f6942010-11-12 01:47:39 +00008023 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008024 /*
8025 Sort colors by decreasing intensity.
8026 */
8027 qsort((void *) diversity,image->colors,sizeof(*diversity),
8028 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008029 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008030 {
8031 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008032 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008033 }
8034 diversity[image->colors-1].count<<=4;
8035 qsort((void *) diversity,image->colors,sizeof(*diversity),
8036 PopularityCompare);
8037 /*
8038 Allocate colors.
8039 */
8040 p=colors;
8041 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008042 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008043 {
8044 index=diversity[i].index;
8045 color.red=
8046 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8047 color.green=
8048 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8049 color.blue=
8050 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8051 if (visual_info->klass != PseudoColor)
8052 {
8053 gray_value=(unsigned short) XPixelIntensity(&color);
8054 color.red=gray_value;
8055 color.green=gray_value;
8056 color.blue=gray_value;
8057 }
8058 status=XAllocColor(display,colormap,&color);
8059 if (status == False)
8060 break;
8061 pixel->pixels[index]=color.pixel;
8062 *p++=color;
8063 }
8064 /*
8065 Read X server colormap.
8066 */
8067 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8068 visual_info->colormap_size,sizeof(*server_colors));
8069 if (server_colors == (XColor *) NULL)
8070 ThrowXWindowFatalException(ResourceLimitFatalError,
8071 "UnableToCreateColormap",image->filename);
8072 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008073 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008074 (void) XQueryColors(display,colormap,server_colors,
8075 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8076 /*
8077 Select remaining colors from X server colormap.
8078 */
cristybb503372010-05-27 20:51:26 +00008079 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008080 {
8081 index=diversity[i].index;
8082 color.red=
8083 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8084 color.green=
8085 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8086 color.blue=
8087 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8088 if (visual_info->klass != PseudoColor)
8089 {
8090 gray_value=(unsigned short) XPixelIntensity(&color);
8091 color.red=gray_value;
8092 color.green=gray_value;
8093 color.blue=gray_value;
8094 }
8095 XBestPixel(display,colormap,server_colors,(unsigned int)
8096 visual_info->colormap_size,&color);
8097 pixel->pixels[index]=color.pixel;
8098 *p++=color;
8099 }
8100 if ((int) image->colors < visual_info->colormap_size)
8101 {
8102 /*
8103 Fill up colors array-- more choices for pen colors.
8104 */
8105 retain_colors=MagickMin((unsigned int)
8106 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008107 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008108 *p++=server_colors[i];
8109 number_colors+=retain_colors;
8110 }
8111 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8112 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8113 break;
8114 }
8115 /*
8116 Define Standard colormap for private GrayScale or PseudoColor visual.
8117 */
8118 if (status == False)
8119 {
8120 /*
8121 Not enough colormap entries in the colormap-- Create a new colormap.
8122 */
8123 colormap=XCreateColormap(display,
8124 XRootWindow(display,visual_info->screen),visual_info->visual,
8125 AllocNone);
8126 if (colormap == (Colormap) NULL)
8127 ThrowXWindowFatalException(ResourceLimitFatalError,
8128 "UnableToCreateColormap",image->filename);
8129 map_info->colormap=colormap;
8130 if ((int) image->colors < visual_info->colormap_size)
8131 {
8132 /*
8133 Retain colors from the default colormap to help lessens the
8134 effects of colormap flashing.
8135 */
8136 retain_colors=MagickMin((unsigned int)
8137 (visual_info->colormap_size-image->colors),256);
8138 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008139 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008140 {
cristyc57f6942010-11-12 01:47:39 +00008141 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008142 p++;
8143 }
8144 (void) XQueryColors(display,
8145 XDefaultColormap(display,visual_info->screen),
8146 colors+image->colors,(int) retain_colors);
8147 /*
8148 Transfer colors from default to private colormap.
8149 */
8150 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008151 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008152 retain_colors);
8153 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008154 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008155 {
8156 p->pixel=pixel->pixels[i];
8157 p++;
8158 }
8159 (void) XStoreColors(display,colormap,colors+image->colors,
8160 (int) retain_colors);
8161 number_colors+=retain_colors;
8162 }
8163 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008164 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008165 image->colors);
8166 }
8167 /*
8168 Store the image colormap.
8169 */
8170 p=colors;
8171 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008172 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008173 {
8174 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8175 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8176 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8177 if (visual_info->klass != PseudoColor)
8178 {
8179 gray_value=(unsigned short) XPixelIntensity(&color);
8180 color.red=gray_value;
8181 color.green=gray_value;
8182 color.blue=gray_value;
8183 }
8184 color.pixel=pixel->pixels[i];
8185 *p++=color;
8186 }
8187 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8188 break;
8189 }
8190 case TrueColor:
8191 case DirectColor:
8192 default:
8193 {
8194 MagickBooleanType
8195 linear_colormap;
8196
8197 /*
8198 Define Standard Colormap for TrueColor or DirectColor visual.
8199 */
8200 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8201 (map_info->green_max*map_info->green_mult)+
8202 (map_info->blue_max*map_info->blue_mult)+1);
8203 linear_colormap=(number_colors > 4096) ||
8204 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8205 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8206 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8207 MagickTrue : MagickFalse;
8208 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008209 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008210 /*
8211 Allocate color array.
8212 */
8213 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8214 if (colors == (XColor *) NULL)
8215 ThrowXWindowFatalException(ResourceLimitFatalError,
8216 "UnableToCreateColormap",image->filename);
8217 /*
8218 Initialize linear color ramp.
8219 */
8220 p=colors;
8221 color.flags=(char) (DoRed | DoGreen | DoBlue);
8222 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008223 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008224 {
8225 color.blue=(unsigned short) 0;
8226 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008227 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008228 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8229 color.green=color.blue;
8230 color.red=color.blue;
8231 color.pixel=XStandardPixel(map_info,&color);
8232 *p++=color;
8233 }
8234 else
cristybb503372010-05-27 20:51:26 +00008235 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008236 {
8237 color.red=(unsigned short) 0;
8238 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008239 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008240 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8241 color.green=(unsigned int) 0;
8242 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008243 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008244 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8245 map_info->green_max));
8246 color.blue=(unsigned short) 0;
8247 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008248 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008249 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8250 color.pixel=XStandardPixel(map_info,&color);
8251 *p++=color;
8252 }
8253 if ((visual_info->klass == DirectColor) &&
8254 (colormap != XDefaultColormap(display,visual_info->screen)))
8255 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8256 else
cristybb503372010-05-27 20:51:26 +00008257 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008258 (void) XAllocColor(display,colormap,&colors[i]);
8259 break;
8260 }
8261 }
8262 if ((visual_info->klass != DirectColor) &&
8263 (visual_info->klass != TrueColor))
8264 {
8265 /*
8266 Set foreground, background, border, etc. pixels.
8267 */
8268 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8269 &pixel->foreground_color);
8270 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8271 &pixel->background_color);
8272 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8273 {
8274 /*
8275 Foreground and background colors must differ.
8276 */
8277 pixel->background_color.red=(~pixel->foreground_color.red);
8278 pixel->background_color.green=
8279 (~pixel->foreground_color.green);
8280 pixel->background_color.blue=
8281 (~pixel->foreground_color.blue);
8282 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8283 &pixel->background_color);
8284 }
8285 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8286 &pixel->border_color);
8287 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8288 &pixel->matte_color);
8289 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8290 &pixel->highlight_color);
8291 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8292 &pixel->shadow_color);
8293 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8294 &pixel->depth_color);
8295 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8296 &pixel->trough_color);
8297 for (i=0; i < MaxNumberPens; i++)
8298 {
8299 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8300 &pixel->pen_colors[i]);
8301 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8302 }
cristyc57f6942010-11-12 01:47:39 +00008303 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008304 }
8305 colors=(XColor *) RelinquishMagickMemory(colors);
8306 if (IsEventLogging())
8307 {
8308 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8309 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8310 map_info->colormap);
8311 (void) LogMagickEvent(X11Event,GetMagickModule(),
8312 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8313 map_info->green_max,map_info->blue_max);
8314 (void) LogMagickEvent(X11Event,GetMagickModule(),
8315 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8316 map_info->green_mult,map_info->blue_mult);
8317 }
8318}
8319
8320/*
8321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8322% %
8323% %
8324% %
8325% X M a k e W i n d o w %
8326% %
8327% %
8328% %
8329%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8330%
8331% XMakeWindow() creates an X11 window.
8332%
8333% The format of the XMakeWindow method is:
8334%
8335% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8336% XClassHint *class_hint,XWMHints *manager_hints,
8337% XWindowInfo *window_info)
8338%
8339% A description of each parameter follows:
8340%
8341% o display: Specifies a connection to an X server; returned from
8342% XOpenDisplay.
8343%
8344% o parent: Specifies the parent window_info.
8345%
8346% o argv: Specifies the application's argument list.
8347%
8348% o argc: Specifies the number of arguments.
8349%
8350% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8351%
8352% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8353%
8354% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8355%
8356*/
cristybcbda3f2011-09-03 13:01:22 +00008357MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008358 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8359 XWindowInfo *window_info)
8360{
8361#define MinWindowSize 64
8362
8363 Atom
8364 atom_list[2];
8365
8366 int
8367 gravity;
8368
8369 static XTextProperty
8370 icon_name,
8371 window_name;
8372
8373 Status
8374 status;
8375
8376 XSizeHints
8377 *size_hints;
8378
8379 /*
8380 Set window info hints.
8381 */
8382 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8383 assert(display != (Display *) NULL);
8384 assert(window_info != (XWindowInfo *) NULL);
8385 size_hints=XAllocSizeHints();
8386 if (size_hints == (XSizeHints *) NULL)
8387 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008388 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008389 size_hints->x=window_info->x;
8390 size_hints->y=window_info->y;
8391 size_hints->width=(int) window_info->width;
8392 size_hints->height=(int) window_info->height;
8393 if (window_info->immutable != MagickFalse)
8394 {
8395 /*
8396 Window size cannot be changed.
8397 */
8398 size_hints->min_width=size_hints->width;
8399 size_hints->min_height=size_hints->height;
8400 size_hints->max_width=size_hints->width;
8401 size_hints->max_height=size_hints->height;
8402 size_hints->flags|=PMinSize;
8403 size_hints->flags|=PMaxSize;
8404 }
8405 else
8406 {
8407 /*
8408 Window size can be changed.
8409 */
8410 size_hints->min_width=(int) window_info->min_width;
8411 size_hints->min_height=(int) window_info->min_height;
8412 size_hints->flags|=PResizeInc;
8413 size_hints->width_inc=(int) window_info->width_inc;
8414 size_hints->height_inc=(int) window_info->height_inc;
8415#if !defined(PRE_R4_ICCCM)
8416 size_hints->flags|=PBaseSize;
8417 size_hints->base_width=size_hints->width_inc;
8418 size_hints->base_height=size_hints->height_inc;
8419#endif
8420 }
8421 gravity=NorthWestGravity;
8422 if (window_info->geometry != (char *) NULL)
8423 {
8424 char
8425 default_geometry[MaxTextExtent],
8426 geometry[MaxTextExtent];
8427
8428 int
8429 flags;
8430
8431 register char
8432 *p;
8433
8434 /*
8435 User specified geometry.
8436 */
cristyb51dff52011-05-19 16:55:47 +00008437 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008438 size_hints->width,size_hints->height);
8439 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8440 p=geometry;
8441 while (strlen(p) != 0)
8442 {
8443 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8444 p++;
8445 else
8446 (void) CopyMagickString(p,p+1,MaxTextExtent);
8447 }
8448 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8449 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8450 &size_hints->width,&size_hints->height,&gravity);
8451 if ((flags & WidthValue) && (flags & HeightValue))
8452 size_hints->flags|=USSize;
8453 if ((flags & XValue) && (flags & YValue))
8454 {
8455 size_hints->flags|=USPosition;
8456 window_info->x=size_hints->x;
8457 window_info->y=size_hints->y;
8458 }
8459 }
8460#if !defined(PRE_R4_ICCCM)
8461 size_hints->win_gravity=gravity;
8462 size_hints->flags|=PWinGravity;
8463#endif
8464 if (window_info->id == (Window) NULL)
8465 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8466 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8467 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008468 window_info->visual,(unsigned long) window_info->mask,
8469 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008470 else
8471 {
8472 MagickStatusType
8473 mask;
8474
8475 XEvent
8476 sans_event;
8477
8478 XWindowChanges
8479 window_changes;
8480
8481 /*
8482 Window already exists; change relevant attributes.
8483 */
cristyc57f6942010-11-12 01:47:39 +00008484 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8485 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008486 mask=ConfigureNotify;
8487 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8488 window_changes.x=window_info->x;
8489 window_changes.y=window_info->y;
8490 window_changes.width=(int) window_info->width;
8491 window_changes.height=(int) window_info->height;
8492 mask=(MagickStatusType) (CWWidth | CWHeight);
8493 if (window_info->flags & USPosition)
8494 mask|=CWX | CWY;
8495 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8496 mask,&window_changes);
8497 }
8498 if (window_info->id == (Window) NULL)
8499 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8500 window_info->name);
8501 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8502 if (status == False)
8503 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8504 window_info->name);
8505 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8506 if (status == False)
8507 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8508 window_info->icon_name);
8509 if (window_info->icon_geometry != (char *) NULL)
8510 {
8511 int
8512 flags,
8513 height,
8514 width;
8515
8516 /*
8517 User specified icon geometry.
8518 */
8519 size_hints->flags|=USPosition;
8520 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8521 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8522 &manager_hints->icon_y,&width,&height,&gravity);
8523 if ((flags & XValue) && (flags & YValue))
8524 manager_hints->flags|=IconPositionHint;
8525 }
8526 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8527 size_hints,manager_hints,class_hint);
8528 if (window_name.value != (void *) NULL)
8529 {
8530 (void) XFree((void *) window_name.value);
8531 window_name.value=(unsigned char *) NULL;
8532 window_name.nitems=0;
8533 }
8534 if (icon_name.value != (void *) NULL)
8535 {
8536 (void) XFree((void *) icon_name.value);
8537 icon_name.value=(unsigned char *) NULL;
8538 icon_name.nitems=0;
8539 }
8540 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8541 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8542 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8543 (void) XFree((void *) size_hints);
8544 if (window_info->shape != MagickFalse)
8545 {
8546#if defined(MAGICKCORE_HAVE_SHAPE)
8547 int
8548 error_base,
8549 event_base;
8550
8551 /*
8552 Can we apply a non-rectangular shaping mask?
8553 */
8554 error_base=0;
8555 event_base=0;
8556 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8557 window_info->shape=MagickFalse;
8558#else
8559 window_info->shape=MagickFalse;
8560#endif
8561 }
8562 if (window_info->shared_memory)
8563 {
8564#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8565 /*
8566 Can we use shared memory with this window?
8567 */
8568 if (XShmQueryExtension(display) == 0)
8569 window_info->shared_memory=MagickFalse;
8570#else
8571 window_info->shared_memory=MagickFalse;
8572#endif
8573 }
8574 window_info->image=NewImageList();
8575 window_info->destroy=MagickFalse;
8576}
8577
8578/*
8579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8580% %
8581% %
8582% %
8583% X M a g i c k P r o g r e s s M o n i t o r %
8584% %
8585% %
8586% %
8587%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8588%
8589% XMagickProgressMonitor() displays the progress a task is making in
8590% completing a task.
8591%
8592% The format of the XMagickProgressMonitor method is:
8593%
8594% void XMagickProgressMonitor(const char *task,
8595% const MagickOffsetType quantum,const MagickSizeType span,
8596% void *client_data)
8597%
8598% A description of each parameter follows:
8599%
8600% o task: Identifies the task in progress.
8601%
8602% o quantum: Specifies the quantum position within the span which represents
8603% how much progress has been made in completing a task.
8604%
8605% o span: Specifies the span relative to completing a task.
8606%
8607% o client_data: Pointer to any client data.
8608%
8609*/
8610
8611static const char *GetLocaleMonitorMessage(const char *text)
8612{
8613 char
8614 message[MaxTextExtent],
8615 tag[MaxTextExtent];
8616
8617 const char
8618 *locale_message;
8619
8620 register char
8621 *p;
8622
8623 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8624 p=strrchr(tag,'/');
8625 if (p != (char *) NULL)
8626 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008627 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008628 locale_message=GetLocaleMessage(message);
8629 if (locale_message == message)
8630 return(text);
8631 return(locale_message);
8632}
8633
cristybcbda3f2011-09-03 13:01:22 +00008634MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008635 const MagickOffsetType quantum,const MagickSizeType span,
8636 void *magick_unused(client_data))
8637{
8638 XWindows
8639 *windows;
8640
8641 windows=XSetWindows((XWindows *) ~0);
8642 if (windows == (XWindows *) NULL)
8643 return(MagickTrue);
8644 if (windows->info.mapped != MagickFalse)
8645 XProgressMonitorWidget(windows->display,windows,
8646 GetLocaleMonitorMessage(tag),quantum,span);
8647 return(MagickTrue);
8648}
8649
8650/*
8651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8652% %
8653% %
8654% %
8655% X Q u e r y C o l o r D a t a b a s e %
8656% %
8657% %
8658% %
8659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8660%
cristy9950d572011-10-01 18:22:35 +00008661% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008662% string.
8663%
8664% The format of the XQueryColorDatabase method is:
8665%
cristy9950d572011-10-01 18:22:35 +00008666% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008667%
8668% A description of each parameter follows:
8669%
8670% o target: Specifies the color to lookup in the X color database.
8671%
cristy101ab702011-10-13 13:06:32 +00008672% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008673% color is returned as this value.
8674%
8675*/
cristy9950d572011-10-01 18:22:35 +00008676MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008677 XColor *color)
8678{
8679 Colormap
8680 colormap;
8681
8682 static Display
8683 *display = (Display *) NULL;
8684
8685 Status
8686 status;
8687
8688 XColor
8689 xcolor;
8690
8691 /*
8692 Initialize color return value.
8693 */
8694 assert(color != (XColor *) NULL);
8695 color->red=0;
8696 color->green=0;
8697 color->blue=0;
8698 color->flags=(char) (DoRed | DoGreen | DoBlue);
8699 if ((target == (char *) NULL) || (*target == '\0'))
8700 target="#ffffffffffff";
8701 /*
8702 Let the X server define the color for us.
8703 */
8704 if (display == (Display *) NULL)
8705 display=XOpenDisplay((char *) NULL);
8706 if (display == (Display *) NULL)
8707 {
8708 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8709 return(MagickFalse);
8710 }
8711 colormap=XDefaultColormap(display,XDefaultScreen(display));
8712 status=XParseColor(display,colormap,(char *) target,&xcolor);
8713 if (status == False)
8714 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8715 else
8716 {
8717 color->red=xcolor.red;
8718 color->green=xcolor.green;
8719 color->blue=xcolor.blue;
8720 color->flags=xcolor.flags;
8721 }
8722 return(status != False ? MagickTrue : MagickFalse);
8723}
8724
8725/*
8726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8727% %
8728% %
8729% %
8730% X Q u e r y P o s i t i o n %
8731% %
8732% %
8733% %
8734%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8735%
8736% XQueryPosition() gets the pointer coordinates relative to a window.
8737%
8738% The format of the XQueryPosition method is:
8739%
8740% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8741%
8742% A description of each parameter follows:
8743%
8744% o display: Specifies a connection to an X server; returned from
8745% XOpenDisplay.
8746%
8747% o window: Specifies a pointer to a Window.
8748%
8749% o x: Return the x coordinate of the pointer relative to the origin of the
8750% window.
8751%
8752% o y: Return the y coordinate of the pointer relative to the origin of the
8753% window.
8754%
8755*/
cristybcbda3f2011-09-03 13:01:22 +00008756MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008757{
8758 int
8759 x_root,
8760 y_root;
8761
8762 unsigned int
8763 mask;
8764
8765 Window
8766 root_window;
8767
8768 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8769 assert(display != (Display *) NULL);
8770 assert(window != (Window) NULL);
8771 assert(x != (int *) NULL);
8772 assert(y != (int *) NULL);
8773 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8774 x,y,&mask);
8775}
8776
8777/*
8778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8779% %
8780% %
8781% %
8782% X R e f r e s h W i n d o w %
8783% %
8784% %
8785% %
8786%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8787%
8788% XRefreshWindow() refreshes an image in a X window.
8789%
8790% The format of the XRefreshWindow method is:
8791%
8792% void XRefreshWindow(Display *display,const XWindowInfo *window,
8793% const XEvent *event)
8794%
8795% A description of each parameter follows:
8796%
8797% o display: Specifies a connection to an X server; returned from
8798% XOpenDisplay.
8799%
8800% o window: Specifies a pointer to a XWindowInfo structure.
8801%
8802% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8803% the entire image is refreshed.
8804%
8805*/
cristybcbda3f2011-09-03 13:01:22 +00008806MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008807 const XEvent *event)
8808{
8809 int
8810 x,
8811 y;
8812
8813 unsigned int
8814 height,
8815 width;
8816
8817 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8818 assert(display != (Display *) NULL);
8819 assert(window != (XWindowInfo *) NULL);
8820 if (window->ximage == (XImage *) NULL)
8821 return;
8822 if (event != (XEvent *) NULL)
8823 {
8824 /*
8825 Determine geometry from expose event.
8826 */
8827 x=event->xexpose.x;
8828 y=event->xexpose.y;
8829 width=(unsigned int) event->xexpose.width;
8830 height=(unsigned int) event->xexpose.height;
8831 }
8832 else
8833 {
8834 XEvent
8835 sans_event;
8836
8837 /*
8838 Refresh entire window; discard outstanding expose events.
8839 */
8840 x=0;
8841 y=0;
8842 width=window->width;
8843 height=window->height;
8844 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008845 if (window->matte_pixmap != (Pixmap) NULL)
8846 {
8847#if defined(MAGICKCORE_HAVE_SHAPE)
8848 if (window->shape != MagickFalse)
8849 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8850 window->matte_pixmap,ShapeSet);
8851#endif
8852 }
cristy3ed852e2009-09-05 21:47:34 +00008853 }
8854 /*
8855 Check boundary conditions.
8856 */
8857 if ((window->ximage->width-(x+window->x)) < (int) width)
8858 width=(unsigned int) (window->ximage->width-(x+window->x));
8859 if ((window->ximage->height-(y+window->y)) < (int) height)
8860 height=(unsigned int) (window->ximage->height-(y+window->y));
8861 /*
8862 Refresh image.
8863 */
8864 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008865 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008866 if (window->pixmap != (Pixmap) NULL)
8867 {
8868 if (window->depth > 1)
8869 (void) XCopyArea(display,window->pixmap,window->id,
8870 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8871 else
8872 (void) XCopyPlane(display,window->pixmap,window->id,
8873 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8874 1L);
8875 }
8876 else
8877 {
8878#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8879 if (window->shared_memory)
8880 (void) XShmPutImage(display,window->id,window->annotate_context,
8881 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8882#endif
8883 if (window->shared_memory == MagickFalse)
8884 (void) XPutImage(display,window->id,window->annotate_context,
8885 window->ximage,x+window->x,y+window->y,x,y,width,height);
8886 }
8887 if (window->matte_pixmap != (Pixmap) NULL)
8888 (void) XSetClipMask(display,window->annotate_context,None);
8889 (void) XFlush(display);
8890}
8891
8892/*
8893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8894% %
8895% %
8896% %
8897% X R e m o t e C o m m a n d %
8898% %
8899% %
8900% %
8901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8902%
8903% XRemoteCommand() forces a remote display(1) to display the specified
8904% image filename.
8905%
8906% The format of the XRemoteCommand method is:
8907%
8908% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8909% const char *filename)
8910%
8911% A description of each parameter follows:
8912%
8913% o display: Specifies a connection to an X server; returned from
8914% XOpenDisplay.
8915%
8916% o window: Specifies the name or id of an X window.
8917%
8918% o filename: the name of the image filename to display.
8919%
8920*/
8921MagickExport MagickBooleanType XRemoteCommand(Display *display,
8922 const char *window,const char *filename)
8923{
8924 Atom
8925 remote_atom;
8926
8927 Window
8928 remote_window,
8929 root_window;
8930
8931 assert(filename != (char *) NULL);
8932 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8933 if (display == (Display *) NULL)
8934 display=XOpenDisplay((char *) NULL);
8935 if (display == (Display *) NULL)
8936 {
8937 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8938 return(MagickFalse);
8939 }
8940 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8941 remote_window=(Window) NULL;
8942 root_window=XRootWindow(display,XDefaultScreen(display));
8943 if (window != (char *) NULL)
8944 {
8945 /*
8946 Search window hierarchy and identify any clients by name or ID.
8947 */
8948 if (isdigit((unsigned char) *window) != 0)
8949 remote_window=XWindowByID(display,root_window,(Window)
8950 strtol((char *) window,(char **) NULL,0));
8951 if (remote_window == (Window) NULL)
8952 remote_window=XWindowByName(display,root_window,window);
8953 }
8954 if (remote_window == (Window) NULL)
8955 remote_window=XWindowByProperty(display,root_window,remote_atom);
8956 if (remote_window == (Window) NULL)
8957 {
8958 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8959 filename);
8960 return(MagickFalse);
8961 }
8962 /*
8963 Send remote command.
8964 */
8965 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8966 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8967 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8968 (void) XSync(display,MagickFalse);
8969 return(MagickTrue);
8970}
8971
8972/*
8973%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8974% %
8975% %
8976% %
8977% X R e t a i n W i n d o w C o l o r s %
8978% %
8979% %
8980% %
8981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8982%
8983% XRetainWindowColors() sets X11 color resources on a window. This preserves
8984% the colors associated with an image displayed on the window.
8985%
8986% The format of the XRetainWindowColors method is:
8987%
8988% void XRetainWindowColors(Display *display,const Window window)
8989%
8990% A description of each parameter follows:
8991%
8992% o display: Specifies a connection to an X server; returned from
8993% XOpenDisplay.
8994%
8995% o window: Specifies a pointer to a XWindowInfo structure.
8996%
8997*/
8998MagickExport void XRetainWindowColors(Display *display,const Window window)
8999{
9000 Atom
9001 property;
9002
9003 Pixmap
9004 pixmap;
9005
9006 /*
9007 Put property on the window.
9008 */
9009 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9010 assert(display != (Display *) NULL);
9011 assert(window != (Window) NULL);
9012 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9013 if (property == (Atom) NULL)
9014 {
9015 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9016 "_XSETROOT_ID");
9017 return;
9018 }
9019 pixmap=XCreatePixmap(display,window,1,1,1);
9020 if (pixmap == (Pixmap) NULL)
9021 {
9022 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9023 return;
9024 }
9025 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9026 (unsigned char *) &pixmap,1);
9027 (void) XSetCloseDownMode(display,RetainPermanent);
9028}
9029
9030/*
9031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9032% %
9033% %
9034% %
9035% X S e l e c t W i n d o w %
9036% %
9037% %
9038% %
9039%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9040%
9041% XSelectWindow() allows a user to select a window using the mouse. If the
9042% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9043% is returned in the crop_info structure.
9044%
9045% The format of the XSelectWindow function is:
9046%
9047% target_window=XSelectWindow(display,crop_info)
9048%
9049% A description of each parameter follows:
9050%
9051% o window: XSelectWindow returns the window id.
9052%
9053% o display: Specifies a pointer to the Display structure; returned from
9054% XOpenDisplay.
9055%
9056% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9057% contains the extents of any cropping rectangle.
9058%
cristy3ed852e2009-09-05 21:47:34 +00009059*/
9060static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9061{
9062#define MinimumCropArea (unsigned int) 9
9063
9064 Cursor
9065 target_cursor;
9066
9067 GC
9068 annotate_context;
9069
9070 int
9071 presses,
9072 x_offset,
9073 y_offset;
9074
9075 Status
9076 status;
9077
9078 Window
9079 root_window,
9080 target_window;
9081
9082 XEvent
9083 event;
9084
9085 XGCValues
9086 context_values;
9087
9088 /*
9089 Initialize graphic context.
9090 */
9091 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9092 assert(display != (Display *) NULL);
9093 assert(crop_info != (RectangleInfo *) NULL);
9094 root_window=XRootWindow(display,XDefaultScreen(display));
9095 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9096 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9097 context_values.function=GXinvert;
9098 context_values.plane_mask=
9099 context_values.background ^ context_values.foreground;
9100 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009101 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009102 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9103 if (annotate_context == (GC) NULL)
9104 return(MagickFalse);
9105 /*
9106 Grab the pointer using target cursor.
9107 */
9108 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9109 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9110 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9111 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9112 GrabModeAsync,root_window,target_cursor,CurrentTime);
9113 if (status != GrabSuccess)
9114 {
9115 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9116 return((Window) NULL);
9117 }
9118 /*
9119 Select a window.
9120 */
9121 crop_info->width=0;
9122 crop_info->height=0;
9123 presses=0;
9124 target_window=(Window) NULL;
9125 x_offset=0;
9126 y_offset=0;
9127 do
9128 {
9129 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9130 (void) XDrawRectangle(display,root_window,annotate_context,
9131 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9132 (unsigned int) crop_info->height-1);
9133 /*
9134 Allow another event.
9135 */
9136 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9137 (void) XWindowEvent(display,root_window,ButtonPressMask |
9138 ButtonReleaseMask | ButtonMotionMask,&event);
9139 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9140 (void) XDrawRectangle(display,root_window,annotate_context,
9141 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9142 (unsigned int) crop_info->height-1);
9143 switch (event.type)
9144 {
9145 case ButtonPress:
9146 {
9147 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9148 event.xbutton.x,event.xbutton.y);
9149 if (target_window == (Window) NULL)
9150 target_window=root_window;
9151 x_offset=event.xbutton.x_root;
9152 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009153 crop_info->x=(ssize_t) x_offset;
9154 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009155 crop_info->width=0;
9156 crop_info->height=0;
9157 presses++;
9158 break;
9159 }
9160 case ButtonRelease:
9161 {
9162 presses--;
9163 break;
9164 }
9165 case MotionNotify:
9166 {
9167 /*
9168 Discard pending button motion events.
9169 */
9170 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009171 crop_info->x=(ssize_t) event.xmotion.x;
9172 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009173 /*
9174 Check boundary conditions.
9175 */
9176 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009177 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009178 else
9179 {
cristyecd0ab52010-05-30 14:59:20 +00009180 crop_info->width=(size_t) (crop_info->x-x_offset);
9181 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009182 }
9183 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009184 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009185 else
9186 {
cristyecd0ab52010-05-30 14:59:20 +00009187 crop_info->height=(size_t) (crop_info->y-y_offset);
9188 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009189 }
9190 }
9191 default:
9192 break;
9193 }
9194 } while ((target_window == (Window) NULL) || (presses > 0));
9195 (void) XUngrabPointer(display,CurrentTime);
9196 (void) XFreeCursor(display,target_cursor);
9197 (void) XFreeGC(display,annotate_context);
9198 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9199 {
9200 crop_info->width=0;
9201 crop_info->height=0;
9202 }
9203 if ((crop_info->width != 0) && (crop_info->height != 0))
9204 target_window=root_window;
9205 return(target_window);
9206}
9207
9208/*
9209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9210% %
9211% %
9212% %
9213% X S e t C u r s o r S t a t e %
9214% %
9215% %
9216% %
9217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9218%
9219% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9220% reset to their default.
9221%
9222% The format of the XXSetCursorState method is:
9223%
9224% XSetCursorState(display,windows,const MagickStatusType state)
9225%
9226% A description of each parameter follows:
9227%
9228% o display: Specifies a connection to an X server; returned from
9229% XOpenDisplay.
9230%
9231% o windows: Specifies a pointer to a XWindows structure.
9232%
9233% o state: An unsigned integer greater than 0 sets the cursor state
9234% to busy, otherwise the cursor are reset to their default.
9235%
9236*/
cristybcbda3f2011-09-03 13:01:22 +00009237MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009238 const MagickStatusType state)
9239{
9240 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9241 assert(display != (Display *) NULL);
9242 assert(windows != (XWindows *) NULL);
9243 if (state)
9244 {
9245 (void) XCheckDefineCursor(display,windows->image.id,
9246 windows->image.busy_cursor);
9247 (void) XCheckDefineCursor(display,windows->pan.id,
9248 windows->pan.busy_cursor);
9249 (void) XCheckDefineCursor(display,windows->magnify.id,
9250 windows->magnify.busy_cursor);
9251 (void) XCheckDefineCursor(display,windows->command.id,
9252 windows->command.busy_cursor);
9253 }
9254 else
9255 {
9256 (void) XCheckDefineCursor(display,windows->image.id,
9257 windows->image.cursor);
9258 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9259 (void) XCheckDefineCursor(display,windows->magnify.id,
9260 windows->magnify.cursor);
9261 (void) XCheckDefineCursor(display,windows->command.id,
9262 windows->command.cursor);
9263 (void) XCheckDefineCursor(display,windows->command.id,
9264 windows->widget.cursor);
9265 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9266 }
9267 windows->info.mapped=MagickFalse;
9268}
9269
9270/*
9271%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9272% %
9273% %
9274% %
9275% X S e t W i n d o w s %
9276% %
9277% %
9278% %
9279%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9280%
9281% XSetWindows() sets the X windows structure if the windows info is specified.
9282% Otherwise the current windows structure is returned.
9283%
9284% The format of the XSetWindows method is:
9285%
9286% XWindows *XSetWindows(XWindows *windows_info)
9287%
9288% A description of each parameter follows:
9289%
9290% o windows_info: Initialize the Windows structure with this information.
9291%
9292*/
cristybcbda3f2011-09-03 13:01:22 +00009293MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009294{
9295 static XWindows
9296 *windows = (XWindows *) NULL;
9297
9298 if (windows_info != (XWindows *) ~0)
9299 {
9300 windows=(XWindows *) RelinquishMagickMemory(windows);
9301 windows=windows_info;
9302 }
9303 return(windows);
9304}
9305/*
9306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9307% %
9308% %
9309% %
9310% X U s e r P r e f e r e n c e s %
9311% %
9312% %
9313% %
9314%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9315%
9316% XUserPreferences() saves the preferences in a configuration file in the
9317% users' home directory.
9318%
9319% The format of the XUserPreferences method is:
9320%
9321% void XUserPreferences(XResourceInfo *resource_info)
9322%
9323% A description of each parameter follows:
9324%
9325% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9326%
9327*/
cristybcbda3f2011-09-03 13:01:22 +00009328MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009329{
9330#if defined(X11_PREFERENCES_PATH)
9331 char
9332 cache[MaxTextExtent],
9333 filename[MaxTextExtent],
9334 specifier[MaxTextExtent];
9335
9336 const char
cristy104cea82009-10-25 02:26:51 +00009337 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009338 *value;
9339
9340 XrmDatabase
9341 preferences_database;
9342
9343 /*
9344 Save user preferences to the client configuration file.
9345 */
9346 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009347 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009348 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009349 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009350 value=resource_info->backdrop ? "True" : "False";
9351 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009352 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009353 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9354 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009355 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009356 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009357 value=resource_info->confirm_exit ? "True" : "False";
9358 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009359 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009360 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009361 value=resource_info->confirm_edit ? "True" : "False";
9362 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009363 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009364 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009365 value=resource_info->display_warnings ? "True" : "False";
9366 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009367 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009368 value=resource_info->quantize_info->dither ? "True" : "False";
9369 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009370 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009371 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009372 value=resource_info->gamma_correct ? "True" : "False";
9373 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009374 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9375 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009376 resource_info->undo_cache);
9377 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009378 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009379 value=resource_info->use_pixmap ? "True" : "False";
9380 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009381 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009382 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009383 ExpandFilename(filename);
9384 XrmPutFileDatabase(preferences_database,filename);
9385#endif
9386}
9387
9388/*
9389%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9390% %
9391% %
9392% %
9393% X V i s u a l C l a s s N a m e %
9394% %
9395% %
9396% %
9397%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9398%
9399% XVisualClassName() returns the visual class name as a character string.
9400%
9401% The format of the XVisualClassName method is:
9402%
9403% char *XVisualClassName(const int visual_class)
9404%
9405% A description of each parameter follows:
9406%
9407% o visual_type: XVisualClassName returns the visual class as a character
9408% string.
9409%
9410% o class: Specifies the visual class.
9411%
cristy3ed852e2009-09-05 21:47:34 +00009412*/
9413static const char *XVisualClassName(const int visual_class)
9414{
9415 switch (visual_class)
9416 {
9417 case StaticGray: return("StaticGray");
9418 case GrayScale: return("GrayScale");
9419 case StaticColor: return("StaticColor");
9420 case PseudoColor: return("PseudoColor");
9421 case TrueColor: return("TrueColor");
9422 case DirectColor: return("DirectColor");
9423 }
9424 return("unknown visual class");
9425}
9426
9427/*
9428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9429% %
9430% %
9431% %
9432% X W a r n i n g %
9433% %
9434% %
9435% %
9436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9437%
9438% XWarning() displays a warning reason in a Notice widget.
9439%
9440% The format of the XWarning method is:
9441%
9442% void XWarning(const unsigned int warning,const char *reason,
9443% const char *description)
9444%
9445% A description of each parameter follows:
9446%
9447% o warning: Specifies the numeric warning category.
9448%
9449% o reason: Specifies the reason to display before terminating the
9450% program.
9451%
9452% o description: Specifies any description to the reason.
9453%
9454*/
cristybcbda3f2011-09-03 13:01:22 +00009455MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009456 const char *reason,const char *description)
9457{
9458 char
9459 text[MaxTextExtent];
9460
9461 XWindows
9462 *windows;
9463
9464 if (reason == (char *) NULL)
9465 return;
9466 (void) CopyMagickString(text,reason,MaxTextExtent);
9467 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9468 windows=XSetWindows((XWindows *) ~0);
9469 XNoticeWidget(windows->display,windows,text,(char *) description);
9470}
9471
9472/*
9473%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9474% %
9475% %
9476% %
9477% X W i n d o w B y I D %
9478% %
9479% %
9480% %
9481%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9482%
9483% XWindowByID() locates a child window with a given ID. If not window with
9484% the given name is found, 0 is returned. Only the window specified and its
9485% subwindows are searched.
9486%
9487% The format of the XWindowByID function is:
9488%
9489% child=XWindowByID(display,window,id)
9490%
9491% A description of each parameter follows:
9492%
9493% o child: XWindowByID returns the window with the specified
9494% id. If no windows are found, XWindowByID returns 0.
9495%
9496% o display: Specifies a pointer to the Display structure; returned from
9497% XOpenDisplay.
9498%
9499% o id: Specifies the id of the window to locate.
9500%
9501*/
cristybcbda3f2011-09-03 13:01:22 +00009502MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009503 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009504{
9505 RectangleInfo
9506 rectangle_info;
9507
9508 register int
9509 i;
9510
9511 Status
9512 status;
9513
9514 unsigned int
9515 number_children;
9516
9517 Window
9518 child,
9519 *children,
9520 window;
9521
9522 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9523 assert(display != (Display *) NULL);
9524 assert(root_window != (Window) NULL);
9525 if (id == 0)
9526 return(XSelectWindow(display,&rectangle_info));
9527 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009528 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009529 status=XQueryTree(display,root_window,&child,&child,&children,
9530 &number_children);
9531 if (status == False)
9532 return((Window) NULL);
9533 window=(Window) NULL;
9534 for (i=0; i < (int) number_children; i++)
9535 {
9536 /*
9537 Search each child and their children.
9538 */
9539 window=XWindowByID(display,children[i],id);
9540 if (window != (Window) NULL)
9541 break;
9542 }
9543 if (children != (Window *) NULL)
9544 (void) XFree((void *) children);
9545 return(window);
9546}
9547
9548/*
9549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9550% %
9551% %
9552% %
9553% X W i n d o w B y N a m e %
9554% %
9555% %
9556% %
9557%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9558%
9559% XWindowByName() locates a window with a given name on a display. If no
9560% window with the given name is found, 0 is returned. If more than one window
9561% has the given name, the first one is returned. Only root and its children
9562% are searched.
9563%
9564% The format of the XWindowByName function is:
9565%
9566% window=XWindowByName(display,root_window,name)
9567%
9568% A description of each parameter follows:
9569%
9570% o window: XWindowByName returns the window id.
9571%
9572% o display: Specifies a pointer to the Display structure; returned from
9573% XOpenDisplay.
9574%
9575% o root_window: Specifies the id of the root window.
9576%
9577% o name: Specifies the name of the window to locate.
9578%
9579*/
cristybcbda3f2011-09-03 13:01:22 +00009580MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009581 const char *name)
9582{
9583 register int
9584 i;
9585
9586 Status
9587 status;
9588
9589 unsigned int
9590 number_children;
9591
9592 Window
9593 *children,
9594 child,
9595 window;
9596
9597 XTextProperty
9598 window_name;
9599
9600 assert(display != (Display *) NULL);
9601 assert(root_window != (Window) NULL);
9602 assert(name != (char *) NULL);
9603 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9604 if (XGetWMName(display,root_window,&window_name) != 0)
9605 if (LocaleCompare((char *) window_name.value,name) == 0)
9606 return(root_window);
9607 status=XQueryTree(display,root_window,&child,&child,&children,
9608 &number_children);
9609 if (status == False)
9610 return((Window) NULL);
9611 window=(Window) NULL;
9612 for (i=0; i < (int) number_children; i++)
9613 {
9614 /*
9615 Search each child and their children.
9616 */
9617 window=XWindowByName(display,children[i],name);
9618 if (window != (Window) NULL)
9619 break;
9620 }
9621 if (children != (Window *) NULL)
9622 (void) XFree((void *) children);
9623 return(window);
9624}
9625
9626/*
9627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9628% %
9629% %
9630% %
9631% X W i n d o w B y P r o p e r y %
9632% %
9633% %
9634% %
9635%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9636%
9637% XWindowByProperty() locates a child window with a given property. If not
9638% window with the given name is found, 0 is returned. If more than one window
9639% has the given property, the first one is returned. Only the window
9640% specified and its subwindows are searched.
9641%
9642% The format of the XWindowByProperty function is:
9643%
9644% child=XWindowByProperty(display,window,property)
9645%
9646% A description of each parameter follows:
9647%
9648% o child: XWindowByProperty returns the window id with the specified
9649% property. If no windows are found, XWindowByProperty returns 0.
9650%
9651% o display: Specifies a pointer to the Display structure; returned from
9652% XOpenDisplay.
9653%
9654% o property: Specifies the property of the window to locate.
9655%
9656*/
cristybcbda3f2011-09-03 13:01:22 +00009657MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009658 const Atom property)
9659{
9660 Atom
9661 type;
9662
9663 int
9664 format;
9665
9666 Status
9667 status;
9668
9669 unsigned char
9670 *data;
9671
9672 unsigned int
9673 i,
9674 number_children;
9675
cristyf2faecf2010-05-28 19:19:36 +00009676 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009677 after,
9678 number_items;
9679
9680 Window
9681 child,
9682 *children,
9683 parent,
9684 root;
9685
9686 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9687 assert(display != (Display *) NULL);
9688 assert(window != (Window) NULL);
9689 assert(property != (Atom) NULL);
9690 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9691 if (status == False)
9692 return((Window) NULL);
9693 type=(Atom) NULL;
9694 child=(Window) NULL;
9695 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9696 {
9697 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9698 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9699 if (data != NULL)
9700 (void) XFree((void *) data);
9701 if ((status == Success) && (type != (Atom) NULL))
9702 child=children[i];
9703 }
9704 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9705 child=XWindowByProperty(display,children[i],property);
9706 if (children != (Window *) NULL)
9707 (void) XFree((void *) children);
9708 return(child);
9709}
9710#else
9711
9712/*
9713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9714% %
9715% %
9716% %
9717% X I m p o r t I m a g e %
9718% %
9719% %
9720% %
9721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9722%
9723% XImportImage() reads an image from an X window.
9724%
9725% The format of the XImportImage method is:
9726%
9727% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9728%
9729% A description of each parameter follows:
9730%
9731% o image_info: the image info..
9732%
9733% o ximage_info: Specifies a pointer to an XImportInfo structure.
9734%
9735*/
cristybcbda3f2011-09-03 13:01:22 +00009736MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00009737 XImportInfo *ximage_info)
9738{
9739 assert(image_info != (const ImageInfo *) NULL);
9740 assert(image_info->signature == MagickSignature);
9741 if (image_info->debug != MagickFalse)
9742 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9743 image_info->filename);
9744 assert(ximage_info != (XImportInfo *) NULL);
9745 return((Image *) NULL);
9746}
9747#endif
9748
9749/*
9750%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9751% %
9752% %
9753% %
cristy576974e2009-10-25 20:45:31 +00009754+ X C o m p o n e n t G e n e s i s %
9755% %
9756% %
9757% %
9758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9759%
9760% XComponentGenesis() instantiates the X component.
9761%
9762% The format of the XComponentGenesis method is:
9763%
9764% MagickBooleanType XComponentGenesis(void)
9765%
9766*/
cristy5ff4eaf2011-09-03 01:38:02 +00009767MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009768{
9769 return(MagickTrue);
9770}
9771
9772/*
9773%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9774% %
9775% %
9776% %
cristy3ed852e2009-09-05 21:47:34 +00009777% X G e t I m p o r t I n f o %
9778% %
9779% %
9780% %
9781%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9782%
9783% XGetImportInfo() initializes the XImportInfo structure.
9784%
9785% The format of the XGetImportInfo method is:
9786%
9787% void XGetImportInfo(XImportInfo *ximage_info)
9788%
9789% A description of each parameter follows:
9790%
9791% o ximage_info: Specifies a pointer to an ImageInfo structure.
9792%
9793*/
9794MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9795{
9796 assert(ximage_info != (XImportInfo *) NULL);
9797 ximage_info->frame=MagickFalse;
9798 ximage_info->borders=MagickFalse;
9799 ximage_info->screen=MagickFalse;
9800 ximage_info->descend=MagickTrue;
9801 ximage_info->silent=MagickFalse;
9802}