blob: 0e434908f71cf16b6cc5913f9aca69ce1906bbc2 [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
487 virtual_pixel[MaxPixelChannels];
488
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
2330 virtual_pixel[MaxPixelChannels];
2331
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 */
cristy101ab702011-10-13 13:06:32 +00002519 SetPixelPixelInfo(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 }
cristyc57f6942010-11-12 01:47:39 +00004440 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004441 break;
4442 }
4443 else
4444 for (y=0; y < (int) composite_image->rows; y++)
4445 {
cristyc57f6942010-11-12 01:47:39 +00004446 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004447 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004448 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004449 break;
4450 for (x=0; x < (int) composite_image->columns; x++)
4451 {
4452 pixel=XGetPixel(ximage,x,y);
4453 color=(pixel >> red_shift) & red_mask;
4454 color=(65535UL*color)/red_mask;
cristy4c08aed2011-07-01 19:47:50 +00004455 SetPixelRed(composite_image,
4456 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004457 color=(pixel >> green_shift) & green_mask;
4458 color=(65535UL*color)/green_mask;
cristy4c08aed2011-07-01 19:47:50 +00004459 SetPixelGreen(composite_image,
4460 ScaleShortToQuantum((unsigned short) color),q);
cristy3ed852e2009-09-05 21:47:34 +00004461 color=(pixel >> blue_shift) & blue_mask;
4462 color=(65535UL*color)/blue_mask;
cristy4c08aed2011-07-01 19:47:50 +00004463 SetPixelBlue(composite_image,
4464 ScaleShortToQuantum((unsigned short) color),q);
cristyed231572011-07-14 02:18:59 +00004465 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004466 }
cristyc57f6942010-11-12 01:47:39 +00004467 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004468 break;
4469 }
4470 break;
4471 }
4472 case PseudoClass:
4473 {
4474 /*
4475 Create colormap.
4476 */
cristy018f07f2011-09-04 21:15:19 +00004477 if (AcquireImageColormap(composite_image,number_colors,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004478 {
4479 XDestroyImage(ximage);
4480 composite_image=DestroyImage(composite_image);
4481 return((Image *) NULL);
4482 }
4483 for (i=0; i < (int) composite_image->colors; i++)
4484 {
4485 composite_image->colormap[colors[i].pixel].red=
4486 ScaleShortToQuantum(colors[i].red);
4487 composite_image->colormap[colors[i].pixel].green=
4488 ScaleShortToQuantum(colors[i].green);
4489 composite_image->colormap[colors[i].pixel].blue=
4490 ScaleShortToQuantum(colors[i].blue);
4491 }
4492 /*
4493 Convert X image to PseudoClass packets.
4494 */
4495 for (y=0; y < (int) composite_image->rows; y++)
4496 {
cristyc57f6942010-11-12 01:47:39 +00004497 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4498 composite_image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +00004499 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00004500 break;
cristy3ed852e2009-09-05 21:47:34 +00004501 for (x=0; x < (int) composite_image->columns; x++)
4502 {
cristy4c08aed2011-07-01 19:47:50 +00004503 index=(Quantum) XGetPixel(ximage,x,y);
4504 SetPixelIndex(composite_image,index,q);
cristy101ab702011-10-13 13:06:32 +00004505 SetPixelPixelInfo(composite_image,
cristy4c08aed2011-07-01 19:47:50 +00004506 composite_image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +00004507 q+=GetPixelChannels(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004508 }
cristyc57f6942010-11-12 01:47:39 +00004509 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004510 break;
4511 }
4512 break;
4513 }
4514 }
cristyc57f6942010-11-12 01:47:39 +00004515 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004516 XDestroyImage(ximage);
4517 if (image == (Image *) NULL)
4518 {
4519 image=composite_image;
4520 continue;
4521 }
4522 /*
4523 Composite any children in back-to-front order.
4524 */
4525 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4526 &x_offset,&y_offset,&child);
4527 x_offset-=(int) crop_info.x;
4528 if (x_offset < 0)
4529 x_offset=0;
4530 y_offset-=(int) crop_info.y;
4531 if (y_offset < 0)
4532 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004533 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
cristye941a752011-10-15 01:52:48 +00004534 x_offset,(ssize_t) y_offset,exception);
cristy3ed852e2009-09-05 21:47:34 +00004535 }
4536 /*
4537 Relinquish resources.
4538 */
4539 while (colormap_info != (ColormapInfo *) NULL)
4540 {
4541 next=colormap_info->next;
cristye941a752011-10-15 01:52:48 +00004542 colormap_info->colors=(XColor *) RelinquishMagickMemory(
4543 colormap_info->colors);
cristy3ed852e2009-09-05 21:47:34 +00004544 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4545 colormap_info=next;
4546 }
4547 /*
4548 Relinquish resources and restore initial state.
4549 */
4550 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4551 max_windows=0;
4552 number_windows=0;
4553 colormap_info=(ColormapInfo *) NULL;
4554 return(image);
4555 }
4556 return((Image *) NULL);
4557}
4558
4559/*
4560%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4561% %
4562% %
4563% %
4564% X G e t W i n d o w I n f o %
4565% %
4566% %
4567% %
4568%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4569%
4570% XGetWindowInfo() initializes the XWindowInfo structure.
4571%
4572% The format of the XGetWindowInfo method is:
4573%
4574% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4575% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4576% XResourceInfo *resource_info,XWindowInfo *window)
4577% resource_info,window)
4578%
4579% A description of each parameter follows:
4580%
4581% o display: Specifies a connection to an X server; returned from
4582% XOpenDisplay.
4583%
4584% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4585% returned from XGetVisualInfo.
4586%
4587% o map_info: If map_type is specified, this structure is initialized
4588% with info from the Standard Colormap.
4589%
4590% o pixel: Specifies a pointer to a XPixelInfo structure.
4591%
4592% o font_info: Specifies a pointer to a XFontStruct structure.
4593%
4594% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4595%
4596*/
cristybcbda3f2011-09-03 13:01:22 +00004597MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
cristy3ed852e2009-09-05 21:47:34 +00004598 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4599 XResourceInfo *resource_info,XWindowInfo *window)
4600{
4601 /*
4602 Initialize window info.
4603 */
4604 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4605 assert(display != (Display *) NULL);
4606 assert(visual_info != (XVisualInfo *) NULL);
4607 assert(map_info != (XStandardColormap *) NULL);
4608 assert(pixel != (XPixelInfo *) NULL);
4609 assert(resource_info != (XResourceInfo *) NULL);
4610 assert(window != (XWindowInfo *) NULL);
4611 if (window->id != (Window) NULL)
4612 {
4613 if (window->cursor != (Cursor) NULL)
4614 (void) XFreeCursor(display,window->cursor);
4615 if (window->busy_cursor != (Cursor) NULL)
4616 (void) XFreeCursor(display,window->busy_cursor);
4617 if (window->highlight_stipple != (Pixmap) NULL)
4618 (void) XFreePixmap(display,window->highlight_stipple);
4619 if (window->shadow_stipple != (Pixmap) NULL)
4620 (void) XFreePixmap(display,window->shadow_stipple);
4621 if (window->name == (char *) NULL)
4622 window->name=AcquireString("");
4623 if (window->icon_name == (char *) NULL)
4624 window->icon_name=AcquireString("");
4625 }
4626 else
4627 {
4628 /*
4629 Initialize these attributes just once.
4630 */
4631 window->id=(Window) NULL;
4632 if (window->name == (char *) NULL)
4633 window->name=AcquireString("");
4634 if (window->icon_name == (char *) NULL)
4635 window->icon_name=AcquireString("");
4636 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4637 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4638 window->ximage=(XImage *) NULL;
4639 window->matte_image=(XImage *) NULL;
4640 window->pixmap=(Pixmap) NULL;
4641 window->matte_pixmap=(Pixmap) NULL;
4642 window->mapped=MagickFalse;
4643 window->stasis=MagickFalse;
4644 window->shared_memory=MagickTrue;
4645 window->segment_info=(void *) NULL;
4646#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4647 {
4648 XShmSegmentInfo
4649 *segment_info;
4650
4651 if (window->segment_info == (void *) NULL)
4652 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4653 segment_info=(XShmSegmentInfo *) window->segment_info;
4654 segment_info[0].shmid=(-1);
4655 segment_info[0].shmaddr=(char *) NULL;
4656 segment_info[1].shmid=(-1);
4657 segment_info[1].shmaddr=(char *) NULL;
4658 }
4659#endif
4660 }
4661 /*
4662 Initialize these attributes every time function is called.
4663 */
4664 window->screen=visual_info->screen;
4665 window->root=XRootWindow(display,visual_info->screen);
4666 window->visual=visual_info->visual;
4667 window->storage_class=(unsigned int) visual_info->klass;
4668 window->depth=(unsigned int) visual_info->depth;
4669 window->visual_info=visual_info;
4670 window->map_info=map_info;
4671 window->pixel_info=pixel;
4672 window->font_info=font_info;
4673 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4674 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4675 window->geometry=(char *) NULL;
4676 window->icon_geometry=(char *) NULL;
4677 if (resource_info->icon_geometry != (char *) NULL)
4678 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4679 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004680 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004681 window->width=1;
4682 window->height=1;
4683 window->min_width=1;
4684 window->min_height=1;
4685 window->width_inc=1;
4686 window->height_inc=1;
4687 window->border_width=resource_info->border_width;
4688 window->annotate_context=pixel->annotate_context;
4689 window->highlight_context=pixel->highlight_context;
4690 window->widget_context=pixel->widget_context;
4691 window->shadow_stipple=(Pixmap) NULL;
4692 window->highlight_stipple=(Pixmap) NULL;
4693 window->use_pixmap=MagickTrue;
4694 window->immutable=MagickFalse;
4695 window->shape=MagickFalse;
4696 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004697 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004698 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4699 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4700 window->attributes.background_pixel=pixel->background_color.pixel;
4701 window->attributes.background_pixmap=(Pixmap) NULL;
4702 window->attributes.bit_gravity=ForgetGravity;
4703 window->attributes.backing_store=WhenMapped;
4704 window->attributes.save_under=MagickTrue;
4705 window->attributes.border_pixel=pixel->border_color.pixel;
4706 window->attributes.colormap=map_info->colormap;
4707 window->attributes.cursor=window->cursor;
4708 window->attributes.do_not_propagate_mask=NoEventMask;
4709 window->attributes.event_mask=NoEventMask;
4710 window->attributes.override_redirect=MagickFalse;
4711 window->attributes.win_gravity=NorthWestGravity;
4712 window->orphan=MagickFalse;
4713}
4714
4715/*
4716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4717% %
4718% %
4719% %
4720% X H i g h l i g h t E l l i p s e %
4721% %
4722% %
4723% %
4724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4725%
4726% XHighlightEllipse() puts a border on the X server around a region defined by
4727% highlight_info.
4728%
4729% The format of the XHighlightEllipse method is:
4730%
4731% void XHighlightEllipse(Display *display,Window window,
4732% GC annotate_context,const RectangleInfo *highlight_info)
4733%
4734% A description of each parameter follows:
4735%
4736% o display: Specifies a connection to an X server; returned from
4737% XOpenDisplay.
4738%
4739% o window: Specifies a pointer to a Window structure.
4740%
4741% o annotate_context: Specifies a pointer to a GC structure.
4742%
4743% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4744% contains the extents of any highlighting rectangle.
4745%
4746*/
cristybcbda3f2011-09-03 13:01:22 +00004747MagickPrivate void XHighlightEllipse(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004748 GC annotate_context,const RectangleInfo *highlight_info)
4749{
4750 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4751 assert(display != (Display *) NULL);
4752 assert(window != (Window) NULL);
4753 assert(annotate_context != (GC) NULL);
4754 assert(highlight_info != (RectangleInfo *) NULL);
4755 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4756 return;
4757 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4758 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4759 (unsigned int) highlight_info->height-1,0,360*64);
4760 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4761 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4762 (unsigned int) highlight_info->height-3,0,360*64);
4763}
4764
4765/*
4766%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4767% %
4768% %
4769% %
4770% X H i g h l i g h t L i n e %
4771% %
4772% %
4773% %
4774%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4775%
4776% XHighlightLine() puts a border on the X server around a region defined by
4777% highlight_info.
4778%
4779% The format of the XHighlightLine method is:
4780%
4781% void XHighlightLine(Display *display,Window window,GC annotate_context,
4782% const XSegment *highlight_info)
4783%
4784% A description of each parameter follows:
4785%
4786% o display: Specifies a connection to an X server; returned from
4787% XOpenDisplay.
4788%
4789% o window: Specifies a pointer to a Window structure.
4790%
4791% o annotate_context: Specifies a pointer to a GC structure.
4792%
4793% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4794% contains the extents of any highlighting rectangle.
4795%
4796*/
cristybcbda3f2011-09-03 13:01:22 +00004797MagickPrivate void XHighlightLine(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004798 GC annotate_context,const XSegment *highlight_info)
4799{
4800 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4801 assert(display != (Display *) NULL);
4802 assert(window != (Window) NULL);
4803 assert(annotate_context != (GC) NULL);
4804 assert(highlight_info != (XSegment *) NULL);
4805 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4806 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4807}
4808
4809/*
4810%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4811% %
4812% %
4813% %
4814% X H i g h l i g h t R e c t a n g l e %
4815% %
4816% %
4817% %
4818%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4819%
4820% XHighlightRectangle() puts a border on the X server around a region defined
4821% by highlight_info.
4822%
4823% The format of the XHighlightRectangle method is:
4824%
4825% void XHighlightRectangle(Display *display,Window window,
4826% GC annotate_context,const RectangleInfo *highlight_info)
4827%
4828% A description of each parameter follows:
4829%
4830% o display: Specifies a connection to an X server; returned from
4831% XOpenDisplay.
4832%
4833% o window: Specifies a pointer to a Window structure.
4834%
4835% o annotate_context: Specifies a pointer to a GC structure.
4836%
4837% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4838% contains the extents of any highlighting rectangle.
4839%
4840*/
cristybcbda3f2011-09-03 13:01:22 +00004841MagickPrivate void XHighlightRectangle(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00004842 GC annotate_context,const RectangleInfo *highlight_info)
4843{
4844 assert(display != (Display *) NULL);
4845 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4846 assert(window != (Window) NULL);
4847 assert(annotate_context != (GC) NULL);
4848 assert(highlight_info != (RectangleInfo *) NULL);
4849 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4850 return;
4851 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4852 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4853 (unsigned int) highlight_info->height-1);
4854 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4855 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4856 (unsigned int) highlight_info->height-3);
4857}
4858
4859/*
4860%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4861% %
4862% %
4863% %
4864% X I m p o r t I m a g e %
4865% %
4866% %
4867% %
4868%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4869%
4870% XImportImage() reads an image from an X window.
4871%
4872% The format of the XImportImage method is:
4873%
cristy6710d842011-10-20 23:23:00 +00004874% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
4875% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004876%
4877% A description of each parameter follows:
4878%
4879% o image_info: the image info.
4880%
4881% o ximage_info: Specifies a pointer to an XImportInfo structure.
4882%
cristy6710d842011-10-20 23:23:00 +00004883% o exception: return any errors or warnings in this structure.
4884%
cristy3ed852e2009-09-05 21:47:34 +00004885*/
4886MagickExport Image *XImportImage(const ImageInfo *image_info,
cristy6710d842011-10-20 23:23:00 +00004887 XImportInfo *ximage_info,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00004888{
4889 Colormap
4890 *colormaps;
4891
4892 Display
4893 *display;
4894
4895 Image
4896 *image;
4897
4898 int
4899 number_colormaps,
4900 number_windows,
4901 x;
4902
4903 RectangleInfo
4904 crop_info;
4905
4906 Status
4907 status;
4908
4909 Window
4910 *children,
4911 client,
4912 prior_target,
4913 root,
4914 target;
4915
4916 XTextProperty
4917 window_name;
4918
4919 /*
4920 Open X server connection.
4921 */
4922 assert(image_info != (const ImageInfo *) NULL);
4923 assert(image_info->signature == MagickSignature);
4924 if (image_info->debug != MagickFalse)
4925 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4926 image_info->filename);
4927 assert(ximage_info != (XImportInfo *) NULL);
4928 display=XOpenDisplay(image_info->server_name);
4929 if (display == (Display *) NULL)
4930 {
4931 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4932 XDisplayName(image_info->server_name));
4933 return((Image *) NULL);
4934 }
4935 /*
4936 Set our forgiving exception handler.
4937 */
4938 (void) XSetErrorHandler(XError);
4939 /*
4940 Select target window.
4941 */
4942 crop_info.x=0;
4943 crop_info.y=0;
4944 crop_info.width=0;
4945 crop_info.height=0;
4946 root=XRootWindow(display,XDefaultScreen(display));
4947 target=(Window) NULL;
4948 if ((image_info->filename != (char *) NULL) &&
4949 (*image_info->filename != '\0'))
4950 {
4951 if (LocaleCompare(image_info->filename,"root") == 0)
4952 target=root;
4953 else
4954 {
4955 /*
4956 Select window by ID or name.
4957 */
4958 if (isdigit((unsigned char) *image_info->filename) != 0)
4959 target=XWindowByID(display,root,(Window)
4960 strtol(image_info->filename,(char **) NULL,0));
4961 if (target == (Window) NULL)
4962 target=XWindowByName(display,root,image_info->filename);
4963 if (target == (Window) NULL)
4964 ThrowXWindowFatalException(XServerError,
4965 "NoWindowWithSpecifiedIDExists",image_info->filename);
4966 }
4967 }
4968 /*
4969 If target window is not defined, interactively select one.
4970 */
4971 prior_target=target;
4972 if (target == (Window) NULL)
4973 target=XSelectWindow(display,&crop_info);
4974 if (target == (Window) NULL)
4975 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4976 image_info->filename);
4977 client=target; /* obsolete */
4978 if (target != root)
4979 {
4980 unsigned int
4981 d;
4982
4983 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4984 if (status != False)
4985 {
4986 for ( ; ; )
4987 {
4988 Window
4989 parent;
4990
4991 /*
4992 Find window manager frame.
4993 */
4994 status=XQueryTree(display,target,&root,&parent,&children,&d);
4995 if ((status != False) && (children != (Window *) NULL))
4996 (void) XFree((char *) children);
4997 if ((status == False) || (parent == (Window) NULL) ||
4998 (parent == root))
4999 break;
5000 target=parent;
5001 }
5002 /*
5003 Get client window.
5004 */
5005 client=XClientWindow(display,target);
5006 if (ximage_info->frame == MagickFalse)
5007 target=client;
5008 if ((ximage_info->frame == MagickFalse) &&
5009 (prior_target != MagickFalse))
5010 target=prior_target;
5011 XDelay(display,SuspendTime << 4);
5012 }
5013 }
5014 if (ximage_info->screen)
5015 {
5016 int
5017 y;
5018
5019 Window
5020 child;
5021
5022 XWindowAttributes
5023 window_attributes;
5024
5025 /*
5026 Obtain window image directly from screen.
5027 */
5028 status=XGetWindowAttributes(display,target,&window_attributes);
5029 if (status == False)
5030 {
5031 ThrowXWindowFatalException(XServerError,
5032 "UnableToReadXWindowAttributes",image_info->filename);
5033 (void) XCloseDisplay(display);
5034 return((Image *) NULL);
5035 }
5036 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00005037 crop_info.x=(ssize_t) x;
5038 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00005039 crop_info.width=(size_t) window_attributes.width;
5040 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00005041 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00005042 {
5043 /*
5044 Include border in image.
5045 */
5046 crop_info.x-=window_attributes.border_width;
5047 crop_info.y-=window_attributes.border_width;
5048 crop_info.width+=window_attributes.border_width << 1;
5049 crop_info.height+=window_attributes.border_width << 1;
5050 }
5051 target=root;
5052 }
5053 /*
5054 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5055 */
5056 number_windows=0;
5057 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5058 if ((status == True) && (number_windows > 0))
5059 {
5060 ximage_info->descend=MagickTrue;
5061 (void) XFree ((char *) children);
5062 }
5063 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5064 if (number_colormaps > 0)
5065 {
5066 if (number_colormaps > 1)
5067 ximage_info->descend=MagickTrue;
5068 (void) XFree((char *) colormaps);
5069 }
5070 /*
5071 Alert the user not to alter the screen.
5072 */
5073 if (ximage_info->silent == MagickFalse)
5074 (void) XBell(display,0);
5075 /*
5076 Get image by window id.
5077 */
5078 (void) XGrabServer(display);
5079 image=XGetWindowImage(display,target,ximage_info->borders,
cristy6710d842011-10-20 23:23:00 +00005080 ximage_info->descend ? 1U : 0U,exception);
cristy3ed852e2009-09-05 21:47:34 +00005081 (void) XUngrabServer(display);
5082 if (image == (Image *) NULL)
5083 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5084 image_info->filename)
5085 else
5086 {
5087 (void) CopyMagickString(image->filename,image_info->filename,
5088 MaxTextExtent);
5089 if ((crop_info.width != 0) && (crop_info.height != 0))
5090 {
5091 Image
5092 *clone_image,
5093 *crop_image;
5094
5095 /*
5096 Crop image as defined by the cropping rectangle.
5097 */
cristy6710d842011-10-20 23:23:00 +00005098 clone_image=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005099 if (clone_image != (Image *) NULL)
5100 {
cristy6710d842011-10-20 23:23:00 +00005101 crop_image=CropImage(clone_image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005102 if (crop_image != (Image *) NULL)
5103 {
5104 image=DestroyImage(image);
5105 image=crop_image;
5106 }
5107 }
5108 }
5109 status=XGetWMName(display,target,&window_name);
5110 if (status == True)
5111 {
5112 if ((image_info->filename != (char *) NULL) &&
5113 (*image_info->filename == '\0'))
5114 (void) CopyMagickString(image->filename,(char *) window_name.value,
5115 (size_t) window_name.nitems+1);
5116 (void) XFree((void *) window_name.value);
5117 }
5118 }
5119 if (ximage_info->silent == MagickFalse)
5120 {
5121 /*
5122 Alert the user we're done.
5123 */
5124 (void) XBell(display,0);
5125 (void) XBell(display,0);
5126 }
5127 (void) XCloseDisplay(display);
5128 return(image);
5129}
5130
5131/*
5132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5133% %
5134% %
5135% %
5136% X I n i t i a l i z e W i n d o w s %
5137% %
5138% %
5139% %
5140%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5141%
5142% XInitializeWindows() initializes the XWindows structure.
5143%
5144% The format of the XInitializeWindows method is:
5145%
5146% XWindows *XInitializeWindows(Display *display,
5147% XResourceInfo *resource_info)
5148%
5149% A description of each parameter follows:
5150%
5151% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5152%
5153% o display: Specifies a connection to an X server; returned from
5154% XOpenDisplay.
5155%
5156% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5157%
5158*/
cristybcbda3f2011-09-03 13:01:22 +00005159MagickPrivate XWindows *XInitializeWindows(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005160 XResourceInfo *resource_info)
5161{
5162 Window
5163 root_window;
5164
5165 XWindows
5166 *windows;
5167
5168 /*
5169 Allocate windows structure.
5170 */
cristy73bd4a52010-10-05 11:24:23 +00005171 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005172 if (windows == (XWindows *) NULL)
5173 {
5174 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5175 "...");
5176 return((XWindows *) NULL);
5177 }
5178 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5179 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5180 sizeof(*windows->pixel_info));
5181 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5182 sizeof(*windows->icon_pixel));
5183 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5184 sizeof(*windows->icon_resources));
5185 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5186 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5187 (windows->icon_resources == (XResourceInfo *) NULL))
5188 {
5189 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5190 "...");
5191 return((XWindows *) NULL);
5192 }
5193 /*
5194 Initialize windows structure.
5195 */
5196 windows->display=display;
5197 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5198 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5199 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5200 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5201 windows->im_remote_command=
5202 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5203 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5204 windows->im_update_colormap=
5205 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5206 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5207 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5208 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5209 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5210 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005211#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005212 (void) XSynchronize(display,IsWindows95());
5213#endif
5214 if (IsEventLogging())
5215 {
5216 (void) XSynchronize(display,MagickTrue);
5217 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005218 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005219 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5220 (void) LogMagickEvent(X11Event,GetMagickModule(),
5221 " Window Manager: 0x%lx",windows->wm_protocols);
5222 (void) LogMagickEvent(X11Event,GetMagickModule(),
5223 " delete window: 0x%lx",windows->wm_delete_window);
5224 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5225 windows->wm_take_focus);
5226 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5227 windows->im_protocols);
5228 (void) LogMagickEvent(X11Event,GetMagickModule(),
5229 " remote command: 0x%lx",windows->im_remote_command);
5230 (void) LogMagickEvent(X11Event,GetMagickModule(),
5231 " update widget: 0x%lx",windows->im_update_widget);
5232 (void) LogMagickEvent(X11Event,GetMagickModule(),
5233 " update colormap: 0x%lx",windows->im_update_colormap);
5234 (void) LogMagickEvent(X11Event,GetMagickModule(),
5235 " former image: 0x%lx",windows->im_former_image);
5236 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5237 windows->im_next_image);
5238 (void) LogMagickEvent(X11Event,GetMagickModule(),
5239 " retain colors: 0x%lx",windows->im_retain_colors);
5240 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5241 windows->im_exit);
5242 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5243 windows->dnd_protocols);
5244 }
5245 /*
5246 Allocate standard colormap.
5247 */
5248 windows->map_info=XAllocStandardColormap();
5249 windows->icon_map=XAllocStandardColormap();
5250 if ((windows->map_info == (XStandardColormap *) NULL) ||
5251 (windows->icon_map == (XStandardColormap *) NULL))
5252 ThrowXWindowFatalException(ResourceLimitFatalError,
5253 "MemoryAllocationFailed","...");
5254 windows->map_info->colormap=(Colormap) NULL;
5255 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005256 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005257 windows->pixel_info->annotate_context=(GC) NULL;
5258 windows->pixel_info->highlight_context=(GC) NULL;
5259 windows->pixel_info->widget_context=(GC) NULL;
5260 windows->font_info=(XFontStruct *) NULL;
5261 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005262 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005263 /*
5264 Allocate visual.
5265 */
5266 *windows->icon_resources=(*resource_info);
5267 windows->icon_resources->visual_type=(char *) "default";
5268 windows->icon_resources->colormap=SharedColormap;
5269 windows->visual_info=
5270 XBestVisualInfo(display,windows->map_info,resource_info);
5271 windows->icon_visual=
5272 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5273 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5274 (windows->icon_visual == (XVisualInfo *) NULL))
5275 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5276 resource_info->visual_type);
5277 if (IsEventLogging())
5278 {
5279 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5280 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5281 windows->visual_info->visualid);
5282 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5283 XVisualClassName(windows->visual_info->klass));
5284 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5285 windows->visual_info->depth);
5286 (void) LogMagickEvent(X11Event,GetMagickModule(),
5287 " size of colormap: %d entries",windows->visual_info->colormap_size);
5288 (void) LogMagickEvent(X11Event,GetMagickModule(),
5289 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5290 windows->visual_info->red_mask,windows->visual_info->green_mask,
5291 windows->visual_info->blue_mask);
5292 (void) LogMagickEvent(X11Event,GetMagickModule(),
5293 " significant bits in color: %d bits",
5294 windows->visual_info->bits_per_rgb);
5295 }
5296 /*
5297 Allocate class and manager hints.
5298 */
5299 windows->class_hints=XAllocClassHint();
5300 windows->manager_hints=XAllocWMHints();
5301 if ((windows->class_hints == (XClassHint *) NULL) ||
5302 (windows->manager_hints == (XWMHints *) NULL))
5303 ThrowXWindowFatalException(ResourceLimitFatalError,
5304 "MemoryAllocationFailed","...");
5305 /*
5306 Determine group leader if we have one.
5307 */
5308 root_window=XRootWindow(display,windows->visual_info->screen);
5309 windows->group_leader.id=(Window) NULL;
5310 if (resource_info->window_group != (char *) NULL)
5311 {
5312 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5313 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5314 strtol((char *) resource_info->window_group,(char **) NULL,0));
5315 if (windows->group_leader.id == (Window) NULL)
5316 windows->group_leader.id=
5317 XWindowByName(display,root_window,resource_info->window_group);
5318 }
5319 return(windows);
5320}
5321
5322/*
5323%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5324% %
5325% %
5326% %
5327% X M a k e C u r s o r %
5328% %
5329% %
5330% %
5331%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5332%
5333% XMakeCursor() creates a crosshairs X11 cursor.
5334%
5335% The format of the XMakeCursor method is:
5336%
5337% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5338% char *background_color,char *foreground_color)
5339%
5340% A description of each parameter follows:
5341%
5342% o display: Specifies a connection to an X server; returned from
5343% XOpenDisplay.
5344%
5345% o window: Specifies the ID of the window for which the cursor is
5346% assigned.
5347%
5348% o colormap: Specifies the ID of the colormap from which the background
5349% and foreground color will be retrieved.
5350%
5351% o background_color: Specifies the color to use for the cursor background.
5352%
5353% o foreground_color: Specifies the color to use for the cursor foreground.
5354%
5355*/
cristybcbda3f2011-09-03 13:01:22 +00005356MagickPrivate Cursor XMakeCursor(Display *display,Window window,
cristy3ed852e2009-09-05 21:47:34 +00005357 Colormap colormap,char *background_color,char *foreground_color)
5358{
5359#define scope_height 17
5360#define scope_x_hot 8
5361#define scope_y_hot 8
5362#define scope_width 17
5363
5364 static const unsigned char
5365 scope_bits[] =
5366 {
5367 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5368 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5369 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5370 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5371 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5372 },
5373 scope_mask_bits[] =
5374 {
5375 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5376 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5377 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5378 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5379 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5380 };
5381
5382 Cursor
5383 cursor;
5384
5385 Pixmap
5386 mask,
5387 source;
5388
5389 XColor
5390 background,
5391 foreground;
5392
5393 assert(display != (Display *) NULL);
5394 assert(window != (Window) NULL);
5395 assert(colormap != (Colormap) NULL);
5396 assert(background_color != (char *) NULL);
5397 assert(foreground_color != (char *) NULL);
5398 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5399 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5400 scope_height);
5401 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5402 scope_width,scope_height);
5403 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5404 {
5405 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5406 return((Cursor) NULL);
5407 }
5408 (void) XParseColor(display,colormap,background_color,&background);
5409 (void) XParseColor(display,colormap,foreground_color,&foreground);
5410 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5411 scope_x_hot,scope_y_hot);
5412 (void) XFreePixmap(display,source);
5413 (void) XFreePixmap(display,mask);
5414 return(cursor);
5415}
5416
5417/*
5418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5419% %
5420% %
5421% %
5422% X M a k e I m a g e %
5423% %
5424% %
5425% %
5426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5427%
5428% XMakeImage() creates an X11 image. If the image size differs from the X11
5429% image size, the image is first resized.
5430%
5431% The format of the XMakeImage method is:
5432%
5433% MagickBooleanType XMakeImage(Display *display,
5434% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005435% unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005436%
5437% A description of each parameter follows:
5438%
5439% o display: Specifies a connection to an X server; returned from
5440% XOpenDisplay.
5441%
5442% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5443%
5444% o window: Specifies a pointer to a XWindowInfo structure.
5445%
5446% o image: the image.
5447%
5448% o width: Specifies the width in pixels of the rectangular area to
5449% display.
5450%
5451% o height: Specifies the height in pixels of the rectangular area to
5452% display.
5453%
cristy051718b2011-08-28 22:49:25 +00005454% o exception: return any errors or warnings in this structure.
5455%
cristy3ed852e2009-09-05 21:47:34 +00005456*/
cristybcbda3f2011-09-03 13:01:22 +00005457MagickPrivate MagickBooleanType XMakeImage(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00005458 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
cristy051718b2011-08-28 22:49:25 +00005459 unsigned int width,unsigned int height,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005460{
5461#define CheckOverflowException(length,width,height) \
5462 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5463
5464 int
5465 depth,
5466 format;
5467
5468 size_t
5469 length;
5470
5471 XImage
5472 *matte_image,
5473 *ximage;
5474
5475 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5476 assert(display != (Display *) NULL);
5477 assert(resource_info != (XResourceInfo *) NULL);
5478 assert(window != (XWindowInfo *) NULL);
5479 assert(width != 0);
5480 assert(height != 0);
5481 if ((window->width == 0) || (window->height == 0))
5482 return(MagickFalse);
5483 /*
5484 Apply user transforms to the image.
5485 */
5486 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5487 (void) XFlush(display);
5488 depth=(int) window->depth;
5489 if (window->destroy)
5490 window->image=DestroyImage(window->image);
5491 window->image=image;
5492 window->destroy=MagickFalse;
5493 if (window->image != (Image *) NULL)
5494 {
5495 if (window->crop_geometry != (char *) NULL)
5496 {
5497 Image
5498 *crop_image;
5499
5500 RectangleInfo
5501 crop_info;
5502
5503 /*
5504 Crop image.
5505 */
5506 window->image->page.x=0;
5507 window->image->page.y=0;
5508 (void) ParsePageGeometry(window->image,window->crop_geometry,
cristy6710d842011-10-20 23:23:00 +00005509 &crop_info,exception);
5510 crop_image=CropImage(window->image,&crop_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005511 if (crop_image != (Image *) NULL)
5512 {
5513 if (window->image != image)
5514 window->image=DestroyImage(window->image);
5515 window->image=crop_image;
5516 window->destroy=MagickTrue;
5517 }
5518 }
5519 if ((width != (unsigned int) window->image->columns) ||
5520 (height != (unsigned int) window->image->rows))
5521 {
5522 Image
5523 *resize_image;
5524
5525 /*
5526 Resize image.
5527 */
5528 resize_image=NewImageList();
5529 if (window->pixel_info->colors != 0)
cristy6710d842011-10-20 23:23:00 +00005530 resize_image=SampleImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005531 else
cristy6710d842011-10-20 23:23:00 +00005532 resize_image=ThumbnailImage(window->image,width,height,exception);
cristy3ed852e2009-09-05 21:47:34 +00005533 if (resize_image != (Image *) NULL)
5534 {
5535 if (window->image != image)
5536 window->image=DestroyImage(window->image);
5537 window->image=resize_image;
5538 window->destroy=MagickTrue;
5539 }
5540 }
5541 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005542 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005543 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005544 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005545 }
5546 /*
5547 Create X image.
5548 */
5549 ximage=(XImage *) NULL;
5550 format=(depth == 1) ? XYBitmap : ZPixmap;
5551#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5552 if (window->shared_memory != MagickFalse)
5553 {
5554 XShmSegmentInfo
5555 *segment_info;
5556
5557 segment_info=(XShmSegmentInfo *) window->segment_info;
5558 segment_info[1].shmid=(-1);
5559 segment_info[1].shmaddr=(char *) NULL;
5560 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5561 (char *) NULL,&segment_info[1],width,height);
5562 if (ximage == (XImage *) NULL)
5563 window->shared_memory=MagickFalse;
5564 length=(size_t) ximage->bytes_per_line*ximage->height;
5565 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5566 window->shared_memory=MagickFalse;
5567 if (window->shared_memory != MagickFalse)
5568 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5569 if (window->shared_memory != MagickFalse)
5570 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5571 if (segment_info[1].shmid < 0)
5572 window->shared_memory=MagickFalse;
5573 if (window->shared_memory != MagickFalse)
5574 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5575 else
5576 {
5577 if (ximage != (XImage *) NULL)
5578 XDestroyImage(ximage);
5579 ximage=(XImage *) NULL;
5580 if (segment_info[1].shmaddr)
5581 {
5582 (void) shmdt(segment_info[1].shmaddr);
5583 segment_info[1].shmaddr=(char *) NULL;
5584 }
5585 if (segment_info[1].shmid >= 0)
5586 {
5587 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5588 segment_info[1].shmid=(-1);
5589 }
5590 }
5591 }
5592#endif
5593 /*
5594 Allocate X image pixel data.
5595 */
5596#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5597 if (window->shared_memory)
5598 {
5599 Status
5600 status;
5601
5602 XShmSegmentInfo
5603 *segment_info;
5604
5605 (void) XSync(display,MagickFalse);
5606 xerror_alert=MagickFalse;
5607 segment_info=(XShmSegmentInfo *) window->segment_info;
5608 ximage->data=segment_info[1].shmaddr;
5609 segment_info[1].readOnly=MagickFalse;
5610 status=XShmAttach(display,&segment_info[1]);
5611 if (status != False)
5612 (void) XSync(display,MagickFalse);
5613 if ((status == False) || (xerror_alert != MagickFalse))
5614 {
5615 window->shared_memory=MagickFalse;
5616 if (status != False)
5617 XShmDetach(display,&segment_info[1]);
5618 if (ximage != (XImage *) NULL)
5619 {
5620 ximage->data=NULL;
5621 XDestroyImage(ximage);
5622 ximage=(XImage *) NULL;
5623 }
5624 if (segment_info[1].shmid >= 0)
5625 {
5626 if (segment_info[1].shmaddr != NULL)
5627 (void) shmdt(segment_info[1].shmaddr);
5628 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5629 segment_info[1].shmid=(-1);
5630 segment_info[1].shmaddr=(char *) NULL;
5631 }
5632 }
5633 }
5634#endif
5635 if (window->shared_memory == MagickFalse)
5636 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5637 (char *) NULL,width,height,XBitmapPad(display),0);
5638 if (ximage == (XImage *) NULL)
5639 {
5640 /*
5641 Unable to create X image.
5642 */
5643 (void) XCheckDefineCursor(display,window->id,window->cursor);
5644 return(MagickFalse);
5645 }
5646 length=(size_t) ximage->bytes_per_line*ximage->height;
5647 if (IsEventLogging())
5648 {
5649 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5650 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5651 ximage->width,ximage->height);
5652 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5653 ximage->format);
5654 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5655 ximage->byte_order);
5656 (void) LogMagickEvent(X11Event,GetMagickModule(),
5657 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5658 ximage->bitmap_bit_order,ximage->bitmap_pad);
5659 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5660 ximage->depth);
5661 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5662 ximage->bytes_per_line);
5663 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5664 ximage->bits_per_pixel);
5665 (void) LogMagickEvent(X11Event,GetMagickModule(),
5666 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5667 ximage->green_mask,ximage->blue_mask);
5668 }
5669 if (window->shared_memory == MagickFalse)
5670 {
5671 if (ximage->format != XYBitmap)
5672 ximage->data=(char *) AcquireQuantumMemory((size_t)
5673 ximage->bytes_per_line,(size_t) ximage->height);
5674 else
5675 ximage->data=(char *) AcquireQuantumMemory((size_t)
5676 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5677 }
5678 if (ximage->data == (char *) NULL)
5679 {
5680 /*
5681 Unable to allocate pixel data.
5682 */
5683 XDestroyImage(ximage);
5684 ximage=(XImage *) NULL;
5685 (void) XCheckDefineCursor(display,window->id,window->cursor);
5686 return(MagickFalse);
5687 }
5688 if (window->ximage != (XImage *) NULL)
5689 {
5690 /*
5691 Destroy previous X image.
5692 */
5693 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5694#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5695 if (window->segment_info != (XShmSegmentInfo *) NULL)
5696 {
5697 XShmSegmentInfo
5698 *segment_info;
5699
5700 segment_info=(XShmSegmentInfo *) window->segment_info;
5701 if (segment_info[0].shmid >= 0)
5702 {
5703 (void) XSync(display,MagickFalse);
5704 (void) XShmDetach(display,&segment_info[0]);
5705 (void) XSync(display,MagickFalse);
5706 if (segment_info[0].shmaddr != (char *) NULL)
5707 (void) shmdt(segment_info[0].shmaddr);
5708 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5709 segment_info[0].shmid=(-1);
5710 segment_info[0].shmaddr=(char *) NULL;
5711 window->ximage->data=(char *) NULL;
5712 }
5713 }
5714#endif
5715 if (window->ximage->data != (char *) NULL)
5716 free(window->ximage->data);
5717 window->ximage->data=(char *) NULL;
5718 XDestroyImage(window->ximage);
5719 window->ximage=(XImage *) NULL;
5720 }
5721#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5722 if (window->segment_info != (XShmSegmentInfo *) NULL)
5723 {
5724 XShmSegmentInfo
5725 *segment_info;
5726
5727 segment_info=(XShmSegmentInfo *) window->segment_info;
5728 segment_info[0]=segment_info[1];
5729 }
5730#endif
5731 window->ximage=ximage;
5732 matte_image=(XImage *) NULL;
5733 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5734 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005735 ((int) width <= XDisplayWidth(display,window->screen)) &&
5736 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005737 {
5738 /*
5739 Create matte image.
5740 */
5741 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5742 (char *) NULL,width,height,XBitmapPad(display),0);
5743 if (IsEventLogging())
5744 {
5745 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5746 (void) LogMagickEvent(X11Event,GetMagickModule(),
5747 " width, height: %dx%d",matte_image->width,matte_image->height);
5748 }
5749 if (matte_image != (XImage *) NULL)
5750 {
5751 /*
5752 Allocate matte image pixel data.
5753 */
5754 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5755 matte_image->bytes_per_line*matte_image->depth,
5756 (size_t) matte_image->height);
5757 if (matte_image->data == (char *) NULL)
5758 {
5759 XDestroyImage(matte_image);
5760 matte_image=(XImage *) NULL;
5761 }
5762 }
5763 }
5764 if (window->matte_image != (XImage *) NULL)
5765 {
5766 /*
5767 Free matte image.
5768 */
5769 if (window->matte_image->data != (char *) NULL)
5770 free(window->matte_image->data);
5771 window->matte_image->data=(char *) NULL;
5772 XDestroyImage(window->matte_image);
5773 window->matte_image=(XImage *) NULL;
5774 }
5775 window->matte_image=matte_image;
5776 if (window->matte_pixmap != (Pixmap) NULL)
5777 {
5778 (void) XFreePixmap(display,window->matte_pixmap);
5779 window->matte_pixmap=(Pixmap) NULL;
5780#if defined(MAGICKCORE_HAVE_SHAPE)
5781 if (window->shape != MagickFalse)
5782 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5783#endif
5784 }
5785 window->stasis=MagickFalse;
5786 /*
5787 Convert pixels to X image data.
5788 */
5789 if (window->image != (Image *) NULL)
5790 {
5791 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5792 (ximage->bitmap_bit_order == LSBFirst)))
5793 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005794 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005795 else
5796 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
cristye941a752011-10-15 01:52:48 +00005797 matte_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00005798 }
5799 if (window->matte_image != (XImage *) NULL)
5800 {
5801 /*
5802 Create matte pixmap.
5803 */
5804 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5805 if (window->matte_pixmap != (Pixmap) NULL)
5806 {
5807 GC
5808 graphics_context;
5809
5810 XGCValues
5811 context_values;
5812
5813 /*
5814 Copy matte image to matte pixmap.
5815 */
cristy4c08aed2011-07-01 19:47:50 +00005816 context_values.background=0;
5817 context_values.foreground=1;
cristy3ed852e2009-09-05 21:47:34 +00005818 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005819 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005820 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5821 window->matte_image,0,0,0,0,width,height);
5822 (void) XFreeGC(display,graphics_context);
5823#if defined(MAGICKCORE_HAVE_SHAPE)
5824 if (window->shape != MagickFalse)
5825 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5826 window->matte_pixmap,ShapeSet);
5827#endif
5828 }
5829 }
5830 (void) XMakePixmap(display,resource_info,window);
5831 /*
5832 Restore cursor.
5833 */
5834 (void) XCheckDefineCursor(display,window->id,window->cursor);
5835 return(MagickTrue);
5836}
5837
5838/*
5839%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5840% %
5841% %
5842% %
5843+ X M a k e I m a g e L S B F i r s t %
5844% %
5845% %
5846% %
5847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5848%
5849% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5850% pixels are copied in least-significant bit and byte first order. The
5851% server's scanline pad is respected. Rather than using one or two general
5852% cases, many special cases are found here to help speed up the image
5853% conversion.
5854%
5855% The format of the XMakeImageLSBFirst method is:
5856%
cristye941a752011-10-15 01:52:48 +00005857% void XMakeImageLSBFirst(Display *display,XWindows *windows,
5858% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005859%
5860% A description of each parameter follows:
5861%
5862% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5863%
5864% o window: Specifies a pointer to a XWindowInfo structure.
5865%
5866% o image: the image.
5867%
5868% o ximage: Specifies a pointer to a XImage structure; returned from
5869% XCreateImage.
5870%
5871% o matte_image: Specifies a pointer to a XImage structure; returned from
5872% XCreateImage.
5873%
cristye941a752011-10-15 01:52:48 +00005874% o exception: return any errors or warnings in this structure.
5875%
cristy3ed852e2009-09-05 21:47:34 +00005876*/
5877static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00005878 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
5879 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00005880{
cristyc57f6942010-11-12 01:47:39 +00005881 CacheView
5882 *canvas_view;
5883
cristy3ed852e2009-09-05 21:47:34 +00005884 Image
5885 *canvas;
5886
5887 int
5888 y;
5889
cristy4c08aed2011-07-01 19:47:50 +00005890 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00005891 *p;
5892
5893 register int
5894 x;
5895
5896 register unsigned char
5897 *q;
5898
5899 unsigned char
5900 bit,
5901 byte;
5902
5903 unsigned int
5904 scanline_pad;
5905
cristyf2faecf2010-05-28 19:19:36 +00005906 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005907 pixel,
5908 *pixels;
5909
5910 XStandardColormap
5911 *map_info;
5912
5913 assert(resource_info != (XResourceInfo *) NULL);
5914 assert(window != (XWindowInfo *) NULL);
5915 assert(image != (Image *) NULL);
5916 if (image->debug != MagickFalse)
5917 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5918 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005919 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005920 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005921 {
5922 char
5923 size[MaxTextExtent];
5924
5925 Image
5926 *pattern;
5927
5928 ImageInfo
5929 *image_info;
5930
5931 image_info=AcquireImageInfo();
5932 (void) CopyMagickString(image_info->filename,
5933 resource_info->image_info->texture != (char *) NULL ?
5934 resource_info->image_info->texture : "pattern:checkerboard",
5935 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00005936 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00005937 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005938 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00005939 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00005940 image_info=DestroyImageInfo(image_info);
5941 if (pattern != (Image *) NULL)
5942 {
cristy6710d842011-10-20 23:23:00 +00005943 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00005944 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00005945 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
5946 exception);
cristy3ed852e2009-09-05 21:47:34 +00005947 pattern=DestroyImage(pattern);
5948 }
5949 }
5950 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5951 ximage->bits_per_pixel) >> 3));
5952 map_info=window->map_info;
5953 pixels=window->pixel_info->pixels;
5954 q=(unsigned char *) ximage->data;
5955 x=0;
cristyc57f6942010-11-12 01:47:39 +00005956 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005957 if (ximage->format == XYBitmap)
5958 {
5959 register unsigned short
5960 polarity;
5961
5962 unsigned char
5963 background,
5964 foreground;
5965
5966 /*
5967 Convert canvas to big-endian bitmap.
5968 */
5969 background=(unsigned char)
5970 (XPixelIntensity(&window->pixel_info->foreground_color) <
5971 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5972 foreground=(unsigned char)
5973 (XPixelIntensity(&window->pixel_info->background_color) <
5974 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
cristy101ab702011-10-13 13:06:32 +00005975 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00005976 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5977 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00005978 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
5979 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00005980 for (y=0; y < (int) canvas->rows; y++)
5981 {
cristyc57f6942010-11-12 01:47:39 +00005982 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00005983 exception);
cristy4c08aed2011-07-01 19:47:50 +00005984 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00005985 break;
cristy3ed852e2009-09-05 21:47:34 +00005986 bit=0;
5987 byte=0;
5988 for (x=0; x < (int) canvas->columns; x++)
5989 {
5990 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00005991 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005992 byte|=foreground;
5993 else
5994 byte|=background;
5995 bit++;
5996 if (bit == 8)
5997 {
5998 *q++=byte;
5999 bit=0;
6000 byte=0;
6001 }
cristyed231572011-07-14 02:18:59 +00006002 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006003 }
6004 if (bit != 0)
6005 *q=byte >> (8-bit);
6006 q+=scanline_pad;
6007 }
6008 }
6009 else
6010 if (window->pixel_info->colors != 0)
6011 switch (ximage->bits_per_pixel)
6012 {
6013 case 2:
6014 {
6015 register unsigned int
6016 nibble;
6017
6018 /*
6019 Convert to 2 bit color-mapped X canvas.
6020 */
6021 for (y=0; y < (int) canvas->rows; y++)
6022 {
cristyc57f6942010-11-12 01:47:39 +00006023 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006024 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006025 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006026 break;
cristy3ed852e2009-09-05 21:47:34 +00006027 nibble=0;
6028 for (x=0; x < (int) canvas->columns; x++)
6029 {
cristy4c08aed2011-07-01 19:47:50 +00006030 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00006031 switch (nibble)
6032 {
6033 case 0:
6034 {
6035 *q=(unsigned char) pixel;
6036 nibble++;
6037 break;
6038 }
6039 case 1:
6040 {
6041 *q|=(unsigned char) (pixel << 2);
6042 nibble++;
6043 break;
6044 }
6045 case 2:
6046 {
6047 *q|=(unsigned char) (pixel << 4);
6048 nibble++;
6049 break;
6050 }
6051 case 3:
6052 {
6053 *q|=(unsigned char) (pixel << 6);
6054 q++;
6055 nibble=0;
6056 break;
6057 }
6058 }
cristyed231572011-07-14 02:18:59 +00006059 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006060 }
6061 q+=scanline_pad;
6062 }
6063 break;
6064 }
6065 case 4:
6066 {
6067 register unsigned int
6068 nibble;
6069
6070 /*
6071 Convert to 4 bit color-mapped X canvas.
6072 */
6073 for (y=0; y < (int) canvas->rows; y++)
6074 {
cristyc57f6942010-11-12 01:47:39 +00006075 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006076 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006077 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006078 break;
cristy3ed852e2009-09-05 21:47:34 +00006079 nibble=0;
6080 for (x=0; x < (int) canvas->columns; x++)
6081 {
cristy4c08aed2011-07-01 19:47:50 +00006082 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006083 switch (nibble)
6084 {
6085 case 0:
6086 {
6087 *q=(unsigned char) pixel;
6088 nibble++;
6089 break;
6090 }
6091 case 1:
6092 {
6093 *q|=(unsigned char) (pixel << 4);
6094 q++;
6095 nibble=0;
6096 break;
6097 }
6098 }
cristyed231572011-07-14 02:18:59 +00006099 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006100 }
6101 q+=scanline_pad;
6102 }
6103 break;
6104 }
6105 case 6:
6106 case 8:
6107 {
6108 /*
6109 Convert to 8 bit color-mapped X canvas.
6110 */
6111 if (resource_info->color_recovery &&
6112 resource_info->quantize_info->dither)
6113 {
cristy6710d842011-10-20 23:23:00 +00006114 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006115 break;
6116 }
6117 for (y=0; y < (int) canvas->rows; y++)
6118 {
cristyc57f6942010-11-12 01:47:39 +00006119 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006120 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006121 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006122 break;
cristy3ed852e2009-09-05 21:47:34 +00006123 for (x=0; x < (int) canvas->columns; x++)
6124 {
cristy4c08aed2011-07-01 19:47:50 +00006125 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006126 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006127 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006128 }
6129 q+=scanline_pad;
6130 }
6131 break;
6132 }
6133 default:
6134 {
6135 register int
6136 k;
6137
6138 register unsigned int
6139 bytes_per_pixel;
6140
6141 unsigned char
cristybb503372010-05-27 20:51:26 +00006142 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006143
6144 /*
6145 Convert to multi-byte color-mapped X canvas.
6146 */
6147 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6148 for (y=0; y < (int) canvas->rows; y++)
6149 {
cristyc57f6942010-11-12 01:47:39 +00006150 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006151 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006152 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006153 break;
cristy3ed852e2009-09-05 21:47:34 +00006154 for (x=0; x < (int) canvas->columns; x++)
6155 {
cristy4c08aed2011-07-01 19:47:50 +00006156 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006157 for (k=0; k < (int) bytes_per_pixel; k++)
6158 {
6159 channel[k]=(unsigned char) pixel;
6160 pixel>>=8;
6161 }
6162 for (k=0; k < (int) bytes_per_pixel; k++)
6163 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006164 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006165 }
6166 q+=scanline_pad;
6167 }
6168 break;
6169 }
6170 }
6171 else
6172 switch (ximage->bits_per_pixel)
6173 {
6174 case 2:
6175 {
6176 register unsigned int
6177 nibble;
6178
6179 /*
6180 Convert to contiguous 2 bit continuous-tone X canvas.
6181 */
6182 for (y=0; y < (int) canvas->rows; y++)
6183 {
6184 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006185 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006186 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006187 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006188 break;
6189 for (x=0; x < (int) canvas->columns; x++)
6190 {
cristy4c08aed2011-07-01 19:47:50 +00006191 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006192 pixel&=0xf;
6193 switch (nibble)
6194 {
6195 case 0:
6196 {
6197 *q=(unsigned char) pixel;
6198 nibble++;
6199 break;
6200 }
6201 case 1:
6202 {
6203 *q|=(unsigned char) (pixel << 2);
6204 nibble++;
6205 break;
6206 }
6207 case 2:
6208 {
6209 *q|=(unsigned char) (pixel << 4);
6210 nibble++;
6211 break;
6212 }
6213 case 3:
6214 {
6215 *q|=(unsigned char) (pixel << 6);
6216 q++;
6217 nibble=0;
6218 break;
6219 }
6220 }
cristyed231572011-07-14 02:18:59 +00006221 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006222 }
6223 q+=scanline_pad;
6224 }
6225 break;
6226 }
6227 case 4:
6228 {
6229 register unsigned int
6230 nibble;
6231
6232 /*
6233 Convert to contiguous 4 bit continuous-tone X canvas.
6234 */
6235 for (y=0; y < (int) canvas->rows; y++)
6236 {
cristyc57f6942010-11-12 01:47:39 +00006237 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006238 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006239 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006240 break;
6241 nibble=0;
6242 for (x=0; x < (int) canvas->columns; x++)
6243 {
cristy4c08aed2011-07-01 19:47:50 +00006244 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006245 pixel&=0xf;
6246 switch (nibble)
6247 {
6248 case 0:
6249 {
6250 *q=(unsigned char) pixel;
6251 nibble++;
6252 break;
6253 }
6254 case 1:
6255 {
6256 *q|=(unsigned char) (pixel << 4);
6257 q++;
6258 nibble=0;
6259 break;
6260 }
6261 }
cristyed231572011-07-14 02:18:59 +00006262 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006263 }
6264 q+=scanline_pad;
6265 }
6266 break;
6267 }
6268 case 6:
6269 case 8:
6270 {
6271 /*
6272 Convert to contiguous 8 bit continuous-tone X canvas.
6273 */
6274 if (resource_info->color_recovery &&
6275 resource_info->quantize_info->dither)
6276 {
cristy6710d842011-10-20 23:23:00 +00006277 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006278 break;
6279 }
6280 for (y=0; y < (int) canvas->rows; y++)
6281 {
cristyc57f6942010-11-12 01:47:39 +00006282 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006283 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006284 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006285 break;
6286 for (x=0; x < (int) canvas->columns; x++)
6287 {
cristy4c08aed2011-07-01 19:47:50 +00006288 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006289 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006290 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006291 }
6292 q+=scanline_pad;
6293 }
6294 break;
6295 }
6296 default:
6297 {
6298 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6299 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6300 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6301 (map_info->blue_mult == 1))
6302 {
6303 /*
6304 Convert to 32 bit continuous-tone X canvas.
6305 */
6306 for (y=0; y < (int) canvas->rows; y++)
6307 {
cristyc57f6942010-11-12 01:47:39 +00006308 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006309 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006310 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006311 break;
6312 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6313 (blue_gamma != 1.0))
6314 {
6315 /*
6316 Gamma correct canvas.
6317 */
6318 for (x=(int) canvas->columns-1; x >= 0; x--)
6319 {
cristyccf844f2010-02-03 23:28:16 +00006320 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006321 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006322 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006323 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006324 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006325 GetPixelRed(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006326 *q++=0;
cristyed231572011-07-14 02:18:59 +00006327 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006328 }
6329 continue;
6330 }
6331 for (x=(int) canvas->columns-1; x >= 0; x--)
6332 {
cristy4c08aed2011-07-01 19:47:50 +00006333 *q++=ScaleQuantumToChar((Quantum)
6334 GetPixelBlue(canvas,p));
6335 *q++=ScaleQuantumToChar((Quantum)
6336 GetPixelGreen(canvas,p));
6337 *q++=ScaleQuantumToChar((Quantum)
6338 GetPixelRed(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006339 *q++=0;
cristyed231572011-07-14 02:18:59 +00006340 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006341 }
6342 }
6343 }
6344 else
6345 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6346 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6347 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6348 (map_info->blue_mult == 65536L))
6349 {
6350 /*
6351 Convert to 32 bit continuous-tone X canvas.
6352 */
6353 for (y=0; y < (int) canvas->rows; y++)
6354 {
cristyc57f6942010-11-12 01:47:39 +00006355 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006356 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006357 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006358 break;
6359 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6360 (blue_gamma != 1.0))
6361 {
6362 /*
6363 Gamma correct canvas.
6364 */
6365 for (x=(int) canvas->columns-1; x >= 0; x--)
6366 {
cristyccf844f2010-02-03 23:28:16 +00006367 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006368 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006369 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006370 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006371 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006372 GetPixelBlue(canvas,p)));
cristy3ed852e2009-09-05 21:47:34 +00006373 *q++=0;
cristyed231572011-07-14 02:18:59 +00006374 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006375 }
6376 continue;
6377 }
6378 for (x=(int) canvas->columns-1; x >= 0; x--)
6379 {
cristyccf844f2010-02-03 23:28:16 +00006380 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006381 GetPixelRed(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006382 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006383 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00006384 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00006385 GetPixelBlue(canvas,p));
cristy3ed852e2009-09-05 21:47:34 +00006386 *q++=0;
cristyed231572011-07-14 02:18:59 +00006387 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006388 }
6389 }
6390 }
6391 else
6392 {
6393 register int
6394 k;
6395
6396 register unsigned int
6397 bytes_per_pixel;
6398
6399 unsigned char
cristybb503372010-05-27 20:51:26 +00006400 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006401
6402 /*
6403 Convert to multi-byte continuous-tone X canvas.
6404 */
6405 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6406 for (y=0; y < (int) canvas->rows; y++)
6407 {
cristyc57f6942010-11-12 01:47:39 +00006408 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006409 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006410 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006411 break;
cristyc57f6942010-11-12 01:47:39 +00006412 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006413 {
cristy4c08aed2011-07-01 19:47:50 +00006414 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006415 for (k=0; k < (int) bytes_per_pixel; k++)
6416 {
6417 channel[k]=(unsigned char) pixel;
6418 pixel>>=8;
6419 }
6420 for (k=0; k < (int) bytes_per_pixel; k++)
6421 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006422 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006423 }
6424 q+=scanline_pad;
6425 }
6426 }
6427 break;
6428 }
6429 }
6430 if (matte_image != (XImage *) NULL)
6431 {
6432 /*
6433 Initialize matte canvas.
6434 */
6435 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6436 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6437 q=(unsigned char *) matte_image->data;
6438 for (y=0; y < (int) canvas->rows; y++)
6439 {
cristyc57f6942010-11-12 01:47:39 +00006440 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006441 exception);
cristy4c08aed2011-07-01 19:47:50 +00006442 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006443 break;
6444 bit=0;
6445 byte=0;
6446 for (x=(int) canvas->columns-1; x >= 0; x--)
6447 {
6448 byte>>=1;
cristy4c08aed2011-07-01 19:47:50 +00006449 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006450 byte|=0x80;
6451 bit++;
6452 if (bit == 8)
6453 {
6454 *q++=byte;
6455 bit=0;
6456 byte=0;
6457 }
cristyed231572011-07-14 02:18:59 +00006458 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006459 }
6460 if (bit != 0)
6461 *q=byte >> (8-bit);
6462 q+=scanline_pad;
6463 }
6464 }
cristyc57f6942010-11-12 01:47:39 +00006465 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006466 if (canvas != image)
6467 canvas=DestroyImage(canvas);
6468}
6469
6470/*
6471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6472% %
6473% %
6474% %
6475+ X M a k e I m a g e M S B F i r s t %
6476% %
6477% %
6478% %
6479%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6480%
6481% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6482% image pixels are copied in most-significant bit and byte first order. The
6483% server's scanline pad is also respected. Rather than using one or two
6484% general cases, many special cases are found here to help speed up the image
6485% conversion.
6486%
6487% The format of the XMakeImageMSBFirst method is:
6488%
cristye941a752011-10-15 01:52:48 +00006489% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
6490% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006491%
6492% A description of each parameter follows:
6493%
6494% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6495%
6496% o window: Specifies a pointer to a XWindowInfo structure.
6497%
6498% o image: the image.
6499%
6500% o ximage: Specifies a pointer to a XImage structure; returned from
6501% XCreateImage.
6502%
6503% o matte_image: Specifies a pointer to a XImage structure; returned from
6504% XCreateImage.
6505%
cristye941a752011-10-15 01:52:48 +00006506% o exception: return any errors or warnings in this structure.
6507%
cristy3ed852e2009-09-05 21:47:34 +00006508*/
6509static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
cristye941a752011-10-15 01:52:48 +00006510 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
6511 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00006512{
cristyc57f6942010-11-12 01:47:39 +00006513 CacheView
6514 *canvas_view;
6515
cristy3ed852e2009-09-05 21:47:34 +00006516 Image
6517 *canvas;
6518
6519 int
6520 y;
6521
6522 register int
6523 x;
6524
cristy4c08aed2011-07-01 19:47:50 +00006525 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +00006526 *p;
6527
6528 register unsigned char
6529 *q;
6530
6531 unsigned char
6532 bit,
6533 byte;
6534
6535 unsigned int
6536 scanline_pad;
6537
cristyf2faecf2010-05-28 19:19:36 +00006538 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006539 pixel,
6540 *pixels;
6541
6542 XStandardColormap
6543 *map_info;
6544
6545 assert(resource_info != (XResourceInfo *) NULL);
6546 assert(window != (XWindowInfo *) NULL);
6547 assert(image != (Image *) NULL);
6548 if (image->debug != MagickFalse)
6549 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6550 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006551 if ((window->immutable != MagickFalse) &&
6552 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006553 {
6554 char
6555 size[MaxTextExtent];
6556
6557 Image
6558 *pattern;
6559
6560 ImageInfo
6561 *image_info;
6562
6563 image_info=AcquireImageInfo();
6564 (void) CopyMagickString(image_info->filename,
6565 resource_info->image_info->texture != (char *) NULL ?
6566 resource_info->image_info->texture : "pattern:checkerboard",
6567 MaxTextExtent);
cristyb51dff52011-05-19 16:55:47 +00006568 (void) FormatLocaleString(size,MaxTextExtent,"%.20gx%.20g",(double)
cristye8c25f92010-06-03 00:53:06 +00006569 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006570 image_info->size=ConstantString(size);
cristy6710d842011-10-20 23:23:00 +00006571 pattern=ReadImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +00006572 image_info=DestroyImageInfo(image_info);
6573 if (pattern != (Image *) NULL)
6574 {
cristy6710d842011-10-20 23:23:00 +00006575 canvas=CloneImage(image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +00006576 if (canvas != (Image *) NULL)
cristye941a752011-10-15 01:52:48 +00006577 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0,
6578 exception);
cristy3ed852e2009-09-05 21:47:34 +00006579 pattern=DestroyImage(pattern);
6580 }
6581 }
cristy4c08aed2011-07-01 19:47:50 +00006582 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
6583 ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00006584 map_info=window->map_info;
6585 pixels=window->pixel_info->pixels;
6586 q=(unsigned char *) ximage->data;
6587 x=0;
cristyc57f6942010-11-12 01:47:39 +00006588 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006589 if (ximage->format == XYBitmap)
6590 {
6591 register unsigned short
6592 polarity;
6593
6594 unsigned char
6595 background,
6596 foreground;
6597
6598 /*
6599 Convert canvas to big-endian bitmap.
6600 */
6601 background=(unsigned char)
6602 (XPixelIntensity(&window->pixel_info->foreground_color) <
6603 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6604 foreground=(unsigned char)
6605 (XPixelIntensity(&window->pixel_info->background_color) <
6606 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
cristy101ab702011-10-13 13:06:32 +00006607 polarity=(unsigned short) ((GetPixelInfoIntensity(
cristy3ed852e2009-09-05 21:47:34 +00006608 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6609 if (canvas->colors == 2)
cristy101ab702011-10-13 13:06:32 +00006610 polarity=GetPixelInfoIntensity(&canvas->colormap[0]) <
6611 GetPixelInfoIntensity(&canvas->colormap[1]);
cristy3ed852e2009-09-05 21:47:34 +00006612 for (y=0; y < (int) canvas->rows; y++)
6613 {
cristyc57f6942010-11-12 01:47:39 +00006614 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00006615 exception);
cristy4c08aed2011-07-01 19:47:50 +00006616 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006617 break;
cristy3ed852e2009-09-05 21:47:34 +00006618 bit=0;
6619 byte=0;
6620 for (x=(int) canvas->columns-1; x >= 0; x--)
6621 {
6622 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00006623 if (GetPixelIndex(canvas,p) == (Quantum) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006624 byte|=foreground;
6625 else
6626 byte|=background;
6627 bit++;
6628 if (bit == 8)
6629 {
6630 *q++=byte;
6631 bit=0;
6632 byte=0;
6633 }
cristyed231572011-07-14 02:18:59 +00006634 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006635 }
6636 if (bit != 0)
6637 *q=byte << (8-bit);
6638 q+=scanline_pad;
6639 }
6640 }
6641 else
6642 if (window->pixel_info->colors != 0)
6643 switch (ximage->bits_per_pixel)
6644 {
6645 case 2:
6646 {
6647 register unsigned int
6648 nibble;
6649
6650 /*
6651 Convert to 2 bit color-mapped X canvas.
6652 */
6653 for (y=0; y < (int) canvas->rows; y++)
6654 {
cristyc57f6942010-11-12 01:47:39 +00006655 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006656 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006657 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006658 break;
cristy3ed852e2009-09-05 21:47:34 +00006659 nibble=0;
6660 for (x=0; x < (int) canvas->columns; x++)
6661 {
cristy4c08aed2011-07-01 19:47:50 +00006662 pixel=pixels[(ssize_t)
6663 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006664 switch (nibble)
6665 {
6666 case 0:
6667 {
6668 *q=(unsigned char) (pixel << 6);
6669 nibble++;
6670 break;
6671 }
6672 case 1:
6673 {
6674 *q|=(unsigned char) (pixel << 4);
6675 nibble++;
6676 break;
6677 }
6678 case 2:
6679 {
6680 *q|=(unsigned char) (pixel << 2);
6681 nibble++;
6682 break;
6683 }
6684 case 3:
6685 {
6686 *q|=(unsigned char) pixel;
6687 q++;
6688 nibble=0;
6689 break;
6690 }
6691 }
cristyed231572011-07-14 02:18:59 +00006692 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006693 }
6694 q+=scanline_pad;
6695 }
6696 break;
6697 }
6698 case 4:
6699 {
6700 register unsigned int
6701 nibble;
6702
6703 /*
6704 Convert to 4 bit color-mapped X canvas.
6705 */
6706 for (y=0; y < (int) canvas->rows; y++)
6707 {
cristyc57f6942010-11-12 01:47:39 +00006708 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006709 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006710 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006711 break;
cristy3ed852e2009-09-05 21:47:34 +00006712 nibble=0;
6713 for (x=0; x < (int) canvas->columns; x++)
6714 {
cristy4c08aed2011-07-01 19:47:50 +00006715 pixel=pixels[(ssize_t)
6716 GetPixelIndex(canvas,p)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006717 switch (nibble)
6718 {
6719 case 0:
6720 {
6721 *q=(unsigned char) (pixel << 4);
6722 nibble++;
6723 break;
6724 }
6725 case 1:
6726 {
6727 *q|=(unsigned char) pixel;
6728 q++;
6729 nibble=0;
6730 break;
6731 }
6732 }
cristyed231572011-07-14 02:18:59 +00006733 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006734 }
6735 q+=scanline_pad;
6736 }
6737 break;
6738 }
6739 case 6:
6740 case 8:
6741 {
6742 /*
6743 Convert to 8 bit color-mapped X canvas.
6744 */
6745 if (resource_info->color_recovery &&
6746 resource_info->quantize_info->dither)
6747 {
cristy6710d842011-10-20 23:23:00 +00006748 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006749 break;
6750 }
6751 for (y=0; y < (int) canvas->rows; y++)
6752 {
cristyc57f6942010-11-12 01:47:39 +00006753 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006754 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006755 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006756 break;
cristy3ed852e2009-09-05 21:47:34 +00006757 for (x=0; x < (int) canvas->columns; x++)
6758 {
cristy6710d842011-10-20 23:23:00 +00006759 pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006760 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006761 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006762 }
6763 q+=scanline_pad;
6764 }
6765 break;
6766 }
6767 default:
6768 {
6769 register int
6770 k;
6771
6772 register unsigned int
6773 bytes_per_pixel;
6774
6775 unsigned char
cristybb503372010-05-27 20:51:26 +00006776 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006777
6778 /*
6779 Convert to 8 bit color-mapped X canvas.
6780 */
6781 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6782 for (y=0; y < (int) canvas->rows; y++)
6783 {
cristyc57f6942010-11-12 01:47:39 +00006784 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006785 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006786 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006787 break;
cristy3ed852e2009-09-05 21:47:34 +00006788 for (x=0; x < (int) canvas->columns; x++)
6789 {
cristy4c08aed2011-07-01 19:47:50 +00006790 pixel=pixels[(ssize_t)
6791 GetPixelIndex(canvas,p)];
cristy3ed852e2009-09-05 21:47:34 +00006792 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6793 {
6794 channel[k]=(unsigned char) pixel;
6795 pixel>>=8;
6796 }
6797 for (k=0; k < (int) bytes_per_pixel; k++)
6798 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00006799 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006800 }
6801 q+=scanline_pad;
6802 }
6803 break;
6804 }
6805 }
6806 else
6807 switch (ximage->bits_per_pixel)
6808 {
6809 case 2:
6810 {
6811 register unsigned int
6812 nibble;
6813
6814 /*
6815 Convert to 4 bit continuous-tone X canvas.
6816 */
6817 for (y=0; y < (int) canvas->rows; y++)
6818 {
cristyc57f6942010-11-12 01:47:39 +00006819 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006820 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006821 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006822 break;
6823 nibble=0;
6824 for (x=(int) canvas->columns-1; x >= 0; x--)
6825 {
cristy4c08aed2011-07-01 19:47:50 +00006826 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006827 pixel&=0xf;
6828 switch (nibble)
6829 {
6830 case 0:
6831 {
6832 *q=(unsigned char) (pixel << 6);
6833 nibble++;
6834 break;
6835 }
6836 case 1:
6837 {
6838 *q|=(unsigned char) (pixel << 4);
6839 nibble++;
6840 break;
6841 }
6842 case 2:
6843 {
6844 *q|=(unsigned char) (pixel << 2);
6845 nibble++;
6846 break;
6847 }
6848 case 3:
6849 {
6850 *q|=(unsigned char) pixel;
6851 q++;
6852 nibble=0;
6853 break;
6854 }
6855 }
cristyed231572011-07-14 02:18:59 +00006856 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006857 }
6858 q+=scanline_pad;
6859 }
6860 break;
6861 }
6862 case 4:
6863 {
6864 register unsigned int
6865 nibble;
6866
6867 /*
6868 Convert to 4 bit continuous-tone X canvas.
6869 */
6870 for (y=0; y < (int) canvas->rows; y++)
6871 {
cristyc57f6942010-11-12 01:47:39 +00006872 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006873 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006874 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006875 break;
6876 nibble=0;
6877 for (x=(int) canvas->columns-1; x >= 0; x--)
6878 {
cristy4c08aed2011-07-01 19:47:50 +00006879 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006880 pixel&=0xf;
6881 switch (nibble)
6882 {
6883 case 0:
6884 {
6885 *q=(unsigned char) (pixel << 4);
6886 nibble++;
6887 break;
6888 }
6889 case 1:
6890 {
6891 *q|=(unsigned char) pixel;
6892 q++;
6893 nibble=0;
6894 break;
6895 }
6896 }
cristyed231572011-07-14 02:18:59 +00006897 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006898 }
6899 q+=scanline_pad;
6900 }
6901 break;
6902 }
6903 case 6:
6904 case 8:
6905 {
6906 /*
6907 Convert to 8 bit continuous-tone X canvas.
6908 */
6909 if (resource_info->color_recovery &&
6910 resource_info->quantize_info->dither)
6911 {
cristy6710d842011-10-20 23:23:00 +00006912 XDitherImage(canvas,ximage,exception);
cristy3ed852e2009-09-05 21:47:34 +00006913 break;
6914 }
6915 for (y=0; y < (int) canvas->rows; y++)
6916 {
cristyc57f6942010-11-12 01:47:39 +00006917 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006918 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006919 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006920 break;
6921 for (x=(int) canvas->columns-1; x >= 0; x--)
6922 {
cristy4c08aed2011-07-01 19:47:50 +00006923 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00006924 *q++=(unsigned char) pixel;
cristyed231572011-07-14 02:18:59 +00006925 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006926 }
6927 q+=scanline_pad;
6928 }
6929 break;
6930 }
6931 default:
6932 {
6933 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6934 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6935 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6936 (map_info->blue_mult == 1))
6937 {
6938 /*
6939 Convert to 32 bit continuous-tone X canvas.
6940 */
6941 for (y=0; y < (int) canvas->rows; y++)
6942 {
cristyc57f6942010-11-12 01:47:39 +00006943 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006944 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006945 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006946 break;
6947 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6948 (blue_gamma != 1.0))
6949 {
6950 /*
6951 Gamma correct canvas.
6952 */
6953 for (x=(int) canvas->columns-1; x >= 0; x--)
6954 {
6955 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006956 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00006957 GetPixelRed(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006958 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00006959 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00006960 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00006961 GetPixelBlue(canvas,p)));
cristyed231572011-07-14 02:18:59 +00006962 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006963 }
6964 continue;
6965 }
6966 for (x=(int) canvas->columns-1; x >= 0; x--)
6967 {
6968 *q++=0;
cristy4c08aed2011-07-01 19:47:50 +00006969 *q++=ScaleQuantumToChar((Quantum)
6970 GetPixelRed(canvas,p));
6971 *q++=ScaleQuantumToChar((Quantum)
6972 GetPixelGreen(canvas,p));
6973 *q++=ScaleQuantumToChar((Quantum)
6974 GetPixelBlue(canvas,p));
cristyed231572011-07-14 02:18:59 +00006975 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006976 }
6977 }
6978 }
6979 else
6980 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6981 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6982 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6983 (map_info->blue_mult == 65536L))
6984 {
6985 /*
6986 Convert to 32 bit continuous-tone X canvas.
6987 */
6988 for (y=0; y < (int) canvas->rows; y++)
6989 {
cristyc57f6942010-11-12 01:47:39 +00006990 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00006991 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00006992 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00006993 break;
6994 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6995 (blue_gamma != 1.0))
6996 {
6997 /*
6998 Gamma correct canvas.
6999 */
7000 for (x=(int) canvas->columns-1; x >= 0; x--)
7001 {
7002 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007003 *q++=ScaleQuantumToChar(XBlueGamma(
cristy4c08aed2011-07-01 19:47:50 +00007004 GetPixelBlue(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00007005 *q++=ScaleQuantumToChar(XGreenGamma(
cristy4c08aed2011-07-01 19:47:50 +00007006 GetPixelGreen(canvas,p)));
cristyccf844f2010-02-03 23:28:16 +00007007 *q++=ScaleQuantumToChar(XRedGamma(
cristy4c08aed2011-07-01 19:47:50 +00007008 GetPixelRed(canvas,p)));
cristyed231572011-07-14 02:18:59 +00007009 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007010 }
7011 continue;
7012 }
7013 for (x=(int) canvas->columns-1; x >= 0; x--)
7014 {
7015 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00007016 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007017 GetPixelBlue(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007018 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007019 GetPixelGreen(canvas,p));
cristyccf844f2010-02-03 23:28:16 +00007020 *q++=ScaleQuantumToChar((Quantum)
cristy4c08aed2011-07-01 19:47:50 +00007021 GetPixelRed(canvas,p));
cristyed231572011-07-14 02:18:59 +00007022 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007023 }
7024 }
7025 }
7026 else
7027 {
7028 register int
7029 k;
7030
7031 register unsigned int
7032 bytes_per_pixel;
7033
7034 unsigned char
cristybb503372010-05-27 20:51:26 +00007035 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00007036
7037 /*
7038 Convert to multi-byte continuous-tone X canvas.
7039 */
7040 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
7041 for (y=0; y < (int) canvas->rows; y++)
7042 {
cristyc57f6942010-11-12 01:47:39 +00007043 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
cristy6710d842011-10-20 23:23:00 +00007044 canvas->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007045 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007046 break;
7047 for (x=(int) canvas->columns-1; x >= 0; x--)
7048 {
cristy4c08aed2011-07-01 19:47:50 +00007049 pixel=XGammaPixel(canvas,map_info,p);
cristy3ed852e2009-09-05 21:47:34 +00007050 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
7051 {
7052 channel[k]=(unsigned char) pixel;
7053 pixel>>=8;
7054 }
7055 for (k=0; k < (int) bytes_per_pixel; k++)
7056 *q++=channel[k];
cristyed231572011-07-14 02:18:59 +00007057 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007058 }
7059 q+=scanline_pad;
7060 }
7061 }
7062 break;
7063 }
7064 }
7065 if (matte_image != (XImage *) NULL)
7066 {
7067 /*
7068 Initialize matte canvas.
7069 */
7070 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7071 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7072 q=(unsigned char *) matte_image->data;
7073 for (y=0; y < (int) canvas->rows; y++)
7074 {
cristyc57f6942010-11-12 01:47:39 +00007075 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
cristy6710d842011-10-20 23:23:00 +00007076 exception);
cristy4c08aed2011-07-01 19:47:50 +00007077 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007078 break;
7079 bit=0;
7080 byte=0;
7081 for (x=(int) canvas->columns-1; x >= 0; x--)
7082 {
7083 byte<<=1;
cristy4c08aed2011-07-01 19:47:50 +00007084 if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007085 byte|=0x01;
7086 bit++;
7087 if (bit == 8)
7088 {
7089 *q++=byte;
7090 bit=0;
7091 byte=0;
7092 }
cristyed231572011-07-14 02:18:59 +00007093 p+=GetPixelChannels(canvas);
cristy3ed852e2009-09-05 21:47:34 +00007094 }
7095 if (bit != 0)
7096 *q=byte << (8-bit);
7097 q+=scanline_pad;
7098 }
7099 }
cristyc57f6942010-11-12 01:47:39 +00007100 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007101 if (canvas != image)
7102 canvas=DestroyImage(canvas);
7103}
7104
7105/*
7106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7107% %
7108% %
7109% %
7110% X M a k e M a g n i f y I m a g e %
7111% %
7112% %
7113% %
7114%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7115%
7116% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7117%
7118% The format of the XMakeMagnifyImage method is:
7119%
cristy6710d842011-10-20 23:23:00 +00007120% void XMakeMagnifyImage(Display *display,XWindows *windows,
7121% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007122%
7123% A description of each parameter follows:
7124%
7125% o display: Specifies a connection to an X server; returned from
7126% XOpenDisplay.
7127%
7128% o windows: Specifies a pointer to a XWindows structure.
7129%
cristy6710d842011-10-20 23:23:00 +00007130% o exception: return any errors or warnings in this structure.
7131%
cristy3ed852e2009-09-05 21:47:34 +00007132*/
cristy6710d842011-10-20 23:23:00 +00007133MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
7134 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007135{
7136 char
7137 tuple[MaxTextExtent];
7138
7139 int
7140 y;
7141
cristy4c08aed2011-07-01 19:47:50 +00007142 PixelInfo
cristy3ed852e2009-09-05 21:47:34 +00007143 pixel;
7144
7145 register int
7146 x;
7147
cristybb503372010-05-27 20:51:26 +00007148 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007149 i;
7150
7151 register unsigned char
7152 *p,
7153 *q;
7154
cristy9d314ff2011-03-09 01:30:28 +00007155 ssize_t
7156 n;
7157
cristy3ed852e2009-09-05 21:47:34 +00007158 static unsigned int
7159 previous_magnify = 0;
7160
7161 static XWindowInfo
7162 magnify_window;
7163
7164 unsigned int
7165 height,
7166 j,
7167 k,
7168 l,
7169 magnify,
7170 scanline_pad,
7171 width;
7172
7173 XImage
7174 *ximage;
7175
7176 /*
7177 Check boundary conditions.
7178 */
7179 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7180 assert(display != (Display *) NULL);
7181 assert(windows != (XWindows *) NULL);
7182 magnify=1;
cristybb503372010-05-27 20:51:26 +00007183 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007184 magnify<<=1;
7185 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7186 magnify<<=1;
7187 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7188 magnify<<=1;
7189 while (magnify > windows->magnify.width)
7190 magnify>>=1;
7191 while (magnify > windows->magnify.height)
7192 magnify>>=1;
7193 if (magnify != previous_magnify)
7194 {
7195 Status
7196 status;
7197
7198 XTextProperty
7199 window_name;
7200
7201 /*
7202 New magnify factor: update magnify window name.
7203 */
7204 i=0;
7205 while ((1 << i) <= (int) magnify)
7206 i++;
cristyb51dff52011-05-19 16:55:47 +00007207 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007208 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007209 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7210 if (status != False)
7211 {
7212 XSetWMName(display,windows->magnify.id,&window_name);
7213 XSetWMIconName(display,windows->magnify.id,&window_name);
7214 (void) XFree((void *) window_name.value);
7215 }
7216 }
7217 previous_magnify=magnify;
7218 ximage=windows->image.ximage;
7219 width=(unsigned int) windows->magnify.ximage->width;
7220 height=(unsigned int) windows->magnify.ximage->height;
7221 if ((windows->magnify.x < 0) ||
7222 (windows->magnify.x >= windows->image.ximage->width))
7223 windows->magnify.x=windows->image.ximage->width >> 1;
7224 x=windows->magnify.x-((width/magnify) >> 1);
7225 if (x < 0)
7226 x=0;
7227 else
7228 if (x > (int) (ximage->width-(width/magnify)))
7229 x=ximage->width-width/magnify;
7230 if ((windows->magnify.y < 0) ||
7231 (windows->magnify.y >= windows->image.ximage->height))
7232 windows->magnify.y=windows->image.ximage->height >> 1;
7233 y=windows->magnify.y-((height/magnify) >> 1);
7234 if (y < 0)
7235 y=0;
7236 else
7237 if (y > (int) (ximage->height-(height/magnify)))
7238 y=ximage->height-height/magnify;
7239 q=(unsigned char *) windows->magnify.ximage->data;
7240 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7241 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7242 if (ximage->bits_per_pixel < 8)
7243 {
7244 register unsigned char
7245 background,
7246 byte,
7247 foreground,
7248 p_bit,
7249 q_bit;
7250
7251 register unsigned int
7252 plane;
7253
7254 XPixelInfo
7255 *pixel_info;
7256
7257 pixel_info=windows->magnify.pixel_info;
7258 switch (ximage->bitmap_bit_order)
7259 {
7260 case LSBFirst:
7261 {
7262 /*
7263 Magnify little-endian bitmap.
7264 */
7265 background=0x00;
7266 foreground=0x80;
7267 if (ximage->format == XYBitmap)
7268 {
7269 background=(unsigned char)
7270 (XPixelIntensity(&pixel_info->foreground_color) <
7271 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7272 foreground=(unsigned char)
7273 (XPixelIntensity(&pixel_info->background_color) <
7274 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7275 if (windows->magnify.depth > 1)
7276 Swap(background,foreground);
7277 }
cristybb503372010-05-27 20:51:26 +00007278 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007279 {
7280 /*
7281 Propogate pixel magnify rows.
7282 */
7283 for (j=0; j < magnify; j++)
7284 {
7285 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7286 ((x*ximage->bits_per_pixel) >> 3);
7287 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7288 q_bit=0;
7289 byte=0;
7290 for (k=0; k < width; k+=magnify)
7291 {
7292 /*
7293 Propogate pixel magnify columns.
7294 */
7295 for (l=0; l < magnify; l++)
7296 {
7297 /*
7298 Propogate each bit plane.
7299 */
7300 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7301 {
7302 byte>>=1;
7303 if (*p & (0x01 << (p_bit+plane)))
7304 byte|=foreground;
7305 else
7306 byte|=background;
7307 q_bit++;
7308 if (q_bit == 8)
7309 {
7310 *q++=byte;
7311 q_bit=0;
7312 byte=0;
7313 }
7314 }
7315 }
7316 p_bit+=ximage->bits_per_pixel;
7317 if (p_bit == 8)
7318 {
7319 p++;
7320 p_bit=0;
7321 }
7322 if (q_bit != 0)
7323 *q=byte >> (8-q_bit);
7324 q+=scanline_pad;
7325 }
7326 }
7327 y++;
7328 }
7329 break;
7330 }
7331 case MSBFirst:
7332 default:
7333 {
7334 /*
7335 Magnify big-endian bitmap.
7336 */
7337 background=0x00;
7338 foreground=0x01;
7339 if (ximage->format == XYBitmap)
7340 {
7341 background=(unsigned char)
7342 (XPixelIntensity(&pixel_info->foreground_color) <
7343 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7344 foreground=(unsigned char)
7345 (XPixelIntensity(&pixel_info->background_color) <
7346 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7347 if (windows->magnify.depth > 1)
7348 Swap(background,foreground);
7349 }
cristybb503372010-05-27 20:51:26 +00007350 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007351 {
7352 /*
7353 Propogate pixel magnify rows.
7354 */
7355 for (j=0; j < magnify; j++)
7356 {
7357 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7358 ((x*ximage->bits_per_pixel) >> 3);
7359 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7360 q_bit=0;
7361 byte=0;
7362 for (k=0; k < width; k+=magnify)
7363 {
7364 /*
7365 Propogate pixel magnify columns.
7366 */
7367 for (l=0; l < magnify; l++)
7368 {
7369 /*
7370 Propogate each bit plane.
7371 */
7372 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7373 {
7374 byte<<=1;
7375 if (*p & (0x80 >> (p_bit+plane)))
7376 byte|=foreground;
7377 else
7378 byte|=background;
7379 q_bit++;
7380 if (q_bit == 8)
7381 {
7382 *q++=byte;
7383 q_bit=0;
7384 byte=0;
7385 }
7386 }
7387 }
7388 p_bit+=ximage->bits_per_pixel;
7389 if (p_bit == 8)
7390 {
7391 p++;
7392 p_bit=0;
7393 }
7394 if (q_bit != 0)
7395 *q=byte << (8-q_bit);
7396 q+=scanline_pad;
7397 }
7398 }
7399 y++;
7400 }
7401 break;
7402 }
7403 }
7404 }
7405 else
7406 switch (ximage->bits_per_pixel)
7407 {
7408 case 6:
7409 case 8:
7410 {
7411 /*
7412 Magnify 8 bit X image.
7413 */
cristybb503372010-05-27 20:51:26 +00007414 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007415 {
7416 /*
7417 Propogate pixel magnify rows.
7418 */
7419 for (j=0; j < magnify; j++)
7420 {
7421 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7422 ((x*ximage->bits_per_pixel) >> 3);
7423 for (k=0; k < width; k+=magnify)
7424 {
7425 /*
7426 Propogate pixel magnify columns.
7427 */
7428 for (l=0; l < magnify; l++)
7429 *q++=(*p);
7430 p++;
7431 }
7432 q+=scanline_pad;
7433 }
7434 y++;
7435 }
7436 break;
7437 }
7438 default:
7439 {
7440 register unsigned int
7441 bytes_per_pixel,
7442 m;
7443
7444 /*
7445 Magnify multi-byte X image.
7446 */
7447 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007448 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007449 {
7450 /*
7451 Propogate pixel magnify rows.
7452 */
7453 for (j=0; j < magnify; j++)
7454 {
7455 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7456 ((x*ximage->bits_per_pixel) >> 3);
7457 for (k=0; k < width; k+=magnify)
7458 {
7459 /*
7460 Propogate pixel magnify columns.
7461 */
7462 for (l=0; l < magnify; l++)
7463 for (m=0; m < bytes_per_pixel; m++)
7464 *q++=(*(p+m));
7465 p+=bytes_per_pixel;
7466 }
7467 q+=scanline_pad;
7468 }
7469 y++;
7470 }
7471 break;
7472 }
7473 }
7474 /*
7475 Copy X image to magnify pixmap.
7476 */
7477 x=windows->magnify.x-((width/magnify) >> 1);
7478 if (x < 0)
7479 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7480 else
7481 if (x > (int) (ximage->width-(width/magnify)))
7482 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7483 else
7484 x=0;
7485 y=windows->magnify.y-((height/magnify) >> 1);
7486 if (y < 0)
7487 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7488 else
7489 if (y > (int) (ximage->height-(height/magnify)))
7490 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7491 else
7492 y=0;
7493 if ((x != 0) || (y != 0))
7494 (void) XFillRectangle(display,windows->magnify.pixmap,
7495 windows->magnify.annotate_context,0,0,width,height);
7496 (void) XPutImage(display,windows->magnify.pixmap,
7497 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7498 height-y);
7499 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7500 (magnify <= (height >> 1))))
7501 {
7502 RectangleInfo
7503 highlight_info;
7504
7505 /*
7506 Highlight center pixel.
7507 */
cristybb503372010-05-27 20:51:26 +00007508 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7509 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007510 highlight_info.width=magnify;
7511 highlight_info.height=magnify;
7512 (void) XDrawRectangle(display,windows->magnify.pixmap,
7513 windows->magnify.highlight_context,(int) highlight_info.x,
7514 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7515 (unsigned int) highlight_info.height-1);
7516 if (magnify > 2)
7517 (void) XDrawRectangle(display,windows->magnify.pixmap,
7518 windows->magnify.annotate_context,(int) highlight_info.x+1,
7519 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7520 (unsigned int) highlight_info.height-3);
7521 }
7522 /*
7523 Show center pixel color.
7524 */
cristyc57f6942010-11-12 01:47:39 +00007525 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
cristy6710d842011-10-20 23:23:00 +00007526 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
cristyb51dff52011-05-19 16:55:47 +00007527 (void) FormatLocaleString(tuple,MaxTextExtent,"%d,%d: ",
cristy3ed852e2009-09-05 21:47:34 +00007528 windows->magnify.x,windows->magnify.y);
7529 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007530 ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007531 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007532 ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007533 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007534 ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007535 if (pixel.colorspace == CMYKColorspace)
7536 {
7537 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007538 ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007539 }
7540 if (pixel.matte != MagickFalse)
7541 {
7542 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
cristyed231572011-07-14 02:18:59 +00007543 ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
cristy3ed852e2009-09-05 21:47:34 +00007544 }
7545 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7546 height=(unsigned int) windows->magnify.font_info->ascent+
7547 windows->magnify.font_info->descent;
7548 x=windows->magnify.font_info->max_bounds.width >> 1;
7549 y=windows->magnify.font_info->ascent+(height >> 2);
7550 (void) XDrawImageString(display,windows->magnify.pixmap,
7551 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7552 GetColorTuple(&pixel,MagickTrue,tuple);
7553 y+=height;
7554 (void) XDrawImageString(display,windows->magnify.pixmap,
7555 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
cristy269c9412011-10-13 23:41:15 +00007556 (void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
cristy6710d842011-10-20 23:23:00 +00007557 exception);
cristy3ed852e2009-09-05 21:47:34 +00007558 y+=height;
7559 (void) XDrawImageString(display,windows->magnify.pixmap,
7560 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7561 /*
7562 Refresh magnify window.
7563 */
7564 magnify_window=windows->magnify;
7565 magnify_window.x=0;
7566 magnify_window.y=0;
7567 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7568}
7569
7570/*
7571%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7572% %
7573% %
7574% %
7575% X M a k e P i x m a p %
7576% %
7577% %
7578% %
7579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7580%
7581% XMakePixmap() creates an X11 pixmap.
7582%
7583% The format of the XMakePixmap method is:
7584%
7585% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7586% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7587% XPixelInfo *pixel)
7588%
7589% A description of each parameter follows:
7590%
7591% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7592%
7593% o display: Specifies a connection to an X server; returned from
7594% XOpenDisplay.
7595%
7596% o window: Specifies a pointer to a XWindowInfo structure.
7597%
cristy3ed852e2009-09-05 21:47:34 +00007598*/
7599static MagickBooleanType XMakePixmap(Display *display,
7600 const XResourceInfo *resource_info,XWindowInfo *window)
7601{
7602 unsigned int
7603 height,
7604 width;
7605
7606 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7607 assert(display != (Display *) NULL);
7608 assert(resource_info != (XResourceInfo *) NULL);
7609 assert(window != (XWindowInfo *) NULL);
7610 if (window->pixmap != (Pixmap) NULL)
7611 {
7612 /*
7613 Destroy previous X pixmap.
7614 */
7615 (void) XFreePixmap(display,window->pixmap);
7616 window->pixmap=(Pixmap) NULL;
7617 }
7618 if (window->use_pixmap == MagickFalse)
7619 return(MagickFalse);
7620 if (window->ximage == (XImage *) NULL)
7621 return(MagickFalse);
7622 /*
7623 Display busy cursor.
7624 */
7625 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7626 (void) XFlush(display);
7627 /*
7628 Create pixmap.
7629 */
7630 width=(unsigned int) window->ximage->width;
7631 height=(unsigned int) window->ximage->height;
7632 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7633 if (window->pixmap == (Pixmap) NULL)
7634 {
7635 /*
7636 Unable to allocate pixmap.
7637 */
7638 (void) XCheckDefineCursor(display,window->id,window->cursor);
7639 return(MagickFalse);
7640 }
7641 /*
7642 Copy X image to pixmap.
7643 */
7644#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7645 if (window->shared_memory)
7646 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7647 window->ximage,0,0,0,0,width,height,MagickTrue);
7648#endif
7649 if (window->shared_memory == MagickFalse)
7650 (void) XPutImage(display,window->pixmap,window->annotate_context,
7651 window->ximage,0,0,0,0,width,height);
7652 if (IsEventLogging())
7653 {
7654 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7655 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7656 width,height);
7657 }
7658 /*
7659 Restore cursor.
7660 */
7661 (void) XCheckDefineCursor(display,window->id,window->cursor);
7662 return(MagickTrue);
7663}
7664
7665/*
7666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7667% %
7668% %
7669% %
7670% X M a k e S t a n d a r d C o l o r m a p %
7671% %
7672% %
7673% %
7674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7675%
7676% XMakeStandardColormap() creates an X11 Standard Colormap.
7677%
7678% The format of the XMakeStandardColormap method is:
7679%
cristy6710d842011-10-20 23:23:00 +00007680% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7681% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7682% XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007683%
7684% A description of each parameter follows:
7685%
7686% o display: Specifies a connection to an X server; returned from
7687% XOpenDisplay.
7688%
7689% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7690% returned from XGetVisualInfo.
7691%
7692% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7693%
7694% o image: the image.
7695%
7696% o map_info: If a Standard Colormap type is specified, this structure is
7697% initialized with info from the Standard Colormap.
7698%
7699% o pixel: Specifies a pointer to a XPixelInfo structure.
7700%
cristy6710d842011-10-20 23:23:00 +00007701% o exception: return any errors or warnings in this structure.
7702%
cristy3ed852e2009-09-05 21:47:34 +00007703*/
7704
7705#if defined(__cplusplus) || defined(c_plusplus)
7706extern "C" {
7707#endif
7708
7709static inline MagickRealType DiversityPixelIntensity(
7710 const DiversityPacket *pixel)
7711{
7712 MagickRealType
7713 intensity;
7714
7715 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7716 return(intensity);
7717}
7718
7719static int IntensityCompare(const void *x,const void *y)
7720{
7721 DiversityPacket
7722 *color_1,
7723 *color_2;
7724
7725 int
7726 diversity;
7727
7728 color_1=(DiversityPacket *) x;
7729 color_2=(DiversityPacket *) y;
7730 diversity=(int) (DiversityPixelIntensity(color_2)-
7731 DiversityPixelIntensity(color_1));
7732 return(diversity);
7733}
7734
7735static int PopularityCompare(const void *x,const void *y)
7736{
7737 DiversityPacket
7738 *color_1,
7739 *color_2;
7740
7741 color_1=(DiversityPacket *) x;
7742 color_2=(DiversityPacket *) y;
7743 return((int) color_2->count-(int) color_1->count);
7744}
7745
7746#if defined(__cplusplus) || defined(c_plusplus)
7747}
7748#endif
7749
cristybb503372010-05-27 20:51:26 +00007750static inline Quantum ScaleXToQuantum(const size_t x,
7751 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007752{
7753 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7754}
7755
cristybcbda3f2011-09-03 13:01:22 +00007756MagickPrivate void XMakeStandardColormap(Display *display,
cristy3ed852e2009-09-05 21:47:34 +00007757 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
cristy6710d842011-10-20 23:23:00 +00007758 XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00007759{
7760 Colormap
7761 colormap;
7762
cristybb503372010-05-27 20:51:26 +00007763 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007764 i;
7765
7766 Status
7767 status;
7768
cristybb503372010-05-27 20:51:26 +00007769 size_t
cristy3ed852e2009-09-05 21:47:34 +00007770 number_colors,
7771 retain_colors;
7772
7773 unsigned short
7774 gray_value;
7775
7776 XColor
7777 color,
7778 *colors,
7779 *p;
7780
7781 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7782 assert(display != (Display *) NULL);
7783 assert(visual_info != (XVisualInfo *) NULL);
7784 assert(map_info != (XStandardColormap *) NULL);
7785 assert(resource_info != (XResourceInfo *) NULL);
7786 assert(pixel != (XPixelInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00007787 if (resource_info->map_type != (char *) NULL)
7788 {
7789 /*
7790 Standard Colormap is already defined (i.e. xstdcmap).
7791 */
cristy4c08aed2011-07-01 19:47:50 +00007792 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007793 pixel);
7794 number_colors=(unsigned int) (map_info->base_pixel+
7795 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7796 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7797 if ((image->matte == MagickFalse) &&
7798 (resource_info->color_recovery == MagickFalse) &&
7799 resource_info->quantize_info->dither &&
7800 (number_colors < MaxColormapSize))
7801 {
7802 Image
7803 *affinity_image;
7804
cristy4c08aed2011-07-01 19:47:50 +00007805 register Quantum
cristyc47d1f82009-11-26 01:44:43 +00007806 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007807
7808 /*
7809 Improve image appearance with error diffusion.
7810 */
cristy6710d842011-10-20 23:23:00 +00007811 affinity_image=AcquireImage((ImageInfo *) NULL,exception);
cristy3ed852e2009-09-05 21:47:34 +00007812 if (affinity_image == (Image *) NULL)
7813 ThrowXWindowFatalException(ResourceLimitFatalError,
7814 "UnableToDitherImage",image->filename);
7815 affinity_image->columns=number_colors;
7816 affinity_image->rows=1;
7817 /*
7818 Initialize colormap image.
7819 */
7820 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7821 1,exception);
cristy4c08aed2011-07-01 19:47:50 +00007822 if (q != (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007823 {
cristybb503372010-05-27 20:51:26 +00007824 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007825 {
cristy4c08aed2011-07-01 19:47:50 +00007826 SetPixelRed(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007827 if (map_info->red_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007828 SetPixelRed(affinity_image,
7829 ScaleXToQuantum((size_t) (i/map_info->red_mult),
7830 map_info->red_max),q);
7831 SetPixelGreen(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007832 if (map_info->green_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007833 SetPixelGreen(affinity_image,
7834 ScaleXToQuantum((size_t) ((i/map_info->green_mult) %
7835 (map_info->green_max+1)),map_info->green_max),q);
7836 SetPixelBlue(affinity_image,0,q);
cristy3ed852e2009-09-05 21:47:34 +00007837 if (map_info->blue_max != 0)
cristy4c08aed2011-07-01 19:47:50 +00007838 SetPixelBlue(affinity_image,
7839 ScaleXToQuantum((size_t) (i % map_info->green_mult),
7840 map_info->blue_max),q);
7841 SetPixelAlpha(affinity_image,
7842 TransparentAlpha,q);
cristyed231572011-07-14 02:18:59 +00007843 q+=GetPixelChannels(affinity_image);
cristy3ed852e2009-09-05 21:47:34 +00007844 }
7845 (void) SyncAuthenticPixels(affinity_image,exception);
7846 (void) RemapImage(resource_info->quantize_info,image,
cristy018f07f2011-09-04 21:15:19 +00007847 affinity_image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007848 }
cristy4c08aed2011-07-01 19:47:50 +00007849 XGetPixelInfo(display,visual_info,map_info,resource_info,image,
cristy3ed852e2009-09-05 21:47:34 +00007850 pixel);
cristy574cc262011-08-05 01:23:58 +00007851 (void) SetImageStorageClass(image,DirectClass,exception);
cristy3ed852e2009-09-05 21:47:34 +00007852 affinity_image=DestroyImage(affinity_image);
7853 }
7854 if (IsEventLogging())
7855 {
7856 (void) LogMagickEvent(X11Event,GetMagickModule(),
7857 "Standard Colormap:");
7858 (void) LogMagickEvent(X11Event,GetMagickModule(),
7859 " colormap id: 0x%lx",map_info->colormap);
7860 (void) LogMagickEvent(X11Event,GetMagickModule(),
7861 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7862 map_info->green_max,map_info->blue_max);
7863 (void) LogMagickEvent(X11Event,GetMagickModule(),
7864 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7865 map_info->green_mult,map_info->blue_mult);
7866 }
7867 return;
7868 }
7869 if ((visual_info->klass != DirectColor) &&
7870 (visual_info->klass != TrueColor))
7871 if ((image->storage_class == DirectClass) ||
7872 ((int) image->colors > visual_info->colormap_size))
7873 {
7874 QuantizeInfo
7875 quantize_info;
7876
7877 /*
7878 Image has more colors than the visual supports.
7879 */
7880 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007881 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy018f07f2011-09-04 21:15:19 +00007882 (void) QuantizeImage(&quantize_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +00007883 }
7884 /*
7885 Free previous and create new colormap.
7886 */
7887 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7888 colormap=XDefaultColormap(display,visual_info->screen);
7889 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7890 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7891 visual_info->visual,visual_info->klass == DirectColor ?
7892 AllocAll : AllocNone);
7893 if (colormap == (Colormap) NULL)
7894 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7895 image->filename);
7896 /*
7897 Initialize the map and pixel info structures.
7898 */
7899 XGetMapInfo(visual_info,colormap,map_info);
cristy4c08aed2011-07-01 19:47:50 +00007900 XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
cristy3ed852e2009-09-05 21:47:34 +00007901 /*
7902 Allocating colors in server colormap is based on visual class.
7903 */
7904 switch (visual_info->klass)
7905 {
7906 case StaticGray:
7907 case StaticColor:
7908 {
7909 /*
7910 Define Standard Colormap for StaticGray or StaticColor visual.
7911 */
7912 number_colors=image->colors;
7913 colors=(XColor *) AcquireQuantumMemory((size_t)
7914 visual_info->colormap_size,sizeof(*colors));
7915 if (colors == (XColor *) NULL)
7916 ThrowXWindowFatalException(ResourceLimitFatalError,
7917 "UnableToCreateColormap",image->filename);
7918 p=colors;
7919 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007920 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007921 {
7922 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7923 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7924 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7925 if (visual_info->klass != StaticColor)
7926 {
7927 gray_value=(unsigned short) XPixelIntensity(&color);
7928 color.red=gray_value;
7929 color.green=gray_value;
7930 color.blue=gray_value;
7931 }
7932 status=XAllocColor(display,colormap,&color);
7933 if (status == False)
7934 {
7935 colormap=XCopyColormapAndFree(display,colormap);
7936 (void) XAllocColor(display,colormap,&color);
7937 }
7938 pixel->pixels[i]=color.pixel;
7939 *p++=color;
7940 }
7941 break;
7942 }
7943 case GrayScale:
7944 case PseudoColor:
7945 {
7946 unsigned int
7947 colormap_type;
7948
7949 /*
7950 Define Standard Colormap for GrayScale or PseudoColor visual.
7951 */
7952 number_colors=image->colors;
7953 colors=(XColor *) AcquireQuantumMemory((size_t)
7954 visual_info->colormap_size,sizeof(*colors));
7955 if (colors == (XColor *) NULL)
7956 ThrowXWindowFatalException(ResourceLimitFatalError,
7957 "UnableToCreateColormap",image->filename);
7958 /*
7959 Preallocate our GUI colors.
7960 */
7961 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7962 (void) XAllocColor(display,colormap,&pixel->background_color);
7963 (void) XAllocColor(display,colormap,&pixel->border_color);
7964 (void) XAllocColor(display,colormap,&pixel->matte_color);
7965 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7966 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7967 (void) XAllocColor(display,colormap,&pixel->depth_color);
7968 (void) XAllocColor(display,colormap,&pixel->trough_color);
7969 for (i=0; i < MaxNumberPens; i++)
7970 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7971 /*
7972 Determine if image colors will "fit" into X server colormap.
7973 */
7974 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007975 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007976 NULL,0,pixel->pixels,(unsigned int) image->colors);
7977 if (status != False)
7978 colormap_type=PrivateColormap;
7979 if (colormap_type == SharedColormap)
7980 {
cristyc57f6942010-11-12 01:47:39 +00007981 CacheView
7982 *image_view;
7983
cristy3ed852e2009-09-05 21:47:34 +00007984 DiversityPacket
7985 *diversity;
7986
7987 int
7988 y;
7989
7990 register int
7991 x;
7992
7993 unsigned short
7994 index;
7995
7996 XColor
7997 *server_colors;
7998
7999 /*
8000 Define Standard colormap for shared GrayScale or PseudoColor visual.
8001 */
8002 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
8003 sizeof(*diversity));
8004 if (diversity == (DiversityPacket *) NULL)
8005 ThrowXWindowFatalException(ResourceLimitFatalError,
8006 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00008007 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008008 {
8009 diversity[i].red=image->colormap[i].red;
8010 diversity[i].green=image->colormap[i].green;
8011 diversity[i].blue=image->colormap[i].blue;
8012 diversity[i].index=(unsigned short) i;
8013 diversity[i].count=0;
8014 }
cristyc57f6942010-11-12 01:47:39 +00008015 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00008016 for (y=0; y < (int) image->rows; y++)
8017 {
cristyc57f6942010-11-12 01:47:39 +00008018 register int
cristy3ed852e2009-09-05 21:47:34 +00008019 x;
8020
cristy4c08aed2011-07-01 19:47:50 +00008021 register const Quantum
cristyc57f6942010-11-12 01:47:39 +00008022 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00008023
cristyc57f6942010-11-12 01:47:39 +00008024 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
8025 image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +00008026 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00008027 break;
cristyc57f6942010-11-12 01:47:39 +00008028 for (x=(int) image->columns-1; x >= 0; x--)
cristy4c08aed2011-07-01 19:47:50 +00008029 {
8030 diversity[(ssize_t) GetPixelIndex(image,p)].count++;
cristyed231572011-07-14 02:18:59 +00008031 p+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +00008032 }
cristy3ed852e2009-09-05 21:47:34 +00008033 }
cristyc57f6942010-11-12 01:47:39 +00008034 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00008035 /*
8036 Sort colors by decreasing intensity.
8037 */
8038 qsort((void *) diversity,image->colors,sizeof(*diversity),
8039 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00008040 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00008041 {
8042 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00008043 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00008044 }
8045 diversity[image->colors-1].count<<=4;
8046 qsort((void *) diversity,image->colors,sizeof(*diversity),
8047 PopularityCompare);
8048 /*
8049 Allocate colors.
8050 */
8051 p=colors;
8052 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008053 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008054 {
8055 index=diversity[i].index;
8056 color.red=
8057 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8058 color.green=
8059 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8060 color.blue=
8061 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8062 if (visual_info->klass != PseudoColor)
8063 {
8064 gray_value=(unsigned short) XPixelIntensity(&color);
8065 color.red=gray_value;
8066 color.green=gray_value;
8067 color.blue=gray_value;
8068 }
8069 status=XAllocColor(display,colormap,&color);
8070 if (status == False)
8071 break;
8072 pixel->pixels[index]=color.pixel;
8073 *p++=color;
8074 }
8075 /*
8076 Read X server colormap.
8077 */
8078 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8079 visual_info->colormap_size,sizeof(*server_colors));
8080 if (server_colors == (XColor *) NULL)
8081 ThrowXWindowFatalException(ResourceLimitFatalError,
8082 "UnableToCreateColormap",image->filename);
8083 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008084 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008085 (void) XQueryColors(display,colormap,server_colors,
8086 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8087 /*
8088 Select remaining colors from X server colormap.
8089 */
cristybb503372010-05-27 20:51:26 +00008090 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008091 {
8092 index=diversity[i].index;
8093 color.red=
8094 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8095 color.green=
8096 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8097 color.blue=
8098 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8099 if (visual_info->klass != PseudoColor)
8100 {
8101 gray_value=(unsigned short) XPixelIntensity(&color);
8102 color.red=gray_value;
8103 color.green=gray_value;
8104 color.blue=gray_value;
8105 }
8106 XBestPixel(display,colormap,server_colors,(unsigned int)
8107 visual_info->colormap_size,&color);
8108 pixel->pixels[index]=color.pixel;
8109 *p++=color;
8110 }
8111 if ((int) image->colors < visual_info->colormap_size)
8112 {
8113 /*
8114 Fill up colors array-- more choices for pen colors.
8115 */
8116 retain_colors=MagickMin((unsigned int)
8117 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008118 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008119 *p++=server_colors[i];
8120 number_colors+=retain_colors;
8121 }
8122 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8123 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8124 break;
8125 }
8126 /*
8127 Define Standard colormap for private GrayScale or PseudoColor visual.
8128 */
8129 if (status == False)
8130 {
8131 /*
8132 Not enough colormap entries in the colormap-- Create a new colormap.
8133 */
8134 colormap=XCreateColormap(display,
8135 XRootWindow(display,visual_info->screen),visual_info->visual,
8136 AllocNone);
8137 if (colormap == (Colormap) NULL)
8138 ThrowXWindowFatalException(ResourceLimitFatalError,
8139 "UnableToCreateColormap",image->filename);
8140 map_info->colormap=colormap;
8141 if ((int) image->colors < visual_info->colormap_size)
8142 {
8143 /*
8144 Retain colors from the default colormap to help lessens the
8145 effects of colormap flashing.
8146 */
8147 retain_colors=MagickMin((unsigned int)
8148 (visual_info->colormap_size-image->colors),256);
8149 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008150 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008151 {
cristyc57f6942010-11-12 01:47:39 +00008152 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008153 p++;
8154 }
8155 (void) XQueryColors(display,
8156 XDefaultColormap(display,visual_info->screen),
8157 colors+image->colors,(int) retain_colors);
8158 /*
8159 Transfer colors from default to private colormap.
8160 */
8161 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008162 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008163 retain_colors);
8164 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008165 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008166 {
8167 p->pixel=pixel->pixels[i];
8168 p++;
8169 }
8170 (void) XStoreColors(display,colormap,colors+image->colors,
8171 (int) retain_colors);
8172 number_colors+=retain_colors;
8173 }
8174 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008175 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008176 image->colors);
8177 }
8178 /*
8179 Store the image colormap.
8180 */
8181 p=colors;
8182 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008183 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008184 {
8185 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8186 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8187 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8188 if (visual_info->klass != PseudoColor)
8189 {
8190 gray_value=(unsigned short) XPixelIntensity(&color);
8191 color.red=gray_value;
8192 color.green=gray_value;
8193 color.blue=gray_value;
8194 }
8195 color.pixel=pixel->pixels[i];
8196 *p++=color;
8197 }
8198 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8199 break;
8200 }
8201 case TrueColor:
8202 case DirectColor:
8203 default:
8204 {
8205 MagickBooleanType
8206 linear_colormap;
8207
8208 /*
8209 Define Standard Colormap for TrueColor or DirectColor visual.
8210 */
8211 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8212 (map_info->green_max*map_info->green_mult)+
8213 (map_info->blue_max*map_info->blue_mult)+1);
8214 linear_colormap=(number_colors > 4096) ||
8215 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8216 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8217 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8218 MagickTrue : MagickFalse;
8219 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008220 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008221 /*
8222 Allocate color array.
8223 */
8224 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8225 if (colors == (XColor *) NULL)
8226 ThrowXWindowFatalException(ResourceLimitFatalError,
8227 "UnableToCreateColormap",image->filename);
8228 /*
8229 Initialize linear color ramp.
8230 */
8231 p=colors;
8232 color.flags=(char) (DoRed | DoGreen | DoBlue);
8233 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008234 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008235 {
8236 color.blue=(unsigned short) 0;
8237 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008238 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008239 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8240 color.green=color.blue;
8241 color.red=color.blue;
8242 color.pixel=XStandardPixel(map_info,&color);
8243 *p++=color;
8244 }
8245 else
cristybb503372010-05-27 20:51:26 +00008246 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008247 {
8248 color.red=(unsigned short) 0;
8249 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008250 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008251 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8252 color.green=(unsigned int) 0;
8253 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008254 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008255 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8256 map_info->green_max));
8257 color.blue=(unsigned short) 0;
8258 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008259 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008260 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8261 color.pixel=XStandardPixel(map_info,&color);
8262 *p++=color;
8263 }
8264 if ((visual_info->klass == DirectColor) &&
8265 (colormap != XDefaultColormap(display,visual_info->screen)))
8266 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8267 else
cristybb503372010-05-27 20:51:26 +00008268 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008269 (void) XAllocColor(display,colormap,&colors[i]);
8270 break;
8271 }
8272 }
8273 if ((visual_info->klass != DirectColor) &&
8274 (visual_info->klass != TrueColor))
8275 {
8276 /*
8277 Set foreground, background, border, etc. pixels.
8278 */
8279 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8280 &pixel->foreground_color);
8281 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8282 &pixel->background_color);
8283 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8284 {
8285 /*
8286 Foreground and background colors must differ.
8287 */
8288 pixel->background_color.red=(~pixel->foreground_color.red);
8289 pixel->background_color.green=
8290 (~pixel->foreground_color.green);
8291 pixel->background_color.blue=
8292 (~pixel->foreground_color.blue);
8293 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8294 &pixel->background_color);
8295 }
8296 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8297 &pixel->border_color);
8298 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8299 &pixel->matte_color);
8300 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8301 &pixel->highlight_color);
8302 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8303 &pixel->shadow_color);
8304 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8305 &pixel->depth_color);
8306 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8307 &pixel->trough_color);
8308 for (i=0; i < MaxNumberPens; i++)
8309 {
8310 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8311 &pixel->pen_colors[i]);
8312 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8313 }
cristyc57f6942010-11-12 01:47:39 +00008314 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008315 }
8316 colors=(XColor *) RelinquishMagickMemory(colors);
8317 if (IsEventLogging())
8318 {
8319 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8320 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8321 map_info->colormap);
8322 (void) LogMagickEvent(X11Event,GetMagickModule(),
8323 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8324 map_info->green_max,map_info->blue_max);
8325 (void) LogMagickEvent(X11Event,GetMagickModule(),
8326 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8327 map_info->green_mult,map_info->blue_mult);
8328 }
8329}
8330
8331/*
8332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8333% %
8334% %
8335% %
8336% X M a k e W i n d o w %
8337% %
8338% %
8339% %
8340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8341%
8342% XMakeWindow() creates an X11 window.
8343%
8344% The format of the XMakeWindow method is:
8345%
8346% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8347% XClassHint *class_hint,XWMHints *manager_hints,
8348% XWindowInfo *window_info)
8349%
8350% A description of each parameter follows:
8351%
8352% o display: Specifies a connection to an X server; returned from
8353% XOpenDisplay.
8354%
8355% o parent: Specifies the parent window_info.
8356%
8357% o argv: Specifies the application's argument list.
8358%
8359% o argc: Specifies the number of arguments.
8360%
8361% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8362%
8363% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8364%
8365% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8366%
8367*/
cristybcbda3f2011-09-03 13:01:22 +00008368MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
cristy3ed852e2009-09-05 21:47:34 +00008369 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8370 XWindowInfo *window_info)
8371{
8372#define MinWindowSize 64
8373
8374 Atom
8375 atom_list[2];
8376
8377 int
8378 gravity;
8379
8380 static XTextProperty
8381 icon_name,
8382 window_name;
8383
8384 Status
8385 status;
8386
8387 XSizeHints
8388 *size_hints;
8389
8390 /*
8391 Set window info hints.
8392 */
8393 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8394 assert(display != (Display *) NULL);
8395 assert(window_info != (XWindowInfo *) NULL);
8396 size_hints=XAllocSizeHints();
8397 if (size_hints == (XSizeHints *) NULL)
8398 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008399 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008400 size_hints->x=window_info->x;
8401 size_hints->y=window_info->y;
8402 size_hints->width=(int) window_info->width;
8403 size_hints->height=(int) window_info->height;
8404 if (window_info->immutable != MagickFalse)
8405 {
8406 /*
8407 Window size cannot be changed.
8408 */
8409 size_hints->min_width=size_hints->width;
8410 size_hints->min_height=size_hints->height;
8411 size_hints->max_width=size_hints->width;
8412 size_hints->max_height=size_hints->height;
8413 size_hints->flags|=PMinSize;
8414 size_hints->flags|=PMaxSize;
8415 }
8416 else
8417 {
8418 /*
8419 Window size can be changed.
8420 */
8421 size_hints->min_width=(int) window_info->min_width;
8422 size_hints->min_height=(int) window_info->min_height;
8423 size_hints->flags|=PResizeInc;
8424 size_hints->width_inc=(int) window_info->width_inc;
8425 size_hints->height_inc=(int) window_info->height_inc;
8426#if !defined(PRE_R4_ICCCM)
8427 size_hints->flags|=PBaseSize;
8428 size_hints->base_width=size_hints->width_inc;
8429 size_hints->base_height=size_hints->height_inc;
8430#endif
8431 }
8432 gravity=NorthWestGravity;
8433 if (window_info->geometry != (char *) NULL)
8434 {
8435 char
8436 default_geometry[MaxTextExtent],
8437 geometry[MaxTextExtent];
8438
8439 int
8440 flags;
8441
8442 register char
8443 *p;
8444
8445 /*
8446 User specified geometry.
8447 */
cristyb51dff52011-05-19 16:55:47 +00008448 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
cristy3ed852e2009-09-05 21:47:34 +00008449 size_hints->width,size_hints->height);
8450 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8451 p=geometry;
8452 while (strlen(p) != 0)
8453 {
8454 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8455 p++;
8456 else
8457 (void) CopyMagickString(p,p+1,MaxTextExtent);
8458 }
8459 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8460 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8461 &size_hints->width,&size_hints->height,&gravity);
8462 if ((flags & WidthValue) && (flags & HeightValue))
8463 size_hints->flags|=USSize;
8464 if ((flags & XValue) && (flags & YValue))
8465 {
8466 size_hints->flags|=USPosition;
8467 window_info->x=size_hints->x;
8468 window_info->y=size_hints->y;
8469 }
8470 }
8471#if !defined(PRE_R4_ICCCM)
8472 size_hints->win_gravity=gravity;
8473 size_hints->flags|=PWinGravity;
8474#endif
8475 if (window_info->id == (Window) NULL)
8476 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8477 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8478 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008479 window_info->visual,(unsigned long) window_info->mask,
8480 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008481 else
8482 {
8483 MagickStatusType
8484 mask;
8485
8486 XEvent
8487 sans_event;
8488
8489 XWindowChanges
8490 window_changes;
8491
8492 /*
8493 Window already exists; change relevant attributes.
8494 */
cristyc57f6942010-11-12 01:47:39 +00008495 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8496 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008497 mask=ConfigureNotify;
8498 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8499 window_changes.x=window_info->x;
8500 window_changes.y=window_info->y;
8501 window_changes.width=(int) window_info->width;
8502 window_changes.height=(int) window_info->height;
8503 mask=(MagickStatusType) (CWWidth | CWHeight);
8504 if (window_info->flags & USPosition)
8505 mask|=CWX | CWY;
8506 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8507 mask,&window_changes);
8508 }
8509 if (window_info->id == (Window) NULL)
8510 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8511 window_info->name);
8512 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8513 if (status == False)
8514 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8515 window_info->name);
8516 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8517 if (status == False)
8518 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8519 window_info->icon_name);
8520 if (window_info->icon_geometry != (char *) NULL)
8521 {
8522 int
8523 flags,
8524 height,
8525 width;
8526
8527 /*
8528 User specified icon geometry.
8529 */
8530 size_hints->flags|=USPosition;
8531 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8532 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8533 &manager_hints->icon_y,&width,&height,&gravity);
8534 if ((flags & XValue) && (flags & YValue))
8535 manager_hints->flags|=IconPositionHint;
8536 }
8537 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8538 size_hints,manager_hints,class_hint);
8539 if (window_name.value != (void *) NULL)
8540 {
8541 (void) XFree((void *) window_name.value);
8542 window_name.value=(unsigned char *) NULL;
8543 window_name.nitems=0;
8544 }
8545 if (icon_name.value != (void *) NULL)
8546 {
8547 (void) XFree((void *) icon_name.value);
8548 icon_name.value=(unsigned char *) NULL;
8549 icon_name.nitems=0;
8550 }
8551 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8552 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8553 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8554 (void) XFree((void *) size_hints);
8555 if (window_info->shape != MagickFalse)
8556 {
8557#if defined(MAGICKCORE_HAVE_SHAPE)
8558 int
8559 error_base,
8560 event_base;
8561
8562 /*
8563 Can we apply a non-rectangular shaping mask?
8564 */
8565 error_base=0;
8566 event_base=0;
8567 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8568 window_info->shape=MagickFalse;
8569#else
8570 window_info->shape=MagickFalse;
8571#endif
8572 }
8573 if (window_info->shared_memory)
8574 {
8575#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8576 /*
8577 Can we use shared memory with this window?
8578 */
8579 if (XShmQueryExtension(display) == 0)
8580 window_info->shared_memory=MagickFalse;
8581#else
8582 window_info->shared_memory=MagickFalse;
8583#endif
8584 }
8585 window_info->image=NewImageList();
8586 window_info->destroy=MagickFalse;
8587}
8588
8589/*
8590%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8591% %
8592% %
8593% %
8594% X M a g i c k P r o g r e s s M o n i t o r %
8595% %
8596% %
8597% %
8598%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8599%
8600% XMagickProgressMonitor() displays the progress a task is making in
8601% completing a task.
8602%
8603% The format of the XMagickProgressMonitor method is:
8604%
8605% void XMagickProgressMonitor(const char *task,
8606% const MagickOffsetType quantum,const MagickSizeType span,
8607% void *client_data)
8608%
8609% A description of each parameter follows:
8610%
8611% o task: Identifies the task in progress.
8612%
8613% o quantum: Specifies the quantum position within the span which represents
8614% how much progress has been made in completing a task.
8615%
8616% o span: Specifies the span relative to completing a task.
8617%
8618% o client_data: Pointer to any client data.
8619%
8620*/
8621
8622static const char *GetLocaleMonitorMessage(const char *text)
8623{
8624 char
8625 message[MaxTextExtent],
8626 tag[MaxTextExtent];
8627
8628 const char
8629 *locale_message;
8630
8631 register char
8632 *p;
8633
8634 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8635 p=strrchr(tag,'/');
8636 if (p != (char *) NULL)
8637 *p='\0';
cristyb51dff52011-05-19 16:55:47 +00008638 (void) FormatLocaleString(message,MaxTextExtent,"Monitor/%s",tag);
cristy3ed852e2009-09-05 21:47:34 +00008639 locale_message=GetLocaleMessage(message);
8640 if (locale_message == message)
8641 return(text);
8642 return(locale_message);
8643}
8644
cristybcbda3f2011-09-03 13:01:22 +00008645MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
cristy3ed852e2009-09-05 21:47:34 +00008646 const MagickOffsetType quantum,const MagickSizeType span,
8647 void *magick_unused(client_data))
8648{
8649 XWindows
8650 *windows;
8651
8652 windows=XSetWindows((XWindows *) ~0);
8653 if (windows == (XWindows *) NULL)
8654 return(MagickTrue);
8655 if (windows->info.mapped != MagickFalse)
8656 XProgressMonitorWidget(windows->display,windows,
8657 GetLocaleMonitorMessage(tag),quantum,span);
8658 return(MagickTrue);
8659}
8660
8661/*
8662%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8663% %
8664% %
8665% %
8666% X Q u e r y C o l o r D a t a b a s e %
8667% %
8668% %
8669% %
8670%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8671%
cristy9950d572011-10-01 18:22:35 +00008672% XQueryColorCompliance() looks up a RGB values for a color given in the target
cristy3ed852e2009-09-05 21:47:34 +00008673% string.
8674%
8675% The format of the XQueryColorDatabase method is:
8676%
cristy9950d572011-10-01 18:22:35 +00008677% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
cristy3ed852e2009-09-05 21:47:34 +00008678%
8679% A description of each parameter follows:
8680%
8681% o target: Specifies the color to lookup in the X color database.
8682%
cristy101ab702011-10-13 13:06:32 +00008683% o color: A pointer to an PixelInfo structure. The RGB value of the target
cristy3ed852e2009-09-05 21:47:34 +00008684% color is returned as this value.
8685%
8686*/
cristy9950d572011-10-01 18:22:35 +00008687MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
cristy3ed852e2009-09-05 21:47:34 +00008688 XColor *color)
8689{
8690 Colormap
8691 colormap;
8692
8693 static Display
8694 *display = (Display *) NULL;
8695
8696 Status
8697 status;
8698
8699 XColor
8700 xcolor;
8701
8702 /*
8703 Initialize color return value.
8704 */
8705 assert(color != (XColor *) NULL);
8706 color->red=0;
8707 color->green=0;
8708 color->blue=0;
8709 color->flags=(char) (DoRed | DoGreen | DoBlue);
8710 if ((target == (char *) NULL) || (*target == '\0'))
8711 target="#ffffffffffff";
8712 /*
8713 Let the X server define the color for us.
8714 */
8715 if (display == (Display *) NULL)
8716 display=XOpenDisplay((char *) NULL);
8717 if (display == (Display *) NULL)
8718 {
8719 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8720 return(MagickFalse);
8721 }
8722 colormap=XDefaultColormap(display,XDefaultScreen(display));
8723 status=XParseColor(display,colormap,(char *) target,&xcolor);
8724 if (status == False)
8725 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8726 else
8727 {
8728 color->red=xcolor.red;
8729 color->green=xcolor.green;
8730 color->blue=xcolor.blue;
8731 color->flags=xcolor.flags;
8732 }
8733 return(status != False ? MagickTrue : MagickFalse);
8734}
8735
8736/*
8737%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8738% %
8739% %
8740% %
8741% X Q u e r y P o s i t i o n %
8742% %
8743% %
8744% %
8745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8746%
8747% XQueryPosition() gets the pointer coordinates relative to a window.
8748%
8749% The format of the XQueryPosition method is:
8750%
8751% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8752%
8753% A description of each parameter follows:
8754%
8755% o display: Specifies a connection to an X server; returned from
8756% XOpenDisplay.
8757%
8758% o window: Specifies a pointer to a Window.
8759%
8760% o x: Return the x coordinate of the pointer relative to the origin of the
8761% window.
8762%
8763% o y: Return the y coordinate of the pointer relative to the origin of the
8764% window.
8765%
8766*/
cristybcbda3f2011-09-03 13:01:22 +00008767MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,int *y)
cristy3ed852e2009-09-05 21:47:34 +00008768{
8769 int
8770 x_root,
8771 y_root;
8772
8773 unsigned int
8774 mask;
8775
8776 Window
8777 root_window;
8778
8779 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8780 assert(display != (Display *) NULL);
8781 assert(window != (Window) NULL);
8782 assert(x != (int *) NULL);
8783 assert(y != (int *) NULL);
8784 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8785 x,y,&mask);
8786}
8787
8788/*
8789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8790% %
8791% %
8792% %
8793% X R e f r e s h W i n d o w %
8794% %
8795% %
8796% %
8797%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8798%
8799% XRefreshWindow() refreshes an image in a X window.
8800%
8801% The format of the XRefreshWindow method is:
8802%
8803% void XRefreshWindow(Display *display,const XWindowInfo *window,
8804% const XEvent *event)
8805%
8806% A description of each parameter follows:
8807%
8808% o display: Specifies a connection to an X server; returned from
8809% XOpenDisplay.
8810%
8811% o window: Specifies a pointer to a XWindowInfo structure.
8812%
8813% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8814% the entire image is refreshed.
8815%
8816*/
cristybcbda3f2011-09-03 13:01:22 +00008817MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
cristy3ed852e2009-09-05 21:47:34 +00008818 const XEvent *event)
8819{
8820 int
8821 x,
8822 y;
8823
8824 unsigned int
8825 height,
8826 width;
8827
8828 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8829 assert(display != (Display *) NULL);
8830 assert(window != (XWindowInfo *) NULL);
8831 if (window->ximage == (XImage *) NULL)
8832 return;
8833 if (event != (XEvent *) NULL)
8834 {
8835 /*
8836 Determine geometry from expose event.
8837 */
8838 x=event->xexpose.x;
8839 y=event->xexpose.y;
8840 width=(unsigned int) event->xexpose.width;
8841 height=(unsigned int) event->xexpose.height;
8842 }
8843 else
8844 {
8845 XEvent
8846 sans_event;
8847
8848 /*
8849 Refresh entire window; discard outstanding expose events.
8850 */
8851 x=0;
8852 y=0;
8853 width=window->width;
8854 height=window->height;
8855 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008856 if (window->matte_pixmap != (Pixmap) NULL)
8857 {
8858#if defined(MAGICKCORE_HAVE_SHAPE)
8859 if (window->shape != MagickFalse)
8860 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8861 window->matte_pixmap,ShapeSet);
8862#endif
8863 }
cristy3ed852e2009-09-05 21:47:34 +00008864 }
8865 /*
8866 Check boundary conditions.
8867 */
8868 if ((window->ximage->width-(x+window->x)) < (int) width)
8869 width=(unsigned int) (window->ximage->width-(x+window->x));
8870 if ((window->ximage->height-(y+window->y)) < (int) height)
8871 height=(unsigned int) (window->ximage->height-(y+window->y));
8872 /*
8873 Refresh image.
8874 */
8875 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008876 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008877 if (window->pixmap != (Pixmap) NULL)
8878 {
8879 if (window->depth > 1)
8880 (void) XCopyArea(display,window->pixmap,window->id,
8881 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8882 else
8883 (void) XCopyPlane(display,window->pixmap,window->id,
8884 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8885 1L);
8886 }
8887 else
8888 {
8889#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8890 if (window->shared_memory)
8891 (void) XShmPutImage(display,window->id,window->annotate_context,
8892 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8893#endif
8894 if (window->shared_memory == MagickFalse)
8895 (void) XPutImage(display,window->id,window->annotate_context,
8896 window->ximage,x+window->x,y+window->y,x,y,width,height);
8897 }
8898 if (window->matte_pixmap != (Pixmap) NULL)
8899 (void) XSetClipMask(display,window->annotate_context,None);
8900 (void) XFlush(display);
8901}
8902
8903/*
8904%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8905% %
8906% %
8907% %
8908% X R e m o t e C o m m a n d %
8909% %
8910% %
8911% %
8912%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8913%
8914% XRemoteCommand() forces a remote display(1) to display the specified
8915% image filename.
8916%
8917% The format of the XRemoteCommand method is:
8918%
8919% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8920% const char *filename)
8921%
8922% A description of each parameter follows:
8923%
8924% o display: Specifies a connection to an X server; returned from
8925% XOpenDisplay.
8926%
8927% o window: Specifies the name or id of an X window.
8928%
8929% o filename: the name of the image filename to display.
8930%
8931*/
8932MagickExport MagickBooleanType XRemoteCommand(Display *display,
8933 const char *window,const char *filename)
8934{
8935 Atom
8936 remote_atom;
8937
8938 Window
8939 remote_window,
8940 root_window;
8941
8942 assert(filename != (char *) NULL);
8943 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8944 if (display == (Display *) NULL)
8945 display=XOpenDisplay((char *) NULL);
8946 if (display == (Display *) NULL)
8947 {
8948 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8949 return(MagickFalse);
8950 }
8951 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8952 remote_window=(Window) NULL;
8953 root_window=XRootWindow(display,XDefaultScreen(display));
8954 if (window != (char *) NULL)
8955 {
8956 /*
8957 Search window hierarchy and identify any clients by name or ID.
8958 */
8959 if (isdigit((unsigned char) *window) != 0)
8960 remote_window=XWindowByID(display,root_window,(Window)
8961 strtol((char *) window,(char **) NULL,0));
8962 if (remote_window == (Window) NULL)
8963 remote_window=XWindowByName(display,root_window,window);
8964 }
8965 if (remote_window == (Window) NULL)
8966 remote_window=XWindowByProperty(display,root_window,remote_atom);
8967 if (remote_window == (Window) NULL)
8968 {
8969 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8970 filename);
8971 return(MagickFalse);
8972 }
8973 /*
8974 Send remote command.
8975 */
8976 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8977 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8978 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8979 (void) XSync(display,MagickFalse);
8980 return(MagickTrue);
8981}
8982
8983/*
8984%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8985% %
8986% %
8987% %
8988% X R e t a i n W i n d o w C o l o r s %
8989% %
8990% %
8991% %
8992%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8993%
8994% XRetainWindowColors() sets X11 color resources on a window. This preserves
8995% the colors associated with an image displayed on the window.
8996%
8997% The format of the XRetainWindowColors method is:
8998%
8999% void XRetainWindowColors(Display *display,const Window window)
9000%
9001% A description of each parameter follows:
9002%
9003% o display: Specifies a connection to an X server; returned from
9004% XOpenDisplay.
9005%
9006% o window: Specifies a pointer to a XWindowInfo structure.
9007%
9008*/
9009MagickExport void XRetainWindowColors(Display *display,const Window window)
9010{
9011 Atom
9012 property;
9013
9014 Pixmap
9015 pixmap;
9016
9017 /*
9018 Put property on the window.
9019 */
9020 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9021 assert(display != (Display *) NULL);
9022 assert(window != (Window) NULL);
9023 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
9024 if (property == (Atom) NULL)
9025 {
9026 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
9027 "_XSETROOT_ID");
9028 return;
9029 }
9030 pixmap=XCreatePixmap(display,window,1,1,1);
9031 if (pixmap == (Pixmap) NULL)
9032 {
9033 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
9034 return;
9035 }
9036 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
9037 (unsigned char *) &pixmap,1);
9038 (void) XSetCloseDownMode(display,RetainPermanent);
9039}
9040
9041/*
9042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9043% %
9044% %
9045% %
9046% X S e l e c t W i n d o w %
9047% %
9048% %
9049% %
9050%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9051%
9052% XSelectWindow() allows a user to select a window using the mouse. If the
9053% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
9054% is returned in the crop_info structure.
9055%
9056% The format of the XSelectWindow function is:
9057%
9058% target_window=XSelectWindow(display,crop_info)
9059%
9060% A description of each parameter follows:
9061%
9062% o window: XSelectWindow returns the window id.
9063%
9064% o display: Specifies a pointer to the Display structure; returned from
9065% XOpenDisplay.
9066%
9067% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9068% contains the extents of any cropping rectangle.
9069%
cristy3ed852e2009-09-05 21:47:34 +00009070*/
9071static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9072{
9073#define MinimumCropArea (unsigned int) 9
9074
9075 Cursor
9076 target_cursor;
9077
9078 GC
9079 annotate_context;
9080
9081 int
9082 presses,
9083 x_offset,
9084 y_offset;
9085
9086 Status
9087 status;
9088
9089 Window
9090 root_window,
9091 target_window;
9092
9093 XEvent
9094 event;
9095
9096 XGCValues
9097 context_values;
9098
9099 /*
9100 Initialize graphic context.
9101 */
9102 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9103 assert(display != (Display *) NULL);
9104 assert(crop_info != (RectangleInfo *) NULL);
9105 root_window=XRootWindow(display,XDefaultScreen(display));
9106 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9107 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9108 context_values.function=GXinvert;
9109 context_values.plane_mask=
9110 context_values.background ^ context_values.foreground;
9111 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009112 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009113 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9114 if (annotate_context == (GC) NULL)
9115 return(MagickFalse);
9116 /*
9117 Grab the pointer using target cursor.
9118 */
9119 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9120 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9121 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9122 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9123 GrabModeAsync,root_window,target_cursor,CurrentTime);
9124 if (status != GrabSuccess)
9125 {
9126 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9127 return((Window) NULL);
9128 }
9129 /*
9130 Select a window.
9131 */
9132 crop_info->width=0;
9133 crop_info->height=0;
9134 presses=0;
9135 target_window=(Window) NULL;
9136 x_offset=0;
9137 y_offset=0;
9138 do
9139 {
9140 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9141 (void) XDrawRectangle(display,root_window,annotate_context,
9142 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9143 (unsigned int) crop_info->height-1);
9144 /*
9145 Allow another event.
9146 */
9147 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9148 (void) XWindowEvent(display,root_window,ButtonPressMask |
9149 ButtonReleaseMask | ButtonMotionMask,&event);
9150 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9151 (void) XDrawRectangle(display,root_window,annotate_context,
9152 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9153 (unsigned int) crop_info->height-1);
9154 switch (event.type)
9155 {
9156 case ButtonPress:
9157 {
9158 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9159 event.xbutton.x,event.xbutton.y);
9160 if (target_window == (Window) NULL)
9161 target_window=root_window;
9162 x_offset=event.xbutton.x_root;
9163 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009164 crop_info->x=(ssize_t) x_offset;
9165 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009166 crop_info->width=0;
9167 crop_info->height=0;
9168 presses++;
9169 break;
9170 }
9171 case ButtonRelease:
9172 {
9173 presses--;
9174 break;
9175 }
9176 case MotionNotify:
9177 {
9178 /*
9179 Discard pending button motion events.
9180 */
9181 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009182 crop_info->x=(ssize_t) event.xmotion.x;
9183 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009184 /*
9185 Check boundary conditions.
9186 */
9187 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009188 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009189 else
9190 {
cristyecd0ab52010-05-30 14:59:20 +00009191 crop_info->width=(size_t) (crop_info->x-x_offset);
9192 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009193 }
9194 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009195 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009196 else
9197 {
cristyecd0ab52010-05-30 14:59:20 +00009198 crop_info->height=(size_t) (crop_info->y-y_offset);
9199 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009200 }
9201 }
9202 default:
9203 break;
9204 }
9205 } while ((target_window == (Window) NULL) || (presses > 0));
9206 (void) XUngrabPointer(display,CurrentTime);
9207 (void) XFreeCursor(display,target_cursor);
9208 (void) XFreeGC(display,annotate_context);
9209 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9210 {
9211 crop_info->width=0;
9212 crop_info->height=0;
9213 }
9214 if ((crop_info->width != 0) && (crop_info->height != 0))
9215 target_window=root_window;
9216 return(target_window);
9217}
9218
9219/*
9220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9221% %
9222% %
9223% %
9224% X S e t C u r s o r S t a t e %
9225% %
9226% %
9227% %
9228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9229%
9230% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9231% reset to their default.
9232%
9233% The format of the XXSetCursorState method is:
9234%
9235% XSetCursorState(display,windows,const MagickStatusType state)
9236%
9237% A description of each parameter follows:
9238%
9239% o display: Specifies a connection to an X server; returned from
9240% XOpenDisplay.
9241%
9242% o windows: Specifies a pointer to a XWindows structure.
9243%
9244% o state: An unsigned integer greater than 0 sets the cursor state
9245% to busy, otherwise the cursor are reset to their default.
9246%
9247*/
cristybcbda3f2011-09-03 13:01:22 +00009248MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
cristy3ed852e2009-09-05 21:47:34 +00009249 const MagickStatusType state)
9250{
9251 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9252 assert(display != (Display *) NULL);
9253 assert(windows != (XWindows *) NULL);
9254 if (state)
9255 {
9256 (void) XCheckDefineCursor(display,windows->image.id,
9257 windows->image.busy_cursor);
9258 (void) XCheckDefineCursor(display,windows->pan.id,
9259 windows->pan.busy_cursor);
9260 (void) XCheckDefineCursor(display,windows->magnify.id,
9261 windows->magnify.busy_cursor);
9262 (void) XCheckDefineCursor(display,windows->command.id,
9263 windows->command.busy_cursor);
9264 }
9265 else
9266 {
9267 (void) XCheckDefineCursor(display,windows->image.id,
9268 windows->image.cursor);
9269 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9270 (void) XCheckDefineCursor(display,windows->magnify.id,
9271 windows->magnify.cursor);
9272 (void) XCheckDefineCursor(display,windows->command.id,
9273 windows->command.cursor);
9274 (void) XCheckDefineCursor(display,windows->command.id,
9275 windows->widget.cursor);
9276 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9277 }
9278 windows->info.mapped=MagickFalse;
9279}
9280
9281/*
9282%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9283% %
9284% %
9285% %
9286% X S e t W i n d o w s %
9287% %
9288% %
9289% %
9290%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9291%
9292% XSetWindows() sets the X windows structure if the windows info is specified.
9293% Otherwise the current windows structure is returned.
9294%
9295% The format of the XSetWindows method is:
9296%
9297% XWindows *XSetWindows(XWindows *windows_info)
9298%
9299% A description of each parameter follows:
9300%
9301% o windows_info: Initialize the Windows structure with this information.
9302%
9303*/
cristybcbda3f2011-09-03 13:01:22 +00009304MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
cristy3ed852e2009-09-05 21:47:34 +00009305{
9306 static XWindows
9307 *windows = (XWindows *) NULL;
9308
9309 if (windows_info != (XWindows *) ~0)
9310 {
9311 windows=(XWindows *) RelinquishMagickMemory(windows);
9312 windows=windows_info;
9313 }
9314 return(windows);
9315}
9316/*
9317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9318% %
9319% %
9320% %
9321% X U s e r P r e f e r e n c e s %
9322% %
9323% %
9324% %
9325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9326%
9327% XUserPreferences() saves the preferences in a configuration file in the
9328% users' home directory.
9329%
9330% The format of the XUserPreferences method is:
9331%
9332% void XUserPreferences(XResourceInfo *resource_info)
9333%
9334% A description of each parameter follows:
9335%
9336% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9337%
9338*/
cristybcbda3f2011-09-03 13:01:22 +00009339MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
cristy3ed852e2009-09-05 21:47:34 +00009340{
9341#if defined(X11_PREFERENCES_PATH)
9342 char
9343 cache[MaxTextExtent],
9344 filename[MaxTextExtent],
9345 specifier[MaxTextExtent];
9346
9347 const char
cristy104cea82009-10-25 02:26:51 +00009348 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009349 *value;
9350
9351 XrmDatabase
9352 preferences_database;
9353
9354 /*
9355 Save user preferences to the client configuration file.
9356 */
9357 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009358 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009359 preferences_database=XrmGetStringDatabase("");
cristyb51dff52011-05-19 16:55:47 +00009360 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009361 value=resource_info->backdrop ? "True" : "False";
9362 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009363 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009364 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9365 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009366 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009367 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009368 value=resource_info->confirm_exit ? "True" : "False";
9369 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009370 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009371 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009372 value=resource_info->confirm_edit ? "True" : "False";
9373 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009374 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009375 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009376 value=resource_info->display_warnings ? "True" : "False";
9377 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009378 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009379 value=resource_info->quantize_info->dither ? "True" : "False";
9380 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009381 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009382 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009383 value=resource_info->gamma_correct ? "True" : "False";
9384 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009385 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.undoCache",client_name);
9386 (void) FormatLocaleString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009387 resource_info->undo_cache);
9388 XrmPutStringResource(&preferences_database,specifier,cache);
cristyb51dff52011-05-19 16:55:47 +00009389 (void) FormatLocaleString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009390 value=resource_info->use_pixmap ? "True" : "False";
9391 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristyb51dff52011-05-19 16:55:47 +00009392 (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009393 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009394 ExpandFilename(filename);
9395 XrmPutFileDatabase(preferences_database,filename);
9396#endif
9397}
9398
9399/*
9400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9401% %
9402% %
9403% %
9404% X V i s u a l C l a s s N a m e %
9405% %
9406% %
9407% %
9408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9409%
9410% XVisualClassName() returns the visual class name as a character string.
9411%
9412% The format of the XVisualClassName method is:
9413%
9414% char *XVisualClassName(const int visual_class)
9415%
9416% A description of each parameter follows:
9417%
9418% o visual_type: XVisualClassName returns the visual class as a character
9419% string.
9420%
9421% o class: Specifies the visual class.
9422%
cristy3ed852e2009-09-05 21:47:34 +00009423*/
9424static const char *XVisualClassName(const int visual_class)
9425{
9426 switch (visual_class)
9427 {
9428 case StaticGray: return("StaticGray");
9429 case GrayScale: return("GrayScale");
9430 case StaticColor: return("StaticColor");
9431 case PseudoColor: return("PseudoColor");
9432 case TrueColor: return("TrueColor");
9433 case DirectColor: return("DirectColor");
9434 }
9435 return("unknown visual class");
9436}
9437
9438/*
9439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9440% %
9441% %
9442% %
9443% X W a r n i n g %
9444% %
9445% %
9446% %
9447%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9448%
9449% XWarning() displays a warning reason in a Notice widget.
9450%
9451% The format of the XWarning method is:
9452%
9453% void XWarning(const unsigned int warning,const char *reason,
9454% const char *description)
9455%
9456% A description of each parameter follows:
9457%
9458% o warning: Specifies the numeric warning category.
9459%
9460% o reason: Specifies the reason to display before terminating the
9461% program.
9462%
9463% o description: Specifies any description to the reason.
9464%
9465*/
cristybcbda3f2011-09-03 13:01:22 +00009466MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
cristy3ed852e2009-09-05 21:47:34 +00009467 const char *reason,const char *description)
9468{
9469 char
9470 text[MaxTextExtent];
9471
9472 XWindows
9473 *windows;
9474
9475 if (reason == (char *) NULL)
9476 return;
9477 (void) CopyMagickString(text,reason,MaxTextExtent);
9478 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9479 windows=XSetWindows((XWindows *) ~0);
9480 XNoticeWidget(windows->display,windows,text,(char *) description);
9481}
9482
9483/*
9484%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9485% %
9486% %
9487% %
9488% X W i n d o w B y I D %
9489% %
9490% %
9491% %
9492%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9493%
9494% XWindowByID() locates a child window with a given ID. If not window with
9495% the given name is found, 0 is returned. Only the window specified and its
9496% subwindows are searched.
9497%
9498% The format of the XWindowByID function is:
9499%
9500% child=XWindowByID(display,window,id)
9501%
9502% A description of each parameter follows:
9503%
9504% o child: XWindowByID returns the window with the specified
9505% id. If no windows are found, XWindowByID returns 0.
9506%
9507% o display: Specifies a pointer to the Display structure; returned from
9508% XOpenDisplay.
9509%
9510% o id: Specifies the id of the window to locate.
9511%
9512*/
cristybcbda3f2011-09-03 13:01:22 +00009513MagickPrivate Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009514 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009515{
9516 RectangleInfo
9517 rectangle_info;
9518
9519 register int
9520 i;
9521
9522 Status
9523 status;
9524
9525 unsigned int
9526 number_children;
9527
9528 Window
9529 child,
9530 *children,
9531 window;
9532
9533 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9534 assert(display != (Display *) NULL);
9535 assert(root_window != (Window) NULL);
9536 if (id == 0)
9537 return(XSelectWindow(display,&rectangle_info));
9538 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009539 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009540 status=XQueryTree(display,root_window,&child,&child,&children,
9541 &number_children);
9542 if (status == False)
9543 return((Window) NULL);
9544 window=(Window) NULL;
9545 for (i=0; i < (int) number_children; i++)
9546 {
9547 /*
9548 Search each child and their children.
9549 */
9550 window=XWindowByID(display,children[i],id);
9551 if (window != (Window) NULL)
9552 break;
9553 }
9554 if (children != (Window *) NULL)
9555 (void) XFree((void *) children);
9556 return(window);
9557}
9558
9559/*
9560%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9561% %
9562% %
9563% %
9564% X W i n d o w B y N a m e %
9565% %
9566% %
9567% %
9568%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9569%
9570% XWindowByName() locates a window with a given name on a display. If no
9571% window with the given name is found, 0 is returned. If more than one window
9572% has the given name, the first one is returned. Only root and its children
9573% are searched.
9574%
9575% The format of the XWindowByName function is:
9576%
9577% window=XWindowByName(display,root_window,name)
9578%
9579% A description of each parameter follows:
9580%
9581% o window: XWindowByName returns the window id.
9582%
9583% o display: Specifies a pointer to the Display structure; returned from
9584% XOpenDisplay.
9585%
9586% o root_window: Specifies the id of the root window.
9587%
9588% o name: Specifies the name of the window to locate.
9589%
9590*/
cristybcbda3f2011-09-03 13:01:22 +00009591MagickPrivate Window XWindowByName(Display *display,const Window root_window,
cristy3ed852e2009-09-05 21:47:34 +00009592 const char *name)
9593{
9594 register int
9595 i;
9596
9597 Status
9598 status;
9599
9600 unsigned int
9601 number_children;
9602
9603 Window
9604 *children,
9605 child,
9606 window;
9607
9608 XTextProperty
9609 window_name;
9610
9611 assert(display != (Display *) NULL);
9612 assert(root_window != (Window) NULL);
9613 assert(name != (char *) NULL);
9614 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9615 if (XGetWMName(display,root_window,&window_name) != 0)
9616 if (LocaleCompare((char *) window_name.value,name) == 0)
9617 return(root_window);
9618 status=XQueryTree(display,root_window,&child,&child,&children,
9619 &number_children);
9620 if (status == False)
9621 return((Window) NULL);
9622 window=(Window) NULL;
9623 for (i=0; i < (int) number_children; i++)
9624 {
9625 /*
9626 Search each child and their children.
9627 */
9628 window=XWindowByName(display,children[i],name);
9629 if (window != (Window) NULL)
9630 break;
9631 }
9632 if (children != (Window *) NULL)
9633 (void) XFree((void *) children);
9634 return(window);
9635}
9636
9637/*
9638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9639% %
9640% %
9641% %
9642% X W i n d o w B y P r o p e r y %
9643% %
9644% %
9645% %
9646%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9647%
9648% XWindowByProperty() locates a child window with a given property. If not
9649% window with the given name is found, 0 is returned. If more than one window
9650% has the given property, the first one is returned. Only the window
9651% specified and its subwindows are searched.
9652%
9653% The format of the XWindowByProperty function is:
9654%
9655% child=XWindowByProperty(display,window,property)
9656%
9657% A description of each parameter follows:
9658%
9659% o child: XWindowByProperty returns the window id with the specified
9660% property. If no windows are found, XWindowByProperty returns 0.
9661%
9662% o display: Specifies a pointer to the Display structure; returned from
9663% XOpenDisplay.
9664%
9665% o property: Specifies the property of the window to locate.
9666%
9667*/
cristybcbda3f2011-09-03 13:01:22 +00009668MagickPrivate Window XWindowByProperty(Display *display,const Window window,
cristy3ed852e2009-09-05 21:47:34 +00009669 const Atom property)
9670{
9671 Atom
9672 type;
9673
9674 int
9675 format;
9676
9677 Status
9678 status;
9679
9680 unsigned char
9681 *data;
9682
9683 unsigned int
9684 i,
9685 number_children;
9686
cristyf2faecf2010-05-28 19:19:36 +00009687 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009688 after,
9689 number_items;
9690
9691 Window
9692 child,
9693 *children,
9694 parent,
9695 root;
9696
9697 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9698 assert(display != (Display *) NULL);
9699 assert(window != (Window) NULL);
9700 assert(property != (Atom) NULL);
9701 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9702 if (status == False)
9703 return((Window) NULL);
9704 type=(Atom) NULL;
9705 child=(Window) NULL;
9706 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9707 {
9708 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9709 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9710 if (data != NULL)
9711 (void) XFree((void *) data);
9712 if ((status == Success) && (type != (Atom) NULL))
9713 child=children[i];
9714 }
9715 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9716 child=XWindowByProperty(display,children[i],property);
9717 if (children != (Window *) NULL)
9718 (void) XFree((void *) children);
9719 return(child);
9720}
9721#else
9722
9723/*
9724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9725% %
9726% %
9727% %
9728% X I m p o r t I m a g e %
9729% %
9730% %
9731% %
9732%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9733%
9734% XImportImage() reads an image from an X window.
9735%
9736% The format of the XImportImage method is:
9737%
9738% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9739%
9740% A description of each parameter follows:
9741%
9742% o image_info: the image info..
9743%
9744% o ximage_info: Specifies a pointer to an XImportInfo structure.
9745%
9746*/
cristybcbda3f2011-09-03 13:01:22 +00009747MagickPrivate Image *XImportImage(const ImageInfo *image_info,
cristy3ed852e2009-09-05 21:47:34 +00009748 XImportInfo *ximage_info)
9749{
9750 assert(image_info != (const ImageInfo *) NULL);
9751 assert(image_info->signature == MagickSignature);
9752 if (image_info->debug != MagickFalse)
9753 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9754 image_info->filename);
9755 assert(ximage_info != (XImportInfo *) NULL);
9756 return((Image *) NULL);
9757}
9758#endif
9759
9760/*
9761%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9762% %
9763% %
9764% %
cristy576974e2009-10-25 20:45:31 +00009765+ X C o m p o n e n t G e n e s i s %
9766% %
9767% %
9768% %
9769%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9770%
9771% XComponentGenesis() instantiates the X component.
9772%
9773% The format of the XComponentGenesis method is:
9774%
9775% MagickBooleanType XComponentGenesis(void)
9776%
9777*/
cristy5ff4eaf2011-09-03 01:38:02 +00009778MagickPrivate MagickBooleanType XComponentGenesis(void)
cristy576974e2009-10-25 20:45:31 +00009779{
9780 return(MagickTrue);
9781}
9782
9783/*
9784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9785% %
9786% %
9787% %
cristy3ed852e2009-09-05 21:47:34 +00009788% X G e t I m p o r t I n f o %
9789% %
9790% %
9791% %
9792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9793%
9794% XGetImportInfo() initializes the XImportInfo structure.
9795%
9796% The format of the XGetImportInfo method is:
9797%
9798% void XGetImportInfo(XImportInfo *ximage_info)
9799%
9800% A description of each parameter follows:
9801%
9802% o ximage_info: Specifies a pointer to an ImageInfo structure.
9803%
9804*/
9805MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9806{
9807 assert(ximage_info != (XImportInfo *) NULL);
9808 ximage_info->frame=MagickFalse;
9809 ximage_info->borders=MagickFalse;
9810 ximage_info->screen=MagickFalse;
9811 ximage_info->descend=MagickTrue;
9812 ximage_info->silent=MagickFalse;
9813}