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