• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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