blob: 6556d43ba1f66d19bb286440856d40550b95c83e [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,
cristy7c3af952011-10-20 16:04:16 +0000446% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
447% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000448%
449% A description of each parameter follows:
450%
451% o display: Specifies a connection to an X server; returned from
452% XOpenDisplay.
453%
454% o pixel: Specifies a pointer to a XPixelInfo structure.
455%
456% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
457%
458% o image: the image.
459%
cristy7c3af952011-10-20 16:04:16 +0000460% o exception: return any errors or warnings in this structure.
461%
cristy3ed852e2009-09-05 21:47:34 +0000462*/
cristybcbda3f2011-09-03 13:01:22 +0000463MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
cristy7c3af952011-10-20 16:04:16 +0000464 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
465 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000466{
cristyc57f6942010-11-12 01:47:39 +0000467 CacheView
468 *annotate_view;
469
cristy3ed852e2009-09-05 21:47:34 +0000470 GC
471 annotate_context;
472
cristy3ed852e2009-09-05 21:47:34 +0000473 Image
474 *annotate_image;
475
476 int
477 x,
478 y;
479
480 MagickBooleanType
481 matte;
482
483 Pixmap
484 annotate_pixmap;
485
cristy2ed42f62011-10-02 19:49:57 +0000486 Quantum
cristy5f95f4f2011-10-23 01:01:01 +0000487 virtual_pixel[CompositePixelChannel];
cristy2ed42f62011-10-02 19:49:57 +0000488
cristy3ed852e2009-09-05 21:47:34 +0000489 unsigned int
490 depth,
491 height,
492 width;
493
494 Window
495 root_window;
496
497 XGCValues
498 context_values;
499
500 XImage
501 *annotate_ximage;
502
503 /*
504 Initialize annotated image.
505 */
506 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
507 assert(display != (Display *) NULL);
508 assert(pixel != (XPixelInfo *) NULL);
509 assert(annotate_info != (XAnnotateInfo *) NULL);
510 assert(image != (Image *) NULL);
511 /*
512 Initialize annotated pixmap.
513 */
514 root_window=XRootWindow(display,XDefaultScreen(display));
515 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
516 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
517 annotate_info->height,depth);
518 if (annotate_pixmap == (Pixmap) NULL)
519 return(MagickFalse);
520 /*
521 Initialize graphics info.
522 */
523 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000524 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000525 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000526 annotate_context=XCreateGC(display,root_window,(unsigned long)
527 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000528 if (annotate_context == (GC) NULL)
529 return(MagickFalse);
530 /*
531 Draw text to pixmap.
532 */
533 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
534 (int) annotate_info->font_info->ascent,annotate_info->text,
535 (int) strlen(annotate_info->text));
536 (void) XFreeGC(display,annotate_context);
537 /*
538 Initialize annotated X image.
539 */
540 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
541 annotate_info->height,AllPlanes,ZPixmap);
542 if (annotate_ximage == (XImage *) NULL)
543 return(MagickFalse);
544 (void) XFreePixmap(display,annotate_pixmap);
545 /*
546 Initialize annotated image.
547 */
cristy6710d842011-10-20 23:23:00 +0000548 annotate_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +0000549 if (annotate_image == (Image *) NULL)
550 return(MagickFalse);
551 annotate_image->columns=annotate_info->width;
552 annotate_image->rows=annotate_info->height;
553 /*
554 Transfer annotated X image to image.
555 */
556 width=(unsigned int) image->columns;
557 height=(unsigned int) image->rows;
558 x=0;
559 y=0;
560 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristy2ed42f62011-10-02 19:49:57 +0000561 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,virtual_pixel,
cristy6710d842011-10-20 23:23:00 +0000562 exception);
cristy2ed42f62011-10-02 19:49:57 +0000563 annotate_image->background_color.red=virtual_pixel[RedPixelChannel];
564 annotate_image->background_color.green=virtual_pixel[GreenPixelChannel];
565 annotate_image->background_color.blue=virtual_pixel[BluePixelChannel];
566 annotate_image->background_color.alpha=virtual_pixel[AlphaPixelChannel];
cristy3ed852e2009-09-05 21:47:34 +0000567 if (annotate_info->stencil == ForegroundStencil)
568 annotate_image->matte=MagickTrue;
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 */
cristy6710d842011-10-20 23:23:00 +0000653 rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +0000654 if (rotate_image == (Image *) NULL)
655 return(MagickFalse);
656 annotate_image=DestroyImage(annotate_image);
657 annotate_image=rotate_image;
658 /*
659 Annotation is relative to the degree of rotation.
660 */
661 normalized_degrees=annotate_info->degrees;
662 while (normalized_degrees < -45.0)
663 normalized_degrees+=360.0;
664 for (rotations=0; normalized_degrees > 45.0; rotations++)
665 normalized_degrees-=90.0;
666 switch (rotations % 4)
667 {
668 default:
669 case 0:
670 break;
671 case 1:
672 {
673 /*
674 Rotate 90 degrees.
675 */
676 x-=(int) annotate_image->columns/2;
677 y+=(int) annotate_image->columns/2;
678 break;
679 }
680 case 2:
681 {
682 /*
683 Rotate 180 degrees.
684 */
685 x=x-(int) annotate_image->columns;
686 break;
687 }
688 case 3:
689 {
690 /*
691 Rotate 270 degrees.
692 */
693 x=x-(int) annotate_image->columns/2;
694 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
695 break;
696 }
697 }
698 }
699 /*
700 Composite text onto the image.
701 */
702 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
703 matte=image->matte;
704 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristye941a752011-10-15 01:52:48 +0000705 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y,
706 exception);
cristy3ed852e2009-09-05 21:47:34 +0000707 image->matte=matte;
708 annotate_image=DestroyImage(annotate_image);
709 return(MagickTrue);
710}
711
712/*
713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714% %
715% %
716% %
717% X B e s t F o n t %
718% %
719% %
720% %
721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722%
723% XBestFont() returns the "best" font. "Best" is defined as a font specified
724% in the X resource database or a font such that the text width displayed
725% with the font does not exceed the specified maximum width.
726%
727% The format of the XBestFont method is:
728%
729% XFontStruct *XBestFont(Display *display,
730% const XResourceInfo *resource_info,const MagickBooleanType text_font)
731%
732% A description of each parameter follows:
733%
734% o font: XBestFont returns a pointer to a XFontStruct structure.
735%
736% o display: Specifies a connection to an X server; returned from
737% XOpenDisplay.
738%
739% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
740%
741% o text_font: True is font should be mono-spaced (typewriter style).
742%
cristy3ed852e2009-09-05 21:47:34 +0000743*/
744
745static char **FontToList(char *font)
746{
747 char
748 **fontlist;
749
750 register char
751 *p,
752 *q;
753
754 register int
755 i;
756
757 unsigned int
758 fonts;
759
760 if (font == (char *) NULL)
761 return((char **) NULL);
762 /*
763 Convert string to an ASCII list.
764 */
765 fonts=1U;
766 for (p=font; *p != '\0'; p++)
767 if ((*p == ':') || (*p == ';') || (*p == ','))
768 fonts++;
769 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
770 if (fontlist == (char **) NULL)
771 {
772 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
773 font);
774 return((char **) NULL);
775 }
776 p=font;
777 for (i=0; i < (int) fonts; i++)
778 {
779 for (q=p; *q != '\0'; q++)
780 if ((*q == ':') || (*q == ';') || (*q == ','))
781 break;
782 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
783 sizeof(*fontlist[i]));
784 if (fontlist[i] == (char *) NULL)
785 {
786 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
787 font);
788 return((char **) NULL);
789 }
790 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
791 p=q+1;
792 }
793 fontlist[i]=(char *) NULL;
794 return(fontlist);
795}
796
cristybcbda3f2011-09-03 13:01:22 +0000797MagickPrivate XFontStruct *XBestFont(Display *display,
cristy3ed852e2009-09-05 21:47:34 +0000798 const XResourceInfo *resource_info,const MagickBooleanType text_font)
799{
800 static const char
801 *Fonts[]=
802 {
803 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
804 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
805 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
806 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
807 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
808 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
809 "variable",
810 "fixed",
811 (char *) NULL
812 },
813 *TextFonts[]=
814 {
815 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
816 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
817 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
818 "fixed",
819 (char *) NULL
820 };
821
822 char
823 *font_name;
824
825 register const char
826 **p;
827
828 XFontStruct
829 *font_info;
830
831 font_info=(XFontStruct *) NULL;
832 font_name=resource_info->font;
833 if (text_font != MagickFalse)
834 font_name=resource_info->text_font;
835 if ((font_name != (char *) NULL) && (*font_name != '\0'))
836 {
837 char
838 **fontlist;
839
840 register int
841 i;
842
843 /*
844 Load preferred font specified in the X resource database.
845 */
846 fontlist=FontToList(font_name);
847 if (fontlist != (char **) NULL)
848 {
849 for (i=0; fontlist[i] != (char *) NULL; i++)
850 {
851 if (font_info == (XFontStruct *) NULL)
852 font_info=XLoadQueryFont(display,fontlist[i]);
853 fontlist[i]=DestroyString(fontlist[i]);
854 }
855 fontlist=(char **) RelinquishMagickMemory(fontlist);
856 }
857 if (font_info == (XFontStruct *) NULL)
858 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
859 }
860 /*
861 Load fonts from list of fonts until one is found.
862 */
863 p=Fonts;
864 if (text_font != MagickFalse)
865 p=TextFonts;
866 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
867 p++;
868 while (*p != (char *) NULL)
869 {
870 if (font_info != (XFontStruct *) NULL)
871 break;
872 font_info=XLoadQueryFont(display,(char *) *p);
873 p++;
874 }
875 return(font_info);
876}
877
878/*
879%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
880% %
881% %
882% %
883% X B e s t I c o n S i z e %
884% %
885% %
886% %
887%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
888%
889% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
890% size that maintains the aspect ratio of the image. If the window manager
891% has preferred icon sizes, one of the preferred sizes is used.
892%
893% The format of the XBestIconSize method is:
894%
895% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
896%
897% A description of each parameter follows:
898%
899% o display: Specifies a connection to an X server; returned from
900% XOpenDisplay.
901%
902% o image: the image.
903%
904*/
cristybcbda3f2011-09-03 13:01:22 +0000905MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +0000906 Image *image)
907{
908 int
909 i,
910 number_sizes;
911
912 MagickRealType
913 scale_factor;
914
915 unsigned int
916 height,
917 icon_height,
918 icon_width,
919 width;
920
921 Window
922 root_window;
923
924 XIconSize
925 *icon_size,
926 *size_list;
927
928 /*
929 Determine if the window manager has specified preferred icon sizes.
930 */
931 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
932 assert(display != (Display *) NULL);
933 assert(window != (XWindowInfo *) NULL);
934 assert(image != (Image *) NULL);
935 window->width=MaxIconSize;
936 window->height=MaxIconSize;
937 icon_size=(XIconSize *) NULL;
938 number_sizes=0;
939 root_window=XRootWindow(display,window->screen);
940 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
941 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
942 icon_size=size_list;
943 if (icon_size == (XIconSize *) NULL)
944 {
945 /*
946 Window manager does not restrict icon size.
947 */
948 icon_size=XAllocIconSize();
949 if (icon_size == (XIconSize *) NULL)
950 {
951 ThrowXWindowFatalException(ResourceLimitError,
952 "MemoryAllocationFailed",image->filename);
953 return;
954 }
955 icon_size->min_width=1;
956 icon_size->max_width=MaxIconSize;
957 icon_size->min_height=1;
958 icon_size->max_height=MaxIconSize;
959 icon_size->width_inc=1;
960 icon_size->height_inc=1;
961 }
962 /*
963 Determine aspect ratio of image.
964 */
965 width=(unsigned int) image->columns;
966 height=(unsigned int) image->rows;
967 i=0;
968 if (window->crop_geometry)
969 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
970 /*
971 Look for an icon size that maintains the aspect ratio of image.
972 */
973 scale_factor=(MagickRealType) icon_size->max_width/width;
974 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
975 scale_factor=(MagickRealType) icon_size->max_height/height;
976 icon_width=(unsigned int) icon_size->min_width;
977 while ((int) icon_width < icon_size->max_width)
978 {
979 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
980 break;
981 icon_width+=icon_size->width_inc;
982 }
983 icon_height=(unsigned int) icon_size->min_height;
984 while ((int) icon_height < icon_size->max_height)
985 {
986 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
987 break;
988 icon_height+=icon_size->height_inc;
989 }
990 (void) XFree((void *) icon_size);
991 window->width=icon_width;
992 window->height=icon_height;
993}
994
995/*
996%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997% %
998% %
999% %
1000% X B e s t P i x e l %
1001% %
1002% %
1003% %
1004%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1005%
1006% XBestPixel() returns a pixel from an array of pixels that is closest to the
1007% requested color. If the color array is NULL, the colors are obtained from
1008% the X server.
1009%
1010% The format of the XBestPixel method is:
1011%
1012% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
1013% unsigned int number_colors,XColor *color)
1014%
1015% A description of each parameter follows:
1016%
1017% o pixel: XBestPixel returns the pixel value closest to the requested
1018% color.
1019%
1020% o display: Specifies a connection to an X server; returned from
1021% XOpenDisplay.
1022%
1023% o colormap: Specifies the ID of the X server colormap.
1024%
1025% o colors: Specifies an array of XColor structures.
1026%
1027% o number_colors: Specifies the number of XColor structures in the
1028% color definition array.
1029%
1030% o color: Specifies the desired RGB value to find in the colors array.
1031%
1032*/
cristybcbda3f2011-09-03 13:01:22 +00001033MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
cristy3ed852e2009-09-05 21:47:34 +00001034 XColor *colors,unsigned int number_colors,XColor *color)
1035{
1036 MagickBooleanType
1037 query_server;
1038
cristy4c08aed2011-07-01 19:47:50 +00001039 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00001040 pixel;
1041
1042 MagickRealType
1043 min_distance;
1044
1045 register MagickRealType
1046 distance;
1047
1048 register int
1049 i,
1050 j;
1051
1052 Status
1053 status;
1054
1055 /*
1056 Find closest representation for the requested RGB color.
1057 */
1058 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1059 assert(display != (Display *) NULL);
1060 assert(color != (XColor *) NULL);
1061 status=XAllocColor(display,colormap,color);
1062 if (status != False)
1063 return;
1064 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1065 if (query_server != MagickFalse)
1066 {
1067 /*
1068 Read X server colormap.
1069 */
1070 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1071 if (colors == (XColor *) NULL)
1072 {
1073 ThrowXWindowFatalException(ResourceLimitError,
1074 "MemoryAllocationFailed","...");
1075 return;
1076 }
1077 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001078 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001079 if (number_colors > 256)
1080 number_colors=256;
1081 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1082 }
1083 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1084 QuantumRange+1.0);
1085 j=0;
1086 for (i=0; i < (int) number_colors; i++)
1087 {
1088 pixel.red=colors[i].red-(MagickRealType) color->red;
1089 distance=pixel.red*pixel.red;
1090 if (distance > min_distance)
1091 continue;
1092 pixel.green=colors[i].green-(MagickRealType) color->green;
1093 distance+=pixel.green*pixel.green;
1094 if (distance > min_distance)
1095 continue;
1096 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1097 distance+=pixel.blue*pixel.blue;
1098 if (distance > min_distance)
1099 continue;
1100 min_distance=distance;
1101 color->pixel=colors[i].pixel;
1102 j=i;
1103 }
1104 (void) XAllocColor(display,colormap,&colors[j]);
1105 if (query_server != MagickFalse)
1106 colors=(XColor *) RelinquishMagickMemory(colors);
1107}
1108
1109/*
1110%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1111% %
1112% %
1113% %
1114% X B e s t V i s u a l I n f o %
1115% %
1116% %
1117% %
1118%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1119%
1120% XBestVisualInfo() returns visual information for a visual that is the "best"
1121% the server supports. "Best" is defined as:
1122%
1123% 1. Restrict the visual list to those supported by the default screen.
1124%
1125% 2. If a visual type is specified, restrict the visual list to those of
1126% that type.
1127%
1128% 3. If a map type is specified, choose the visual that matches the id
1129% specified by the Standard Colormap.
1130%
1131% 4 From the list of visuals, choose one that can display the most
1132% simultaneous colors. If more than one visual can display the same
1133% number of simultaneous colors, one is chosen based on a rank.
1134%
1135% The format of the XBestVisualInfo method is:
1136%
1137% XVisualInfo *XBestVisualInfo(Display *display,
1138% XStandardColormap *map_info,XResourceInfo *resource_info)
1139%
1140% A description of each parameter follows:
1141%
1142% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1143% structure.
1144%
1145% o display: Specifies a connection to an X server; returned from
1146% XOpenDisplay.
1147%
1148% o map_info: If map_type is specified, this structure is initialized
1149% with info from the Standard Colormap.
1150%
1151% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1152%
1153*/
1154
1155static inline int MagickMax(const int x,const int y)
1156{
1157 if (x > y)
1158 return(x);
1159 return(y);
1160}
1161
cristybb503372010-05-27 20:51:26 +00001162static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001163 const unsigned int y)
1164{
1165 if (x < y)
1166 return(x);
1167 return(y);
1168}
1169
cristybcbda3f2011-09-03 13:01:22 +00001170MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001171 XStandardColormap *map_info,XResourceInfo *resource_info)
1172{
1173#define MaxStandardColormaps 7
1174#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1175 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1176 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1177 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1178
1179 char
1180 *map_type,
1181 *visual_type;
1182
cristyc57f6942010-11-12 01:47:39 +00001183 int
1184 visual_mask;
1185
cristy3ed852e2009-09-05 21:47:34 +00001186 register int
1187 i;
1188
cristy8891f9c2010-06-04 23:32:17 +00001189 size_t
1190 one;
1191
cristy3ed852e2009-09-05 21:47:34 +00001192 static int
1193 number_visuals;
1194
1195 static XVisualInfo
1196 visual_template;
1197
1198 XVisualInfo
1199 *visual_info,
1200 *visual_list;
1201
1202 /*
1203 Restrict visual search by screen number.
1204 */
1205 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1206 assert(display != (Display *) NULL);
1207 assert(map_info != (XStandardColormap *) NULL);
1208 assert(resource_info != (XResourceInfo *) NULL);
1209 map_type=resource_info->map_type;
1210 visual_type=resource_info->visual_type;
1211 visual_mask=VisualScreenMask;
1212 visual_template.screen=XDefaultScreen(display);
1213 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001214 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001215 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001216 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001217 visual_mask|=VisualDepthMask;
1218 if (visual_type != (char *) NULL)
1219 {
1220 /*
1221 Restrict visual search by class or visual id.
1222 */
1223 if (LocaleCompare("staticgray",visual_type) == 0)
1224 {
1225 visual_mask|=VisualClassMask;
1226 visual_template.klass=StaticGray;
1227 }
1228 else
1229 if (LocaleCompare("grayscale",visual_type) == 0)
1230 {
1231 visual_mask|=VisualClassMask;
1232 visual_template.klass=GrayScale;
1233 }
1234 else
1235 if (LocaleCompare("staticcolor",visual_type) == 0)
1236 {
1237 visual_mask|=VisualClassMask;
1238 visual_template.klass=StaticColor;
1239 }
1240 else
1241 if (LocaleCompare("pseudocolor",visual_type) == 0)
1242 {
1243 visual_mask|=VisualClassMask;
1244 visual_template.klass=PseudoColor;
1245 }
1246 else
1247 if (LocaleCompare("truecolor",visual_type) == 0)
1248 {
1249 visual_mask|=VisualClassMask;
1250 visual_template.klass=TrueColor;
1251 }
1252 else
1253 if (LocaleCompare("directcolor",visual_type) == 0)
1254 {
1255 visual_mask|=VisualClassMask;
1256 visual_template.klass=DirectColor;
1257 }
1258 else
1259 if (LocaleCompare("default",visual_type) == 0)
1260 {
1261 visual_mask|=VisualIDMask;
1262 visual_template.visualid=XVisualIDFromVisual(
1263 XDefaultVisual(display,XDefaultScreen(display)));
1264 }
1265 else
1266 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1267 {
1268 visual_mask|=VisualIDMask;
1269 visual_template.visualid=
1270 strtol(visual_type,(char **) NULL,0);
1271 }
1272 else
1273 ThrowXWindowFatalException(XServerError,
1274 "UnrecognizedVisualSpecifier",visual_type);
1275 }
1276 /*
1277 Get all visuals that meet our criteria so far.
1278 */
1279 number_visuals=0;
1280 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1281 &number_visuals);
1282 visual_mask=VisualScreenMask | VisualIDMask;
1283 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1284 {
1285 /*
1286 Failed to get visual; try using the default visual.
1287 */
1288 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1289 visual_type);
1290 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1291 XDefaultScreen(display)));
1292 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1293 &number_visuals);
1294 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1295 return((XVisualInfo *) NULL);
1296 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1297 XVisualClassName(visual_list->klass));
1298 }
1299 resource_info->color_recovery=MagickFalse;
1300 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1301 {
1302 Atom
1303 map_property;
1304
1305 char
1306 map_name[MaxTextExtent];
1307
1308 int
1309 j,
1310 number_maps;
1311
1312 Status
1313 status;
1314
1315 Window
1316 root_window;
1317
1318 XStandardColormap
1319 *map_list;
1320
1321 /*
1322 Choose a visual associated with a standard colormap.
1323 */
1324 root_window=XRootWindow(display,XDefaultScreen(display));
1325 status=False;
1326 if (LocaleCompare(map_type,"list") != 0)
1327 {
1328 /*
1329 User specified Standard Colormap.
1330 */
cristyb51dff52011-05-19 16:55:47 +00001331 (void) FormatLocaleString((char *) map_name,MaxTextExtent,
cristy3ed852e2009-09-05 21:47:34 +00001332 "RGB_%s_MAP",map_type);
1333 LocaleUpper(map_name);
1334 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1335 if (map_property != (Atom) NULL)
1336 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1337 map_property);
1338 }
1339 else
1340 {
1341 static const char
1342 *colormap[MaxStandardColormaps]=
1343 {
1344 "_HP_RGB_SMOOTH_MAP_LIST",
1345 "RGB_BEST_MAP",
1346 "RGB_DEFAULT_MAP",
1347 "RGB_GRAY_MAP",
1348 "RGB_RED_MAP",
1349 "RGB_GREEN_MAP",
1350 "RGB_BLUE_MAP",
1351 };
1352
1353 /*
1354 Choose a standard colormap from a list.
1355 */
1356 for (i=0; i < MaxStandardColormaps; i++)
1357 {
1358 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1359 if (map_property == (Atom) NULL)
1360 continue;
1361 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1362 map_property);
1363 if (status != False)
1364 break;
1365 }
1366 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1367 }
1368 if (status == False)
1369 {
1370 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1371 map_type);
1372 return((XVisualInfo *) NULL);
1373 }
1374 /*
1375 Search all Standard Colormaps and visuals for ids that match.
1376 */
1377 *map_info=map_list[0];
1378#if !defined(PRE_R4_ICCCM)
1379 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1380 for (i=0; i < number_maps; i++)
1381 for (j=0; j < number_visuals; j++)
1382 if (map_list[i].visualid ==
1383 XVisualIDFromVisual(visual_list[j].visual))
1384 {
1385 *map_info=map_list[i];
1386 visual_template.visualid=XVisualIDFromVisual(
1387 visual_list[j].visual);
1388 break;
1389 }
1390 if (map_info->visualid != visual_template.visualid)
1391 {
1392 ThrowXWindowFatalException(XServerError,
1393 "UnableToMatchVisualToStandardColormap",map_type);
1394 return((XVisualInfo *) NULL);
1395 }
1396#endif
1397 if (map_info->colormap == (Colormap) NULL)
1398 {
1399 ThrowXWindowFatalException(XServerError,
1400 "StandardColormapIsNotInitialized",map_type);
1401 return((XVisualInfo *) NULL);
1402 }
1403 (void) XFree((void *) map_list);
1404 }
1405 else
1406 {
1407 static const unsigned int
1408 rank[]=
1409 {
1410 StaticGray,
1411 GrayScale,
1412 StaticColor,
1413 DirectColor,
1414 TrueColor,
1415 PseudoColor
1416 };
1417
1418 XVisualInfo
1419 *p;
1420
1421 /*
1422 Pick one visual that displays the most simultaneous colors.
1423 */
1424 visual_info=visual_list;
1425 p=visual_list;
1426 for (i=1; i < number_visuals; i++)
1427 {
1428 p++;
1429 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1430 visual_info=p;
1431 else
1432 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1433 if (rank[p->klass] > rank[visual_info->klass])
1434 visual_info=p;
1435 }
1436 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1437 }
1438 (void) XFree((void *) visual_list);
1439 /*
1440 Retrieve only one visual by its screen & id number.
1441 */
1442 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1443 &number_visuals);
1444 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1445 return((XVisualInfo *) NULL);
1446 return(visual_info);
1447}
1448
1449/*
1450%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1451% %
1452% %
1453% %
1454% X C h e c k D e f i n e C u r s o r %
1455% %
1456% %
1457% %
1458%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1459%
1460% XCheckDefineCursor() prevents cursor changes on the root window.
1461%
1462% The format of the XXCheckDefineCursor method is:
1463%
1464% XCheckDefineCursor(display,window,cursor)
1465%
1466% A description of each parameter follows:
1467%
1468% o display: Specifies a connection to an X server; returned from
1469% XOpenDisplay.
1470%
1471% o window: the window.
1472%
1473% o cursor: the cursor.
1474%
1475*/
cristybcbda3f2011-09-03 13:01:22 +00001476MagickPrivate int XCheckDefineCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00001477 Cursor cursor)
1478{
1479 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1480 assert(display != (Display *) NULL);
1481 if (window == XRootWindow(display,XDefaultScreen(display)))
1482 return(0);
1483 return(XDefineCursor(display,window,cursor));
1484}
1485
1486/*
1487%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1488% %
1489% %
1490% %
1491% X C h e c k R e f r e s h W i n d o w s %
1492% %
1493% %
1494% %
1495%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1496%
1497% XCheckRefreshWindows() checks the X server for exposure events for a
1498% particular window and updates the areassociated with the exposure event.
1499%
1500% The format of the XCheckRefreshWindows method is:
1501%
1502% void XCheckRefreshWindows(Display *display,XWindows *windows)
1503%
1504% A description of each parameter follows:
1505%
1506% o display: Specifies a connection to an X server; returned from
1507% XOpenDisplay.
1508%
1509% o windows: Specifies a pointer to a XWindows structure.
1510%
1511*/
cristybcbda3f2011-09-03 13:01:22 +00001512MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
cristy3ed852e2009-09-05 21:47:34 +00001513{
1514 Window
1515 id;
1516
1517 XEvent
1518 event;
1519
1520 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1521 assert(display != (Display *) NULL);
1522 assert(windows != (XWindows *) NULL);
1523 XDelay(display,SuspendTime);
1524 id=windows->command.id;
1525 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1526 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1527 id=windows->image.id;
1528 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1529 XRefreshWindow(display,&windows->image,&event);
1530 XDelay(display,SuspendTime << 1);
1531 id=windows->command.id;
1532 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1533 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1534 id=windows->image.id;
1535 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1536 XRefreshWindow(display,&windows->image,&event);
1537}
1538
1539/*
1540%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1541% %
1542% %
1543% %
1544% X C l i e n t M e s s a g e %
1545% %
1546% %
1547% %
1548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1549%
1550% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1551% initialized with a particular protocol type and atom.
1552%
1553% The format of the XClientMessage function is:
1554%
1555% XClientMessage(display,window,protocol,reason,timestamp)
1556%
1557% A description of each parameter follows:
1558%
1559% o display: Specifies a pointer to the Display structure; returned from
1560% XOpenDisplay.
1561%
1562% o window: Specifies a pointer to a Window structure.
1563%
1564% o protocol: Specifies an atom value.
1565%
1566% o reason: Specifies an atom value which is the reason to send.
1567%
1568% o timestamp: Specifies a value of type Time.
1569%
1570*/
cristybcbda3f2011-09-03 13:01:22 +00001571MagickPrivate void XClientMessage(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00001572 const Atom protocol,const Atom reason,const Time timestamp)
1573{
1574 XClientMessageEvent
1575 client_event;
1576
1577 assert(display != (Display *) NULL);
1578 client_event.type=ClientMessage;
1579 client_event.window=window;
1580 client_event.message_type=protocol;
1581 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001582 client_event.data.l[0]=(long) reason;
1583 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001584 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1585}
1586
1587/*
1588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1589% %
1590% %
1591% %
1592+ X C l i e n t W i n d o w %
1593% %
1594% %
1595% %
1596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1597%
1598% XClientWindow() finds a window, at or below the specified window, which has
1599% a WM_STATE property. If such a window is found, it is returned, otherwise
1600% the argument window is returned.
1601%
1602% The format of the XClientWindow function is:
1603%
1604% client_window=XClientWindow(display,target_window)
1605%
1606% A description of each parameter follows:
1607%
1608% o client_window: XClientWindow returns a window, at or below the specified
1609% window, which has a WM_STATE property otherwise the argument
1610% target_window is returned.
1611%
1612% o display: Specifies a pointer to the Display structure; returned from
1613% XOpenDisplay.
1614%
1615% o target_window: Specifies the window to find a WM_STATE property.
1616%
cristy3ed852e2009-09-05 21:47:34 +00001617*/
1618static Window XClientWindow(Display *display,Window target_window)
1619{
1620 Atom
1621 state,
1622 type;
1623
1624 int
1625 format;
1626
1627 Status
1628 status;
1629
1630 unsigned char
1631 *data;
1632
cristyf2faecf2010-05-28 19:19:36 +00001633 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001634 after,
1635 number_items;
1636
1637 Window
1638 client_window;
1639
1640 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1641 assert(display != (Display *) NULL);
1642 state=XInternAtom(display,"WM_STATE",MagickTrue);
1643 if (state == (Atom) NULL)
1644 return(target_window);
1645 type=(Atom) NULL;
1646 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1647 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1648 if ((status == Success) && (type != (Atom) NULL))
1649 return(target_window);
1650 client_window=XWindowByProperty(display,target_window,state);
1651 if (client_window == (Window) NULL)
1652 return(target_window);
1653 return(client_window);
1654}
1655
1656/*
1657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1658% %
1659% %
1660% %
cristyf34a1452009-10-24 22:29:27 +00001661+ X C o m p o n e n t T e r m i n u s %
1662% %
1663% %
1664% %
1665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1666%
1667% XComponentTerminus() destroys the module component.
1668%
1669% The format of the XComponentTerminus method is:
1670%
1671% XComponentTerminus(void)
1672%
1673*/
cristy5ff4eaf2011-09-03 01:38:02 +00001674MagickPrivate void XComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +00001675{
1676 DestroyXResources();
1677}
1678
1679/*
1680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1681% %
1682% %
1683% %
cristy3ed852e2009-09-05 21:47:34 +00001684% X C o n f i g u r e I m a g e C o l o r m a p %
1685% %
1686% %
1687% %
1688%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1689%
1690% XConfigureImageColormap() creates a new X colormap.
1691%
1692% The format of the XConfigureImageColormap method is:
1693%
1694% void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001695% XResourceInfo *resource_info,XWindows *windows,Image *image,
1696% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001697%
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%
cristy6710d842011-10-20 23:23:00 +00001709% o exception: return any errors or warnings in this structure.
1710%
cristy3ed852e2009-09-05 21:47:34 +00001711*/
cristybcbda3f2011-09-03 13:01:22 +00001712MagickPrivate void XConfigureImageColormap(Display *display,
cristy6710d842011-10-20 23:23:00 +00001713 XResourceInfo *resource_info,XWindows *windows,Image *image,
1714 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001715{
1716 Colormap
1717 colormap;
1718
1719 /*
1720 Make standard colormap.
1721 */
1722 XSetCursorState(display,windows,MagickTrue);
1723 XCheckRefreshWindows(display,windows);
1724 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
cristy6710d842011-10-20 23:23:00 +00001725 windows->map_info,windows->pixel_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00001726 colormap=windows->map_info->colormap;
1727 (void) XSetWindowColormap(display,windows->image.id,colormap);
1728 (void) XSetWindowColormap(display,windows->command.id,colormap);
1729 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1730 if (windows->magnify.mapped != MagickFalse)
1731 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1732 if (windows->pan.mapped != MagickFalse)
1733 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1734 XSetCursorState(display,windows,MagickFalse);
1735 XClientMessage(display,windows->image.id,windows->im_protocols,
1736 windows->im_update_colormap,CurrentTime);
1737}
1738
1739/*
1740%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1741% %
1742% %
1743% %
1744% X C o n s t r a i n W i n d o w P o s i t i o n %
1745% %
1746% %
1747% %
1748%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1749%
1750% XConstrainWindowPosition() assures a window is positioned within the X
1751% server boundaries.
1752%
1753% The format of the XConstrainWindowPosition method is:
1754%
1755% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1756%
1757% A description of each parameter follows:
1758%
1759% o display: Specifies a pointer to the Display structure; returned from
1760% XOpenDisplay.
1761%
1762% o window_info: Specifies a pointer to a XWindowInfo structure.
1763%
1764*/
cristybcbda3f2011-09-03 13:01:22 +00001765MagickPrivate void XConstrainWindowPosition(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001766 XWindowInfo *window_info)
1767{
1768 int
1769 limit;
1770
1771 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1772 assert(display != (Display *) NULL);
1773 assert(window_info != (XWindowInfo *) NULL);
1774 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1775 if (window_info->x < 0)
1776 window_info->x=0;
1777 else
1778 if (window_info->x > (int) limit)
1779 window_info->x=(int) limit;
1780 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1781 if (window_info->y < 0)
1782 window_info->y=0;
1783 else
1784 if (window_info->y > limit)
1785 window_info->y=limit;
1786}
1787
1788/*
1789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1790% %
1791% %
1792% %
1793% X D e l a y %
1794% %
1795% %
1796% %
1797%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1798%
1799% XDelay() suspends program execution for the number of milliseconds
1800% specified.
1801%
1802% The format of the Delay method is:
1803%
cristybb503372010-05-27 20:51:26 +00001804% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001805%
1806% A description of each parameter follows:
1807%
1808% o display: Specifies a pointer to the Display structure; returned from
1809% XOpenDisplay.
1810%
1811% o milliseconds: Specifies the number of milliseconds to delay before
1812% returning.
1813%
1814*/
cristybcbda3f2011-09-03 13:01:22 +00001815MagickPrivate void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001816{
1817 assert(display != (Display *) NULL);
1818 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001819 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001820}
1821
1822/*
1823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1824% %
1825% %
1826% %
1827% X D e s t r o y R e s o u r c e I n f o %
1828% %
1829% %
1830% %
1831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1832%
1833% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1834% structure.
1835%
1836% The format of the XDestroyResourceInfo method is:
1837%
1838% void XDestroyResourceInfo(XResourceInfo *resource_info)
1839%
1840% A description of each parameter follows:
1841%
1842% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1843%
1844*/
1845MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1846{
1847 if (resource_info->image_geometry != (char *) NULL)
1848 resource_info->image_geometry=(char *)
1849 RelinquishMagickMemory(resource_info->image_geometry);
1850 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1851 resource_info->quantize_info=DestroyQuantizeInfo(
1852 resource_info->quantize_info);
1853 if (resource_info->client_name != (char *) NULL)
1854 resource_info->client_name=(char *)
1855 RelinquishMagickMemory(resource_info->client_name);
1856 if (resource_info->name != (char *) NULL)
1857 resource_info->name=DestroyString(resource_info->name);
1858 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1859}
1860
1861/*
1862%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1863% %
1864% %
1865% %
1866% X D e s t r o y W i n d o w C o l o r s %
1867% %
1868% %
1869% %
1870%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1871%
1872% XDestroyWindowColors() frees X11 color resources previously saved on a
1873% window by XRetainWindowColors or programs like xsetroot.
1874%
1875% The format of the XDestroyWindowColors method is:
1876%
1877% void XDestroyWindowColors(Display *display,Window window)
1878%
1879% A description of each parameter follows:
1880%
1881% o display: Specifies a connection to an X server; returned from
1882% XOpenDisplay.
1883%
1884% o window: Specifies a pointer to a Window structure.
1885%
1886*/
cristybcbda3f2011-09-03 13:01:22 +00001887MagickPrivate void XDestroyWindowColors(Display *display,Window window)
cristy3ed852e2009-09-05 21:47:34 +00001888{
1889 Atom
1890 property,
1891 type;
1892
1893 int
1894 format;
1895
1896 Status
1897 status;
1898
1899 unsigned char
1900 *data;
1901
cristyf2faecf2010-05-28 19:19:36 +00001902 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001903 after,
1904 length;
1905
1906 /*
1907 If there are previous resources on the root window, destroy them.
1908 */
1909 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1910 assert(display != (Display *) NULL);
1911 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1912 if (property == (Atom) NULL)
1913 {
1914 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1915 "_XSETROOT_ID");
1916 return;
1917 }
1918 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1919 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1920 if (status != Success)
1921 return;
1922 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1923 {
1924 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1925 (void) XDeleteProperty(display,window,property);
1926 }
1927 if (type != None)
1928 (void) XFree((void *) data);
1929}
1930
1931/*
1932%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1933% %
1934% %
1935% %
1936% X D i s p l a y I m a g e I n f o %
1937% %
1938% %
1939% %
1940%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1941%
1942% XDisplayImageInfo() displays information about an X image.
1943%
1944% The format of the XDisplayImageInfo method is:
1945%
1946% void XDisplayImageInfo(Display *display,
1947% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001948% Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001949%
1950% A description of each parameter follows:
1951%
1952% o display: Specifies a connection to an X server; returned from
1953% XOpenDisplay.
1954%
1955% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1956%
1957% o windows: Specifies a pointer to a XWindows structure.
1958%
1959% o undo_image: the undo image.
1960%
1961% o image: the image.
1962%
cristy6710d842011-10-20 23:23:00 +00001963% o exception: return any errors or warnings in this structure.
1964%
cristy3ed852e2009-09-05 21:47:34 +00001965*/
cristybcbda3f2011-09-03 13:01:22 +00001966MagickPrivate void XDisplayImageInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00001967 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
cristy6710d842011-10-20 23:23:00 +00001968 Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001969{
1970 char
1971 filename[MaxTextExtent],
1972 *text,
1973 **textlist;
1974
1975 FILE
1976 *file;
1977
1978 int
1979 unique_file;
1980
cristybb503372010-05-27 20:51:26 +00001981 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001982 i;
1983
cristybb503372010-05-27 20:51:26 +00001984 size_t
cristy3ed852e2009-09-05 21:47:34 +00001985 number_pixels;
1986
cristy9d314ff2011-03-09 01:30:28 +00001987 ssize_t
1988 bytes;
1989
1990 unsigned int
1991 levels;
1992
cristy3ed852e2009-09-05 21:47:34 +00001993 /*
1994 Write info about the X server to a file.
1995 */
1996 assert(display != (Display *) NULL);
1997 assert(resource_info != (XResourceInfo *) NULL);
1998 assert(windows != (XWindows *) NULL);
1999 assert(image != (Image *) NULL);
2000 if (image->debug)
2001 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2002 file=(FILE *) NULL;
2003 unique_file=AcquireUniqueFileResource(filename);
2004 if (unique_file != -1)
2005 file=fdopen(unique_file,"w");
2006 if ((unique_file == -1) || (file == (FILE *) NULL))
2007 {
2008 XNoticeWidget(display,windows,"Unable to display image info",filename);
2009 return;
2010 }
2011 if (resource_info->gamma_correct != MagickFalse)
2012 if (resource_info->display_gamma != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002013 (void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
cristy3ed852e2009-09-05 21:47:34 +00002014 resource_info->display_gamma);
2015 /*
2016 Write info about the X image to a file.
2017 */
cristyb51dff52011-05-19 16:55:47 +00002018 (void) FormatLocaleFile(file,"X\n visual: %s\n",
cristy3ed852e2009-09-05 21:47:34 +00002019 XVisualClassName((int) windows->image.storage_class));
cristyb51dff52011-05-19 16:55:47 +00002020 (void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
cristy3ed852e2009-09-05 21:47:34 +00002021 if (windows->visual_info->colormap_size != 0)
cristyb51dff52011-05-19 16:55:47 +00002022 (void) FormatLocaleFile(file," colormap size: %d\n",
cristy3ed852e2009-09-05 21:47:34 +00002023 windows->visual_info->colormap_size);
2024 if (resource_info->colormap== SharedColormap)
cristyb51dff52011-05-19 16:55:47 +00002025 (void) FormatLocaleFile(file," colormap type: Shared\n");
cristy3ed852e2009-09-05 21:47:34 +00002026 else
cristyb51dff52011-05-19 16:55:47 +00002027 (void) FormatLocaleFile(file," colormap type: Private\n");
cristy1e604812011-05-19 18:07:50 +00002028 (void) FormatLocaleFile(file," geometry: %dx%d\n",
2029 windows->image.ximage->width,windows->image.ximage->height);
cristy3ed852e2009-09-05 21:47:34 +00002030 if (windows->image.crop_geometry != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00002031 (void) FormatLocaleFile(file," crop geometry: %s\n",
2032 windows->image.crop_geometry);
cristy3ed852e2009-09-05 21:47:34 +00002033 if (windows->image.pixmap == (Pixmap) NULL)
cristyb51dff52011-05-19 16:55:47 +00002034 (void) FormatLocaleFile(file," type: X Image\n");
cristy3ed852e2009-09-05 21:47:34 +00002035 else
cristyb51dff52011-05-19 16:55:47 +00002036 (void) FormatLocaleFile(file," type: Pixmap\n");
cristy3ed852e2009-09-05 21:47:34 +00002037 if (windows->image.shape != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002038 (void) FormatLocaleFile(file," non-rectangular shape: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002039 else
cristyb51dff52011-05-19 16:55:47 +00002040 (void) FormatLocaleFile(file," non-rectangular shape: False\n");
cristy3ed852e2009-09-05 21:47:34 +00002041 if (windows->image.shared_memory != MagickFalse)
cristyb51dff52011-05-19 16:55:47 +00002042 (void) FormatLocaleFile(file," shared memory: True\n");
cristy3ed852e2009-09-05 21:47:34 +00002043 else
cristyb51dff52011-05-19 16:55:47 +00002044 (void) FormatLocaleFile(file," shared memory: False\n");
2045 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00002046 if (resource_info->font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002047 (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
cristy3ed852e2009-09-05 21:47:34 +00002048 if (resource_info->text_font != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00002049 (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
cristy3ed852e2009-09-05 21:47:34 +00002050 /*
2051 Write info about the undo cache to a file.
2052 */
2053 bytes=0;
2054 for (levels=0; undo_image != (Image *) NULL; levels++)
2055 {
2056 number_pixels=undo_image->list->columns*undo_image->list->rows;
cristy101ab702011-10-13 13:06:32 +00002057 bytes+=number_pixels*sizeof(PixelInfo);
cristy3ed852e2009-09-05 21:47:34 +00002058 undo_image=GetPreviousImageInList(undo_image);
2059 }
cristyb51dff52011-05-19 16:55:47 +00002060 (void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
cristy1e604812011-05-19 18:07:50 +00002061 (void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
2062 ((bytes+(1 << 19)) >> 20));
cristyb51dff52011-05-19 16:55:47 +00002063 (void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002064 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002065 /*
2066 Write info about the image to a file.
2067 */
cristy6710d842011-10-20 23:23:00 +00002068 (void) IdentifyImage(image,file,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00002069 (void) fclose(file);
cristy6710d842011-10-20 23:23:00 +00002070 text=FileToString(filename,~0,exception);
cristy3ed852e2009-09-05 21:47:34 +00002071 (void) RelinquishUniqueFileResource(filename);
2072 if (text == (char *) NULL)
2073 {
2074 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2075 "UnableToDisplayImageInfo");
2076 return;
2077 }
2078 textlist=StringToList(text);
2079 if (textlist != (char **) NULL)
2080 {
2081 char
2082 title[MaxTextExtent];
2083
2084 /*
2085 Display information about the image in the Text View widget.
2086 */
2087 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
cristyb51dff52011-05-19 16:55:47 +00002088 (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
cristy3ed852e2009-09-05 21:47:34 +00002089 image->filename);
2090 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2091 (char const **) textlist);
2092 for (i=0; textlist[i] != (char *) NULL; i++)
2093 textlist[i]=DestroyString(textlist[i]);
2094 textlist=(char **) RelinquishMagickMemory(textlist);
2095 }
2096 text=DestroyString(text);
2097}
2098
2099/*
2100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2101% %
2102% %
2103% %
2104+ X D i t h e r I m a g e %
2105% %
2106% %
2107% %
2108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2109%
2110% XDitherImage() dithers the reference image as required by the HP Color
2111% Recovery algorithm. The color values are quantized to 3 bits of red and
2112% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2113% standard colormap.
2114%
2115% The format of the XDitherImage method is:
2116%
cristy6710d842011-10-20 23:23:00 +00002117% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002118%
2119% A description of each parameter follows:
2120%
2121% o image: the image.
2122%
2123% o ximage: Specifies a pointer to a XImage structure; returned from
2124% XCreateImage.
2125%
cristy6710d842011-10-20 23:23:00 +00002126% o exception: return any errors or warnings in this structure.
2127%
cristy3ed852e2009-09-05 21:47:34 +00002128*/
cristy6710d842011-10-20 23:23:00 +00002129static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002130{
2131 static const short int
2132 dither_red[2][16]=
2133 {
2134 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2135 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2136 },
2137 dither_green[2][16]=
2138 {
2139 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2140 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2141 },
2142 dither_blue[2][16]=
2143 {
2144 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2145 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2146 };
2147
cristyc57f6942010-11-12 01:47:39 +00002148 CacheView
2149 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002150
2151 int
cristyc57f6942010-11-12 01:47:39 +00002152 value,
cristy3ed852e2009-09-05 21:47:34 +00002153 y;
2154
cristy101ab702011-10-13 13:06:32 +00002155 PixelInfo
cristyc57f6942010-11-12 01:47:39 +00002156 color;
cristy3ed852e2009-09-05 21:47:34 +00002157
2158 register char
2159 *q;
2160
cristy4c08aed2011-07-01 19:47:50 +00002161 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00002162 *p;
2163
2164 register int
2165 i,
2166 j,
2167 x;
2168
2169 unsigned int
2170 scanline_pad;
2171
cristybb503372010-05-27 20:51:26 +00002172 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002173 pixel;
2174
2175 unsigned char
2176 *blue_map[2][16],
2177 *green_map[2][16],
2178 *red_map[2][16];
2179
2180 /*
2181 Allocate and initialize dither maps.
2182 */
2183 for (i=0; i < 2; i++)
2184 for (j=0; j < 16; j++)
2185 {
2186 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2187 sizeof(*red_map));
2188 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2189 sizeof(*green_map));
2190 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2191 sizeof(*blue_map));
2192 if ((red_map[i][j] == (unsigned char *) NULL) ||
2193 (green_map[i][j] == (unsigned char *) NULL) ||
2194 (blue_map[i][j] == (unsigned char *) NULL))
2195 {
2196 ThrowXWindowFatalException(ResourceLimitError,
2197 "MemoryAllocationFailed",image->filename);
2198 return;
2199 }
2200 }
2201 /*
2202 Initialize dither tables.
2203 */
2204 for (i=0; i < 2; i++)
2205 for (j=0; j < 16; j++)
2206 for (x=0; x < 256; x++)
2207 {
2208 value=x-16;
2209 if (x < 48)
2210 value=x/2+8;
2211 value+=dither_red[i][j];
2212 red_map[i][j][x]=(unsigned char)
2213 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2214 value=x-16;
2215 if (x < 48)
2216 value=x/2+8;
2217 value+=dither_green[i][j];
2218 green_map[i][j][x]=(unsigned char)
2219 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2220 value=x-32;
2221 if (x < 112)
2222 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002223 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002224 blue_map[i][j][x]=(unsigned char)
2225 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2226 }
2227 /*
2228 Dither image.
2229 */
2230 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002231 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002232 i=0;
2233 j=0;
2234 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002235 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002236 for (y=0; y < (int) image->rows; y++)
2237 {
cristyc57f6942010-11-12 01:47:39 +00002238 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
cristy6710d842011-10-20 23:23:00 +00002239 exception);
cristy4c08aed2011-07-01 19:47:50 +00002240 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002241 break;
2242 for (x=0; x < (int) image->columns; x++)
2243 {
cristyce70c172010-01-07 17:15:30 +00002244 color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002245 ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002246 color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002247 ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
cristyce70c172010-01-07 17:15:30 +00002248 color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
cristy4c08aed2011-07-01 19:47:50 +00002249 ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
cristybb503372010-05-27 20:51:26 +00002250 pixel=(size_t) (((size_t) color.red & 0xe0) |
2251 (((size_t) color.green & 0xe0) >> 3) |
2252 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002253 *q++=(char) pixel;
cristyed231572011-07-14 02:18:59 +00002254 p+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +00002255 j++;
2256 if (j == 16)
2257 j=0;
2258 }
2259 q+=scanline_pad;
2260 i++;
2261 if (i == 2)
2262 i=0;
2263 }
cristyc57f6942010-11-12 01:47:39 +00002264 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002265 /*
2266 Free allocated memory.
2267 */
2268 for (i=0; i < 2; i++)
2269 for (j=0; j < 16; j++)
2270 {
2271 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2272 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2273 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2274 }
2275}
2276
2277/*
2278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2279% %
2280% %
2281% %
2282% X D r a w I m a g e %
2283% %
2284% %
2285% %
2286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2287%
2288% XDrawImage() draws a line on the image.
2289%
2290% The format of the XDrawImage method is:
2291%
cristy6710d842011-10-20 23:23:00 +00002292% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
2293% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002294%
2295% A description of each parameter follows:
2296%
2297% o display: Specifies a connection to an X server; returned from
2298% XOpenDisplay.
2299%
2300% o pixel: Specifies a pointer to a XPixelInfo structure.
2301%
2302% o draw_info: Specifies a pointer to a XDrawInfo structure.
2303%
2304% o image: the image.
2305%
cristy6710d842011-10-20 23:23:00 +00002306% o exception: return any errors or warnings in this structure.
2307%
cristy3ed852e2009-09-05 21:47:34 +00002308*/
cristybcbda3f2011-09-03 13:01:22 +00002309MagickPrivate MagickBooleanType XDrawImage(Display *display,
cristy6710d842011-10-20 23:23:00 +00002310 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
2311 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002312{
cristyc57f6942010-11-12 01:47:39 +00002313 CacheView
2314 *draw_view;
2315
cristy3ed852e2009-09-05 21:47:34 +00002316 GC
2317 draw_context;
2318
2319 Image
2320 *draw_image;
2321
2322 int
2323 x,
2324 y;
2325
2326 MagickBooleanType
2327 matte;
2328
cristy2ed42f62011-10-02 19:49:57 +00002329 Quantum
cristy5f95f4f2011-10-23 01:01:01 +00002330 virtual_pixel[CompositePixelChannel];
cristy2ed42f62011-10-02 19:49:57 +00002331
cristy3ed852e2009-09-05 21:47:34 +00002332 Pixmap
2333 draw_pixmap;
2334
2335 unsigned int
2336 depth,
2337 height,
2338 width;
2339
2340 Window
2341 root_window;
2342
2343 XGCValues
2344 context_values;
2345
2346 XImage
2347 *draw_ximage;
2348
2349 /*
2350 Initialize drawd image.
2351 */
2352 assert(display != (Display *) NULL);
2353 assert(pixel != (XPixelInfo *) NULL);
2354 assert(draw_info != (XDrawInfo *) NULL);
2355 assert(image != (Image *) NULL);
2356 if (image->debug != MagickFalse)
2357 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2358 /*
2359 Initialize drawd pixmap.
2360 */
2361 root_window=XRootWindow(display,XDefaultScreen(display));
2362 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2363 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2364 draw_info->height,depth);
2365 if (draw_pixmap == (Pixmap) NULL)
2366 return(MagickFalse);
2367 /*
2368 Initialize graphics info.
2369 */
cristybb503372010-05-27 20:51:26 +00002370 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002371 context_values.foreground=0;
2372 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002373 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002374 (GCBackground | GCForeground | GCLineWidth),&context_values);
2375 if (draw_context == (GC) NULL)
2376 return(MagickFalse);
2377 /*
2378 Clear pixmap.
2379 */
2380 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2381 draw_info->height);
2382 /*
2383 Draw line to pixmap.
2384 */
2385 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002386 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002387 if (draw_info->stipple != (Pixmap) NULL)
2388 {
2389 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2390 (void) XSetStipple(display,draw_context,draw_info->stipple);
2391 }
cristy3ed852e2009-09-05 21:47:34 +00002392 switch (draw_info->element)
2393 {
2394 case PointElement:
2395 default:
2396 {
2397 (void) XDrawLines(display,draw_pixmap,draw_context,
2398 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2399 CoordModeOrigin);
2400 break;
2401 }
2402 case LineElement:
2403 {
2404 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2405 draw_info->line_info.y1,draw_info->line_info.x2,
2406 draw_info->line_info.y2);
2407 break;
2408 }
2409 case RectangleElement:
2410 {
2411 (void) XDrawRectangle(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 FillRectangleElement:
2418 {
2419 (void) XFillRectangle(display,draw_pixmap,draw_context,
2420 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2421 (unsigned int) draw_info->rectangle_info.width,
2422 (unsigned int) draw_info->rectangle_info.height);
2423 break;
2424 }
2425 case CircleElement:
2426 case EllipseElement:
2427 {
2428 (void) XDrawArc(display,draw_pixmap,draw_context,
2429 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2430 (unsigned int) draw_info->rectangle_info.width,
2431 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2432 break;
2433 }
2434 case FillCircleElement:
2435 case FillEllipseElement:
2436 {
2437 (void) XFillArc(display,draw_pixmap,draw_context,
2438 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2439 (unsigned int) draw_info->rectangle_info.width,
2440 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2441 break;
2442 }
2443 case PolygonElement:
2444 {
2445 XPoint
2446 *coordinate_info;
2447
2448 coordinate_info=draw_info->coordinate_info;
2449 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2450 (int) draw_info->number_coordinates,CoordModeOrigin);
2451 (void) XDrawLine(display,draw_pixmap,draw_context,
2452 coordinate_info[draw_info->number_coordinates-1].x,
2453 coordinate_info[draw_info->number_coordinates-1].y,
2454 coordinate_info[0].x,coordinate_info[0].y);
2455 break;
2456 }
2457 case FillPolygonElement:
2458 {
2459 (void) XFillPolygon(display,draw_pixmap,draw_context,
2460 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2461 CoordModeOrigin);
2462 break;
2463 }
2464 }
2465 (void) XFreeGC(display,draw_context);
2466 /*
2467 Initialize X image.
2468 */
2469 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2470 draw_info->height,AllPlanes,ZPixmap);
2471 if (draw_ximage == (XImage *) NULL)
2472 return(MagickFalse);
2473 (void) XFreePixmap(display,draw_pixmap);
2474 /*
2475 Initialize draw image.
2476 */
cristy6710d842011-10-20 23:23:00 +00002477 draw_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00002478 if (draw_image == (Image *) NULL)
2479 return(MagickFalse);
2480 draw_image->columns=draw_info->width;
2481 draw_image->rows=draw_info->height;
2482 /*
2483 Transfer drawn X image to image.
2484 */
2485 width=(unsigned int) image->columns;
2486 height=(unsigned int) image->rows;
2487 x=0;
2488 y=0;
2489 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristy2ed42f62011-10-02 19:49:57 +00002490 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,virtual_pixel,
cristy6710d842011-10-20 23:23:00 +00002491 exception);
cristy2ed42f62011-10-02 19:49:57 +00002492 draw_image->background_color.red=virtual_pixel[RedPixelChannel];
2493 draw_image->background_color.green=virtual_pixel[GreenPixelChannel];
2494 draw_image->background_color.blue=virtual_pixel[BluePixelChannel];
2495 draw_image->background_color.alpha=virtual_pixel[AlphaPixelChannel];
cristy6710d842011-10-20 23:23:00 +00002496 if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002497 return(MagickFalse);
2498 draw_image->matte=MagickTrue;
cristyc57f6942010-11-12 01:47:39 +00002499 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002500 for (y=0; y < (int) draw_image->rows; y++)
2501 {
cristyc57f6942010-11-12 01:47:39 +00002502 register int
cristy3ed852e2009-09-05 21:47:34 +00002503 x;
2504
cristy4c08aed2011-07-01 19:47:50 +00002505 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002506 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002507
cristyc57f6942010-11-12 01:47:39 +00002508 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2509 1,exception);
cristyacd2ed22011-08-30 01:44:23 +00002510 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002511 break;
cristyc57f6942010-11-12 01:47:39 +00002512 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002513 {
2514 if (XGetPixel(draw_ximage,x,y) == 0)
2515 {
2516 /*
2517 Set this pixel to the background color.
2518 */
cristy803640d2011-11-17 02:11:32 +00002519 SetPixelInfoPixel(draw_image,&draw_image->background_color,q);
cristy76761582011-09-18 02:14:00 +00002520 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
cristy4c08aed2011-07-01 19:47:50 +00002521 OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002522 }
2523 else
2524 {
2525 /*
2526 Set this pixel to the pen color.
2527 */
cristy4c08aed2011-07-01 19:47:50 +00002528 SetPixelRed(draw_image,ScaleShortToQuantum(
2529 pixel->pen_color.red),q);
2530 SetPixelGreen(draw_image,ScaleShortToQuantum(
2531 pixel->pen_color.green),q);
2532 SetPixelBlue(draw_image,ScaleShortToQuantum(
2533 pixel->pen_color.blue),q);
2534 SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
2535 OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
cristy3ed852e2009-09-05 21:47:34 +00002536 }
cristyed231572011-07-14 02:18:59 +00002537 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002538 }
cristyc57f6942010-11-12 01:47:39 +00002539 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002540 break;
2541 }
cristyc57f6942010-11-12 01:47:39 +00002542 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002543 XDestroyImage(draw_ximage);
2544 /*
2545 Determine draw geometry.
2546 */
2547 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2548 if ((width != (unsigned int) draw_image->columns) ||
2549 (height != (unsigned int) draw_image->rows))
2550 {
2551 char
2552 image_geometry[MaxTextExtent];
2553
2554 /*
2555 Scale image.
2556 */
cristyb51dff52011-05-19 16:55:47 +00002557 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
cristy3ed852e2009-09-05 21:47:34 +00002558 width,height);
cristye941a752011-10-15 01:52:48 +00002559 (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
2560 exception);
cristy3ed852e2009-09-05 21:47:34 +00002561 }
2562 if (draw_info->degrees != 0.0)
2563 {
2564 Image
2565 *rotate_image;
2566
2567 int
2568 rotations;
2569
2570 MagickRealType
2571 normalized_degrees;
2572
2573 /*
2574 Rotate image.
2575 */
cristy6710d842011-10-20 23:23:00 +00002576 rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
cristy3ed852e2009-09-05 21:47:34 +00002577 if (rotate_image == (Image *) NULL)
2578 return(MagickFalse);
2579 draw_image=DestroyImage(draw_image);
2580 draw_image=rotate_image;
2581 /*
2582 Annotation is relative to the degree of rotation.
2583 */
2584 normalized_degrees=draw_info->degrees;
2585 while (normalized_degrees < -45.0)
2586 normalized_degrees+=360.0;
2587 for (rotations=0; normalized_degrees > 45.0; rotations++)
2588 normalized_degrees-=90.0;
2589 switch (rotations % 4)
2590 {
2591 default:
2592 case 0:
2593 break;
2594 case 1:
2595 {
2596 /*
2597 Rotate 90 degrees.
2598 */
2599 x=x-(int) draw_image->columns/2;
2600 y=y+(int) draw_image->columns/2;
2601 break;
2602 }
2603 case 2:
2604 {
2605 /*
2606 Rotate 180 degrees.
2607 */
2608 x=x-(int) draw_image->columns;
2609 break;
2610 }
2611 case 3:
2612 {
2613 /*
2614 Rotate 270 degrees.
2615 */
2616 x=x-(int) draw_image->columns/2;
2617 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2618 break;
2619 }
2620 }
2621 }
2622 /*
2623 Composite text onto the image.
2624 */
cristyc57f6942010-11-12 01:47:39 +00002625 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002626 for (y=0; y < (int) draw_image->rows; y++)
2627 {
cristyc57f6942010-11-12 01:47:39 +00002628 register int
cristy3ed852e2009-09-05 21:47:34 +00002629 x;
2630
cristy4c08aed2011-07-01 19:47:50 +00002631 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00002632 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002633
cristyc57f6942010-11-12 01:47:39 +00002634 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2635 exception);
cristyacd2ed22011-08-30 01:44:23 +00002636 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002637 break;
cristyc57f6942010-11-12 01:47:39 +00002638 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002639 {
cristy4c08aed2011-07-01 19:47:50 +00002640 if (GetPixelAlpha(image,q) != TransparentAlpha)
2641 SetPixelAlpha(draw_image,OpaqueAlpha,q);
cristyed231572011-07-14 02:18:59 +00002642 q+=GetPixelChannels(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002643 }
cristyc57f6942010-11-12 01:47:39 +00002644 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002645 break;
2646 }
cristyc57f6942010-11-12 01:47:39 +00002647 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002648 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2649 if (draw_info->stencil == TransparentStencil)
cristyc57f6942010-11-12 01:47:39 +00002650 (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,(ssize_t) x,
cristye941a752011-10-15 01:52:48 +00002651 (ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002652 else
2653 {
2654 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002655 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
cristye941a752011-10-15 01:52:48 +00002656 (ssize_t) y,exception);
cristy3ed852e2009-09-05 21:47:34 +00002657 image->matte=matte;
2658 }
2659 draw_image=DestroyImage(draw_image);
2660 return(MagickTrue);
2661}
2662
2663/*
2664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2665% %
2666% %
2667% %
2668% X E r r o r %
2669% %
2670% %
2671% %
2672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2673%
2674% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2675% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
cristybcbda3f2011-09-03 13:01:22 +00002676% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
2677% returns True.
cristy3ed852e2009-09-05 21:47:34 +00002678%
2679% The format of the XError function is:
2680%
cristybcbda3f2011-09-03 13:01:22 +00002681% int XError(display,error)
cristy3ed852e2009-09-05 21:47:34 +00002682%
2683% A description of each parameter follows:
2684%
2685% o display: Specifies a pointer to the Display structure; returned from
2686% XOpenDisplay.
2687%
2688% o error: Specifies the error event.
2689%
2690*/
2691
2692#if defined(__cplusplus) || defined(c_plusplus)
2693extern "C" {
2694#endif
2695
2696MagickExport int XError(Display *display,XErrorEvent *error)
2697{
2698 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2699 assert(display != (Display *) NULL);
2700 assert(error != (XErrorEvent *) NULL);
2701 xerror_alert=MagickTrue;
2702 switch (error->request_code)
2703 {
2704 case X_GetGeometry:
2705 {
2706 if ((int) error->error_code == BadDrawable)
2707 return(MagickFalse);
2708 break;
2709 }
2710 case X_GetWindowAttributes:
2711 case X_QueryTree:
2712 {
2713 if ((int) error->error_code == BadWindow)
2714 return(MagickFalse);
2715 break;
2716 }
2717 case X_QueryColors:
2718 {
2719 if ((int) error->error_code == BadValue)
2720 return(MagickFalse);
2721 break;
2722 }
2723 }
2724 return(MagickTrue);
2725}
2726
2727#if defined(__cplusplus) || defined(c_plusplus)
2728}
2729#endif
2730
2731/*
2732%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2733% %
2734% %
2735% %
2736% X F r e e R e s o u r c e s %
2737% %
2738% %
2739% %
2740%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2741%
2742% XFreeResources() frees X11 resources.
2743%
2744% The format of the XFreeResources method is:
2745%
2746% void XFreeResources(Display *display,XVisualInfo *visual_info,
2747% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2748% XResourceInfo *resource_info,XWindowInfo *window_info)
2749% resource_info,window_info)
2750%
2751% A description of each parameter follows:
2752%
2753% o display: Specifies a connection to an X server; returned from
2754% XOpenDisplay.
2755%
2756% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2757% returned from XGetVisualInfo.
2758%
2759% o map_info: If map_type is specified, this structure is initialized
2760% with info from the Standard Colormap.
2761%
2762% o pixel: Specifies a pointer to a XPixelInfo structure.
2763%
2764% o font_info: Specifies a pointer to a XFontStruct structure.
2765%
2766% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2767%
2768% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2769%
2770*/
cristybcbda3f2011-09-03 13:01:22 +00002771MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002772 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2773 XResourceInfo *resource_info,XWindowInfo *window_info)
2774{
2775 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2776 assert(display != (Display *) NULL);
2777 assert(resource_info != (XResourceInfo *) NULL);
2778 if (window_info != (XWindowInfo *) NULL)
2779 {
2780 /*
2781 Free X image.
2782 */
2783 if (window_info->ximage != (XImage *) NULL)
2784 XDestroyImage(window_info->ximage);
2785 if (window_info->id != (Window) NULL)
2786 {
2787 /*
2788 Free destroy window and free cursors.
2789 */
2790 if (window_info->id != XRootWindow(display,visual_info->screen))
2791 (void) XDestroyWindow(display,window_info->id);
2792 if (window_info->annotate_context != (GC) NULL)
2793 (void) XFreeGC(display,window_info->annotate_context);
2794 if (window_info->highlight_context != (GC) NULL)
2795 (void) XFreeGC(display,window_info->highlight_context);
2796 if (window_info->widget_context != (GC) NULL)
2797 (void) XFreeGC(display,window_info->widget_context);
2798 if (window_info->cursor != (Cursor) NULL)
2799 (void) XFreeCursor(display,window_info->cursor);
2800 window_info->cursor=(Cursor) NULL;
2801 if (window_info->busy_cursor != (Cursor) NULL)
2802 (void) XFreeCursor(display,window_info->busy_cursor);
2803 window_info->busy_cursor=(Cursor) NULL;
2804 }
2805 }
2806 /*
2807 Free font.
2808 */
2809 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002810 {
2811 (void) XFreeFont(display,font_info);
2812 font_info=(XFontStruct *) NULL;
2813 }
cristy3ed852e2009-09-05 21:47:34 +00002814 if (map_info != (XStandardColormap *) NULL)
2815 {
2816 /*
2817 Free X Standard Colormap.
2818 */
2819 if (resource_info->map_type == (char *) NULL)
2820 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2821 (void) XFree((void *) map_info);
2822 }
2823 /*
2824 Free X visual info.
2825 */
2826 if (visual_info != (XVisualInfo *) NULL)
2827 (void) XFree((void *) visual_info);
2828 if (resource_info->close_server != MagickFalse)
2829 (void) XCloseDisplay(display);
2830}
2831
2832/*
2833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2834% %
2835% %
2836% %
2837% X F r e e S t a n d a r d C o l o r m a p %
2838% %
2839% %
2840% %
2841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2842%
2843% XFreeStandardColormap() frees an X11 colormap.
2844%
2845% The format of the XFreeStandardColormap method is:
2846%
2847% void XFreeStandardColormap(Display *display,
2848% const XVisualInfo *visual_info,XStandardColormap *map_info,
2849% XPixelInfo *pixel)
2850%
2851% A description of each parameter follows:
2852%
2853% o display: Specifies a connection to an X server; returned from
2854% XOpenDisplay.
2855%
2856% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2857% returned from XGetVisualInfo.
2858%
2859% o map_info: If map_type is specified, this structure is initialized
2860% with info from the Standard Colormap.
2861%
2862% o pixel: Specifies a pointer to a XPixelInfo structure.
2863%
2864*/
cristybcbda3f2011-09-03 13:01:22 +00002865MagickPrivate void XFreeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00002866 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2867{
2868 /*
2869 Free colormap.
2870 */
2871 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2872 assert(display != (Display *) NULL);
2873 assert(visual_info != (XVisualInfo *) NULL);
2874 assert(map_info != (XStandardColormap *) NULL);
2875 (void) XFlush(display);
2876 if (map_info->colormap != (Colormap) NULL)
2877 {
2878 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2879 (void) XFreeColormap(display,map_info->colormap);
2880 else
2881 if (pixel != (XPixelInfo *) NULL)
2882 if ((visual_info->klass != TrueColor) &&
2883 (visual_info->klass != DirectColor))
2884 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2885 (int) pixel->colors,0);
2886 }
2887 map_info->colormap=(Colormap) NULL;
2888 if (pixel != (XPixelInfo *) NULL)
2889 {
cristyf2faecf2010-05-28 19:19:36 +00002890 if (pixel->pixels != (unsigned long *) NULL)
2891 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2892 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002893 }
2894}
2895
2896/*
2897%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2898% %
2899% %
2900% %
2901% X G e t A n n o t a t e I n f o %
2902% %
2903% %
2904% %
2905%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2906%
2907% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2908%
2909% The format of the XGetAnnotateInfo method is:
2910%
2911% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2912%
2913% A description of each parameter follows:
2914%
2915% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2916%
2917*/
cristybcbda3f2011-09-03 13:01:22 +00002918MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
cristy3ed852e2009-09-05 21:47:34 +00002919{
2920 /*
2921 Initialize annotate structure.
2922 */
2923 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2924 assert(annotate_info != (XAnnotateInfo *) NULL);
2925 annotate_info->x=0;
2926 annotate_info->y=0;
2927 annotate_info->width=0;
2928 annotate_info->height=0;
2929 annotate_info->stencil=ForegroundStencil;
2930 annotate_info->degrees=0.0;
2931 annotate_info->font_info=(XFontStruct *) NULL;
2932 annotate_info->text=(char *) NULL;
2933 *annotate_info->geometry='\0';
2934 annotate_info->previous=(XAnnotateInfo *) NULL;
2935 annotate_info->next=(XAnnotateInfo *) NULL;
2936 (void) XSupportsLocale();
2937 (void) XSetLocaleModifiers("");
2938}
2939
2940/*
2941%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2942% %
2943% %
2944% %
2945% X G e t M a p I n f o %
2946% %
2947% %
2948% %
2949%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2950%
2951% XGetMapInfo() initializes the XStandardColormap structure.
2952%
2953% The format of the XStandardColormap method is:
2954%
2955% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2956% XStandardColormap *map_info)
2957%
2958% A description of each parameter follows:
2959%
2960% o colormap: Specifies the ID of the X server colormap.
2961%
2962% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2963% returned from XGetVisualInfo.
2964%
2965% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2966%
2967*/
cristybcbda3f2011-09-03 13:01:22 +00002968MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00002969 const Colormap colormap,XStandardColormap *map_info)
2970{
2971 /*
2972 Initialize map info.
2973 */
2974 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2975 assert(visual_info != (XVisualInfo *) NULL);
2976 assert(map_info != (XStandardColormap *) NULL);
2977 map_info->colormap=colormap;
2978 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002979 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002980 if (map_info->red_max != 0)
2981 while ((map_info->red_max & 0x01) == 0)
2982 {
2983 map_info->red_max>>=1;
2984 map_info->red_mult<<=1;
2985 }
2986 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002987 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002988 if (map_info->green_max != 0)
2989 while ((map_info->green_max & 0x01) == 0)
2990 {
2991 map_info->green_max>>=1;
2992 map_info->green_mult<<=1;
2993 }
2994 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002995 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002996 if (map_info->blue_max != 0)
2997 while ((map_info->blue_max & 0x01) == 0)
2998 {
2999 map_info->blue_max>>=1;
3000 map_info->blue_mult<<=1;
3001 }
3002 map_info->base_pixel=0;
3003}
3004
3005/*
3006%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3007% %
3008% %
3009% %
3010% X G e t P i x e l I n f o %
3011% %
3012% %
3013% %
3014%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3015%
cristy101ab702011-10-13 13:06:32 +00003016% XGetPixelInfo() initializes the PixelInfo structure.
cristy3ed852e2009-09-05 21:47:34 +00003017%
cristy4c08aed2011-07-01 19:47:50 +00003018% The format of the XGetPixelInfo method is:
cristy3ed852e2009-09-05 21:47:34 +00003019%
cristy4c08aed2011-07-01 19:47:50 +00003020% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00003021% const XStandardColormap *map_info,const XResourceInfo *resource_info,
3022% Image *image,XPixelInfo *pixel)
3023% pixel)
3024%
3025% A description of each parameter follows:
3026%
3027% o display: Specifies a connection to an X server; returned from
3028% XOpenDisplay.
3029%
3030% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
3031% returned from XGetVisualInfo.
3032%
3033% o map_info: If map_type is specified, this structure is initialized
3034% with info from the Standard Colormap.
3035%
3036% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3037%
3038% o image: the image.
3039%
3040% o pixel: Specifies a pointer to a XPixelInfo structure.
3041%
3042*/
cristybcbda3f2011-09-03 13:01:22 +00003043MagickPrivate void XGetPixelInfo(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00003044 const XVisualInfo *visual_info,const XStandardColormap *map_info,
3045 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
3046{
3047 static const char
3048 *PenColors[MaxNumberPens]=
3049 {
3050 "#000000000000", /* black */
3051 "#00000000ffff", /* blue */
3052 "#0000ffffffff", /* cyan */
3053 "#0000ffff0000", /* green */
3054 "#bdbdbdbdbdbd", /* gray */
3055 "#ffff00000000", /* red */
3056 "#ffff0000ffff", /* magenta */
3057 "#ffffffff0000", /* yellow */
3058 "#ffffffffffff", /* white */
3059 "#bdbdbdbdbdbd", /* gray */
3060 "#bdbdbdbdbdbd" /* gray */
3061 };
3062
3063 Colormap
3064 colormap;
3065
cristybb503372010-05-27 20:51:26 +00003066 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003067 i;
3068
3069 Status
3070 status;
3071
3072 unsigned int
3073 packets;
3074
3075 /*
3076 Initialize pixel info.
3077 */
3078 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3079 assert(display != (Display *) NULL);
3080 assert(visual_info != (XVisualInfo *) NULL);
3081 assert(map_info != (XStandardColormap *) NULL);
3082 assert(resource_info != (XResourceInfo *) NULL);
3083 assert(pixel != (XPixelInfo *) NULL);
3084 pixel->colors=0;
3085 if (image != (Image *) NULL)
3086 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003087 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003088 packets=(unsigned int)
3089 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003090 if (pixel->pixels != (unsigned long *) NULL)
3091 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3092 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003093 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003094 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003095 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3096 image->filename);
3097 /*
3098 Set foreground color.
3099 */
3100 colormap=map_info->colormap;
3101 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3102 &pixel->foreground_color);
3103 status=XParseColor(display,colormap,resource_info->foreground_color,
3104 &pixel->foreground_color);
3105 if (status == False)
3106 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3107 resource_info->foreground_color);
3108 pixel->foreground_color.pixel=
3109 XStandardPixel(map_info,&pixel->foreground_color);
3110 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3111 /*
3112 Set background color.
3113 */
3114 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3115 status=XParseColor(display,colormap,resource_info->background_color,
3116 &pixel->background_color);
3117 if (status == False)
3118 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3119 resource_info->background_color);
3120 pixel->background_color.pixel=
3121 XStandardPixel(map_info,&pixel->background_color);
3122 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3123 /*
3124 Set border color.
3125 */
3126 (void) XParseColor(display,colormap,(char *) BorderColor,
3127 &pixel->border_color);
3128 status=XParseColor(display,colormap,resource_info->border_color,
3129 &pixel->border_color);
3130 if (status == False)
3131 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3132 resource_info->border_color);
3133 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3134 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3135 /*
3136 Set matte color.
3137 */
3138 pixel->matte_color=pixel->background_color;
3139 if (resource_info->matte_color != (char *) NULL)
3140 {
3141 /*
3142 Matte color is specified as a X resource or command line argument.
3143 */
3144 status=XParseColor(display,colormap,resource_info->matte_color,
3145 &pixel->matte_color);
3146 if (status == False)
3147 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3148 resource_info->matte_color);
3149 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3150 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3151 }
3152 /*
3153 Set highlight color.
3154 */
3155 pixel->highlight_color.red=(unsigned short) ((
3156 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3157 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3158 pixel->highlight_color.green=(unsigned short) ((
3159 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3160 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3161 pixel->highlight_color.blue=(unsigned short) ((
3162 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3163 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3164 pixel->highlight_color.pixel=
3165 XStandardPixel(map_info,&pixel->highlight_color);
3166 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3167 /*
3168 Set shadow color.
3169 */
3170 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3171 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3172 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3173 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3174 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3175 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3176 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3177 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3178 /*
3179 Set depth color.
3180 */
3181 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3182 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3183 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3184 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3185 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3186 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3187 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3188 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3189 /*
3190 Set trough color.
3191 */
3192 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3193 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3194 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3195 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3196 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3197 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3198 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3199 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3200 /*
3201 Set pen color.
3202 */
3203 for (i=0; i < MaxNumberPens; i++)
3204 {
3205 (void) XParseColor(display,colormap,(char *) PenColors[i],
3206 &pixel->pen_colors[i]);
3207 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3208 &pixel->pen_colors[i]);
3209 if (status == False)
3210 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3211 resource_info->pen_colors[i]);
3212 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3213 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3214 }
3215 pixel->box_color=pixel->background_color;
3216 pixel->pen_color=pixel->foreground_color;
3217 pixel->box_index=0;
3218 pixel->pen_index=1;
3219 if (image != (Image *) NULL)
3220 {
3221 if ((resource_info->gamma_correct != MagickFalse) &&
3222 (image->gamma != 0.0))
3223 {
3224 GeometryInfo
3225 geometry_info;
3226
3227 MagickStatusType
3228 flags;
3229
3230 /*
3231 Initialize map relative to display and image gamma.
3232 */
3233 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3234 red_gamma=geometry_info.rho;
3235 green_gamma=geometry_info.sigma;
3236 if ((flags & SigmaValue) == 0)
3237 green_gamma=red_gamma;
3238 blue_gamma=geometry_info.xi;
3239 if ((flags & XiValue) == 0)
3240 blue_gamma=red_gamma;
3241 red_gamma*=image->gamma;
3242 green_gamma*=image->gamma;
3243 blue_gamma*=image->gamma;
3244 }
3245 if (image->storage_class == PseudoClass)
3246 {
3247 /*
3248 Initialize pixel array for images of type PseudoClass.
3249 */
cristybb503372010-05-27 20:51:26 +00003250 for (i=0; i < (ssize_t) image->colors; i++)
cristy4c08aed2011-07-01 19:47:50 +00003251 pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003252 for (i=0; i < MaxNumberPens; i++)
3253 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3254 pixel->colors+=MaxNumberPens;
3255 }
3256 }
3257}
3258
3259/*
3260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3261% %
3262% %
3263% %
3264% X G e t R e s o u r c e C l a s s %
3265% %
3266% %
3267% %
3268%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3269%
3270% XGetResourceClass() queries the X server for the specified resource name or
3271% class. If the resource name or class is not defined in the database, the
3272% supplied default value is returned.
3273%
3274% The format of the XGetResourceClass method is:
3275%
3276% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3277% const char *keyword,char *resource_default)
3278%
3279% A description of each parameter follows:
3280%
3281% o database: Specifies a resource database; returned from
3282% XrmGetStringDatabase.
3283%
3284% o client_name: Specifies the application name used to retrieve resource
3285% info from the X server database.
3286%
3287% o keyword: Specifies the keyword of the value being retrieved.
3288%
3289% o resource_default: Specifies the default value to return if the query
3290% fails to find the specified keyword/class.
3291%
3292*/
3293MagickExport char *XGetResourceClass(XrmDatabase database,
3294 const char *client_name,const char *keyword,char *resource_default)
3295{
3296 char
3297 resource_class[MaxTextExtent],
3298 resource_name[MaxTextExtent];
3299
3300 static char
3301 *resource_type;
3302
3303 Status
3304 status;
3305
3306 XrmValue
3307 resource_value;
3308
3309 if (database == (XrmDatabase) NULL)
3310 return(resource_default);
3311 *resource_name='\0';
3312 *resource_class='\0';
3313 if (keyword != (char *) NULL)
3314 {
3315 int
3316 c,
3317 k;
3318
3319 /*
3320 Initialize resource keyword and class.
3321 */
cristyb51dff52011-05-19 16:55:47 +00003322 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
cristy3ed852e2009-09-05 21:47:34 +00003323 client_name,keyword);
3324 c=(int) (*client_name);
3325 if ((c >= XK_a) && (c <= XK_z))
3326 c-=(XK_a-XK_A);
3327 else
3328 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3329 c-=(XK_agrave-XK_Agrave);
3330 else
3331 if ((c >= XK_oslash) && (c <= XK_thorn))
3332 c-=(XK_oslash-XK_Ooblique);
3333 k=(int) (*keyword);
3334 if ((k >= XK_a) && (k <= XK_z))
3335 k-=(XK_a-XK_A);
3336 else
3337 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3338 k-=(XK_agrave-XK_Agrave);
3339 else
3340 if ((k >= XK_oslash) && (k <= XK_thorn))
3341 k-=(XK_oslash-XK_Ooblique);
cristyb51dff52011-05-19 16:55:47 +00003342 (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
cristy3ed852e2009-09-05 21:47:34 +00003343 client_name+1,k,keyword+1);
3344 }
3345 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3346 &resource_value);
3347 if (status == False)
3348 return(resource_default);
3349 return(resource_value.addr);
3350}
3351
3352/*
3353%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3354% %
3355% %
3356% %
3357% X G e t R e s o u r c e D a t a b a s e %
3358% %
3359% %
3360% %
3361%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3362%
3363% XGetResourceDatabase() creates a new resource database and initializes it.
3364%
3365% The format of the XGetResourceDatabase method is:
3366%
3367% XrmDatabase XGetResourceDatabase(Display *display,
3368% const char *client_name)
3369%
3370% A description of each parameter follows:
3371%
3372% o database: XGetResourceDatabase() returns the database after it is
3373% initialized.
3374%
3375% o display: Specifies a connection to an X server; returned from
3376% XOpenDisplay.
3377%
3378% o client_name: Specifies the application name used to retrieve resource
3379% info from the X server database.
3380%
3381*/
3382MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3383 const char *client_name)
3384{
3385 char
3386 filename[MaxTextExtent];
3387
3388 int
3389 c;
3390
3391 register const char
3392 *p;
3393
3394 XrmDatabase
3395 resource_database,
3396 server_database;
3397
3398 if (display == (Display *) NULL)
3399 return((XrmDatabase) NULL);
3400 assert(client_name != (char *) NULL);
3401 /*
3402 Initialize resource database.
3403 */
3404 XrmInitialize();
3405 (void) XGetDefault(display,(char *) client_name,"dummy");
3406 resource_database=XrmGetDatabase(display);
3407 /*
3408 Combine application database.
3409 */
3410 if (client_name != (char *) NULL)
3411 {
3412 /*
3413 Get basename of client.
3414 */
3415 p=client_name+(strlen(client_name)-1);
3416 while ((p > client_name) && (*p != '/'))
3417 p--;
3418 if (*p == '/')
3419 client_name=p+1;
3420 }
3421 c=(int) (*client_name);
3422 if ((c >= XK_a) && (c <= XK_z))
3423 c-=(XK_a-XK_A);
3424 else
3425 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3426 c-=(XK_agrave-XK_Agrave);
3427 else
3428 if ((c >= XK_oslash) && (c <= XK_thorn))
3429 c-=(XK_oslash-XK_Ooblique);
3430#if defined(X11_APPLICATION_PATH)
cristyb51dff52011-05-19 16:55:47 +00003431 (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
cristy3ed852e2009-09-05 21:47:34 +00003432 X11_APPLICATION_PATH,c,client_name+1);
3433 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3434#endif
3435 if (XResourceManagerString(display) != (char *) NULL)
3436 {
3437 /*
3438 Combine server database.
3439 */
3440 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3441 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3442 }
3443 /*
3444 Merge user preferences database.
3445 */
3446#if defined(X11_PREFERENCES_PATH)
cristyb51dff52011-05-19 16:55:47 +00003447 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy3ed852e2009-09-05 21:47:34 +00003448 X11_PREFERENCES_PATH,client_name);
3449 ExpandFilename(filename);
3450 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3451#endif
3452 return(resource_database);
3453}
3454
3455/*
3456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3457% %
3458% %
3459% %
3460% X G e t R e s o u r c e I n f o %
3461% %
3462% %
3463% %
3464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3465%
3466% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3467%
3468% The format of the XGetResourceInfo method is:
3469%
3470% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3471% const char *client_name,XResourceInfo *resource_info)
3472%
3473% A description of each parameter follows:
3474%
3475% o image_info: the image info.
3476%
3477% o database: Specifies a resource database; returned from
3478% XrmGetStringDatabase.
3479%
3480% o client_name: Specifies the application name used to retrieve
3481% resource info from the X server database.
3482%
3483% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3484%
3485*/
3486MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3487 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3488{
3489 char
cristy00976d82011-02-20 20:31:28 +00003490 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003491 *resource_value;
3492
3493 /*
3494 Initialize resource info fields.
3495 */
3496 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3497 assert(resource_info != (XResourceInfo *) NULL);
3498 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3499 resource_info->resource_database=database;
3500 resource_info->image_info=(ImageInfo *) image_info;
3501 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3502 XMagickProgressMonitor,(void *) NULL);
3503 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3504 resource_info->close_server=MagickTrue;
3505 resource_info->client_name=AcquireString(client_name);
3506 resource_value=XGetResourceClass(database,client_name,"backdrop",
3507 (char *) "False");
3508 resource_info->backdrop=IsMagickTrue(resource_value);
3509 resource_info->background_color=XGetResourceInstance(database,client_name,
3510 "background",(char *) "#d6d6d6d6d6d6");
3511 resource_info->border_color=XGetResourceInstance(database,client_name,
3512 "borderColor",BorderColor);
3513 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3514 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003515 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3516 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003517 resource_value=XGetResourceClass(database,client_name,"colormap",
3518 (char *) "shared");
3519 resource_info->colormap=UndefinedColormap;
3520 if (LocaleCompare("private",resource_value) == 0)
3521 resource_info->colormap=PrivateColormap;
3522 if (LocaleCompare("shared",resource_value) == 0)
3523 resource_info->colormap=SharedColormap;
3524 if (resource_info->colormap == UndefinedColormap)
3525 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3526 resource_value);
3527 resource_value=XGetResourceClass(database,client_name,
3528 "colorRecovery",(char *) "False");
3529 resource_info->color_recovery=IsMagickTrue(resource_value);
3530 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3531 (char *) "False");
3532 resource_info->confirm_exit=IsMagickTrue(resource_value);
3533 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3534 (char *) "False");
3535 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003536 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003537 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003538 resource_info->display_gamma=XGetResourceClass(database,client_name,
3539 "displayGamma",(char *) "2.2");
3540 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3541 (char *) "True");
3542 resource_info->display_warnings=IsMagickTrue(resource_value);
3543 resource_info->font=XGetResourceClass(database,client_name,"font",
3544 (char *) NULL);
3545 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3546 resource_info->font);
3547 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3548 (char *) "fixed");
3549 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3550 (char *) "variable");
3551 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3552 (char *) "5x8");
3553 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3554 (char *) "6x10");
3555 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3556 (char *) "7x13bold");
3557 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3558 (char *) "8x13bold");
3559 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3560 (char *) "9x15bold");
3561 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3562 (char *) "10x20");
3563 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3564 (char *) "12x24");
3565 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3566 (char *) "fixed");
3567 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3568 (char *) "fixed");
3569 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3570 "foreground",ForegroundColor);
3571 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3572 (char *) "True");
3573 resource_info->gamma_correct=IsMagickTrue(resource_value);
3574 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3575 client_name,"geometry",(char *) NULL));
3576 resource_value=XGetResourceClass(database,client_name,"gravity",
3577 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003578 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003579 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003580 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3581 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003582 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3583 "iconGeometry",(char *) NULL);
3584 resource_value=XGetResourceClass(database,client_name,"iconic",
3585 (char *) "False");
3586 resource_info->iconic=IsMagickTrue(resource_value);
3587 resource_value=XGetResourceClass(database,client_name,"immutable",
3588 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3589 (char *) "False");
3590 resource_info->immutable=IsMagickTrue(resource_value);
3591 resource_value=XGetResourceClass(database,client_name,"magnify",
3592 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003593 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003594 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3595 (char *) NULL);
3596 resource_info->matte_color=XGetResourceInstance(database,client_name,
3597 "mattecolor",(char *) NULL);
3598 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3599 "name",(char *) NULL));
3600 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3601 (char *) "black");
3602 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3603 (char *) "blue");
3604 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3605 (char *) "cyan");
3606 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3607 (char *) "green");
3608 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3609 (char *) "gray");
3610 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3611 (char *) "red");
3612 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3613 (char *) "magenta");
3614 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3615 (char *) "yellow");
3616 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3617 (char *) "white");
3618 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3619 (char *) "gray");
3620 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3621 (char *) "gray");
3622 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003623 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003624 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003625 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003626 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3627 "font",(char *) "fixed");
3628 resource_info->text_font=XGetResourceClass(database,client_name,
3629 "textFontList",resource_info->text_font);
3630 resource_info->title=XGetResourceClass(database,client_name,"title",
3631 (char *) NULL);
3632 resource_value=XGetResourceClass(database,client_name,"undoCache",
3633 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003634 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003635 resource_value=XGetResourceClass(database,client_name,"update",
3636 (char *) "False");
3637 resource_info->update=IsMagickTrue(resource_value);
3638 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3639 (char *) "True");
3640 resource_info->use_pixmap=IsMagickTrue(resource_value);
3641 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3642 (char *) "True");
3643 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3644 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3645 (char *) NULL);
3646 resource_info->window_group=XGetResourceClass(database,client_name,
3647 "windowGroup",(char *) NULL);
3648 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3649 (char *) NULL);
3650 resource_info->write_filename=XGetResourceClass(database,client_name,
3651 "writeFilename",(char *) NULL);
3652}
3653
3654/*
3655%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3656% %
3657% %
3658% %
3659% X G e t R e s o u r c e I n s t a n c e %
3660% %
3661% %
3662% %
3663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3664%
3665% XGetResourceInstance() queries the X server for the specified resource name.
3666% If the resource name is not defined in the database, the supplied default
3667% value is returned.
3668%
3669% The format of the XGetResourceInstance method is:
3670%
3671% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3672% const char *keyword,const char *resource_default)
3673%
3674% A description of each parameter follows:
3675%
3676% o database: Specifies a resource database; returned from
3677% XrmGetStringDatabase.
3678%
3679% o client_name: Specifies the application name used to retrieve
3680% resource info from the X server database.
3681%
3682% o keyword: Specifies the keyword of the value being retrieved.
3683%
3684% o resource_default: Specifies the default value to return if the query
3685% fails to find the specified keyword/class.
3686%
3687*/
3688MagickExport char *XGetResourceInstance(XrmDatabase database,
3689 const char *client_name,const char *keyword,const char *resource_default)
3690{
3691 char
3692 *resource_type,
3693 resource_name[MaxTextExtent];
3694
3695 Status
3696 status;
3697
3698 XrmValue
3699 resource_value;
3700
3701 if (database == (XrmDatabase) NULL)
3702 return((char *) resource_default);
3703 *resource_name='\0';
3704 if (keyword != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00003705 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
cristy3ed852e2009-09-05 21:47:34 +00003706 keyword);
3707 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3708 &resource_value);
3709 if (status == False)
3710 return((char *) resource_default);
3711 return(resource_value.addr);
3712}
3713
3714/*
3715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3716% %
3717% %
3718% %
3719% X G e t S c r e e n D e n s i t y %
3720% %
3721% %
3722% %
3723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3724%
3725% XGetScreenDensity() returns the density of the X server screen in
3726% dots-per-inch.
3727%
3728% The format of the XGetScreenDensity method is:
3729%
3730% char *XGetScreenDensity(Display *display)
3731%
3732% A description of each parameter follows:
3733%
3734% o density: XGetScreenDensity() returns the density of the X screen in
3735% dots-per-inch.
3736%
3737% o display: Specifies a connection to an X server; returned from
3738% XOpenDisplay.
3739%
3740*/
3741MagickExport char *XGetScreenDensity(Display *display)
3742{
3743 char
3744 density[MaxTextExtent];
3745
3746 double
3747 x_density,
3748 y_density;
3749
3750 /*
3751 Set density as determined by screen size.
3752 */
3753 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3754 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3755 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3756 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristyb51dff52011-05-19 16:55:47 +00003757 (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003758 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003759 return(GetPageGeometry(density));
3760}
3761
3762/*
3763%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3764% %
3765% %
3766% %
3767+ X G e t S u b w i n d o w %
3768% %
3769% %
3770% %
3771%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3772%
3773% XGetSubwindow() returns the subwindow of a window chosen the user with the
3774% pointer and a button press.
3775%
3776% The format of the XGetSubwindow method is:
3777%
3778% Window XGetSubwindow(Display *display,Window window,int x,int y)
3779%
3780% A description of each parameter follows:
3781%
3782% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3783% otherwise the subwindow is returned.
3784%
3785% o display: Specifies a connection to an X server; returned from
3786% XOpenDisplay.
3787%
3788% o window: Specifies a pointer to a Window.
3789%
3790% o x: the x coordinate of the pointer relative to the origin of the
3791% window.
3792%
3793% o y: the y coordinate of the pointer relative to the origin of the
3794% window.
3795%
cristy3ed852e2009-09-05 21:47:34 +00003796*/
3797static Window XGetSubwindow(Display *display,Window window,int x,int y)
3798{
3799 int
3800 x_offset,
3801 y_offset;
3802
3803 Status
3804 status;
3805
3806 Window
3807 source_window,
3808 target_window;
3809
3810 assert(display != (Display *) NULL);
3811 source_window=XRootWindow(display,XDefaultScreen(display));
3812 if (window == (Window) NULL)
3813 return(source_window);
3814 target_window=window;
3815 for ( ; ; )
3816 {
3817 status=XTranslateCoordinates(display,source_window,window,x,y,
3818 &x_offset,&y_offset,&target_window);
3819 if (status != True)
3820 break;
3821 if (target_window == (Window) NULL)
3822 break;
3823 source_window=window;
3824 window=target_window;
3825 x=x_offset;
3826 y=y_offset;
3827 }
3828 if (target_window == (Window) NULL)
3829 target_window=window;
3830 return(target_window);
3831}
3832
3833/*
3834%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3835% %
3836% %
3837% %
3838% X G e t W i n d o w C o l o r %
3839% %
3840% %
3841% %
3842%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3843%
3844% XGetWindowColor() returns the color of a pixel interactively chosen from the
3845% X server.
3846%
3847% The format of the XGetWindowColor method is:
3848%
3849% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
cristy6710d842011-10-20 23:23:00 +00003850% char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003851%
3852% A description of each parameter follows:
3853%
3854% o display: Specifies a connection to an X server; returned from
3855% XOpenDisplay.
3856%
3857% o windows: Specifies a pointer to a XWindows structure.
3858%
3859% o name: the name of the color if found in the X Color Database is
3860% returned in this character string.
3861%
cristy6710d842011-10-20 23:23:00 +00003862% o exception: return any errors or warnings in this structure.
3863%
cristy3ed852e2009-09-05 21:47:34 +00003864*/
cristybcbda3f2011-09-03 13:01:22 +00003865MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
cristy6710d842011-10-20 23:23:00 +00003866 XWindows *windows,char *name,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003867{
3868 int
3869 x,
3870 y;
3871
cristy101ab702011-10-13 13:06:32 +00003872 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00003873 pixel;
3874
3875 RectangleInfo
3876 crop_info;
3877
3878 Status
3879 status;
3880
3881 Window
3882 child,
3883 client_window,
3884 root_window,
3885 target_window;
3886
3887 XColor
3888 color;
3889
3890 XImage
3891 *ximage;
3892
3893 XWindowAttributes
3894 window_attributes;
3895
3896 /*
3897 Choose a pixel from the X server.
3898 */
3899 assert(display != (Display *) NULL);
3900 assert(name != (char *) NULL);
3901 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3902 *name='\0';
3903 target_window=XSelectWindow(display,&crop_info);
3904 if (target_window == (Window) NULL)
3905 return(MagickFalse);
3906 root_window=XRootWindow(display,XDefaultScreen(display));
3907 client_window=target_window;
3908 if (target_window != root_window)
3909 {
3910 unsigned int
3911 d;
3912
3913 /*
3914 Get client window.
3915 */
3916 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3917 if (status != False)
3918 {
3919 client_window=XClientWindow(display,target_window);
3920 target_window=client_window;
3921 }
3922 }
3923 /*
3924 Verify window is viewable.
3925 */
3926 status=XGetWindowAttributes(display,target_window,&window_attributes);
3927 if ((status == False) || (window_attributes.map_state != IsViewable))
3928 return(MagickFalse);
3929 /*
3930 Get window X image.
3931 */
3932 (void) XTranslateCoordinates(display,root_window,target_window,
3933 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3934 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3935 if (ximage == (XImage *) NULL)
3936 return(MagickFalse);
3937 color.pixel=XGetPixel(ximage,0,0);
3938 XDestroyImage(ximage);
3939 /*
3940 Match color against the color database.
3941 */
3942 (void) XQueryColor(display,window_attributes.colormap,&color);
3943 pixel.red=ScaleShortToQuantum(color.red);
3944 pixel.green=ScaleShortToQuantum(color.green);
3945 pixel.blue=ScaleShortToQuantum(color.blue);
cristy4c08aed2011-07-01 19:47:50 +00003946 pixel.alpha=OpaqueAlpha;
cristy3ed852e2009-09-05 21:47:34 +00003947 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
cristy6710d842011-10-20 23:23:00 +00003948 exception);
cristy3ed852e2009-09-05 21:47:34 +00003949 return(MagickTrue);
3950}
3951
3952/*
3953%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3954% %
3955% %
3956% %
3957+ X G e t W i n d o w I m a g e %
3958% %
3959% %
3960% %
3961%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3962%
3963% XGetWindowImage() reads an image from the target X window and returns it.
3964% XGetWindowImage() optionally descends the window hierarchy and overlays the
3965% target image with each child image in an optimized fashion. Any child
3966% window that have the same visual, colormap, and are contained by its parent
3967% are exempted.
3968%
3969% The format of the XGetWindowImage method is:
3970%
3971% Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003972% const unsigned int borders,const unsigned int level,
3973% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003974%
3975% A description of each parameter follows:
3976%
3977% o display: Specifies a connection to an X server; returned from
3978% XOpenDisplay.
3979%
3980% o window: Specifies the window to obtain the image from.
3981%
3982% o borders: Specifies whether borders pixels are to be saved with
3983% the image.
3984%
3985% o level: Specifies an unsigned integer representing the level of
3986% decent in the window hierarchy. This value must be zero or one on
3987% the initial call to XGetWindowImage. A value of zero returns after
3988% one call. A value of one causes the function to descend the window
3989% hierarchy and overlay the target image with each subwindow image.
3990%
cristy6710d842011-10-20 23:23:00 +00003991% o exception: return any errors or warnings in this structure.
3992%
cristy3ed852e2009-09-05 21:47:34 +00003993*/
3994static Image *XGetWindowImage(Display *display,const Window window,
cristy6710d842011-10-20 23:23:00 +00003995 const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003996{
3997 typedef struct _ColormapInfo
3998 {
3999 Colormap
4000 colormap;
4001
4002 XColor
4003 *colors;
4004
4005 struct _ColormapInfo
4006 *next;
4007 } ColormapInfo;
4008
4009 typedef struct _WindowInfo
4010 {
4011 Window
4012 window,
4013 parent;
4014
4015 Visual
4016 *visual;
4017
4018 Colormap
4019 colormap;
4020
4021 XSegment
4022 bounds;
4023
4024 RectangleInfo
4025 crop_info;
4026 } WindowInfo;
4027
cristy3ed852e2009-09-05 21:47:34 +00004028 int
4029 display_height,
4030 display_width,
4031 id,
4032 x_offset,
4033 y_offset;
4034
cristy4c08aed2011-07-01 19:47:50 +00004035 Quantum
4036 index;
4037
cristy3ed852e2009-09-05 21:47:34 +00004038 RectangleInfo
4039 crop_info;
4040
cristy3ed852e2009-09-05 21:47:34 +00004041 register int
4042 i;
4043
4044 static ColormapInfo
4045 *colormap_info = (ColormapInfo *) NULL;
4046
4047 static int
4048 max_windows = 0,
4049 number_windows = 0;
4050
4051 static WindowInfo
4052 *window_info;
4053
4054 Status
4055 status;
4056
4057 Window
4058 child,
4059 root_window;
4060
4061 XWindowAttributes
4062 window_attributes;
4063
4064 /*
4065 Verify window is viewable.
4066 */
4067 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4068 assert(display != (Display *) NULL);
4069 status=XGetWindowAttributes(display,window,&window_attributes);
4070 if ((status == False) || (window_attributes.map_state != IsViewable))
4071 return((Image *) NULL);
4072 /*
4073 Cropping rectangle is relative to root window.
4074 */
4075 root_window=XRootWindow(display,XDefaultScreen(display));
4076 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4077 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004078 crop_info.x=(ssize_t) x_offset;
4079 crop_info.y=(ssize_t) y_offset;
4080 crop_info.width=(size_t) window_attributes.width;
4081 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004082 if (borders != MagickFalse)
4083 {
4084 /*
4085 Include border in image.
4086 */
cristybb503372010-05-27 20:51:26 +00004087 crop_info.x-=(ssize_t) window_attributes.border_width;
4088 crop_info.y-=(ssize_t) window_attributes.border_width;
4089 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4090 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004091 }
4092 /*
4093 Crop to root window.
4094 */
4095 if (crop_info.x < 0)
4096 {
4097 crop_info.width+=crop_info.x;
4098 crop_info.x=0;
4099 }
4100 if (crop_info.y < 0)
4101 {
4102 crop_info.height+=crop_info.y;
4103 crop_info.y=0;
4104 }
4105 display_width=XDisplayWidth(display,XDefaultScreen(display));
4106 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004107 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004108 display_height=XDisplayHeight(display,XDefaultScreen(display));
4109 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004110 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004111 /*
4112 Initialize window info attributes.
4113 */
4114 if (number_windows >= max_windows)
4115 {
4116 /*
4117 Allocate or resize window info buffer.
4118 */
4119 max_windows+=1024;
4120 if (window_info == (WindowInfo *) NULL)
4121 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4122 sizeof(*window_info));
4123 else
4124 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4125 max_windows,sizeof(*window_info));
4126 }
4127 if (window_info == (WindowInfo *) NULL)
4128 {
4129 ThrowXWindowFatalException(ResourceLimitError,
4130 "MemoryAllocationFailed","...");
4131 return((Image *) NULL);
4132 }
4133 id=number_windows++;
4134 window_info[id].window=window;
4135 window_info[id].visual=window_attributes.visual;
4136 window_info[id].colormap=window_attributes.colormap;
4137 window_info[id].bounds.x1=(short) crop_info.x;
4138 window_info[id].bounds.y1=(short) crop_info.y;
4139 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4140 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4141 crop_info.x-=x_offset;
4142 crop_info.y-=y_offset;
4143 window_info[id].crop_info=crop_info;
4144 if (level != 0)
4145 {
4146 unsigned int
4147 number_children;
4148
4149 Window
4150 *children;
4151
4152 /*
4153 Descend the window hierarchy.
4154 */
4155 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4156 &children,&number_children);
4157 for (i=0; i < id; i++)
4158 if ((window_info[i].window == window_info[id].parent) &&
4159 (window_info[i].visual == window_info[id].visual) &&
4160 (window_info[i].colormap == window_info[id].colormap))
4161 {
4162 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4163 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4164 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4165 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4166 {
4167 /*
4168 Eliminate windows not circumscribed by their parent.
4169 */
4170 number_windows--;
4171 break;
4172 }
4173 }
4174 if ((status == True) && (number_children != 0))
4175 {
4176 for (i=0; i < (int) number_children; i++)
cristy6710d842011-10-20 23:23:00 +00004177 (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
4178 exception);
cristy3ed852e2009-09-05 21:47:34 +00004179 (void) XFree((void *) children);
4180 }
4181 }
4182 if (level <= 1)
4183 {
cristyc57f6942010-11-12 01:47:39 +00004184 CacheView
4185 *composite_view;
4186
cristy3ed852e2009-09-05 21:47:34 +00004187 ColormapInfo
4188 *next;
4189
cristy3ed852e2009-09-05 21:47:34 +00004190 Image
4191 *composite_image,
4192 *image;
4193
4194 int
4195 y;
4196
4197 MagickBooleanType
4198 import;
4199
4200 register int
4201 j,
4202 x;
4203
cristy4c08aed2011-07-01 19:47:50 +00004204 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00004205 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004206
cristybb503372010-05-27 20:51:26 +00004207 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004208 pixel;
4209
4210 unsigned int
4211 number_colors;
4212
4213 XColor
4214 *colors;
4215
4216 XImage
4217 *ximage;
4218
4219 /*
4220 Get X image for each window in the list.
4221 */
4222 image=NewImageList();
4223 for (id=0; id < number_windows; id++)
4224 {
4225 /*
4226 Does target window intersect top level window?
4227 */
4228 import=
4229 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4230 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4231 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4232 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4233 MagickTrue : MagickFalse;
4234 /*
4235 Is target window contained by another window with the same colormap?
4236 */
4237 for (j=0; j < id; j++)
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.x1 <= window_info[j].bounds.x1) ||
4242 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4243 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4244 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4245 import=MagickFalse;
4246 }
4247 else
4248 if ((window_info[id].visual != window_info[j].visual) ||
4249 (window_info[id].colormap != window_info[j].colormap))
4250 {
4251 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4252 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4253 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4254 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4255 import=MagickTrue;
4256 }
4257 if (import == MagickFalse)
4258 continue;
4259 /*
4260 Get X image.
4261 */
4262 ximage=XGetImage(display,window_info[id].window,(int)
4263 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4264 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4265 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4266 if (ximage == (XImage *) NULL)
4267 continue;
4268 /*
4269 Initialize window colormap.
4270 */
4271 number_colors=0;
4272 colors=(XColor *) NULL;
4273 if (window_info[id].colormap != (Colormap) NULL)
4274 {
4275 ColormapInfo
4276 *p;
4277
4278 /*
4279 Search colormap list for window colormap.
4280 */
4281 number_colors=(unsigned int) window_info[id].visual->map_entries;
4282 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4283 if (p->colormap == window_info[id].colormap)
4284 break;
4285 if (p == (ColormapInfo *) NULL)
4286 {
4287 /*
4288 Get the window colormap.
4289 */
4290 colors=(XColor *) AcquireQuantumMemory(number_colors,
4291 sizeof(*colors));
4292 if (colors == (XColor *) NULL)
4293 {
4294 XDestroyImage(ximage);
4295 return((Image *) NULL);
4296 }
4297 if ((window_info[id].visual->klass != DirectColor) &&
4298 (window_info[id].visual->klass != TrueColor))
4299 for (i=0; i < (int) number_colors; i++)
4300 {
cristybb503372010-05-27 20:51:26 +00004301 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004302 colors[i].pad='\0';
4303 }
4304 else
4305 {
cristybb503372010-05-27 20:51:26 +00004306 size_t
cristy3ed852e2009-09-05 21:47:34 +00004307 blue,
4308 blue_bit,
4309 green,
4310 green_bit,
4311 red,
4312 red_bit;
4313
4314 /*
4315 DirectColor or TrueColor visual.
4316 */
4317 red=0;
4318 green=0;
4319 blue=0;
4320 red_bit=window_info[id].visual->red_mask &
4321 (~(window_info[id].visual->red_mask)+1);
4322 green_bit=window_info[id].visual->green_mask &
4323 (~(window_info[id].visual->green_mask)+1);
4324 blue_bit=window_info[id].visual->blue_mask &
4325 (~(window_info[id].visual->blue_mask)+1);
4326 for (i=0; i < (int) number_colors; i++)
4327 {
cristy8891f9c2010-06-04 23:32:17 +00004328 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004329 colors[i].pad='\0';
4330 red+=red_bit;
4331 if (red > window_info[id].visual->red_mask)
4332 red=0;
4333 green+=green_bit;
4334 if (green > window_info[id].visual->green_mask)
4335 green=0;
4336 blue+=blue_bit;
4337 if (blue > window_info[id].visual->blue_mask)
4338 blue=0;
4339 }
4340 }
4341 (void) XQueryColors(display,window_info[id].colormap,colors,
4342 (int) number_colors);
4343 /*
4344 Append colormap to colormap list.
4345 */
cristy73bd4a52010-10-05 11:24:23 +00004346 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004347 if (p == (ColormapInfo *) NULL)
4348 return((Image *) NULL);
4349 p->colormap=window_info[id].colormap;
4350 p->colors=colors;
4351 p->next=colormap_info;
4352 colormap_info=p;
4353 }
4354 colors=p->colors;
4355 }
4356 /*
4357 Allocate image structure.
4358 */
cristy6710d842011-10-20 23:23:00 +00004359 composite_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00004360 if (composite_image == (Image *) NULL)
4361 {
4362 XDestroyImage(ximage);
4363 return((Image *) NULL);
4364 }
4365 /*
4366 Convert X image to MIFF format.
4367 */
4368 if ((window_info[id].visual->klass != TrueColor) &&
4369 (window_info[id].visual->klass != DirectColor))
4370 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004371 composite_image->columns=(size_t) ximage->width;
4372 composite_image->rows=(size_t) ximage->height;
cristyc57f6942010-11-12 01:47:39 +00004373 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004374 switch (composite_image->storage_class)
4375 {
4376 case DirectClass:
4377 default:
4378 {
cristybb503372010-05-27 20:51:26 +00004379 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004380 color,
4381 index;
4382
cristybb503372010-05-27 20:51:26 +00004383 size_t
cristy3ed852e2009-09-05 21:47:34 +00004384 blue_mask,
4385 blue_shift,
4386 green_mask,
4387 green_shift,
4388 red_mask,
4389 red_shift;
4390
4391 /*
4392 Determine shift and mask for red, green, and blue.
4393 */
4394 red_mask=window_info[id].visual->red_mask;
4395 red_shift=0;
4396 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4397 {
4398 red_mask>>=1;
4399 red_shift++;
4400 }
4401 green_mask=window_info[id].visual->green_mask;
4402 green_shift=0;
4403 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4404 {
4405 green_mask>>=1;
4406 green_shift++;
4407 }
4408 blue_mask=window_info[id].visual->blue_mask;
4409 blue_shift=0;
4410 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4411 {
4412 blue_mask>>=1;
4413 blue_shift++;
4414 }
4415 /*
4416 Convert X image to DirectClass packets.
4417 */
4418 if ((number_colors != 0) &&
4419 (window_info[id].visual->klass == DirectColor))
4420 for (y=0; y < (int) composite_image->rows; y++)
4421 {
cristyc57f6942010-11-12 01:47:39 +00004422 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004423 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004424 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004425 break;
4426 for (x=0; x < (int) composite_image->columns; x++)
4427 {
4428 pixel=XGetPixel(ximage,x,y);
4429 index=(pixel >> red_shift) & red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004430 SetPixelRed(composite_image,
4431 ScaleShortToQuantum(colors[index].red),q);
cristy3ed852e2009-09-05 21:47:34 +00004432 index=(pixel >> green_shift) & green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004433 SetPixelGreen(composite_image,
4434 ScaleShortToQuantum(colors[index].green),q);
cristy3ed852e2009-09-05 21:47:34 +00004435 index=(pixel >> blue_shift) & blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004436 SetPixelBlue(composite_image,
4437 ScaleShortToQuantum(colors[index].blue),q);
cristyed231572011-07-14 02:18:59 +00004438 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004439 }
cristy0b1a7972011-10-22 22:17:02 +00004440 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4441 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004442 break;
4443 }
4444 else
4445 for (y=0; y < (int) composite_image->rows; y++)
4446 {
cristyc57f6942010-11-12 01:47:39 +00004447 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004448 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004449 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004450 break;
4451 for (x=0; x < (int) composite_image->columns; x++)
4452 {
4453 pixel=XGetPixel(ximage,x,y);
4454 color=(pixel >> red_shift) & red_mask;
4455 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004456 SetPixelRed(composite_image,
4457 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004458 color=(pixel >> green_shift) & green_mask;
4459 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004460 SetPixelGreen(composite_image,
4461 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004462 color=(pixel >> blue_shift) & blue_mask;
4463 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004464 SetPixelBlue(composite_image,
4465 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004466 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004467 }
cristy0b1a7972011-10-22 22:17:02 +00004468 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4469 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004470 break;
4471 }
4472 break;
4473 }
4474 case PseudoClass:
4475 {
4476 /*
4477 Create colormap.
4478 */
cristy0b1a7972011-10-22 22:17:02 +00004479 status=AcquireImageColormap(composite_image,number_colors,
4480 exception);
4481 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004482 {
4483 XDestroyImage(ximage);
4484 composite_image=DestroyImage(composite_image);
4485 return((Image *) NULL);
4486 }
4487 for (i=0; i < (int) composite_image->colors; i++)
4488 {
4489 composite_image->colormap[colors[i].pixel].red=
4490 ScaleShortToQuantum(colors[i].red);
4491 composite_image->colormap[colors[i].pixel].green=
4492 ScaleShortToQuantum(colors[i].green);
4493 composite_image->colormap[colors[i].pixel].blue=
4494 ScaleShortToQuantum(colors[i].blue);
4495 }
4496 /*
4497 Convert X image to PseudoClass packets.
4498 */
4499 for (y=0; y < (int) composite_image->rows; y++)
4500 {
cristyc57f6942010-11-12 01:47:39 +00004501 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4502 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004503 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004504 break;
cristy3ed852e2009-09-05 21:47:34 +00004505 for (x=0; x < (int) composite_image->columns; x++)
4506 {
cristy4c08aed2011-07-01 19:47:50 +00004507 index=(Quantum) XGetPixel(ximage,x,y);
4508 SetPixelIndex(composite_image,index,q);
cristy803640d2011-11-17 02:11:32 +00004509 SetPixelInfoPixel(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004510 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004511 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004512 }
cristy0b1a7972011-10-22 22:17:02 +00004513 status=SyncCacheViewAuthenticPixels(composite_view,exception);
4514 if (status == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004515 break;
4516 }
4517 break;
4518 }
4519 }
cristyc57f6942010-11-12 01:47:39 +00004520 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004521 XDestroyImage(ximage);
4522 if (image == (Image *) NULL)
4523 {
4524 image=composite_image;
4525 continue;
4526 }
4527 /*
4528 Composite any children in back-to-front order.
4529 */
4530 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4531 &x_offset,&y_offset,&child);
4532 x_offset-=(int) crop_info.x;
4533 if (x_offset < 0)
4534 x_offset=0;
4535 y_offset-=(int) crop_info.y;
4536 if (y_offset < 0)
4537 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004538 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
cristye941a752011-10-15 01:52:48 +00004539 x_offset,(ssize_t) y_offset,exception);
cristy3ed852e2009-09-05 21:47:34 +00004540 }
4541 /*
4542 Relinquish resources.
4543 */
4544 while (colormap_info != (ColormapInfo *) NULL)
4545 {
4546 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004547 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4548 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004549 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4550 colormap_info=next;
4551 }
4552 /*
4553 Relinquish resources and restore initial state.
4554 */
4555 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4556 max_windows=0;
4557 number_windows=0;
4558 colormap_info=(ColormapInfo *) NULL;
4559 return(image);
4560 }
4561 return((Image *) NULL);
4562}
4563
4564/*
4565%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4566% %
4567% %
4568% %
4569% X G e t W i n d o w I n f o %
4570% %
4571% %
4572% %
4573%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4574%
4575% XGetWindowInfo() initializes the XWindowInfo structure.
4576%
4577% The format of the XGetWindowInfo method is:
4578%
4579% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4580% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4581% XResourceInfo *resource_info,XWindowInfo *window)
4582% resource_info,window)
4583%
4584% A description of each parameter follows:
4585%
4586% o display: Specifies a connection to an X server; returned from
4587% XOpenDisplay.
4588%
4589% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4590% returned from XGetVisualInfo.
4591%
4592% o map_info: If map_type is specified, this structure is initialized
4593% with info from the Standard Colormap.
4594%
4595% o pixel: Specifies a pointer to a XPixelInfo structure.
4596%
4597% o font_info: Specifies a pointer to a XFontStruct structure.
4598%
4599% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4600%
4601*/
cristybcbda3f2011-09-03 13:01:22 +00004602MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004603 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4604 XResourceInfo *resource_info,XWindowInfo *window)
4605{
4606 /*
4607 Initialize window info.
4608 */
4609 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4610 assert(display != (Display *) NULL);
4611 assert(visual_info != (XVisualInfo *) NULL);
4612 assert(map_info != (XStandardColormap *) NULL);
4613 assert(pixel != (XPixelInfo *) NULL);
4614 assert(resource_info != (XResourceInfo *) NULL);
4615 assert(window != (XWindowInfo *) NULL);
4616 if (window->id != (Window) NULL)
4617 {
4618 if (window->cursor != (Cursor) NULL)
4619 (void) XFreeCursor(display,window->cursor);
4620 if (window->busy_cursor != (Cursor) NULL)
4621 (void) XFreeCursor(display,window->busy_cursor);
4622 if (window->highlight_stipple != (Pixmap) NULL)
4623 (void) XFreePixmap(display,window->highlight_stipple);
4624 if (window->shadow_stipple != (Pixmap) NULL)
4625 (void) XFreePixmap(display,window->shadow_stipple);
4626 if (window->name == (char *) NULL)
4627 window->name=AcquireString("");
4628 if (window->icon_name == (char *) NULL)
4629 window->icon_name=AcquireString("");
4630 }
4631 else
4632 {
4633 /*
4634 Initialize these attributes just once.
4635 */
4636 window->id=(Window) NULL;
4637 if (window->name == (char *) NULL)
4638 window->name=AcquireString("");
4639 if (window->icon_name == (char *) NULL)
4640 window->icon_name=AcquireString("");
4641 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4642 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4643 window->ximage=(XImage *) NULL;
4644 window->matte_image=(XImage *) NULL;
4645 window->pixmap=(Pixmap) NULL;
4646 window->matte_pixmap=(Pixmap) NULL;
4647 window->mapped=MagickFalse;
4648 window->stasis=MagickFalse;
4649 window->shared_memory=MagickTrue;
4650 window->segment_info=(void *) NULL;
4651#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4652 {
4653 XShmSegmentInfo
4654 *segment_info;
4655
4656 if (window->segment_info == (void *) NULL)
4657 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4658 segment_info=(XShmSegmentInfo *) window->segment_info;
4659 segment_info[0].shmid=(-1);
4660 segment_info[0].shmaddr=(char *) NULL;
4661 segment_info[1].shmid=(-1);
4662 segment_info[1].shmaddr=(char *) NULL;
4663 }
4664#endif
4665 }
4666 /*
4667 Initialize these attributes every time function is called.
4668 */
4669 window->screen=visual_info->screen;
4670 window->root=XRootWindow(display,visual_info->screen);
4671 window->visual=visual_info->visual;
4672 window->storage_class=(unsigned int) visual_info->klass;
4673 window->depth=(unsigned int) visual_info->depth;
4674 window->visual_info=visual_info;
4675 window->map_info=map_info;
4676 window->pixel_info=pixel;
4677 window->font_info=font_info;
4678 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4679 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4680 window->geometry=(char *) NULL;
4681 window->icon_geometry=(char *) NULL;
4682 if (resource_info->icon_geometry != (char *) NULL)
4683 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4684 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004685 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004686 window->width=1;
4687 window->height=1;
4688 window->min_width=1;
4689 window->min_height=1;
4690 window->width_inc=1;
4691 window->height_inc=1;
4692 window->border_width=resource_info->border_width;
4693 window->annotate_context=pixel->annotate_context;
4694 window->highlight_context=pixel->highlight_context;
4695 window->widget_context=pixel->widget_context;
4696 window->shadow_stipple=(Pixmap) NULL;
4697 window->highlight_stipple=(Pixmap) NULL;
4698 window->use_pixmap=MagickTrue;
4699 window->immutable=MagickFalse;
4700 window->shape=MagickFalse;
4701 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004702 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004703 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4704 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4705 window->attributes.background_pixel=pixel->background_color.pixel;
4706 window->attributes.background_pixmap=(Pixmap) NULL;
4707 window->attributes.bit_gravity=ForgetGravity;
4708 window->attributes.backing_store=WhenMapped;
4709 window->attributes.save_under=MagickTrue;
4710 window->attributes.border_pixel=pixel->border_color.pixel;
4711 window->attributes.colormap=map_info->colormap;
4712 window->attributes.cursor=window->cursor;
4713 window->attributes.do_not_propagate_mask=NoEventMask;
4714 window->attributes.event_mask=NoEventMask;
4715 window->attributes.override_redirect=MagickFalse;
4716 window->attributes.win_gravity=NorthWestGravity;
4717 window->orphan=MagickFalse;
4718}
4719
4720/*
4721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4722% %
4723% %
4724% %
4725% X H i g h l i g h t E l l i p s e %
4726% %
4727% %
4728% %
4729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4730%
4731% XHighlightEllipse() puts a border on the X server around a region defined by
4732% highlight_info.
4733%
4734% The format of the XHighlightEllipse method is:
4735%
4736% void XHighlightEllipse(Display *display,Window window,
4737% GC annotate_context,const RectangleInfo *highlight_info)
4738%
4739% A description of each parameter follows:
4740%
4741% o display: Specifies a connection to an X server; returned from
4742% XOpenDisplay.
4743%
4744% o window: Specifies a pointer to a Window structure.
4745%
4746% o annotate_context: Specifies a pointer to a GC structure.
4747%
4748% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4749% contains the extents of any highlighting rectangle.
4750%
4751*/
cristybcbda3f2011-09-03 13:01:22 +00004752MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004753 GC annotate_context,const RectangleInfo *highlight_info)
4754{
4755 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4756 assert(display != (Display *) NULL);
4757 assert(window != (Window) NULL);
4758 assert(annotate_context != (GC) NULL);
4759 assert(highlight_info != (RectangleInfo *) NULL);
4760 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4761 return;
4762 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4763 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4764 (unsigned int) highlight_info->height-1,0,360*64);
4765 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4766 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4767 (unsigned int) highlight_info->height-3,0,360*64);
4768}
4769
4770/*
4771%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4772% %
4773% %
4774% %
4775% X H i g h l i g h t L i n e %
4776% %
4777% %
4778% %
4779%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4780%
4781% XHighlightLine() puts a border on the X server around a region defined by
4782% highlight_info.
4783%
4784% The format of the XHighlightLine method is:
4785%
4786% void XHighlightLine(Display *display,Window window,GC annotate_context,
4787% const XSegment *highlight_info)
4788%
4789% A description of each parameter follows:
4790%
4791% o display: Specifies a connection to an X server; returned from
4792% XOpenDisplay.
4793%
4794% o window: Specifies a pointer to a Window structure.
4795%
4796% o annotate_context: Specifies a pointer to a GC structure.
4797%
4798% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4799% contains the extents of any highlighting rectangle.
4800%
4801*/
cristybcbda3f2011-09-03 13:01:22 +00004802MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004803 GC annotate_context,const XSegment *highlight_info)
4804{
4805 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4806 assert(display != (Display *) NULL);
4807 assert(window != (Window) NULL);
4808 assert(annotate_context != (GC) NULL);
4809 assert(highlight_info != (XSegment *) NULL);
4810 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4811 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4812}
4813
4814/*
4815%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4816% %
4817% %
4818% %
4819% X H i g h l i g h t R e c t a n g l e %
4820% %
4821% %
4822% %
4823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4824%
4825% XHighlightRectangle() puts a border on the X server around a region defined
4826% by highlight_info.
4827%
4828% The format of the XHighlightRectangle method is:
4829%
4830% void XHighlightRectangle(Display *display,Window window,
4831% GC annotate_context,const RectangleInfo *highlight_info)
4832%
4833% A description of each parameter follows:
4834%
4835% o display: Specifies a connection to an X server; returned from
4836% XOpenDisplay.
4837%
4838% o window: Specifies a pointer to a Window structure.
4839%
4840% o annotate_context: Specifies a pointer to a GC structure.
4841%
4842% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4843% contains the extents of any highlighting rectangle.
4844%
4845*/
cristybcbda3f2011-09-03 13:01:22 +00004846MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004847 GC annotate_context,const RectangleInfo *highlight_info)
4848{
4849 assert(display != (Display *) NULL);
4850 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4851 assert(window != (Window) NULL);
4852 assert(annotate_context != (GC) NULL);
4853 assert(highlight_info != (RectangleInfo *) NULL);
4854 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4855 return;
4856 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4857 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4858 (unsigned int) highlight_info->height-1);
4859 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4860 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4861 (unsigned int) highlight_info->height-3);
4862}
4863
4864/*
4865%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4866% %
4867% %
4868% %
4869% X I m p o r t I m a g e %
4870% %
4871% %
4872% %
4873%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4874%
4875% XImportImage() reads an image from an X window.
4876%
4877% The format of the XImportImage method is:
4878%
cristy6710d842011-10-20 23:23:00 +00004879% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4880% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004881%
4882% A description of each parameter follows:
4883%
4884% o image_info: the image info.
4885%
4886% o ximage_info: Specifies a pointer to an XImportInfo structure.
4887%
cristy6710d842011-10-20 23:23:00 +00004888% o exception: return any errors or warnings in this structure.
4889%
cristy3ed852e2009-09-05 21:47:34 +00004890*/
4891MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004892 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004893{
4894 Colormap
4895 *colormaps;
4896
4897 Display
4898 *display;
4899
4900 Image
4901 *image;
4902
4903 int
4904 number_colormaps,
4905 number_windows,
4906 x;
4907
4908 RectangleInfo
4909 crop_info;
4910
4911 Status
4912 status;
4913
4914 Window
4915 *children,
4916 client,
4917 prior_target,
4918 root,
4919 target;
4920
4921 XTextProperty
4922 window_name;
4923
4924 /*
4925 Open X server connection.
4926 */
4927 assert(image_info != (const ImageInfo *) NULL);
4928 assert(image_info->signature == MagickSignature);
4929 if (image_info->debug != MagickFalse)
4930 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4931 image_info->filename);
4932 assert(ximage_info != (XImportInfo *) NULL);
4933 display=XOpenDisplay(image_info->server_name);
4934 if (display == (Display *) NULL)
4935 {
4936 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4937 XDisplayName(image_info->server_name));
4938 return((Image *) NULL);
4939 }
4940 /*
4941 Set our forgiving exception handler.
4942 */
4943 (void) XSetErrorHandler(XError);
4944 /*
4945 Select target window.
4946 */
4947 crop_info.x=0;
4948 crop_info.y=0;
4949 crop_info.width=0;
4950 crop_info.height=0;
4951 root=XRootWindow(display,XDefaultScreen(display));
4952 target=(Window) NULL;
4953 if ((image_info->filename != (char *) NULL) &&
4954 (*image_info->filename != '\0'))
4955 {
4956 if (LocaleCompare(image_info->filename,"root") == 0)
4957 target=root;
4958 else
4959 {
4960 /*
4961 Select window by ID or name.
4962 */
4963 if (isdigit((unsigned char) *image_info->filename) != 0)
4964 target=XWindowByID(display,root,(Window)
4965 strtol(image_info->filename,(char **) NULL,0));
4966 if (target == (Window) NULL)
4967 target=XWindowByName(display,root,image_info->filename);
4968 if (target == (Window) NULL)
4969 ThrowXWindowFatalException(XServerError,
4970 "NoWindowWithSpecifiedIDExists",image_info->filename);
4971 }
4972 }
4973 /*
4974 If target window is not defined, interactively select one.
4975 */
4976 prior_target=target;
4977 if (target == (Window) NULL)
4978 target=XSelectWindow(display,&crop_info);
4979 if (target == (Window) NULL)
4980 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4981 image_info->filename);
4982 client=target; /* obsolete */
4983 if (target != root)
4984 {
4985 unsigned int
4986 d;
4987
4988 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4989 if (status != False)
4990 {
4991 for ( ; ; )
4992 {
4993 Window
4994 parent;
4995
4996 /*
4997 Find window manager frame.
4998 */
4999 status=XQueryTree(display,target,&root,&parent,&children,&d);
5000 if ((status != False) && (children != (Window *) NULL))
5001 (void) XFree((char *) children);
5002 if ((status == False) || (parent == (Window) NULL) ||
5003 (parent == root))
5004 break;
5005 target=parent;
5006 }
5007 /*
5008 Get client window.
5009 */
5010 client=XClientWindow(display,target);
5011 if (ximage_info->frame == MagickFalse)
5012 target=client;
5013 if ((ximage_info->frame == MagickFalse) &&
5014 (prior_target != MagickFalse))
5015 target=prior_target;
5016 XDelay(display,SuspendTime << 4);
5017 }
5018 }
5019 if (ximage_info->screen)
5020 {
5021 int
5022 y;
5023
5024 Window
5025 child;
5026
5027 XWindowAttributes
5028 window_attributes;
5029
5030 /*
5031 Obtain window image directly from screen.
5032 */
5033 status=XGetWindowAttributes(display,target,&window_attributes);
5034 if (status == False)
5035 {
5036 ThrowXWindowFatalException(XServerError,
5037 "UnableToReadXWindowAttributes",image_info->filename);
5038 (void) XCloseDisplay(display);
5039 return((Image *) NULL);
5040 }
5041 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005042 crop_info.x=(ssize_t) x;
5043 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005044 crop_info.width=(size_t) window_attributes.width;
5045 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005046 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005047 {
5048 /*
5049 Include border in image.
5050 */
5051 crop_info.x-=window_attributes.border_width;
5052 crop_info.y-=window_attributes.border_width;
5053 crop_info.width+=window_attributes.border_width << 1;
5054 crop_info.height+=window_attributes.border_width << 1;
5055 }
5056 target=root;
5057 }
5058 /*
5059 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5060 */
5061 number_windows=0;
5062 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5063 if ((status == True) && (number_windows > 0))
5064 {
5065 ximage_info->descend=MagickTrue;
5066 (void) XFree ((char *) children);
5067 }
5068 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5069 if (number_colormaps > 0)
5070 {
5071 if (number_colormaps > 1)
5072 ximage_info->descend=MagickTrue;
5073 (void) XFree((char *) colormaps);
5074 }
5075 /*
5076 Alert the user not to alter the screen.
5077 */
5078 if (ximage_info->silent == MagickFalse)
5079 (void) XBell(display,0);
5080 /*
5081 Get image by window id.
5082 */
5083 (void) XGrabServer(display);
5084 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005085 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005086 (void) XUngrabServer(display);
5087 if (image == (Image *) NULL)
5088 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5089 image_info->filename)
5090 else
5091 {
5092 (void) CopyMagickString(image->filename,image_info->filename,
5093 MaxTextExtent);
5094 if ((crop_info.width != 0) && (crop_info.height != 0))
5095 {
5096 Image
5097 *clone_image,
5098 *crop_image;
5099
5100 /*
5101 Crop image as defined by the cropping rectangle.
5102 */
cristy6710d842011-10-20 23:23:00 +00005103 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005104 if (clone_image != (Image *) NULL)
5105 {
cristy6710d842011-10-20 23:23:00 +00005106 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005107 if (crop_image != (Image *) NULL)
5108 {
5109 image=DestroyImage(image);
5110 image=crop_image;
5111 }
5112 }
5113 }
5114 status=XGetWMName(display,target,&window_name);
5115 if (status == True)
5116 {
5117 if ((image_info->filename != (char *) NULL) &&
5118 (*image_info->filename == '\0'))
5119 (void) CopyMagickString(image->filename,(char *) window_name.value,
5120 (size_t) window_name.nitems+1);
5121 (void) XFree((void *) window_name.value);
5122 }
5123 }
5124 if (ximage_info->silent == MagickFalse)
5125 {
5126 /*
5127 Alert the user we're done.
5128 */
5129 (void) XBell(display,0);
5130 (void) XBell(display,0);
5131 }
5132 (void) XCloseDisplay(display);
5133 return(image);
5134}
5135
5136/*
5137%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5138% %
5139% %
5140% %
5141% X I n i t i a l i z e W i n d o w s %
5142% %
5143% %
5144% %
5145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5146%
5147% XInitializeWindows() initializes the XWindows structure.
5148%
5149% The format of the XInitializeWindows method is:
5150%
5151% XWindows *XInitializeWindows(Display *display,
5152% XResourceInfo *resource_info)
5153%
5154% A description of each parameter follows:
5155%
5156% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5157%
5158% o display: Specifies a connection to an X server; returned from
5159% XOpenDisplay.
5160%
5161% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5162%
5163*/
cristybcbda3f2011-09-03 13:01:22 +00005164MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005165 XResourceInfo *resource_info)
5166{
5167 Window
5168 root_window;
5169
5170 XWindows
5171 *windows;
5172
5173 /*
5174 Allocate windows structure.
5175 */
cristy73bd4a52010-10-05 11:24:23 +00005176 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005177 if (windows == (XWindows *) NULL)
5178 {
5179 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5180 "...");
5181 return((XWindows *) NULL);
5182 }
5183 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5184 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5185 sizeof(*windows->pixel_info));
5186 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5187 sizeof(*windows->icon_pixel));
5188 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5189 sizeof(*windows->icon_resources));
5190 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5191 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5192 (windows->icon_resources == (XResourceInfo *) NULL))
5193 {
5194 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5195 "...");
5196 return((XWindows *) NULL);
5197 }
5198 /*
5199 Initialize windows structure.
5200 */
5201 windows->display=display;
5202 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5203 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5204 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5205 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5206 windows->im_remote_command=
5207 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5208 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5209 windows->im_update_colormap=
5210 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5211 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5212 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5213 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5214 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5215 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005216#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005217 (void) XSynchronize(display,IsWindows95());
5218#endif
5219 if (IsEventLogging())
5220 {
5221 (void) XSynchronize(display,MagickTrue);
5222 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005223 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005224 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5225 (void) LogMagickEvent(X11Event,GetMagickModule(),
5226 " Window Manager: 0x%lx",windows->wm_protocols);
5227 (void) LogMagickEvent(X11Event,GetMagickModule(),
5228 " delete window: 0x%lx",windows->wm_delete_window);
5229 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5230 windows->wm_take_focus);
5231 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5232 windows->im_protocols);
5233 (void) LogMagickEvent(X11Event,GetMagickModule(),
5234 " remote command: 0x%lx",windows->im_remote_command);
5235 (void) LogMagickEvent(X11Event,GetMagickModule(),
5236 " update widget: 0x%lx",windows->im_update_widget);
5237 (void) LogMagickEvent(X11Event,GetMagickModule(),
5238 " update colormap: 0x%lx",windows->im_update_colormap);
5239 (void) LogMagickEvent(X11Event,GetMagickModule(),
5240 " former image: 0x%lx",windows->im_former_image);
5241 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5242 windows->im_next_image);
5243 (void) LogMagickEvent(X11Event,GetMagickModule(),
5244 " retain colors: 0x%lx",windows->im_retain_colors);
5245 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5246 windows->im_exit);
5247 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5248 windows->dnd_protocols);
5249 }
5250 /*
5251 Allocate standard colormap.
5252 */
5253 windows->map_info=XAllocStandardColormap();
5254 windows->icon_map=XAllocStandardColormap();
5255 if ((windows->map_info == (XStandardColormap *) NULL) ||
5256 (windows->icon_map == (XStandardColormap *) NULL))
5257 ThrowXWindowFatalException(ResourceLimitFatalError,
5258 "MemoryAllocationFailed","...");
5259 windows->map_info->colormap=(Colormap) NULL;
5260 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005261 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005262 windows->pixel_info->annotate_context=(GC) NULL;
5263 windows->pixel_info->highlight_context=(GC) NULL;
5264 windows->pixel_info->widget_context=(GC) NULL;
5265 windows->font_info=(XFontStruct *) NULL;
5266 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005267 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005268 /*
5269 Allocate visual.
5270 */
5271 *windows->icon_resources=(*resource_info);
5272 windows->icon_resources->visual_type=(char *) "default";
5273 windows->icon_resources->colormap=SharedColormap;
5274 windows->visual_info=
5275 XBestVisualInfo(display,windows->map_info,resource_info);
5276 windows->icon_visual=
5277 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5278 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5279 (windows->icon_visual == (XVisualInfo *) NULL))
5280 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5281 resource_info->visual_type);
5282 if (IsEventLogging())
5283 {
5284 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5285 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5286 windows->visual_info->visualid);
5287 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5288 XVisualClassName(windows->visual_info->klass));
5289 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5290 windows->visual_info->depth);
5291 (void) LogMagickEvent(X11Event,GetMagickModule(),
5292 " size of colormap: %d entries",windows->visual_info->colormap_size);
5293 (void) LogMagickEvent(X11Event,GetMagickModule(),
5294 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5295 windows->visual_info->red_mask,windows->visual_info->green_mask,
5296 windows->visual_info->blue_mask);
5297 (void) LogMagickEvent(X11Event,GetMagickModule(),
5298 " significant bits in color: %d bits",
5299 windows->visual_info->bits_per_rgb);
5300 }
5301 /*
5302 Allocate class and manager hints.
5303 */
5304 windows->class_hints=XAllocClassHint();
5305 windows->manager_hints=XAllocWMHints();
5306 if ((windows->class_hints == (XClassHint *) NULL) ||
5307 (windows->manager_hints == (XWMHints *) NULL))
5308 ThrowXWindowFatalException(ResourceLimitFatalError,
5309 "MemoryAllocationFailed","...");
5310 /*
5311 Determine group leader if we have one.
5312 */
5313 root_window=XRootWindow(display,windows->visual_info->screen);
5314 windows->group_leader.id=(Window) NULL;
5315 if (resource_info->window_group != (char *) NULL)
5316 {
5317 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5318 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5319 strtol((char *) resource_info->window_group,(char **) NULL,0));
5320 if (windows->group_leader.id == (Window) NULL)
5321 windows->group_leader.id=
5322 XWindowByName(display,root_window,resource_info->window_group);
5323 }
5324 return(windows);
5325}
5326
5327/*
5328%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5329% %
5330% %
5331% %
5332% X M a k e C u r s o r %
5333% %
5334% %
5335% %
5336%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5337%
5338% XMakeCursor() creates a crosshairs X11 cursor.
5339%
5340% The format of the XMakeCursor method is:
5341%
5342% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5343% char *background_color,char *foreground_color)
5344%
5345% A description of each parameter follows:
5346%
5347% o display: Specifies a connection to an X server; returned from
5348% XOpenDisplay.
5349%
5350% o window: Specifies the ID of the window for which the cursor is
5351% assigned.
5352%
5353% o colormap: Specifies the ID of the colormap from which the background
5354% and foreground color will be retrieved.
5355%
5356% o background_color: Specifies the color to use for the cursor background.
5357%
5358% o foreground_color: Specifies the color to use for the cursor foreground.
5359%
5360*/
cristybcbda3f2011-09-03 13:01:22 +00005361MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005362 Colormap colormap,char *background_color,char *foreground_color)
5363{
5364#define scope_height 17
5365#define scope_x_hot 8
5366#define scope_y_hot 8
5367#define scope_width 17
5368
5369 static const unsigned char
5370 scope_bits[] =
5371 {
5372 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5373 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5374 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5375 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5376 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5377 },
5378 scope_mask_bits[] =
5379 {
5380 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5381 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5382 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5383 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5384 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5385 };
5386
5387 Cursor
5388 cursor;
5389
5390 Pixmap
5391 mask,
5392 source;
5393
5394 XColor
5395 background,
5396 foreground;
5397
5398 assert(display != (Display *) NULL);
5399 assert(window != (Window) NULL);
5400 assert(colormap != (Colormap) NULL);
5401 assert(background_color != (char *) NULL);
5402 assert(foreground_color != (char *) NULL);
5403 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5404 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5405 scope_height);
5406 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5407 scope_width,scope_height);
5408 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5409 {
5410 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5411 return((Cursor) NULL);
5412 }
5413 (void) XParseColor(display,colormap,background_color,&background);
5414 (void) XParseColor(display,colormap,foreground_color,&foreground);
5415 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5416 scope_x_hot,scope_y_hot);
5417 (void) XFreePixmap(display,source);
5418 (void) XFreePixmap(display,mask);
5419 return(cursor);
5420}
5421
5422/*
5423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5424% %
5425% %
5426% %
5427% X M a k e I m a g e %
5428% %
5429% %
5430% %
5431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5432%
5433% XMakeImage() creates an X11 image. If the image size differs from the X11
5434% image size, the image is first resized.
5435%
5436% The format of the XMakeImage method is:
5437%
5438% MagickBooleanType XMakeImage(Display *display,
5439% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005440% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005441%
5442% A description of each parameter follows:
5443%
5444% o display: Specifies a connection to an X server; returned from
5445% XOpenDisplay.
5446%
5447% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5448%
5449% o window: Specifies a pointer to a XWindowInfo structure.
5450%
5451% o image: the image.
5452%
5453% o width: Specifies the width in pixels of the rectangular area to
5454% display.
5455%
5456% o height: Specifies the height in pixels of the rectangular area to
5457% display.
5458%
cristy051718b2011-08-28 22:49:25 +00005459% o exception: return any errors or warnings in this structure.
5460%
cristy3ed852e2009-09-05 21:47:34 +00005461*/
cristybcbda3f2011-09-03 13:01:22 +00005462MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005463 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005464 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005465{
5466#define CheckOverflowException(length,width,height) \
5467 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5468
5469 int
5470 depth,
5471 format;
5472
5473 size_t
5474 length;
5475
5476 XImage
5477 *matte_image,
5478 *ximage;
5479
5480 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5481 assert(display != (Display *) NULL);
5482 assert(resource_info != (XResourceInfo *) NULL);
5483 assert(window != (XWindowInfo *) NULL);
5484 assert(width != 0);
5485 assert(height != 0);
5486 if ((window->width == 0) || (window->height == 0))
5487 return(MagickFalse);
5488 /*
5489 Apply user transforms to the image.
5490 */
5491 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5492 (void) XFlush(display);
5493 depth=(int) window->depth;
5494 if (window->destroy)
5495 window->image=DestroyImage(window->image);
5496 window->image=image;
5497 window->destroy=MagickFalse;
5498 if (window->image != (Image *) NULL)
5499 {
5500 if (window->crop_geometry != (char *) NULL)
5501 {
5502 Image
5503 *crop_image;
5504
5505 RectangleInfo
5506 crop_info;
5507
5508 /*
5509 Crop image.
5510 */
5511 window->image->page.x=0;
5512 window->image->page.y=0;
5513 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005514 &crop_info,exception);
5515 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005516 if (crop_image != (Image *) NULL)
5517 {
5518 if (window->image != image)
5519 window->image=DestroyImage(window->image);
5520 window->image=crop_image;
5521 window->destroy=MagickTrue;
5522 }
5523 }
5524 if ((width != (unsigned int) window->image->columns) ||
5525 (height != (unsigned int) window->image->rows))
5526 {
5527 Image
5528 *resize_image;
5529
5530 /*
5531 Resize image.
5532 */
5533 resize_image=NewImageList();
5534 if (window->pixel_info->colors != 0)
cristy6710d842011-10-20 23:23:00 +00005535 resize_image=SampleImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005536 else
cristy6710d842011-10-20 23:23:00 +00005537 resize_image=ThumbnailImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005538 if (resize_image != (Image *) NULL)
5539 {
5540 if (window->image != image)
5541 window->image=DestroyImage(window->image);
5542 window->image=resize_image;
5543 window->destroy=MagickTrue;
5544 }
5545 }
5546 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005547 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005548 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005549 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005550 }
5551 /*
5552 Create X image.
5553 */
5554 ximage=(XImage *) NULL;
5555 format=(depth == 1) ? XYBitmap : ZPixmap;
5556#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5557 if (window->shared_memory != MagickFalse)
5558 {
5559 XShmSegmentInfo
5560 *segment_info;
5561
5562 segment_info=(XShmSegmentInfo *) window->segment_info;
5563 segment_info[1].shmid=(-1);
5564 segment_info[1].shmaddr=(char *) NULL;
5565 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5566 (char *) NULL,&segment_info[1],width,height);
5567 if (ximage == (XImage *) NULL)
5568 window->shared_memory=MagickFalse;
5569 length=(size_t) ximage->bytes_per_line*ximage->height;
5570 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5571 window->shared_memory=MagickFalse;
5572 if (window->shared_memory != MagickFalse)
5573 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5574 if (window->shared_memory != MagickFalse)
5575 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5576 if (segment_info[1].shmid < 0)
5577 window->shared_memory=MagickFalse;
5578 if (window->shared_memory != MagickFalse)
5579 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5580 else
5581 {
5582 if (ximage != (XImage *) NULL)
5583 XDestroyImage(ximage);
5584 ximage=(XImage *) NULL;
5585 if (segment_info[1].shmaddr)
5586 {
5587 (void) shmdt(segment_info[1].shmaddr);
5588 segment_info[1].shmaddr=(char *) NULL;
5589 }
5590 if (segment_info[1].shmid >= 0)
5591 {
5592 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5593 segment_info[1].shmid=(-1);
5594 }
5595 }
5596 }
5597#endif
5598 /*
5599 Allocate X image pixel data.
5600 */
5601#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5602 if (window->shared_memory)
5603 {
5604 Status
5605 status;
5606
5607 XShmSegmentInfo
5608 *segment_info;
5609
5610 (void) XSync(display,MagickFalse);
5611 xerror_alert=MagickFalse;
5612 segment_info=(XShmSegmentInfo *) window->segment_info;
5613 ximage->data=segment_info[1].shmaddr;
5614 segment_info[1].readOnly=MagickFalse;
5615 status=XShmAttach(display,&segment_info[1]);
5616 if (status != False)
5617 (void) XSync(display,MagickFalse);
5618 if ((status == False) || (xerror_alert != MagickFalse))
5619 {
5620 window->shared_memory=MagickFalse;
5621 if (status != False)
5622 XShmDetach(display,&segment_info[1]);
5623 if (ximage != (XImage *) NULL)
5624 {
5625 ximage->data=NULL;
5626 XDestroyImage(ximage);
5627 ximage=(XImage *) NULL;
5628 }
5629 if (segment_info[1].shmid >= 0)
5630 {
5631 if (segment_info[1].shmaddr != NULL)
5632 (void) shmdt(segment_info[1].shmaddr);
5633 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5634 segment_info[1].shmid=(-1);
5635 segment_info[1].shmaddr=(char *) NULL;
5636 }
5637 }
5638 }
5639#endif
5640 if (window->shared_memory == MagickFalse)
5641 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5642 (char *) NULL,width,height,XBitmapPad(display),0);
5643 if (ximage == (XImage *) NULL)
5644 {
5645 /*
5646 Unable to create X image.
5647 */
5648 (void) XCheckDefineCursor(display,window->id,window->cursor);
5649 return(MagickFalse);
5650 }
5651 length=(size_t) ximage->bytes_per_line*ximage->height;
5652 if (IsEventLogging())
5653 {
5654 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5655 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5656 ximage->width,ximage->height);
5657 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5658 ximage->format);
5659 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5660 ximage->byte_order);
5661 (void) LogMagickEvent(X11Event,GetMagickModule(),
5662 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5663 ximage->bitmap_bit_order,ximage->bitmap_pad);
5664 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5665 ximage->depth);
5666 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5667 ximage->bytes_per_line);
5668 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5669 ximage->bits_per_pixel);
5670 (void) LogMagickEvent(X11Event,GetMagickModule(),
5671 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5672 ximage->green_mask,ximage->blue_mask);
5673 }
5674 if (window->shared_memory == MagickFalse)
5675 {
5676 if (ximage->format != XYBitmap)
5677 ximage->data=(char *) AcquireQuantumMemory((size_t)
5678 ximage->bytes_per_line,(size_t) ximage->height);
5679 else
5680 ximage->data=(char *) AcquireQuantumMemory((size_t)
5681 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5682 }
5683 if (ximage->data == (char *) NULL)
5684 {
5685 /*
5686 Unable to allocate pixel data.
5687 */
5688 XDestroyImage(ximage);
5689 ximage=(XImage *) NULL;
5690 (void) XCheckDefineCursor(display,window->id,window->cursor);
5691 return(MagickFalse);
5692 }
5693 if (window->ximage != (XImage *) NULL)
5694 {
5695 /*
5696 Destroy previous X image.
5697 */
5698 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5699#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5700 if (window->segment_info != (XShmSegmentInfo *) NULL)
5701 {
5702 XShmSegmentInfo
5703 *segment_info;
5704
5705 segment_info=(XShmSegmentInfo *) window->segment_info;
5706 if (segment_info[0].shmid >= 0)
5707 {
5708 (void) XSync(display,MagickFalse);
5709 (void) XShmDetach(display,&segment_info[0]);
5710 (void) XSync(display,MagickFalse);
5711 if (segment_info[0].shmaddr != (char *) NULL)
5712 (void) shmdt(segment_info[0].shmaddr);
5713 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5714 segment_info[0].shmid=(-1);
5715 segment_info[0].shmaddr=(char *) NULL;
5716 window->ximage->data=(char *) NULL;
5717 }
5718 }
5719#endif
5720 if (window->ximage->data != (char *) NULL)
5721 free(window->ximage->data);
5722 window->ximage->data=(char *) NULL;
5723 XDestroyImage(window->ximage);
5724 window->ximage=(XImage *) NULL;
5725 }
5726#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5727 if (window->segment_info != (XShmSegmentInfo *) NULL)
5728 {
5729 XShmSegmentInfo
5730 *segment_info;
5731
5732 segment_info=(XShmSegmentInfo *) window->segment_info;
5733 segment_info[0]=segment_info[1];
5734 }
5735#endif
5736 window->ximage=ximage;
5737 matte_image=(XImage *) NULL;
5738 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5739 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005740 ((int) width <= XDisplayWidth(display,window->screen)) &&
5741 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005742 {
5743 /*
5744 Create matte image.
5745 */
5746 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5747 (char *) NULL,width,height,XBitmapPad(display),0);
5748 if (IsEventLogging())
5749 {
5750 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5751 (void) LogMagickEvent(X11Event,GetMagickModule(),
5752 " width, height: %dx%d",matte_image->width,matte_image->height);
5753 }
5754 if (matte_image != (XImage *) NULL)
5755 {
5756 /*
5757 Allocate matte image pixel data.
5758 */
5759 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5760 matte_image->bytes_per_line*matte_image->depth,
5761 (size_t) matte_image->height);
5762 if (matte_image->data == (char *) NULL)
5763 {
5764 XDestroyImage(matte_image);
5765 matte_image=(XImage *) NULL;
5766 }
5767 }
5768 }
5769 if (window->matte_image != (XImage *) NULL)
5770 {
5771 /*
5772 Free matte image.
5773 */
5774 if (window->matte_image->data != (char *) NULL)
5775 free(window->matte_image->data);
5776 window->matte_image->data=(char *) NULL;
5777 XDestroyImage(window->matte_image);
5778 window->matte_image=(XImage *) NULL;
5779 }
5780 window->matte_image=matte_image;
5781 if (window->matte_pixmap != (Pixmap) NULL)
5782 {
5783 (void) XFreePixmap(display,window->matte_pixmap);
5784 window->matte_pixmap=(Pixmap) NULL;
5785#if defined(MAGICKCORE_HAVE_SHAPE)
5786 if (window->shape != MagickFalse)
5787 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5788#endif
5789 }
5790 window->stasis=MagickFalse;
5791 /*
5792 Convert pixels to X image data.
5793 */
5794 if (window->image != (Image *) NULL)
5795 {
5796 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5797 (ximage->bitmap_bit_order == LSBFirst)))
5798 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005799 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005800 else
5801 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005802 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005803 }
5804 if (window->matte_image != (XImage *) NULL)
5805 {
5806 /*
5807 Create matte pixmap.
5808 */
5809 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5810 if (window->matte_pixmap != (Pixmap) NULL)
5811 {
5812 GC
5813 graphics_context;
5814
5815 XGCValues
5816 context_values;
5817
5818 /*
5819 Copy matte image to matte pixmap.
5820 */
cristy4c08aed2011-07-01 19:47:50 +00005821 context_values.background=0;
5822 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005823 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005824 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005825 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5826 window->matte_image,0,0,0,0,width,height);
5827 (void) XFreeGC(display,graphics_context);
5828#if defined(MAGICKCORE_HAVE_SHAPE)
5829 if (window->shape != MagickFalse)
5830 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5831 window->matte_pixmap,ShapeSet);
5832#endif
5833 }
5834 }
5835 (void) XMakePixmap(display,resource_info,window);
5836 /*
5837 Restore cursor.
5838 */
5839 (void) XCheckDefineCursor(display,window->id,window->cursor);
5840 return(MagickTrue);
5841}
5842
5843/*
5844%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5845% %
5846% %
5847% %
5848+ X M a k e I m a g e L S B F i r s t %
5849% %
5850% %
5851% %
5852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5853%
5854% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5855% pixels are copied in least-significant bit and byte first order. The
5856% server's scanline pad is respected. Rather than using one or two general
5857% cases, many special cases are found here to help speed up the image
5858% conversion.
5859%
5860% The format of the XMakeImageLSBFirst method is:
5861%
cristye941a752011-10-15 01:52:48 +00005862% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5863% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005864%
5865% A description of each parameter follows:
5866%
5867% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5868%
5869% o window: Specifies a pointer to a XWindowInfo structure.
5870%
5871% o image: the image.
5872%
5873% o ximage: Specifies a pointer to a XImage structure; returned from
5874% XCreateImage.
5875%
5876% o matte_image: Specifies a pointer to a XImage structure; returned from
5877% XCreateImage.
5878%
cristye941a752011-10-15 01:52:48 +00005879% o exception: return any errors or warnings in this structure.
5880%
cristy3ed852e2009-09-05 21:47:34 +00005881*/
5882static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005883 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5884 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005885{
cristyc57f6942010-11-12 01:47:39 +00005886 CacheView
5887 *canvas_view;
5888
cristy3ed852e2009-09-05 21:47:34 +00005889 Image
5890 *canvas;
5891
5892 int
5893 y;
5894
cristy4c08aed2011-07-01 19:47:50 +00005895 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005896 *p;
5897
5898 register int
5899 x;
5900
5901 register unsigned char
5902 *q;
5903
5904 unsigned char
5905 bit,
5906 byte;
5907
5908 unsigned int
5909 scanline_pad;
5910
cristyf2faecf2010-05-28 19:19:36 +00005911 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005912 pixel,
5913 *pixels;
5914
5915 XStandardColormap
5916 *map_info;
5917
5918 assert(resource_info != (XResourceInfo *) NULL);
5919 assert(window != (XWindowInfo *) NULL);
5920 assert(image != (Image *) NULL);
5921 if (image->debug != MagickFalse)
5922 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5923 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005924 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005925 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005926 {
5927 char
5928 size[MaxTextExtent];
5929
5930 Image
5931 *pattern;
5932
5933 ImageInfo
5934 *image_info;
5935
5936 image_info=AcquireImageInfo();
5937 (void) CopyMagickString(image_info->filename,
5938 resource_info->image_info->texture != (char *) NULL ?
5939 resource_info->image_info->texture : "pattern:checkerboard",
5940 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005941 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005942 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005943 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005944 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005945 image_info=DestroyImageInfo(image_info);
5946 if (pattern != (Image *) NULL)
5947 {
cristy6710d842011-10-20 23:23:00 +00005948 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005949 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00005950 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
5951 exception);
cristy3ed852e2009-09-05 21:47:34 +00005952 pattern=DestroyImage(pattern);
5953 }
5954 }
5955 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5956 ximage->bits_per_pixel) >> 3));
5957 map_info=window->map_info;
5958 pixels=window->pixel_info->pixels;
5959 q=(unsigned char *) ximage->data;
5960 x=0;
cristyc57f6942010-11-12 01:47:39 +00005961 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005962 if (ximage->format == XYBitmap)
5963 {
5964 register unsigned short
5965 polarity;
5966
5967 unsigned char
5968 background,
5969 foreground;
5970
5971 /*
5972 Convert canvas to big-endian bitmap.
5973 */
5974 background=(unsigned char)
5975 (XPixelIntensity(&window->pixel_info->foreground_color) <
5976 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5977 foreground=(unsigned char)
5978 (XPixelIntensity(&window->pixel_info->background_color) <
5979 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005980 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005981 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5982 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005983 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5984 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005985 for (y=0; y < (int) canvas->rows; y++)
5986 {
cristyc57f6942010-11-12 01:47:39 +00005987 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005988 exception);
cristy4c08aed2011-07-01 19:47:50 +00005989 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005990 break;
cristy3ed852e2009-09-05 21:47:34 +00005991 bit=0;
5992 byte=0;
5993 for (x=0; x < (int) canvas->columns; x++)
5994 {
5995 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005996 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005997 byte|=foreground;
5998 else
5999 byte|=background;
6000 bit++;
6001 if (bit == 8)
6002 {
6003 *q++=byte;
6004 bit=0;
6005 byte=0;
6006 }
cristyed231572011-07-14 02:18:59 +00006007 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006008 }
6009 if (bit != 0)
6010 *q=byte >> (8-bit);
6011 q+=scanline_pad;
6012 }
6013 }
6014 else
6015 if (window->pixel_info->colors != 0)
6016 switch (ximage->bits_per_pixel)
6017 {
6018 case 2:
6019 {
6020 register unsigned int
6021 nibble;
6022
6023 /*
6024 Convert to 2 bit color-mapped X canvas.
6025 */
6026 for (y=0; y < (int) canvas->rows; y++)
6027 {
cristyc57f6942010-11-12 01:47:39 +00006028 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006029 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006030 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006031 break;
cristy3ed852e2009-09-05 21:47:34 +00006032 nibble=0;
6033 for (x=0; x < (int) canvas->columns; x++)
6034 {
cristy4c08aed2011-07-01 19:47:50 +00006035 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006036 switch (nibble)
6037 {
6038 case 0:
6039 {
6040 *q=(unsigned char) pixel;
6041 nibble++;
6042 break;
6043 }
6044 case 1:
6045 {
6046 *q|=(unsigned char) (pixel << 2);
6047 nibble++;
6048 break;
6049 }
6050 case 2:
6051 {
6052 *q|=(unsigned char) (pixel << 4);
6053 nibble++;
6054 break;
6055 }
6056 case 3:
6057 {
6058 *q|=(unsigned char) (pixel << 6);
6059 q++;
6060 nibble=0;
6061 break;
6062 }
6063 }
cristyed231572011-07-14 02:18:59 +00006064 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006065 }
6066 q+=scanline_pad;
6067 }
6068 break;
6069 }
6070 case 4:
6071 {
6072 register unsigned int
6073 nibble;
6074
6075 /*
6076 Convert to 4 bit color-mapped X canvas.
6077 */
6078 for (y=0; y < (int) canvas->rows; y++)
6079 {
cristyc57f6942010-11-12 01:47:39 +00006080 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006081 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006082 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006083 break;
cristy3ed852e2009-09-05 21:47:34 +00006084 nibble=0;
6085 for (x=0; x < (int) canvas->columns; x++)
6086 {
cristy4c08aed2011-07-01 19:47:50 +00006087 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006088 switch (nibble)
6089 {
6090 case 0:
6091 {
6092 *q=(unsigned char) pixel;
6093 nibble++;
6094 break;
6095 }
6096 case 1:
6097 {
6098 *q|=(unsigned char) (pixel << 4);
6099 q++;
6100 nibble=0;
6101 break;
6102 }
6103 }
cristyed231572011-07-14 02:18:59 +00006104 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006105 }
6106 q+=scanline_pad;
6107 }
6108 break;
6109 }
6110 case 6:
6111 case 8:
6112 {
6113 /*
6114 Convert to 8 bit color-mapped X canvas.
6115 */
6116 if (resource_info->color_recovery &&
6117 resource_info->quantize_info->dither)
6118 {
cristy6710d842011-10-20 23:23:00 +00006119 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006120 break;
6121 }
6122 for (y=0; y < (int) canvas->rows; y++)
6123 {
cristyc57f6942010-11-12 01:47:39 +00006124 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006125 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006126 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006127 break;
cristy3ed852e2009-09-05 21:47:34 +00006128 for (x=0; x < (int) canvas->columns; x++)
6129 {
cristy4c08aed2011-07-01 19:47:50 +00006130 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006131 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006132 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006133 }
6134 q+=scanline_pad;
6135 }
6136 break;
6137 }
6138 default:
6139 {
6140 register int
6141 k;
6142
6143 register unsigned int
6144 bytes_per_pixel;
6145
6146 unsigned char
cristybb503372010-05-27 20:51:26 +00006147 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006148
6149 /*
6150 Convert to multi-byte color-mapped X canvas.
6151 */
6152 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6153 for (y=0; y < (int) canvas->rows; y++)
6154 {
cristyc57f6942010-11-12 01:47:39 +00006155 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006156 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006157 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006158 break;
cristy3ed852e2009-09-05 21:47:34 +00006159 for (x=0; x < (int) canvas->columns; x++)
6160 {
cristy4c08aed2011-07-01 19:47:50 +00006161 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006162 for (k=0; k < (int) bytes_per_pixel; k++)
6163 {
6164 channel[k]=(unsigned char) pixel;
6165 pixel>>=8;
6166 }
6167 for (k=0; k < (int) bytes_per_pixel; k++)
6168 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006169 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006170 }
6171 q+=scanline_pad;
6172 }
6173 break;
6174 }
6175 }
6176 else
6177 switch (ximage->bits_per_pixel)
6178 {
6179 case 2:
6180 {
6181 register unsigned int
6182 nibble;
6183
6184 /*
6185 Convert to contiguous 2 bit continuous-tone X canvas.
6186 */
6187 for (y=0; y < (int) canvas->rows; y++)
6188 {
6189 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006190 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006191 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006192 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006193 break;
6194 for (x=0; x < (int) canvas->columns; x++)
6195 {
cristy4c08aed2011-07-01 19:47:50 +00006196 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006197 pixel&=0xf;
6198 switch (nibble)
6199 {
6200 case 0:
6201 {
6202 *q=(unsigned char) pixel;
6203 nibble++;
6204 break;
6205 }
6206 case 1:
6207 {
6208 *q|=(unsigned char) (pixel << 2);
6209 nibble++;
6210 break;
6211 }
6212 case 2:
6213 {
6214 *q|=(unsigned char) (pixel << 4);
6215 nibble++;
6216 break;
6217 }
6218 case 3:
6219 {
6220 *q|=(unsigned char) (pixel << 6);
6221 q++;
6222 nibble=0;
6223 break;
6224 }
6225 }
cristyed231572011-07-14 02:18:59 +00006226 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006227 }
6228 q+=scanline_pad;
6229 }
6230 break;
6231 }
6232 case 4:
6233 {
6234 register unsigned int
6235 nibble;
6236
6237 /*
6238 Convert to contiguous 4 bit continuous-tone X canvas.
6239 */
6240 for (y=0; y < (int) canvas->rows; y++)
6241 {
cristyc57f6942010-11-12 01:47:39 +00006242 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006243 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006244 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006245 break;
6246 nibble=0;
6247 for (x=0; x < (int) canvas->columns; x++)
6248 {
cristy4c08aed2011-07-01 19:47:50 +00006249 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006250 pixel&=0xf;
6251 switch (nibble)
6252 {
6253 case 0:
6254 {
6255 *q=(unsigned char) pixel;
6256 nibble++;
6257 break;
6258 }
6259 case 1:
6260 {
6261 *q|=(unsigned char) (pixel << 4);
6262 q++;
6263 nibble=0;
6264 break;
6265 }
6266 }
cristyed231572011-07-14 02:18:59 +00006267 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006268 }
6269 q+=scanline_pad;
6270 }
6271 break;
6272 }
6273 case 6:
6274 case 8:
6275 {
6276 /*
6277 Convert to contiguous 8 bit continuous-tone X canvas.
6278 */
6279 if (resource_info->color_recovery &&
6280 resource_info->quantize_info->dither)
6281 {
cristy6710d842011-10-20 23:23:00 +00006282 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006283 break;
6284 }
6285 for (y=0; y < (int) canvas->rows; y++)
6286 {
cristyc57f6942010-11-12 01:47:39 +00006287 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006288 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006289 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006290 break;
6291 for (x=0; x < (int) canvas->columns; x++)
6292 {
cristy4c08aed2011-07-01 19:47:50 +00006293 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006294 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006295 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006296 }
6297 q+=scanline_pad;
6298 }
6299 break;
6300 }
6301 default:
6302 {
6303 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6304 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6305 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6306 (map_info->blue_mult == 1))
6307 {
6308 /*
6309 Convert to 32 bit continuous-tone X canvas.
6310 */
6311 for (y=0; y < (int) canvas->rows; y++)
6312 {
cristyc57f6942010-11-12 01:47:39 +00006313 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006314 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006315 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006316 break;
6317 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6318 (blue_gamma != 1.0))
6319 {
6320 /*
6321 Gamma correct canvas.
6322 */
6323 for (x=(int) canvas->columns-1; x >= 0; x--)
6324 {
cristyccf844f2010-02-03 23:28:16 +00006325 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006326 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006327 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006328 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006329 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006330 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006331 *q++=0;
cristyed231572011-07-14 02:18:59 +00006332 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006333 }
6334 continue;
6335 }
6336 for (x=(int) canvas->columns-1; x >= 0; x--)
6337 {
cristy4c08aed2011-07-01 19:47:50 +00006338 *q++=ScaleQuantumToChar((Quantum)
6339 GetPixelBlue(canvas,p));
6340 *q++=ScaleQuantumToChar((Quantum)
6341 GetPixelGreen(canvas,p));
6342 *q++=ScaleQuantumToChar((Quantum)
6343 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006344 *q++=0;
cristyed231572011-07-14 02:18:59 +00006345 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006346 }
6347 }
6348 }
6349 else
6350 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6351 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6352 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6353 (map_info->blue_mult == 65536L))
6354 {
6355 /*
6356 Convert to 32 bit continuous-tone X canvas.
6357 */
6358 for (y=0; y < (int) canvas->rows; y++)
6359 {
cristyc57f6942010-11-12 01:47:39 +00006360 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006361 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006362 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006363 break;
6364 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6365 (blue_gamma != 1.0))
6366 {
6367 /*
6368 Gamma correct canvas.
6369 */
6370 for (x=(int) canvas->columns-1; x >= 0; x--)
6371 {
cristyccf844f2010-02-03 23:28:16 +00006372 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006373 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006374 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006375 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006376 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006377 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006378 *q++=0;
cristyed231572011-07-14 02:18:59 +00006379 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006380 }
6381 continue;
6382 }
6383 for (x=(int) canvas->columns-1; x >= 0; x--)
6384 {
cristyccf844f2010-02-03 23:28:16 +00006385 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006386 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006387 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006388 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006389 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006390 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006391 *q++=0;
cristyed231572011-07-14 02:18:59 +00006392 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006393 }
6394 }
6395 }
6396 else
6397 {
6398 register int
6399 k;
6400
6401 register unsigned int
6402 bytes_per_pixel;
6403
6404 unsigned char
cristybb503372010-05-27 20:51:26 +00006405 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006406
6407 /*
6408 Convert to multi-byte continuous-tone X canvas.
6409 */
6410 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6411 for (y=0; y < (int) canvas->rows; y++)
6412 {
cristyc57f6942010-11-12 01:47:39 +00006413 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006414 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006415 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006416 break;
cristyc57f6942010-11-12 01:47:39 +00006417 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006418 {
cristy4c08aed2011-07-01 19:47:50 +00006419 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006420 for (k=0; k < (int) bytes_per_pixel; k++)
6421 {
6422 channel[k]=(unsigned char) pixel;
6423 pixel>>=8;
6424 }
6425 for (k=0; k < (int) bytes_per_pixel; k++)
6426 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006427 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006428 }
6429 q+=scanline_pad;
6430 }
6431 }
6432 break;
6433 }
6434 }
6435 if (matte_image != (XImage *) NULL)
6436 {
6437 /*
6438 Initialize matte canvas.
6439 */
6440 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6441 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6442 q=(unsigned char *) matte_image->data;
6443 for (y=0; y < (int) canvas->rows; y++)
6444 {
cristyc57f6942010-11-12 01:47:39 +00006445 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006446 exception);
cristy4c08aed2011-07-01 19:47:50 +00006447 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006448 break;
6449 bit=0;
6450 byte=0;
6451 for (x=(int) canvas->columns-1; x >= 0; x--)
6452 {
6453 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006454 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006455 byte|=0x80;
6456 bit++;
6457 if (bit == 8)
6458 {
6459 *q++=byte;
6460 bit=0;
6461 byte=0;
6462 }
cristyed231572011-07-14 02:18:59 +00006463 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006464 }
6465 if (bit != 0)
6466 *q=byte >> (8-bit);
6467 q+=scanline_pad;
6468 }
6469 }
cristyc57f6942010-11-12 01:47:39 +00006470 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006471 if (canvas != image)
6472 canvas=DestroyImage(canvas);
6473}
6474
6475/*
6476%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6477% %
6478% %
6479% %
6480+ X M a k e I m a g e M S B F i r s t %
6481% %
6482% %
6483% %
6484%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6485%
6486% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6487% image pixels are copied in most-significant bit and byte first order. The
6488% server's scanline pad is also respected. Rather than using one or two
6489% general cases, many special cases are found here to help speed up the image
6490% conversion.
6491%
6492% The format of the XMakeImageMSBFirst method is:
6493%
cristye941a752011-10-15 01:52:48 +00006494% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6495% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006496%
6497% A description of each parameter follows:
6498%
6499% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6500%
6501% o window: Specifies a pointer to a XWindowInfo structure.
6502%
6503% o image: the image.
6504%
6505% o ximage: Specifies a pointer to a XImage structure; returned from
6506% XCreateImage.
6507%
6508% o matte_image: Specifies a pointer to a XImage structure; returned from
6509% XCreateImage.
6510%
cristye941a752011-10-15 01:52:48 +00006511% o exception: return any errors or warnings in this structure.
6512%
cristy3ed852e2009-09-05 21:47:34 +00006513*/
6514static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006515 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6516 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006517{
cristyc57f6942010-11-12 01:47:39 +00006518 CacheView
6519 *canvas_view;
6520
cristy3ed852e2009-09-05 21:47:34 +00006521 Image
6522 *canvas;
6523
6524 int
6525 y;
6526
6527 register int
6528 x;
6529
cristy4c08aed2011-07-01 19:47:50 +00006530 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006531 *p;
6532
6533 register unsigned char
6534 *q;
6535
6536 unsigned char
6537 bit,
6538 byte;
6539
6540 unsigned int
6541 scanline_pad;
6542
cristyf2faecf2010-05-28 19:19:36 +00006543 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006544 pixel,
6545 *pixels;
6546
6547 XStandardColormap
6548 *map_info;
6549
6550 assert(resource_info != (XResourceInfo *) NULL);
6551 assert(window != (XWindowInfo *) NULL);
6552 assert(image != (Image *) NULL);
6553 if (image->debug != MagickFalse)
6554 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6555 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006556 if ((window->immutable != MagickFalse) &&
6557 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006558 {
6559 char
6560 size[MaxTextExtent];
6561
6562 Image
6563 *pattern;
6564
6565 ImageInfo
6566 *image_info;
6567
6568 image_info=AcquireImageInfo();
6569 (void) CopyMagickString(image_info->filename,
6570 resource_info->image_info->texture != (char *) NULL ?
6571 resource_info->image_info->texture : "pattern:checkerboard",
6572 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006573 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006574 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006575 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006576 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006577 image_info=DestroyImageInfo(image_info);
6578 if (pattern != (Image *) NULL)
6579 {
cristy6710d842011-10-20 23:23:00 +00006580 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006581 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00006582 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
6583 exception);
cristy3ed852e2009-09-05 21:47:34 +00006584 pattern=DestroyImage(pattern);
6585 }
6586 }
cristy4c08aed2011-07-01 19:47:50 +00006587 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6588 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006589 map_info=window->map_info;
6590 pixels=window->pixel_info->pixels;
6591 q=(unsigned char *) ximage->data;
6592 x=0;
cristyc57f6942010-11-12 01:47:39 +00006593 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006594 if (ximage->format == XYBitmap)
6595 {
6596 register unsigned short
6597 polarity;
6598
6599 unsigned char
6600 background,
6601 foreground;
6602
6603 /*
6604 Convert canvas to big-endian bitmap.
6605 */
6606 background=(unsigned char)
6607 (XPixelIntensity(&window->pixel_info->foreground_color) <
6608 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6609 foreground=(unsigned char)
6610 (XPixelIntensity(&window->pixel_info->background_color) <
6611 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006612 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006613 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6614 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006615 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6616 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006617 for (y=0; y < (int) canvas->rows; y++)
6618 {
cristyc57f6942010-11-12 01:47:39 +00006619 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006620 exception);
cristy4c08aed2011-07-01 19:47:50 +00006621 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006622 break;
cristy3ed852e2009-09-05 21:47:34 +00006623 bit=0;
6624 byte=0;
6625 for (x=(int) canvas->columns-1; x >= 0; x--)
6626 {
6627 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006628 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006629 byte|=foreground;
6630 else
6631 byte|=background;
6632 bit++;
6633 if (bit == 8)
6634 {
6635 *q++=byte;
6636 bit=0;
6637 byte=0;
6638 }
cristyed231572011-07-14 02:18:59 +00006639 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006640 }
6641 if (bit != 0)
6642 *q=byte << (8-bit);
6643 q+=scanline_pad;
6644 }
6645 }
6646 else
6647 if (window->pixel_info->colors != 0)
6648 switch (ximage->bits_per_pixel)
6649 {
6650 case 2:
6651 {
6652 register unsigned int
6653 nibble;
6654
6655 /*
6656 Convert to 2 bit color-mapped X canvas.
6657 */
6658 for (y=0; y < (int) canvas->rows; y++)
6659 {
cristyc57f6942010-11-12 01:47:39 +00006660 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006661 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006662 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006663 break;
cristy3ed852e2009-09-05 21:47:34 +00006664 nibble=0;
6665 for (x=0; x < (int) canvas->columns; x++)
6666 {
cristy4c08aed2011-07-01 19:47:50 +00006667 pixel=pixels[(ssize_t)
6668 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006669 switch (nibble)
6670 {
6671 case 0:
6672 {
6673 *q=(unsigned char) (pixel << 6);
6674 nibble++;
6675 break;
6676 }
6677 case 1:
6678 {
6679 *q|=(unsigned char) (pixel << 4);
6680 nibble++;
6681 break;
6682 }
6683 case 2:
6684 {
6685 *q|=(unsigned char) (pixel << 2);
6686 nibble++;
6687 break;
6688 }
6689 case 3:
6690 {
6691 *q|=(unsigned char) pixel;
6692 q++;
6693 nibble=0;
6694 break;
6695 }
6696 }
cristyed231572011-07-14 02:18:59 +00006697 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006698 }
6699 q+=scanline_pad;
6700 }
6701 break;
6702 }
6703 case 4:
6704 {
6705 register unsigned int
6706 nibble;
6707
6708 /*
6709 Convert to 4 bit color-mapped X canvas.
6710 */
6711 for (y=0; y < (int) canvas->rows; y++)
6712 {
cristyc57f6942010-11-12 01:47:39 +00006713 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006714 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006715 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006716 break;
cristy3ed852e2009-09-05 21:47:34 +00006717 nibble=0;
6718 for (x=0; x < (int) canvas->columns; x++)
6719 {
cristy4c08aed2011-07-01 19:47:50 +00006720 pixel=pixels[(ssize_t)
6721 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006722 switch (nibble)
6723 {
6724 case 0:
6725 {
6726 *q=(unsigned char) (pixel << 4);
6727 nibble++;
6728 break;
6729 }
6730 case 1:
6731 {
6732 *q|=(unsigned char) pixel;
6733 q++;
6734 nibble=0;
6735 break;
6736 }
6737 }
cristyed231572011-07-14 02:18:59 +00006738 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006739 }
6740 q+=scanline_pad;
6741 }
6742 break;
6743 }
6744 case 6:
6745 case 8:
6746 {
6747 /*
6748 Convert to 8 bit color-mapped X canvas.
6749 */
6750 if (resource_info->color_recovery &&
6751 resource_info->quantize_info->dither)
6752 {
cristy6710d842011-10-20 23:23:00 +00006753 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006754 break;
6755 }
6756 for (y=0; y < (int) canvas->rows; y++)
6757 {
cristyc57f6942010-11-12 01:47:39 +00006758 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006759 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006760 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006761 break;
cristy3ed852e2009-09-05 21:47:34 +00006762 for (x=0; x < (int) canvas->columns; x++)
6763 {
cristy6710d842011-10-20 23:23:00 +00006764 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006765 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006766 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006767 }
6768 q+=scanline_pad;
6769 }
6770 break;
6771 }
6772 default:
6773 {
6774 register int
6775 k;
6776
6777 register unsigned int
6778 bytes_per_pixel;
6779
6780 unsigned char
cristybb503372010-05-27 20:51:26 +00006781 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006782
6783 /*
6784 Convert to 8 bit color-mapped X canvas.
6785 */
6786 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6787 for (y=0; y < (int) canvas->rows; y++)
6788 {
cristyc57f6942010-11-12 01:47:39 +00006789 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006790 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006791 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006792 break;
cristy3ed852e2009-09-05 21:47:34 +00006793 for (x=0; x < (int) canvas->columns; x++)
6794 {
cristy4c08aed2011-07-01 19:47:50 +00006795 pixel=pixels[(ssize_t)
6796 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006797 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6798 {
6799 channel[k]=(unsigned char) pixel;
6800 pixel>>=8;
6801 }
6802 for (k=0; k < (int) bytes_per_pixel; k++)
6803 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006804 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006805 }
6806 q+=scanline_pad;
6807 }
6808 break;
6809 }
6810 }
6811 else
6812 switch (ximage->bits_per_pixel)
6813 {
6814 case 2:
6815 {
6816 register unsigned int
6817 nibble;
6818
6819 /*
6820 Convert to 4 bit continuous-tone X canvas.
6821 */
6822 for (y=0; y < (int) canvas->rows; y++)
6823 {
cristyc57f6942010-11-12 01:47:39 +00006824 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006825 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006826 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006827 break;
6828 nibble=0;
6829 for (x=(int) canvas->columns-1; x >= 0; x--)
6830 {
cristy4c08aed2011-07-01 19:47:50 +00006831 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006832 pixel&=0xf;
6833 switch (nibble)
6834 {
6835 case 0:
6836 {
6837 *q=(unsigned char) (pixel << 6);
6838 nibble++;
6839 break;
6840 }
6841 case 1:
6842 {
6843 *q|=(unsigned char) (pixel << 4);
6844 nibble++;
6845 break;
6846 }
6847 case 2:
6848 {
6849 *q|=(unsigned char) (pixel << 2);
6850 nibble++;
6851 break;
6852 }
6853 case 3:
6854 {
6855 *q|=(unsigned char) pixel;
6856 q++;
6857 nibble=0;
6858 break;
6859 }
6860 }
cristyed231572011-07-14 02:18:59 +00006861 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006862 }
6863 q+=scanline_pad;
6864 }
6865 break;
6866 }
6867 case 4:
6868 {
6869 register unsigned int
6870 nibble;
6871
6872 /*
6873 Convert to 4 bit continuous-tone X canvas.
6874 */
6875 for (y=0; y < (int) canvas->rows; y++)
6876 {
cristyc57f6942010-11-12 01:47:39 +00006877 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006878 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006879 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006880 break;
6881 nibble=0;
6882 for (x=(int) canvas->columns-1; x >= 0; x--)
6883 {
cristy4c08aed2011-07-01 19:47:50 +00006884 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006885 pixel&=0xf;
6886 switch (nibble)
6887 {
6888 case 0:
6889 {
6890 *q=(unsigned char) (pixel << 4);
6891 nibble++;
6892 break;
6893 }
6894 case 1:
6895 {
6896 *q|=(unsigned char) pixel;
6897 q++;
6898 nibble=0;
6899 break;
6900 }
6901 }
cristyed231572011-07-14 02:18:59 +00006902 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006903 }
6904 q+=scanline_pad;
6905 }
6906 break;
6907 }
6908 case 6:
6909 case 8:
6910 {
6911 /*
6912 Convert to 8 bit continuous-tone X canvas.
6913 */
6914 if (resource_info->color_recovery &&
6915 resource_info->quantize_info->dither)
6916 {
cristy6710d842011-10-20 23:23:00 +00006917 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006918 break;
6919 }
6920 for (y=0; y < (int) canvas->rows; y++)
6921 {
cristyc57f6942010-11-12 01:47:39 +00006922 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006923 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006924 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006925 break;
6926 for (x=(int) canvas->columns-1; x >= 0; x--)
6927 {
cristy4c08aed2011-07-01 19:47:50 +00006928 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006929 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006930 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006931 }
6932 q+=scanline_pad;
6933 }
6934 break;
6935 }
6936 default:
6937 {
6938 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6939 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6940 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6941 (map_info->blue_mult == 1))
6942 {
6943 /*
6944 Convert to 32 bit continuous-tone X canvas.
6945 */
6946 for (y=0; y < (int) canvas->rows; y++)
6947 {
cristyc57f6942010-11-12 01:47:39 +00006948 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006949 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006950 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006951 break;
6952 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6953 (blue_gamma != 1.0))
6954 {
6955 /*
6956 Gamma correct canvas.
6957 */
6958 for (x=(int) canvas->columns-1; x >= 0; x--)
6959 {
6960 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006961 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006962 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006963 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006964 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006965 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006966 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006967 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006968 }
6969 continue;
6970 }
6971 for (x=(int) canvas->columns-1; x >= 0; x--)
6972 {
6973 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006974 *q++=ScaleQuantumToChar((Quantum)
6975 GetPixelRed(canvas,p));
6976 *q++=ScaleQuantumToChar((Quantum)
6977 GetPixelGreen(canvas,p));
6978 *q++=ScaleQuantumToChar((Quantum)
6979 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006980 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006981 }
6982 }
6983 }
6984 else
6985 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6986 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6987 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6988 (map_info->blue_mult == 65536L))
6989 {
6990 /*
6991 Convert to 32 bit continuous-tone X canvas.
6992 */
6993 for (y=0; y < (int) canvas->rows; y++)
6994 {
cristyc57f6942010-11-12 01:47:39 +00006995 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006996 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006997 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006998 break;
6999 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
7000 (blue_gamma != 1.0))
7001 {
7002 /*
7003 Gamma correct canvas.
7004 */
7005 for (x=(int) canvas->columns-1; x >= 0; x--)
7006 {
7007 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007008 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00007009 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00007010 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00007011 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00007012 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00007013 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00007014 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007015 }
7016 continue;
7017 }
7018 for (x=(int) canvas->columns-1; x >= 0; x--)
7019 {
7020 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007021 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007022 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007023 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007024 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007025 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007026 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00007027 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007028 }
7029 }
7030 }
7031 else
7032 {
7033 register int
7034 k;
7035
7036 register unsigned int
7037 bytes_per_pixel;
7038
7039 unsigned char
cristybb503372010-05-27 20:51:26 +00007040 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007041
7042 /*
7043 Convert to multi-byte continuous-tone X canvas.
7044 */
7045 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7046 for (y=0; y < (int) canvas->rows; y++)
7047 {
cristyc57f6942010-11-12 01:47:39 +00007048 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007049 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007050 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007051 break;
7052 for (x=(int) canvas->columns-1; x >= 0; x--)
7053 {
cristy4c08aed2011-07-01 19:47:50 +00007054 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007055 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7056 {
7057 channel[k]=(unsigned char) pixel;
7058 pixel>>=8;
7059 }
7060 for (k=0; k < (int) bytes_per_pixel; k++)
7061 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007062 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007063 }
7064 q+=scanline_pad;
7065 }
7066 }
7067 break;
7068 }
7069 }
7070 if (matte_image != (XImage *) NULL)
7071 {
7072 /*
7073 Initialize matte canvas.
7074 */
7075 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7076 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7077 q=(unsigned char *) matte_image->data;
7078 for (y=0; y < (int) canvas->rows; y++)
7079 {
cristyc57f6942010-11-12 01:47:39 +00007080 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007081 exception);
cristy4c08aed2011-07-01 19:47:50 +00007082 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007083 break;
7084 bit=0;
7085 byte=0;
7086 for (x=(int) canvas->columns-1; x >= 0; x--)
7087 {
7088 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007089 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007090 byte|=0x01;
7091 bit++;
7092 if (bit == 8)
7093 {
7094 *q++=byte;
7095 bit=0;
7096 byte=0;
7097 }
cristyed231572011-07-14 02:18:59 +00007098 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007099 }
7100 if (bit != 0)
7101 *q=byte << (8-bit);
7102 q+=scanline_pad;
7103 }
7104 }
cristyc57f6942010-11-12 01:47:39 +00007105 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007106 if (canvas != image)
7107 canvas=DestroyImage(canvas);
7108}
7109
7110/*
7111%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7112% %
7113% %
7114% %
7115% X M a k e M a g n i f y I m a g e %
7116% %
7117% %
7118% %
7119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7120%
7121% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7122%
7123% The format of the XMakeMagnifyImage method is:
7124%
cristy6710d842011-10-20 23:23:00 +00007125% void XMakeMagnifyImage(Display *display,XWindows *windows,
7126% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007127%
7128% A description of each parameter follows:
7129%
7130% o display: Specifies a connection to an X server; returned from
7131% XOpenDisplay.
7132%
7133% o windows: Specifies a pointer to a XWindows structure.
7134%
cristy6710d842011-10-20 23:23:00 +00007135% o exception: return any errors or warnings in this structure.
7136%
cristy3ed852e2009-09-05 21:47:34 +00007137*/
cristy6710d842011-10-20 23:23:00 +00007138MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7139 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007140{
7141 char
7142 tuple[MaxTextExtent];
7143
7144 int
7145 y;
7146
cristy4c08aed2011-07-01 19:47:50 +00007147 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007148 pixel;
7149
7150 register int
7151 x;
7152
cristybb503372010-05-27 20:51:26 +00007153 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007154 i;
7155
7156 register unsigned char
7157 *p,
7158 *q;
7159
cristy9d314ff2011-03-09 01:30:28 +00007160 ssize_t
7161 n;
7162
cristy3ed852e2009-09-05 21:47:34 +00007163 static unsigned int
7164 previous_magnify = 0;
7165
7166 static XWindowInfo
7167 magnify_window;
7168
7169 unsigned int
7170 height,
7171 j,
7172 k,
7173 l,
7174 magnify,
7175 scanline_pad,
7176 width;
7177
7178 XImage
7179 *ximage;
7180
7181 /*
7182 Check boundary conditions.
7183 */
7184 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7185 assert(display != (Display *) NULL);
7186 assert(windows != (XWindows *) NULL);
7187 magnify=1;
cristybb503372010-05-27 20:51:26 +00007188 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007189 magnify<<=1;
7190 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7191 magnify<<=1;
7192 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7193 magnify<<=1;
7194 while (magnify > windows->magnify.width)
7195 magnify>>=1;
7196 while (magnify > windows->magnify.height)
7197 magnify>>=1;
7198 if (magnify != previous_magnify)
7199 {
7200 Status
7201 status;
7202
7203 XTextProperty
7204 window_name;
7205
7206 /*
7207 New magnify factor: update magnify window name.
7208 */
7209 i=0;
7210 while ((1 << i) <= (int) magnify)
7211 i++;
cristyb51dff52011-05-19 16:55:47 +00007212 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007213 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007214 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7215 if (status != False)
7216 {
7217 XSetWMName(display,windows->magnify.id,&window_name);
7218 XSetWMIconName(display,windows->magnify.id,&window_name);
7219 (void) XFree((void *) window_name.value);
7220 }
7221 }
7222 previous_magnify=magnify;
7223 ximage=windows->image.ximage;
7224 width=(unsigned int) windows->magnify.ximage->width;
7225 height=(unsigned int) windows->magnify.ximage->height;
7226 if ((windows->magnify.x < 0) ||
7227 (windows->magnify.x >= windows->image.ximage->width))
7228 windows->magnify.x=windows->image.ximage->width >> 1;
7229 x=windows->magnify.x-((width/magnify) >> 1);
7230 if (x < 0)
7231 x=0;
7232 else
7233 if (x > (int) (ximage->width-(width/magnify)))
7234 x=ximage->width-width/magnify;
7235 if ((windows->magnify.y < 0) ||
7236 (windows->magnify.y >= windows->image.ximage->height))
7237 windows->magnify.y=windows->image.ximage->height >> 1;
7238 y=windows->magnify.y-((height/magnify) >> 1);
7239 if (y < 0)
7240 y=0;
7241 else
7242 if (y > (int) (ximage->height-(height/magnify)))
7243 y=ximage->height-height/magnify;
7244 q=(unsigned char *) windows->magnify.ximage->data;
7245 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7246 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7247 if (ximage->bits_per_pixel < 8)
7248 {
7249 register unsigned char
7250 background,
7251 byte,
7252 foreground,
7253 p_bit,
7254 q_bit;
7255
7256 register unsigned int
7257 plane;
7258
7259 XPixelInfo
7260 *pixel_info;
7261
7262 pixel_info=windows->magnify.pixel_info;
7263 switch (ximage->bitmap_bit_order)
7264 {
7265 case LSBFirst:
7266 {
7267 /*
7268 Magnify little-endian bitmap.
7269 */
7270 background=0x00;
7271 foreground=0x80;
7272 if (ximage->format == XYBitmap)
7273 {
7274 background=(unsigned char)
7275 (XPixelIntensity(&pixel_info->foreground_color) <
7276 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7277 foreground=(unsigned char)
7278 (XPixelIntensity(&pixel_info->background_color) <
7279 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7280 if (windows->magnify.depth > 1)
7281 Swap(background,foreground);
7282 }
cristybb503372010-05-27 20:51:26 +00007283 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007284 {
7285 /*
7286 Propogate pixel magnify rows.
7287 */
7288 for (j=0; j < magnify; j++)
7289 {
7290 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7291 ((x*ximage->bits_per_pixel) >> 3);
7292 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7293 q_bit=0;
7294 byte=0;
7295 for (k=0; k < width; k+=magnify)
7296 {
7297 /*
7298 Propogate pixel magnify columns.
7299 */
7300 for (l=0; l < magnify; l++)
7301 {
7302 /*
7303 Propogate each bit plane.
7304 */
7305 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7306 {
7307 byte>>=1;
7308 if (*p & (0x01 << (p_bit+plane)))
7309 byte|=foreground;
7310 else
7311 byte|=background;
7312 q_bit++;
7313 if (q_bit == 8)
7314 {
7315 *q++=byte;
7316 q_bit=0;
7317 byte=0;
7318 }
7319 }
7320 }
7321 p_bit+=ximage->bits_per_pixel;
7322 if (p_bit == 8)
7323 {
7324 p++;
7325 p_bit=0;
7326 }
7327 if (q_bit != 0)
7328 *q=byte >> (8-q_bit);
7329 q+=scanline_pad;
7330 }
7331 }
7332 y++;
7333 }
7334 break;
7335 }
7336 case MSBFirst:
7337 default:
7338 {
7339 /*
7340 Magnify big-endian bitmap.
7341 */
7342 background=0x00;
7343 foreground=0x01;
7344 if (ximage->format == XYBitmap)
7345 {
7346 background=(unsigned char)
7347 (XPixelIntensity(&pixel_info->foreground_color) <
7348 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7349 foreground=(unsigned char)
7350 (XPixelIntensity(&pixel_info->background_color) <
7351 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7352 if (windows->magnify.depth > 1)
7353 Swap(background,foreground);
7354 }
cristybb503372010-05-27 20:51:26 +00007355 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007356 {
7357 /*
7358 Propogate pixel magnify rows.
7359 */
7360 for (j=0; j < magnify; j++)
7361 {
7362 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7363 ((x*ximage->bits_per_pixel) >> 3);
7364 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7365 q_bit=0;
7366 byte=0;
7367 for (k=0; k < width; k+=magnify)
7368 {
7369 /*
7370 Propogate pixel magnify columns.
7371 */
7372 for (l=0; l < magnify; l++)
7373 {
7374 /*
7375 Propogate each bit plane.
7376 */
7377 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7378 {
7379 byte<<=1;
7380 if (*p & (0x80 >> (p_bit+plane)))
7381 byte|=foreground;
7382 else
7383 byte|=background;
7384 q_bit++;
7385 if (q_bit == 8)
7386 {
7387 *q++=byte;
7388 q_bit=0;
7389 byte=0;
7390 }
7391 }
7392 }
7393 p_bit+=ximage->bits_per_pixel;
7394 if (p_bit == 8)
7395 {
7396 p++;
7397 p_bit=0;
7398 }
7399 if (q_bit != 0)
7400 *q=byte << (8-q_bit);
7401 q+=scanline_pad;
7402 }
7403 }
7404 y++;
7405 }
7406 break;
7407 }
7408 }
7409 }
7410 else
7411 switch (ximage->bits_per_pixel)
7412 {
7413 case 6:
7414 case 8:
7415 {
7416 /*
7417 Magnify 8 bit X image.
7418 */
cristybb503372010-05-27 20:51:26 +00007419 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007420 {
7421 /*
7422 Propogate pixel magnify rows.
7423 */
7424 for (j=0; j < magnify; j++)
7425 {
7426 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7427 ((x*ximage->bits_per_pixel) >> 3);
7428 for (k=0; k < width; k+=magnify)
7429 {
7430 /*
7431 Propogate pixel magnify columns.
7432 */
7433 for (l=0; l < magnify; l++)
7434 *q++=(*p);
7435 p++;
7436 }
7437 q+=scanline_pad;
7438 }
7439 y++;
7440 }
7441 break;
7442 }
7443 default:
7444 {
7445 register unsigned int
7446 bytes_per_pixel,
7447 m;
7448
7449 /*
7450 Magnify multi-byte X image.
7451 */
7452 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007453 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007454 {
7455 /*
7456 Propogate pixel magnify rows.
7457 */
7458 for (j=0; j < magnify; j++)
7459 {
7460 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7461 ((x*ximage->bits_per_pixel) >> 3);
7462 for (k=0; k < width; k+=magnify)
7463 {
7464 /*
7465 Propogate pixel magnify columns.
7466 */
7467 for (l=0; l < magnify; l++)
7468 for (m=0; m < bytes_per_pixel; m++)
7469 *q++=(*(p+m));
7470 p+=bytes_per_pixel;
7471 }
7472 q+=scanline_pad;
7473 }
7474 y++;
7475 }
7476 break;
7477 }
7478 }
7479 /*
7480 Copy X image to magnify pixmap.
7481 */
7482 x=windows->magnify.x-((width/magnify) >> 1);
7483 if (x < 0)
7484 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7485 else
7486 if (x > (int) (ximage->width-(width/magnify)))
7487 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7488 else
7489 x=0;
7490 y=windows->magnify.y-((height/magnify) >> 1);
7491 if (y < 0)
7492 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7493 else
7494 if (y > (int) (ximage->height-(height/magnify)))
7495 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7496 else
7497 y=0;
7498 if ((x != 0) || (y != 0))
7499 (void) XFillRectangle(display,windows->magnify.pixmap,
7500 windows->magnify.annotate_context,0,0,width,height);
7501 (void) XPutImage(display,windows->magnify.pixmap,
7502 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7503 height-y);
7504 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7505 (magnify <= (height >> 1))))
7506 {
7507 RectangleInfo
7508 highlight_info;
7509
7510 /*
7511 Highlight center pixel.
7512 */
cristybb503372010-05-27 20:51:26 +00007513 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7514 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007515 highlight_info.width=magnify;
7516 highlight_info.height=magnify;
7517 (void) XDrawRectangle(display,windows->magnify.pixmap,
7518 windows->magnify.highlight_context,(int) highlight_info.x,
7519 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7520 (unsigned int) highlight_info.height-1);
7521 if (magnify > 2)
7522 (void) XDrawRectangle(display,windows->magnify.pixmap,
7523 windows->magnify.annotate_context,(int) highlight_info.x+1,
7524 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7525 (unsigned int) highlight_info.height-3);
7526 }
7527 /*
7528 Show center pixel color.
7529 */
cristy52010022011-10-21 18:07:37 +00007530 (void) GetOneVirtualMagickPixel(windows->image.image,TileVirtualPixelMethod,
7531 (ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007532 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007533 windows->magnify.x,windows->magnify.y);
7534 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007535 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007536 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007537 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007538 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007539 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007540 if (pixel.colorspace == CMYKColorspace)
7541 {
7542 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007543 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007544 }
7545 if (pixel.matte != MagickFalse)
7546 {
7547 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007548 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007549 }
7550 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7551 height=(unsigned int) windows->magnify.font_info->ascent+
7552 windows->magnify.font_info->descent;
7553 x=windows->magnify.font_info->max_bounds.width >> 1;
7554 y=windows->magnify.font_info->ascent+(height >> 2);
7555 (void) XDrawImageString(display,windows->magnify.pixmap,
7556 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7557 GetColorTuple(&pixel,MagickTrue,tuple);
7558 y+=height;
7559 (void) XDrawImageString(display,windows->magnify.pixmap,
7560 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007561 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007562 exception);
cristy3ed852e2009-09-05 21:47:34 +00007563 y+=height;
7564 (void) XDrawImageString(display,windows->magnify.pixmap,
7565 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7566 /*
7567 Refresh magnify window.
7568 */
7569 magnify_window=windows->magnify;
7570 magnify_window.x=0;
7571 magnify_window.y=0;
7572 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7573}
7574
7575/*
7576%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7577% %
7578% %
7579% %
7580% X M a k e P i x m a p %
7581% %
7582% %
7583% %
7584%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7585%
7586% XMakePixmap() creates an X11 pixmap.
7587%
7588% The format of the XMakePixmap method is:
7589%
7590% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7591% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7592% XPixelInfo *pixel)
7593%
7594% A description of each parameter follows:
7595%
7596% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7597%
7598% o display: Specifies a connection to an X server; returned from
7599% XOpenDisplay.
7600%
7601% o window: Specifies a pointer to a XWindowInfo structure.
7602%
cristy3ed852e2009-09-05 21:47:34 +00007603*/
7604static MagickBooleanType XMakePixmap(Display *display,
7605 const XResourceInfo *resource_info,XWindowInfo *window)
7606{
7607 unsigned int
7608 height,
7609 width;
7610
7611 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7612 assert(display != (Display *) NULL);
7613 assert(resource_info != (XResourceInfo *) NULL);
7614 assert(window != (XWindowInfo *) NULL);
7615 if (window->pixmap != (Pixmap) NULL)
7616 {
7617 /*
7618 Destroy previous X pixmap.
7619 */
7620 (void) XFreePixmap(display,window->pixmap);
7621 window->pixmap=(Pixmap) NULL;
7622 }
7623 if (window->use_pixmap == MagickFalse)
7624 return(MagickFalse);
7625 if (window->ximage == (XImage *) NULL)
7626 return(MagickFalse);
7627 /*
7628 Display busy cursor.
7629 */
7630 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7631 (void) XFlush(display);
7632 /*
7633 Create pixmap.
7634 */
7635 width=(unsigned int) window->ximage->width;
7636 height=(unsigned int) window->ximage->height;
7637 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7638 if (window->pixmap == (Pixmap) NULL)
7639 {
7640 /*
7641 Unable to allocate pixmap.
7642 */
7643 (void) XCheckDefineCursor(display,window->id,window->cursor);
7644 return(MagickFalse);
7645 }
7646 /*
7647 Copy X image to pixmap.
7648 */
7649#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7650 if (window->shared_memory)
7651 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7652 window->ximage,0,0,0,0,width,height,MagickTrue);
7653#endif
7654 if (window->shared_memory == MagickFalse)
7655 (void) XPutImage(display,window->pixmap,window->annotate_context,
7656 window->ximage,0,0,0,0,width,height);
7657 if (IsEventLogging())
7658 {
7659 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7660 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7661 width,height);
7662 }
7663 /*
7664 Restore cursor.
7665 */
7666 (void) XCheckDefineCursor(display,window->id,window->cursor);
7667 return(MagickTrue);
7668}
7669
7670/*
7671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7672% %
7673% %
7674% %
7675% X M a k e S t a n d a r d C o l o r m a p %
7676% %
7677% %
7678% %
7679%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7680%
7681% XMakeStandardColormap() creates an X11 Standard Colormap.
7682%
7683% The format of the XMakeStandardColormap method is:
7684%
cristy6710d842011-10-20 23:23:00 +00007685% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7686% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7687% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007688%
7689% A description of each parameter follows:
7690%
7691% o display: Specifies a connection to an X server; returned from
7692% XOpenDisplay.
7693%
7694% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7695% returned from XGetVisualInfo.
7696%
7697% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7698%
7699% o image: the image.
7700%
7701% o map_info: If a Standard Colormap type is specified, this structure is
7702% initialized with info from the Standard Colormap.
7703%
7704% o pixel: Specifies a pointer to a XPixelInfo structure.
7705%
cristy6710d842011-10-20 23:23:00 +00007706% o exception: return any errors or warnings in this structure.
7707%
cristy3ed852e2009-09-05 21:47:34 +00007708*/
7709
7710#if defined(__cplusplus) || defined(c_plusplus)
7711extern "C" {
7712#endif
7713
7714static inline MagickRealType DiversityPixelIntensity(
7715 const DiversityPacket *pixel)
7716{
7717 MagickRealType
7718 intensity;
7719
7720 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7721 return(intensity);
7722}
7723
7724static int IntensityCompare(const void *x,const void *y)
7725{
7726 DiversityPacket
7727 *color_1,
7728 *color_2;
7729
7730 int
7731 diversity;
7732
7733 color_1=(DiversityPacket *) x;
7734 color_2=(DiversityPacket *) y;
7735 diversity=(int) (DiversityPixelIntensity(color_2)-
7736 DiversityPixelIntensity(color_1));
7737 return(diversity);
7738}
7739
7740static int PopularityCompare(const void *x,const void *y)
7741{
7742 DiversityPacket
7743 *color_1,
7744 *color_2;
7745
7746 color_1=(DiversityPacket *) x;
7747 color_2=(DiversityPacket *) y;
7748 return((int) color_2->count-(int) color_1->count);
7749}
7750
7751#if defined(__cplusplus) || defined(c_plusplus)
7752}
7753#endif
7754
cristybb503372010-05-27 20:51:26 +00007755static inline Quantum ScaleXToQuantum(const size_t x,
7756 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007757{
7758 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7759}
7760
cristybcbda3f2011-09-03 13:01:22 +00007761MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007762 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007763 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007764{
7765 Colormap
7766 colormap;
7767
cristybb503372010-05-27 20:51:26 +00007768 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007769 i;
7770
7771 Status
7772 status;
7773
cristybb503372010-05-27 20:51:26 +00007774 size_t
cristy3ed852e2009-09-05 21:47:34 +00007775 number_colors,
7776 retain_colors;
7777
7778 unsigned short
7779 gray_value;
7780
7781 XColor
7782 color,
7783 *colors,
7784 *p;
7785
7786 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7787 assert(display != (Display *) NULL);
7788 assert(visual_info != (XVisualInfo *) NULL);
7789 assert(map_info != (XStandardColormap *) NULL);
7790 assert(resource_info != (XResourceInfo *) NULL);
7791 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007792 if (resource_info->map_type != (char *) NULL)
7793 {
7794 /*
7795 Standard Colormap is already defined (i.e. xstdcmap).
7796 */
cristy4c08aed2011-07-01 19:47:50 +00007797 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007798 pixel);
7799 number_colors=(unsigned int) (map_info->base_pixel+
7800 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7801 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7802 if ((image->matte == MagickFalse) &&
7803 (resource_info->color_recovery == MagickFalse) &&
7804 resource_info->quantize_info->dither &&
7805 (number_colors < MaxColormapSize))
7806 {
7807 Image
7808 *affinity_image;
7809
cristy4c08aed2011-07-01 19:47:50 +00007810 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007811 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007812
7813 /*
7814 Improve image appearance with error diffusion.
7815 */
cristy6710d842011-10-20 23:23:00 +00007816 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007817 if (affinity_image == (Image *) NULL)
7818 ThrowXWindowFatalException(ResourceLimitFatalError,
7819 "UnableToDitherImage",image->filename);
7820 affinity_image->columns=number_colors;
7821 affinity_image->rows=1;
7822 /*
7823 Initialize colormap image.
7824 */
7825 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7826 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007827 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007828 {
cristybb503372010-05-27 20:51:26 +00007829 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007830 {
cristy4c08aed2011-07-01 19:47:50 +00007831 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007832 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007833 SetPixelRed(affinity_image,
7834 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7835 map_info->red_max),q);
7836 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007837 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007838 SetPixelGreen(affinity_image,
7839 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7840 (map_info->green_max+1)),map_info->green_max),q);
7841 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007842 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007843 SetPixelBlue(affinity_image,
7844 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7845 map_info->blue_max),q);
7846 SetPixelAlpha(affinity_image,
7847 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007848 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007849 }
7850 (void) SyncAuthenticPixels(affinity_image,exception);
7851 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007852 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007853 }
cristy4c08aed2011-07-01 19:47:50 +00007854 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007855 pixel);
cristy574cc262011-08-05 01:23:58 +00007856 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007857 affinity_image=DestroyImage(affinity_image);
7858 }
7859 if (IsEventLogging())
7860 {
7861 (void) LogMagickEvent(X11Event,GetMagickModule(),
7862 "Standard Colormap:");
7863 (void) LogMagickEvent(X11Event,GetMagickModule(),
7864 " colormap id: 0x%lx",map_info->colormap);
7865 (void) LogMagickEvent(X11Event,GetMagickModule(),
7866 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7867 map_info->green_max,map_info->blue_max);
7868 (void) LogMagickEvent(X11Event,GetMagickModule(),
7869 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7870 map_info->green_mult,map_info->blue_mult);
7871 }
7872 return;
7873 }
7874 if ((visual_info->klass != DirectColor) &&
7875 (visual_info->klass != TrueColor))
7876 if ((image->storage_class == DirectClass) ||
7877 ((int) image->colors > visual_info->colormap_size))
7878 {
7879 QuantizeInfo
7880 quantize_info;
7881
7882 /*
7883 Image has more colors than the visual supports.
7884 */
7885 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007886 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007887 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007888 }
7889 /*
7890 Free previous and create new colormap.
7891 */
7892 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7893 colormap=XDefaultColormap(display,visual_info->screen);
7894 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7895 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7896 visual_info->visual,visual_info->klass == DirectColor ?
7897 AllocAll : AllocNone);
7898 if (colormap == (Colormap) NULL)
7899 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7900 image->filename);
7901 /*
7902 Initialize the map and pixel info structures.
7903 */
7904 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007905 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007906 /*
7907 Allocating colors in server colormap is based on visual class.
7908 */
7909 switch (visual_info->klass)
7910 {
7911 case StaticGray:
7912 case StaticColor:
7913 {
7914 /*
7915 Define Standard Colormap for StaticGray or StaticColor visual.
7916 */
7917 number_colors=image->colors;
7918 colors=(XColor *) AcquireQuantumMemory((size_t)
7919 visual_info->colormap_size,sizeof(*colors));
7920 if (colors == (XColor *) NULL)
7921 ThrowXWindowFatalException(ResourceLimitFatalError,
7922 "UnableToCreateColormap",image->filename);
7923 p=colors;
7924 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007925 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007926 {
7927 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7928 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7929 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7930 if (visual_info->klass != StaticColor)
7931 {
7932 gray_value=(unsigned short) XPixelIntensity(&color);
7933 color.red=gray_value;
7934 color.green=gray_value;
7935 color.blue=gray_value;
7936 }
7937 status=XAllocColor(display,colormap,&color);
7938 if (status == False)
7939 {
7940 colormap=XCopyColormapAndFree(display,colormap);
7941 (void) XAllocColor(display,colormap,&color);
7942 }
7943 pixel->pixels[i]=color.pixel;
7944 *p++=color;
7945 }
7946 break;
7947 }
7948 case GrayScale:
7949 case PseudoColor:
7950 {
7951 unsigned int
7952 colormap_type;
7953
7954 /*
7955 Define Standard Colormap for GrayScale or PseudoColor visual.
7956 */
7957 number_colors=image->colors;
7958 colors=(XColor *) AcquireQuantumMemory((size_t)
7959 visual_info->colormap_size,sizeof(*colors));
7960 if (colors == (XColor *) NULL)
7961 ThrowXWindowFatalException(ResourceLimitFatalError,
7962 "UnableToCreateColormap",image->filename);
7963 /*
7964 Preallocate our GUI colors.
7965 */
7966 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7967 (void) XAllocColor(display,colormap,&pixel->background_color);
7968 (void) XAllocColor(display,colormap,&pixel->border_color);
7969 (void) XAllocColor(display,colormap,&pixel->matte_color);
7970 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7971 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7972 (void) XAllocColor(display,colormap,&pixel->depth_color);
7973 (void) XAllocColor(display,colormap,&pixel->trough_color);
7974 for (i=0; i < MaxNumberPens; i++)
7975 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7976 /*
7977 Determine if image colors will "fit" into X server colormap.
7978 */
7979 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007980 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007981 NULL,0,pixel->pixels,(unsigned int) image->colors);
7982 if (status != False)
7983 colormap_type=PrivateColormap;
7984 if (colormap_type == SharedColormap)
7985 {
cristyc57f6942010-11-12 01:47:39 +00007986 CacheView
7987 *image_view;
7988
cristy3ed852e2009-09-05 21:47:34 +00007989 DiversityPacket
7990 *diversity;
7991
7992 int
7993 y;
7994
7995 register int
7996 x;
7997
7998 unsigned short
7999 index;
8000
8001 XColor
8002 *server_colors;
8003
8004 /*
8005 Define Standard colormap for shared GrayScale or PseudoColor visual.
8006 */
8007 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
8008 sizeof(*diversity));
8009 if (diversity == (DiversityPacket *) NULL)
8010 ThrowXWindowFatalException(ResourceLimitFatalError,
8011 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00008012 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008013 {
8014 diversity[i].red=image->colormap[i].red;
8015 diversity[i].green=image->colormap[i].green;
8016 diversity[i].blue=image->colormap[i].blue;
8017 diversity[i].index=(unsigned short) i;
8018 diversity[i].count=0;
8019 }
cristyc57f6942010-11-12 01:47:39 +00008020 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00008021 for (y=0; y < (int) image->rows; y++)
8022 {
cristyc57f6942010-11-12 01:47:39 +00008023 register int
cristy3ed852e2009-09-05 21:47:34 +00008024 x;
8025
cristy4c08aed2011-07-01 19:47:50 +00008026 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00008027 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00008028
cristyc57f6942010-11-12 01:47:39 +00008029 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8030 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008031 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008032 break;
cristyc57f6942010-11-12 01:47:39 +00008033 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008034 {
8035 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008036 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008037 }
cristy3ed852e2009-09-05 21:47:34 +00008038 }
cristyc57f6942010-11-12 01:47:39 +00008039 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008040 /*
8041 Sort colors by decreasing intensity.
8042 */
8043 qsort((void *) diversity,image->colors,sizeof(*diversity),
8044 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008045 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008046 {
8047 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008048 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008049 }
8050 diversity[image->colors-1].count<<=4;
8051 qsort((void *) diversity,image->colors,sizeof(*diversity),
8052 PopularityCompare);
8053 /*
8054 Allocate colors.
8055 */
8056 p=colors;
8057 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008058 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008059 {
8060 index=diversity[i].index;
8061 color.red=
8062 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8063 color.green=
8064 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8065 color.blue=
8066 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8067 if (visual_info->klass != PseudoColor)
8068 {
8069 gray_value=(unsigned short) XPixelIntensity(&color);
8070 color.red=gray_value;
8071 color.green=gray_value;
8072 color.blue=gray_value;
8073 }
8074 status=XAllocColor(display,colormap,&color);
8075 if (status == False)
8076 break;
8077 pixel->pixels[index]=color.pixel;
8078 *p++=color;
8079 }
8080 /*
8081 Read X server colormap.
8082 */
8083 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8084 visual_info->colormap_size,sizeof(*server_colors));
8085 if (server_colors == (XColor *) NULL)
8086 ThrowXWindowFatalException(ResourceLimitFatalError,
8087 "UnableToCreateColormap",image->filename);
8088 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008089 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008090 (void) XQueryColors(display,colormap,server_colors,
8091 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8092 /*
8093 Select remaining colors from X server colormap.
8094 */
cristybb503372010-05-27 20:51:26 +00008095 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008096 {
8097 index=diversity[i].index;
8098 color.red=
8099 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8100 color.green=
8101 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8102 color.blue=
8103 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8104 if (visual_info->klass != PseudoColor)
8105 {
8106 gray_value=(unsigned short) XPixelIntensity(&color);
8107 color.red=gray_value;
8108 color.green=gray_value;
8109 color.blue=gray_value;
8110 }
8111 XBestPixel(display,colormap,server_colors,(unsigned int)
8112 visual_info->colormap_size,&color);
8113 pixel->pixels[index]=color.pixel;
8114 *p++=color;
8115 }
8116 if ((int) image->colors < visual_info->colormap_size)
8117 {
8118 /*
8119 Fill up colors array-- more choices for pen colors.
8120 */
8121 retain_colors=MagickMin((unsigned int)
8122 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008123 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008124 *p++=server_colors[i];
8125 number_colors+=retain_colors;
8126 }
8127 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8128 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8129 break;
8130 }
8131 /*
8132 Define Standard colormap for private GrayScale or PseudoColor visual.
8133 */
8134 if (status == False)
8135 {
8136 /*
8137 Not enough colormap entries in the colormap-- Create a new colormap.
8138 */
8139 colormap=XCreateColormap(display,
8140 XRootWindow(display,visual_info->screen),visual_info->visual,
8141 AllocNone);
8142 if (colormap == (Colormap) NULL)
8143 ThrowXWindowFatalException(ResourceLimitFatalError,
8144 "UnableToCreateColormap",image->filename);
8145 map_info->colormap=colormap;
8146 if ((int) image->colors < visual_info->colormap_size)
8147 {
8148 /*
8149 Retain colors from the default colormap to help lessens the
8150 effects of colormap flashing.
8151 */
8152 retain_colors=MagickMin((unsigned int)
8153 (visual_info->colormap_size-image->colors),256);
8154 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008155 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008156 {
cristyc57f6942010-11-12 01:47:39 +00008157 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008158 p++;
8159 }
8160 (void) XQueryColors(display,
8161 XDefaultColormap(display,visual_info->screen),
8162 colors+image->colors,(int) retain_colors);
8163 /*
8164 Transfer colors from default to private colormap.
8165 */
8166 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008167 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008168 retain_colors);
8169 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008170 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008171 {
8172 p->pixel=pixel->pixels[i];
8173 p++;
8174 }
8175 (void) XStoreColors(display,colormap,colors+image->colors,
8176 (int) retain_colors);
8177 number_colors+=retain_colors;
8178 }
8179 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008180 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008181 image->colors);
8182 }
8183 /*
8184 Store the image colormap.
8185 */
8186 p=colors;
8187 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008188 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008189 {
8190 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8191 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8192 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8193 if (visual_info->klass != PseudoColor)
8194 {
8195 gray_value=(unsigned short) XPixelIntensity(&color);
8196 color.red=gray_value;
8197 color.green=gray_value;
8198 color.blue=gray_value;
8199 }
8200 color.pixel=pixel->pixels[i];
8201 *p++=color;
8202 }
8203 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8204 break;
8205 }
8206 case TrueColor:
8207 case DirectColor:
8208 default:
8209 {
8210 MagickBooleanType
8211 linear_colormap;
8212
8213 /*
8214 Define Standard Colormap for TrueColor or DirectColor visual.
8215 */
8216 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8217 (map_info->green_max*map_info->green_mult)+
8218 (map_info->blue_max*map_info->blue_mult)+1);
8219 linear_colormap=(number_colors > 4096) ||
8220 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8221 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8222 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8223 MagickTrue : MagickFalse;
8224 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008225 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008226 /*
8227 Allocate color array.
8228 */
8229 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8230 if (colors == (XColor *) NULL)
8231 ThrowXWindowFatalException(ResourceLimitFatalError,
8232 "UnableToCreateColormap",image->filename);
8233 /*
8234 Initialize linear color ramp.
8235 */
8236 p=colors;
8237 color.flags=(char) (DoRed | DoGreen | DoBlue);
8238 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008239 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008240 {
8241 color.blue=(unsigned short) 0;
8242 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008243 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008244 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8245 color.green=color.blue;
8246 color.red=color.blue;
8247 color.pixel=XStandardPixel(map_info,&color);
8248 *p++=color;
8249 }
8250 else
cristybb503372010-05-27 20:51:26 +00008251 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008252 {
8253 color.red=(unsigned short) 0;
8254 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008255 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008256 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8257 color.green=(unsigned int) 0;
8258 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008259 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008260 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8261 map_info->green_max));
8262 color.blue=(unsigned short) 0;
8263 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008264 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008265 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8266 color.pixel=XStandardPixel(map_info,&color);
8267 *p++=color;
8268 }
8269 if ((visual_info->klass == DirectColor) &&
8270 (colormap != XDefaultColormap(display,visual_info->screen)))
8271 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8272 else
cristybb503372010-05-27 20:51:26 +00008273 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008274 (void) XAllocColor(display,colormap,&colors[i]);
8275 break;
8276 }
8277 }
8278 if ((visual_info->klass != DirectColor) &&
8279 (visual_info->klass != TrueColor))
8280 {
8281 /*
8282 Set foreground, background, border, etc. pixels.
8283 */
8284 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8285 &pixel->foreground_color);
8286 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8287 &pixel->background_color);
8288 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8289 {
8290 /*
8291 Foreground and background colors must differ.
8292 */
8293 pixel->background_color.red=(~pixel->foreground_color.red);
8294 pixel->background_color.green=
8295 (~pixel->foreground_color.green);
8296 pixel->background_color.blue=
8297 (~pixel->foreground_color.blue);
8298 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8299 &pixel->background_color);
8300 }
8301 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8302 &pixel->border_color);
8303 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8304 &pixel->matte_color);
8305 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8306 &pixel->highlight_color);
8307 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8308 &pixel->shadow_color);
8309 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8310 &pixel->depth_color);
8311 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8312 &pixel->trough_color);
8313 for (i=0; i < MaxNumberPens; i++)
8314 {
8315 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8316 &pixel->pen_colors[i]);
8317 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8318 }
cristyc57f6942010-11-12 01:47:39 +00008319 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008320 }
8321 colors=(XColor *) RelinquishMagickMemory(colors);
8322 if (IsEventLogging())
8323 {
8324 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8325 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8326 map_info->colormap);
8327 (void) LogMagickEvent(X11Event,GetMagickModule(),
8328 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8329 map_info->green_max,map_info->blue_max);
8330 (void) LogMagickEvent(X11Event,GetMagickModule(),
8331 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8332 map_info->green_mult,map_info->blue_mult);
8333 }
8334}
8335
8336/*
8337%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8338% %
8339% %
8340% %
8341% X M a k e W i n d o w %
8342% %
8343% %
8344% %
8345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8346%
8347% XMakeWindow() creates an X11 window.
8348%
8349% The format of the XMakeWindow method is:
8350%
8351% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8352% XClassHint *class_hint,XWMHints *manager_hints,
8353% XWindowInfo *window_info)
8354%
8355% A description of each parameter follows:
8356%
8357% o display: Specifies a connection to an X server; returned from
8358% XOpenDisplay.
8359%
8360% o parent: Specifies the parent window_info.
8361%
8362% o argv: Specifies the application's argument list.
8363%
8364% o argc: Specifies the number of arguments.
8365%
8366% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8367%
8368% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8369%
8370% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8371%
8372*/
cristybcbda3f2011-09-03 13:01:22 +00008373MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008374 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8375 XWindowInfo *window_info)
8376{
8377#define MinWindowSize 64
8378
8379 Atom
8380 atom_list[2];
8381
8382 int
8383 gravity;
8384
8385 static XTextProperty
8386 icon_name,
8387 window_name;
8388
8389 Status
8390 status;
8391
8392 XSizeHints
8393 *size_hints;
8394
8395 /*
8396 Set window info hints.
8397 */
8398 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8399 assert(display != (Display *) NULL);
8400 assert(window_info != (XWindowInfo *) NULL);
8401 size_hints=XAllocSizeHints();
8402 if (size_hints == (XSizeHints *) NULL)
8403 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008404 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008405 size_hints->x=window_info->x;
8406 size_hints->y=window_info->y;
8407 size_hints->width=(int) window_info->width;
8408 size_hints->height=(int) window_info->height;
8409 if (window_info->immutable != MagickFalse)
8410 {
8411 /*
8412 Window size cannot be changed.
8413 */
8414 size_hints->min_width=size_hints->width;
8415 size_hints->min_height=size_hints->height;
8416 size_hints->max_width=size_hints->width;
8417 size_hints->max_height=size_hints->height;
8418 size_hints->flags|=PMinSize;
8419 size_hints->flags|=PMaxSize;
8420 }
8421 else
8422 {
8423 /*
8424 Window size can be changed.
8425 */
8426 size_hints->min_width=(int) window_info->min_width;
8427 size_hints->min_height=(int) window_info->min_height;
8428 size_hints->flags|=PResizeInc;
8429 size_hints->width_inc=(int) window_info->width_inc;
8430 size_hints->height_inc=(int) window_info->height_inc;
8431#if !defined(PRE_R4_ICCCM)
8432 size_hints->flags|=PBaseSize;
8433 size_hints->base_width=size_hints->width_inc;
8434 size_hints->base_height=size_hints->height_inc;
8435#endif
8436 }
8437 gravity=NorthWestGravity;
8438 if (window_info->geometry != (char *) NULL)
8439 {
8440 char
8441 default_geometry[MaxTextExtent],
8442 geometry[MaxTextExtent];
8443
8444 int
8445 flags;
8446
8447 register char
8448 *p;
8449
8450 /*
8451 User specified geometry.
8452 */
cristyb51dff52011-05-19 16:55:47 +00008453 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008454 size_hints->width,size_hints->height);
8455 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8456 p=geometry;
8457 while (strlen(p) != 0)
8458 {
8459 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8460 p++;
8461 else
8462 (void) CopyMagickString(p,p+1,MaxTextExtent);
8463 }
8464 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8465 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8466 &size_hints->width,&size_hints->height,&gravity);
8467 if ((flags & WidthValue) && (flags & HeightValue))
8468 size_hints->flags|=USSize;
8469 if ((flags & XValue) && (flags & YValue))
8470 {
8471 size_hints->flags|=USPosition;
8472 window_info->x=size_hints->x;
8473 window_info->y=size_hints->y;
8474 }
8475 }
8476#if !defined(PRE_R4_ICCCM)
8477 size_hints->win_gravity=gravity;
8478 size_hints->flags|=PWinGravity;
8479#endif
8480 if (window_info->id == (Window) NULL)
8481 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8482 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8483 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008484 window_info->visual,(unsigned long) window_info->mask,
8485 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008486 else
8487 {
8488 MagickStatusType
8489 mask;
8490
8491 XEvent
8492 sans_event;
8493
8494 XWindowChanges
8495 window_changes;
8496
8497 /*
8498 Window already exists; change relevant attributes.
8499 */
cristyc57f6942010-11-12 01:47:39 +00008500 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8501 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008502 mask=ConfigureNotify;
8503 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8504 window_changes.x=window_info->x;
8505 window_changes.y=window_info->y;
8506 window_changes.width=(int) window_info->width;
8507 window_changes.height=(int) window_info->height;
8508 mask=(MagickStatusType) (CWWidth | CWHeight);
8509 if (window_info->flags & USPosition)
8510 mask|=CWX | CWY;
8511 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8512 mask,&window_changes);
8513 }
8514 if (window_info->id == (Window) NULL)
8515 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8516 window_info->name);
8517 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8518 if (status == False)
8519 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8520 window_info->name);
8521 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8522 if (status == False)
8523 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8524 window_info->icon_name);
8525 if (window_info->icon_geometry != (char *) NULL)
8526 {
8527 int
8528 flags,
8529 height,
8530 width;
8531
8532 /*
8533 User specified icon geometry.
8534 */
8535 size_hints->flags|=USPosition;
8536 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8537 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8538 &manager_hints->icon_y,&width,&height,&gravity);
8539 if ((flags & XValue) && (flags & YValue))
8540 manager_hints->flags|=IconPositionHint;
8541 }
8542 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8543 size_hints,manager_hints,class_hint);
8544 if (window_name.value != (void *) NULL)
8545 {
8546 (void) XFree((void *) window_name.value);
8547 window_name.value=(unsigned char *) NULL;
8548 window_name.nitems=0;
8549 }
8550 if (icon_name.value != (void *) NULL)
8551 {
8552 (void) XFree((void *) icon_name.value);
8553 icon_name.value=(unsigned char *) NULL;
8554 icon_name.nitems=0;
8555 }
8556 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8557 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8558 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8559 (void) XFree((void *) size_hints);
8560 if (window_info->shape != MagickFalse)
8561 {
8562#if defined(MAGICKCORE_HAVE_SHAPE)
8563 int
8564 error_base,
8565 event_base;
8566
8567 /*
8568 Can we apply a non-rectangular shaping mask?
8569 */
8570 error_base=0;
8571 event_base=0;
8572 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8573 window_info->shape=MagickFalse;
8574#else
8575 window_info->shape=MagickFalse;
8576#endif
8577 }
8578 if (window_info->shared_memory)
8579 {
8580#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8581 /*
8582 Can we use shared memory with this window?
8583 */
8584 if (XShmQueryExtension(display) == 0)
8585 window_info->shared_memory=MagickFalse;
8586#else
8587 window_info->shared_memory=MagickFalse;
8588#endif
8589 }
8590 window_info->image=NewImageList();
8591 window_info->destroy=MagickFalse;
8592}
8593
8594/*
8595%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8596% %
8597% %
8598% %
8599% X M a g i c k P r o g r e s s M o n i t o r %
8600% %
8601% %
8602% %
8603%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8604%
8605% XMagickProgressMonitor() displays the progress a task is making in
8606% completing a task.
8607%
8608% The format of the XMagickProgressMonitor method is:
8609%
8610% void XMagickProgressMonitor(const char *task,
8611% const MagickOffsetType quantum,const MagickSizeType span,
8612% void *client_data)
8613%
8614% A description of each parameter follows:
8615%
8616% o task: Identifies the task in progress.
8617%
8618% o quantum: Specifies the quantum position within the span which represents
8619% how much progress has been made in completing a task.
8620%
8621% o span: Specifies the span relative to completing a task.
8622%
8623% o client_data: Pointer to any client data.
8624%
8625*/
8626
8627static const char *GetLocaleMonitorMessage(const char *text)
8628{
8629 char
8630 message[MaxTextExtent],
8631 tag[MaxTextExtent];
8632
8633 const char
8634 *locale_message;
8635
8636 register char
8637 *p;
8638
8639 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8640 p=strrchr(tag,'/');
8641 if (p != (char *) NULL)
8642 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008643 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008644 locale_message=GetLocaleMessage(message);
8645 if (locale_message == message)
8646 return(text);
8647 return(locale_message);
8648}
8649
cristybcbda3f2011-09-03 13:01:22 +00008650MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008651 const MagickOffsetType quantum,const MagickSizeType span,
8652 void *magick_unused(client_data))
8653{
8654 XWindows
8655 *windows;
8656
8657 windows=XSetWindows((XWindows *) ~0);
8658 if (windows == (XWindows *) NULL)
8659 return(MagickTrue);
8660 if (windows->info.mapped != MagickFalse)
8661 XProgressMonitorWidget(windows->display,windows,
8662 GetLocaleMonitorMessage(tag),quantum,span);
8663 return(MagickTrue);
8664}
8665
8666/*
8667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8668% %
8669% %
8670% %
8671% X Q u e r y C o l o r D a t a b a s e %
8672% %
8673% %
8674% %
8675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8676%
cristy9950d572011-10-01 18:22:35 +00008677% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008678% string.
8679%
8680% The format of the XQueryColorDatabase method is:
8681%
cristy9950d572011-10-01 18:22:35 +00008682% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008683%
8684% A description of each parameter follows:
8685%
8686% o target: Specifies the color to lookup in the X color database.
8687%
cristy101ab702011-10-13 13:06:32 +00008688% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008689% color is returned as this value.
8690%
8691*/
cristy9950d572011-10-01 18:22:35 +00008692MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008693 XColor *color)
8694{
8695 Colormap
8696 colormap;
8697
8698 static Display
8699 *display = (Display *) NULL;
8700
8701 Status
8702 status;
8703
8704 XColor
8705 xcolor;
8706
8707 /*
8708 Initialize color return value.
8709 */
8710 assert(color != (XColor *) NULL);
8711 color->red=0;
8712 color->green=0;
8713 color->blue=0;
8714 color->flags=(char) (DoRed | DoGreen | DoBlue);
8715 if ((target == (char *) NULL) || (*target == '\0'))
8716 target="#ffffffffffff";
8717 /*
8718 Let the X server define the color for us.
8719 */
8720 if (display == (Display *) NULL)
8721 display=XOpenDisplay((char *) NULL);
8722 if (display == (Display *) NULL)
8723 {
8724 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8725 return(MagickFalse);
8726 }
8727 colormap=XDefaultColormap(display,XDefaultScreen(display));
8728 status=XParseColor(display,colormap,(char *) target,&xcolor);
8729 if (status == False)
8730 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8731 else
8732 {
8733 color->red=xcolor.red;
8734 color->green=xcolor.green;
8735 color->blue=xcolor.blue;
8736 color->flags=xcolor.flags;
8737 }
8738 return(status != False ? MagickTrue : MagickFalse);
8739}
8740
8741/*
8742%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8743% %
8744% %
8745% %
8746% X Q u e r y P o s i t i o n %
8747% %
8748% %
8749% %
8750%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8751%
8752% XQueryPosition() gets the pointer coordinates relative to a window.
8753%
8754% The format of the XQueryPosition method is:
8755%
8756% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8757%
8758% A description of each parameter follows:
8759%
8760% o display: Specifies a connection to an X server; returned from
8761% XOpenDisplay.
8762%
8763% o window: Specifies a pointer to a Window.
8764%
8765% o x: Return the x coordinate of the pointer relative to the origin of the
8766% window.
8767%
8768% o y: Return the y coordinate of the pointer relative to the origin of the
8769% window.
8770%
8771*/
cristybcbda3f2011-09-03 13:01:22 +00008772MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008773{
8774 int
8775 x_root,
8776 y_root;
8777
8778 unsigned int
8779 mask;
8780
8781 Window
8782 root_window;
8783
8784 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8785 assert(display != (Display *) NULL);
8786 assert(window != (Window) NULL);
8787 assert(x != (int *) NULL);
8788 assert(y != (int *) NULL);
8789 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8790 x,y,&mask);
8791}
8792
8793/*
8794%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8795% %
8796% %
8797% %
8798% X R e f r e s h W i n d o w %
8799% %
8800% %
8801% %
8802%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8803%
8804% XRefreshWindow() refreshes an image in a X window.
8805%
8806% The format of the XRefreshWindow method is:
8807%
8808% void XRefreshWindow(Display *display,const XWindowInfo *window,
8809% const XEvent *event)
8810%
8811% A description of each parameter follows:
8812%
8813% o display: Specifies a connection to an X server; returned from
8814% XOpenDisplay.
8815%
8816% o window: Specifies a pointer to a XWindowInfo structure.
8817%
8818% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8819% the entire image is refreshed.
8820%
8821*/
cristybcbda3f2011-09-03 13:01:22 +00008822MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008823 const XEvent *event)
8824{
8825 int
8826 x,
8827 y;
8828
8829 unsigned int
8830 height,
8831 width;
8832
8833 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8834 assert(display != (Display *) NULL);
8835 assert(window != (XWindowInfo *) NULL);
8836 if (window->ximage == (XImage *) NULL)
8837 return;
8838 if (event != (XEvent *) NULL)
8839 {
8840 /*
8841 Determine geometry from expose event.
8842 */
8843 x=event->xexpose.x;
8844 y=event->xexpose.y;
8845 width=(unsigned int) event->xexpose.width;
8846 height=(unsigned int) event->xexpose.height;
8847 }
8848 else
8849 {
8850 XEvent
8851 sans_event;
8852
8853 /*
8854 Refresh entire window; discard outstanding expose events.
8855 */
8856 x=0;
8857 y=0;
8858 width=window->width;
8859 height=window->height;
8860 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008861 if (window->matte_pixmap != (Pixmap) NULL)
8862 {
8863#if defined(MAGICKCORE_HAVE_SHAPE)
8864 if (window->shape != MagickFalse)
8865 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8866 window->matte_pixmap,ShapeSet);
8867#endif
8868 }
cristy3ed852e2009-09-05 21:47:34 +00008869 }
8870 /*
8871 Check boundary conditions.
8872 */
8873 if ((window->ximage->width-(x+window->x)) < (int) width)
8874 width=(unsigned int) (window->ximage->width-(x+window->x));
8875 if ((window->ximage->height-(y+window->y)) < (int) height)
8876 height=(unsigned int) (window->ximage->height-(y+window->y));
8877 /*
8878 Refresh image.
8879 */
8880 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008881 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008882 if (window->pixmap != (Pixmap) NULL)
8883 {
8884 if (window->depth > 1)
8885 (void) XCopyArea(display,window->pixmap,window->id,
8886 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8887 else
8888 (void) XCopyPlane(display,window->pixmap,window->id,
8889 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8890 1L);
8891 }
8892 else
8893 {
8894#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8895 if (window->shared_memory)
8896 (void) XShmPutImage(display,window->id,window->annotate_context,
8897 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8898#endif
8899 if (window->shared_memory == MagickFalse)
8900 (void) XPutImage(display,window->id,window->annotate_context,
8901 window->ximage,x+window->x,y+window->y,x,y,width,height);
8902 }
8903 if (window->matte_pixmap != (Pixmap) NULL)
8904 (void) XSetClipMask(display,window->annotate_context,None);
8905 (void) XFlush(display);
8906}
8907
8908/*
8909%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8910% %
8911% %
8912% %
8913% X R e m o t e C o m m a n d %
8914% %
8915% %
8916% %
8917%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8918%
8919% XRemoteCommand() forces a remote display(1) to display the specified
8920% image filename.
8921%
8922% The format of the XRemoteCommand method is:
8923%
8924% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8925% const char *filename)
8926%
8927% A description of each parameter follows:
8928%
8929% o display: Specifies a connection to an X server; returned from
8930% XOpenDisplay.
8931%
8932% o window: Specifies the name or id of an X window.
8933%
8934% o filename: the name of the image filename to display.
8935%
8936*/
8937MagickExport MagickBooleanType XRemoteCommand(Display *display,
8938 const char *window,const char *filename)
8939{
8940 Atom
8941 remote_atom;
8942
8943 Window
8944 remote_window,
8945 root_window;
8946
8947 assert(filename != (char *) NULL);
8948 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8949 if (display == (Display *) NULL)
8950 display=XOpenDisplay((char *) NULL);
8951 if (display == (Display *) NULL)
8952 {
8953 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8954 return(MagickFalse);
8955 }
8956 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8957 remote_window=(Window) NULL;
8958 root_window=XRootWindow(display,XDefaultScreen(display));
8959 if (window != (char *) NULL)
8960 {
8961 /*
8962 Search window hierarchy and identify any clients by name or ID.
8963 */
8964 if (isdigit((unsigned char) *window) != 0)
8965 remote_window=XWindowByID(display,root_window,(Window)
8966 strtol((char *) window,(char **) NULL,0));
8967 if (remote_window == (Window) NULL)
8968 remote_window=XWindowByName(display,root_window,window);
8969 }
8970 if (remote_window == (Window) NULL)
8971 remote_window=XWindowByProperty(display,root_window,remote_atom);
8972 if (remote_window == (Window) NULL)
8973 {
8974 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8975 filename);
8976 return(MagickFalse);
8977 }
8978 /*
8979 Send remote command.
8980 */
8981 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8982 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8983 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8984 (void) XSync(display,MagickFalse);
8985 return(MagickTrue);
8986}
8987
8988/*
8989%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8990% %
8991% %
8992% %
8993% X R e t a i n W i n d o w C o l o r s %
8994% %
8995% %
8996% %
8997%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8998%
8999% XRetainWindowColors() sets X11 color resources on a window. This preserves
9000% the colors associated with an image displayed on the window.
9001%
9002% The format of the XRetainWindowColors method is:
9003%
9004% void XRetainWindowColors(Display *display,const Window window)
9005%
9006% A description of each parameter follows:
9007%
9008% o display: Specifies a connection to an X server; returned from
9009% XOpenDisplay.
9010%
9011% o window: Specifies a pointer to a XWindowInfo structure.
9012%
9013*/
9014MagickExport void XRetainWindowColors(Display *display,const Window window)
9015{
9016 Atom
9017 property;
9018
9019 Pixmap
9020 pixmap;
9021
9022 /*
9023 Put property on the window.
9024 */
9025 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9026 assert(display != (Display *) NULL);
9027 assert(window != (Window) NULL);
9028 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9029 if (property == (Atom) NULL)
9030 {
9031 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9032 "_XSETROOT_ID");
9033 return;
9034 }
9035 pixmap=XCreatePixmap(display,window,1,1,1);
9036 if (pixmap == (Pixmap) NULL)
9037 {
9038 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9039 return;
9040 }
9041 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9042 (unsigned char *) &pixmap,1);
9043 (void) XSetCloseDownMode(display,RetainPermanent);
9044}
9045
9046/*
9047%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9048% %
9049% %
9050% %
9051% X S e l e c t W i n d o w %
9052% %
9053% %
9054% %
9055%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9056%
9057% XSelectWindow() allows a user to select a window using the mouse. If the
9058% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9059% is returned in the crop_info structure.
9060%
9061% The format of the XSelectWindow function is:
9062%
9063% target_window=XSelectWindow(display,crop_info)
9064%
9065% A description of each parameter follows:
9066%
9067% o window: XSelectWindow returns the window id.
9068%
9069% o display: Specifies a pointer to the Display structure; returned from
9070% XOpenDisplay.
9071%
9072% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9073% contains the extents of any cropping rectangle.
9074%
cristy3ed852e2009-09-05 21:47:34 +00009075*/
9076static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9077{
9078#define MinimumCropArea (unsigned int) 9
9079
9080 Cursor
9081 target_cursor;
9082
9083 GC
9084 annotate_context;
9085
9086 int
9087 presses,
9088 x_offset,
9089 y_offset;
9090
9091 Status
9092 status;
9093
9094 Window
9095 root_window,
9096 target_window;
9097
9098 XEvent
9099 event;
9100
9101 XGCValues
9102 context_values;
9103
9104 /*
9105 Initialize graphic context.
9106 */
9107 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9108 assert(display != (Display *) NULL);
9109 assert(crop_info != (RectangleInfo *) NULL);
9110 root_window=XRootWindow(display,XDefaultScreen(display));
9111 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9112 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9113 context_values.function=GXinvert;
9114 context_values.plane_mask=
9115 context_values.background ^ context_values.foreground;
9116 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009117 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009118 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9119 if (annotate_context == (GC) NULL)
9120 return(MagickFalse);
9121 /*
9122 Grab the pointer using target cursor.
9123 */
9124 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9125 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9126 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9127 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9128 GrabModeAsync,root_window,target_cursor,CurrentTime);
9129 if (status != GrabSuccess)
9130 {
9131 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9132 return((Window) NULL);
9133 }
9134 /*
9135 Select a window.
9136 */
9137 crop_info->width=0;
9138 crop_info->height=0;
9139 presses=0;
9140 target_window=(Window) NULL;
9141 x_offset=0;
9142 y_offset=0;
9143 do
9144 {
9145 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9146 (void) XDrawRectangle(display,root_window,annotate_context,
9147 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9148 (unsigned int) crop_info->height-1);
9149 /*
9150 Allow another event.
9151 */
9152 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9153 (void) XWindowEvent(display,root_window,ButtonPressMask |
9154 ButtonReleaseMask | ButtonMotionMask,&event);
9155 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9156 (void) XDrawRectangle(display,root_window,annotate_context,
9157 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9158 (unsigned int) crop_info->height-1);
9159 switch (event.type)
9160 {
9161 case ButtonPress:
9162 {
9163 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9164 event.xbutton.x,event.xbutton.y);
9165 if (target_window == (Window) NULL)
9166 target_window=root_window;
9167 x_offset=event.xbutton.x_root;
9168 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009169 crop_info->x=(ssize_t) x_offset;
9170 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009171 crop_info->width=0;
9172 crop_info->height=0;
9173 presses++;
9174 break;
9175 }
9176 case ButtonRelease:
9177 {
9178 presses--;
9179 break;
9180 }
9181 case MotionNotify:
9182 {
9183 /*
9184 Discard pending button motion events.
9185 */
9186 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009187 crop_info->x=(ssize_t) event.xmotion.x;
9188 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009189 /*
9190 Check boundary conditions.
9191 */
9192 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009193 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009194 else
9195 {
cristyecd0ab52010-05-30 14:59:20 +00009196 crop_info->width=(size_t) (crop_info->x-x_offset);
9197 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009198 }
9199 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009200 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009201 else
9202 {
cristyecd0ab52010-05-30 14:59:20 +00009203 crop_info->height=(size_t) (crop_info->y-y_offset);
9204 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009205 }
9206 }
9207 default:
9208 break;
9209 }
9210 } while ((target_window == (Window) NULL) || (presses > 0));
9211 (void) XUngrabPointer(display,CurrentTime);
9212 (void) XFreeCursor(display,target_cursor);
9213 (void) XFreeGC(display,annotate_context);
9214 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9215 {
9216 crop_info->width=0;
9217 crop_info->height=0;
9218 }
9219 if ((crop_info->width != 0) && (crop_info->height != 0))
9220 target_window=root_window;
9221 return(target_window);
9222}
9223
9224/*
9225%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9226% %
9227% %
9228% %
9229% X S e t C u r s o r S t a t e %
9230% %
9231% %
9232% %
9233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9234%
9235% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9236% reset to their default.
9237%
9238% The format of the XXSetCursorState method is:
9239%
9240% XSetCursorState(display,windows,const MagickStatusType state)
9241%
9242% A description of each parameter follows:
9243%
9244% o display: Specifies a connection to an X server; returned from
9245% XOpenDisplay.
9246%
9247% o windows: Specifies a pointer to a XWindows structure.
9248%
9249% o state: An unsigned integer greater than 0 sets the cursor state
9250% to busy, otherwise the cursor are reset to their default.
9251%
9252*/
cristybcbda3f2011-09-03 13:01:22 +00009253MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009254 const MagickStatusType state)
9255{
9256 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9257 assert(display != (Display *) NULL);
9258 assert(windows != (XWindows *) NULL);
9259 if (state)
9260 {
9261 (void) XCheckDefineCursor(display,windows->image.id,
9262 windows->image.busy_cursor);
9263 (void) XCheckDefineCursor(display,windows->pan.id,
9264 windows->pan.busy_cursor);
9265 (void) XCheckDefineCursor(display,windows->magnify.id,
9266 windows->magnify.busy_cursor);
9267 (void) XCheckDefineCursor(display,windows->command.id,
9268 windows->command.busy_cursor);
9269 }
9270 else
9271 {
9272 (void) XCheckDefineCursor(display,windows->image.id,
9273 windows->image.cursor);
9274 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9275 (void) XCheckDefineCursor(display,windows->magnify.id,
9276 windows->magnify.cursor);
9277 (void) XCheckDefineCursor(display,windows->command.id,
9278 windows->command.cursor);
9279 (void) XCheckDefineCursor(display,windows->command.id,
9280 windows->widget.cursor);
9281 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9282 }
9283 windows->info.mapped=MagickFalse;
9284}
9285
9286/*
9287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9288% %
9289% %
9290% %
9291% X S e t W i n d o w s %
9292% %
9293% %
9294% %
9295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9296%
9297% XSetWindows() sets the X windows structure if the windows info is specified.
9298% Otherwise the current windows structure is returned.
9299%
9300% The format of the XSetWindows method is:
9301%
9302% XWindows *XSetWindows(XWindows *windows_info)
9303%
9304% A description of each parameter follows:
9305%
9306% o windows_info: Initialize the Windows structure with this information.
9307%
9308*/
cristybcbda3f2011-09-03 13:01:22 +00009309MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009310{
9311 static XWindows
9312 *windows = (XWindows *) NULL;
9313
9314 if (windows_info != (XWindows *) ~0)
9315 {
9316 windows=(XWindows *) RelinquishMagickMemory(windows);
9317 windows=windows_info;
9318 }
9319 return(windows);
9320}
9321/*
9322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9323% %
9324% %
9325% %
9326% X U s e r P r e f e r e n c e s %
9327% %
9328% %
9329% %
9330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9331%
9332% XUserPreferences() saves the preferences in a configuration file in the
9333% users' home directory.
9334%
9335% The format of the XUserPreferences method is:
9336%
9337% void XUserPreferences(XResourceInfo *resource_info)
9338%
9339% A description of each parameter follows:
9340%
9341% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9342%
9343*/
cristybcbda3f2011-09-03 13:01:22 +00009344MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009345{
9346#if defined(X11_PREFERENCES_PATH)
9347 char
9348 cache[MaxTextExtent],
9349 filename[MaxTextExtent],
9350 specifier[MaxTextExtent];
9351
9352 const char
cristy104cea82009-10-25 02:26:51 +00009353 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009354 *value;
9355
9356 XrmDatabase
9357 preferences_database;
9358
9359 /*
9360 Save user preferences to the client configuration file.
9361 */
9362 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009363 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009364 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009365 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009366 value=resource_info->backdrop ? "True" : "False";
9367 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009368 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009369 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9370 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009371 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009372 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009373 value=resource_info->confirm_exit ? "True" : "False";
9374 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009375 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009376 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009377 value=resource_info->confirm_edit ? "True" : "False";
9378 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009379 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009380 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009381 value=resource_info->display_warnings ? "True" : "False";
9382 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009383 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009384 value=resource_info->quantize_info->dither ? "True" : "False";
9385 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009386 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009387 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009388 value=resource_info->gamma_correct ? "True" : "False";
9389 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009390 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9391 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009392 resource_info->undo_cache);
9393 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009394 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009395 value=resource_info->use_pixmap ? "True" : "False";
9396 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009397 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009398 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009399 ExpandFilename(filename);
9400 XrmPutFileDatabase(preferences_database,filename);
9401#endif
9402}
9403
9404/*
9405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9406% %
9407% %
9408% %
9409% X V i s u a l C l a s s N a m e %
9410% %
9411% %
9412% %
9413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9414%
9415% XVisualClassName() returns the visual class name as a character string.
9416%
9417% The format of the XVisualClassName method is:
9418%
9419% char *XVisualClassName(const int visual_class)
9420%
9421% A description of each parameter follows:
9422%
9423% o visual_type: XVisualClassName returns the visual class as a character
9424% string.
9425%
9426% o class: Specifies the visual class.
9427%
cristy3ed852e2009-09-05 21:47:34 +00009428*/
9429static const char *XVisualClassName(const int visual_class)
9430{
9431 switch (visual_class)
9432 {
9433 case StaticGray: return("StaticGray");
9434 case GrayScale: return("GrayScale");
9435 case StaticColor: return("StaticColor");
9436 case PseudoColor: return("PseudoColor");
9437 case TrueColor: return("TrueColor");
9438 case DirectColor: return("DirectColor");
9439 }
9440 return("unknown visual class");
9441}
9442
9443/*
9444%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9445% %
9446% %
9447% %
9448% X W a r n i n g %
9449% %
9450% %
9451% %
9452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9453%
9454% XWarning() displays a warning reason in a Notice widget.
9455%
9456% The format of the XWarning method is:
9457%
9458% void XWarning(const unsigned int warning,const char *reason,
9459% const char *description)
9460%
9461% A description of each parameter follows:
9462%
9463% o warning: Specifies the numeric warning category.
9464%
9465% o reason: Specifies the reason to display before terminating the
9466% program.
9467%
9468% o description: Specifies any description to the reason.
9469%
9470*/
cristybcbda3f2011-09-03 13:01:22 +00009471MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009472 const char *reason,const char *description)
9473{
9474 char
9475 text[MaxTextExtent];
9476
9477 XWindows
9478 *windows;
9479
9480 if (reason == (char *) NULL)
9481 return;
9482 (void) CopyMagickString(text,reason,MaxTextExtent);
9483 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9484 windows=XSetWindows((XWindows *) ~0);
9485 XNoticeWidget(windows->display,windows,text,(char *) description);
9486}
9487
9488/*
9489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9490% %
9491% %
9492% %
9493% X W i n d o w B y I D %
9494% %
9495% %
9496% %
9497%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9498%
9499% XWindowByID() locates a child window with a given ID. If not window with
9500% the given name is found, 0 is returned. Only the window specified and its
9501% subwindows are searched.
9502%
9503% The format of the XWindowByID function is:
9504%
9505% child=XWindowByID(display,window,id)
9506%
9507% A description of each parameter follows:
9508%
9509% o child: XWindowByID returns the window with the specified
9510% id. If no windows are found, XWindowByID returns 0.
9511%
9512% o display: Specifies a pointer to the Display structure; returned from
9513% XOpenDisplay.
9514%
9515% o id: Specifies the id of the window to locate.
9516%
9517*/
cristybcbda3f2011-09-03 13:01:22 +00009518MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009519 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009520{
9521 RectangleInfo
9522 rectangle_info;
9523
9524 register int
9525 i;
9526
9527 Status
9528 status;
9529
9530 unsigned int
9531 number_children;
9532
9533 Window
9534 child,
9535 *children,
9536 window;
9537
9538 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9539 assert(display != (Display *) NULL);
9540 assert(root_window != (Window) NULL);
9541 if (id == 0)
9542 return(XSelectWindow(display,&rectangle_info));
9543 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009544 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009545 status=XQueryTree(display,root_window,&child,&child,&children,
9546 &number_children);
9547 if (status == False)
9548 return((Window) NULL);
9549 window=(Window) NULL;
9550 for (i=0; i < (int) number_children; i++)
9551 {
9552 /*
9553 Search each child and their children.
9554 */
9555 window=XWindowByID(display,children[i],id);
9556 if (window != (Window) NULL)
9557 break;
9558 }
9559 if (children != (Window *) NULL)
9560 (void) XFree((void *) children);
9561 return(window);
9562}
9563
9564/*
9565%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9566% %
9567% %
9568% %
9569% X W i n d o w B y N a m e %
9570% %
9571% %
9572% %
9573%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9574%
9575% XWindowByName() locates a window with a given name on a display. If no
9576% window with the given name is found, 0 is returned. If more than one window
9577% has the given name, the first one is returned. Only root and its children
9578% are searched.
9579%
9580% The format of the XWindowByName function is:
9581%
9582% window=XWindowByName(display,root_window,name)
9583%
9584% A description of each parameter follows:
9585%
9586% o window: XWindowByName returns the window id.
9587%
9588% o display: Specifies a pointer to the Display structure; returned from
9589% XOpenDisplay.
9590%
9591% o root_window: Specifies the id of the root window.
9592%
9593% o name: Specifies the name of the window to locate.
9594%
9595*/
cristybcbda3f2011-09-03 13:01:22 +00009596MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009597 const char *name)
9598{
9599 register int
9600 i;
9601
9602 Status
9603 status;
9604
9605 unsigned int
9606 number_children;
9607
9608 Window
9609 *children,
9610 child,
9611 window;
9612
9613 XTextProperty
9614 window_name;
9615
9616 assert(display != (Display *) NULL);
9617 assert(root_window != (Window) NULL);
9618 assert(name != (char *) NULL);
9619 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9620 if (XGetWMName(display,root_window,&window_name) != 0)
9621 if (LocaleCompare((char *) window_name.value,name) == 0)
9622 return(root_window);
9623 status=XQueryTree(display,root_window,&child,&child,&children,
9624 &number_children);
9625 if (status == False)
9626 return((Window) NULL);
9627 window=(Window) NULL;
9628 for (i=0; i < (int) number_children; i++)
9629 {
9630 /*
9631 Search each child and their children.
9632 */
9633 window=XWindowByName(display,children[i],name);
9634 if (window != (Window) NULL)
9635 break;
9636 }
9637 if (children != (Window *) NULL)
9638 (void) XFree((void *) children);
9639 return(window);
9640}
9641
9642/*
9643%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9644% %
9645% %
9646% %
9647% X W i n d o w B y P r o p e r y %
9648% %
9649% %
9650% %
9651%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9652%
9653% XWindowByProperty() locates a child window with a given property. If not
9654% window with the given name is found, 0 is returned. If more than one window
9655% has the given property, the first one is returned. Only the window
9656% specified and its subwindows are searched.
9657%
9658% The format of the XWindowByProperty function is:
9659%
9660% child=XWindowByProperty(display,window,property)
9661%
9662% A description of each parameter follows:
9663%
9664% o child: XWindowByProperty returns the window id with the specified
9665% property. If no windows are found, XWindowByProperty returns 0.
9666%
9667% o display: Specifies a pointer to the Display structure; returned from
9668% XOpenDisplay.
9669%
9670% o property: Specifies the property of the window to locate.
9671%
9672*/
cristybcbda3f2011-09-03 13:01:22 +00009673MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009674 const Atom property)
9675{
9676 Atom
9677 type;
9678
9679 int
9680 format;
9681
9682 Status
9683 status;
9684
9685 unsigned char
9686 *data;
9687
9688 unsigned int
9689 i,
9690 number_children;
9691
cristyf2faecf2010-05-28 19:19:36 +00009692 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009693 after,
9694 number_items;
9695
9696 Window
9697 child,
9698 *children,
9699 parent,
9700 root;
9701
9702 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9703 assert(display != (Display *) NULL);
9704 assert(window != (Window) NULL);
9705 assert(property != (Atom) NULL);
9706 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9707 if (status == False)
9708 return((Window) NULL);
9709 type=(Atom) NULL;
9710 child=(Window) NULL;
9711 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9712 {
9713 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9714 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9715 if (data != NULL)
9716 (void) XFree((void *) data);
9717 if ((status == Success) && (type != (Atom) NULL))
9718 child=children[i];
9719 }
9720 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9721 child=XWindowByProperty(display,children[i],property);
9722 if (children != (Window *) NULL)
9723 (void) XFree((void *) children);
9724 return(child);
9725}
9726#else
9727
9728/*
9729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9730% %
9731% %
9732% %
9733% X I m p o r t I m a g e %
9734% %
9735% %
9736% %
9737%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9738%
9739% XImportImage() reads an image from an X window.
9740%
9741% The format of the XImportImage method is:
9742%
9743% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9744%
9745% A description of each parameter follows:
9746%
9747% o image_info: the image info..
9748%
9749% o ximage_info: Specifies a pointer to an XImportInfo structure.
9750%
9751*/
cristybcbda3f2011-09-03 13:01:22 +00009752MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00009753 XImportInfo *ximage_info)
9754{
9755 assert(image_info != (const ImageInfo *) NULL);
9756 assert(image_info->signature == MagickSignature);
9757 if (image_info->debug != MagickFalse)
9758 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9759 image_info->filename);
9760 assert(ximage_info != (XImportInfo *) NULL);
9761 return((Image *) NULL);
9762}
9763#endif
9764
9765/*
9766%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9767% %
9768% %
9769% %
cristy576974e2009-10-25 20:45:31 +00009770+ X C o m p o n e n t G e n e s i s %
9771% %
9772% %
9773% %
9774%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9775%
9776% XComponentGenesis() instantiates the X component.
9777%
9778% The format of the XComponentGenesis method is:
9779%
9780% MagickBooleanType XComponentGenesis(void)
9781%
9782*/
cristy5ff4eaf2011-09-03 01:38:02 +00009783MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009784{
9785 return(MagickTrue);
9786}
9787
9788/*
9789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9790% %
9791% %
9792% %
cristy3ed852e2009-09-05 21:47:34 +00009793% X G e t I m p o r t I n f o %
9794% %
9795% %
9796% %
9797%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9798%
9799% XGetImportInfo() initializes the XImportInfo structure.
9800%
9801% The format of the XGetImportInfo method is:
9802%
9803% void XGetImportInfo(XImportInfo *ximage_info)
9804%
9805% A description of each parameter follows:
9806%
9807% o ximage_info: Specifies a pointer to an ImageInfo structure.
9808%
9809*/
9810MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9811{
9812 assert(ximage_info != (XImportInfo *) NULL);
9813 ximage_info->frame=MagickFalse;
9814 ximage_info->borders=MagickFalse;
9815 ximage_info->screen=MagickFalse;
9816 ximage_info->descend=MagickTrue;
9817 ximage_info->silent=MagickFalse;
9818}