blob: c1e60818fb308d32ab339e5b44a773a0ff8fd08b [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*/
42#include "magick/studio.h"
43#include "magick/animate.h"
44#include "magick/artifact.h"
45#include "magick/blob.h"
46#include "magick/cache.h"
47#include "magick/client.h"
48#include "magick/color.h"
49#include "magick/color-private.h"
cristyb67b4fa2010-04-25 20:03:59 +000050#include "magick/colormap.h"
cristy3ed852e2009-09-05 21:47:34 +000051#include "magick/composite.h"
52#include "magick/display.h"
53#include "magick/exception.h"
54#include "magick/exception-private.h"
55#include "magick/geometry.h"
56#include "magick/identify.h"
57#include "magick/image.h"
58#include "magick/image-private.h"
59#include "magick/list.h"
60#include "magick/locale_.h"
61#include "magick/log.h"
62#include "magick/magick.h"
63#include "magick/memory_.h"
64#include "magick/monitor.h"
65#include "magick/option.h"
66#include "magick/PreRvIcccm.h"
67#include "magick/quantize.h"
68#include "magick/quantum.h"
69#include "magick/quantum-private.h"
70#include "magick/resource_.h"
71#include "magick/resize.h"
72#include "magick/shear.h"
73#include "magick/statistic.h"
74#include "magick/string_.h"
cristyf2f27272009-12-17 14:48:46 +000075#include "magick/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000076#include "magick/transform.h"
77#include "magick/utility.h"
78#include "magick/widget.h"
79#include "magick/xwindow.h"
80#include "magick/xwindow-private.h"
81#include "magick/version.h"
82#if defined(__BEOS__)
83#include <OS.h>
84#endif
85#if defined(MAGICKCORE_X11_DELEGATE)
86#include <X11/Xproto.h>
87#include <X11/Xlocale.h>
88#if defined(MAGICK_HAVE_POLL)
89# include <sys/poll.h>
90#endif
91#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
92#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
93# include <machine/param.h>
94#endif
95#include <sys/ipc.h>
96#include <sys/shm.h>
97#include <X11/extensions/XShm.h>
98#endif
99#if defined(MAGICKCORE_HAVE_SHAPE)
100#include <X11/extensions/shape.h>
101#endif
102
103/*
104 X defines.
105*/
cristyce70c172010-01-07 17:15:30 +0000106#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000107 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
108 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000109#define XGammaPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000110 ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
111 map->red_mult)+ \
112 ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
113 map->green_mult)+ \
114 ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
115 map->blue_mult))
cristyce70c172010-01-07 17:15:30 +0000116#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000117 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
118 QuantumRange)))
cristyce70c172010-01-07 17:15:30 +0000119#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
cristy3ed852e2009-09-05 21:47:34 +0000120 (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
121 QuantumRange)))
cristybb503372010-05-27 20:51:26 +0000122#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
cristy7e9f2332011-04-22 23:12:22 +0000123 (((color)->red*map->red_max/65535L)*map->red_mult)+ \
124 (((color)->green*map->green_max/65535L)*map->green_mult)+ \
125 (((color)->blue*map->blue_max/65535L)*map->blue_mult))
cristy3ed852e2009-09-05 21:47:34 +0000126
127#define AccentuateModulate ScaleCharToQuantum(80)
128#define HighlightModulate ScaleCharToQuantum(125)
129#define ShadowModulate ScaleCharToQuantum(135)
130#define DepthModulate ScaleCharToQuantum(185)
131#define TroughModulate ScaleCharToQuantum(110)
132
133#define XLIB_ILLEGAL_ACCESS 1
134#undef ForgetGravity
135#undef NorthWestGravity
136#undef NorthGravity
137#undef NorthEastGravity
138#undef WestGravity
139#undef CenterGravity
140#undef EastGravity
141#undef SouthWestGravity
142#undef SouthGravity
143#undef SouthEastGravity
144#undef StaticGravity
145
146#undef index
147#if defined(hpux9)
148#define XFD_SET int
149#else
150#define XFD_SET fd_set
151#endif
152
153/*
154 Enumeration declarations.
155*/
156typedef enum
157{
158#undef DoRed
159 DoRed = 0x0001,
160#undef DoGreen
161 DoGreen = 0x0002,
162#undef DoBlue
163 DoBlue = 0x0004,
164 DoMatte = 0x0008
165} XColorFlags;
166
167/*
168 Typedef declarations.
169*/
170typedef struct _DiversityPacket
171{
172 Quantum
173 red,
174 green,
175 blue;
176
177 unsigned short
178 index;
179
cristybb503372010-05-27 20:51:26 +0000180 size_t
cristy3ed852e2009-09-05 21:47:34 +0000181 count;
182} DiversityPacket;
183
184/*
185 Constant declaractions.
186*/
187static MagickBooleanType
188 xerror_alert = MagickFalse;
189
190/*
191 Method prototypes.
192*/
193static const char
194 *XVisualClassName(const int);
195
196static MagickRealType
197 blue_gamma = 1.0,
198 green_gamma = 1.0,
199 red_gamma = 1.0;
200
201static MagickBooleanType
202 XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
203
204static void
205 XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
206 XImage *,XImage *),
207 XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
208 XImage *,XImage *);
209
210static Window
211 XSelectWindow(Display *,RectangleInfo *);
212
213/*
214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215% %
216% %
217% %
218% D e s t r o y X R e s o u r c e s %
219% %
220% %
221% %
222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223%
224% DestroyXResources() destroys any X resources.
225%
226% The format of the DestroyXResources method is:
227%
228% void DestroyXResources()
229%
230% A description of each parameter follows:
231%
232*/
233MagickExport void DestroyXResources(void)
234{
235 register int
236 i;
237
238 unsigned int
239 number_windows;
240
241 XWindowInfo
242 *magick_windows[MaxXWindows];
243
244 XWindows
245 *windows;
246
247 DestroyXWidget();
248 windows=XSetWindows((XWindows *) ~0);
249 if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
250 return;
251 number_windows=0;
252 magick_windows[number_windows++]=(&windows->context);
253 magick_windows[number_windows++]=(&windows->group_leader);
254 magick_windows[number_windows++]=(&windows->backdrop);
255 magick_windows[number_windows++]=(&windows->icon);
256 magick_windows[number_windows++]=(&windows->image);
257 magick_windows[number_windows++]=(&windows->info);
258 magick_windows[number_windows++]=(&windows->magnify);
259 magick_windows[number_windows++]=(&windows->pan);
260 magick_windows[number_windows++]=(&windows->command);
261 magick_windows[number_windows++]=(&windows->widget);
262 magick_windows[number_windows++]=(&windows->popup);
263 magick_windows[number_windows++]=(&windows->context);
264 for (i=0; i < (int) number_windows; i++)
265 {
266 if (magick_windows[i]->mapped != MagickFalse)
267 {
268 (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
269 magick_windows[i]->screen);
270 magick_windows[i]->mapped=MagickFalse;
271 }
272 if (magick_windows[i]->name != (char *) NULL)
273 magick_windows[i]->name=(char *)
274 RelinquishMagickMemory(magick_windows[i]->name);
275 if (magick_windows[i]->icon_name != (char *) NULL)
276 magick_windows[i]->icon_name=(char *)
277 RelinquishMagickMemory(magick_windows[i]->icon_name);
278 if (magick_windows[i]->cursor != (Cursor) NULL)
279 {
280 (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
281 magick_windows[i]->cursor=(Cursor) NULL;
282 }
283 if (magick_windows[i]->busy_cursor != (Cursor) NULL)
284 {
285 (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
286 magick_windows[i]->busy_cursor=(Cursor) NULL;
287 }
288 if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
289 {
290 (void) XFreePixmap(windows->display,
291 magick_windows[i]->highlight_stipple);
292 magick_windows[i]->highlight_stipple=(Pixmap) NULL;
293 }
294 if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
295 {
296 (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
297 magick_windows[i]->shadow_stipple=(Pixmap) NULL;
298 }
299 if (magick_windows[i]->ximage != (XImage *) NULL)
300 {
301 XDestroyImage(magick_windows[i]->ximage);
302 magick_windows[i]->ximage=(XImage *) NULL;
303 }
304 if (magick_windows[i]->pixmap != (Pixmap) NULL)
305 {
306 (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
307 magick_windows[i]->pixmap=(Pixmap) NULL;
308 }
309 if (magick_windows[i]->id != (Window) NULL)
310 {
311 (void) XDestroyWindow(windows->display,magick_windows[i]->id);
312 magick_windows[i]->id=(Window) NULL;
313 }
314 if (magick_windows[i]->destroy != MagickFalse)
315 {
316 if (magick_windows[i]->image != (Image *) NULL)
317 {
318 magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
319 magick_windows[i]->image=NewImageList();
320 }
321 if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
322 {
323 (void) XFreePixmap(windows->display,
324 magick_windows[i]->matte_pixmap);
325 magick_windows[i]->matte_pixmap=(Pixmap) NULL;
326 }
327 }
328 if (magick_windows[i]->segment_info != (void *) NULL)
329 {
330#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
331 XShmSegmentInfo
332 *segment_info;
333
334 segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
335 if (segment_info != (XShmSegmentInfo *) NULL)
336 if (segment_info[0].shmid >= 0)
337 {
338 if (segment_info[0].shmaddr != NULL)
339 (void) shmdt(segment_info[0].shmaddr);
340 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
341 segment_info[0].shmaddr=NULL;
342 segment_info[0].shmid=(-1);
343 }
344#endif
345 magick_windows[i]->segment_info=(void *)
346 RelinquishMagickMemory(magick_windows[i]->segment_info);
347 }
348 }
349 windows->icon_resources=(XResourceInfo *)
350 RelinquishMagickMemory(windows->icon_resources);
351 if (windows->icon_pixel != (XPixelInfo *) NULL)
352 {
cristyf2faecf2010-05-28 19:19:36 +0000353 if (windows->icon_pixel->pixels != (unsigned long *) NULL)
354 windows->icon_pixel->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000355 RelinquishMagickMemory(windows->icon_pixel->pixels);
356 if (windows->icon_pixel->annotate_context != (GC) NULL)
357 XFreeGC(windows->display,windows->icon_pixel->annotate_context);
358 windows->icon_pixel=(XPixelInfo *)
359 RelinquishMagickMemory(windows->icon_pixel);
360 }
361 if (windows->pixel_info != (XPixelInfo *) NULL)
362 {
cristyf2faecf2010-05-28 19:19:36 +0000363 if (windows->pixel_info->pixels != (unsigned long *) NULL)
364 windows->pixel_info->pixels=(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +0000365 RelinquishMagickMemory(windows->pixel_info->pixels);
366 if (windows->pixel_info->annotate_context != (GC) NULL)
367 XFreeGC(windows->display,windows->pixel_info->annotate_context);
368 if (windows->pixel_info->widget_context != (GC) NULL)
369 XFreeGC(windows->display,windows->pixel_info->widget_context);
370 if (windows->pixel_info->highlight_context != (GC) NULL)
371 XFreeGC(windows->display,windows->pixel_info->highlight_context);
372 windows->pixel_info=(XPixelInfo *)
373 RelinquishMagickMemory(windows->pixel_info);
374 }
375 if (windows->font_info != (XFontStruct *) NULL)
376 {
377 XFreeFont(windows->display,windows->font_info);
378 windows->font_info=(XFontStruct *) NULL;
379 }
380 if (windows->class_hints != (XClassHint *) NULL)
381 {
382 if (windows->class_hints->res_name != (char *) NULL)
383 XFree(windows->class_hints->res_name);
384 if (windows->class_hints->res_class != (char *) NULL)
385 XFree(windows->class_hints->res_class);
386 XFree(windows->class_hints);
387 windows->class_hints=(XClassHint *) NULL;
388 }
389 if (windows->manager_hints != (XWMHints *) NULL)
390 {
391 XFree(windows->manager_hints);
392 windows->manager_hints=(XWMHints *) NULL;
393 }
394 if (windows->map_info != (XStandardColormap *) NULL)
395 {
396 XFree(windows->map_info);
397 windows->map_info=(XStandardColormap *) NULL;
398 }
399 if (windows->icon_map != (XStandardColormap *) NULL)
400 {
401 XFree(windows->icon_map);
402 windows->icon_map=(XStandardColormap *) NULL;
403 }
404 if (windows->visual_info != (XVisualInfo *) NULL)
405 {
406 XFree(windows->visual_info);
407 windows->visual_info=(XVisualInfo *) NULL;
408 }
409 if (windows->icon_visual != (XVisualInfo *) NULL)
410 {
411 XFree(windows->icon_visual);
412 windows->icon_visual=(XVisualInfo *) NULL;
413 }
414 (void) XSetWindows((XWindows *) NULL);
415}
416
417/*
418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419% %
420% %
421% %
422% X A n n o t a t e I m a g e %
423% %
424% %
425% %
426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427%
428% XAnnotateImage() annotates the image with text.
429%
430% The format of the XAnnotateImage method is:
431%
432% MagickBooleanType XAnnotateImage(Display *display,
433% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
434%
435% A description of each parameter follows:
436%
437% o display: Specifies a connection to an X server; returned from
438% XOpenDisplay.
439%
440% o pixel: Specifies a pointer to a XPixelInfo structure.
441%
442% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
443%
444% o image: the image.
445%
446*/
447MagickExport MagickBooleanType XAnnotateImage(Display *display,
448 const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
449{
cristyc57f6942010-11-12 01:47:39 +0000450 CacheView
451 *annotate_view;
452
cristy3ed852e2009-09-05 21:47:34 +0000453 GC
454 annotate_context;
455
456 ExceptionInfo
457 *exception;
458
459 Image
460 *annotate_image;
461
462 int
463 x,
464 y;
465
466 MagickBooleanType
467 matte;
468
469 Pixmap
470 annotate_pixmap;
471
472 unsigned int
473 depth,
474 height,
475 width;
476
477 Window
478 root_window;
479
480 XGCValues
481 context_values;
482
483 XImage
484 *annotate_ximage;
485
486 /*
487 Initialize annotated image.
488 */
489 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
490 assert(display != (Display *) NULL);
491 assert(pixel != (XPixelInfo *) NULL);
492 assert(annotate_info != (XAnnotateInfo *) NULL);
493 assert(image != (Image *) NULL);
494 /*
495 Initialize annotated pixmap.
496 */
497 root_window=XRootWindow(display,XDefaultScreen(display));
498 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
499 annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
500 annotate_info->height,depth);
501 if (annotate_pixmap == (Pixmap) NULL)
502 return(MagickFalse);
503 /*
504 Initialize graphics info.
505 */
506 context_values.background=0;
cristybb503372010-05-27 20:51:26 +0000507 context_values.foreground=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +0000508 context_values.font=annotate_info->font_info->fid;
cristyc57f6942010-11-12 01:47:39 +0000509 annotate_context=XCreateGC(display,root_window,(unsigned long)
510 (GCBackground | GCFont | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +0000511 if (annotate_context == (GC) NULL)
512 return(MagickFalse);
513 /*
514 Draw text to pixmap.
515 */
516 (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
517 (int) annotate_info->font_info->ascent,annotate_info->text,
518 (int) strlen(annotate_info->text));
519 (void) XFreeGC(display,annotate_context);
520 /*
521 Initialize annotated X image.
522 */
523 annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
524 annotate_info->height,AllPlanes,ZPixmap);
525 if (annotate_ximage == (XImage *) NULL)
526 return(MagickFalse);
527 (void) XFreePixmap(display,annotate_pixmap);
528 /*
529 Initialize annotated image.
530 */
531 annotate_image=AcquireImage((ImageInfo *) NULL);
532 if (annotate_image == (Image *) NULL)
533 return(MagickFalse);
534 annotate_image->columns=annotate_info->width;
535 annotate_image->rows=annotate_info->height;
536 /*
537 Transfer annotated X image to image.
538 */
539 width=(unsigned int) image->columns;
540 height=(unsigned int) image->rows;
541 x=0;
542 y=0;
543 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +0000544 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
545 &annotate_image->background_color,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +0000546 if (annotate_info->stencil == ForegroundStencil)
547 annotate_image->matte=MagickTrue;
548 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +0000549 annotate_view=AcquireCacheView(annotate_image);
cristy3ed852e2009-09-05 21:47:34 +0000550 for (y=0; y < (int) annotate_image->rows; y++)
551 {
cristyc57f6942010-11-12 01:47:39 +0000552 register int
cristy3ed852e2009-09-05 21:47:34 +0000553 x;
554
555 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000556 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000557
cristyc57f6942010-11-12 01:47:39 +0000558 q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
559 annotate_image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +0000560 if (q == (PixelPacket *) NULL)
561 break;
cristyc57f6942010-11-12 01:47:39 +0000562 for (x=0; x < (int) annotate_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000563 {
cristyce70c172010-01-07 17:15:30 +0000564 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +0000565 if (XGetPixel(annotate_ximage,x,y) == 0)
566 {
567 /*
568 Set this pixel to the background color.
569 */
cristyfba5a8b2011-05-03 17:12:12 +0000570 SetRedPixelComponent(q,ScaleShortToQuantum(pixel->box_color.red));
571 SetGreenPixelComponent(q,ScaleShortToQuantum(pixel->box_color.green));
572 SetBluePixelComponent(q,ScaleShortToQuantum(pixel->box_color.blue));
cristy3ed852e2009-09-05 21:47:34 +0000573 if ((annotate_info->stencil == ForegroundStencil) ||
574 (annotate_info->stencil == OpaqueStencil))
cristyfba5a8b2011-05-03 17:12:12 +0000575 SetOpacityPixelComponent(q,TransparentOpacity);
cristy3ed852e2009-09-05 21:47:34 +0000576 }
577 else
578 {
579 /*
580 Set this pixel to the pen color.
581 */
cristyfba5a8b2011-05-03 17:12:12 +0000582 SetRedPixelComponent(q,ScaleShortToQuantum(pixel->pen_color.red));
583 SetGreenPixelComponent(q,ScaleShortToQuantum(pixel->pen_color.green));
584 SetBluePixelComponent(q,ScaleShortToQuantum(pixel->pen_color.blue));
cristy3ed852e2009-09-05 21:47:34 +0000585 if (annotate_info->stencil == BackgroundStencil)
cristyfba5a8b2011-05-03 17:12:12 +0000586 SetOpacityPixelComponent(q,TransparentOpacity);
cristy3ed852e2009-09-05 21:47:34 +0000587 }
588 q++;
589 }
cristyc57f6942010-11-12 01:47:39 +0000590 if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000591 break;
592 }
cristyc57f6942010-11-12 01:47:39 +0000593 annotate_view=DestroyCacheView(annotate_view);
cristy3ed852e2009-09-05 21:47:34 +0000594 XDestroyImage(annotate_ximage);
595 /*
596 Determine annotate geometry.
597 */
598 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
599 if ((width != (unsigned int) annotate_image->columns) ||
600 (height != (unsigned int) annotate_image->rows))
601 {
602 char
603 image_geometry[MaxTextExtent];
604
605 /*
606 Scale image.
607 */
608 (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
609 width,height);
610 (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
611 }
612 if (annotate_info->degrees != 0.0)
613 {
614 Image
615 *rotate_image;
616
617 int
618 rotations;
619
620 MagickRealType
621 normalized_degrees;
622
623 /*
624 Rotate image.
625 */
626 rotate_image=
627 RotateImage(annotate_image,annotate_info->degrees,&image->exception);
628 if (rotate_image == (Image *) NULL)
629 return(MagickFalse);
630 annotate_image=DestroyImage(annotate_image);
631 annotate_image=rotate_image;
632 /*
633 Annotation is relative to the degree of rotation.
634 */
635 normalized_degrees=annotate_info->degrees;
636 while (normalized_degrees < -45.0)
637 normalized_degrees+=360.0;
638 for (rotations=0; normalized_degrees > 45.0; rotations++)
639 normalized_degrees-=90.0;
640 switch (rotations % 4)
641 {
642 default:
643 case 0:
644 break;
645 case 1:
646 {
647 /*
648 Rotate 90 degrees.
649 */
650 x-=(int) annotate_image->columns/2;
651 y+=(int) annotate_image->columns/2;
652 break;
653 }
654 case 2:
655 {
656 /*
657 Rotate 180 degrees.
658 */
659 x=x-(int) annotate_image->columns;
660 break;
661 }
662 case 3:
663 {
664 /*
665 Rotate 270 degrees.
666 */
667 x=x-(int) annotate_image->columns/2;
668 y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
669 break;
670 }
671 }
672 }
673 /*
674 Composite text onto the image.
675 */
676 (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
677 matte=image->matte;
678 (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
cristyc57f6942010-11-12 01:47:39 +0000679 OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +0000680 image->matte=matte;
681 annotate_image=DestroyImage(annotate_image);
682 return(MagickTrue);
683}
684
685/*
686%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
687% %
688% %
689% %
690% X B e s t F o n t %
691% %
692% %
693% %
694%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
695%
696% XBestFont() returns the "best" font. "Best" is defined as a font specified
697% in the X resource database or a font such that the text width displayed
698% with the font does not exceed the specified maximum width.
699%
700% The format of the XBestFont method is:
701%
702% XFontStruct *XBestFont(Display *display,
703% const XResourceInfo *resource_info,const MagickBooleanType text_font)
704%
705% A description of each parameter follows:
706%
707% o font: XBestFont returns a pointer to a XFontStruct structure.
708%
709% o display: Specifies a connection to an X server; returned from
710% XOpenDisplay.
711%
712% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
713%
714% o text_font: True is font should be mono-spaced (typewriter style).
715%
cristy3ed852e2009-09-05 21:47:34 +0000716*/
717
718static char **FontToList(char *font)
719{
720 char
721 **fontlist;
722
723 register char
724 *p,
725 *q;
726
727 register int
728 i;
729
730 unsigned int
731 fonts;
732
733 if (font == (char *) NULL)
734 return((char **) NULL);
735 /*
736 Convert string to an ASCII list.
737 */
738 fonts=1U;
739 for (p=font; *p != '\0'; p++)
740 if ((*p == ':') || (*p == ';') || (*p == ','))
741 fonts++;
742 fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
743 if (fontlist == (char **) NULL)
744 {
745 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
746 font);
747 return((char **) NULL);
748 }
749 p=font;
750 for (i=0; i < (int) fonts; i++)
751 {
752 for (q=p; *q != '\0'; q++)
753 if ((*q == ':') || (*q == ';') || (*q == ','))
754 break;
755 fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
756 sizeof(*fontlist[i]));
757 if (fontlist[i] == (char *) NULL)
758 {
759 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
760 font);
761 return((char **) NULL);
762 }
763 (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
764 p=q+1;
765 }
766 fontlist[i]=(char *) NULL;
767 return(fontlist);
768}
769
770MagickExport XFontStruct *XBestFont(Display *display,
771 const XResourceInfo *resource_info,const MagickBooleanType text_font)
772{
773 static const char
774 *Fonts[]=
775 {
776 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
777 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
778 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
779 "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
780 "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
781 "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
782 "variable",
783 "fixed",
784 (char *) NULL
785 },
786 *TextFonts[]=
787 {
788 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
789 "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
790 "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
791 "fixed",
792 (char *) NULL
793 };
794
795 char
796 *font_name;
797
798 register const char
799 **p;
800
801 XFontStruct
802 *font_info;
803
804 font_info=(XFontStruct *) NULL;
805 font_name=resource_info->font;
806 if (text_font != MagickFalse)
807 font_name=resource_info->text_font;
808 if ((font_name != (char *) NULL) && (*font_name != '\0'))
809 {
810 char
811 **fontlist;
812
813 register int
814 i;
815
816 /*
817 Load preferred font specified in the X resource database.
818 */
819 fontlist=FontToList(font_name);
820 if (fontlist != (char **) NULL)
821 {
822 for (i=0; fontlist[i] != (char *) NULL; i++)
823 {
824 if (font_info == (XFontStruct *) NULL)
825 font_info=XLoadQueryFont(display,fontlist[i]);
826 fontlist[i]=DestroyString(fontlist[i]);
827 }
828 fontlist=(char **) RelinquishMagickMemory(fontlist);
829 }
830 if (font_info == (XFontStruct *) NULL)
831 ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
832 }
833 /*
834 Load fonts from list of fonts until one is found.
835 */
836 p=Fonts;
837 if (text_font != MagickFalse)
838 p=TextFonts;
839 if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
840 p++;
841 while (*p != (char *) NULL)
842 {
843 if (font_info != (XFontStruct *) NULL)
844 break;
845 font_info=XLoadQueryFont(display,(char *) *p);
846 p++;
847 }
848 return(font_info);
849}
850
851/*
852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853% %
854% %
855% %
856% X B e s t I c o n S i z e %
857% %
858% %
859% %
860%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861%
862% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
863% size that maintains the aspect ratio of the image. If the window manager
864% has preferred icon sizes, one of the preferred sizes is used.
865%
866% The format of the XBestIconSize method is:
867%
868% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
869%
870% A description of each parameter follows:
871%
872% o display: Specifies a connection to an X server; returned from
873% XOpenDisplay.
874%
875% o image: the image.
876%
877*/
878MagickExport void XBestIconSize(Display *display,XWindowInfo *window,
879 Image *image)
880{
881 int
882 i,
883 number_sizes;
884
885 MagickRealType
886 scale_factor;
887
888 unsigned int
889 height,
890 icon_height,
891 icon_width,
892 width;
893
894 Window
895 root_window;
896
897 XIconSize
898 *icon_size,
899 *size_list;
900
901 /*
902 Determine if the window manager has specified preferred icon sizes.
903 */
904 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
905 assert(display != (Display *) NULL);
906 assert(window != (XWindowInfo *) NULL);
907 assert(image != (Image *) NULL);
908 window->width=MaxIconSize;
909 window->height=MaxIconSize;
910 icon_size=(XIconSize *) NULL;
911 number_sizes=0;
912 root_window=XRootWindow(display,window->screen);
913 if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
914 if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
915 icon_size=size_list;
916 if (icon_size == (XIconSize *) NULL)
917 {
918 /*
919 Window manager does not restrict icon size.
920 */
921 icon_size=XAllocIconSize();
922 if (icon_size == (XIconSize *) NULL)
923 {
924 ThrowXWindowFatalException(ResourceLimitError,
925 "MemoryAllocationFailed",image->filename);
926 return;
927 }
928 icon_size->min_width=1;
929 icon_size->max_width=MaxIconSize;
930 icon_size->min_height=1;
931 icon_size->max_height=MaxIconSize;
932 icon_size->width_inc=1;
933 icon_size->height_inc=1;
934 }
935 /*
936 Determine aspect ratio of image.
937 */
938 width=(unsigned int) image->columns;
939 height=(unsigned int) image->rows;
940 i=0;
941 if (window->crop_geometry)
942 (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
943 /*
944 Look for an icon size that maintains the aspect ratio of image.
945 */
946 scale_factor=(MagickRealType) icon_size->max_width/width;
947 if (scale_factor > ((MagickRealType) icon_size->max_height/height))
948 scale_factor=(MagickRealType) icon_size->max_height/height;
949 icon_width=(unsigned int) icon_size->min_width;
950 while ((int) icon_width < icon_size->max_width)
951 {
952 if (icon_width >= (unsigned int) (scale_factor*width+0.5))
953 break;
954 icon_width+=icon_size->width_inc;
955 }
956 icon_height=(unsigned int) icon_size->min_height;
957 while ((int) icon_height < icon_size->max_height)
958 {
959 if (icon_height >= (unsigned int) (scale_factor*height+0.5))
960 break;
961 icon_height+=icon_size->height_inc;
962 }
963 (void) XFree((void *) icon_size);
964 window->width=icon_width;
965 window->height=icon_height;
966}
967
968/*
969%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
970% %
971% %
972% %
973% X B e s t P i x e l %
974% %
975% %
976% %
977%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978%
979% XBestPixel() returns a pixel from an array of pixels that is closest to the
980% requested color. If the color array is NULL, the colors are obtained from
981% the X server.
982%
983% The format of the XBestPixel method is:
984%
985% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
986% unsigned int number_colors,XColor *color)
987%
988% A description of each parameter follows:
989%
990% o pixel: XBestPixel returns the pixel value closest to the requested
991% color.
992%
993% o display: Specifies a connection to an X server; returned from
994% XOpenDisplay.
995%
996% o colormap: Specifies the ID of the X server colormap.
997%
998% o colors: Specifies an array of XColor structures.
999%
1000% o number_colors: Specifies the number of XColor structures in the
1001% color definition array.
1002%
1003% o color: Specifies the desired RGB value to find in the colors array.
1004%
1005*/
1006MagickExport void XBestPixel(Display *display,const Colormap colormap,
1007 XColor *colors,unsigned int number_colors,XColor *color)
1008{
1009 MagickBooleanType
1010 query_server;
1011
1012 MagickPixelPacket
1013 pixel;
1014
1015 MagickRealType
1016 min_distance;
1017
1018 register MagickRealType
1019 distance;
1020
1021 register int
1022 i,
1023 j;
1024
1025 Status
1026 status;
1027
1028 /*
1029 Find closest representation for the requested RGB color.
1030 */
1031 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1032 assert(display != (Display *) NULL);
1033 assert(color != (XColor *) NULL);
1034 status=XAllocColor(display,colormap,color);
1035 if (status != False)
1036 return;
1037 query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
1038 if (query_server != MagickFalse)
1039 {
1040 /*
1041 Read X server colormap.
1042 */
1043 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
1044 if (colors == (XColor *) NULL)
1045 {
1046 ThrowXWindowFatalException(ResourceLimitError,
1047 "MemoryAllocationFailed","...");
1048 return;
1049 }
1050 for (i=0; i < (int) number_colors; i++)
cristybb503372010-05-27 20:51:26 +00001051 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00001052 if (number_colors > 256)
1053 number_colors=256;
1054 (void) XQueryColors(display,colormap,colors,(int) number_colors);
1055 }
1056 min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
1057 QuantumRange+1.0);
1058 j=0;
1059 for (i=0; i < (int) number_colors; i++)
1060 {
1061 pixel.red=colors[i].red-(MagickRealType) color->red;
1062 distance=pixel.red*pixel.red;
1063 if (distance > min_distance)
1064 continue;
1065 pixel.green=colors[i].green-(MagickRealType) color->green;
1066 distance+=pixel.green*pixel.green;
1067 if (distance > min_distance)
1068 continue;
1069 pixel.blue=colors[i].blue-(MagickRealType) color->blue;
1070 distance+=pixel.blue*pixel.blue;
1071 if (distance > min_distance)
1072 continue;
1073 min_distance=distance;
1074 color->pixel=colors[i].pixel;
1075 j=i;
1076 }
1077 (void) XAllocColor(display,colormap,&colors[j]);
1078 if (query_server != MagickFalse)
1079 colors=(XColor *) RelinquishMagickMemory(colors);
1080}
1081
1082/*
1083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1084% %
1085% %
1086% %
1087% X B e s t V i s u a l I n f o %
1088% %
1089% %
1090% %
1091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1092%
1093% XBestVisualInfo() returns visual information for a visual that is the "best"
1094% the server supports. "Best" is defined as:
1095%
1096% 1. Restrict the visual list to those supported by the default screen.
1097%
1098% 2. If a visual type is specified, restrict the visual list to those of
1099% that type.
1100%
1101% 3. If a map type is specified, choose the visual that matches the id
1102% specified by the Standard Colormap.
1103%
1104% 4 From the list of visuals, choose one that can display the most
1105% simultaneous colors. If more than one visual can display the same
1106% number of simultaneous colors, one is chosen based on a rank.
1107%
1108% The format of the XBestVisualInfo method is:
1109%
1110% XVisualInfo *XBestVisualInfo(Display *display,
1111% XStandardColormap *map_info,XResourceInfo *resource_info)
1112%
1113% A description of each parameter follows:
1114%
1115% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
1116% structure.
1117%
1118% o display: Specifies a connection to an X server; returned from
1119% XOpenDisplay.
1120%
1121% o map_info: If map_type is specified, this structure is initialized
1122% with info from the Standard Colormap.
1123%
1124% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1125%
1126*/
1127
1128static inline int MagickMax(const int x,const int y)
1129{
1130 if (x > y)
1131 return(x);
1132 return(y);
1133}
1134
cristybb503372010-05-27 20:51:26 +00001135static inline size_t MagickMin(const unsigned int x,
cristy3ed852e2009-09-05 21:47:34 +00001136 const unsigned int y)
1137{
1138 if (x < y)
1139 return(x);
1140 return(y);
1141}
1142
1143MagickExport XVisualInfo *XBestVisualInfo(Display *display,
1144 XStandardColormap *map_info,XResourceInfo *resource_info)
1145{
1146#define MaxStandardColormaps 7
1147#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
1148 (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
1149 visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
1150 (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
1151
1152 char
1153 *map_type,
1154 *visual_type;
1155
cristyc57f6942010-11-12 01:47:39 +00001156 int
1157 visual_mask;
1158
cristy3ed852e2009-09-05 21:47:34 +00001159 register int
1160 i;
1161
cristy8891f9c2010-06-04 23:32:17 +00001162 size_t
1163 one;
1164
cristy3ed852e2009-09-05 21:47:34 +00001165 static int
1166 number_visuals;
1167
1168 static XVisualInfo
1169 visual_template;
1170
1171 XVisualInfo
1172 *visual_info,
1173 *visual_list;
1174
1175 /*
1176 Restrict visual search by screen number.
1177 */
1178 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1179 assert(display != (Display *) NULL);
1180 assert(map_info != (XStandardColormap *) NULL);
1181 assert(resource_info != (XResourceInfo *) NULL);
1182 map_type=resource_info->map_type;
1183 visual_type=resource_info->visual_type;
1184 visual_mask=VisualScreenMask;
1185 visual_template.screen=XDefaultScreen(display);
1186 visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
cristy8891f9c2010-06-04 23:32:17 +00001187 one=1;
cristy3ed852e2009-09-05 21:47:34 +00001188 if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
cristy8891f9c2010-06-04 23:32:17 +00001189 if (resource_info->colors <= (one << (size_t) visual_template.depth))
cristy3ed852e2009-09-05 21:47:34 +00001190 visual_mask|=VisualDepthMask;
1191 if (visual_type != (char *) NULL)
1192 {
1193 /*
1194 Restrict visual search by class or visual id.
1195 */
1196 if (LocaleCompare("staticgray",visual_type) == 0)
1197 {
1198 visual_mask|=VisualClassMask;
1199 visual_template.klass=StaticGray;
1200 }
1201 else
1202 if (LocaleCompare("grayscale",visual_type) == 0)
1203 {
1204 visual_mask|=VisualClassMask;
1205 visual_template.klass=GrayScale;
1206 }
1207 else
1208 if (LocaleCompare("staticcolor",visual_type) == 0)
1209 {
1210 visual_mask|=VisualClassMask;
1211 visual_template.klass=StaticColor;
1212 }
1213 else
1214 if (LocaleCompare("pseudocolor",visual_type) == 0)
1215 {
1216 visual_mask|=VisualClassMask;
1217 visual_template.klass=PseudoColor;
1218 }
1219 else
1220 if (LocaleCompare("truecolor",visual_type) == 0)
1221 {
1222 visual_mask|=VisualClassMask;
1223 visual_template.klass=TrueColor;
1224 }
1225 else
1226 if (LocaleCompare("directcolor",visual_type) == 0)
1227 {
1228 visual_mask|=VisualClassMask;
1229 visual_template.klass=DirectColor;
1230 }
1231 else
1232 if (LocaleCompare("default",visual_type) == 0)
1233 {
1234 visual_mask|=VisualIDMask;
1235 visual_template.visualid=XVisualIDFromVisual(
1236 XDefaultVisual(display,XDefaultScreen(display)));
1237 }
1238 else
1239 if (isdigit((int) ((unsigned char) *visual_type)) != 0)
1240 {
1241 visual_mask|=VisualIDMask;
1242 visual_template.visualid=
1243 strtol(visual_type,(char **) NULL,0);
1244 }
1245 else
1246 ThrowXWindowFatalException(XServerError,
1247 "UnrecognizedVisualSpecifier",visual_type);
1248 }
1249 /*
1250 Get all visuals that meet our criteria so far.
1251 */
1252 number_visuals=0;
1253 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1254 &number_visuals);
1255 visual_mask=VisualScreenMask | VisualIDMask;
1256 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1257 {
1258 /*
1259 Failed to get visual; try using the default visual.
1260 */
1261 ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
1262 visual_type);
1263 visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
1264 XDefaultScreen(display)));
1265 visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
1266 &number_visuals);
1267 if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
1268 return((XVisualInfo *) NULL);
1269 ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
1270 XVisualClassName(visual_list->klass));
1271 }
1272 resource_info->color_recovery=MagickFalse;
1273 if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
1274 {
1275 Atom
1276 map_property;
1277
1278 char
1279 map_name[MaxTextExtent];
1280
1281 int
1282 j,
1283 number_maps;
1284
1285 Status
1286 status;
1287
1288 Window
1289 root_window;
1290
1291 XStandardColormap
1292 *map_list;
1293
1294 /*
1295 Choose a visual associated with a standard colormap.
1296 */
1297 root_window=XRootWindow(display,XDefaultScreen(display));
1298 status=False;
1299 if (LocaleCompare(map_type,"list") != 0)
1300 {
1301 /*
1302 User specified Standard Colormap.
1303 */
1304 (void) FormatMagickString((char *) map_name,MaxTextExtent,
1305 "RGB_%s_MAP",map_type);
1306 LocaleUpper(map_name);
1307 map_property=XInternAtom(display,(char *) map_name,MagickTrue);
1308 if (map_property != (Atom) NULL)
1309 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1310 map_property);
1311 }
1312 else
1313 {
1314 static const char
1315 *colormap[MaxStandardColormaps]=
1316 {
1317 "_HP_RGB_SMOOTH_MAP_LIST",
1318 "RGB_BEST_MAP",
1319 "RGB_DEFAULT_MAP",
1320 "RGB_GRAY_MAP",
1321 "RGB_RED_MAP",
1322 "RGB_GREEN_MAP",
1323 "RGB_BLUE_MAP",
1324 };
1325
1326 /*
1327 Choose a standard colormap from a list.
1328 */
1329 for (i=0; i < MaxStandardColormaps; i++)
1330 {
1331 map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
1332 if (map_property == (Atom) NULL)
1333 continue;
1334 status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
1335 map_property);
1336 if (status != False)
1337 break;
1338 }
1339 resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
1340 }
1341 if (status == False)
1342 {
1343 ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
1344 map_type);
1345 return((XVisualInfo *) NULL);
1346 }
1347 /*
1348 Search all Standard Colormaps and visuals for ids that match.
1349 */
1350 *map_info=map_list[0];
1351#if !defined(PRE_R4_ICCCM)
1352 visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
1353 for (i=0; i < number_maps; i++)
1354 for (j=0; j < number_visuals; j++)
1355 if (map_list[i].visualid ==
1356 XVisualIDFromVisual(visual_list[j].visual))
1357 {
1358 *map_info=map_list[i];
1359 visual_template.visualid=XVisualIDFromVisual(
1360 visual_list[j].visual);
1361 break;
1362 }
1363 if (map_info->visualid != visual_template.visualid)
1364 {
1365 ThrowXWindowFatalException(XServerError,
1366 "UnableToMatchVisualToStandardColormap",map_type);
1367 return((XVisualInfo *) NULL);
1368 }
1369#endif
1370 if (map_info->colormap == (Colormap) NULL)
1371 {
1372 ThrowXWindowFatalException(XServerError,
1373 "StandardColormapIsNotInitialized",map_type);
1374 return((XVisualInfo *) NULL);
1375 }
1376 (void) XFree((void *) map_list);
1377 }
1378 else
1379 {
1380 static const unsigned int
1381 rank[]=
1382 {
1383 StaticGray,
1384 GrayScale,
1385 StaticColor,
1386 DirectColor,
1387 TrueColor,
1388 PseudoColor
1389 };
1390
1391 XVisualInfo
1392 *p;
1393
1394 /*
1395 Pick one visual that displays the most simultaneous colors.
1396 */
1397 visual_info=visual_list;
1398 p=visual_list;
1399 for (i=1; i < number_visuals; i++)
1400 {
1401 p++;
1402 if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
1403 visual_info=p;
1404 else
1405 if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
1406 if (rank[p->klass] > rank[visual_info->klass])
1407 visual_info=p;
1408 }
1409 visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
1410 }
1411 (void) XFree((void *) visual_list);
1412 /*
1413 Retrieve only one visual by its screen & id number.
1414 */
1415 visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
1416 &number_visuals);
1417 if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
1418 return((XVisualInfo *) NULL);
1419 return(visual_info);
1420}
1421
1422/*
1423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1424% %
1425% %
1426% %
1427% X C h e c k D e f i n e C u r s o r %
1428% %
1429% %
1430% %
1431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1432%
1433% XCheckDefineCursor() prevents cursor changes on the root window.
1434%
1435% The format of the XXCheckDefineCursor method is:
1436%
1437% XCheckDefineCursor(display,window,cursor)
1438%
1439% A description of each parameter follows:
1440%
1441% o display: Specifies a connection to an X server; returned from
1442% XOpenDisplay.
1443%
1444% o window: the window.
1445%
1446% o cursor: the cursor.
1447%
1448*/
1449MagickExport int XCheckDefineCursor(Display *display,Window window,
1450 Cursor cursor)
1451{
1452 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1453 assert(display != (Display *) NULL);
1454 if (window == XRootWindow(display,XDefaultScreen(display)))
1455 return(0);
1456 return(XDefineCursor(display,window,cursor));
1457}
1458
1459/*
1460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1461% %
1462% %
1463% %
1464% X C h e c k R e f r e s h W i n d o w s %
1465% %
1466% %
1467% %
1468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1469%
1470% XCheckRefreshWindows() checks the X server for exposure events for a
1471% particular window and updates the areassociated with the exposure event.
1472%
1473% The format of the XCheckRefreshWindows method is:
1474%
1475% void XCheckRefreshWindows(Display *display,XWindows *windows)
1476%
1477% A description of each parameter follows:
1478%
1479% o display: Specifies a connection to an X server; returned from
1480% XOpenDisplay.
1481%
1482% o windows: Specifies a pointer to a XWindows structure.
1483%
1484*/
1485MagickExport void XCheckRefreshWindows(Display *display,XWindows *windows)
1486{
1487 Window
1488 id;
1489
1490 XEvent
1491 event;
1492
1493 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1494 assert(display != (Display *) NULL);
1495 assert(windows != (XWindows *) NULL);
1496 XDelay(display,SuspendTime);
1497 id=windows->command.id;
1498 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1499 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1500 id=windows->image.id;
1501 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1502 XRefreshWindow(display,&windows->image,&event);
1503 XDelay(display,SuspendTime << 1);
1504 id=windows->command.id;
1505 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1506 (void) XCommandWidget(display,windows,(char const **) NULL,&event);
1507 id=windows->image.id;
1508 while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
1509 XRefreshWindow(display,&windows->image,&event);
1510}
1511
1512/*
1513%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1514% %
1515% %
1516% %
1517% X C l i e n t M e s s a g e %
1518% %
1519% %
1520% %
1521%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1522%
1523% XClientMessage() sends a reason to a window with XSendEvent. The reason is
1524% initialized with a particular protocol type and atom.
1525%
1526% The format of the XClientMessage function is:
1527%
1528% XClientMessage(display,window,protocol,reason,timestamp)
1529%
1530% A description of each parameter follows:
1531%
1532% o display: Specifies a pointer to the Display structure; returned from
1533% XOpenDisplay.
1534%
1535% o window: Specifies a pointer to a Window structure.
1536%
1537% o protocol: Specifies an atom value.
1538%
1539% o reason: Specifies an atom value which is the reason to send.
1540%
1541% o timestamp: Specifies a value of type Time.
1542%
1543*/
1544MagickExport void XClientMessage(Display *display,const Window window,
1545 const Atom protocol,const Atom reason,const Time timestamp)
1546{
1547 XClientMessageEvent
1548 client_event;
1549
1550 assert(display != (Display *) NULL);
1551 client_event.type=ClientMessage;
1552 client_event.window=window;
1553 client_event.message_type=protocol;
1554 client_event.format=32;
cristyc57f6942010-11-12 01:47:39 +00001555 client_event.data.l[0]=(long) reason;
1556 client_event.data.l[1]=(long) timestamp;
cristy3ed852e2009-09-05 21:47:34 +00001557 (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
1558}
1559
1560/*
1561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1562% %
1563% %
1564% %
1565+ X C l i e n t W i n d o w %
1566% %
1567% %
1568% %
1569%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1570%
1571% XClientWindow() finds a window, at or below the specified window, which has
1572% a WM_STATE property. If such a window is found, it is returned, otherwise
1573% the argument window is returned.
1574%
1575% The format of the XClientWindow function is:
1576%
1577% client_window=XClientWindow(display,target_window)
1578%
1579% A description of each parameter follows:
1580%
1581% o client_window: XClientWindow returns a window, at or below the specified
1582% window, which has a WM_STATE property otherwise the argument
1583% target_window is returned.
1584%
1585% o display: Specifies a pointer to the Display structure; returned from
1586% XOpenDisplay.
1587%
1588% o target_window: Specifies the window to find a WM_STATE property.
1589%
cristy3ed852e2009-09-05 21:47:34 +00001590*/
1591static Window XClientWindow(Display *display,Window target_window)
1592{
1593 Atom
1594 state,
1595 type;
1596
1597 int
1598 format;
1599
1600 Status
1601 status;
1602
1603 unsigned char
1604 *data;
1605
cristyf2faecf2010-05-28 19:19:36 +00001606 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001607 after,
1608 number_items;
1609
1610 Window
1611 client_window;
1612
1613 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1614 assert(display != (Display *) NULL);
1615 state=XInternAtom(display,"WM_STATE",MagickTrue);
1616 if (state == (Atom) NULL)
1617 return(target_window);
1618 type=(Atom) NULL;
1619 status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
1620 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
1621 if ((status == Success) && (type != (Atom) NULL))
1622 return(target_window);
1623 client_window=XWindowByProperty(display,target_window,state);
1624 if (client_window == (Window) NULL)
1625 return(target_window);
1626 return(client_window);
1627}
1628
1629/*
1630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1631% %
1632% %
1633% %
cristyf34a1452009-10-24 22:29:27 +00001634+ X C o m p o n e n t T e r m i n u s %
1635% %
1636% %
1637% %
1638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1639%
1640% XComponentTerminus() destroys the module component.
1641%
1642% The format of the XComponentTerminus method is:
1643%
1644% XComponentTerminus(void)
1645%
1646*/
1647MagickExport void XComponentTerminus(void)
1648{
1649 DestroyXResources();
1650}
1651
1652/*
1653%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1654% %
1655% %
1656% %
cristy3ed852e2009-09-05 21:47:34 +00001657% X C o n f i g u r e I m a g e C o l o r m a p %
1658% %
1659% %
1660% %
1661%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1662%
1663% XConfigureImageColormap() creates a new X colormap.
1664%
1665% The format of the XConfigureImageColormap method is:
1666%
1667% void XConfigureImageColormap(Display *display,
1668% XResourceInfo *resource_info,XWindows *windows,Image *image)
1669%
1670% A description of each parameter follows:
1671%
1672% o display: Specifies a connection to an X server; returned from
1673% XOpenDisplay.
1674%
1675% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1676%
1677% o windows: Specifies a pointer to a XWindows structure.
1678%
1679% o image: the image.
1680%
1681*/
1682MagickExport void XConfigureImageColormap(Display *display,
1683 XResourceInfo *resource_info,XWindows *windows,Image *image)
1684{
1685 Colormap
1686 colormap;
1687
1688 /*
1689 Make standard colormap.
1690 */
1691 XSetCursorState(display,windows,MagickTrue);
1692 XCheckRefreshWindows(display,windows);
1693 XMakeStandardColormap(display,windows->visual_info,resource_info,image,
1694 windows->map_info,windows->pixel_info);
1695 colormap=windows->map_info->colormap;
1696 (void) XSetWindowColormap(display,windows->image.id,colormap);
1697 (void) XSetWindowColormap(display,windows->command.id,colormap);
1698 (void) XSetWindowColormap(display,windows->widget.id,colormap);
1699 if (windows->magnify.mapped != MagickFalse)
1700 (void) XSetWindowColormap(display,windows->magnify.id,colormap);
1701 if (windows->pan.mapped != MagickFalse)
1702 (void) XSetWindowColormap(display,windows->pan.id,colormap);
1703 XSetCursorState(display,windows,MagickFalse);
1704 XClientMessage(display,windows->image.id,windows->im_protocols,
1705 windows->im_update_colormap,CurrentTime);
1706}
1707
1708/*
1709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1710% %
1711% %
1712% %
1713% X C o n s t r a i n W i n d o w P o s i t i o n %
1714% %
1715% %
1716% %
1717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1718%
1719% XConstrainWindowPosition() assures a window is positioned within the X
1720% server boundaries.
1721%
1722% The format of the XConstrainWindowPosition method is:
1723%
1724% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
1725%
1726% A description of each parameter follows:
1727%
1728% o display: Specifies a pointer to the Display structure; returned from
1729% XOpenDisplay.
1730%
1731% o window_info: Specifies a pointer to a XWindowInfo structure.
1732%
1733*/
1734MagickExport void XConstrainWindowPosition(Display *display,
1735 XWindowInfo *window_info)
1736{
1737 int
1738 limit;
1739
1740 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1741 assert(display != (Display *) NULL);
1742 assert(window_info != (XWindowInfo *) NULL);
1743 limit=XDisplayWidth(display,window_info->screen)-window_info->width;
1744 if (window_info->x < 0)
1745 window_info->x=0;
1746 else
1747 if (window_info->x > (int) limit)
1748 window_info->x=(int) limit;
1749 limit=XDisplayHeight(display,window_info->screen)-window_info->height;
1750 if (window_info->y < 0)
1751 window_info->y=0;
1752 else
1753 if (window_info->y > limit)
1754 window_info->y=limit;
1755}
1756
1757/*
1758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1759% %
1760% %
1761% %
1762% X D e l a y %
1763% %
1764% %
1765% %
1766%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1767%
1768% XDelay() suspends program execution for the number of milliseconds
1769% specified.
1770%
1771% The format of the Delay method is:
1772%
cristybb503372010-05-27 20:51:26 +00001773% void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001774%
1775% A description of each parameter follows:
1776%
1777% o display: Specifies a pointer to the Display structure; returned from
1778% XOpenDisplay.
1779%
1780% o milliseconds: Specifies the number of milliseconds to delay before
1781% returning.
1782%
1783*/
cristybb503372010-05-27 20:51:26 +00001784MagickExport void XDelay(Display *display,const size_t milliseconds)
cristy3ed852e2009-09-05 21:47:34 +00001785{
1786 assert(display != (Display *) NULL);
1787 (void) XFlush(display);
cristya21afde2010-07-02 00:45:40 +00001788 MagickDelay(milliseconds);
cristy3ed852e2009-09-05 21:47:34 +00001789}
1790
1791/*
1792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1793% %
1794% %
1795% %
1796% X D e s t r o y R e s o u r c e I n f o %
1797% %
1798% %
1799% %
1800%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1801%
1802% XDestroyResourceInfo() frees memory associated with the XResourceInfo
1803% structure.
1804%
1805% The format of the XDestroyResourceInfo method is:
1806%
1807% void XDestroyResourceInfo(XResourceInfo *resource_info)
1808%
1809% A description of each parameter follows:
1810%
1811% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1812%
1813*/
1814MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
1815{
1816 if (resource_info->image_geometry != (char *) NULL)
1817 resource_info->image_geometry=(char *)
1818 RelinquishMagickMemory(resource_info->image_geometry);
1819 if (resource_info->quantize_info != (QuantizeInfo *) NULL)
1820 resource_info->quantize_info=DestroyQuantizeInfo(
1821 resource_info->quantize_info);
1822 if (resource_info->client_name != (char *) NULL)
1823 resource_info->client_name=(char *)
1824 RelinquishMagickMemory(resource_info->client_name);
1825 if (resource_info->name != (char *) NULL)
1826 resource_info->name=DestroyString(resource_info->name);
1827 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
1828}
1829
1830/*
1831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1832% %
1833% %
1834% %
1835% X D e s t r o y W i n d o w C o l o r s %
1836% %
1837% %
1838% %
1839%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1840%
1841% XDestroyWindowColors() frees X11 color resources previously saved on a
1842% window by XRetainWindowColors or programs like xsetroot.
1843%
1844% The format of the XDestroyWindowColors method is:
1845%
1846% void XDestroyWindowColors(Display *display,Window window)
1847%
1848% A description of each parameter follows:
1849%
1850% o display: Specifies a connection to an X server; returned from
1851% XOpenDisplay.
1852%
1853% o window: Specifies a pointer to a Window structure.
1854%
1855*/
1856MagickExport void XDestroyWindowColors(Display *display,Window window)
1857{
1858 Atom
1859 property,
1860 type;
1861
1862 int
1863 format;
1864
1865 Status
1866 status;
1867
1868 unsigned char
1869 *data;
1870
cristyf2faecf2010-05-28 19:19:36 +00001871 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00001872 after,
1873 length;
1874
1875 /*
1876 If there are previous resources on the root window, destroy them.
1877 */
1878 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1879 assert(display != (Display *) NULL);
1880 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
1881 if (property == (Atom) NULL)
1882 {
1883 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
1884 "_XSETROOT_ID");
1885 return;
1886 }
1887 status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
1888 (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
1889 if (status != Success)
1890 return;
1891 if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
1892 {
1893 (void) XKillClient(display,(XID) (*((Pixmap *) data)));
1894 (void) XDeleteProperty(display,window,property);
1895 }
1896 if (type != None)
1897 (void) XFree((void *) data);
1898}
1899
1900/*
1901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1902% %
1903% %
1904% %
1905% X D i s p l a y I m a g e I n f o %
1906% %
1907% %
1908% %
1909%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1910%
1911% XDisplayImageInfo() displays information about an X image.
1912%
1913% The format of the XDisplayImageInfo method is:
1914%
1915% void XDisplayImageInfo(Display *display,
1916% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1917% Image *image)
1918%
1919% A description of each parameter follows:
1920%
1921% o display: Specifies a connection to an X server; returned from
1922% XOpenDisplay.
1923%
1924% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1925%
1926% o windows: Specifies a pointer to a XWindows structure.
1927%
1928% o undo_image: the undo image.
1929%
1930% o image: the image.
1931%
1932*/
1933MagickExport void XDisplayImageInfo(Display *display,
1934 const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
1935 Image *image)
1936{
1937 char
1938 filename[MaxTextExtent],
1939 *text,
1940 **textlist;
1941
1942 FILE
1943 *file;
1944
1945 int
1946 unique_file;
1947
cristybb503372010-05-27 20:51:26 +00001948 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001949 i;
1950
cristybb503372010-05-27 20:51:26 +00001951 size_t
cristy3ed852e2009-09-05 21:47:34 +00001952 number_pixels;
1953
cristy9d314ff2011-03-09 01:30:28 +00001954 ssize_t
1955 bytes;
1956
1957 unsigned int
1958 levels;
1959
cristy3ed852e2009-09-05 21:47:34 +00001960 /*
1961 Write info about the X server to a file.
1962 */
1963 assert(display != (Display *) NULL);
1964 assert(resource_info != (XResourceInfo *) NULL);
1965 assert(windows != (XWindows *) NULL);
1966 assert(image != (Image *) NULL);
1967 if (image->debug)
1968 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1969 file=(FILE *) NULL;
1970 unique_file=AcquireUniqueFileResource(filename);
1971 if (unique_file != -1)
1972 file=fdopen(unique_file,"w");
1973 if ((unique_file == -1) || (file == (FILE *) NULL))
1974 {
1975 XNoticeWidget(display,windows,"Unable to display image info",filename);
1976 return;
1977 }
1978 if (resource_info->gamma_correct != MagickFalse)
1979 if (resource_info->display_gamma != (char *) NULL)
1980 (void) fprintf(file,"Display\n gamma: %s\n\n",
1981 resource_info->display_gamma);
1982 /*
1983 Write info about the X image to a file.
1984 */
1985 (void) fprintf(file,"X\n visual: %s\n",
1986 XVisualClassName((int) windows->image.storage_class));
1987 (void) fprintf(file," depth: %d\n",windows->image.ximage->depth);
1988 if (windows->visual_info->colormap_size != 0)
1989 (void) fprintf(file," colormap size: %d\n",
1990 windows->visual_info->colormap_size);
1991 if (resource_info->colormap== SharedColormap)
1992 (void) fprintf(file," colormap type: Shared\n");
1993 else
1994 (void) fprintf(file," colormap type: Private\n");
1995 (void) fprintf(file," geometry: %dx%d\n",windows->image.ximage->width,
1996 windows->image.ximage->height);
1997 if (windows->image.crop_geometry != (char *) NULL)
1998 (void) fprintf(file," crop geometry: %s\n",windows->image.crop_geometry);
1999 if (windows->image.pixmap == (Pixmap) NULL)
2000 (void) fprintf(file," type: X Image\n");
2001 else
2002 (void) fprintf(file," type: Pixmap\n");
2003 if (windows->image.shape != MagickFalse)
2004 (void) fprintf(file," non-rectangular shape: True\n");
2005 else
2006 (void) fprintf(file," non-rectangular shape: False\n");
2007 if (windows->image.shared_memory != MagickFalse)
2008 (void) fprintf(file," shared memory: True\n");
2009 else
2010 (void) fprintf(file," shared memory: False\n");
2011 (void) fprintf(file,"\n");
2012 if (resource_info->font != (char *) NULL)
2013 (void) fprintf(file,"Font: %s\n\n",resource_info->font);
2014 if (resource_info->text_font != (char *) NULL)
2015 (void) fprintf(file,"Text font: %s\n\n",resource_info->text_font);
2016 /*
2017 Write info about the undo cache to a file.
2018 */
2019 bytes=0;
2020 for (levels=0; undo_image != (Image *) NULL; levels++)
2021 {
2022 number_pixels=undo_image->list->columns*undo_image->list->rows;
2023 bytes+=number_pixels*sizeof(PixelPacket);
2024 undo_image=GetPreviousImageInList(undo_image);
2025 }
2026 (void) fprintf(file,"Undo Edit Cache\n levels: %u\n",levels);
cristye8c25f92010-06-03 00:53:06 +00002027 (void) fprintf(file," bytes: %.20gmb\n",(double) ((bytes+(1 << 19)) >> 20));
2028 (void) fprintf(file," limit: %.20gmb\n\n",(double)
cristyf2faecf2010-05-28 19:19:36 +00002029 resource_info->undo_cache);
cristy3ed852e2009-09-05 21:47:34 +00002030 /*
2031 Write info about the image to a file.
2032 */
2033 (void) IdentifyImage(image,file,MagickTrue);
2034 (void) fclose(file);
2035 text=FileToString(filename,~0,&image->exception);
2036 (void) RelinquishUniqueFileResource(filename);
2037 if (text == (char *) NULL)
2038 {
2039 XNoticeWidget(display,windows,"MemoryAllocationFailed",
2040 "UnableToDisplayImageInfo");
2041 return;
2042 }
2043 textlist=StringToList(text);
2044 if (textlist != (char **) NULL)
2045 {
2046 char
2047 title[MaxTextExtent];
2048
2049 /*
2050 Display information about the image in the Text View widget.
2051 */
2052 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2053 (void) FormatMagickString(title,MaxTextExtent,"Image Info: %s",
2054 image->filename);
2055 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
2056 (char const **) textlist);
2057 for (i=0; textlist[i] != (char *) NULL; i++)
2058 textlist[i]=DestroyString(textlist[i]);
2059 textlist=(char **) RelinquishMagickMemory(textlist);
2060 }
2061 text=DestroyString(text);
2062}
2063
2064/*
2065%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2066% %
2067% %
2068% %
2069+ X D i t h e r I m a g e %
2070% %
2071% %
2072% %
2073%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2074%
2075% XDitherImage() dithers the reference image as required by the HP Color
2076% Recovery algorithm. The color values are quantized to 3 bits of red and
2077% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
2078% standard colormap.
2079%
2080% The format of the XDitherImage method is:
2081%
2082% void XDitherImage(Image *image,XImage *ximage)
2083%
2084% A description of each parameter follows:
2085%
2086% o image: the image.
2087%
2088% o ximage: Specifies a pointer to a XImage structure; returned from
2089% XCreateImage.
2090%
cristy3ed852e2009-09-05 21:47:34 +00002091*/
2092static void XDitherImage(Image *image,XImage *ximage)
2093{
2094 static const short int
2095 dither_red[2][16]=
2096 {
2097 {-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
2098 { 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
2099 },
2100 dither_green[2][16]=
2101 {
2102 { 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
2103 {-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
2104 },
2105 dither_blue[2][16]=
2106 {
2107 { -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
2108 { 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
2109 };
2110
cristyc57f6942010-11-12 01:47:39 +00002111 CacheView
2112 *image_view;
cristy3ed852e2009-09-05 21:47:34 +00002113
2114 int
cristyc57f6942010-11-12 01:47:39 +00002115 value,
cristy3ed852e2009-09-05 21:47:34 +00002116 y;
2117
cristyc57f6942010-11-12 01:47:39 +00002118 PixelPacket
2119 color;
cristy3ed852e2009-09-05 21:47:34 +00002120
2121 register char
2122 *q;
2123
2124 register const PixelPacket
2125 *p;
2126
2127 register int
2128 i,
2129 j,
2130 x;
2131
2132 unsigned int
2133 scanline_pad;
2134
cristybb503372010-05-27 20:51:26 +00002135 register size_t
cristy3ed852e2009-09-05 21:47:34 +00002136 pixel;
2137
2138 unsigned char
2139 *blue_map[2][16],
2140 *green_map[2][16],
2141 *red_map[2][16];
2142
2143 /*
2144 Allocate and initialize dither maps.
2145 */
2146 for (i=0; i < 2; i++)
2147 for (j=0; j < 16; j++)
2148 {
2149 red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2150 sizeof(*red_map));
2151 green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2152 sizeof(*green_map));
2153 blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
2154 sizeof(*blue_map));
2155 if ((red_map[i][j] == (unsigned char *) NULL) ||
2156 (green_map[i][j] == (unsigned char *) NULL) ||
2157 (blue_map[i][j] == (unsigned char *) NULL))
2158 {
2159 ThrowXWindowFatalException(ResourceLimitError,
2160 "MemoryAllocationFailed",image->filename);
2161 return;
2162 }
2163 }
2164 /*
2165 Initialize dither tables.
2166 */
2167 for (i=0; i < 2; i++)
2168 for (j=0; j < 16; j++)
2169 for (x=0; x < 256; x++)
2170 {
2171 value=x-16;
2172 if (x < 48)
2173 value=x/2+8;
2174 value+=dither_red[i][j];
2175 red_map[i][j][x]=(unsigned char)
2176 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2177 value=x-16;
2178 if (x < 48)
2179 value=x/2+8;
2180 value+=dither_green[i][j];
2181 green_map[i][j][x]=(unsigned char)
2182 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2183 value=x-32;
2184 if (x < 112)
2185 value=x/2+24;
cristybb503372010-05-27 20:51:26 +00002186 value+=((size_t) dither_blue[i][j] << 1);
cristy3ed852e2009-09-05 21:47:34 +00002187 blue_map[i][j][x]=(unsigned char)
2188 ((value < 0) ? 0 : (value > 255) ? 255 : value);
2189 }
2190 /*
2191 Dither image.
2192 */
2193 scanline_pad=(unsigned int) (ximage->bytes_per_line-
cristybb503372010-05-27 20:51:26 +00002194 ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
cristy3ed852e2009-09-05 21:47:34 +00002195 i=0;
2196 j=0;
2197 q=ximage->data;
cristyc57f6942010-11-12 01:47:39 +00002198 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00002199 for (y=0; y < (int) image->rows; y++)
2200 {
cristyc57f6942010-11-12 01:47:39 +00002201 p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
2202 &image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002203 if (p == (const PixelPacket *) NULL)
2204 break;
2205 for (x=0; x < (int) image->columns; x++)
2206 {
cristyce70c172010-01-07 17:15:30 +00002207 color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
2208 ScaleQuantumToChar(GetRedPixelComponent(p))] << 8));
2209 color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
2210 ScaleQuantumToChar(GetGreenPixelComponent(p))] << 8));
2211 color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
2212 ScaleQuantumToChar(GetBluePixelComponent(p))] << 8));
cristybb503372010-05-27 20:51:26 +00002213 pixel=(size_t) (((size_t) color.red & 0xe0) |
2214 (((size_t) color.green & 0xe0) >> 3) |
2215 (((size_t) color.blue & 0xc0) >> 6));
cristy3ed852e2009-09-05 21:47:34 +00002216 *q++=(char) pixel;
2217 p++;
2218 j++;
2219 if (j == 16)
2220 j=0;
2221 }
2222 q+=scanline_pad;
2223 i++;
2224 if (i == 2)
2225 i=0;
2226 }
cristyc57f6942010-11-12 01:47:39 +00002227 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00002228 /*
2229 Free allocated memory.
2230 */
2231 for (i=0; i < 2; i++)
2232 for (j=0; j < 16; j++)
2233 {
2234 green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
2235 blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
2236 red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
2237 }
2238}
2239
2240/*
2241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2242% %
2243% %
2244% %
2245% X D r a w I m a g e %
2246% %
2247% %
2248% %
2249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2250%
2251% XDrawImage() draws a line on the image.
2252%
2253% The format of the XDrawImage method is:
2254%
2255% MagickBooleanType XDrawImage(display,pixel,draw_info,image)
2256%
2257% A description of each parameter follows:
2258%
2259% o display: Specifies a connection to an X server; returned from
2260% XOpenDisplay.
2261%
2262% o pixel: Specifies a pointer to a XPixelInfo structure.
2263%
2264% o draw_info: Specifies a pointer to a XDrawInfo structure.
2265%
2266% o image: the image.
2267%
2268*/
2269MagickExport MagickBooleanType XDrawImage(Display *display,
2270 const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
2271{
cristyc57f6942010-11-12 01:47:39 +00002272 CacheView
2273 *draw_view;
2274
cristy3ed852e2009-09-05 21:47:34 +00002275 ExceptionInfo
2276 *exception;
2277
2278 GC
2279 draw_context;
2280
2281 Image
2282 *draw_image;
2283
2284 int
2285 x,
2286 y;
2287
2288 MagickBooleanType
2289 matte;
2290
2291 Pixmap
2292 draw_pixmap;
2293
2294 unsigned int
2295 depth,
2296 height,
2297 width;
2298
2299 Window
2300 root_window;
2301
2302 XGCValues
2303 context_values;
2304
2305 XImage
2306 *draw_ximage;
2307
2308 /*
2309 Initialize drawd image.
2310 */
2311 assert(display != (Display *) NULL);
2312 assert(pixel != (XPixelInfo *) NULL);
2313 assert(draw_info != (XDrawInfo *) NULL);
2314 assert(image != (Image *) NULL);
2315 if (image->debug != MagickFalse)
2316 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2317 /*
2318 Initialize drawd pixmap.
2319 */
2320 root_window=XRootWindow(display,XDefaultScreen(display));
2321 depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
2322 draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
2323 draw_info->height,depth);
2324 if (draw_pixmap == (Pixmap) NULL)
2325 return(MagickFalse);
2326 /*
2327 Initialize graphics info.
2328 */
cristybb503372010-05-27 20:51:26 +00002329 context_values.background=(size_t) (~0);
cristy3ed852e2009-09-05 21:47:34 +00002330 context_values.foreground=0;
2331 context_values.line_width=(int) draw_info->line_width;
cristybb503372010-05-27 20:51:26 +00002332 draw_context=XCreateGC(display,root_window,(size_t)
cristy3ed852e2009-09-05 21:47:34 +00002333 (GCBackground | GCForeground | GCLineWidth),&context_values);
2334 if (draw_context == (GC) NULL)
2335 return(MagickFalse);
2336 /*
2337 Clear pixmap.
2338 */
2339 (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
2340 draw_info->height);
2341 /*
2342 Draw line to pixmap.
2343 */
2344 (void) XSetBackground(display,draw_context,0);
cristybb503372010-05-27 20:51:26 +00002345 (void) XSetForeground(display,draw_context,(size_t) (~0));
cristydd05beb2010-11-21 21:23:39 +00002346 if (draw_info->stipple != (Pixmap) NULL)
2347 {
2348 (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
2349 (void) XSetStipple(display,draw_context,draw_info->stipple);
2350 }
cristy3ed852e2009-09-05 21:47:34 +00002351 switch (draw_info->element)
2352 {
2353 case PointElement:
2354 default:
2355 {
2356 (void) XDrawLines(display,draw_pixmap,draw_context,
2357 draw_info->coordinate_info,(int) draw_info->number_coordinates,
2358 CoordModeOrigin);
2359 break;
2360 }
2361 case LineElement:
2362 {
2363 (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
2364 draw_info->line_info.y1,draw_info->line_info.x2,
2365 draw_info->line_info.y2);
2366 break;
2367 }
2368 case RectangleElement:
2369 {
2370 (void) XDrawRectangle(display,draw_pixmap,draw_context,
2371 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2372 (unsigned int) draw_info->rectangle_info.width,
2373 (unsigned int) draw_info->rectangle_info.height);
2374 break;
2375 }
2376 case FillRectangleElement:
2377 {
2378 (void) XFillRectangle(display,draw_pixmap,draw_context,
2379 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2380 (unsigned int) draw_info->rectangle_info.width,
2381 (unsigned int) draw_info->rectangle_info.height);
2382 break;
2383 }
2384 case CircleElement:
2385 case EllipseElement:
2386 {
2387 (void) XDrawArc(display,draw_pixmap,draw_context,
2388 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2389 (unsigned int) draw_info->rectangle_info.width,
2390 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2391 break;
2392 }
2393 case FillCircleElement:
2394 case FillEllipseElement:
2395 {
2396 (void) XFillArc(display,draw_pixmap,draw_context,
2397 (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
2398 (unsigned int) draw_info->rectangle_info.width,
2399 (unsigned int) draw_info->rectangle_info.height,0,360*64);
2400 break;
2401 }
2402 case PolygonElement:
2403 {
2404 XPoint
2405 *coordinate_info;
2406
2407 coordinate_info=draw_info->coordinate_info;
2408 (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
2409 (int) draw_info->number_coordinates,CoordModeOrigin);
2410 (void) XDrawLine(display,draw_pixmap,draw_context,
2411 coordinate_info[draw_info->number_coordinates-1].x,
2412 coordinate_info[draw_info->number_coordinates-1].y,
2413 coordinate_info[0].x,coordinate_info[0].y);
2414 break;
2415 }
2416 case FillPolygonElement:
2417 {
2418 (void) XFillPolygon(display,draw_pixmap,draw_context,
2419 draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
2420 CoordModeOrigin);
2421 break;
2422 }
2423 }
2424 (void) XFreeGC(display,draw_context);
2425 /*
2426 Initialize X image.
2427 */
2428 draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
2429 draw_info->height,AllPlanes,ZPixmap);
2430 if (draw_ximage == (XImage *) NULL)
2431 return(MagickFalse);
2432 (void) XFreePixmap(display,draw_pixmap);
2433 /*
2434 Initialize draw image.
2435 */
2436 draw_image=AcquireImage((ImageInfo *) NULL);
2437 if (draw_image == (Image *) NULL)
2438 return(MagickFalse);
2439 draw_image->columns=draw_info->width;
2440 draw_image->rows=draw_info->height;
2441 /*
2442 Transfer drawn X image to image.
2443 */
2444 width=(unsigned int) image->columns;
2445 height=(unsigned int) image->rows;
2446 x=0;
2447 y=0;
2448 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
cristyc57f6942010-11-12 01:47:39 +00002449 (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,
2450 &draw_image->background_color,&image->exception);
cristy3ed852e2009-09-05 21:47:34 +00002451 if (SetImageStorageClass(draw_image,DirectClass) == MagickFalse)
2452 return(MagickFalse);
2453 draw_image->matte=MagickTrue;
2454 exception=(&image->exception);
cristyc57f6942010-11-12 01:47:39 +00002455 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002456 for (y=0; y < (int) draw_image->rows; y++)
2457 {
cristyc57f6942010-11-12 01:47:39 +00002458 register int
cristy3ed852e2009-09-05 21:47:34 +00002459 x;
2460
2461 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002462 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002463
cristyc57f6942010-11-12 01:47:39 +00002464 q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
2465 1,exception);
cristy3ed852e2009-09-05 21:47:34 +00002466 if (q == (PixelPacket *) NULL)
2467 break;
cristyc57f6942010-11-12 01:47:39 +00002468 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002469 {
2470 if (XGetPixel(draw_ximage,x,y) == 0)
2471 {
2472 /*
2473 Set this pixel to the background color.
2474 */
2475 *q=draw_image->background_color;
2476 q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
2477 TransparentOpacity : OpaqueOpacity);
2478 }
2479 else
2480 {
2481 /*
2482 Set this pixel to the pen color.
2483 */
cristyfba5a8b2011-05-03 17:12:12 +00002484 SetRedPixelComponent(q,ScaleShortToQuantum(pixel->pen_color.red));
2485 SetGreenPixelComponent(q,ScaleShortToQuantum(pixel->pen_color.green));
2486 SetBluePixelComponent(q,ScaleShortToQuantum(pixel->pen_color.blue));
2487 SetOpacityPixelComponent(q,(Quantum) (draw_info->stencil ==
2488 OpaqueStencil ? OpaqueOpacity : TransparentOpacity));
cristy3ed852e2009-09-05 21:47:34 +00002489 }
2490 q++;
2491 }
cristyc57f6942010-11-12 01:47:39 +00002492 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002493 break;
2494 }
cristyc57f6942010-11-12 01:47:39 +00002495 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002496 XDestroyImage(draw_ximage);
2497 /*
2498 Determine draw geometry.
2499 */
2500 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2501 if ((width != (unsigned int) draw_image->columns) ||
2502 (height != (unsigned int) draw_image->rows))
2503 {
2504 char
2505 image_geometry[MaxTextExtent];
2506
2507 /*
2508 Scale image.
2509 */
2510 (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
2511 width,height);
2512 (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
2513 }
2514 if (draw_info->degrees != 0.0)
2515 {
2516 Image
2517 *rotate_image;
2518
2519 int
2520 rotations;
2521
2522 MagickRealType
2523 normalized_degrees;
2524
2525 /*
2526 Rotate image.
2527 */
2528 rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
2529 if (rotate_image == (Image *) NULL)
2530 return(MagickFalse);
2531 draw_image=DestroyImage(draw_image);
2532 draw_image=rotate_image;
2533 /*
2534 Annotation is relative to the degree of rotation.
2535 */
2536 normalized_degrees=draw_info->degrees;
2537 while (normalized_degrees < -45.0)
2538 normalized_degrees+=360.0;
2539 for (rotations=0; normalized_degrees > 45.0; rotations++)
2540 normalized_degrees-=90.0;
2541 switch (rotations % 4)
2542 {
2543 default:
2544 case 0:
2545 break;
2546 case 1:
2547 {
2548 /*
2549 Rotate 90 degrees.
2550 */
2551 x=x-(int) draw_image->columns/2;
2552 y=y+(int) draw_image->columns/2;
2553 break;
2554 }
2555 case 2:
2556 {
2557 /*
2558 Rotate 180 degrees.
2559 */
2560 x=x-(int) draw_image->columns;
2561 break;
2562 }
2563 case 3:
2564 {
2565 /*
2566 Rotate 270 degrees.
2567 */
2568 x=x-(int) draw_image->columns/2;
2569 y=y-(int) (draw_image->rows-(draw_image->columns/2));
2570 break;
2571 }
2572 }
2573 }
2574 /*
2575 Composite text onto the image.
2576 */
cristyc57f6942010-11-12 01:47:39 +00002577 draw_view=AcquireCacheView(draw_image);
cristy3ed852e2009-09-05 21:47:34 +00002578 for (y=0; y < (int) draw_image->rows; y++)
2579 {
cristyc57f6942010-11-12 01:47:39 +00002580 register int
cristy3ed852e2009-09-05 21:47:34 +00002581 x;
2582
2583 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002584 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002585
cristyc57f6942010-11-12 01:47:39 +00002586 q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
2587 exception);
cristy3ed852e2009-09-05 21:47:34 +00002588 if (q == (PixelPacket *) NULL)
2589 break;
cristyc57f6942010-11-12 01:47:39 +00002590 for (x=0; x < (int) draw_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002591 {
2592 if (q->opacity != (Quantum) TransparentOpacity)
cristyce70c172010-01-07 17:15:30 +00002593 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +00002594 q++;
2595 }
cristyc57f6942010-11-12 01:47:39 +00002596 if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00002597 break;
2598 }
cristyc57f6942010-11-12 01:47:39 +00002599 draw_view=DestroyCacheView(draw_view);
cristy3ed852e2009-09-05 21:47:34 +00002600 (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
2601 if (draw_info->stencil == TransparentStencil)
cristyc57f6942010-11-12 01:47:39 +00002602 (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,(ssize_t) x,
2603 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002604 else
2605 {
2606 matte=image->matte;
cristyc57f6942010-11-12 01:47:39 +00002607 (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
2608 (ssize_t) y);
cristy3ed852e2009-09-05 21:47:34 +00002609 image->matte=matte;
2610 }
2611 draw_image=DestroyImage(draw_image);
2612 return(MagickTrue);
2613}
2614
2615/*
2616%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2617% %
2618% %
2619% %
2620% X E r r o r %
2621% %
2622% %
2623% %
2624%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2625%
2626% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
2627% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
2628% for XQueryColor. It returns MagickFalse in those cases. Otherwise it returns
2629% True.
2630%
2631% The format of the XError function is:
2632%
2633% XError(display,error)
2634%
2635% A description of each parameter follows:
2636%
2637% o display: Specifies a pointer to the Display structure; returned from
2638% XOpenDisplay.
2639%
2640% o error: Specifies the error event.
2641%
2642*/
2643
2644#if defined(__cplusplus) || defined(c_plusplus)
2645extern "C" {
2646#endif
2647
2648MagickExport int XError(Display *display,XErrorEvent *error)
2649{
2650 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2651 assert(display != (Display *) NULL);
2652 assert(error != (XErrorEvent *) NULL);
2653 xerror_alert=MagickTrue;
2654 switch (error->request_code)
2655 {
2656 case X_GetGeometry:
2657 {
2658 if ((int) error->error_code == BadDrawable)
2659 return(MagickFalse);
2660 break;
2661 }
2662 case X_GetWindowAttributes:
2663 case X_QueryTree:
2664 {
2665 if ((int) error->error_code == BadWindow)
2666 return(MagickFalse);
2667 break;
2668 }
2669 case X_QueryColors:
2670 {
2671 if ((int) error->error_code == BadValue)
2672 return(MagickFalse);
2673 break;
2674 }
2675 }
2676 return(MagickTrue);
2677}
2678
2679#if defined(__cplusplus) || defined(c_plusplus)
2680}
2681#endif
2682
2683/*
2684%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2685% %
2686% %
2687% %
2688% X F r e e R e s o u r c e s %
2689% %
2690% %
2691% %
2692%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2693%
2694% XFreeResources() frees X11 resources.
2695%
2696% The format of the XFreeResources method is:
2697%
2698% void XFreeResources(Display *display,XVisualInfo *visual_info,
2699% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2700% XResourceInfo *resource_info,XWindowInfo *window_info)
2701% resource_info,window_info)
2702%
2703% A description of each parameter follows:
2704%
2705% o display: Specifies a connection to an X server; returned from
2706% XOpenDisplay.
2707%
2708% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2709% returned from XGetVisualInfo.
2710%
2711% o map_info: If map_type is specified, this structure is initialized
2712% with info from the Standard Colormap.
2713%
2714% o pixel: Specifies a pointer to a XPixelInfo structure.
2715%
2716% o font_info: Specifies a pointer to a XFontStruct structure.
2717%
2718% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2719%
2720% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
2721%
2722*/
2723MagickExport void XFreeResources(Display *display,XVisualInfo *visual_info,
2724 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
2725 XResourceInfo *resource_info,XWindowInfo *window_info)
2726{
2727 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2728 assert(display != (Display *) NULL);
2729 assert(resource_info != (XResourceInfo *) NULL);
2730 if (window_info != (XWindowInfo *) NULL)
2731 {
2732 /*
2733 Free X image.
2734 */
2735 if (window_info->ximage != (XImage *) NULL)
2736 XDestroyImage(window_info->ximage);
2737 if (window_info->id != (Window) NULL)
2738 {
2739 /*
2740 Free destroy window and free cursors.
2741 */
2742 if (window_info->id != XRootWindow(display,visual_info->screen))
2743 (void) XDestroyWindow(display,window_info->id);
2744 if (window_info->annotate_context != (GC) NULL)
2745 (void) XFreeGC(display,window_info->annotate_context);
2746 if (window_info->highlight_context != (GC) NULL)
2747 (void) XFreeGC(display,window_info->highlight_context);
2748 if (window_info->widget_context != (GC) NULL)
2749 (void) XFreeGC(display,window_info->widget_context);
2750 if (window_info->cursor != (Cursor) NULL)
2751 (void) XFreeCursor(display,window_info->cursor);
2752 window_info->cursor=(Cursor) NULL;
2753 if (window_info->busy_cursor != (Cursor) NULL)
2754 (void) XFreeCursor(display,window_info->busy_cursor);
2755 window_info->busy_cursor=(Cursor) NULL;
2756 }
2757 }
2758 /*
2759 Free font.
2760 */
2761 if (font_info != (XFontStruct *) NULL)
cristyaafc1922011-03-04 16:59:40 +00002762 {
2763 (void) XFreeFont(display,font_info);
2764 font_info=(XFontStruct *) NULL;
2765 }
cristy3ed852e2009-09-05 21:47:34 +00002766 if (map_info != (XStandardColormap *) NULL)
2767 {
2768 /*
2769 Free X Standard Colormap.
2770 */
2771 if (resource_info->map_type == (char *) NULL)
2772 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
2773 (void) XFree((void *) map_info);
2774 }
2775 /*
2776 Free X visual info.
2777 */
2778 if (visual_info != (XVisualInfo *) NULL)
2779 (void) XFree((void *) visual_info);
2780 if (resource_info->close_server != MagickFalse)
2781 (void) XCloseDisplay(display);
2782}
2783
2784/*
2785%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2786% %
2787% %
2788% %
2789% X F r e e S t a n d a r d C o l o r m a p %
2790% %
2791% %
2792% %
2793%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2794%
2795% XFreeStandardColormap() frees an X11 colormap.
2796%
2797% The format of the XFreeStandardColormap method is:
2798%
2799% void XFreeStandardColormap(Display *display,
2800% const XVisualInfo *visual_info,XStandardColormap *map_info,
2801% XPixelInfo *pixel)
2802%
2803% A description of each parameter follows:
2804%
2805% o display: Specifies a connection to an X server; returned from
2806% XOpenDisplay.
2807%
2808% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2809% returned from XGetVisualInfo.
2810%
2811% o map_info: If map_type is specified, this structure is initialized
2812% with info from the Standard Colormap.
2813%
2814% o pixel: Specifies a pointer to a XPixelInfo structure.
2815%
2816*/
2817MagickExport void XFreeStandardColormap(Display *display,
2818 const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
2819{
2820 /*
2821 Free colormap.
2822 */
2823 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2824 assert(display != (Display *) NULL);
2825 assert(visual_info != (XVisualInfo *) NULL);
2826 assert(map_info != (XStandardColormap *) NULL);
2827 (void) XFlush(display);
2828 if (map_info->colormap != (Colormap) NULL)
2829 {
2830 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
2831 (void) XFreeColormap(display,map_info->colormap);
2832 else
2833 if (pixel != (XPixelInfo *) NULL)
2834 if ((visual_info->klass != TrueColor) &&
2835 (visual_info->klass != DirectColor))
2836 (void) XFreeColors(display,map_info->colormap,pixel->pixels,
2837 (int) pixel->colors,0);
2838 }
2839 map_info->colormap=(Colormap) NULL;
2840 if (pixel != (XPixelInfo *) NULL)
2841 {
cristyf2faecf2010-05-28 19:19:36 +00002842 if (pixel->pixels != (unsigned long *) NULL)
2843 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
2844 pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00002845 }
2846}
2847
2848/*
2849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2850% %
2851% %
2852% %
2853% X G e t A n n o t a t e I n f o %
2854% %
2855% %
2856% %
2857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2858%
2859% XGetAnnotateInfo() initializes the AnnotateInfo structure.
2860%
2861% The format of the XGetAnnotateInfo method is:
2862%
2863% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2864%
2865% A description of each parameter follows:
2866%
2867% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
2868%
2869*/
2870MagickExport void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
2871{
2872 /*
2873 Initialize annotate structure.
2874 */
2875 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2876 assert(annotate_info != (XAnnotateInfo *) NULL);
2877 annotate_info->x=0;
2878 annotate_info->y=0;
2879 annotate_info->width=0;
2880 annotate_info->height=0;
2881 annotate_info->stencil=ForegroundStencil;
2882 annotate_info->degrees=0.0;
2883 annotate_info->font_info=(XFontStruct *) NULL;
2884 annotate_info->text=(char *) NULL;
2885 *annotate_info->geometry='\0';
2886 annotate_info->previous=(XAnnotateInfo *) NULL;
2887 annotate_info->next=(XAnnotateInfo *) NULL;
2888 (void) XSupportsLocale();
2889 (void) XSetLocaleModifiers("");
2890}
2891
2892/*
2893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2894% %
2895% %
2896% %
2897% X G e t M a p I n f o %
2898% %
2899% %
2900% %
2901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2902%
2903% XGetMapInfo() initializes the XStandardColormap structure.
2904%
2905% The format of the XStandardColormap method is:
2906%
2907% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
2908% XStandardColormap *map_info)
2909%
2910% A description of each parameter follows:
2911%
2912% o colormap: Specifies the ID of the X server colormap.
2913%
2914% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2915% returned from XGetVisualInfo.
2916%
2917% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
2918%
2919*/
2920MagickExport void XGetMapInfo(const XVisualInfo *visual_info,
2921 const Colormap colormap,XStandardColormap *map_info)
2922{
2923 /*
2924 Initialize map info.
2925 */
2926 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2927 assert(visual_info != (XVisualInfo *) NULL);
2928 assert(map_info != (XStandardColormap *) NULL);
2929 map_info->colormap=colormap;
2930 map_info->red_max=visual_info->red_mask;
cristybb503372010-05-27 20:51:26 +00002931 map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002932 if (map_info->red_max != 0)
2933 while ((map_info->red_max & 0x01) == 0)
2934 {
2935 map_info->red_max>>=1;
2936 map_info->red_mult<<=1;
2937 }
2938 map_info->green_max=visual_info->green_mask;
cristybb503372010-05-27 20:51:26 +00002939 map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002940 if (map_info->green_max != 0)
2941 while ((map_info->green_max & 0x01) == 0)
2942 {
2943 map_info->green_max>>=1;
2944 map_info->green_mult<<=1;
2945 }
2946 map_info->blue_max=visual_info->blue_mask;
cristybb503372010-05-27 20:51:26 +00002947 map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
cristy3ed852e2009-09-05 21:47:34 +00002948 if (map_info->blue_max != 0)
2949 while ((map_info->blue_max & 0x01) == 0)
2950 {
2951 map_info->blue_max>>=1;
2952 map_info->blue_mult<<=1;
2953 }
2954 map_info->base_pixel=0;
2955}
2956
2957/*
2958%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2959% %
2960% %
2961% %
2962% X G e t P i x e l I n f o %
2963% %
2964% %
2965% %
2966%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2967%
2968% XGetPixelPacket() initializes the PixelPacket structure.
2969%
2970% The format of the XGetPixelPacket method is:
2971%
2972% void XGetPixelPacket(Display *display,const XVisualInfo *visual_info,
2973% const XStandardColormap *map_info,const XResourceInfo *resource_info,
2974% Image *image,XPixelInfo *pixel)
2975% pixel)
2976%
2977% A description of each parameter follows:
2978%
2979% o display: Specifies a connection to an X server; returned from
2980% XOpenDisplay.
2981%
2982% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
2983% returned from XGetVisualInfo.
2984%
2985% o map_info: If map_type is specified, this structure is initialized
2986% with info from the Standard Colormap.
2987%
2988% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2989%
2990% o image: the image.
2991%
2992% o pixel: Specifies a pointer to a XPixelInfo structure.
2993%
2994*/
2995MagickExport void XGetPixelPacket(Display *display,
2996 const XVisualInfo *visual_info,const XStandardColormap *map_info,
2997 const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
2998{
2999 static const char
3000 *PenColors[MaxNumberPens]=
3001 {
3002 "#000000000000", /* black */
3003 "#00000000ffff", /* blue */
3004 "#0000ffffffff", /* cyan */
3005 "#0000ffff0000", /* green */
3006 "#bdbdbdbdbdbd", /* gray */
3007 "#ffff00000000", /* red */
3008 "#ffff0000ffff", /* magenta */
3009 "#ffffffff0000", /* yellow */
3010 "#ffffffffffff", /* white */
3011 "#bdbdbdbdbdbd", /* gray */
3012 "#bdbdbdbdbdbd" /* gray */
3013 };
3014
3015 Colormap
3016 colormap;
3017
cristybb503372010-05-27 20:51:26 +00003018 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003019 i;
3020
3021 Status
3022 status;
3023
3024 unsigned int
3025 packets;
3026
3027 /*
3028 Initialize pixel info.
3029 */
3030 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3031 assert(display != (Display *) NULL);
3032 assert(visual_info != (XVisualInfo *) NULL);
3033 assert(map_info != (XStandardColormap *) NULL);
3034 assert(resource_info != (XResourceInfo *) NULL);
3035 assert(pixel != (XPixelInfo *) NULL);
3036 pixel->colors=0;
3037 if (image != (Image *) NULL)
3038 if (image->storage_class == PseudoClass)
cristyc57f6942010-11-12 01:47:39 +00003039 pixel->colors=(ssize_t) image->colors;
cristy3ed852e2009-09-05 21:47:34 +00003040 packets=(unsigned int)
3041 MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
cristyf2faecf2010-05-28 19:19:36 +00003042 if (pixel->pixels != (unsigned long *) NULL)
3043 pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
3044 pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
cristy3ed852e2009-09-05 21:47:34 +00003045 sizeof(pixel->pixels));
cristyf2faecf2010-05-28 19:19:36 +00003046 if (pixel->pixels == (unsigned long *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00003047 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
3048 image->filename);
3049 /*
3050 Set foreground color.
3051 */
3052 colormap=map_info->colormap;
3053 (void) XParseColor(display,colormap,(char *) ForegroundColor,
3054 &pixel->foreground_color);
3055 status=XParseColor(display,colormap,resource_info->foreground_color,
3056 &pixel->foreground_color);
3057 if (status == False)
3058 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3059 resource_info->foreground_color);
3060 pixel->foreground_color.pixel=
3061 XStandardPixel(map_info,&pixel->foreground_color);
3062 pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
3063 /*
3064 Set background color.
3065 */
3066 (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
3067 status=XParseColor(display,colormap,resource_info->background_color,
3068 &pixel->background_color);
3069 if (status == False)
3070 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3071 resource_info->background_color);
3072 pixel->background_color.pixel=
3073 XStandardPixel(map_info,&pixel->background_color);
3074 pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
3075 /*
3076 Set border color.
3077 */
3078 (void) XParseColor(display,colormap,(char *) BorderColor,
3079 &pixel->border_color);
3080 status=XParseColor(display,colormap,resource_info->border_color,
3081 &pixel->border_color);
3082 if (status == False)
3083 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3084 resource_info->border_color);
3085 pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
3086 pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
3087 /*
3088 Set matte color.
3089 */
3090 pixel->matte_color=pixel->background_color;
3091 if (resource_info->matte_color != (char *) NULL)
3092 {
3093 /*
3094 Matte color is specified as a X resource or command line argument.
3095 */
3096 status=XParseColor(display,colormap,resource_info->matte_color,
3097 &pixel->matte_color);
3098 if (status == False)
3099 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3100 resource_info->matte_color);
3101 pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
3102 pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
3103 }
3104 /*
3105 Set highlight color.
3106 */
3107 pixel->highlight_color.red=(unsigned short) ((
3108 pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
3109 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3110 pixel->highlight_color.green=(unsigned short) ((
3111 pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
3112 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3113 pixel->highlight_color.blue=(unsigned short) ((
3114 pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
3115 (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
3116 pixel->highlight_color.pixel=
3117 XStandardPixel(map_info,&pixel->highlight_color);
3118 pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
3119 /*
3120 Set shadow color.
3121 */
3122 pixel->shadow_color.red=(unsigned short) (((MagickRealType)
3123 pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
3124 pixel->shadow_color.green=(unsigned short) (((MagickRealType)
3125 pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
3126 pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
3127 pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
3128 pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
3129 pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
3130 /*
3131 Set depth color.
3132 */
3133 pixel->depth_color.red=(unsigned short) (((MagickRealType)
3134 pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
3135 pixel->depth_color.green=(unsigned short) (((MagickRealType)
3136 pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
3137 pixel->depth_color.blue=(unsigned short) (((MagickRealType)
3138 pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
3139 pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
3140 pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
3141 /*
3142 Set trough color.
3143 */
3144 pixel->trough_color.red=(unsigned short) (((MagickRealType)
3145 pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
3146 pixel->trough_color.green=(unsigned short) (((MagickRealType)
3147 pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
3148 pixel->trough_color.blue=(unsigned short) (((MagickRealType)
3149 pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
3150 pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
3151 pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
3152 /*
3153 Set pen color.
3154 */
3155 for (i=0; i < MaxNumberPens; i++)
3156 {
3157 (void) XParseColor(display,colormap,(char *) PenColors[i],
3158 &pixel->pen_colors[i]);
3159 status=XParseColor(display,colormap,resource_info->pen_colors[i],
3160 &pixel->pen_colors[i]);
3161 if (status == False)
3162 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
3163 resource_info->pen_colors[i]);
3164 pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
3165 pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
3166 }
3167 pixel->box_color=pixel->background_color;
3168 pixel->pen_color=pixel->foreground_color;
3169 pixel->box_index=0;
3170 pixel->pen_index=1;
3171 if (image != (Image *) NULL)
3172 {
3173 if ((resource_info->gamma_correct != MagickFalse) &&
3174 (image->gamma != 0.0))
3175 {
3176 GeometryInfo
3177 geometry_info;
3178
3179 MagickStatusType
3180 flags;
3181
3182 /*
3183 Initialize map relative to display and image gamma.
3184 */
3185 flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
3186 red_gamma=geometry_info.rho;
3187 green_gamma=geometry_info.sigma;
3188 if ((flags & SigmaValue) == 0)
3189 green_gamma=red_gamma;
3190 blue_gamma=geometry_info.xi;
3191 if ((flags & XiValue) == 0)
3192 blue_gamma=red_gamma;
3193 red_gamma*=image->gamma;
3194 green_gamma*=image->gamma;
3195 blue_gamma*=image->gamma;
3196 }
3197 if (image->storage_class == PseudoClass)
3198 {
3199 /*
3200 Initialize pixel array for images of type PseudoClass.
3201 */
cristybb503372010-05-27 20:51:26 +00003202 for (i=0; i < (ssize_t) image->colors; i++)
cristy7e9f2332011-04-22 23:12:22 +00003203 pixel->pixels[i]=XGammaPixel(map_info,image->colormap+i);
cristy3ed852e2009-09-05 21:47:34 +00003204 for (i=0; i < MaxNumberPens; i++)
3205 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
3206 pixel->colors+=MaxNumberPens;
3207 }
3208 }
3209}
3210
3211/*
3212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3213% %
3214% %
3215% %
3216% X G e t R e s o u r c e C l a s s %
3217% %
3218% %
3219% %
3220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3221%
3222% XGetResourceClass() queries the X server for the specified resource name or
3223% class. If the resource name or class is not defined in the database, the
3224% supplied default value is returned.
3225%
3226% The format of the XGetResourceClass method is:
3227%
3228% char *XGetResourceClass(XrmDatabase database,const char *client_name,
3229% const char *keyword,char *resource_default)
3230%
3231% A description of each parameter follows:
3232%
3233% o database: Specifies a resource database; returned from
3234% XrmGetStringDatabase.
3235%
3236% o client_name: Specifies the application name used to retrieve resource
3237% info from the X server database.
3238%
3239% o keyword: Specifies the keyword of the value being retrieved.
3240%
3241% o resource_default: Specifies the default value to return if the query
3242% fails to find the specified keyword/class.
3243%
3244*/
3245MagickExport char *XGetResourceClass(XrmDatabase database,
3246 const char *client_name,const char *keyword,char *resource_default)
3247{
3248 char
3249 resource_class[MaxTextExtent],
3250 resource_name[MaxTextExtent];
3251
3252 static char
3253 *resource_type;
3254
3255 Status
3256 status;
3257
3258 XrmValue
3259 resource_value;
3260
3261 if (database == (XrmDatabase) NULL)
3262 return(resource_default);
3263 *resource_name='\0';
3264 *resource_class='\0';
3265 if (keyword != (char *) NULL)
3266 {
3267 int
3268 c,
3269 k;
3270
3271 /*
3272 Initialize resource keyword and class.
3273 */
3274 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",
3275 client_name,keyword);
3276 c=(int) (*client_name);
3277 if ((c >= XK_a) && (c <= XK_z))
3278 c-=(XK_a-XK_A);
3279 else
3280 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3281 c-=(XK_agrave-XK_Agrave);
3282 else
3283 if ((c >= XK_oslash) && (c <= XK_thorn))
3284 c-=(XK_oslash-XK_Ooblique);
3285 k=(int) (*keyword);
3286 if ((k >= XK_a) && (k <= XK_z))
3287 k-=(XK_a-XK_A);
3288 else
3289 if ((k >= XK_agrave) && (k <= XK_odiaeresis))
3290 k-=(XK_agrave-XK_Agrave);
3291 else
3292 if ((k >= XK_oslash) && (k <= XK_thorn))
3293 k-=(XK_oslash-XK_Ooblique);
3294 (void) FormatMagickString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
3295 client_name+1,k,keyword+1);
3296 }
3297 status=XrmGetResource(database,resource_name,resource_class,&resource_type,
3298 &resource_value);
3299 if (status == False)
3300 return(resource_default);
3301 return(resource_value.addr);
3302}
3303
3304/*
3305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3306% %
3307% %
3308% %
3309% X G e t R e s o u r c e D a t a b a s e %
3310% %
3311% %
3312% %
3313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3314%
3315% XGetResourceDatabase() creates a new resource database and initializes it.
3316%
3317% The format of the XGetResourceDatabase method is:
3318%
3319% XrmDatabase XGetResourceDatabase(Display *display,
3320% const char *client_name)
3321%
3322% A description of each parameter follows:
3323%
3324% o database: XGetResourceDatabase() returns the database after it is
3325% initialized.
3326%
3327% o display: Specifies a connection to an X server; returned from
3328% XOpenDisplay.
3329%
3330% o client_name: Specifies the application name used to retrieve resource
3331% info from the X server database.
3332%
3333*/
3334MagickExport XrmDatabase XGetResourceDatabase(Display *display,
3335 const char *client_name)
3336{
3337 char
3338 filename[MaxTextExtent];
3339
3340 int
3341 c;
3342
3343 register const char
3344 *p;
3345
3346 XrmDatabase
3347 resource_database,
3348 server_database;
3349
3350 if (display == (Display *) NULL)
3351 return((XrmDatabase) NULL);
3352 assert(client_name != (char *) NULL);
3353 /*
3354 Initialize resource database.
3355 */
3356 XrmInitialize();
3357 (void) XGetDefault(display,(char *) client_name,"dummy");
3358 resource_database=XrmGetDatabase(display);
3359 /*
3360 Combine application database.
3361 */
3362 if (client_name != (char *) NULL)
3363 {
3364 /*
3365 Get basename of client.
3366 */
3367 p=client_name+(strlen(client_name)-1);
3368 while ((p > client_name) && (*p != '/'))
3369 p--;
3370 if (*p == '/')
3371 client_name=p+1;
3372 }
3373 c=(int) (*client_name);
3374 if ((c >= XK_a) && (c <= XK_z))
3375 c-=(XK_a-XK_A);
3376 else
3377 if ((c >= XK_agrave) && (c <= XK_odiaeresis))
3378 c-=(XK_agrave-XK_Agrave);
3379 else
3380 if ((c >= XK_oslash) && (c <= XK_thorn))
3381 c-=(XK_oslash-XK_Ooblique);
3382#if defined(X11_APPLICATION_PATH)
3383 (void) FormatMagickString(filename,MaxTextExtent,"%s%c%s",
3384 X11_APPLICATION_PATH,c,client_name+1);
3385 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3386#endif
3387 if (XResourceManagerString(display) != (char *) NULL)
3388 {
3389 /*
3390 Combine server database.
3391 */
3392 server_database=XrmGetStringDatabase(XResourceManagerString(display));
3393 XrmCombineDatabase(server_database,&resource_database,MagickFalse);
3394 }
3395 /*
3396 Merge user preferences database.
3397 */
3398#if defined(X11_PREFERENCES_PATH)
3399 (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
3400 X11_PREFERENCES_PATH,client_name);
3401 ExpandFilename(filename);
3402 (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
3403#endif
3404 return(resource_database);
3405}
3406
3407/*
3408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3409% %
3410% %
3411% %
3412% X G e t R e s o u r c e I n f o %
3413% %
3414% %
3415% %
3416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3417%
3418% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
3419%
3420% The format of the XGetResourceInfo method is:
3421%
3422% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
3423% const char *client_name,XResourceInfo *resource_info)
3424%
3425% A description of each parameter follows:
3426%
3427% o image_info: the image info.
3428%
3429% o database: Specifies a resource database; returned from
3430% XrmGetStringDatabase.
3431%
3432% o client_name: Specifies the application name used to retrieve
3433% resource info from the X server database.
3434%
3435% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3436%
3437*/
3438MagickExport void XGetResourceInfo(const ImageInfo *image_info,
3439 XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
3440{
3441 char
cristy00976d82011-02-20 20:31:28 +00003442 *directory,
cristy3ed852e2009-09-05 21:47:34 +00003443 *resource_value;
3444
3445 /*
3446 Initialize resource info fields.
3447 */
3448 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3449 assert(resource_info != (XResourceInfo *) NULL);
3450 (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
3451 resource_info->resource_database=database;
3452 resource_info->image_info=(ImageInfo *) image_info;
3453 (void) SetImageInfoProgressMonitor(resource_info->image_info,
3454 XMagickProgressMonitor,(void *) NULL);
3455 resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
3456 resource_info->close_server=MagickTrue;
3457 resource_info->client_name=AcquireString(client_name);
3458 resource_value=XGetResourceClass(database,client_name,"backdrop",
3459 (char *) "False");
3460 resource_info->backdrop=IsMagickTrue(resource_value);
3461 resource_info->background_color=XGetResourceInstance(database,client_name,
3462 "background",(char *) "#d6d6d6d6d6d6");
3463 resource_info->border_color=XGetResourceInstance(database,client_name,
3464 "borderColor",BorderColor);
3465 resource_value=XGetResourceClass(database,client_name,"borderWidth",
3466 (char *) "2");
cristy00976d82011-02-20 20:31:28 +00003467 resource_info->border_width=(unsigned int) StringToUnsignedLong(
3468 resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003469 resource_value=XGetResourceClass(database,client_name,"colormap",
3470 (char *) "shared");
3471 resource_info->colormap=UndefinedColormap;
3472 if (LocaleCompare("private",resource_value) == 0)
3473 resource_info->colormap=PrivateColormap;
3474 if (LocaleCompare("shared",resource_value) == 0)
3475 resource_info->colormap=SharedColormap;
3476 if (resource_info->colormap == UndefinedColormap)
3477 ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
3478 resource_value);
3479 resource_value=XGetResourceClass(database,client_name,
3480 "colorRecovery",(char *) "False");
3481 resource_info->color_recovery=IsMagickTrue(resource_value);
3482 resource_value=XGetResourceClass(database,client_name,"confirmExit",
3483 (char *) "False");
3484 resource_info->confirm_exit=IsMagickTrue(resource_value);
3485 resource_value=XGetResourceClass(database,client_name,"confirmEdit",
3486 (char *) "False");
3487 resource_info->confirm_edit=IsMagickTrue(resource_value);
cristyba0c3252010-06-27 13:31:44 +00003488 resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
cristye27293e2009-12-18 02:53:20 +00003489 resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003490 resource_info->display_gamma=XGetResourceClass(database,client_name,
3491 "displayGamma",(char *) "2.2");
3492 resource_value=XGetResourceClass(database,client_name,"displayWarnings",
3493 (char *) "True");
3494 resource_info->display_warnings=IsMagickTrue(resource_value);
3495 resource_info->font=XGetResourceClass(database,client_name,"font",
3496 (char *) NULL);
3497 resource_info->font=XGetResourceClass(database,client_name,"fontList",
3498 resource_info->font);
3499 resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
3500 (char *) "fixed");
3501 resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
3502 (char *) "variable");
3503 resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
3504 (char *) "5x8");
3505 resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
3506 (char *) "6x10");
3507 resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
3508 (char *) "7x13bold");
3509 resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
3510 (char *) "8x13bold");
3511 resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
3512 (char *) "9x15bold");
3513 resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
3514 (char *) "10x20");
3515 resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
3516 (char *) "12x24");
3517 resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
3518 (char *) "fixed");
3519 resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
3520 (char *) "fixed");
3521 resource_info->foreground_color=XGetResourceInstance(database,client_name,
3522 "foreground",ForegroundColor);
3523 resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
3524 (char *) "True");
3525 resource_info->gamma_correct=IsMagickTrue(resource_value);
3526 resource_info->image_geometry=ConstantString(XGetResourceClass(database,
3527 client_name,"geometry",(char *) NULL));
3528 resource_value=XGetResourceClass(database,client_name,"gravity",
3529 (char *) "Center");
cristy042ee782011-04-22 18:48:30 +00003530 resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
cristy3ed852e2009-09-05 21:47:34 +00003531 MagickFalse,resource_value);
cristy00976d82011-02-20 20:31:28 +00003532 directory=getcwd(resource_info->home_directory,MaxTextExtent);
3533 (void) directory;
cristy3ed852e2009-09-05 21:47:34 +00003534 resource_info->icon_geometry=XGetResourceClass(database,client_name,
3535 "iconGeometry",(char *) NULL);
3536 resource_value=XGetResourceClass(database,client_name,"iconic",
3537 (char *) "False");
3538 resource_info->iconic=IsMagickTrue(resource_value);
3539 resource_value=XGetResourceClass(database,client_name,"immutable",
3540 LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
3541 (char *) "False");
3542 resource_info->immutable=IsMagickTrue(resource_value);
3543 resource_value=XGetResourceClass(database,client_name,"magnify",
3544 (char *) "3");
cristye27293e2009-12-18 02:53:20 +00003545 resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003546 resource_info->map_type=XGetResourceClass(database,client_name,"map",
3547 (char *) NULL);
3548 resource_info->matte_color=XGetResourceInstance(database,client_name,
3549 "mattecolor",(char *) NULL);
3550 resource_info->name=ConstantString(XGetResourceClass(database,client_name,
3551 "name",(char *) NULL));
3552 resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
3553 (char *) "black");
3554 resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
3555 (char *) "blue");
3556 resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
3557 (char *) "cyan");
3558 resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
3559 (char *) "green");
3560 resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
3561 (char *) "gray");
3562 resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
3563 (char *) "red");
3564 resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
3565 (char *) "magenta");
3566 resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
3567 (char *) "yellow");
3568 resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
3569 (char *) "white");
3570 resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
3571 (char *) "gray");
3572 resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
3573 (char *) "gray");
3574 resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
cristye27293e2009-12-18 02:53:20 +00003575 resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003576 resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
cristyf2f27272009-12-17 14:48:46 +00003577 resource_info->quantum=StringToLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003578 resource_info->text_font=XGetResourceClass(database,client_name,(char *)
3579 "font",(char *) "fixed");
3580 resource_info->text_font=XGetResourceClass(database,client_name,
3581 "textFontList",resource_info->text_font);
3582 resource_info->title=XGetResourceClass(database,client_name,"title",
3583 (char *) NULL);
3584 resource_value=XGetResourceClass(database,client_name,"undoCache",
3585 (char *) "16");
cristye27293e2009-12-18 02:53:20 +00003586 resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
cristy3ed852e2009-09-05 21:47:34 +00003587 resource_value=XGetResourceClass(database,client_name,"update",
3588 (char *) "False");
3589 resource_info->update=IsMagickTrue(resource_value);
3590 resource_value=XGetResourceClass(database,client_name,"usePixmap",
3591 (char *) "True");
3592 resource_info->use_pixmap=IsMagickTrue(resource_value);
3593 resource_value=XGetResourceClass(database,client_name,"sharedMemory",
3594 (char *) "True");
3595 resource_info->use_shared_memory=IsMagickTrue(resource_value);
3596 resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
3597 (char *) NULL);
3598 resource_info->window_group=XGetResourceClass(database,client_name,
3599 "windowGroup",(char *) NULL);
3600 resource_info->window_id=XGetResourceClass(database,client_name,"window",
3601 (char *) NULL);
3602 resource_info->write_filename=XGetResourceClass(database,client_name,
3603 "writeFilename",(char *) NULL);
3604}
3605
3606/*
3607%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3608% %
3609% %
3610% %
3611% X G e t R e s o u r c e I n s t a n c e %
3612% %
3613% %
3614% %
3615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3616%
3617% XGetResourceInstance() queries the X server for the specified resource name.
3618% If the resource name is not defined in the database, the supplied default
3619% value is returned.
3620%
3621% The format of the XGetResourceInstance method is:
3622%
3623% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
3624% const char *keyword,const char *resource_default)
3625%
3626% A description of each parameter follows:
3627%
3628% o database: Specifies a resource database; returned from
3629% XrmGetStringDatabase.
3630%
3631% o client_name: Specifies the application name used to retrieve
3632% resource info from the X server database.
3633%
3634% o keyword: Specifies the keyword of the value being retrieved.
3635%
3636% o resource_default: Specifies the default value to return if the query
3637% fails to find the specified keyword/class.
3638%
3639*/
3640MagickExport char *XGetResourceInstance(XrmDatabase database,
3641 const char *client_name,const char *keyword,const char *resource_default)
3642{
3643 char
3644 *resource_type,
3645 resource_name[MaxTextExtent];
3646
3647 Status
3648 status;
3649
3650 XrmValue
3651 resource_value;
3652
3653 if (database == (XrmDatabase) NULL)
3654 return((char *) resource_default);
3655 *resource_name='\0';
3656 if (keyword != (char *) NULL)
3657 (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",client_name,
3658 keyword);
3659 status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
3660 &resource_value);
3661 if (status == False)
3662 return((char *) resource_default);
3663 return(resource_value.addr);
3664}
3665
3666/*
3667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3668% %
3669% %
3670% %
3671% X G e t S c r e e n D e n s i t y %
3672% %
3673% %
3674% %
3675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3676%
3677% XGetScreenDensity() returns the density of the X server screen in
3678% dots-per-inch.
3679%
3680% The format of the XGetScreenDensity method is:
3681%
3682% char *XGetScreenDensity(Display *display)
3683%
3684% A description of each parameter follows:
3685%
3686% o density: XGetScreenDensity() returns the density of the X screen in
3687% dots-per-inch.
3688%
3689% o display: Specifies a connection to an X server; returned from
3690% XOpenDisplay.
3691%
3692*/
3693MagickExport char *XGetScreenDensity(Display *display)
3694{
3695 char
3696 density[MaxTextExtent];
3697
3698 double
3699 x_density,
3700 y_density;
3701
3702 /*
3703 Set density as determined by screen size.
3704 */
3705 x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
3706 ((double) DisplayWidthMM(display,XDefaultScreen(display))));
3707 y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
3708 ((double) DisplayHeightMM(display,XDefaultScreen(display))));
cristye7f51092010-01-17 00:39:37 +00003709 (void) FormatMagickString(density,MaxTextExtent,"%gx%g",x_density,
cristy8cd5b312010-01-07 01:10:24 +00003710 y_density);
cristy3ed852e2009-09-05 21:47:34 +00003711 return(GetPageGeometry(density));
3712}
3713
3714/*
3715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3716% %
3717% %
3718% %
3719+ X G e t S u b w i n d o w %
3720% %
3721% %
3722% %
3723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3724%
3725% XGetSubwindow() returns the subwindow of a window chosen the user with the
3726% pointer and a button press.
3727%
3728% The format of the XGetSubwindow method is:
3729%
3730% Window XGetSubwindow(Display *display,Window window,int x,int y)
3731%
3732% A description of each parameter follows:
3733%
3734% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
3735% otherwise the subwindow is returned.
3736%
3737% o display: Specifies a connection to an X server; returned from
3738% XOpenDisplay.
3739%
3740% o window: Specifies a pointer to a Window.
3741%
3742% o x: the x coordinate of the pointer relative to the origin of the
3743% window.
3744%
3745% o y: the y coordinate of the pointer relative to the origin of the
3746% window.
3747%
cristy3ed852e2009-09-05 21:47:34 +00003748*/
3749static Window XGetSubwindow(Display *display,Window window,int x,int y)
3750{
3751 int
3752 x_offset,
3753 y_offset;
3754
3755 Status
3756 status;
3757
3758 Window
3759 source_window,
3760 target_window;
3761
3762 assert(display != (Display *) NULL);
3763 source_window=XRootWindow(display,XDefaultScreen(display));
3764 if (window == (Window) NULL)
3765 return(source_window);
3766 target_window=window;
3767 for ( ; ; )
3768 {
3769 status=XTranslateCoordinates(display,source_window,window,x,y,
3770 &x_offset,&y_offset,&target_window);
3771 if (status != True)
3772 break;
3773 if (target_window == (Window) NULL)
3774 break;
3775 source_window=window;
3776 window=target_window;
3777 x=x_offset;
3778 y=y_offset;
3779 }
3780 if (target_window == (Window) NULL)
3781 target_window=window;
3782 return(target_window);
3783}
3784
3785/*
3786%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3787% %
3788% %
3789% %
3790% X G e t W i n d o w C o l o r %
3791% %
3792% %
3793% %
3794%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3795%
3796% XGetWindowColor() returns the color of a pixel interactively chosen from the
3797% X server.
3798%
3799% The format of the XGetWindowColor method is:
3800%
3801% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
3802% char *name)
3803%
3804% A description of each parameter follows:
3805%
3806% o display: Specifies a connection to an X server; returned from
3807% XOpenDisplay.
3808%
3809% o windows: Specifies a pointer to a XWindows structure.
3810%
3811% o name: the name of the color if found in the X Color Database is
3812% returned in this character string.
3813%
3814*/
3815MagickExport MagickBooleanType XGetWindowColor(Display *display,
3816 XWindows *windows,char *name)
3817{
3818 int
3819 x,
3820 y;
3821
3822 PixelPacket
3823 pixel;
3824
3825 RectangleInfo
3826 crop_info;
3827
3828 Status
3829 status;
3830
3831 Window
3832 child,
3833 client_window,
3834 root_window,
3835 target_window;
3836
3837 XColor
3838 color;
3839
3840 XImage
3841 *ximage;
3842
3843 XWindowAttributes
3844 window_attributes;
3845
3846 /*
3847 Choose a pixel from the X server.
3848 */
3849 assert(display != (Display *) NULL);
3850 assert(name != (char *) NULL);
3851 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
3852 *name='\0';
3853 target_window=XSelectWindow(display,&crop_info);
3854 if (target_window == (Window) NULL)
3855 return(MagickFalse);
3856 root_window=XRootWindow(display,XDefaultScreen(display));
3857 client_window=target_window;
3858 if (target_window != root_window)
3859 {
3860 unsigned int
3861 d;
3862
3863 /*
3864 Get client window.
3865 */
3866 status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
3867 if (status != False)
3868 {
3869 client_window=XClientWindow(display,target_window);
3870 target_window=client_window;
3871 }
3872 }
3873 /*
3874 Verify window is viewable.
3875 */
3876 status=XGetWindowAttributes(display,target_window,&window_attributes);
3877 if ((status == False) || (window_attributes.map_state != IsViewable))
3878 return(MagickFalse);
3879 /*
3880 Get window X image.
3881 */
3882 (void) XTranslateCoordinates(display,root_window,target_window,
3883 (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
3884 ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
3885 if (ximage == (XImage *) NULL)
3886 return(MagickFalse);
3887 color.pixel=XGetPixel(ximage,0,0);
3888 XDestroyImage(ximage);
3889 /*
3890 Match color against the color database.
3891 */
3892 (void) XQueryColor(display,window_attributes.colormap,&color);
3893 pixel.red=ScaleShortToQuantum(color.red);
3894 pixel.green=ScaleShortToQuantum(color.green);
3895 pixel.blue=ScaleShortToQuantum(color.blue);
3896 pixel.opacity=OpaqueOpacity;
3897 (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
3898 &windows->image.image->exception);
3899 return(MagickTrue);
3900}
3901
3902/*
3903%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3904% %
3905% %
3906% %
3907+ X G e t W i n d o w I m a g e %
3908% %
3909% %
3910% %
3911%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3912%
3913% XGetWindowImage() reads an image from the target X window and returns it.
3914% XGetWindowImage() optionally descends the window hierarchy and overlays the
3915% target image with each child image in an optimized fashion. Any child
3916% window that have the same visual, colormap, and are contained by its parent
3917% are exempted.
3918%
3919% The format of the XGetWindowImage method is:
3920%
3921% Image *XGetWindowImage(Display *display,const Window window,
3922% const unsigned int borders,const unsigned int level)
3923%
3924% A description of each parameter follows:
3925%
3926% o display: Specifies a connection to an X server; returned from
3927% XOpenDisplay.
3928%
3929% o window: Specifies the window to obtain the image from.
3930%
3931% o borders: Specifies whether borders pixels are to be saved with
3932% the image.
3933%
3934% o level: Specifies an unsigned integer representing the level of
3935% decent in the window hierarchy. This value must be zero or one on
3936% the initial call to XGetWindowImage. A value of zero returns after
3937% one call. A value of one causes the function to descend the window
3938% hierarchy and overlay the target image with each subwindow image.
3939%
cristy3ed852e2009-09-05 21:47:34 +00003940*/
3941static Image *XGetWindowImage(Display *display,const Window window,
3942 const unsigned int borders,const unsigned int level)
3943{
3944 typedef struct _ColormapInfo
3945 {
3946 Colormap
3947 colormap;
3948
3949 XColor
3950 *colors;
3951
3952 struct _ColormapInfo
3953 *next;
3954 } ColormapInfo;
3955
3956 typedef struct _WindowInfo
3957 {
3958 Window
3959 window,
3960 parent;
3961
3962 Visual
3963 *visual;
3964
3965 Colormap
3966 colormap;
3967
3968 XSegment
3969 bounds;
3970
3971 RectangleInfo
3972 crop_info;
3973 } WindowInfo;
3974
3975 IndexPacket
3976 index;
3977
3978 int
3979 display_height,
3980 display_width,
3981 id,
3982 x_offset,
3983 y_offset;
3984
3985 RectangleInfo
3986 crop_info;
3987
3988 register IndexPacket
3989 *indexes;
3990
3991 register int
3992 i;
3993
3994 static ColormapInfo
3995 *colormap_info = (ColormapInfo *) NULL;
3996
3997 static int
3998 max_windows = 0,
3999 number_windows = 0;
4000
4001 static WindowInfo
4002 *window_info;
4003
4004 Status
4005 status;
4006
4007 Window
4008 child,
4009 root_window;
4010
4011 XWindowAttributes
4012 window_attributes;
4013
4014 /*
4015 Verify window is viewable.
4016 */
4017 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4018 assert(display != (Display *) NULL);
4019 status=XGetWindowAttributes(display,window,&window_attributes);
4020 if ((status == False) || (window_attributes.map_state != IsViewable))
4021 return((Image *) NULL);
4022 /*
4023 Cropping rectangle is relative to root window.
4024 */
4025 root_window=XRootWindow(display,XDefaultScreen(display));
4026 (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
4027 &y_offset,&child);
cristybb503372010-05-27 20:51:26 +00004028 crop_info.x=(ssize_t) x_offset;
4029 crop_info.y=(ssize_t) y_offset;
4030 crop_info.width=(size_t) window_attributes.width;
4031 crop_info.height=(size_t) window_attributes.height;
cristy3ed852e2009-09-05 21:47:34 +00004032 if (borders != MagickFalse)
4033 {
4034 /*
4035 Include border in image.
4036 */
cristybb503372010-05-27 20:51:26 +00004037 crop_info.x-=(ssize_t) window_attributes.border_width;
4038 crop_info.y-=(ssize_t) window_attributes.border_width;
4039 crop_info.width+=(size_t) (window_attributes.border_width << 1);
4040 crop_info.height+=(size_t) (window_attributes.border_width << 1);
cristy3ed852e2009-09-05 21:47:34 +00004041 }
4042 /*
4043 Crop to root window.
4044 */
4045 if (crop_info.x < 0)
4046 {
4047 crop_info.width+=crop_info.x;
4048 crop_info.x=0;
4049 }
4050 if (crop_info.y < 0)
4051 {
4052 crop_info.height+=crop_info.y;
4053 crop_info.y=0;
4054 }
4055 display_width=XDisplayWidth(display,XDefaultScreen(display));
4056 if ((int) (crop_info.x+crop_info.width) > display_width)
cristybb503372010-05-27 20:51:26 +00004057 crop_info.width=(size_t) (display_width-crop_info.x);
cristy3ed852e2009-09-05 21:47:34 +00004058 display_height=XDisplayHeight(display,XDefaultScreen(display));
4059 if ((int) (crop_info.y+crop_info.height) > display_height)
cristybb503372010-05-27 20:51:26 +00004060 crop_info.height=(size_t) (display_height-crop_info.y);
cristy3ed852e2009-09-05 21:47:34 +00004061 /*
4062 Initialize window info attributes.
4063 */
4064 if (number_windows >= max_windows)
4065 {
4066 /*
4067 Allocate or resize window info buffer.
4068 */
4069 max_windows+=1024;
4070 if (window_info == (WindowInfo *) NULL)
4071 window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
4072 sizeof(*window_info));
4073 else
4074 window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
4075 max_windows,sizeof(*window_info));
4076 }
4077 if (window_info == (WindowInfo *) NULL)
4078 {
4079 ThrowXWindowFatalException(ResourceLimitError,
4080 "MemoryAllocationFailed","...");
4081 return((Image *) NULL);
4082 }
4083 id=number_windows++;
4084 window_info[id].window=window;
4085 window_info[id].visual=window_attributes.visual;
4086 window_info[id].colormap=window_attributes.colormap;
4087 window_info[id].bounds.x1=(short) crop_info.x;
4088 window_info[id].bounds.y1=(short) crop_info.y;
4089 window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
4090 window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
4091 crop_info.x-=x_offset;
4092 crop_info.y-=y_offset;
4093 window_info[id].crop_info=crop_info;
4094 if (level != 0)
4095 {
4096 unsigned int
4097 number_children;
4098
4099 Window
4100 *children;
4101
4102 /*
4103 Descend the window hierarchy.
4104 */
4105 status=XQueryTree(display,window,&root_window,&window_info[id].parent,
4106 &children,&number_children);
4107 for (i=0; i < id; i++)
4108 if ((window_info[i].window == window_info[id].parent) &&
4109 (window_info[i].visual == window_info[id].visual) &&
4110 (window_info[i].colormap == window_info[id].colormap))
4111 {
4112 if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
4113 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
4114 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
4115 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
4116 {
4117 /*
4118 Eliminate windows not circumscribed by their parent.
4119 */
4120 number_windows--;
4121 break;
4122 }
4123 }
4124 if ((status == True) && (number_children != 0))
4125 {
4126 for (i=0; i < (int) number_children; i++)
4127 (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
4128 (void) XFree((void *) children);
4129 }
4130 }
4131 if (level <= 1)
4132 {
cristyc57f6942010-11-12 01:47:39 +00004133 CacheView
4134 *composite_view;
4135
cristy3ed852e2009-09-05 21:47:34 +00004136 ColormapInfo
4137 *next;
4138
4139 ExceptionInfo
4140 *exception;
4141
4142 Image
4143 *composite_image,
4144 *image;
4145
4146 int
4147 y;
4148
4149 MagickBooleanType
4150 import;
4151
4152 register int
4153 j,
4154 x;
4155
4156 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00004157 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00004158
cristybb503372010-05-27 20:51:26 +00004159 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004160 pixel;
4161
4162 unsigned int
4163 number_colors;
4164
4165 XColor
4166 *colors;
4167
4168 XImage
4169 *ximage;
4170
4171 /*
4172 Get X image for each window in the list.
4173 */
4174 image=NewImageList();
4175 for (id=0; id < number_windows; id++)
4176 {
4177 /*
4178 Does target window intersect top level window?
4179 */
4180 import=
4181 ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
4182 (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
4183 (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
4184 (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
4185 MagickTrue : MagickFalse;
4186 /*
4187 Is target window contained by another window with the same colormap?
4188 */
4189 for (j=0; j < id; j++)
4190 if ((window_info[id].visual == window_info[j].visual) &&
4191 (window_info[id].colormap == window_info[j].colormap))
4192 {
4193 if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
4194 (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
4195 (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
4196 (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
4197 import=MagickFalse;
4198 }
4199 else
4200 if ((window_info[id].visual != window_info[j].visual) ||
4201 (window_info[id].colormap != window_info[j].colormap))
4202 {
4203 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
4204 (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
4205 (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
4206 (window_info[id].bounds.y1 < window_info[j].bounds.y2))
4207 import=MagickTrue;
4208 }
4209 if (import == MagickFalse)
4210 continue;
4211 /*
4212 Get X image.
4213 */
4214 ximage=XGetImage(display,window_info[id].window,(int)
4215 window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
4216 (unsigned int) window_info[id].crop_info.width,(unsigned int)
4217 window_info[id].crop_info.height,AllPlanes,ZPixmap);
4218 if (ximage == (XImage *) NULL)
4219 continue;
4220 /*
4221 Initialize window colormap.
4222 */
4223 number_colors=0;
4224 colors=(XColor *) NULL;
4225 if (window_info[id].colormap != (Colormap) NULL)
4226 {
4227 ColormapInfo
4228 *p;
4229
4230 /*
4231 Search colormap list for window colormap.
4232 */
4233 number_colors=(unsigned int) window_info[id].visual->map_entries;
4234 for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
4235 if (p->colormap == window_info[id].colormap)
4236 break;
4237 if (p == (ColormapInfo *) NULL)
4238 {
4239 /*
4240 Get the window colormap.
4241 */
4242 colors=(XColor *) AcquireQuantumMemory(number_colors,
4243 sizeof(*colors));
4244 if (colors == (XColor *) NULL)
4245 {
4246 XDestroyImage(ximage);
4247 return((Image *) NULL);
4248 }
4249 if ((window_info[id].visual->klass != DirectColor) &&
4250 (window_info[id].visual->klass != TrueColor))
4251 for (i=0; i < (int) number_colors; i++)
4252 {
cristybb503372010-05-27 20:51:26 +00004253 colors[i].pixel=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +00004254 colors[i].pad='\0';
4255 }
4256 else
4257 {
cristybb503372010-05-27 20:51:26 +00004258 size_t
cristy3ed852e2009-09-05 21:47:34 +00004259 blue,
4260 blue_bit,
4261 green,
4262 green_bit,
4263 red,
4264 red_bit;
4265
4266 /*
4267 DirectColor or TrueColor visual.
4268 */
4269 red=0;
4270 green=0;
4271 blue=0;
4272 red_bit=window_info[id].visual->red_mask &
4273 (~(window_info[id].visual->red_mask)+1);
4274 green_bit=window_info[id].visual->green_mask &
4275 (~(window_info[id].visual->green_mask)+1);
4276 blue_bit=window_info[id].visual->blue_mask &
4277 (~(window_info[id].visual->blue_mask)+1);
4278 for (i=0; i < (int) number_colors; i++)
4279 {
cristy8891f9c2010-06-04 23:32:17 +00004280 colors[i].pixel=(unsigned long) (red | green | blue);
cristy3ed852e2009-09-05 21:47:34 +00004281 colors[i].pad='\0';
4282 red+=red_bit;
4283 if (red > window_info[id].visual->red_mask)
4284 red=0;
4285 green+=green_bit;
4286 if (green > window_info[id].visual->green_mask)
4287 green=0;
4288 blue+=blue_bit;
4289 if (blue > window_info[id].visual->blue_mask)
4290 blue=0;
4291 }
4292 }
4293 (void) XQueryColors(display,window_info[id].colormap,colors,
4294 (int) number_colors);
4295 /*
4296 Append colormap to colormap list.
4297 */
cristy73bd4a52010-10-05 11:24:23 +00004298 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
cristy3ed852e2009-09-05 21:47:34 +00004299 if (p == (ColormapInfo *) NULL)
4300 return((Image *) NULL);
4301 p->colormap=window_info[id].colormap;
4302 p->colors=colors;
4303 p->next=colormap_info;
4304 colormap_info=p;
4305 }
4306 colors=p->colors;
4307 }
4308 /*
4309 Allocate image structure.
4310 */
4311 composite_image=AcquireImage((ImageInfo *) NULL);
4312 if (composite_image == (Image *) NULL)
4313 {
4314 XDestroyImage(ximage);
4315 return((Image *) NULL);
4316 }
4317 /*
4318 Convert X image to MIFF format.
4319 */
4320 if ((window_info[id].visual->klass != TrueColor) &&
4321 (window_info[id].visual->klass != DirectColor))
4322 composite_image->storage_class=PseudoClass;
cristybb503372010-05-27 20:51:26 +00004323 composite_image->columns=(size_t) ximage->width;
4324 composite_image->rows=(size_t) ximage->height;
cristy3ed852e2009-09-05 21:47:34 +00004325 exception=(&composite_image->exception);
cristyc57f6942010-11-12 01:47:39 +00004326 composite_view=AcquireCacheView(composite_image);
cristy3ed852e2009-09-05 21:47:34 +00004327 switch (composite_image->storage_class)
4328 {
4329 case DirectClass:
4330 default:
4331 {
cristybb503372010-05-27 20:51:26 +00004332 register size_t
cristy3ed852e2009-09-05 21:47:34 +00004333 color,
4334 index;
4335
cristybb503372010-05-27 20:51:26 +00004336 size_t
cristy3ed852e2009-09-05 21:47:34 +00004337 blue_mask,
4338 blue_shift,
4339 green_mask,
4340 green_shift,
4341 red_mask,
4342 red_shift;
4343
4344 /*
4345 Determine shift and mask for red, green, and blue.
4346 */
4347 red_mask=window_info[id].visual->red_mask;
4348 red_shift=0;
4349 while ((red_mask != 0) && ((red_mask & 0x01) == 0))
4350 {
4351 red_mask>>=1;
4352 red_shift++;
4353 }
4354 green_mask=window_info[id].visual->green_mask;
4355 green_shift=0;
4356 while ((green_mask != 0) && ((green_mask & 0x01) == 0))
4357 {
4358 green_mask>>=1;
4359 green_shift++;
4360 }
4361 blue_mask=window_info[id].visual->blue_mask;
4362 blue_shift=0;
4363 while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
4364 {
4365 blue_mask>>=1;
4366 blue_shift++;
4367 }
4368 /*
4369 Convert X image to DirectClass packets.
4370 */
4371 if ((number_colors != 0) &&
4372 (window_info[id].visual->klass == DirectColor))
4373 for (y=0; y < (int) composite_image->rows; y++)
4374 {
cristyc57f6942010-11-12 01:47:39 +00004375 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004376 composite_image->columns,1,exception);
4377 if (q == (PixelPacket *) NULL)
4378 break;
4379 for (x=0; x < (int) composite_image->columns; x++)
4380 {
4381 pixel=XGetPixel(ximage,x,y);
4382 index=(pixel >> red_shift) & red_mask;
cristyfba5a8b2011-05-03 17:12:12 +00004383 SetRedPixelComponent(q,ScaleShortToQuantum(
4384 colors[index].red));
cristy3ed852e2009-09-05 21:47:34 +00004385 index=(pixel >> green_shift) & green_mask;
cristyfba5a8b2011-05-03 17:12:12 +00004386 SetGreenPixelComponent(q,ScaleShortToQuantum(
4387 colors[index].green));
cristy3ed852e2009-09-05 21:47:34 +00004388 index=(pixel >> blue_shift) & blue_mask;
cristyfba5a8b2011-05-03 17:12:12 +00004389 SetBluePixelComponent(q,ScaleShortToQuantum(
4390 colors[index].blue));
cristy3ed852e2009-09-05 21:47:34 +00004391 q++;
4392 }
cristyc57f6942010-11-12 01:47:39 +00004393 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004394 break;
4395 }
4396 else
4397 for (y=0; y < (int) composite_image->rows; y++)
4398 {
cristyc57f6942010-11-12 01:47:39 +00004399 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
cristy3ed852e2009-09-05 21:47:34 +00004400 composite_image->columns,1,exception);
4401 if (q == (PixelPacket *) NULL)
4402 break;
4403 for (x=0; x < (int) composite_image->columns; x++)
4404 {
4405 pixel=XGetPixel(ximage,x,y);
4406 color=(pixel >> red_shift) & red_mask;
4407 color=(65535UL*color)/red_mask;
cristyfba5a8b2011-05-03 17:12:12 +00004408 SetRedPixelComponent(q,ScaleShortToQuantum((unsigned short)
4409 color));
cristy3ed852e2009-09-05 21:47:34 +00004410 color=(pixel >> green_shift) & green_mask;
4411 color=(65535UL*color)/green_mask;
cristyfba5a8b2011-05-03 17:12:12 +00004412 SetGreenPixelComponent(q,ScaleShortToQuantum((unsigned short)
4413 color));
cristy3ed852e2009-09-05 21:47:34 +00004414 color=(pixel >> blue_shift) & blue_mask;
4415 color=(65535UL*color)/blue_mask;
cristyfba5a8b2011-05-03 17:12:12 +00004416 SetBluePixelComponent(q,ScaleShortToQuantum((unsigned short)
4417 color));
cristy3ed852e2009-09-05 21:47:34 +00004418 q++;
4419 }
cristyc57f6942010-11-12 01:47:39 +00004420 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004421 break;
4422 }
4423 break;
4424 }
4425 case PseudoClass:
4426 {
4427 /*
4428 Create colormap.
4429 */
4430 if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
4431 {
4432 XDestroyImage(ximage);
4433 composite_image=DestroyImage(composite_image);
4434 return((Image *) NULL);
4435 }
4436 for (i=0; i < (int) composite_image->colors; i++)
4437 {
4438 composite_image->colormap[colors[i].pixel].red=
4439 ScaleShortToQuantum(colors[i].red);
4440 composite_image->colormap[colors[i].pixel].green=
4441 ScaleShortToQuantum(colors[i].green);
4442 composite_image->colormap[colors[i].pixel].blue=
4443 ScaleShortToQuantum(colors[i].blue);
4444 }
4445 /*
4446 Convert X image to PseudoClass packets.
4447 */
4448 for (y=0; y < (int) composite_image->rows; y++)
4449 {
cristyc57f6942010-11-12 01:47:39 +00004450 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
4451 composite_image->columns,1,exception);
cristy3ed852e2009-09-05 21:47:34 +00004452 if (q == (PixelPacket *) NULL)
4453 break;
cristyc57f6942010-11-12 01:47:39 +00004454 indexes=GetCacheViewAuthenticIndexQueue(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004455 for (x=0; x < (int) composite_image->columns; x++)
4456 {
4457 index=(IndexPacket) XGetPixel(ximage,x,y);
cristyfba5a8b2011-05-03 17:12:12 +00004458 SetIndexPixelComponent(indexes+x,index);
cristybb503372010-05-27 20:51:26 +00004459 *q++=composite_image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +00004460 }
cristyc57f6942010-11-12 01:47:39 +00004461 if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00004462 break;
4463 }
4464 break;
4465 }
4466 }
cristyc57f6942010-11-12 01:47:39 +00004467 composite_view=DestroyCacheView(composite_view);
cristy3ed852e2009-09-05 21:47:34 +00004468 XDestroyImage(ximage);
4469 if (image == (Image *) NULL)
4470 {
4471 image=composite_image;
4472 continue;
4473 }
4474 /*
4475 Composite any children in back-to-front order.
4476 */
4477 (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
4478 &x_offset,&y_offset,&child);
4479 x_offset-=(int) crop_info.x;
4480 if (x_offset < 0)
4481 x_offset=0;
4482 y_offset-=(int) crop_info.y;
4483 if (y_offset < 0)
4484 y_offset=0;
cristyc57f6942010-11-12 01:47:39 +00004485 (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
4486 x_offset,(ssize_t) y_offset);
cristy3ed852e2009-09-05 21:47:34 +00004487 }
4488 /*
4489 Relinquish resources.
4490 */
4491 while (colormap_info != (ColormapInfo *) NULL)
4492 {
4493 next=colormap_info->next;
4494 colormap_info->colors=(XColor *)
4495 RelinquishMagickMemory(colormap_info->colors);
4496 colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
4497 colormap_info=next;
4498 }
4499 /*
4500 Relinquish resources and restore initial state.
4501 */
4502 window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
4503 max_windows=0;
4504 number_windows=0;
4505 colormap_info=(ColormapInfo *) NULL;
4506 return(image);
4507 }
4508 return((Image *) NULL);
4509}
4510
4511/*
4512%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4513% %
4514% %
4515% %
4516% X G e t W i n d o w I n f o %
4517% %
4518% %
4519% %
4520%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4521%
4522% XGetWindowInfo() initializes the XWindowInfo structure.
4523%
4524% The format of the XGetWindowInfo method is:
4525%
4526% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4527% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4528% XResourceInfo *resource_info,XWindowInfo *window)
4529% resource_info,window)
4530%
4531% A description of each parameter follows:
4532%
4533% o display: Specifies a connection to an X server; returned from
4534% XOpenDisplay.
4535%
4536% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
4537% returned from XGetVisualInfo.
4538%
4539% o map_info: If map_type is specified, this structure is initialized
4540% with info from the Standard Colormap.
4541%
4542% o pixel: Specifies a pointer to a XPixelInfo structure.
4543%
4544% o font_info: Specifies a pointer to a XFontStruct structure.
4545%
4546% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4547%
4548*/
4549MagickExport void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
4550 XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
4551 XResourceInfo *resource_info,XWindowInfo *window)
4552{
4553 /*
4554 Initialize window info.
4555 */
4556 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4557 assert(display != (Display *) NULL);
4558 assert(visual_info != (XVisualInfo *) NULL);
4559 assert(map_info != (XStandardColormap *) NULL);
4560 assert(pixel != (XPixelInfo *) NULL);
4561 assert(resource_info != (XResourceInfo *) NULL);
4562 assert(window != (XWindowInfo *) NULL);
4563 if (window->id != (Window) NULL)
4564 {
4565 if (window->cursor != (Cursor) NULL)
4566 (void) XFreeCursor(display,window->cursor);
4567 if (window->busy_cursor != (Cursor) NULL)
4568 (void) XFreeCursor(display,window->busy_cursor);
4569 if (window->highlight_stipple != (Pixmap) NULL)
4570 (void) XFreePixmap(display,window->highlight_stipple);
4571 if (window->shadow_stipple != (Pixmap) NULL)
4572 (void) XFreePixmap(display,window->shadow_stipple);
4573 if (window->name == (char *) NULL)
4574 window->name=AcquireString("");
4575 if (window->icon_name == (char *) NULL)
4576 window->icon_name=AcquireString("");
4577 }
4578 else
4579 {
4580 /*
4581 Initialize these attributes just once.
4582 */
4583 window->id=(Window) NULL;
4584 if (window->name == (char *) NULL)
4585 window->name=AcquireString("");
4586 if (window->icon_name == (char *) NULL)
4587 window->icon_name=AcquireString("");
4588 window->x=XDisplayWidth(display,visual_info->screen) >> 1;
4589 window->y=XDisplayWidth(display,visual_info->screen) >> 1;
4590 window->ximage=(XImage *) NULL;
4591 window->matte_image=(XImage *) NULL;
4592 window->pixmap=(Pixmap) NULL;
4593 window->matte_pixmap=(Pixmap) NULL;
4594 window->mapped=MagickFalse;
4595 window->stasis=MagickFalse;
4596 window->shared_memory=MagickTrue;
4597 window->segment_info=(void *) NULL;
4598#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
4599 {
4600 XShmSegmentInfo
4601 *segment_info;
4602
4603 if (window->segment_info == (void *) NULL)
4604 window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
4605 segment_info=(XShmSegmentInfo *) window->segment_info;
4606 segment_info[0].shmid=(-1);
4607 segment_info[0].shmaddr=(char *) NULL;
4608 segment_info[1].shmid=(-1);
4609 segment_info[1].shmaddr=(char *) NULL;
4610 }
4611#endif
4612 }
4613 /*
4614 Initialize these attributes every time function is called.
4615 */
4616 window->screen=visual_info->screen;
4617 window->root=XRootWindow(display,visual_info->screen);
4618 window->visual=visual_info->visual;
4619 window->storage_class=(unsigned int) visual_info->klass;
4620 window->depth=(unsigned int) visual_info->depth;
4621 window->visual_info=visual_info;
4622 window->map_info=map_info;
4623 window->pixel_info=pixel;
4624 window->font_info=font_info;
4625 window->cursor=XCreateFontCursor(display,XC_left_ptr);
4626 window->busy_cursor=XCreateFontCursor(display,XC_watch);
4627 window->geometry=(char *) NULL;
4628 window->icon_geometry=(char *) NULL;
4629 if (resource_info->icon_geometry != (char *) NULL)
4630 (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
4631 window->crop_geometry=(char *) NULL;
cristybb503372010-05-27 20:51:26 +00004632 window->flags=(size_t) PSize;
cristy3ed852e2009-09-05 21:47:34 +00004633 window->width=1;
4634 window->height=1;
4635 window->min_width=1;
4636 window->min_height=1;
4637 window->width_inc=1;
4638 window->height_inc=1;
4639 window->border_width=resource_info->border_width;
4640 window->annotate_context=pixel->annotate_context;
4641 window->highlight_context=pixel->highlight_context;
4642 window->widget_context=pixel->widget_context;
4643 window->shadow_stipple=(Pixmap) NULL;
4644 window->highlight_stipple=(Pixmap) NULL;
4645 window->use_pixmap=MagickTrue;
4646 window->immutable=MagickFalse;
4647 window->shape=MagickFalse;
4648 window->data=0;
cristyc57f6942010-11-12 01:47:39 +00004649 window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
cristy3ed852e2009-09-05 21:47:34 +00004650 CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
4651 CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
4652 window->attributes.background_pixel=pixel->background_color.pixel;
4653 window->attributes.background_pixmap=(Pixmap) NULL;
4654 window->attributes.bit_gravity=ForgetGravity;
4655 window->attributes.backing_store=WhenMapped;
4656 window->attributes.save_under=MagickTrue;
4657 window->attributes.border_pixel=pixel->border_color.pixel;
4658 window->attributes.colormap=map_info->colormap;
4659 window->attributes.cursor=window->cursor;
4660 window->attributes.do_not_propagate_mask=NoEventMask;
4661 window->attributes.event_mask=NoEventMask;
4662 window->attributes.override_redirect=MagickFalse;
4663 window->attributes.win_gravity=NorthWestGravity;
4664 window->orphan=MagickFalse;
4665}
4666
4667/*
4668%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4669% %
4670% %
4671% %
4672% X H i g h l i g h t E l l i p s e %
4673% %
4674% %
4675% %
4676%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4677%
4678% XHighlightEllipse() puts a border on the X server around a region defined by
4679% highlight_info.
4680%
4681% The format of the XHighlightEllipse method is:
4682%
4683% void XHighlightEllipse(Display *display,Window window,
4684% GC annotate_context,const RectangleInfo *highlight_info)
4685%
4686% A description of each parameter follows:
4687%
4688% o display: Specifies a connection to an X server; returned from
4689% XOpenDisplay.
4690%
4691% o window: Specifies a pointer to a Window structure.
4692%
4693% o annotate_context: Specifies a pointer to a GC structure.
4694%
4695% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4696% contains the extents of any highlighting rectangle.
4697%
4698*/
4699MagickExport void XHighlightEllipse(Display *display,Window window,
4700 GC annotate_context,const RectangleInfo *highlight_info)
4701{
4702 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4703 assert(display != (Display *) NULL);
4704 assert(window != (Window) NULL);
4705 assert(annotate_context != (GC) NULL);
4706 assert(highlight_info != (RectangleInfo *) NULL);
4707 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4708 return;
4709 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
4710 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4711 (unsigned int) highlight_info->height-1,0,360*64);
4712 (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
4713 (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4714 (unsigned int) highlight_info->height-3,0,360*64);
4715}
4716
4717/*
4718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4719% %
4720% %
4721% %
4722% X H i g h l i g h t L i n e %
4723% %
4724% %
4725% %
4726%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4727%
4728% XHighlightLine() puts a border on the X server around a region defined by
4729% highlight_info.
4730%
4731% The format of the XHighlightLine method is:
4732%
4733% void XHighlightLine(Display *display,Window window,GC annotate_context,
4734% const XSegment *highlight_info)
4735%
4736% A description of each parameter follows:
4737%
4738% o display: Specifies a connection to an X server; returned from
4739% XOpenDisplay.
4740%
4741% o window: Specifies a pointer to a Window structure.
4742%
4743% o annotate_context: Specifies a pointer to a GC structure.
4744%
4745% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4746% contains the extents of any highlighting rectangle.
4747%
4748*/
4749MagickExport void XHighlightLine(Display *display,Window window,
4750 GC annotate_context,const XSegment *highlight_info)
4751{
4752 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4753 assert(display != (Display *) NULL);
4754 assert(window != (Window) NULL);
4755 assert(annotate_context != (GC) NULL);
4756 assert(highlight_info != (XSegment *) NULL);
4757 (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
4758 highlight_info->y1,highlight_info->x2,highlight_info->y2);
4759}
4760
4761/*
4762%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4763% %
4764% %
4765% %
4766% X H i g h l i g h t R e c t a n g l e %
4767% %
4768% %
4769% %
4770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4771%
4772% XHighlightRectangle() puts a border on the X server around a region defined
4773% by highlight_info.
4774%
4775% The format of the XHighlightRectangle method is:
4776%
4777% void XHighlightRectangle(Display *display,Window window,
4778% GC annotate_context,const RectangleInfo *highlight_info)
4779%
4780% A description of each parameter follows:
4781%
4782% o display: Specifies a connection to an X server; returned from
4783% XOpenDisplay.
4784%
4785% o window: Specifies a pointer to a Window structure.
4786%
4787% o annotate_context: Specifies a pointer to a GC structure.
4788%
4789% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
4790% contains the extents of any highlighting rectangle.
4791%
4792*/
4793MagickExport void XHighlightRectangle(Display *display,Window window,
4794 GC annotate_context,const RectangleInfo *highlight_info)
4795{
4796 assert(display != (Display *) NULL);
4797 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
4798 assert(window != (Window) NULL);
4799 assert(annotate_context != (GC) NULL);
4800 assert(highlight_info != (RectangleInfo *) NULL);
4801 if ((highlight_info->width < 4) || (highlight_info->height < 4))
4802 return;
4803 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
4804 (int) highlight_info->y,(unsigned int) highlight_info->width-1,
4805 (unsigned int) highlight_info->height-1);
4806 (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
4807 1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
4808 (unsigned int) highlight_info->height-3);
4809}
4810
4811/*
4812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4813% %
4814% %
4815% %
4816% X I m p o r t I m a g e %
4817% %
4818% %
4819% %
4820%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4821%
4822% XImportImage() reads an image from an X window.
4823%
4824% The format of the XImportImage method is:
4825%
4826% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
4827%
4828% A description of each parameter follows:
4829%
4830% o image_info: the image info.
4831%
4832% o ximage_info: Specifies a pointer to an XImportInfo structure.
4833%
4834*/
4835MagickExport Image *XImportImage(const ImageInfo *image_info,
4836 XImportInfo *ximage_info)
4837{
4838 Colormap
4839 *colormaps;
4840
4841 Display
4842 *display;
4843
4844 Image
4845 *image;
4846
4847 int
4848 number_colormaps,
4849 number_windows,
4850 x;
4851
4852 RectangleInfo
4853 crop_info;
4854
4855 Status
4856 status;
4857
4858 Window
4859 *children,
4860 client,
4861 prior_target,
4862 root,
4863 target;
4864
4865 XTextProperty
4866 window_name;
4867
4868 /*
4869 Open X server connection.
4870 */
4871 assert(image_info != (const ImageInfo *) NULL);
4872 assert(image_info->signature == MagickSignature);
4873 if (image_info->debug != MagickFalse)
4874 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
4875 image_info->filename);
4876 assert(ximage_info != (XImportInfo *) NULL);
4877 display=XOpenDisplay(image_info->server_name);
4878 if (display == (Display *) NULL)
4879 {
4880 ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
4881 XDisplayName(image_info->server_name));
4882 return((Image *) NULL);
4883 }
4884 /*
4885 Set our forgiving exception handler.
4886 */
4887 (void) XSetErrorHandler(XError);
4888 /*
4889 Select target window.
4890 */
4891 crop_info.x=0;
4892 crop_info.y=0;
4893 crop_info.width=0;
4894 crop_info.height=0;
4895 root=XRootWindow(display,XDefaultScreen(display));
4896 target=(Window) NULL;
4897 if ((image_info->filename != (char *) NULL) &&
4898 (*image_info->filename != '\0'))
4899 {
4900 if (LocaleCompare(image_info->filename,"root") == 0)
4901 target=root;
4902 else
4903 {
4904 /*
4905 Select window by ID or name.
4906 */
4907 if (isdigit((unsigned char) *image_info->filename) != 0)
4908 target=XWindowByID(display,root,(Window)
4909 strtol(image_info->filename,(char **) NULL,0));
4910 if (target == (Window) NULL)
4911 target=XWindowByName(display,root,image_info->filename);
4912 if (target == (Window) NULL)
4913 ThrowXWindowFatalException(XServerError,
4914 "NoWindowWithSpecifiedIDExists",image_info->filename);
4915 }
4916 }
4917 /*
4918 If target window is not defined, interactively select one.
4919 */
4920 prior_target=target;
4921 if (target == (Window) NULL)
4922 target=XSelectWindow(display,&crop_info);
4923 if (target == (Window) NULL)
4924 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
4925 image_info->filename);
4926 client=target; /* obsolete */
4927 if (target != root)
4928 {
4929 unsigned int
4930 d;
4931
4932 status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
4933 if (status != False)
4934 {
4935 for ( ; ; )
4936 {
4937 Window
4938 parent;
4939
4940 /*
4941 Find window manager frame.
4942 */
4943 status=XQueryTree(display,target,&root,&parent,&children,&d);
4944 if ((status != False) && (children != (Window *) NULL))
4945 (void) XFree((char *) children);
4946 if ((status == False) || (parent == (Window) NULL) ||
4947 (parent == root))
4948 break;
4949 target=parent;
4950 }
4951 /*
4952 Get client window.
4953 */
4954 client=XClientWindow(display,target);
4955 if (ximage_info->frame == MagickFalse)
4956 target=client;
4957 if ((ximage_info->frame == MagickFalse) &&
4958 (prior_target != MagickFalse))
4959 target=prior_target;
4960 XDelay(display,SuspendTime << 4);
4961 }
4962 }
4963 if (ximage_info->screen)
4964 {
4965 int
4966 y;
4967
4968 Window
4969 child;
4970
4971 XWindowAttributes
4972 window_attributes;
4973
4974 /*
4975 Obtain window image directly from screen.
4976 */
4977 status=XGetWindowAttributes(display,target,&window_attributes);
4978 if (status == False)
4979 {
4980 ThrowXWindowFatalException(XServerError,
4981 "UnableToReadXWindowAttributes",image_info->filename);
4982 (void) XCloseDisplay(display);
4983 return((Image *) NULL);
4984 }
4985 (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
cristyc57f6942010-11-12 01:47:39 +00004986 crop_info.x=(ssize_t) x;
4987 crop_info.y=(ssize_t) y;
cristybb503372010-05-27 20:51:26 +00004988 crop_info.width=(size_t) window_attributes.width;
4989 crop_info.height=(size_t) window_attributes.height;
cristy553743c2010-03-03 15:04:17 +00004990 if (ximage_info->borders != 0)
cristy3ed852e2009-09-05 21:47:34 +00004991 {
4992 /*
4993 Include border in image.
4994 */
4995 crop_info.x-=window_attributes.border_width;
4996 crop_info.y-=window_attributes.border_width;
4997 crop_info.width+=window_attributes.border_width << 1;
4998 crop_info.height+=window_attributes.border_width << 1;
4999 }
5000 target=root;
5001 }
5002 /*
5003 If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
5004 */
5005 number_windows=0;
5006 status=XGetWMColormapWindows(display,target,&children,&number_windows);
5007 if ((status == True) && (number_windows > 0))
5008 {
5009 ximage_info->descend=MagickTrue;
5010 (void) XFree ((char *) children);
5011 }
5012 colormaps=XListInstalledColormaps(display,target,&number_colormaps);
5013 if (number_colormaps > 0)
5014 {
5015 if (number_colormaps > 1)
5016 ximage_info->descend=MagickTrue;
5017 (void) XFree((char *) colormaps);
5018 }
5019 /*
5020 Alert the user not to alter the screen.
5021 */
5022 if (ximage_info->silent == MagickFalse)
5023 (void) XBell(display,0);
5024 /*
5025 Get image by window id.
5026 */
5027 (void) XGrabServer(display);
5028 image=XGetWindowImage(display,target,ximage_info->borders,
5029 ximage_info->descend ? 1U : 0U);
5030 (void) XUngrabServer(display);
5031 if (image == (Image *) NULL)
5032 ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
5033 image_info->filename)
5034 else
5035 {
5036 (void) CopyMagickString(image->filename,image_info->filename,
5037 MaxTextExtent);
5038 if ((crop_info.width != 0) && (crop_info.height != 0))
5039 {
5040 Image
5041 *clone_image,
5042 *crop_image;
5043
5044 /*
5045 Crop image as defined by the cropping rectangle.
5046 */
5047 clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
5048 if (clone_image != (Image *) NULL)
5049 {
5050 crop_image=CropImage(clone_image,&crop_info,&image->exception);
5051 if (crop_image != (Image *) NULL)
5052 {
5053 image=DestroyImage(image);
5054 image=crop_image;
5055 }
5056 }
5057 }
5058 status=XGetWMName(display,target,&window_name);
5059 if (status == True)
5060 {
5061 if ((image_info->filename != (char *) NULL) &&
5062 (*image_info->filename == '\0'))
5063 (void) CopyMagickString(image->filename,(char *) window_name.value,
5064 (size_t) window_name.nitems+1);
5065 (void) XFree((void *) window_name.value);
5066 }
5067 }
5068 if (ximage_info->silent == MagickFalse)
5069 {
5070 /*
5071 Alert the user we're done.
5072 */
5073 (void) XBell(display,0);
5074 (void) XBell(display,0);
5075 }
5076 (void) XCloseDisplay(display);
5077 return(image);
5078}
5079
5080/*
5081%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5082% %
5083% %
5084% %
5085% X I n i t i a l i z e W i n d o w s %
5086% %
5087% %
5088% %
5089%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5090%
5091% XInitializeWindows() initializes the XWindows structure.
5092%
5093% The format of the XInitializeWindows method is:
5094%
5095% XWindows *XInitializeWindows(Display *display,
5096% XResourceInfo *resource_info)
5097%
5098% A description of each parameter follows:
5099%
5100% o windows: XInitializeWindows returns a pointer to a XWindows structure.
5101%
5102% o display: Specifies a connection to an X server; returned from
5103% XOpenDisplay.
5104%
5105% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5106%
5107*/
5108MagickExport XWindows *XInitializeWindows(Display *display,
5109 XResourceInfo *resource_info)
5110{
5111 Window
5112 root_window;
5113
5114 XWindows
5115 *windows;
5116
5117 /*
5118 Allocate windows structure.
5119 */
cristy73bd4a52010-10-05 11:24:23 +00005120 windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
cristy3ed852e2009-09-05 21:47:34 +00005121 if (windows == (XWindows *) NULL)
5122 {
5123 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5124 "...");
5125 return((XWindows *) NULL);
5126 }
5127 (void) ResetMagickMemory(windows,0,sizeof(*windows));
5128 windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
5129 sizeof(*windows->pixel_info));
5130 windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
5131 sizeof(*windows->icon_pixel));
5132 windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
5133 sizeof(*windows->icon_resources));
5134 if ((windows->pixel_info == (XPixelInfo *) NULL) ||
5135 (windows->icon_pixel == (XPixelInfo *) NULL) ||
5136 (windows->icon_resources == (XResourceInfo *) NULL))
5137 {
5138 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
5139 "...");
5140 return((XWindows *) NULL);
5141 }
5142 /*
5143 Initialize windows structure.
5144 */
5145 windows->display=display;
5146 windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
5147 windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
5148 windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
5149 windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
5150 windows->im_remote_command=
5151 XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
5152 windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
5153 windows->im_update_colormap=
5154 XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
5155 windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
5156 windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
5157 windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
5158 windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
5159 windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
cristy0157aea2010-04-24 21:12:18 +00005160#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00005161 (void) XSynchronize(display,IsWindows95());
5162#endif
5163 if (IsEventLogging())
5164 {
5165 (void) XSynchronize(display,MagickTrue);
5166 (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
cristybb503372010-05-27 20:51:26 +00005167 GetMagickVersion((size_t *) NULL));
cristy3ed852e2009-09-05 21:47:34 +00005168 (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
5169 (void) LogMagickEvent(X11Event,GetMagickModule(),
5170 " Window Manager: 0x%lx",windows->wm_protocols);
5171 (void) LogMagickEvent(X11Event,GetMagickModule(),
5172 " delete window: 0x%lx",windows->wm_delete_window);
5173 (void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
5174 windows->wm_take_focus);
5175 (void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
5176 windows->im_protocols);
5177 (void) LogMagickEvent(X11Event,GetMagickModule(),
5178 " remote command: 0x%lx",windows->im_remote_command);
5179 (void) LogMagickEvent(X11Event,GetMagickModule(),
5180 " update widget: 0x%lx",windows->im_update_widget);
5181 (void) LogMagickEvent(X11Event,GetMagickModule(),
5182 " update colormap: 0x%lx",windows->im_update_colormap);
5183 (void) LogMagickEvent(X11Event,GetMagickModule(),
5184 " former image: 0x%lx",windows->im_former_image);
5185 (void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
5186 windows->im_next_image);
5187 (void) LogMagickEvent(X11Event,GetMagickModule(),
5188 " retain colors: 0x%lx",windows->im_retain_colors);
5189 (void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
5190 windows->im_exit);
5191 (void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
5192 windows->dnd_protocols);
5193 }
5194 /*
5195 Allocate standard colormap.
5196 */
5197 windows->map_info=XAllocStandardColormap();
5198 windows->icon_map=XAllocStandardColormap();
5199 if ((windows->map_info == (XStandardColormap *) NULL) ||
5200 (windows->icon_map == (XStandardColormap *) NULL))
5201 ThrowXWindowFatalException(ResourceLimitFatalError,
5202 "MemoryAllocationFailed","...");
5203 windows->map_info->colormap=(Colormap) NULL;
5204 windows->icon_map->colormap=(Colormap) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005205 windows->pixel_info->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005206 windows->pixel_info->annotate_context=(GC) NULL;
5207 windows->pixel_info->highlight_context=(GC) NULL;
5208 windows->pixel_info->widget_context=(GC) NULL;
5209 windows->font_info=(XFontStruct *) NULL;
5210 windows->icon_pixel->annotate_context=(GC) NULL;
cristyf2faecf2010-05-28 19:19:36 +00005211 windows->icon_pixel->pixels=(unsigned long *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00005212 /*
5213 Allocate visual.
5214 */
5215 *windows->icon_resources=(*resource_info);
5216 windows->icon_resources->visual_type=(char *) "default";
5217 windows->icon_resources->colormap=SharedColormap;
5218 windows->visual_info=
5219 XBestVisualInfo(display,windows->map_info,resource_info);
5220 windows->icon_visual=
5221 XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
5222 if ((windows->visual_info == (XVisualInfo *) NULL) ||
5223 (windows->icon_visual == (XVisualInfo *) NULL))
5224 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
5225 resource_info->visual_type);
5226 if (IsEventLogging())
5227 {
5228 (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
5229 (void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
5230 windows->visual_info->visualid);
5231 (void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
5232 XVisualClassName(windows->visual_info->klass));
5233 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
5234 windows->visual_info->depth);
5235 (void) LogMagickEvent(X11Event,GetMagickModule(),
5236 " size of colormap: %d entries",windows->visual_info->colormap_size);
5237 (void) LogMagickEvent(X11Event,GetMagickModule(),
5238 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",
5239 windows->visual_info->red_mask,windows->visual_info->green_mask,
5240 windows->visual_info->blue_mask);
5241 (void) LogMagickEvent(X11Event,GetMagickModule(),
5242 " significant bits in color: %d bits",
5243 windows->visual_info->bits_per_rgb);
5244 }
5245 /*
5246 Allocate class and manager hints.
5247 */
5248 windows->class_hints=XAllocClassHint();
5249 windows->manager_hints=XAllocWMHints();
5250 if ((windows->class_hints == (XClassHint *) NULL) ||
5251 (windows->manager_hints == (XWMHints *) NULL))
5252 ThrowXWindowFatalException(ResourceLimitFatalError,
5253 "MemoryAllocationFailed","...");
5254 /*
5255 Determine group leader if we have one.
5256 */
5257 root_window=XRootWindow(display,windows->visual_info->screen);
5258 windows->group_leader.id=(Window) NULL;
5259 if (resource_info->window_group != (char *) NULL)
5260 {
5261 if (isdigit((unsigned char) *resource_info->window_group) != 0)
5262 windows->group_leader.id=XWindowByID(display,root_window,(Window)
5263 strtol((char *) resource_info->window_group,(char **) NULL,0));
5264 if (windows->group_leader.id == (Window) NULL)
5265 windows->group_leader.id=
5266 XWindowByName(display,root_window,resource_info->window_group);
5267 }
5268 return(windows);
5269}
5270
5271/*
5272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5273% %
5274% %
5275% %
5276% X M a k e C u r s o r %
5277% %
5278% %
5279% %
5280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5281%
5282% XMakeCursor() creates a crosshairs X11 cursor.
5283%
5284% The format of the XMakeCursor method is:
5285%
5286% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
5287% char *background_color,char *foreground_color)
5288%
5289% A description of each parameter follows:
5290%
5291% o display: Specifies a connection to an X server; returned from
5292% XOpenDisplay.
5293%
5294% o window: Specifies the ID of the window for which the cursor is
5295% assigned.
5296%
5297% o colormap: Specifies the ID of the colormap from which the background
5298% and foreground color will be retrieved.
5299%
5300% o background_color: Specifies the color to use for the cursor background.
5301%
5302% o foreground_color: Specifies the color to use for the cursor foreground.
5303%
5304*/
5305MagickExport Cursor XMakeCursor(Display *display,Window window,
5306 Colormap colormap,char *background_color,char *foreground_color)
5307{
5308#define scope_height 17
5309#define scope_x_hot 8
5310#define scope_y_hot 8
5311#define scope_width 17
5312
5313 static const unsigned char
5314 scope_bits[] =
5315 {
5316 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5317 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
5318 0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
5319 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
5320 0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
5321 },
5322 scope_mask_bits[] =
5323 {
5324 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5325 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
5326 0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
5327 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
5328 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
5329 };
5330
5331 Cursor
5332 cursor;
5333
5334 Pixmap
5335 mask,
5336 source;
5337
5338 XColor
5339 background,
5340 foreground;
5341
5342 assert(display != (Display *) NULL);
5343 assert(window != (Window) NULL);
5344 assert(colormap != (Colormap) NULL);
5345 assert(background_color != (char *) NULL);
5346 assert(foreground_color != (char *) NULL);
5347 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
5348 source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
5349 scope_height);
5350 mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
5351 scope_width,scope_height);
5352 if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
5353 {
5354 ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
5355 return((Cursor) NULL);
5356 }
5357 (void) XParseColor(display,colormap,background_color,&background);
5358 (void) XParseColor(display,colormap,foreground_color,&foreground);
5359 cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
5360 scope_x_hot,scope_y_hot);
5361 (void) XFreePixmap(display,source);
5362 (void) XFreePixmap(display,mask);
5363 return(cursor);
5364}
5365
5366/*
5367%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5368% %
5369% %
5370% %
5371% X M a k e I m a g e %
5372% %
5373% %
5374% %
5375%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5376%
5377% XMakeImage() creates an X11 image. If the image size differs from the X11
5378% image size, the image is first resized.
5379%
5380% The format of the XMakeImage method is:
5381%
5382% MagickBooleanType XMakeImage(Display *display,
5383% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5384% unsigned int width,unsigned int height)
5385%
5386% A description of each parameter follows:
5387%
5388% o display: Specifies a connection to an X server; returned from
5389% XOpenDisplay.
5390%
5391% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5392%
5393% o window: Specifies a pointer to a XWindowInfo structure.
5394%
5395% o image: the image.
5396%
5397% o width: Specifies the width in pixels of the rectangular area to
5398% display.
5399%
5400% o height: Specifies the height in pixels of the rectangular area to
5401% display.
5402%
5403*/
5404MagickExport MagickBooleanType XMakeImage(Display *display,
5405 const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
5406 unsigned int width,unsigned int height)
5407{
5408#define CheckOverflowException(length,width,height) \
5409 (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
5410
5411 int
5412 depth,
5413 format;
5414
5415 size_t
5416 length;
5417
5418 XImage
5419 *matte_image,
5420 *ximage;
5421
5422 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
5423 assert(display != (Display *) NULL);
5424 assert(resource_info != (XResourceInfo *) NULL);
5425 assert(window != (XWindowInfo *) NULL);
5426 assert(width != 0);
5427 assert(height != 0);
5428 if ((window->width == 0) || (window->height == 0))
5429 return(MagickFalse);
5430 /*
5431 Apply user transforms to the image.
5432 */
5433 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
5434 (void) XFlush(display);
5435 depth=(int) window->depth;
5436 if (window->destroy)
5437 window->image=DestroyImage(window->image);
5438 window->image=image;
5439 window->destroy=MagickFalse;
5440 if (window->image != (Image *) NULL)
5441 {
5442 if (window->crop_geometry != (char *) NULL)
5443 {
5444 Image
5445 *crop_image;
5446
5447 RectangleInfo
5448 crop_info;
5449
5450 /*
5451 Crop image.
5452 */
5453 window->image->page.x=0;
5454 window->image->page.y=0;
5455 (void) ParsePageGeometry(window->image,window->crop_geometry,
5456 &crop_info,&image->exception);
5457 crop_image=CropImage(window->image,&crop_info,&image->exception);
5458 if (crop_image != (Image *) NULL)
5459 {
5460 if (window->image != image)
5461 window->image=DestroyImage(window->image);
5462 window->image=crop_image;
5463 window->destroy=MagickTrue;
5464 }
5465 }
5466 if ((width != (unsigned int) window->image->columns) ||
5467 (height != (unsigned int) window->image->rows))
5468 {
5469 Image
5470 *resize_image;
5471
5472 /*
5473 Resize image.
5474 */
5475 resize_image=NewImageList();
5476 if (window->pixel_info->colors != 0)
5477 resize_image=SampleImage(window->image,width,height,
5478 &image->exception);
5479 else
5480 resize_image=ThumbnailImage(window->image,width,height,
5481 &image->exception);
5482 if (resize_image != (Image *) NULL)
5483 {
5484 if (window->image != image)
5485 window->image=DestroyImage(window->image);
5486 window->image=resize_image;
5487 window->destroy=MagickTrue;
5488 }
5489 }
5490 width=(unsigned int) window->image->columns;
cristybb503372010-05-27 20:51:26 +00005491 assert((size_t) width == window->image->columns);
cristy3ed852e2009-09-05 21:47:34 +00005492 height=(unsigned int) window->image->rows;
cristybb503372010-05-27 20:51:26 +00005493 assert((size_t) height == window->image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005494 }
5495 /*
5496 Create X image.
5497 */
5498 ximage=(XImage *) NULL;
5499 format=(depth == 1) ? XYBitmap : ZPixmap;
5500#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5501 if (window->shared_memory != MagickFalse)
5502 {
5503 XShmSegmentInfo
5504 *segment_info;
5505
5506 segment_info=(XShmSegmentInfo *) window->segment_info;
5507 segment_info[1].shmid=(-1);
5508 segment_info[1].shmaddr=(char *) NULL;
5509 ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
5510 (char *) NULL,&segment_info[1],width,height);
5511 if (ximage == (XImage *) NULL)
5512 window->shared_memory=MagickFalse;
5513 length=(size_t) ximage->bytes_per_line*ximage->height;
5514 if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
5515 window->shared_memory=MagickFalse;
5516 if (window->shared_memory != MagickFalse)
5517 segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
5518 if (window->shared_memory != MagickFalse)
5519 segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
5520 if (segment_info[1].shmid < 0)
5521 window->shared_memory=MagickFalse;
5522 if (window->shared_memory != MagickFalse)
5523 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5524 else
5525 {
5526 if (ximage != (XImage *) NULL)
5527 XDestroyImage(ximage);
5528 ximage=(XImage *) NULL;
5529 if (segment_info[1].shmaddr)
5530 {
5531 (void) shmdt(segment_info[1].shmaddr);
5532 segment_info[1].shmaddr=(char *) NULL;
5533 }
5534 if (segment_info[1].shmid >= 0)
5535 {
5536 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5537 segment_info[1].shmid=(-1);
5538 }
5539 }
5540 }
5541#endif
5542 /*
5543 Allocate X image pixel data.
5544 */
5545#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5546 if (window->shared_memory)
5547 {
5548 Status
5549 status;
5550
5551 XShmSegmentInfo
5552 *segment_info;
5553
5554 (void) XSync(display,MagickFalse);
5555 xerror_alert=MagickFalse;
5556 segment_info=(XShmSegmentInfo *) window->segment_info;
5557 ximage->data=segment_info[1].shmaddr;
5558 segment_info[1].readOnly=MagickFalse;
5559 status=XShmAttach(display,&segment_info[1]);
5560 if (status != False)
5561 (void) XSync(display,MagickFalse);
5562 if ((status == False) || (xerror_alert != MagickFalse))
5563 {
5564 window->shared_memory=MagickFalse;
5565 if (status != False)
5566 XShmDetach(display,&segment_info[1]);
5567 if (ximage != (XImage *) NULL)
5568 {
5569 ximage->data=NULL;
5570 XDestroyImage(ximage);
5571 ximage=(XImage *) NULL;
5572 }
5573 if (segment_info[1].shmid >= 0)
5574 {
5575 if (segment_info[1].shmaddr != NULL)
5576 (void) shmdt(segment_info[1].shmaddr);
5577 (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
5578 segment_info[1].shmid=(-1);
5579 segment_info[1].shmaddr=(char *) NULL;
5580 }
5581 }
5582 }
5583#endif
5584 if (window->shared_memory == MagickFalse)
5585 ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
5586 (char *) NULL,width,height,XBitmapPad(display),0);
5587 if (ximage == (XImage *) NULL)
5588 {
5589 /*
5590 Unable to create X image.
5591 */
5592 (void) XCheckDefineCursor(display,window->id,window->cursor);
5593 return(MagickFalse);
5594 }
5595 length=(size_t) ximage->bytes_per_line*ximage->height;
5596 if (IsEventLogging())
5597 {
5598 (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
5599 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
5600 ximage->width,ximage->height);
5601 (void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
5602 ximage->format);
5603 (void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
5604 ximage->byte_order);
5605 (void) LogMagickEvent(X11Event,GetMagickModule(),
5606 " bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
5607 ximage->bitmap_bit_order,ximage->bitmap_pad);
5608 (void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
5609 ximage->depth);
5610 (void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
5611 ximage->bytes_per_line);
5612 (void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
5613 ximage->bits_per_pixel);
5614 (void) LogMagickEvent(X11Event,GetMagickModule(),
5615 " red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
5616 ximage->green_mask,ximage->blue_mask);
5617 }
5618 if (window->shared_memory == MagickFalse)
5619 {
5620 if (ximage->format != XYBitmap)
5621 ximage->data=(char *) AcquireQuantumMemory((size_t)
5622 ximage->bytes_per_line,(size_t) ximage->height);
5623 else
5624 ximage->data=(char *) AcquireQuantumMemory((size_t)
5625 ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
5626 }
5627 if (ximage->data == (char *) NULL)
5628 {
5629 /*
5630 Unable to allocate pixel data.
5631 */
5632 XDestroyImage(ximage);
5633 ximage=(XImage *) NULL;
5634 (void) XCheckDefineCursor(display,window->id,window->cursor);
5635 return(MagickFalse);
5636 }
5637 if (window->ximage != (XImage *) NULL)
5638 {
5639 /*
5640 Destroy previous X image.
5641 */
5642 length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
5643#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5644 if (window->segment_info != (XShmSegmentInfo *) NULL)
5645 {
5646 XShmSegmentInfo
5647 *segment_info;
5648
5649 segment_info=(XShmSegmentInfo *) window->segment_info;
5650 if (segment_info[0].shmid >= 0)
5651 {
5652 (void) XSync(display,MagickFalse);
5653 (void) XShmDetach(display,&segment_info[0]);
5654 (void) XSync(display,MagickFalse);
5655 if (segment_info[0].shmaddr != (char *) NULL)
5656 (void) shmdt(segment_info[0].shmaddr);
5657 (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
5658 segment_info[0].shmid=(-1);
5659 segment_info[0].shmaddr=(char *) NULL;
5660 window->ximage->data=(char *) NULL;
5661 }
5662 }
5663#endif
5664 if (window->ximage->data != (char *) NULL)
5665 free(window->ximage->data);
5666 window->ximage->data=(char *) NULL;
5667 XDestroyImage(window->ximage);
5668 window->ximage=(XImage *) NULL;
5669 }
5670#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
5671 if (window->segment_info != (XShmSegmentInfo *) NULL)
5672 {
5673 XShmSegmentInfo
5674 *segment_info;
5675
5676 segment_info=(XShmSegmentInfo *) window->segment_info;
5677 segment_info[0]=segment_info[1];
5678 }
5679#endif
5680 window->ximage=ximage;
5681 matte_image=(XImage *) NULL;
5682 if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
5683 if ((window->image->matte != MagickFalse) &&
cristyc57f6942010-11-12 01:47:39 +00005684 ((int) width <= XDisplayWidth(display,window->screen)) &&
5685 ((int) height <= XDisplayHeight(display,window->screen)))
cristy3ed852e2009-09-05 21:47:34 +00005686 {
5687 /*
5688 Create matte image.
5689 */
5690 matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
5691 (char *) NULL,width,height,XBitmapPad(display),0);
5692 if (IsEventLogging())
5693 {
5694 (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
5695 (void) LogMagickEvent(X11Event,GetMagickModule(),
5696 " width, height: %dx%d",matte_image->width,matte_image->height);
5697 }
5698 if (matte_image != (XImage *) NULL)
5699 {
5700 /*
5701 Allocate matte image pixel data.
5702 */
5703 matte_image->data=(char *) AcquireQuantumMemory((size_t)
5704 matte_image->bytes_per_line*matte_image->depth,
5705 (size_t) matte_image->height);
5706 if (matte_image->data == (char *) NULL)
5707 {
5708 XDestroyImage(matte_image);
5709 matte_image=(XImage *) NULL;
5710 }
5711 }
5712 }
5713 if (window->matte_image != (XImage *) NULL)
5714 {
5715 /*
5716 Free matte image.
5717 */
5718 if (window->matte_image->data != (char *) NULL)
5719 free(window->matte_image->data);
5720 window->matte_image->data=(char *) NULL;
5721 XDestroyImage(window->matte_image);
5722 window->matte_image=(XImage *) NULL;
5723 }
5724 window->matte_image=matte_image;
5725 if (window->matte_pixmap != (Pixmap) NULL)
5726 {
5727 (void) XFreePixmap(display,window->matte_pixmap);
5728 window->matte_pixmap=(Pixmap) NULL;
5729#if defined(MAGICKCORE_HAVE_SHAPE)
5730 if (window->shape != MagickFalse)
5731 XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
5732#endif
5733 }
5734 window->stasis=MagickFalse;
5735 /*
5736 Convert pixels to X image data.
5737 */
5738 if (window->image != (Image *) NULL)
5739 {
5740 if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
5741 (ximage->bitmap_bit_order == LSBFirst)))
5742 XMakeImageLSBFirst(resource_info,window,window->image,ximage,
5743 matte_image);
5744 else
5745 XMakeImageMSBFirst(resource_info,window,window->image,ximage,
5746 matte_image);
5747 }
5748 if (window->matte_image != (XImage *) NULL)
5749 {
5750 /*
5751 Create matte pixmap.
5752 */
5753 window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
5754 if (window->matte_pixmap != (Pixmap) NULL)
5755 {
5756 GC
5757 graphics_context;
5758
5759 XGCValues
5760 context_values;
5761
5762 /*
5763 Copy matte image to matte pixmap.
5764 */
5765 context_values.background=1;
5766 context_values.foreground=0;
5767 graphics_context=XCreateGC(display,window->matte_pixmap,
cristybb503372010-05-27 20:51:26 +00005768 (size_t) (GCBackground | GCForeground),&context_values);
cristy3ed852e2009-09-05 21:47:34 +00005769 (void) XPutImage(display,window->matte_pixmap,graphics_context,
5770 window->matte_image,0,0,0,0,width,height);
5771 (void) XFreeGC(display,graphics_context);
5772#if defined(MAGICKCORE_HAVE_SHAPE)
5773 if (window->shape != MagickFalse)
5774 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
5775 window->matte_pixmap,ShapeSet);
5776#endif
5777 }
5778 }
5779 (void) XMakePixmap(display,resource_info,window);
5780 /*
5781 Restore cursor.
5782 */
5783 (void) XCheckDefineCursor(display,window->id,window->cursor);
5784 return(MagickTrue);
5785}
5786
5787/*
5788%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5789% %
5790% %
5791% %
5792+ X M a k e I m a g e L S B F i r s t %
5793% %
5794% %
5795% %
5796%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5797%
5798% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
5799% pixels are copied in least-significant bit and byte first order. The
5800% server's scanline pad is respected. Rather than using one or two general
5801% cases, many special cases are found here to help speed up the image
5802% conversion.
5803%
5804% The format of the XMakeImageLSBFirst method is:
5805%
5806% void XMakeImageLSBFirst(Display *display,XWindows *windows)
5807%
5808% A description of each parameter follows:
5809%
5810% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5811%
5812% o window: Specifies a pointer to a XWindowInfo structure.
5813%
5814% o image: the image.
5815%
5816% o ximage: Specifies a pointer to a XImage structure; returned from
5817% XCreateImage.
5818%
5819% o matte_image: Specifies a pointer to a XImage structure; returned from
5820% XCreateImage.
5821%
5822*/
5823static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
5824 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
5825{
cristyc57f6942010-11-12 01:47:39 +00005826 CacheView
5827 *canvas_view;
5828
cristy3ed852e2009-09-05 21:47:34 +00005829 Image
5830 *canvas;
5831
5832 int
5833 y;
5834
5835 register const IndexPacket
5836 *indexes;
5837
5838 register const PixelPacket
5839 *p;
5840
5841 register int
5842 x;
5843
5844 register unsigned char
5845 *q;
5846
5847 unsigned char
5848 bit,
5849 byte;
5850
5851 unsigned int
5852 scanline_pad;
5853
cristyf2faecf2010-05-28 19:19:36 +00005854 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00005855 pixel,
5856 *pixels;
5857
5858 XStandardColormap
5859 *map_info;
5860
5861 assert(resource_info != (XResourceInfo *) NULL);
5862 assert(window != (XWindowInfo *) NULL);
5863 assert(image != (Image *) NULL);
5864 if (image->debug != MagickFalse)
5865 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5866 canvas=image;
cristybab87c32010-02-09 20:54:22 +00005867 if ((window->immutable == MagickFalse) &&
cristy54666e82010-02-03 23:34:26 +00005868 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00005869 {
5870 char
5871 size[MaxTextExtent];
5872
5873 Image
5874 *pattern;
5875
5876 ImageInfo
5877 *image_info;
5878
5879 image_info=AcquireImageInfo();
5880 (void) CopyMagickString(image_info->filename,
5881 resource_info->image_info->texture != (char *) NULL ?
5882 resource_info->image_info->texture : "pattern:checkerboard",
5883 MaxTextExtent);
cristye8c25f92010-06-03 00:53:06 +00005884 (void) FormatMagickString(size,MaxTextExtent,"%.20gx%.20g",(double)
5885 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00005886 image_info->size=ConstantString(size);
5887 pattern=ReadImage(image_info,&image->exception);
5888 image_info=DestroyImageInfo(image_info);
5889 if (pattern != (Image *) NULL)
5890 {
5891 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
5892 if (canvas != (Image *) NULL)
5893 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
5894 pattern=DestroyImage(pattern);
5895 }
5896 }
5897 scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
5898 ximage->bits_per_pixel) >> 3));
5899 map_info=window->map_info;
5900 pixels=window->pixel_info->pixels;
5901 q=(unsigned char *) ximage->data;
5902 x=0;
cristyc57f6942010-11-12 01:47:39 +00005903 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00005904 if (ximage->format == XYBitmap)
5905 {
5906 register unsigned short
5907 polarity;
5908
5909 unsigned char
5910 background,
5911 foreground;
5912
5913 /*
5914 Convert canvas to big-endian bitmap.
5915 */
5916 background=(unsigned char)
5917 (XPixelIntensity(&window->pixel_info->foreground_color) <
5918 XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
5919 foreground=(unsigned char)
5920 (XPixelIntensity(&window->pixel_info->background_color) <
5921 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
5922 polarity=(unsigned short) ((PixelIntensityToQuantum(
5923 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
5924 if (canvas->colors == 2)
5925 polarity=PixelIntensity(&canvas->colormap[0]) <
5926 PixelIntensity(&canvas->colormap[1]);
5927 for (y=0; y < (int) canvas->rows; y++)
5928 {
cristyc57f6942010-11-12 01:47:39 +00005929 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
5930 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00005931 if (p == (const PixelPacket *) NULL)
5932 break;
cristyc57f6942010-11-12 01:47:39 +00005933 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00005934 bit=0;
5935 byte=0;
5936 for (x=0; x < (int) canvas->columns; x++)
5937 {
5938 byte>>=1;
cristyfba5a8b2011-05-03 17:12:12 +00005939 if (GetIndexPixelComponent(indexes+x) == (IndexPacket) polarity)
cristy3ed852e2009-09-05 21:47:34 +00005940 byte|=foreground;
5941 else
5942 byte|=background;
5943 bit++;
5944 if (bit == 8)
5945 {
5946 *q++=byte;
5947 bit=0;
5948 byte=0;
5949 }
5950 }
5951 if (bit != 0)
5952 *q=byte >> (8-bit);
5953 q+=scanline_pad;
5954 }
5955 }
5956 else
5957 if (window->pixel_info->colors != 0)
5958 switch (ximage->bits_per_pixel)
5959 {
5960 case 2:
5961 {
5962 register unsigned int
5963 nibble;
5964
5965 /*
5966 Convert to 2 bit color-mapped X canvas.
5967 */
5968 for (y=0; y < (int) canvas->rows; y++)
5969 {
cristyc57f6942010-11-12 01:47:39 +00005970 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
5971 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00005972 if (p == (const PixelPacket *) NULL)
5973 break;
cristyc57f6942010-11-12 01:47:39 +00005974 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00005975 nibble=0;
5976 for (x=0; x < (int) canvas->columns; x++)
5977 {
cristyfba5a8b2011-05-03 17:12:12 +00005978 pixel=pixels[(ssize_t) GetIndexPixelComponent(indexes+x)] & 0x0f;
cristy3ed852e2009-09-05 21:47:34 +00005979 switch (nibble)
5980 {
5981 case 0:
5982 {
5983 *q=(unsigned char) pixel;
5984 nibble++;
5985 break;
5986 }
5987 case 1:
5988 {
5989 *q|=(unsigned char) (pixel << 2);
5990 nibble++;
5991 break;
5992 }
5993 case 2:
5994 {
5995 *q|=(unsigned char) (pixel << 4);
5996 nibble++;
5997 break;
5998 }
5999 case 3:
6000 {
6001 *q|=(unsigned char) (pixel << 6);
6002 q++;
6003 nibble=0;
6004 break;
6005 }
6006 }
6007 }
6008 q+=scanline_pad;
6009 }
6010 break;
6011 }
6012 case 4:
6013 {
6014 register unsigned int
6015 nibble;
6016
6017 /*
6018 Convert to 4 bit color-mapped X canvas.
6019 */
6020 for (y=0; y < (int) canvas->rows; y++)
6021 {
cristyc57f6942010-11-12 01:47:39 +00006022 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6023 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006024 if (p == (const PixelPacket *) NULL)
6025 break;
cristyc57f6942010-11-12 01:47:39 +00006026 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006027 nibble=0;
6028 for (x=0; x < (int) canvas->columns; x++)
6029 {
cristyfba5a8b2011-05-03 17:12:12 +00006030 pixel=pixels[(ssize_t) GetIndexPixelComponent(indexes+x)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006031 switch (nibble)
6032 {
6033 case 0:
6034 {
6035 *q=(unsigned char) pixel;
6036 nibble++;
6037 break;
6038 }
6039 case 1:
6040 {
6041 *q|=(unsigned char) (pixel << 4);
6042 q++;
6043 nibble=0;
6044 break;
6045 }
6046 }
6047 }
6048 q+=scanline_pad;
6049 }
6050 break;
6051 }
6052 case 6:
6053 case 8:
6054 {
6055 /*
6056 Convert to 8 bit color-mapped X canvas.
6057 */
6058 if (resource_info->color_recovery &&
6059 resource_info->quantize_info->dither)
6060 {
6061 XDitherImage(canvas,ximage);
6062 break;
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);
cristy3ed852e2009-09-05 21:47:34 +00006068 if (p == (const PixelPacket *) NULL)
6069 break;
cristyc57f6942010-11-12 01:47:39 +00006070 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006071 for (x=0; x < (int) canvas->columns; x++)
6072 {
cristyfba5a8b2011-05-03 17:12:12 +00006073 pixel=pixels[(ssize_t) GetIndexPixelComponent(indexes+x)];
cristy3ed852e2009-09-05 21:47:34 +00006074 *q++=(unsigned char) pixel;
6075 }
6076 q+=scanline_pad;
6077 }
6078 break;
6079 }
6080 default:
6081 {
6082 register int
6083 k;
6084
6085 register unsigned int
6086 bytes_per_pixel;
6087
6088 unsigned char
cristybb503372010-05-27 20:51:26 +00006089 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006090
6091 /*
6092 Convert to multi-byte color-mapped X canvas.
6093 */
6094 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6095 for (y=0; y < (int) canvas->rows; y++)
6096 {
cristyc57f6942010-11-12 01:47:39 +00006097 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6098 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006099 if (p == (const PixelPacket *) NULL)
6100 break;
cristyc57f6942010-11-12 01:47:39 +00006101 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006102 for (x=0; x < (int) canvas->columns; x++)
6103 {
cristyfba5a8b2011-05-03 17:12:12 +00006104 pixel=pixels[(ssize_t) GetIndexPixelComponent(indexes+x)];
cristy3ed852e2009-09-05 21:47:34 +00006105 for (k=0; k < (int) bytes_per_pixel; k++)
6106 {
6107 channel[k]=(unsigned char) pixel;
6108 pixel>>=8;
6109 }
6110 for (k=0; k < (int) bytes_per_pixel; k++)
6111 *q++=channel[k];
6112 }
6113 q+=scanline_pad;
6114 }
6115 break;
6116 }
6117 }
6118 else
6119 switch (ximage->bits_per_pixel)
6120 {
6121 case 2:
6122 {
6123 register unsigned int
6124 nibble;
6125
6126 /*
6127 Convert to contiguous 2 bit continuous-tone X canvas.
6128 */
6129 for (y=0; y < (int) canvas->rows; y++)
6130 {
6131 nibble=0;
cristyc57f6942010-11-12 01:47:39 +00006132 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6133 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006134 if (p == (const PixelPacket *) NULL)
6135 break;
6136 for (x=0; x < (int) canvas->columns; x++)
6137 {
6138 pixel=XGammaPixel(map_info,p);
6139 pixel&=0xf;
6140 switch (nibble)
6141 {
6142 case 0:
6143 {
6144 *q=(unsigned char) pixel;
6145 nibble++;
6146 break;
6147 }
6148 case 1:
6149 {
6150 *q|=(unsigned char) (pixel << 2);
6151 nibble++;
6152 break;
6153 }
6154 case 2:
6155 {
6156 *q|=(unsigned char) (pixel << 4);
6157 nibble++;
6158 break;
6159 }
6160 case 3:
6161 {
6162 *q|=(unsigned char) (pixel << 6);
6163 q++;
6164 nibble=0;
6165 break;
6166 }
6167 }
6168 p++;
6169 }
6170 q+=scanline_pad;
6171 }
6172 break;
6173 }
6174 case 4:
6175 {
6176 register unsigned int
6177 nibble;
6178
6179 /*
6180 Convert to contiguous 4 bit continuous-tone X canvas.
6181 */
6182 for (y=0; y < (int) canvas->rows; y++)
6183 {
cristyc57f6942010-11-12 01:47:39 +00006184 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6185 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006186 if (p == (const PixelPacket *) NULL)
6187 break;
6188 nibble=0;
6189 for (x=0; x < (int) canvas->columns; x++)
6190 {
6191 pixel=XGammaPixel(map_info,p);
6192 pixel&=0xf;
6193 switch (nibble)
6194 {
6195 case 0:
6196 {
6197 *q=(unsigned char) pixel;
6198 nibble++;
6199 break;
6200 }
6201 case 1:
6202 {
6203 *q|=(unsigned char) (pixel << 4);
6204 q++;
6205 nibble=0;
6206 break;
6207 }
6208 }
6209 p++;
6210 }
6211 q+=scanline_pad;
6212 }
6213 break;
6214 }
6215 case 6:
6216 case 8:
6217 {
6218 /*
6219 Convert to contiguous 8 bit continuous-tone X canvas.
6220 */
6221 if (resource_info->color_recovery &&
6222 resource_info->quantize_info->dither)
6223 {
6224 XDitherImage(canvas,ximage);
6225 break;
6226 }
6227 for (y=0; y < (int) canvas->rows; y++)
6228 {
cristyc57f6942010-11-12 01:47:39 +00006229 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6230 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006231 if (p == (const PixelPacket *) NULL)
6232 break;
6233 for (x=0; x < (int) canvas->columns; x++)
6234 {
6235 pixel=XGammaPixel(map_info,p);
6236 *q++=(unsigned char) pixel;
6237 p++;
6238 }
6239 q+=scanline_pad;
6240 }
6241 break;
6242 }
6243 default:
6244 {
6245 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6246 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6247 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6248 (map_info->blue_mult == 1))
6249 {
6250 /*
6251 Convert to 32 bit continuous-tone X canvas.
6252 */
6253 for (y=0; y < (int) canvas->rows; y++)
6254 {
cristyc57f6942010-11-12 01:47:39 +00006255 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6256 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006257 if (p == (const PixelPacket *) NULL)
6258 break;
6259 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6260 (blue_gamma != 1.0))
6261 {
6262 /*
6263 Gamma correct canvas.
6264 */
6265 for (x=(int) canvas->columns-1; x >= 0; x--)
6266 {
cristyccf844f2010-02-03 23:28:16 +00006267 *q++=ScaleQuantumToChar(XBlueGamma(
6268 GetBluePixelComponent(p)));
6269 *q++=ScaleQuantumToChar(XGreenGamma(
6270 GetGreenPixelComponent(p)));
6271 *q++=ScaleQuantumToChar(XRedGamma(
6272 GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006273 *q++=0;
6274 p++;
6275 }
6276 continue;
6277 }
6278 for (x=(int) canvas->columns-1; x >= 0; x--)
6279 {
cristyce70c172010-01-07 17:15:30 +00006280 *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
6281 *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6282 *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006283 *q++=0;
6284 p++;
6285 }
6286 }
6287 }
6288 else
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 == 1) && (map_info->green_mult == 256) &&
6292 (map_info->blue_mult == 65536L))
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);
cristy3ed852e2009-09-05 21:47:34 +00006301 if (p == (const PixelPacket *) NULL)
6302 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(XRedGamma(
6312 GetRedPixelComponent(p)));
6313 *q++=ScaleQuantumToChar(XGreenGamma(
6314 GetGreenPixelComponent(p)));
6315 *q++=ScaleQuantumToChar(XBlueGamma(
6316 GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006317 *q++=0;
6318 p++;
6319 }
6320 continue;
6321 }
6322 for (x=(int) canvas->columns-1; x >= 0; x--)
6323 {
cristyccf844f2010-02-03 23:28:16 +00006324 *q++=ScaleQuantumToChar((Quantum)
6325 GetRedPixelComponent(p));
6326 *q++=ScaleQuantumToChar((Quantum)
6327 GetGreenPixelComponent(p));
6328 *q++=ScaleQuantumToChar((Quantum)
6329 GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006330 *q++=0;
6331 p++;
6332 }
6333 }
6334 }
6335 else
6336 {
6337 register int
6338 k;
6339
6340 register unsigned int
6341 bytes_per_pixel;
6342
6343 unsigned char
cristybb503372010-05-27 20:51:26 +00006344 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006345
6346 /*
6347 Convert to multi-byte continuous-tone X canvas.
6348 */
6349 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6350 for (y=0; y < (int) canvas->rows; y++)
6351 {
cristyc57f6942010-11-12 01:47:39 +00006352 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6353 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006354 if (p == (PixelPacket *) NULL)
6355 break;
cristyc57f6942010-11-12 01:47:39 +00006356 for (x=0; x < (int) canvas->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00006357 {
6358 pixel=XGammaPixel(map_info,p);
6359 for (k=0; k < (int) bytes_per_pixel; k++)
6360 {
6361 channel[k]=(unsigned char) pixel;
6362 pixel>>=8;
6363 }
6364 for (k=0; k < (int) bytes_per_pixel; k++)
6365 *q++=channel[k];
6366 p++;
6367 }
6368 q+=scanline_pad;
6369 }
6370 }
6371 break;
6372 }
6373 }
6374 if (matte_image != (XImage *) NULL)
6375 {
6376 /*
6377 Initialize matte canvas.
6378 */
6379 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
6380 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
6381 q=(unsigned char *) matte_image->data;
6382 for (y=0; y < (int) canvas->rows; y++)
6383 {
cristyc57f6942010-11-12 01:47:39 +00006384 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6385 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006386 if (p == (const PixelPacket *) NULL)
6387 break;
6388 bit=0;
6389 byte=0;
6390 for (x=(int) canvas->columns-1; x >= 0; x--)
6391 {
6392 byte>>=1;
cristyd05ecd12011-04-22 20:44:42 +00006393 if (GetOpacityPixelComponent(p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00006394 byte|=0x80;
6395 bit++;
6396 if (bit == 8)
6397 {
6398 *q++=byte;
6399 bit=0;
6400 byte=0;
6401 }
6402 p++;
6403 }
6404 if (bit != 0)
6405 *q=byte >> (8-bit);
6406 q+=scanline_pad;
6407 }
6408 }
cristyc57f6942010-11-12 01:47:39 +00006409 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006410 if (canvas != image)
6411 canvas=DestroyImage(canvas);
6412}
6413
6414/*
6415%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6416% %
6417% %
6418% %
6419+ X M a k e I m a g e M S B F i r s t %
6420% %
6421% %
6422% %
6423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6424%
6425% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
6426% image pixels are copied in most-significant bit and byte first order. The
6427% server's scanline pad is also respected. Rather than using one or two
6428% general cases, many special cases are found here to help speed up the image
6429% conversion.
6430%
6431% The format of the XMakeImageMSBFirst method is:
6432%
6433% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
6434%
6435% A description of each parameter follows:
6436%
6437% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6438%
6439% o window: Specifies a pointer to a XWindowInfo structure.
6440%
6441% o image: the image.
6442%
6443% o ximage: Specifies a pointer to a XImage structure; returned from
6444% XCreateImage.
6445%
6446% o matte_image: Specifies a pointer to a XImage structure; returned from
6447% XCreateImage.
6448%
cristy3ed852e2009-09-05 21:47:34 +00006449*/
6450static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
6451 const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
6452{
cristyc57f6942010-11-12 01:47:39 +00006453 CacheView
6454 *canvas_view;
6455
cristy3ed852e2009-09-05 21:47:34 +00006456 Image
6457 *canvas;
6458
6459 int
6460 y;
6461
6462 register int
6463 x;
6464
6465 register const IndexPacket
6466 *indexes;
6467
6468 register const PixelPacket
6469 *p;
6470
6471 register unsigned char
6472 *q;
6473
6474 unsigned char
6475 bit,
6476 byte;
6477
6478 unsigned int
6479 scanline_pad;
6480
cristyf2faecf2010-05-28 19:19:36 +00006481 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00006482 pixel,
6483 *pixels;
6484
6485 XStandardColormap
6486 *map_info;
6487
6488 assert(resource_info != (XResourceInfo *) NULL);
6489 assert(window != (XWindowInfo *) NULL);
6490 assert(image != (Image *) NULL);
6491 if (image->debug != MagickFalse)
6492 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
6493 canvas=image;
cristy54666e82010-02-03 23:34:26 +00006494 if ((window->immutable != MagickFalse) &&
6495 (image->storage_class == DirectClass) && (image->matte != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +00006496 {
6497 char
6498 size[MaxTextExtent];
6499
6500 Image
6501 *pattern;
6502
6503 ImageInfo
6504 *image_info;
6505
6506 image_info=AcquireImageInfo();
6507 (void) CopyMagickString(image_info->filename,
6508 resource_info->image_info->texture != (char *) NULL ?
6509 resource_info->image_info->texture : "pattern:checkerboard",
6510 MaxTextExtent);
cristye8c25f92010-06-03 00:53:06 +00006511 (void) FormatMagickString(size,MaxTextExtent,"%.20gx%.20g",(double)
6512 image->columns,(double) image->rows);
cristy3ed852e2009-09-05 21:47:34 +00006513 image_info->size=ConstantString(size);
6514 pattern=ReadImage(image_info,&image->exception);
6515 image_info=DestroyImageInfo(image_info);
6516 if (pattern != (Image *) NULL)
6517 {
6518 canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
6519 if (canvas != (Image *) NULL)
6520 (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
6521 pattern=DestroyImage(pattern);
6522 }
6523 }
6524 scanline_pad=(unsigned int) (ximage->bytes_per_line-
6525 ((ximage->width*ximage->bits_per_pixel) >> 3));
6526 map_info=window->map_info;
6527 pixels=window->pixel_info->pixels;
6528 q=(unsigned char *) ximage->data;
6529 x=0;
cristyc57f6942010-11-12 01:47:39 +00006530 canvas_view=AcquireCacheView(canvas);
cristy3ed852e2009-09-05 21:47:34 +00006531 if (ximage->format == XYBitmap)
6532 {
6533 register unsigned short
6534 polarity;
6535
6536 unsigned char
6537 background,
6538 foreground;
6539
6540 /*
6541 Convert canvas to big-endian bitmap.
6542 */
6543 background=(unsigned char)
6544 (XPixelIntensity(&window->pixel_info->foreground_color) <
6545 XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
6546 foreground=(unsigned char)
6547 (XPixelIntensity(&window->pixel_info->background_color) <
6548 XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
6549 polarity=(unsigned short) ((PixelIntensityToQuantum(
6550 &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
6551 if (canvas->colors == 2)
6552 polarity=PixelIntensity(&canvas->colormap[0]) <
6553 PixelIntensity(&canvas->colormap[1]);
6554 for (y=0; y < (int) canvas->rows; y++)
6555 {
cristyc57f6942010-11-12 01:47:39 +00006556 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
6557 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006558 if (p == (const PixelPacket *) NULL)
6559 break;
cristyc57f6942010-11-12 01:47:39 +00006560 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006561 bit=0;
6562 byte=0;
6563 for (x=(int) canvas->columns-1; x >= 0; x--)
6564 {
6565 byte<<=1;
cristyfba5a8b2011-05-03 17:12:12 +00006566 if (GetIndexPixelComponent(indexes+x) == (IndexPacket) polarity)
cristy3ed852e2009-09-05 21:47:34 +00006567 byte|=foreground;
6568 else
6569 byte|=background;
6570 bit++;
6571 if (bit == 8)
6572 {
6573 *q++=byte;
6574 bit=0;
6575 byte=0;
6576 }
6577 }
6578 if (bit != 0)
6579 *q=byte << (8-bit);
6580 q+=scanline_pad;
6581 }
6582 }
6583 else
6584 if (window->pixel_info->colors != 0)
6585 switch (ximage->bits_per_pixel)
6586 {
6587 case 2:
6588 {
6589 register unsigned int
6590 nibble;
6591
6592 /*
6593 Convert to 2 bit color-mapped X canvas.
6594 */
6595 for (y=0; y < (int) canvas->rows; y++)
6596 {
cristyc57f6942010-11-12 01:47:39 +00006597 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6598 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006599 if (p == (const PixelPacket *) NULL)
6600 break;
cristyc57f6942010-11-12 01:47:39 +00006601 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006602 nibble=0;
6603 for (x=0; x < (int) canvas->columns; x++)
6604 {
cristyfba5a8b2011-05-03 17:12:12 +00006605 pixel=pixels[(ssize_t) GetIndexPixelComponent(indexes+x)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006606 switch (nibble)
6607 {
6608 case 0:
6609 {
6610 *q=(unsigned char) (pixel << 6);
6611 nibble++;
6612 break;
6613 }
6614 case 1:
6615 {
6616 *q|=(unsigned char) (pixel << 4);
6617 nibble++;
6618 break;
6619 }
6620 case 2:
6621 {
6622 *q|=(unsigned char) (pixel << 2);
6623 nibble++;
6624 break;
6625 }
6626 case 3:
6627 {
6628 *q|=(unsigned char) pixel;
6629 q++;
6630 nibble=0;
6631 break;
6632 }
6633 }
6634 }
6635 q+=scanline_pad;
6636 }
6637 break;
6638 }
6639 case 4:
6640 {
6641 register unsigned int
6642 nibble;
6643
6644 /*
6645 Convert to 4 bit color-mapped X canvas.
6646 */
6647 for (y=0; y < (int) canvas->rows; y++)
6648 {
cristyc57f6942010-11-12 01:47:39 +00006649 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6650 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006651 if (p == (const PixelPacket *) NULL)
6652 break;
cristyc57f6942010-11-12 01:47:39 +00006653 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006654 nibble=0;
6655 for (x=0; x < (int) canvas->columns; x++)
6656 {
cristyfba5a8b2011-05-03 17:12:12 +00006657 pixel=pixels[(ssize_t) GetIndexPixelComponent(indexes+x)] & 0xf;
cristy3ed852e2009-09-05 21:47:34 +00006658 switch (nibble)
6659 {
6660 case 0:
6661 {
6662 *q=(unsigned char) (pixel << 4);
6663 nibble++;
6664 break;
6665 }
6666 case 1:
6667 {
6668 *q|=(unsigned char) pixel;
6669 q++;
6670 nibble=0;
6671 break;
6672 }
6673 }
6674 }
6675 q+=scanline_pad;
6676 }
6677 break;
6678 }
6679 case 6:
6680 case 8:
6681 {
6682 /*
6683 Convert to 8 bit color-mapped X canvas.
6684 */
6685 if (resource_info->color_recovery &&
6686 resource_info->quantize_info->dither)
6687 {
6688 XDitherImage(canvas,ximage);
6689 break;
6690 }
6691 for (y=0; y < (int) canvas->rows; y++)
6692 {
cristyc57f6942010-11-12 01:47:39 +00006693 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6694 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006695 if (p == (const PixelPacket *) NULL)
6696 break;
cristyc57f6942010-11-12 01:47:39 +00006697 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006698 for (x=0; x < (int) canvas->columns; x++)
6699 {
cristyfba5a8b2011-05-03 17:12:12 +00006700 pixel=pixels[(ssize_t) GetIndexPixelComponent(indexes+x)];
cristy3ed852e2009-09-05 21:47:34 +00006701 *q++=(unsigned char) pixel;
6702 }
6703 q+=scanline_pad;
6704 }
6705 break;
6706 }
6707 default:
6708 {
6709 register int
6710 k;
6711
6712 register unsigned int
6713 bytes_per_pixel;
6714
6715 unsigned char
cristybb503372010-05-27 20:51:26 +00006716 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006717
6718 /*
6719 Convert to 8 bit color-mapped X canvas.
6720 */
6721 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6722 for (y=0; y < (int) canvas->rows; y++)
6723 {
cristyc57f6942010-11-12 01:47:39 +00006724 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6725 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006726 if (p == (const PixelPacket *) NULL)
6727 break;
cristyc57f6942010-11-12 01:47:39 +00006728 indexes=GetCacheViewVirtualIndexQueue(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00006729 for (x=0; x < (int) canvas->columns; x++)
6730 {
cristyfba5a8b2011-05-03 17:12:12 +00006731 pixel=pixels[(ssize_t) GetIndexPixelComponent(indexes+x)];
cristy3ed852e2009-09-05 21:47:34 +00006732 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6733 {
6734 channel[k]=(unsigned char) pixel;
6735 pixel>>=8;
6736 }
6737 for (k=0; k < (int) bytes_per_pixel; k++)
6738 *q++=channel[k];
6739 }
6740 q+=scanline_pad;
6741 }
6742 break;
6743 }
6744 }
6745 else
6746 switch (ximage->bits_per_pixel)
6747 {
6748 case 2:
6749 {
6750 register unsigned int
6751 nibble;
6752
6753 /*
6754 Convert to 4 bit continuous-tone X canvas.
6755 */
6756 for (y=0; y < (int) canvas->rows; y++)
6757 {
cristyc57f6942010-11-12 01:47:39 +00006758 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6759 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006760 if (p == (const PixelPacket *) NULL)
6761 break;
6762 nibble=0;
6763 for (x=(int) canvas->columns-1; x >= 0; x--)
6764 {
6765 pixel=XGammaPixel(map_info,p);
6766 pixel&=0xf;
6767 switch (nibble)
6768 {
6769 case 0:
6770 {
6771 *q=(unsigned char) (pixel << 6);
6772 nibble++;
6773 break;
6774 }
6775 case 1:
6776 {
6777 *q|=(unsigned char) (pixel << 4);
6778 nibble++;
6779 break;
6780 }
6781 case 2:
6782 {
6783 *q|=(unsigned char) (pixel << 2);
6784 nibble++;
6785 break;
6786 }
6787 case 3:
6788 {
6789 *q|=(unsigned char) pixel;
6790 q++;
6791 nibble=0;
6792 break;
6793 }
6794 }
6795 p++;
6796 }
6797 q+=scanline_pad;
6798 }
6799 break;
6800 }
6801 case 4:
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);
cristy3ed852e2009-09-05 21:47:34 +00006813 if (p == (const PixelPacket *) NULL)
6814 break;
6815 nibble=0;
6816 for (x=(int) canvas->columns-1; x >= 0; x--)
6817 {
6818 pixel=XGammaPixel(map_info,p);
6819 pixel&=0xf;
6820 switch (nibble)
6821 {
6822 case 0:
6823 {
6824 *q=(unsigned char) (pixel << 4);
6825 nibble++;
6826 break;
6827 }
6828 case 1:
6829 {
6830 *q|=(unsigned char) pixel;
6831 q++;
6832 nibble=0;
6833 break;
6834 }
6835 }
6836 p++;
6837 }
6838 q+=scanline_pad;
6839 }
6840 break;
6841 }
6842 case 6:
6843 case 8:
6844 {
6845 /*
6846 Convert to 8 bit continuous-tone X canvas.
6847 */
6848 if (resource_info->color_recovery &&
6849 resource_info->quantize_info->dither)
6850 {
6851 XDitherImage(canvas,ximage);
6852 break;
6853 }
6854 for (y=0; y < (int) canvas->rows; y++)
6855 {
cristyc57f6942010-11-12 01:47:39 +00006856 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6857 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006858 if (p == (const PixelPacket *) NULL)
6859 break;
6860 for (x=(int) canvas->columns-1; x >= 0; x--)
6861 {
6862 pixel=XGammaPixel(map_info,p);
6863 *q++=(unsigned char) pixel;
6864 p++;
6865 }
6866 q+=scanline_pad;
6867 }
6868 break;
6869 }
6870 default:
6871 {
6872 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6873 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6874 (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
6875 (map_info->blue_mult == 1))
6876 {
6877 /*
6878 Convert to 32 bit continuous-tone X canvas.
6879 */
6880 for (y=0; y < (int) canvas->rows; y++)
6881 {
cristyc57f6942010-11-12 01:47:39 +00006882 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6883 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006884 if (p == (const PixelPacket *) NULL)
6885 break;
6886 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6887 (blue_gamma != 1.0))
6888 {
6889 /*
6890 Gamma correct canvas.
6891 */
6892 for (x=(int) canvas->columns-1; x >= 0; x--)
6893 {
6894 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006895 *q++=ScaleQuantumToChar(XRedGamma(
6896 GetRedPixelComponent(p)));
6897 *q++=ScaleQuantumToChar(XGreenGamma(
6898 GetGreenPixelComponent(p)));
6899 *q++=ScaleQuantumToChar(XBlueGamma(
6900 GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006901 p++;
6902 }
6903 continue;
6904 }
6905 for (x=(int) canvas->columns-1; x >= 0; x--)
6906 {
6907 *q++=0;
cristyce70c172010-01-07 17:15:30 +00006908 *q++=ScaleQuantumToChar((Quantum) GetRedPixelComponent(p));
6909 *q++=ScaleQuantumToChar((Quantum) GetGreenPixelComponent(p));
6910 *q++=ScaleQuantumToChar((Quantum) GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006911 p++;
6912 }
6913 }
6914 }
6915 else
6916 if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
6917 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
6918 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
6919 (map_info->blue_mult == 65536L))
6920 {
6921 /*
6922 Convert to 32 bit continuous-tone X canvas.
6923 */
6924 for (y=0; y < (int) canvas->rows; y++)
6925 {
cristyc57f6942010-11-12 01:47:39 +00006926 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6927 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006928 if (p == (const PixelPacket *) NULL)
6929 break;
6930 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
6931 (blue_gamma != 1.0))
6932 {
6933 /*
6934 Gamma correct canvas.
6935 */
6936 for (x=(int) canvas->columns-1; x >= 0; x--)
6937 {
6938 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006939 *q++=ScaleQuantumToChar(XBlueGamma(
6940 GetBluePixelComponent(p)));
6941 *q++=ScaleQuantumToChar(XGreenGamma(
6942 GetGreenPixelComponent(p)));
6943 *q++=ScaleQuantumToChar(XRedGamma(
6944 GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +00006945 p++;
6946 }
6947 continue;
6948 }
6949 for (x=(int) canvas->columns-1; x >= 0; x--)
6950 {
6951 *q++=0;
cristyccf844f2010-02-03 23:28:16 +00006952 *q++=ScaleQuantumToChar((Quantum)
6953 GetBluePixelComponent(p));
6954 *q++=ScaleQuantumToChar((Quantum)
6955 GetGreenPixelComponent(p));
6956 *q++=ScaleQuantumToChar((Quantum)
6957 GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +00006958 p++;
6959 }
6960 }
6961 }
6962 else
6963 {
6964 register int
6965 k;
6966
6967 register unsigned int
6968 bytes_per_pixel;
6969
6970 unsigned char
cristybb503372010-05-27 20:51:26 +00006971 channel[sizeof(size_t)];
cristy3ed852e2009-09-05 21:47:34 +00006972
6973 /*
6974 Convert to multi-byte continuous-tone X canvas.
6975 */
6976 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
6977 for (y=0; y < (int) canvas->rows; y++)
6978 {
cristyc57f6942010-11-12 01:47:39 +00006979 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
6980 canvas->columns,1,&canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00006981 if (p == (const PixelPacket *) NULL)
6982 break;
6983 for (x=(int) canvas->columns-1; x >= 0; x--)
6984 {
6985 pixel=XGammaPixel(map_info,p);
6986 for (k=(int) bytes_per_pixel-1; k >= 0; k--)
6987 {
6988 channel[k]=(unsigned char) pixel;
6989 pixel>>=8;
6990 }
6991 for (k=0; k < (int) bytes_per_pixel; k++)
6992 *q++=channel[k];
6993 p++;
6994 }
6995 q+=scanline_pad;
6996 }
6997 }
6998 break;
6999 }
7000 }
7001 if (matte_image != (XImage *) NULL)
7002 {
7003 /*
7004 Initialize matte canvas.
7005 */
7006 scanline_pad=(unsigned int) (matte_image->bytes_per_line-
7007 ((matte_image->width*matte_image->bits_per_pixel) >> 3));
7008 q=(unsigned char *) matte_image->data;
7009 for (y=0; y < (int) canvas->rows; y++)
7010 {
cristyc57f6942010-11-12 01:47:39 +00007011 p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
7012 &canvas->exception);
cristy3ed852e2009-09-05 21:47:34 +00007013 if (p == (const PixelPacket *) NULL)
7014 break;
7015 bit=0;
7016 byte=0;
7017 for (x=(int) canvas->columns-1; x >= 0; x--)
7018 {
7019 byte<<=1;
cristyd05ecd12011-04-22 20:44:42 +00007020 if (GetOpacityPixelComponent(p) > (QuantumRange/2))
cristy3ed852e2009-09-05 21:47:34 +00007021 byte|=0x01;
7022 bit++;
7023 if (bit == 8)
7024 {
7025 *q++=byte;
7026 bit=0;
7027 byte=0;
7028 }
7029 p++;
7030 }
7031 if (bit != 0)
7032 *q=byte << (8-bit);
7033 q+=scanline_pad;
7034 }
7035 }
cristyc57f6942010-11-12 01:47:39 +00007036 canvas_view=DestroyCacheView(canvas_view);
cristy3ed852e2009-09-05 21:47:34 +00007037 if (canvas != image)
7038 canvas=DestroyImage(canvas);
7039}
7040
7041/*
7042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7043% %
7044% %
7045% %
7046% X M a k e M a g n i f y I m a g e %
7047% %
7048% %
7049% %
7050%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7051%
7052% XMakeMagnifyImage() magnifies a region of an X image and displays it.
7053%
7054% The format of the XMakeMagnifyImage method is:
7055%
7056% void XMakeMagnifyImage(display,windows)
7057%
7058% A description of each parameter follows:
7059%
7060% o display: Specifies a connection to an X server; returned from
7061% XOpenDisplay.
7062%
7063% o windows: Specifies a pointer to a XWindows structure.
7064%
7065*/
7066MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
7067{
7068 char
7069 tuple[MaxTextExtent];
7070
7071 int
7072 y;
7073
cristy3ed852e2009-09-05 21:47:34 +00007074 MagickPixelPacket
7075 pixel;
7076
7077 register int
7078 x;
7079
cristybb503372010-05-27 20:51:26 +00007080 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007081 i;
7082
7083 register unsigned char
7084 *p,
7085 *q;
7086
cristy9d314ff2011-03-09 01:30:28 +00007087 ssize_t
7088 n;
7089
cristy3ed852e2009-09-05 21:47:34 +00007090 static unsigned int
7091 previous_magnify = 0;
7092
7093 static XWindowInfo
7094 magnify_window;
7095
7096 unsigned int
7097 height,
7098 j,
7099 k,
7100 l,
7101 magnify,
7102 scanline_pad,
7103 width;
7104
7105 XImage
7106 *ximage;
7107
7108 /*
7109 Check boundary conditions.
7110 */
7111 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7112 assert(display != (Display *) NULL);
7113 assert(windows != (XWindows *) NULL);
7114 magnify=1;
cristybb503372010-05-27 20:51:26 +00007115 for (n=1; n < (ssize_t) windows->magnify.data; n++)
cristy3ed852e2009-09-05 21:47:34 +00007116 magnify<<=1;
7117 while ((magnify*windows->image.ximage->width) < windows->magnify.width)
7118 magnify<<=1;
7119 while ((magnify*windows->image.ximage->height) < windows->magnify.height)
7120 magnify<<=1;
7121 while (magnify > windows->magnify.width)
7122 magnify>>=1;
7123 while (magnify > windows->magnify.height)
7124 magnify>>=1;
7125 if (magnify != previous_magnify)
7126 {
7127 Status
7128 status;
7129
7130 XTextProperty
7131 window_name;
7132
7133 /*
7134 New magnify factor: update magnify window name.
7135 */
7136 i=0;
7137 while ((1 << i) <= (int) magnify)
7138 i++;
7139 (void) FormatMagickString(windows->magnify.name,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +00007140 "Magnify %.20gX",(double) i);
cristy3ed852e2009-09-05 21:47:34 +00007141 status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
7142 if (status != False)
7143 {
7144 XSetWMName(display,windows->magnify.id,&window_name);
7145 XSetWMIconName(display,windows->magnify.id,&window_name);
7146 (void) XFree((void *) window_name.value);
7147 }
7148 }
7149 previous_magnify=magnify;
7150 ximage=windows->image.ximage;
7151 width=(unsigned int) windows->magnify.ximage->width;
7152 height=(unsigned int) windows->magnify.ximage->height;
7153 if ((windows->magnify.x < 0) ||
7154 (windows->magnify.x >= windows->image.ximage->width))
7155 windows->magnify.x=windows->image.ximage->width >> 1;
7156 x=windows->magnify.x-((width/magnify) >> 1);
7157 if (x < 0)
7158 x=0;
7159 else
7160 if (x > (int) (ximage->width-(width/magnify)))
7161 x=ximage->width-width/magnify;
7162 if ((windows->magnify.y < 0) ||
7163 (windows->magnify.y >= windows->image.ximage->height))
7164 windows->magnify.y=windows->image.ximage->height >> 1;
7165 y=windows->magnify.y-((height/magnify) >> 1);
7166 if (y < 0)
7167 y=0;
7168 else
7169 if (y > (int) (ximage->height-(height/magnify)))
7170 y=ximage->height-height/magnify;
7171 q=(unsigned char *) windows->magnify.ximage->data;
7172 scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
7173 ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
7174 if (ximage->bits_per_pixel < 8)
7175 {
7176 register unsigned char
7177 background,
7178 byte,
7179 foreground,
7180 p_bit,
7181 q_bit;
7182
7183 register unsigned int
7184 plane;
7185
7186 XPixelInfo
7187 *pixel_info;
7188
7189 pixel_info=windows->magnify.pixel_info;
7190 switch (ximage->bitmap_bit_order)
7191 {
7192 case LSBFirst:
7193 {
7194 /*
7195 Magnify little-endian bitmap.
7196 */
7197 background=0x00;
7198 foreground=0x80;
7199 if (ximage->format == XYBitmap)
7200 {
7201 background=(unsigned char)
7202 (XPixelIntensity(&pixel_info->foreground_color) <
7203 XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
7204 foreground=(unsigned char)
7205 (XPixelIntensity(&pixel_info->background_color) <
7206 XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
7207 if (windows->magnify.depth > 1)
7208 Swap(background,foreground);
7209 }
cristybb503372010-05-27 20:51:26 +00007210 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007211 {
7212 /*
7213 Propogate pixel magnify rows.
7214 */
7215 for (j=0; j < magnify; j++)
7216 {
7217 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7218 ((x*ximage->bits_per_pixel) >> 3);
7219 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7220 q_bit=0;
7221 byte=0;
7222 for (k=0; k < width; k+=magnify)
7223 {
7224 /*
7225 Propogate pixel magnify columns.
7226 */
7227 for (l=0; l < magnify; l++)
7228 {
7229 /*
7230 Propogate each bit plane.
7231 */
7232 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7233 {
7234 byte>>=1;
7235 if (*p & (0x01 << (p_bit+plane)))
7236 byte|=foreground;
7237 else
7238 byte|=background;
7239 q_bit++;
7240 if (q_bit == 8)
7241 {
7242 *q++=byte;
7243 q_bit=0;
7244 byte=0;
7245 }
7246 }
7247 }
7248 p_bit+=ximage->bits_per_pixel;
7249 if (p_bit == 8)
7250 {
7251 p++;
7252 p_bit=0;
7253 }
7254 if (q_bit != 0)
7255 *q=byte >> (8-q_bit);
7256 q+=scanline_pad;
7257 }
7258 }
7259 y++;
7260 }
7261 break;
7262 }
7263 case MSBFirst:
7264 default:
7265 {
7266 /*
7267 Magnify big-endian bitmap.
7268 */
7269 background=0x00;
7270 foreground=0x01;
7271 if (ximage->format == XYBitmap)
7272 {
7273 background=(unsigned char)
7274 (XPixelIntensity(&pixel_info->foreground_color) <
7275 XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
7276 foreground=(unsigned char)
7277 (XPixelIntensity(&pixel_info->background_color) <
7278 XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
7279 if (windows->magnify.depth > 1)
7280 Swap(background,foreground);
7281 }
cristybb503372010-05-27 20:51:26 +00007282 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007283 {
7284 /*
7285 Propogate pixel magnify rows.
7286 */
7287 for (j=0; j < magnify; j++)
7288 {
7289 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7290 ((x*ximage->bits_per_pixel) >> 3);
7291 p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
7292 q_bit=0;
7293 byte=0;
7294 for (k=0; k < width; k+=magnify)
7295 {
7296 /*
7297 Propogate pixel magnify columns.
7298 */
7299 for (l=0; l < magnify; l++)
7300 {
7301 /*
7302 Propogate each bit plane.
7303 */
7304 for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
7305 {
7306 byte<<=1;
7307 if (*p & (0x80 >> (p_bit+plane)))
7308 byte|=foreground;
7309 else
7310 byte|=background;
7311 q_bit++;
7312 if (q_bit == 8)
7313 {
7314 *q++=byte;
7315 q_bit=0;
7316 byte=0;
7317 }
7318 }
7319 }
7320 p_bit+=ximage->bits_per_pixel;
7321 if (p_bit == 8)
7322 {
7323 p++;
7324 p_bit=0;
7325 }
7326 if (q_bit != 0)
7327 *q=byte << (8-q_bit);
7328 q+=scanline_pad;
7329 }
7330 }
7331 y++;
7332 }
7333 break;
7334 }
7335 }
7336 }
7337 else
7338 switch (ximage->bits_per_pixel)
7339 {
7340 case 6:
7341 case 8:
7342 {
7343 /*
7344 Magnify 8 bit X image.
7345 */
cristybb503372010-05-27 20:51:26 +00007346 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007347 {
7348 /*
7349 Propogate pixel magnify rows.
7350 */
7351 for (j=0; j < magnify; j++)
7352 {
7353 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7354 ((x*ximage->bits_per_pixel) >> 3);
7355 for (k=0; k < width; k+=magnify)
7356 {
7357 /*
7358 Propogate pixel magnify columns.
7359 */
7360 for (l=0; l < magnify; l++)
7361 *q++=(*p);
7362 p++;
7363 }
7364 q+=scanline_pad;
7365 }
7366 y++;
7367 }
7368 break;
7369 }
7370 default:
7371 {
7372 register unsigned int
7373 bytes_per_pixel,
7374 m;
7375
7376 /*
7377 Magnify multi-byte X image.
7378 */
7379 bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
cristybb503372010-05-27 20:51:26 +00007380 for (i=0; i < (ssize_t) height; i+=magnify)
cristy3ed852e2009-09-05 21:47:34 +00007381 {
7382 /*
7383 Propogate pixel magnify rows.
7384 */
7385 for (j=0; j < magnify; j++)
7386 {
7387 p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
7388 ((x*ximage->bits_per_pixel) >> 3);
7389 for (k=0; k < width; k+=magnify)
7390 {
7391 /*
7392 Propogate pixel magnify columns.
7393 */
7394 for (l=0; l < magnify; l++)
7395 for (m=0; m < bytes_per_pixel; m++)
7396 *q++=(*(p+m));
7397 p+=bytes_per_pixel;
7398 }
7399 q+=scanline_pad;
7400 }
7401 y++;
7402 }
7403 break;
7404 }
7405 }
7406 /*
7407 Copy X image to magnify pixmap.
7408 */
7409 x=windows->magnify.x-((width/magnify) >> 1);
7410 if (x < 0)
7411 x=(int) ((width >> 1)-windows->magnify.x*magnify);
7412 else
7413 if (x > (int) (ximage->width-(width/magnify)))
7414 x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
7415 else
7416 x=0;
7417 y=windows->magnify.y-((height/magnify) >> 1);
7418 if (y < 0)
7419 y=(int) ((height >> 1)-windows->magnify.y*magnify);
7420 else
7421 if (y > (int) (ximage->height-(height/magnify)))
7422 y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
7423 else
7424 y=0;
7425 if ((x != 0) || (y != 0))
7426 (void) XFillRectangle(display,windows->magnify.pixmap,
7427 windows->magnify.annotate_context,0,0,width,height);
7428 (void) XPutImage(display,windows->magnify.pixmap,
7429 windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
7430 height-y);
7431 if ((magnify > 1) && ((magnify <= (width >> 1)) &&
7432 (magnify <= (height >> 1))))
7433 {
7434 RectangleInfo
7435 highlight_info;
7436
7437 /*
7438 Highlight center pixel.
7439 */
cristybb503372010-05-27 20:51:26 +00007440 highlight_info.x=(ssize_t) windows->magnify.width >> 1;
7441 highlight_info.y=(ssize_t) windows->magnify.height >> 1;
cristy3ed852e2009-09-05 21:47:34 +00007442 highlight_info.width=magnify;
7443 highlight_info.height=magnify;
7444 (void) XDrawRectangle(display,windows->magnify.pixmap,
7445 windows->magnify.highlight_context,(int) highlight_info.x,
7446 (int) highlight_info.y,(unsigned int) highlight_info.width-1,
7447 (unsigned int) highlight_info.height-1);
7448 if (magnify > 2)
7449 (void) XDrawRectangle(display,windows->magnify.pixmap,
7450 windows->magnify.annotate_context,(int) highlight_info.x+1,
7451 (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
7452 (unsigned int) highlight_info.height-3);
7453 }
7454 /*
7455 Show center pixel color.
7456 */
cristyc57f6942010-11-12 01:47:39 +00007457 (void) GetOneVirtualMagickPixel(windows->image.image,(ssize_t)
7458 windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,
7459 &windows->image.image->exception);
cristy3ed852e2009-09-05 21:47:34 +00007460 (void) FormatMagickString(tuple,MaxTextExtent,"%d,%d: ",
7461 windows->magnify.x,windows->magnify.y);
7462 (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
7463 ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
7464 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7465 ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
7466 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7467 ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
7468 if (pixel.colorspace == CMYKColorspace)
7469 {
7470 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7471 ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
7472 }
7473 if (pixel.matte != MagickFalse)
7474 {
7475 (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
7476 ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
7477 }
7478 (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
7479 height=(unsigned int) windows->magnify.font_info->ascent+
7480 windows->magnify.font_info->descent;
7481 x=windows->magnify.font_info->max_bounds.width >> 1;
7482 y=windows->magnify.font_info->ascent+(height >> 2);
7483 (void) XDrawImageString(display,windows->magnify.pixmap,
7484 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7485 GetColorTuple(&pixel,MagickTrue,tuple);
7486 y+=height;
7487 (void) XDrawImageString(display,windows->magnify.pixmap,
7488 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7489 (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
7490 &windows->image.image->exception);
7491 y+=height;
7492 (void) XDrawImageString(display,windows->magnify.pixmap,
7493 windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
7494 /*
7495 Refresh magnify window.
7496 */
7497 magnify_window=windows->magnify;
7498 magnify_window.x=0;
7499 magnify_window.y=0;
7500 XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
7501}
7502
7503/*
7504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7505% %
7506% %
7507% %
7508% X M a k e P i x m a p %
7509% %
7510% %
7511% %
7512%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7513%
7514% XMakePixmap() creates an X11 pixmap.
7515%
7516% The format of the XMakePixmap method is:
7517%
7518% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
7519% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
7520% XPixelInfo *pixel)
7521%
7522% A description of each parameter follows:
7523%
7524% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7525%
7526% o display: Specifies a connection to an X server; returned from
7527% XOpenDisplay.
7528%
7529% o window: Specifies a pointer to a XWindowInfo structure.
7530%
cristy3ed852e2009-09-05 21:47:34 +00007531*/
7532static MagickBooleanType XMakePixmap(Display *display,
7533 const XResourceInfo *resource_info,XWindowInfo *window)
7534{
7535 unsigned int
7536 height,
7537 width;
7538
7539 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7540 assert(display != (Display *) NULL);
7541 assert(resource_info != (XResourceInfo *) NULL);
7542 assert(window != (XWindowInfo *) NULL);
7543 if (window->pixmap != (Pixmap) NULL)
7544 {
7545 /*
7546 Destroy previous X pixmap.
7547 */
7548 (void) XFreePixmap(display,window->pixmap);
7549 window->pixmap=(Pixmap) NULL;
7550 }
7551 if (window->use_pixmap == MagickFalse)
7552 return(MagickFalse);
7553 if (window->ximage == (XImage *) NULL)
7554 return(MagickFalse);
7555 /*
7556 Display busy cursor.
7557 */
7558 (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
7559 (void) XFlush(display);
7560 /*
7561 Create pixmap.
7562 */
7563 width=(unsigned int) window->ximage->width;
7564 height=(unsigned int) window->ximage->height;
7565 window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
7566 if (window->pixmap == (Pixmap) NULL)
7567 {
7568 /*
7569 Unable to allocate pixmap.
7570 */
7571 (void) XCheckDefineCursor(display,window->id,window->cursor);
7572 return(MagickFalse);
7573 }
7574 /*
7575 Copy X image to pixmap.
7576 */
7577#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
7578 if (window->shared_memory)
7579 (void) XShmPutImage(display,window->pixmap,window->annotate_context,
7580 window->ximage,0,0,0,0,width,height,MagickTrue);
7581#endif
7582 if (window->shared_memory == MagickFalse)
7583 (void) XPutImage(display,window->pixmap,window->annotate_context,
7584 window->ximage,0,0,0,0,width,height);
7585 if (IsEventLogging())
7586 {
7587 (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
7588 (void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
7589 width,height);
7590 }
7591 /*
7592 Restore cursor.
7593 */
7594 (void) XCheckDefineCursor(display,window->id,window->cursor);
7595 return(MagickTrue);
7596}
7597
7598/*
7599%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7600% %
7601% %
7602% %
7603% X M a k e S t a n d a r d C o l o r m a p %
7604% %
7605% %
7606% %
7607%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7608%
7609% XMakeStandardColormap() creates an X11 Standard Colormap.
7610%
7611% The format of the XMakeStandardColormap method is:
7612%
7613% XMakeStandardColormap(display,visual_info,resource_info,image,
7614% map_info,pixel)
7615%
7616% A description of each parameter follows:
7617%
7618% o display: Specifies a connection to an X server; returned from
7619% XOpenDisplay.
7620%
7621% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
7622% returned from XGetVisualInfo.
7623%
7624% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7625%
7626% o image: the image.
7627%
7628% o map_info: If a Standard Colormap type is specified, this structure is
7629% initialized with info from the Standard Colormap.
7630%
7631% o pixel: Specifies a pointer to a XPixelInfo structure.
7632%
cristy3ed852e2009-09-05 21:47:34 +00007633*/
7634
7635#if defined(__cplusplus) || defined(c_plusplus)
7636extern "C" {
7637#endif
7638
7639static inline MagickRealType DiversityPixelIntensity(
7640 const DiversityPacket *pixel)
7641{
7642 MagickRealType
7643 intensity;
7644
7645 intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
7646 return(intensity);
7647}
7648
7649static int IntensityCompare(const void *x,const void *y)
7650{
7651 DiversityPacket
7652 *color_1,
7653 *color_2;
7654
7655 int
7656 diversity;
7657
7658 color_1=(DiversityPacket *) x;
7659 color_2=(DiversityPacket *) y;
7660 diversity=(int) (DiversityPixelIntensity(color_2)-
7661 DiversityPixelIntensity(color_1));
7662 return(diversity);
7663}
7664
7665static int PopularityCompare(const void *x,const void *y)
7666{
7667 DiversityPacket
7668 *color_1,
7669 *color_2;
7670
7671 color_1=(DiversityPacket *) x;
7672 color_2=(DiversityPacket *) y;
7673 return((int) color_2->count-(int) color_1->count);
7674}
7675
7676#if defined(__cplusplus) || defined(c_plusplus)
7677}
7678#endif
7679
cristybb503372010-05-27 20:51:26 +00007680static inline Quantum ScaleXToQuantum(const size_t x,
7681 const size_t scale)
cristy3ed852e2009-09-05 21:47:34 +00007682{
7683 return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
7684}
7685
7686MagickExport void XMakeStandardColormap(Display *display,
7687 XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
7688 XStandardColormap *map_info,XPixelInfo *pixel)
7689{
7690 Colormap
7691 colormap;
7692
7693 ExceptionInfo
7694 *exception;
7695
7696 register IndexPacket
7697 *indexes;
7698
cristybb503372010-05-27 20:51:26 +00007699 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00007700 i;
7701
7702 Status
7703 status;
7704
cristybb503372010-05-27 20:51:26 +00007705 size_t
cristy3ed852e2009-09-05 21:47:34 +00007706 number_colors,
7707 retain_colors;
7708
7709 unsigned short
7710 gray_value;
7711
7712 XColor
7713 color,
7714 *colors,
7715 *p;
7716
7717 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
7718 assert(display != (Display *) NULL);
7719 assert(visual_info != (XVisualInfo *) NULL);
7720 assert(map_info != (XStandardColormap *) NULL);
7721 assert(resource_info != (XResourceInfo *) NULL);
7722 assert(pixel != (XPixelInfo *) NULL);
7723 exception=(&image->exception);
7724 if (resource_info->map_type != (char *) NULL)
7725 {
7726 /*
7727 Standard Colormap is already defined (i.e. xstdcmap).
7728 */
7729 XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7730 pixel);
7731 number_colors=(unsigned int) (map_info->base_pixel+
7732 (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
7733 if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
7734 if ((image->matte == MagickFalse) &&
7735 (resource_info->color_recovery == MagickFalse) &&
7736 resource_info->quantize_info->dither &&
7737 (number_colors < MaxColormapSize))
7738 {
7739 Image
7740 *affinity_image;
7741
7742 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00007743 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00007744
7745 /*
7746 Improve image appearance with error diffusion.
7747 */
7748 affinity_image=AcquireImage((ImageInfo *) NULL);
7749 if (affinity_image == (Image *) NULL)
7750 ThrowXWindowFatalException(ResourceLimitFatalError,
7751 "UnableToDitherImage",image->filename);
7752 affinity_image->columns=number_colors;
7753 affinity_image->rows=1;
7754 /*
7755 Initialize colormap image.
7756 */
7757 q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
7758 1,exception);
7759 if (q != (PixelPacket *) NULL)
7760 {
cristybb503372010-05-27 20:51:26 +00007761 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007762 {
cristyfba5a8b2011-05-03 17:12:12 +00007763 SetRedPixelComponent(q,0);
cristy3ed852e2009-09-05 21:47:34 +00007764 if (map_info->red_max != 0)
cristyfba5a8b2011-05-03 17:12:12 +00007765 SetRedPixelComponent(q,ScaleXToQuantum((size_t) (i/
7766 map_info->red_mult),map_info->red_max));
7767 SetGreenPixelComponent(q,0);
cristy3ed852e2009-09-05 21:47:34 +00007768 if (map_info->green_max != 0)
cristyfba5a8b2011-05-03 17:12:12 +00007769 SetGreenPixelComponent(q,ScaleXToQuantum((size_t) ((i/
cristy3ed852e2009-09-05 21:47:34 +00007770 map_info->green_mult) % (map_info->green_max+1)),
cristyfba5a8b2011-05-03 17:12:12 +00007771 map_info->green_max));
7772 SetBluePixelComponent(q,0);
cristy3ed852e2009-09-05 21:47:34 +00007773 if (map_info->blue_max != 0)
cristyfba5a8b2011-05-03 17:12:12 +00007774 SetBluePixelComponent(q,ScaleXToQuantum((size_t) (i %
7775 map_info->green_mult),map_info->blue_max));
7776 SetOpacityPixelComponent(q,TransparentOpacity);
cristy3ed852e2009-09-05 21:47:34 +00007777 q++;
7778 }
7779 (void) SyncAuthenticPixels(affinity_image,exception);
7780 (void) RemapImage(resource_info->quantize_info,image,
7781 affinity_image);
7782 }
7783 XGetPixelPacket(display,visual_info,map_info,resource_info,image,
7784 pixel);
7785 (void) SetImageStorageClass(image,DirectClass);
7786 affinity_image=DestroyImage(affinity_image);
7787 }
7788 if (IsEventLogging())
7789 {
7790 (void) LogMagickEvent(X11Event,GetMagickModule(),
7791 "Standard Colormap:");
7792 (void) LogMagickEvent(X11Event,GetMagickModule(),
7793 " colormap id: 0x%lx",map_info->colormap);
7794 (void) LogMagickEvent(X11Event,GetMagickModule(),
7795 " red, green, blue max: %lu %lu %lu",map_info->red_max,
7796 map_info->green_max,map_info->blue_max);
7797 (void) LogMagickEvent(X11Event,GetMagickModule(),
7798 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
7799 map_info->green_mult,map_info->blue_mult);
7800 }
7801 return;
7802 }
7803 if ((visual_info->klass != DirectColor) &&
7804 (visual_info->klass != TrueColor))
7805 if ((image->storage_class == DirectClass) ||
7806 ((int) image->colors > visual_info->colormap_size))
7807 {
7808 QuantizeInfo
7809 quantize_info;
7810
7811 /*
7812 Image has more colors than the visual supports.
7813 */
7814 quantize_info=(*resource_info->quantize_info);
cristybb503372010-05-27 20:51:26 +00007815 quantize_info.number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00007816 (void) QuantizeImage(&quantize_info,image);
7817 }
7818 /*
7819 Free previous and create new colormap.
7820 */
7821 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
7822 colormap=XDefaultColormap(display,visual_info->screen);
7823 if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
7824 colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
7825 visual_info->visual,visual_info->klass == DirectColor ?
7826 AllocAll : AllocNone);
7827 if (colormap == (Colormap) NULL)
7828 ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
7829 image->filename);
7830 /*
7831 Initialize the map and pixel info structures.
7832 */
7833 XGetMapInfo(visual_info,colormap,map_info);
7834 XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
7835 /*
7836 Allocating colors in server colormap is based on visual class.
7837 */
7838 switch (visual_info->klass)
7839 {
7840 case StaticGray:
7841 case StaticColor:
7842 {
7843 /*
7844 Define Standard Colormap for StaticGray or StaticColor visual.
7845 */
7846 number_colors=image->colors;
7847 colors=(XColor *) AcquireQuantumMemory((size_t)
7848 visual_info->colormap_size,sizeof(*colors));
7849 if (colors == (XColor *) NULL)
7850 ThrowXWindowFatalException(ResourceLimitFatalError,
7851 "UnableToCreateColormap",image->filename);
7852 p=colors;
7853 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007854 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007855 {
7856 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
7857 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
7858 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
7859 if (visual_info->klass != StaticColor)
7860 {
7861 gray_value=(unsigned short) XPixelIntensity(&color);
7862 color.red=gray_value;
7863 color.green=gray_value;
7864 color.blue=gray_value;
7865 }
7866 status=XAllocColor(display,colormap,&color);
7867 if (status == False)
7868 {
7869 colormap=XCopyColormapAndFree(display,colormap);
7870 (void) XAllocColor(display,colormap,&color);
7871 }
7872 pixel->pixels[i]=color.pixel;
7873 *p++=color;
7874 }
7875 break;
7876 }
7877 case GrayScale:
7878 case PseudoColor:
7879 {
7880 unsigned int
7881 colormap_type;
7882
7883 /*
7884 Define Standard Colormap for GrayScale or PseudoColor visual.
7885 */
7886 number_colors=image->colors;
7887 colors=(XColor *) AcquireQuantumMemory((size_t)
7888 visual_info->colormap_size,sizeof(*colors));
7889 if (colors == (XColor *) NULL)
7890 ThrowXWindowFatalException(ResourceLimitFatalError,
7891 "UnableToCreateColormap",image->filename);
7892 /*
7893 Preallocate our GUI colors.
7894 */
7895 (void) XAllocColor(display,colormap,&pixel->foreground_color);
7896 (void) XAllocColor(display,colormap,&pixel->background_color);
7897 (void) XAllocColor(display,colormap,&pixel->border_color);
7898 (void) XAllocColor(display,colormap,&pixel->matte_color);
7899 (void) XAllocColor(display,colormap,&pixel->highlight_color);
7900 (void) XAllocColor(display,colormap,&pixel->shadow_color);
7901 (void) XAllocColor(display,colormap,&pixel->depth_color);
7902 (void) XAllocColor(display,colormap,&pixel->trough_color);
7903 for (i=0; i < MaxNumberPens; i++)
7904 (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
7905 /*
7906 Determine if image colors will "fit" into X server colormap.
7907 */
7908 colormap_type=resource_info->colormap;
cristyf2faecf2010-05-28 19:19:36 +00007909 status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
cristy3ed852e2009-09-05 21:47:34 +00007910 NULL,0,pixel->pixels,(unsigned int) image->colors);
7911 if (status != False)
7912 colormap_type=PrivateColormap;
7913 if (colormap_type == SharedColormap)
7914 {
cristyc57f6942010-11-12 01:47:39 +00007915 CacheView
7916 *image_view;
7917
cristy3ed852e2009-09-05 21:47:34 +00007918 DiversityPacket
7919 *diversity;
7920
7921 int
7922 y;
7923
7924 register int
7925 x;
7926
7927 unsigned short
7928 index;
7929
7930 XColor
7931 *server_colors;
7932
7933 /*
7934 Define Standard colormap for shared GrayScale or PseudoColor visual.
7935 */
7936 diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
7937 sizeof(*diversity));
7938 if (diversity == (DiversityPacket *) NULL)
7939 ThrowXWindowFatalException(ResourceLimitFatalError,
7940 "UnableToCreateColormap",image->filename);
cristybb503372010-05-27 20:51:26 +00007941 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007942 {
7943 diversity[i].red=image->colormap[i].red;
7944 diversity[i].green=image->colormap[i].green;
7945 diversity[i].blue=image->colormap[i].blue;
7946 diversity[i].index=(unsigned short) i;
7947 diversity[i].count=0;
7948 }
cristyc57f6942010-11-12 01:47:39 +00007949 image_view=AcquireCacheView(image);
cristy3ed852e2009-09-05 21:47:34 +00007950 for (y=0; y < (int) image->rows; y++)
7951 {
cristyc57f6942010-11-12 01:47:39 +00007952 register int
cristy3ed852e2009-09-05 21:47:34 +00007953 x;
7954
cristyc57f6942010-11-12 01:47:39 +00007955 register const PixelPacket
7956 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00007957
cristyc57f6942010-11-12 01:47:39 +00007958 p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
7959 image->columns,1,exception);
7960 if (p == (const PixelPacket *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00007961 break;
cristyc57f6942010-11-12 01:47:39 +00007962 indexes=GetCacheViewAuthenticIndexQueue(image_view);
7963 for (x=(int) image->columns-1; x >= 0; x--)
cristyfba5a8b2011-05-03 17:12:12 +00007964 diversity[(ssize_t) GetIndexPixelComponent(indexes+x)].count++;
cristy3ed852e2009-09-05 21:47:34 +00007965 }
cristyc57f6942010-11-12 01:47:39 +00007966 image_view=DestroyCacheView(image_view);
cristy3ed852e2009-09-05 21:47:34 +00007967 /*
7968 Sort colors by decreasing intensity.
7969 */
7970 qsort((void *) diversity,image->colors,sizeof(*diversity),
7971 IntensityCompare);
cristybb503372010-05-27 20:51:26 +00007972 for (i=0; i < (ssize_t) image->colors; )
cristy3ed852e2009-09-05 21:47:34 +00007973 {
7974 diversity[i].count<<=4; /* increase this colors popularity */
cristydfe2b662010-08-22 16:17:24 +00007975 i+=MagickMax((int) (image->colors >> 4),2);
cristy3ed852e2009-09-05 21:47:34 +00007976 }
7977 diversity[image->colors-1].count<<=4;
7978 qsort((void *) diversity,image->colors,sizeof(*diversity),
7979 PopularityCompare);
7980 /*
7981 Allocate colors.
7982 */
7983 p=colors;
7984 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00007985 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00007986 {
7987 index=diversity[i].index;
7988 color.red=
7989 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
7990 color.green=
7991 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
7992 color.blue=
7993 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
7994 if (visual_info->klass != PseudoColor)
7995 {
7996 gray_value=(unsigned short) XPixelIntensity(&color);
7997 color.red=gray_value;
7998 color.green=gray_value;
7999 color.blue=gray_value;
8000 }
8001 status=XAllocColor(display,colormap,&color);
8002 if (status == False)
8003 break;
8004 pixel->pixels[index]=color.pixel;
8005 *p++=color;
8006 }
8007 /*
8008 Read X server colormap.
8009 */
8010 server_colors=(XColor *) AcquireQuantumMemory((size_t)
8011 visual_info->colormap_size,sizeof(*server_colors));
8012 if (server_colors == (XColor *) NULL)
8013 ThrowXWindowFatalException(ResourceLimitFatalError,
8014 "UnableToCreateColormap",image->filename);
8015 for (x=visual_info->colormap_size-1; x >= 0; x--)
cristybb503372010-05-27 20:51:26 +00008016 server_colors[x].pixel=(size_t) x;
cristy3ed852e2009-09-05 21:47:34 +00008017 (void) XQueryColors(display,colormap,server_colors,
8018 (int) MagickMin((unsigned int) visual_info->colormap_size,256));
8019 /*
8020 Select remaining colors from X server colormap.
8021 */
cristybb503372010-05-27 20:51:26 +00008022 for (; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008023 {
8024 index=diversity[i].index;
8025 color.red=
8026 ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
8027 color.green=
8028 ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
8029 color.blue=
8030 ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
8031 if (visual_info->klass != PseudoColor)
8032 {
8033 gray_value=(unsigned short) XPixelIntensity(&color);
8034 color.red=gray_value;
8035 color.green=gray_value;
8036 color.blue=gray_value;
8037 }
8038 XBestPixel(display,colormap,server_colors,(unsigned int)
8039 visual_info->colormap_size,&color);
8040 pixel->pixels[index]=color.pixel;
8041 *p++=color;
8042 }
8043 if ((int) image->colors < visual_info->colormap_size)
8044 {
8045 /*
8046 Fill up colors array-- more choices for pen colors.
8047 */
8048 retain_colors=MagickMin((unsigned int)
8049 (visual_info->colormap_size-image->colors),256);
cristybb503372010-05-27 20:51:26 +00008050 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008051 *p++=server_colors[i];
8052 number_colors+=retain_colors;
8053 }
8054 server_colors=(XColor *) RelinquishMagickMemory(server_colors);
8055 diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
8056 break;
8057 }
8058 /*
8059 Define Standard colormap for private GrayScale or PseudoColor visual.
8060 */
8061 if (status == False)
8062 {
8063 /*
8064 Not enough colormap entries in the colormap-- Create a new colormap.
8065 */
8066 colormap=XCreateColormap(display,
8067 XRootWindow(display,visual_info->screen),visual_info->visual,
8068 AllocNone);
8069 if (colormap == (Colormap) NULL)
8070 ThrowXWindowFatalException(ResourceLimitFatalError,
8071 "UnableToCreateColormap",image->filename);
8072 map_info->colormap=colormap;
8073 if ((int) image->colors < visual_info->colormap_size)
8074 {
8075 /*
8076 Retain colors from the default colormap to help lessens the
8077 effects of colormap flashing.
8078 */
8079 retain_colors=MagickMin((unsigned int)
8080 (visual_info->colormap_size-image->colors),256);
8081 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008082 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008083 {
cristyc57f6942010-11-12 01:47:39 +00008084 p->pixel=(unsigned long) i;
cristy3ed852e2009-09-05 21:47:34 +00008085 p++;
8086 }
8087 (void) XQueryColors(display,
8088 XDefaultColormap(display,visual_info->screen),
8089 colors+image->colors,(int) retain_colors);
8090 /*
8091 Transfer colors from default to private colormap.
8092 */
8093 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008094 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008095 retain_colors);
8096 p=colors+image->colors;
cristybb503372010-05-27 20:51:26 +00008097 for (i=0; i < (ssize_t) retain_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008098 {
8099 p->pixel=pixel->pixels[i];
8100 p++;
8101 }
8102 (void) XStoreColors(display,colormap,colors+image->colors,
8103 (int) retain_colors);
8104 number_colors+=retain_colors;
8105 }
8106 (void) XAllocColorCells(display,colormap,MagickFalse,
cristyf2faecf2010-05-28 19:19:36 +00008107 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
cristy3ed852e2009-09-05 21:47:34 +00008108 image->colors);
8109 }
8110 /*
8111 Store the image colormap.
8112 */
8113 p=colors;
8114 color.flags=(char) (DoRed | DoGreen | DoBlue);
cristybb503372010-05-27 20:51:26 +00008115 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008116 {
8117 color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
8118 color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
8119 color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
8120 if (visual_info->klass != PseudoColor)
8121 {
8122 gray_value=(unsigned short) XPixelIntensity(&color);
8123 color.red=gray_value;
8124 color.green=gray_value;
8125 color.blue=gray_value;
8126 }
8127 color.pixel=pixel->pixels[i];
8128 *p++=color;
8129 }
8130 (void) XStoreColors(display,colormap,colors,(int) image->colors);
8131 break;
8132 }
8133 case TrueColor:
8134 case DirectColor:
8135 default:
8136 {
8137 MagickBooleanType
8138 linear_colormap;
8139
8140 /*
8141 Define Standard Colormap for TrueColor or DirectColor visual.
8142 */
8143 number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
8144 (map_info->green_max*map_info->green_mult)+
8145 (map_info->blue_max*map_info->blue_mult)+1);
8146 linear_colormap=(number_colors > 4096) ||
8147 (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
8148 ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
8149 ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
8150 MagickTrue : MagickFalse;
8151 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008152 number_colors=(size_t) visual_info->colormap_size;
cristy3ed852e2009-09-05 21:47:34 +00008153 /*
8154 Allocate color array.
8155 */
8156 colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
8157 if (colors == (XColor *) NULL)
8158 ThrowXWindowFatalException(ResourceLimitFatalError,
8159 "UnableToCreateColormap",image->filename);
8160 /*
8161 Initialize linear color ramp.
8162 */
8163 p=colors;
8164 color.flags=(char) (DoRed | DoGreen | DoBlue);
8165 if (linear_colormap != MagickFalse)
cristybb503372010-05-27 20:51:26 +00008166 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008167 {
8168 color.blue=(unsigned short) 0;
8169 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008170 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008171 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8172 color.green=color.blue;
8173 color.red=color.blue;
8174 color.pixel=XStandardPixel(map_info,&color);
8175 *p++=color;
8176 }
8177 else
cristybb503372010-05-27 20:51:26 +00008178 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008179 {
8180 color.red=(unsigned short) 0;
8181 if (map_info->red_max != 0)
cristybb503372010-05-27 20:51:26 +00008182 color.red=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008183 ((65535L*(i/map_info->red_mult))/map_info->red_max));
8184 color.green=(unsigned int) 0;
8185 if (map_info->green_max != 0)
cristybb503372010-05-27 20:51:26 +00008186 color.green=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008187 ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
8188 map_info->green_max));
8189 color.blue=(unsigned short) 0;
8190 if (map_info->blue_max != 0)
cristybb503372010-05-27 20:51:26 +00008191 color.blue=(unsigned short) ((size_t)
cristy3ed852e2009-09-05 21:47:34 +00008192 ((65535L*(i % map_info->green_mult))/map_info->blue_max));
8193 color.pixel=XStandardPixel(map_info,&color);
8194 *p++=color;
8195 }
8196 if ((visual_info->klass == DirectColor) &&
8197 (colormap != XDefaultColormap(display,visual_info->screen)))
8198 (void) XStoreColors(display,colormap,colors,(int) number_colors);
8199 else
cristybb503372010-05-27 20:51:26 +00008200 for (i=0; i < (ssize_t) number_colors; i++)
cristy3ed852e2009-09-05 21:47:34 +00008201 (void) XAllocColor(display,colormap,&colors[i]);
8202 break;
8203 }
8204 }
8205 if ((visual_info->klass != DirectColor) &&
8206 (visual_info->klass != TrueColor))
8207 {
8208 /*
8209 Set foreground, background, border, etc. pixels.
8210 */
8211 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8212 &pixel->foreground_color);
8213 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8214 &pixel->background_color);
8215 if (pixel->background_color.pixel == pixel->foreground_color.pixel)
8216 {
8217 /*
8218 Foreground and background colors must differ.
8219 */
8220 pixel->background_color.red=(~pixel->foreground_color.red);
8221 pixel->background_color.green=
8222 (~pixel->foreground_color.green);
8223 pixel->background_color.blue=
8224 (~pixel->foreground_color.blue);
8225 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8226 &pixel->background_color);
8227 }
8228 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8229 &pixel->border_color);
8230 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8231 &pixel->matte_color);
8232 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8233 &pixel->highlight_color);
8234 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8235 &pixel->shadow_color);
8236 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8237 &pixel->depth_color);
8238 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8239 &pixel->trough_color);
8240 for (i=0; i < MaxNumberPens; i++)
8241 {
8242 XBestPixel(display,colormap,colors,(unsigned int) number_colors,
8243 &pixel->pen_colors[i]);
8244 pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
8245 }
cristyc57f6942010-11-12 01:47:39 +00008246 pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
cristy3ed852e2009-09-05 21:47:34 +00008247 }
8248 colors=(XColor *) RelinquishMagickMemory(colors);
8249 if (IsEventLogging())
8250 {
8251 (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
8252 (void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
8253 map_info->colormap);
8254 (void) LogMagickEvent(X11Event,GetMagickModule(),
8255 " red, green, blue max: %lu %lu %lu",map_info->red_max,
8256 map_info->green_max,map_info->blue_max);
8257 (void) LogMagickEvent(X11Event,GetMagickModule(),
8258 " red, green, blue mult: %lu %lu %lu",map_info->red_mult,
8259 map_info->green_mult,map_info->blue_mult);
8260 }
8261}
8262
8263/*
8264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8265% %
8266% %
8267% %
8268% X M a k e W i n d o w %
8269% %
8270% %
8271% %
8272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8273%
8274% XMakeWindow() creates an X11 window.
8275%
8276% The format of the XMakeWindow method is:
8277%
8278% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
8279% XClassHint *class_hint,XWMHints *manager_hints,
8280% XWindowInfo *window_info)
8281%
8282% A description of each parameter follows:
8283%
8284% o display: Specifies a connection to an X server; returned from
8285% XOpenDisplay.
8286%
8287% o parent: Specifies the parent window_info.
8288%
8289% o argv: Specifies the application's argument list.
8290%
8291% o argc: Specifies the number of arguments.
8292%
8293% o class_hint: Specifies a pointer to a X11 XClassHint structure.
8294%
8295% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
8296%
8297% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
8298%
8299*/
8300MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
8301 int argc,XClassHint *class_hint,XWMHints *manager_hints,
8302 XWindowInfo *window_info)
8303{
8304#define MinWindowSize 64
8305
8306 Atom
8307 atom_list[2];
8308
8309 int
8310 gravity;
8311
8312 static XTextProperty
8313 icon_name,
8314 window_name;
8315
8316 Status
8317 status;
8318
8319 XSizeHints
8320 *size_hints;
8321
8322 /*
8323 Set window info hints.
8324 */
8325 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8326 assert(display != (Display *) NULL);
8327 assert(window_info != (XWindowInfo *) NULL);
8328 size_hints=XAllocSizeHints();
8329 if (size_hints == (XSizeHints *) NULL)
8330 ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
cristydfe2b662010-08-22 16:17:24 +00008331 size_hints->flags=(int) window_info->flags;
cristy3ed852e2009-09-05 21:47:34 +00008332 size_hints->x=window_info->x;
8333 size_hints->y=window_info->y;
8334 size_hints->width=(int) window_info->width;
8335 size_hints->height=(int) window_info->height;
8336 if (window_info->immutable != MagickFalse)
8337 {
8338 /*
8339 Window size cannot be changed.
8340 */
8341 size_hints->min_width=size_hints->width;
8342 size_hints->min_height=size_hints->height;
8343 size_hints->max_width=size_hints->width;
8344 size_hints->max_height=size_hints->height;
8345 size_hints->flags|=PMinSize;
8346 size_hints->flags|=PMaxSize;
8347 }
8348 else
8349 {
8350 /*
8351 Window size can be changed.
8352 */
8353 size_hints->min_width=(int) window_info->min_width;
8354 size_hints->min_height=(int) window_info->min_height;
8355 size_hints->flags|=PResizeInc;
8356 size_hints->width_inc=(int) window_info->width_inc;
8357 size_hints->height_inc=(int) window_info->height_inc;
8358#if !defined(PRE_R4_ICCCM)
8359 size_hints->flags|=PBaseSize;
8360 size_hints->base_width=size_hints->width_inc;
8361 size_hints->base_height=size_hints->height_inc;
8362#endif
8363 }
8364 gravity=NorthWestGravity;
8365 if (window_info->geometry != (char *) NULL)
8366 {
8367 char
8368 default_geometry[MaxTextExtent],
8369 geometry[MaxTextExtent];
8370
8371 int
8372 flags;
8373
8374 register char
8375 *p;
8376
8377 /*
8378 User specified geometry.
8379 */
8380 (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
8381 size_hints->width,size_hints->height);
8382 (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
8383 p=geometry;
8384 while (strlen(p) != 0)
8385 {
8386 if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
8387 p++;
8388 else
8389 (void) CopyMagickString(p,p+1,MaxTextExtent);
8390 }
8391 flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
8392 window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
8393 &size_hints->width,&size_hints->height,&gravity);
8394 if ((flags & WidthValue) && (flags & HeightValue))
8395 size_hints->flags|=USSize;
8396 if ((flags & XValue) && (flags & YValue))
8397 {
8398 size_hints->flags|=USPosition;
8399 window_info->x=size_hints->x;
8400 window_info->y=size_hints->y;
8401 }
8402 }
8403#if !defined(PRE_R4_ICCCM)
8404 size_hints->win_gravity=gravity;
8405 size_hints->flags|=PWinGravity;
8406#endif
8407 if (window_info->id == (Window) NULL)
8408 window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
8409 (unsigned int) size_hints->width,(unsigned int) size_hints->height,
8410 window_info->border_width,(int) window_info->depth,InputOutput,
cristyc57f6942010-11-12 01:47:39 +00008411 window_info->visual,(unsigned long) window_info->mask,
8412 &window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008413 else
8414 {
8415 MagickStatusType
8416 mask;
8417
8418 XEvent
8419 sans_event;
8420
8421 XWindowChanges
8422 window_changes;
8423
8424 /*
8425 Window already exists; change relevant attributes.
8426 */
cristyc57f6942010-11-12 01:47:39 +00008427 (void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
8428 window_info->mask,&window_info->attributes);
cristy3ed852e2009-09-05 21:47:34 +00008429 mask=ConfigureNotify;
8430 while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
8431 window_changes.x=window_info->x;
8432 window_changes.y=window_info->y;
8433 window_changes.width=(int) window_info->width;
8434 window_changes.height=(int) window_info->height;
8435 mask=(MagickStatusType) (CWWidth | CWHeight);
8436 if (window_info->flags & USPosition)
8437 mask|=CWX | CWY;
8438 (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
8439 mask,&window_changes);
8440 }
8441 if (window_info->id == (Window) NULL)
8442 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
8443 window_info->name);
8444 status=XStringListToTextProperty(&window_info->name,1,&window_name);
8445 if (status == False)
8446 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8447 window_info->name);
8448 status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
8449 if (status == False)
8450 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
8451 window_info->icon_name);
8452 if (window_info->icon_geometry != (char *) NULL)
8453 {
8454 int
8455 flags,
8456 height,
8457 width;
8458
8459 /*
8460 User specified icon geometry.
8461 */
8462 size_hints->flags|=USPosition;
8463 flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
8464 (char *) NULL,0,size_hints,&manager_hints->icon_x,
8465 &manager_hints->icon_y,&width,&height,&gravity);
8466 if ((flags & XValue) && (flags & YValue))
8467 manager_hints->flags|=IconPositionHint;
8468 }
8469 XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
8470 size_hints,manager_hints,class_hint);
8471 if (window_name.value != (void *) NULL)
8472 {
8473 (void) XFree((void *) window_name.value);
8474 window_name.value=(unsigned char *) NULL;
8475 window_name.nitems=0;
8476 }
8477 if (icon_name.value != (void *) NULL)
8478 {
8479 (void) XFree((void *) icon_name.value);
8480 icon_name.value=(unsigned char *) NULL;
8481 icon_name.nitems=0;
8482 }
8483 atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
8484 atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
8485 (void) XSetWMProtocols(display,window_info->id,atom_list,2);
8486 (void) XFree((void *) size_hints);
8487 if (window_info->shape != MagickFalse)
8488 {
8489#if defined(MAGICKCORE_HAVE_SHAPE)
8490 int
8491 error_base,
8492 event_base;
8493
8494 /*
8495 Can we apply a non-rectangular shaping mask?
8496 */
8497 error_base=0;
8498 event_base=0;
8499 if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
8500 window_info->shape=MagickFalse;
8501#else
8502 window_info->shape=MagickFalse;
8503#endif
8504 }
8505 if (window_info->shared_memory)
8506 {
8507#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8508 /*
8509 Can we use shared memory with this window?
8510 */
8511 if (XShmQueryExtension(display) == 0)
8512 window_info->shared_memory=MagickFalse;
8513#else
8514 window_info->shared_memory=MagickFalse;
8515#endif
8516 }
8517 window_info->image=NewImageList();
8518 window_info->destroy=MagickFalse;
8519}
8520
8521/*
8522%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8523% %
8524% %
8525% %
8526% X M a g i c k P r o g r e s s M o n i t o r %
8527% %
8528% %
8529% %
8530%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8531%
8532% XMagickProgressMonitor() displays the progress a task is making in
8533% completing a task.
8534%
8535% The format of the XMagickProgressMonitor method is:
8536%
8537% void XMagickProgressMonitor(const char *task,
8538% const MagickOffsetType quantum,const MagickSizeType span,
8539% void *client_data)
8540%
8541% A description of each parameter follows:
8542%
8543% o task: Identifies the task in progress.
8544%
8545% o quantum: Specifies the quantum position within the span which represents
8546% how much progress has been made in completing a task.
8547%
8548% o span: Specifies the span relative to completing a task.
8549%
8550% o client_data: Pointer to any client data.
8551%
8552*/
8553
8554static const char *GetLocaleMonitorMessage(const char *text)
8555{
8556 char
8557 message[MaxTextExtent],
8558 tag[MaxTextExtent];
8559
8560 const char
8561 *locale_message;
8562
8563 register char
8564 *p;
8565
8566 (void) CopyMagickMemory(tag,text,MaxTextExtent);
8567 p=strrchr(tag,'/');
8568 if (p != (char *) NULL)
8569 *p='\0';
8570 (void) FormatMagickString(message,MaxTextExtent,"Monitor/%s",tag);
8571 locale_message=GetLocaleMessage(message);
8572 if (locale_message == message)
8573 return(text);
8574 return(locale_message);
8575}
8576
8577MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
8578 const MagickOffsetType quantum,const MagickSizeType span,
8579 void *magick_unused(client_data))
8580{
8581 XWindows
8582 *windows;
8583
8584 windows=XSetWindows((XWindows *) ~0);
8585 if (windows == (XWindows *) NULL)
8586 return(MagickTrue);
8587 if (windows->info.mapped != MagickFalse)
8588 XProgressMonitorWidget(windows->display,windows,
8589 GetLocaleMonitorMessage(tag),quantum,span);
8590 return(MagickTrue);
8591}
8592
8593/*
8594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8595% %
8596% %
8597% %
8598% X Q u e r y C o l o r D a t a b a s e %
8599% %
8600% %
8601% %
8602%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8603%
8604% XQueryColorDatabase() looks up a RGB values for a color given in the target
8605% string.
8606%
8607% The format of the XQueryColorDatabase method is:
8608%
8609% MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
8610%
8611% A description of each parameter follows:
8612%
8613% o target: Specifies the color to lookup in the X color database.
8614%
8615% o color: A pointer to an PixelPacket structure. The RGB value of the target
8616% color is returned as this value.
8617%
8618*/
8619MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
8620 XColor *color)
8621{
8622 Colormap
8623 colormap;
8624
8625 static Display
8626 *display = (Display *) NULL;
8627
8628 Status
8629 status;
8630
8631 XColor
8632 xcolor;
8633
8634 /*
8635 Initialize color return value.
8636 */
8637 assert(color != (XColor *) NULL);
8638 color->red=0;
8639 color->green=0;
8640 color->blue=0;
8641 color->flags=(char) (DoRed | DoGreen | DoBlue);
8642 if ((target == (char *) NULL) || (*target == '\0'))
8643 target="#ffffffffffff";
8644 /*
8645 Let the X server define the color for us.
8646 */
8647 if (display == (Display *) NULL)
8648 display=XOpenDisplay((char *) NULL);
8649 if (display == (Display *) NULL)
8650 {
8651 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
8652 return(MagickFalse);
8653 }
8654 colormap=XDefaultColormap(display,XDefaultScreen(display));
8655 status=XParseColor(display,colormap,(char *) target,&xcolor);
8656 if (status == False)
8657 ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
8658 else
8659 {
8660 color->red=xcolor.red;
8661 color->green=xcolor.green;
8662 color->blue=xcolor.blue;
8663 color->flags=xcolor.flags;
8664 }
8665 return(status != False ? MagickTrue : MagickFalse);
8666}
8667
8668/*
8669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8670% %
8671% %
8672% %
8673% X Q u e r y P o s i t i o n %
8674% %
8675% %
8676% %
8677%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8678%
8679% XQueryPosition() gets the pointer coordinates relative to a window.
8680%
8681% The format of the XQueryPosition method is:
8682%
8683% void XQueryPosition(Display *display,const Window window,int *x,int *y)
8684%
8685% A description of each parameter follows:
8686%
8687% o display: Specifies a connection to an X server; returned from
8688% XOpenDisplay.
8689%
8690% o window: Specifies a pointer to a Window.
8691%
8692% o x: Return the x coordinate of the pointer relative to the origin of the
8693% window.
8694%
8695% o y: Return the y coordinate of the pointer relative to the origin of the
8696% window.
8697%
8698*/
8699MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
8700{
8701 int
8702 x_root,
8703 y_root;
8704
8705 unsigned int
8706 mask;
8707
8708 Window
8709 root_window;
8710
8711 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8712 assert(display != (Display *) NULL);
8713 assert(window != (Window) NULL);
8714 assert(x != (int *) NULL);
8715 assert(y != (int *) NULL);
8716 (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
8717 x,y,&mask);
8718}
8719
8720/*
8721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8722% %
8723% %
8724% %
8725% X R e f r e s h W i n d o w %
8726% %
8727% %
8728% %
8729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8730%
8731% XRefreshWindow() refreshes an image in a X window.
8732%
8733% The format of the XRefreshWindow method is:
8734%
8735% void XRefreshWindow(Display *display,const XWindowInfo *window,
8736% const XEvent *event)
8737%
8738% A description of each parameter follows:
8739%
8740% o display: Specifies a connection to an X server; returned from
8741% XOpenDisplay.
8742%
8743% o window: Specifies a pointer to a XWindowInfo structure.
8744%
8745% o event: Specifies a pointer to a XEvent structure. If it is NULL,
8746% the entire image is refreshed.
8747%
8748*/
8749MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
8750 const XEvent *event)
8751{
8752 int
8753 x,
8754 y;
8755
8756 unsigned int
8757 height,
8758 width;
8759
8760 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8761 assert(display != (Display *) NULL);
8762 assert(window != (XWindowInfo *) NULL);
8763 if (window->ximage == (XImage *) NULL)
8764 return;
8765 if (event != (XEvent *) NULL)
8766 {
8767 /*
8768 Determine geometry from expose event.
8769 */
8770 x=event->xexpose.x;
8771 y=event->xexpose.y;
8772 width=(unsigned int) event->xexpose.width;
8773 height=(unsigned int) event->xexpose.height;
8774 }
8775 else
8776 {
8777 XEvent
8778 sans_event;
8779
8780 /*
8781 Refresh entire window; discard outstanding expose events.
8782 */
8783 x=0;
8784 y=0;
8785 width=window->width;
8786 height=window->height;
8787 while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
cristya0e5ad52010-02-10 02:05:12 +00008788 if (window->matte_pixmap != (Pixmap) NULL)
8789 {
8790#if defined(MAGICKCORE_HAVE_SHAPE)
8791 if (window->shape != MagickFalse)
8792 XShapeCombineMask(display,window->id,ShapeBounding,0,0,
8793 window->matte_pixmap,ShapeSet);
8794#endif
8795 }
cristy3ed852e2009-09-05 21:47:34 +00008796 }
8797 /*
8798 Check boundary conditions.
8799 */
8800 if ((window->ximage->width-(x+window->x)) < (int) width)
8801 width=(unsigned int) (window->ximage->width-(x+window->x));
8802 if ((window->ximage->height-(y+window->y)) < (int) height)
8803 height=(unsigned int) (window->ximage->height-(y+window->y));
8804 /*
8805 Refresh image.
8806 */
8807 if (window->matte_pixmap != (Pixmap) NULL)
cristya0e5ad52010-02-10 02:05:12 +00008808 (void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
cristy3ed852e2009-09-05 21:47:34 +00008809 if (window->pixmap != (Pixmap) NULL)
8810 {
8811 if (window->depth > 1)
8812 (void) XCopyArea(display,window->pixmap,window->id,
8813 window->annotate_context,x+window->x,y+window->y,width,height,x,y);
8814 else
8815 (void) XCopyPlane(display,window->pixmap,window->id,
8816 window->highlight_context,x+window->x,y+window->y,width,height,x,y,
8817 1L);
8818 }
8819 else
8820 {
8821#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
8822 if (window->shared_memory)
8823 (void) XShmPutImage(display,window->id,window->annotate_context,
8824 window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
8825#endif
8826 if (window->shared_memory == MagickFalse)
8827 (void) XPutImage(display,window->id,window->annotate_context,
8828 window->ximage,x+window->x,y+window->y,x,y,width,height);
8829 }
8830 if (window->matte_pixmap != (Pixmap) NULL)
8831 (void) XSetClipMask(display,window->annotate_context,None);
8832 (void) XFlush(display);
8833}
8834
8835/*
8836%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8837% %
8838% %
8839% %
8840% X R e m o t e C o m m a n d %
8841% %
8842% %
8843% %
8844%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8845%
8846% XRemoteCommand() forces a remote display(1) to display the specified
8847% image filename.
8848%
8849% The format of the XRemoteCommand method is:
8850%
8851% MagickBooleanType XRemoteCommand(Display *display,const char *window,
8852% const char *filename)
8853%
8854% A description of each parameter follows:
8855%
8856% o display: Specifies a connection to an X server; returned from
8857% XOpenDisplay.
8858%
8859% o window: Specifies the name or id of an X window.
8860%
8861% o filename: the name of the image filename to display.
8862%
8863*/
8864MagickExport MagickBooleanType XRemoteCommand(Display *display,
8865 const char *window,const char *filename)
8866{
8867 Atom
8868 remote_atom;
8869
8870 Window
8871 remote_window,
8872 root_window;
8873
8874 assert(filename != (char *) NULL);
8875 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
8876 if (display == (Display *) NULL)
8877 display=XOpenDisplay((char *) NULL);
8878 if (display == (Display *) NULL)
8879 {
8880 ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
8881 return(MagickFalse);
8882 }
8883 remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
8884 remote_window=(Window) NULL;
8885 root_window=XRootWindow(display,XDefaultScreen(display));
8886 if (window != (char *) NULL)
8887 {
8888 /*
8889 Search window hierarchy and identify any clients by name or ID.
8890 */
8891 if (isdigit((unsigned char) *window) != 0)
8892 remote_window=XWindowByID(display,root_window,(Window)
8893 strtol((char *) window,(char **) NULL,0));
8894 if (remote_window == (Window) NULL)
8895 remote_window=XWindowByName(display,root_window,window);
8896 }
8897 if (remote_window == (Window) NULL)
8898 remote_window=XWindowByProperty(display,root_window,remote_atom);
8899 if (remote_window == (Window) NULL)
8900 {
8901 ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
8902 filename);
8903 return(MagickFalse);
8904 }
8905 /*
8906 Send remote command.
8907 */
8908 remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
8909 (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
8910 PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
8911 (void) XSync(display,MagickFalse);
8912 return(MagickTrue);
8913}
8914
8915/*
8916%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8917% %
8918% %
8919% %
8920% X R e t a i n W i n d o w C o l o r s %
8921% %
8922% %
8923% %
8924%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8925%
8926% XRetainWindowColors() sets X11 color resources on a window. This preserves
8927% the colors associated with an image displayed on the window.
8928%
8929% The format of the XRetainWindowColors method is:
8930%
8931% void XRetainWindowColors(Display *display,const Window window)
8932%
8933% A description of each parameter follows:
8934%
8935% o display: Specifies a connection to an X server; returned from
8936% XOpenDisplay.
8937%
8938% o window: Specifies a pointer to a XWindowInfo structure.
8939%
8940*/
8941MagickExport void XRetainWindowColors(Display *display,const Window window)
8942{
8943 Atom
8944 property;
8945
8946 Pixmap
8947 pixmap;
8948
8949 /*
8950 Put property on the window.
8951 */
8952 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
8953 assert(display != (Display *) NULL);
8954 assert(window != (Window) NULL);
8955 property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
8956 if (property == (Atom) NULL)
8957 {
8958 ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
8959 "_XSETROOT_ID");
8960 return;
8961 }
8962 pixmap=XCreatePixmap(display,window,1,1,1);
8963 if (pixmap == (Pixmap) NULL)
8964 {
8965 ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
8966 return;
8967 }
8968 (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
8969 (unsigned char *) &pixmap,1);
8970 (void) XSetCloseDownMode(display,RetainPermanent);
8971}
8972
8973/*
8974%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8975% %
8976% %
8977% %
8978% X S e l e c t W i n d o w %
8979% %
8980% %
8981% %
8982%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8983%
8984% XSelectWindow() allows a user to select a window using the mouse. If the
8985% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
8986% is returned in the crop_info structure.
8987%
8988% The format of the XSelectWindow function is:
8989%
8990% target_window=XSelectWindow(display,crop_info)
8991%
8992% A description of each parameter follows:
8993%
8994% o window: XSelectWindow returns the window id.
8995%
8996% o display: Specifies a pointer to the Display structure; returned from
8997% XOpenDisplay.
8998%
8999% o crop_info: Specifies a pointer to a RectangleInfo structure. It
9000% contains the extents of any cropping rectangle.
9001%
cristy3ed852e2009-09-05 21:47:34 +00009002*/
9003static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
9004{
9005#define MinimumCropArea (unsigned int) 9
9006
9007 Cursor
9008 target_cursor;
9009
9010 GC
9011 annotate_context;
9012
9013 int
9014 presses,
9015 x_offset,
9016 y_offset;
9017
9018 Status
9019 status;
9020
9021 Window
9022 root_window,
9023 target_window;
9024
9025 XEvent
9026 event;
9027
9028 XGCValues
9029 context_values;
9030
9031 /*
9032 Initialize graphic context.
9033 */
9034 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9035 assert(display != (Display *) NULL);
9036 assert(crop_info != (RectangleInfo *) NULL);
9037 root_window=XRootWindow(display,XDefaultScreen(display));
9038 context_values.background=XBlackPixel(display,XDefaultScreen(display));
9039 context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
9040 context_values.function=GXinvert;
9041 context_values.plane_mask=
9042 context_values.background ^ context_values.foreground;
9043 context_values.subwindow_mode=IncludeInferiors;
cristybb503372010-05-27 20:51:26 +00009044 annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
cristy3ed852e2009-09-05 21:47:34 +00009045 GCForeground | GCFunction | GCSubwindowMode),&context_values);
9046 if (annotate_context == (GC) NULL)
9047 return(MagickFalse);
9048 /*
9049 Grab the pointer using target cursor.
9050 */
9051 target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
9052 XDefaultScreen(display)),(char * ) "white",(char * ) "black");
9053 status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
9054 (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
9055 GrabModeAsync,root_window,target_cursor,CurrentTime);
9056 if (status != GrabSuccess)
9057 {
9058 ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
9059 return((Window) NULL);
9060 }
9061 /*
9062 Select a window.
9063 */
9064 crop_info->width=0;
9065 crop_info->height=0;
9066 presses=0;
9067 target_window=(Window) NULL;
9068 x_offset=0;
9069 y_offset=0;
9070 do
9071 {
9072 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9073 (void) XDrawRectangle(display,root_window,annotate_context,
9074 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9075 (unsigned int) crop_info->height-1);
9076 /*
9077 Allow another event.
9078 */
9079 (void) XAllowEvents(display,SyncPointer,CurrentTime);
9080 (void) XWindowEvent(display,root_window,ButtonPressMask |
9081 ButtonReleaseMask | ButtonMotionMask,&event);
9082 if ((crop_info->width*crop_info->height) >= MinimumCropArea)
9083 (void) XDrawRectangle(display,root_window,annotate_context,
9084 (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
9085 (unsigned int) crop_info->height-1);
9086 switch (event.type)
9087 {
9088 case ButtonPress:
9089 {
9090 target_window=XGetSubwindow(display,event.xbutton.subwindow,
9091 event.xbutton.x,event.xbutton.y);
9092 if (target_window == (Window) NULL)
9093 target_window=root_window;
9094 x_offset=event.xbutton.x_root;
9095 y_offset=event.xbutton.y_root;
cristyecd0ab52010-05-30 14:59:20 +00009096 crop_info->x=(ssize_t) x_offset;
9097 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009098 crop_info->width=0;
9099 crop_info->height=0;
9100 presses++;
9101 break;
9102 }
9103 case ButtonRelease:
9104 {
9105 presses--;
9106 break;
9107 }
9108 case MotionNotify:
9109 {
9110 /*
9111 Discard pending button motion events.
9112 */
9113 while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
cristyecd0ab52010-05-30 14:59:20 +00009114 crop_info->x=(ssize_t) event.xmotion.x;
9115 crop_info->y=(ssize_t) event.xmotion.y;
cristy3ed852e2009-09-05 21:47:34 +00009116 /*
9117 Check boundary conditions.
9118 */
9119 if ((int) crop_info->x < x_offset)
cristyecd0ab52010-05-30 14:59:20 +00009120 crop_info->width=(size_t) (x_offset-crop_info->x);
cristy3ed852e2009-09-05 21:47:34 +00009121 else
9122 {
cristyecd0ab52010-05-30 14:59:20 +00009123 crop_info->width=(size_t) (crop_info->x-x_offset);
9124 crop_info->x=(ssize_t) x_offset;
cristy3ed852e2009-09-05 21:47:34 +00009125 }
9126 if ((int) crop_info->y < y_offset)
cristyecd0ab52010-05-30 14:59:20 +00009127 crop_info->height=(size_t) (y_offset-crop_info->y);
cristy3ed852e2009-09-05 21:47:34 +00009128 else
9129 {
cristyecd0ab52010-05-30 14:59:20 +00009130 crop_info->height=(size_t) (crop_info->y-y_offset);
9131 crop_info->y=(ssize_t) y_offset;
cristy3ed852e2009-09-05 21:47:34 +00009132 }
9133 }
9134 default:
9135 break;
9136 }
9137 } while ((target_window == (Window) NULL) || (presses > 0));
9138 (void) XUngrabPointer(display,CurrentTime);
9139 (void) XFreeCursor(display,target_cursor);
9140 (void) XFreeGC(display,annotate_context);
9141 if ((crop_info->width*crop_info->height) < MinimumCropArea)
9142 {
9143 crop_info->width=0;
9144 crop_info->height=0;
9145 }
9146 if ((crop_info->width != 0) && (crop_info->height != 0))
9147 target_window=root_window;
9148 return(target_window);
9149}
9150
9151/*
9152%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9153% %
9154% %
9155% %
9156% X S e t C u r s o r S t a t e %
9157% %
9158% %
9159% %
9160%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9161%
9162% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
9163% reset to their default.
9164%
9165% The format of the XXSetCursorState method is:
9166%
9167% XSetCursorState(display,windows,const MagickStatusType state)
9168%
9169% A description of each parameter follows:
9170%
9171% o display: Specifies a connection to an X server; returned from
9172% XOpenDisplay.
9173%
9174% o windows: Specifies a pointer to a XWindows structure.
9175%
9176% o state: An unsigned integer greater than 0 sets the cursor state
9177% to busy, otherwise the cursor are reset to their default.
9178%
9179*/
9180MagickExport void XSetCursorState(Display *display,XWindows *windows,
9181 const MagickStatusType state)
9182{
9183 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9184 assert(display != (Display *) NULL);
9185 assert(windows != (XWindows *) NULL);
9186 if (state)
9187 {
9188 (void) XCheckDefineCursor(display,windows->image.id,
9189 windows->image.busy_cursor);
9190 (void) XCheckDefineCursor(display,windows->pan.id,
9191 windows->pan.busy_cursor);
9192 (void) XCheckDefineCursor(display,windows->magnify.id,
9193 windows->magnify.busy_cursor);
9194 (void) XCheckDefineCursor(display,windows->command.id,
9195 windows->command.busy_cursor);
9196 }
9197 else
9198 {
9199 (void) XCheckDefineCursor(display,windows->image.id,
9200 windows->image.cursor);
9201 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
9202 (void) XCheckDefineCursor(display,windows->magnify.id,
9203 windows->magnify.cursor);
9204 (void) XCheckDefineCursor(display,windows->command.id,
9205 windows->command.cursor);
9206 (void) XCheckDefineCursor(display,windows->command.id,
9207 windows->widget.cursor);
9208 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9209 }
9210 windows->info.mapped=MagickFalse;
9211}
9212
9213/*
9214%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9215% %
9216% %
9217% %
9218% X S e t W i n d o w s %
9219% %
9220% %
9221% %
9222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9223%
9224% XSetWindows() sets the X windows structure if the windows info is specified.
9225% Otherwise the current windows structure is returned.
9226%
9227% The format of the XSetWindows method is:
9228%
9229% XWindows *XSetWindows(XWindows *windows_info)
9230%
9231% A description of each parameter follows:
9232%
9233% o windows_info: Initialize the Windows structure with this information.
9234%
9235*/
9236MagickExport XWindows *XSetWindows(XWindows *windows_info)
9237{
9238 static XWindows
9239 *windows = (XWindows *) NULL;
9240
9241 if (windows_info != (XWindows *) ~0)
9242 {
9243 windows=(XWindows *) RelinquishMagickMemory(windows);
9244 windows=windows_info;
9245 }
9246 return(windows);
9247}
9248/*
9249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9250% %
9251% %
9252% %
9253% X U s e r P r e f e r e n c e s %
9254% %
9255% %
9256% %
9257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9258%
9259% XUserPreferences() saves the preferences in a configuration file in the
9260% users' home directory.
9261%
9262% The format of the XUserPreferences method is:
9263%
9264% void XUserPreferences(XResourceInfo *resource_info)
9265%
9266% A description of each parameter follows:
9267%
9268% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9269%
9270*/
9271MagickExport void XUserPreferences(XResourceInfo *resource_info)
9272{
9273#if defined(X11_PREFERENCES_PATH)
9274 char
9275 cache[MaxTextExtent],
9276 filename[MaxTextExtent],
9277 specifier[MaxTextExtent];
9278
9279 const char
cristy104cea82009-10-25 02:26:51 +00009280 *client_name,
cristy3ed852e2009-09-05 21:47:34 +00009281 *value;
9282
9283 XrmDatabase
9284 preferences_database;
9285
9286 /*
9287 Save user preferences to the client configuration file.
9288 */
9289 assert(resource_info != (XResourceInfo *) NULL);
cristy104cea82009-10-25 02:26:51 +00009290 client_name=GetClientName();
cristy3ed852e2009-09-05 21:47:34 +00009291 preferences_database=XrmGetStringDatabase("");
cristy104cea82009-10-25 02:26:51 +00009292 (void) FormatMagickString(specifier,MaxTextExtent,"%s.backdrop",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009293 value=resource_info->backdrop ? "True" : "False";
9294 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009295 (void) FormatMagickString(specifier,MaxTextExtent,"%s.colormap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009296 value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
9297 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9298 (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmExit",
cristy104cea82009-10-25 02:26:51 +00009299 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009300 value=resource_info->confirm_exit ? "True" : "False";
9301 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9302 (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmEdit",
cristy104cea82009-10-25 02:26:51 +00009303 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009304 value=resource_info->confirm_edit ? "True" : "False";
9305 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9306 (void) FormatMagickString(specifier,MaxTextExtent,"%s.displayWarnings",
cristy104cea82009-10-25 02:26:51 +00009307 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009308 value=resource_info->display_warnings ? "True" : "False";
9309 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009310 (void) FormatMagickString(specifier,MaxTextExtent,"%s.dither",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009311 value=resource_info->quantize_info->dither ? "True" : "False";
9312 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9313 (void) FormatMagickString(specifier,MaxTextExtent,"%s.gammaCorrect",
cristy104cea82009-10-25 02:26:51 +00009314 client_name);
cristy3ed852e2009-09-05 21:47:34 +00009315 value=resource_info->gamma_correct ? "True" : "False";
9316 XrmPutStringResource(&preferences_database,specifier,(char *) value);
cristy104cea82009-10-25 02:26:51 +00009317 (void) FormatMagickString(specifier,MaxTextExtent,"%s.undoCache",client_name);
cristye8c25f92010-06-03 00:53:06 +00009318 (void) FormatMagickString(cache,MaxTextExtent,"%.20g",(double)
cristy3ed852e2009-09-05 21:47:34 +00009319 resource_info->undo_cache);
9320 XrmPutStringResource(&preferences_database,specifier,cache);
cristy104cea82009-10-25 02:26:51 +00009321 (void) FormatMagickString(specifier,MaxTextExtent,"%s.usePixmap",client_name);
cristy3ed852e2009-09-05 21:47:34 +00009322 value=resource_info->use_pixmap ? "True" : "False";
9323 XrmPutStringResource(&preferences_database,specifier,(char *) value);
9324 (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
cristy104cea82009-10-25 02:26:51 +00009325 X11_PREFERENCES_PATH,client_name);
cristy3ed852e2009-09-05 21:47:34 +00009326 ExpandFilename(filename);
9327 XrmPutFileDatabase(preferences_database,filename);
9328#endif
9329}
9330
9331/*
9332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9333% %
9334% %
9335% %
9336% X V i s u a l C l a s s N a m e %
9337% %
9338% %
9339% %
9340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9341%
9342% XVisualClassName() returns the visual class name as a character string.
9343%
9344% The format of the XVisualClassName method is:
9345%
9346% char *XVisualClassName(const int visual_class)
9347%
9348% A description of each parameter follows:
9349%
9350% o visual_type: XVisualClassName returns the visual class as a character
9351% string.
9352%
9353% o class: Specifies the visual class.
9354%
cristy3ed852e2009-09-05 21:47:34 +00009355*/
9356static const char *XVisualClassName(const int visual_class)
9357{
9358 switch (visual_class)
9359 {
9360 case StaticGray: return("StaticGray");
9361 case GrayScale: return("GrayScale");
9362 case StaticColor: return("StaticColor");
9363 case PseudoColor: return("PseudoColor");
9364 case TrueColor: return("TrueColor");
9365 case DirectColor: return("DirectColor");
9366 }
9367 return("unknown visual class");
9368}
9369
9370/*
9371%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9372% %
9373% %
9374% %
9375% X W a r n i n g %
9376% %
9377% %
9378% %
9379%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9380%
9381% XWarning() displays a warning reason in a Notice widget.
9382%
9383% The format of the XWarning method is:
9384%
9385% void XWarning(const unsigned int warning,const char *reason,
9386% const char *description)
9387%
9388% A description of each parameter follows:
9389%
9390% o warning: Specifies the numeric warning category.
9391%
9392% o reason: Specifies the reason to display before terminating the
9393% program.
9394%
9395% o description: Specifies any description to the reason.
9396%
9397*/
9398MagickExport void XWarning(const ExceptionType magick_unused(warning),
9399 const char *reason,const char *description)
9400{
9401 char
9402 text[MaxTextExtent];
9403
9404 XWindows
9405 *windows;
9406
9407 if (reason == (char *) NULL)
9408 return;
9409 (void) CopyMagickString(text,reason,MaxTextExtent);
9410 (void) ConcatenateMagickString(text,":",MaxTextExtent);
9411 windows=XSetWindows((XWindows *) ~0);
9412 XNoticeWidget(windows->display,windows,text,(char *) description);
9413}
9414
9415/*
9416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9417% %
9418% %
9419% %
9420% X W i n d o w B y I D %
9421% %
9422% %
9423% %
9424%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9425%
9426% XWindowByID() locates a child window with a given ID. If not window with
9427% the given name is found, 0 is returned. Only the window specified and its
9428% subwindows are searched.
9429%
9430% The format of the XWindowByID function is:
9431%
9432% child=XWindowByID(display,window,id)
9433%
9434% A description of each parameter follows:
9435%
9436% o child: XWindowByID returns the window with the specified
9437% id. If no windows are found, XWindowByID returns 0.
9438%
9439% o display: Specifies a pointer to the Display structure; returned from
9440% XOpenDisplay.
9441%
9442% o id: Specifies the id of the window to locate.
9443%
9444*/
9445MagickExport Window XWindowByID(Display *display,const Window root_window,
cristybb503372010-05-27 20:51:26 +00009446 const size_t id)
cristy3ed852e2009-09-05 21:47:34 +00009447{
9448 RectangleInfo
9449 rectangle_info;
9450
9451 register int
9452 i;
9453
9454 Status
9455 status;
9456
9457 unsigned int
9458 number_children;
9459
9460 Window
9461 child,
9462 *children,
9463 window;
9464
9465 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9466 assert(display != (Display *) NULL);
9467 assert(root_window != (Window) NULL);
9468 if (id == 0)
9469 return(XSelectWindow(display,&rectangle_info));
9470 if (root_window == id)
cristydfe2b662010-08-22 16:17:24 +00009471 return(root_window);
cristy3ed852e2009-09-05 21:47:34 +00009472 status=XQueryTree(display,root_window,&child,&child,&children,
9473 &number_children);
9474 if (status == False)
9475 return((Window) NULL);
9476 window=(Window) NULL;
9477 for (i=0; i < (int) number_children; i++)
9478 {
9479 /*
9480 Search each child and their children.
9481 */
9482 window=XWindowByID(display,children[i],id);
9483 if (window != (Window) NULL)
9484 break;
9485 }
9486 if (children != (Window *) NULL)
9487 (void) XFree((void *) children);
9488 return(window);
9489}
9490
9491/*
9492%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9493% %
9494% %
9495% %
9496% X W i n d o w B y N a m e %
9497% %
9498% %
9499% %
9500%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9501%
9502% XWindowByName() locates a window with a given name on a display. If no
9503% window with the given name is found, 0 is returned. If more than one window
9504% has the given name, the first one is returned. Only root and its children
9505% are searched.
9506%
9507% The format of the XWindowByName function is:
9508%
9509% window=XWindowByName(display,root_window,name)
9510%
9511% A description of each parameter follows:
9512%
9513% o window: XWindowByName returns the window id.
9514%
9515% o display: Specifies a pointer to the Display structure; returned from
9516% XOpenDisplay.
9517%
9518% o root_window: Specifies the id of the root window.
9519%
9520% o name: Specifies the name of the window to locate.
9521%
9522*/
9523MagickExport Window XWindowByName(Display *display,const Window root_window,
9524 const char *name)
9525{
9526 register int
9527 i;
9528
9529 Status
9530 status;
9531
9532 unsigned int
9533 number_children;
9534
9535 Window
9536 *children,
9537 child,
9538 window;
9539
9540 XTextProperty
9541 window_name;
9542
9543 assert(display != (Display *) NULL);
9544 assert(root_window != (Window) NULL);
9545 assert(name != (char *) NULL);
9546 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
9547 if (XGetWMName(display,root_window,&window_name) != 0)
9548 if (LocaleCompare((char *) window_name.value,name) == 0)
9549 return(root_window);
9550 status=XQueryTree(display,root_window,&child,&child,&children,
9551 &number_children);
9552 if (status == False)
9553 return((Window) NULL);
9554 window=(Window) NULL;
9555 for (i=0; i < (int) number_children; i++)
9556 {
9557 /*
9558 Search each child and their children.
9559 */
9560 window=XWindowByName(display,children[i],name);
9561 if (window != (Window) NULL)
9562 break;
9563 }
9564 if (children != (Window *) NULL)
9565 (void) XFree((void *) children);
9566 return(window);
9567}
9568
9569/*
9570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9571% %
9572% %
9573% %
9574% X W i n d o w B y P r o p e r y %
9575% %
9576% %
9577% %
9578%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9579%
9580% XWindowByProperty() locates a child window with a given property. If not
9581% window with the given name is found, 0 is returned. If more than one window
9582% has the given property, the first one is returned. Only the window
9583% specified and its subwindows are searched.
9584%
9585% The format of the XWindowByProperty function is:
9586%
9587% child=XWindowByProperty(display,window,property)
9588%
9589% A description of each parameter follows:
9590%
9591% o child: XWindowByProperty returns the window id with the specified
9592% property. If no windows are found, XWindowByProperty returns 0.
9593%
9594% o display: Specifies a pointer to the Display structure; returned from
9595% XOpenDisplay.
9596%
9597% o property: Specifies the property of the window to locate.
9598%
9599*/
9600MagickExport Window XWindowByProperty(Display *display,const Window window,
9601 const Atom property)
9602{
9603 Atom
9604 type;
9605
9606 int
9607 format;
9608
9609 Status
9610 status;
9611
9612 unsigned char
9613 *data;
9614
9615 unsigned int
9616 i,
9617 number_children;
9618
cristyf2faecf2010-05-28 19:19:36 +00009619 unsigned long
cristy3ed852e2009-09-05 21:47:34 +00009620 after,
9621 number_items;
9622
9623 Window
9624 child,
9625 *children,
9626 parent,
9627 root;
9628
9629 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
9630 assert(display != (Display *) NULL);
9631 assert(window != (Window) NULL);
9632 assert(property != (Atom) NULL);
9633 status=XQueryTree(display,window,&root,&parent,&children,&number_children);
9634 if (status == False)
9635 return((Window) NULL);
9636 type=(Atom) NULL;
9637 child=(Window) NULL;
9638 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9639 {
9640 status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
9641 (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
9642 if (data != NULL)
9643 (void) XFree((void *) data);
9644 if ((status == Success) && (type != (Atom) NULL))
9645 child=children[i];
9646 }
9647 for (i=0; (i < number_children) && (child == (Window) NULL); i++)
9648 child=XWindowByProperty(display,children[i],property);
9649 if (children != (Window *) NULL)
9650 (void) XFree((void *) children);
9651 return(child);
9652}
9653#else
9654
9655/*
9656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9657% %
9658% %
9659% %
9660% X I m p o r t I m a g e %
9661% %
9662% %
9663% %
9664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9665%
9666% XImportImage() reads an image from an X window.
9667%
9668% The format of the XImportImage method is:
9669%
9670% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
9671%
9672% A description of each parameter follows:
9673%
9674% o image_info: the image info..
9675%
9676% o ximage_info: Specifies a pointer to an XImportInfo structure.
9677%
9678*/
9679MagickExport Image *XImportImage(const ImageInfo *image_info,
9680 XImportInfo *ximage_info)
9681{
9682 assert(image_info != (const ImageInfo *) NULL);
9683 assert(image_info->signature == MagickSignature);
9684 if (image_info->debug != MagickFalse)
9685 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
9686 image_info->filename);
9687 assert(ximage_info != (XImportInfo *) NULL);
9688 return((Image *) NULL);
9689}
9690#endif
9691
9692/*
9693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9694% %
9695% %
9696% %
cristy576974e2009-10-25 20:45:31 +00009697+ X C o m p o n e n t G e n e s i s %
9698% %
9699% %
9700% %
9701%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9702%
9703% XComponentGenesis() instantiates the X component.
9704%
9705% The format of the XComponentGenesis method is:
9706%
9707% MagickBooleanType XComponentGenesis(void)
9708%
9709*/
9710MagickExport MagickBooleanType XComponentGenesis(void)
9711{
9712 return(MagickTrue);
9713}
9714
9715/*
9716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9717% %
9718% %
9719% %
cristy3ed852e2009-09-05 21:47:34 +00009720% X G e t I m p o r t I n f o %
9721% %
9722% %
9723% %
9724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9725%
9726% XGetImportInfo() initializes the XImportInfo structure.
9727%
9728% The format of the XGetImportInfo method is:
9729%
9730% void XGetImportInfo(XImportInfo *ximage_info)
9731%
9732% A description of each parameter follows:
9733%
9734% o ximage_info: Specifies a pointer to an ImageInfo structure.
9735%
9736*/
9737MagickExport void XGetImportInfo(XImportInfo *ximage_info)
9738{
9739 assert(ximage_info != (XImportInfo *) NULL);
9740 ximage_info->frame=MagickFalse;
9741 ximage_info->borders=MagickFalse;
9742 ximage_info->screen=MagickFalse;
9743 ximage_info->descend=MagickTrue;
9744 ximage_info->silent=MagickFalse;
9745}