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