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