MagickCore  6.7.5
xwindow.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %              X   X  W   W  IIIII  N   N  DDDD    OOO   W   W                %
00007 %               X X   W   W    I    NN  N  D   D  O   O  W   W                %
00008 %                X    W   W    I    N N N  D   D  O   O  W   W                %
00009 %               X X   W W W    I    N  NN  D   D  O   O  W W W                %
00010 %              X   X   W W   IIIII  N   N  DDDD    OOO    W W                 %
00011 %                                                                             %
00012 %                                                                             %
00013 %                       MagickCore X11 Utility Methods                        %
00014 %                                                                             %
00015 %                               Software Design                               %
00016 %                                 John Cristy                                 %
00017 %                                  July 1992                                  %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "MagickCore/studio.h"
00043 #include "MagickCore/animate.h"
00044 #include "MagickCore/artifact.h"
00045 #include "MagickCore/blob.h"
00046 #include "MagickCore/cache.h"
00047 #include "MagickCore/client.h"
00048 #include "MagickCore/color.h"
00049 #include "MagickCore/color-private.h"
00050 #include "MagickCore/colormap.h"
00051 #include "MagickCore/composite.h"
00052 #include "MagickCore/constitute.h"
00053 #include "MagickCore/display.h"
00054 #include "MagickCore/distort.h"
00055 #include "MagickCore/exception.h"
00056 #include "MagickCore/exception-private.h"
00057 #include "MagickCore/geometry.h"
00058 #include "MagickCore/identify.h"
00059 #include "MagickCore/image.h"
00060 #include "MagickCore/image-private.h"
00061 #include "MagickCore/list.h"
00062 #include "MagickCore/locale_.h"
00063 #include "MagickCore/log.h"
00064 #include "MagickCore/magick.h"
00065 #include "MagickCore/memory_.h"
00066 #include "MagickCore/monitor.h"
00067 #include "MagickCore/nt-base-private.h"
00068 #include "MagickCore/option.h"
00069 #include "MagickCore/pixel-accessor.h"
00070 #include "MagickCore/PreRvIcccm.h"
00071 #include "MagickCore/quantize.h"
00072 #include "MagickCore/quantum.h"
00073 #include "MagickCore/quantum-private.h"
00074 #include "MagickCore/resource_.h"
00075 #include "MagickCore/resize.h"
00076 #include "MagickCore/statistic.h"
00077 #include "MagickCore/string_.h"
00078 #include "MagickCore/string-private.h"
00079 #include "MagickCore/transform.h"
00080 #include "MagickCore/utility.h"
00081 #include "MagickCore/utility-private.h"
00082 #include "MagickCore/widget.h"
00083 #include "MagickCore/widget-private.h"
00084 #include "MagickCore/xwindow.h"
00085 #include "MagickCore/xwindow-private.h"
00086 #include "MagickCore/version.h"
00087 #if defined(__BEOS__)
00088 #include <OS.h>
00089 #endif
00090 #if defined(MAGICKCORE_X11_DELEGATE)
00091 #include <X11/Xproto.h>
00092 #include <X11/Xlocale.h>
00093 #if defined(MAGICK_HAVE_POLL)
00094 # include <sys/poll.h>
00095 #endif
00096 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
00097 #if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
00098 # include <machine/param.h>
00099 #endif
00100 #include <sys/ipc.h>
00101 #include <sys/shm.h>
00102 #include <X11/extensions/XShm.h>
00103 #endif
00104 #if defined(MAGICKCORE_HAVE_SHAPE)
00105 #include <X11/extensions/shape.h>
00106 #endif
00107 
00108 /*
00109   X defines.
00110 */
00111 #define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
00112   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
00113   QuantumRange)))
00114 #define XGammaPacket(map,color)  (size_t) (map->base_pixel+ \
00115   ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
00116     map->red_mult)+ \
00117   ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
00118     map->green_mult)+ \
00119   ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
00120     map->blue_mult))
00121 #define XGammaPixel(image,map,color)  (size_t) (map->base_pixel+ \
00122   ((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
00123     map->red_mult)+ \
00124   ((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
00125     map->green_mult)+ \
00126   ((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
00127     map->blue_mult))
00128 #define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
00129   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
00130   QuantumRange)))
00131 #define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
00132   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
00133   QuantumRange)))
00134 #define XStandardPixel(map,color)  (size_t) (map->base_pixel+ \
00135   (((color)->red*map->red_max/65535L)*map->red_mult)+ \
00136   (((color)->green*map->green_max/65535L)*map->green_mult)+ \
00137   (((color)->blue*map->blue_max/65535L)*map->blue_mult))
00138 
00139 #define AccentuateModulate  ScaleCharToQuantum(80)
00140 #define HighlightModulate  ScaleCharToQuantum(125)
00141 #define ShadowModulate  ScaleCharToQuantum(135)
00142 #define DepthModulate  ScaleCharToQuantum(185)
00143 #define TroughModulate  ScaleCharToQuantum(110)
00144 
00145 #define XLIB_ILLEGAL_ACCESS  1
00146 #undef ForgetGravity
00147 #undef NorthWestGravity
00148 #undef NorthGravity
00149 #undef NorthEastGravity
00150 #undef WestGravity
00151 #undef CenterGravity
00152 #undef EastGravity
00153 #undef SouthWestGravity
00154 #undef SouthGravity
00155 #undef SouthEastGravity
00156 #undef StaticGravity
00157 
00158 #undef index
00159 #if defined(hpux9)
00160 #define XFD_SET  int
00161 #else
00162 #define XFD_SET  fd_set
00163 #endif
00164 
00165 /*
00166   Enumeration declarations.
00167 */
00168 typedef enum
00169 {
00170 #undef DoRed
00171   DoRed = 0x0001,
00172 #undef DoGreen
00173   DoGreen = 0x0002,
00174 #undef DoBlue
00175   DoBlue = 0x0004,
00176   DoMatte = 0x0008
00177 } XColorFlags;
00178 
00179 /*
00180   Typedef declarations.
00181 */
00182 typedef struct _DiversityPacket
00183 {
00184   Quantum
00185     red,
00186     green,
00187     blue;
00188 
00189   unsigned short
00190     index;
00191 
00192   size_t
00193     count;
00194 } DiversityPacket;
00195 
00196 /*
00197   Constant declaractions.
00198 */
00199 static MagickBooleanType
00200   xerror_alert = MagickFalse;
00201 
00202 /*
00203   Method prototypes.
00204 */
00205 static const char
00206   *XVisualClassName(const int);
00207 
00208 static MagickRealType
00209   blue_gamma = 1.0,
00210   green_gamma = 1.0,
00211   red_gamma = 1.0;
00212 
00213 static MagickBooleanType
00214   XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
00215 
00216 static void
00217   XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
00218     XImage *,XImage *,ExceptionInfo *),
00219   XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
00220     XImage *,XImage *,ExceptionInfo *);
00221 
00222 static Window
00223   XSelectWindow(Display *,RectangleInfo *);
00224 
00225 /*
00226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00227 %                                                                             %
00228 %                                                                             %
00229 %                                                                             %
00230 %   D e s t r o y X R e s o u r c e s                                         %
00231 %                                                                             %
00232 %                                                                             %
00233 %                                                                             %
00234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00235 %
00236 %  DestroyXResources() destroys any X resources.
00237 %
00238 %  The format of the DestroyXResources method is:
00239 %
00240 %      void DestroyXResources()
00241 %
00242 %  A description of each parameter follows:
00243 %
00244 */
00245 MagickExport void DestroyXResources(void)
00246 {
00247   register int
00248     i;
00249 
00250   unsigned int
00251     number_windows;
00252 
00253   XWindowInfo
00254     *magick_windows[MaxXWindows];
00255 
00256   XWindows
00257     *windows;
00258 
00259   DestroyXWidget();
00260   windows=XSetWindows((XWindows *) ~0);
00261   if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
00262     return;
00263   number_windows=0;
00264   magick_windows[number_windows++]=(&windows->context);
00265   magick_windows[number_windows++]=(&windows->group_leader);
00266   magick_windows[number_windows++]=(&windows->backdrop);
00267   magick_windows[number_windows++]=(&windows->icon);
00268   magick_windows[number_windows++]=(&windows->image);
00269   magick_windows[number_windows++]=(&windows->info);
00270   magick_windows[number_windows++]=(&windows->magnify);
00271   magick_windows[number_windows++]=(&windows->pan);
00272   magick_windows[number_windows++]=(&windows->command);
00273   magick_windows[number_windows++]=(&windows->widget);
00274   magick_windows[number_windows++]=(&windows->popup);
00275   magick_windows[number_windows++]=(&windows->context);
00276   for (i=0; i < (int) number_windows; i++)
00277   {
00278     if (magick_windows[i]->mapped != MagickFalse)
00279       {
00280         (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
00281           magick_windows[i]->screen);
00282         magick_windows[i]->mapped=MagickFalse;
00283       }
00284     if (magick_windows[i]->name != (char *) NULL)
00285       magick_windows[i]->name=(char *)
00286         RelinquishMagickMemory(magick_windows[i]->name);
00287     if (magick_windows[i]->icon_name != (char *) NULL)
00288       magick_windows[i]->icon_name=(char *)
00289         RelinquishMagickMemory(magick_windows[i]->icon_name);
00290     if (magick_windows[i]->cursor != (Cursor) NULL)
00291       {
00292         (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
00293         magick_windows[i]->cursor=(Cursor) NULL;
00294       }
00295     if (magick_windows[i]->busy_cursor != (Cursor) NULL)
00296       {
00297         (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
00298         magick_windows[i]->busy_cursor=(Cursor) NULL;
00299       }
00300     if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
00301       {
00302         (void) XFreePixmap(windows->display,
00303           magick_windows[i]->highlight_stipple);
00304         magick_windows[i]->highlight_stipple=(Pixmap) NULL;
00305       }
00306     if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
00307       {
00308         (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
00309         magick_windows[i]->shadow_stipple=(Pixmap) NULL;
00310       }
00311     if (magick_windows[i]->ximage != (XImage *) NULL)
00312       {
00313         XDestroyImage(magick_windows[i]->ximage);
00314         magick_windows[i]->ximage=(XImage *) NULL;
00315       }
00316     if (magick_windows[i]->pixmap != (Pixmap) NULL)
00317       {
00318         (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
00319         magick_windows[i]->pixmap=(Pixmap) NULL;
00320       }
00321     if (magick_windows[i]->id != (Window) NULL)
00322       {
00323         (void) XDestroyWindow(windows->display,magick_windows[i]->id);
00324         magick_windows[i]->id=(Window) NULL;
00325       }
00326     if (magick_windows[i]->destroy != MagickFalse)
00327       {
00328         if (magick_windows[i]->image != (Image *) NULL)
00329           {
00330             magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
00331             magick_windows[i]->image=NewImageList();
00332           }
00333         if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
00334           {
00335             (void) XFreePixmap(windows->display,
00336               magick_windows[i]->matte_pixmap);
00337             magick_windows[i]->matte_pixmap=(Pixmap) NULL;
00338           }
00339       }
00340     if (magick_windows[i]->segment_info != (void *) NULL)
00341       {
00342 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
00343         XShmSegmentInfo
00344           *segment_info;
00345 
00346         segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
00347         if (segment_info != (XShmSegmentInfo *) NULL)
00348           if (segment_info[0].shmid >= 0)
00349             {
00350               if (segment_info[0].shmaddr != NULL)
00351                 (void) shmdt(segment_info[0].shmaddr);
00352               (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
00353               segment_info[0].shmaddr=NULL;
00354               segment_info[0].shmid=(-1);
00355             }
00356 #endif
00357         magick_windows[i]->segment_info=(void *)
00358           RelinquishMagickMemory(magick_windows[i]->segment_info);
00359       }
00360   }
00361   windows->icon_resources=(XResourceInfo *)
00362     RelinquishMagickMemory(windows->icon_resources);
00363   if (windows->icon_pixel != (XPixelInfo *) NULL)
00364     {
00365       if (windows->icon_pixel->pixels != (unsigned long *) NULL)
00366         windows->icon_pixel->pixels=(unsigned long *)
00367           RelinquishMagickMemory(windows->icon_pixel->pixels);
00368       if (windows->icon_pixel->annotate_context != (GC) NULL)
00369         XFreeGC(windows->display,windows->icon_pixel->annotate_context);
00370       windows->icon_pixel=(XPixelInfo *)
00371         RelinquishMagickMemory(windows->icon_pixel);
00372     }
00373   if (windows->pixel_info != (XPixelInfo *) NULL)
00374     {
00375       if (windows->pixel_info->pixels != (unsigned long *) NULL)
00376         windows->pixel_info->pixels=(unsigned long *)
00377           RelinquishMagickMemory(windows->pixel_info->pixels);
00378       if (windows->pixel_info->annotate_context != (GC) NULL)
00379         XFreeGC(windows->display,windows->pixel_info->annotate_context);
00380       if (windows->pixel_info->widget_context != (GC) NULL)
00381         XFreeGC(windows->display,windows->pixel_info->widget_context);
00382       if (windows->pixel_info->highlight_context != (GC) NULL)
00383         XFreeGC(windows->display,windows->pixel_info->highlight_context);
00384       windows->pixel_info=(XPixelInfo *)
00385         RelinquishMagickMemory(windows->pixel_info);
00386     }
00387   if (windows->font_info != (XFontStruct *) NULL)
00388     {
00389       XFreeFont(windows->display,windows->font_info);
00390       windows->font_info=(XFontStruct *) NULL;
00391     }
00392   if (windows->class_hints != (XClassHint *) NULL)
00393     {
00394       if (windows->class_hints->res_name != (char *) NULL)
00395         windows->class_hints->res_name=DestroyString(
00396           windows->class_hints->res_name);
00397       if (windows->class_hints->res_class != (char *) NULL)
00398         windows->class_hints->res_class=DestroyString(
00399           windows->class_hints->res_class);
00400       XFree(windows->class_hints);
00401       windows->class_hints=(XClassHint *) NULL;
00402     }
00403   if (windows->manager_hints != (XWMHints *) NULL)
00404     {
00405       XFree(windows->manager_hints);
00406       windows->manager_hints=(XWMHints *) NULL;
00407     }
00408   if (windows->map_info != (XStandardColormap *) NULL)
00409     {
00410       XFree(windows->map_info);
00411       windows->map_info=(XStandardColormap *) NULL;
00412     }
00413   if (windows->icon_map != (XStandardColormap *) NULL)
00414     {
00415       XFree(windows->icon_map);
00416       windows->icon_map=(XStandardColormap *) NULL;
00417     }
00418   if (windows->visual_info != (XVisualInfo *) NULL)
00419     {
00420       XFree(windows->visual_info);
00421       windows->visual_info=(XVisualInfo *) NULL;
00422     }
00423   if (windows->icon_visual != (XVisualInfo *) NULL)
00424     {
00425       XFree(windows->icon_visual);
00426       windows->icon_visual=(XVisualInfo *) NULL;
00427     }
00428   (void) XSetWindows((XWindows *) NULL);
00429 }
00430 
00431 /*
00432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00433 %                                                                             %
00434 %                                                                             %
00435 %                                                                             %
00436 %   X A n n o t a t e I m a g e                                               %
00437 %                                                                             %
00438 %                                                                             %
00439 %                                                                             %
00440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00441 %
00442 %  XAnnotateImage() annotates the image with text.
00443 %
00444 %  The format of the XAnnotateImage method is:
00445 %
00446 %      MagickBooleanType XAnnotateImage(Display *display,
00447 %        const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
00448 %        ExceptionInfo *exception)
00449 %
00450 %  A description of each parameter follows:
00451 %
00452 %    o display: Specifies a connection to an X server;  returned from
00453 %      XOpenDisplay.
00454 %
00455 %    o pixel: Specifies a pointer to a XPixelInfo structure.
00456 %
00457 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
00458 %
00459 %    o image: the image.
00460 %
00461 %    o exception: return any errors or warnings in this structure.
00462 %
00463 */
00464 MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
00465   const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
00466   ExceptionInfo *exception)
00467 {
00468   CacheView
00469     *annotate_view;
00470 
00471   GC
00472     annotate_context;
00473 
00474   Image
00475     *annotate_image;
00476 
00477   int
00478     x,
00479     y;
00480 
00481   MagickBooleanType
00482     matte;
00483 
00484   Pixmap
00485     annotate_pixmap;
00486 
00487   Quantum
00488     virtual_pixel[CompositePixelChannel];
00489 
00490   unsigned int
00491     depth,
00492     height,
00493     width;
00494 
00495   Window
00496     root_window;
00497 
00498   XGCValues
00499     context_values;
00500 
00501   XImage
00502     *annotate_ximage;
00503 
00504   /*
00505     Initialize annotated image.
00506   */
00507   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00508   assert(display != (Display *) NULL);
00509   assert(pixel != (XPixelInfo *) NULL);
00510   assert(annotate_info != (XAnnotateInfo *) NULL);
00511   assert(image != (Image *) NULL);
00512   /*
00513     Initialize annotated pixmap.
00514   */
00515   root_window=XRootWindow(display,XDefaultScreen(display));
00516   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
00517   annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
00518     annotate_info->height,depth);
00519   if (annotate_pixmap == (Pixmap) NULL)
00520     return(MagickFalse);
00521   /*
00522     Initialize graphics info.
00523   */
00524   context_values.background=0;
00525   context_values.foreground=(size_t) (~0);
00526   context_values.font=annotate_info->font_info->fid;
00527   annotate_context=XCreateGC(display,root_window,(unsigned long)
00528     (GCBackground | GCFont | GCForeground),&context_values);
00529   if (annotate_context == (GC) NULL)
00530     return(MagickFalse);
00531   /*
00532     Draw text to pixmap.
00533   */
00534   (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
00535     (int) annotate_info->font_info->ascent,annotate_info->text,
00536     (int) strlen(annotate_info->text));
00537   (void) XFreeGC(display,annotate_context);
00538   /*
00539     Initialize annotated X image.
00540   */
00541   annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
00542     annotate_info->height,AllPlanes,ZPixmap);
00543   if (annotate_ximage == (XImage *) NULL)
00544     return(MagickFalse);
00545   (void) XFreePixmap(display,annotate_pixmap);
00546   /*
00547     Initialize annotated image.
00548   */
00549   annotate_image=AcquireImage((ImageInfo *) NULL,exception);
00550   if (annotate_image == (Image *) NULL)
00551     return(MagickFalse);
00552   annotate_image->columns=annotate_info->width;
00553   annotate_image->rows=annotate_info->height;
00554   /*
00555     Transfer annotated X image to image.
00556   */
00557   width=(unsigned int) image->columns;
00558   height=(unsigned int) image->rows;
00559   x=0;
00560   y=0;
00561   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
00562   (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,virtual_pixel,
00563     exception);
00564   annotate_image->background_color.red=virtual_pixel[RedPixelChannel];
00565   annotate_image->background_color.green=virtual_pixel[GreenPixelChannel];
00566   annotate_image->background_color.blue=virtual_pixel[BluePixelChannel];
00567   annotate_image->background_color.alpha=virtual_pixel[AlphaPixelChannel];
00568   if (annotate_info->stencil == ForegroundStencil)
00569     annotate_image->matte=MagickTrue;
00570   annotate_view=AcquireCacheView(annotate_image);
00571   for (y=0; y < (int) annotate_image->rows; y++)
00572   {
00573     register int
00574       x;
00575 
00576     register Quantum
00577       *restrict q;
00578 
00579     q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
00580       annotate_image->columns,1,exception);
00581     if (q == (Quantum *) NULL)
00582       break;
00583     for (x=0; x < (int) annotate_image->columns; x++)
00584     {
00585       SetPixelAlpha(annotate_image,OpaqueAlpha,q);
00586       if (XGetPixel(annotate_ximage,x,y) == 0)
00587         {
00588           /*
00589             Set this pixel to the background color.
00590           */
00591           SetPixelRed(annotate_image,ScaleShortToQuantum(
00592             pixel->box_color.red),q);
00593           SetPixelGreen(annotate_image,ScaleShortToQuantum(
00594             pixel->box_color.green),q);
00595           SetPixelBlue(annotate_image,ScaleShortToQuantum(
00596             pixel->box_color.blue),q);
00597           if ((annotate_info->stencil == ForegroundStencil) ||
00598               (annotate_info->stencil == OpaqueStencil))
00599             SetPixelAlpha(annotate_image,TransparentAlpha,q);
00600         }
00601       else
00602         {
00603           /*
00604             Set this pixel to the pen color.
00605           */
00606           SetPixelRed(annotate_image,ScaleShortToQuantum(
00607             pixel->pen_color.red),q);
00608           SetPixelGreen(annotate_image,ScaleShortToQuantum(
00609             pixel->pen_color.green),q);
00610           SetPixelBlue(annotate_image,ScaleShortToQuantum(
00611             pixel->pen_color.blue),q);
00612           if (annotate_info->stencil == BackgroundStencil)
00613             SetPixelAlpha(annotate_image,TransparentAlpha,q);
00614         }
00615       q+=GetPixelChannels(annotate_image);
00616     }
00617     if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
00618       break;
00619   }
00620   annotate_view=DestroyCacheView(annotate_view);
00621   XDestroyImage(annotate_ximage);
00622   /*
00623     Determine annotate geometry.
00624   */
00625   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
00626   if ((width != (unsigned int) annotate_image->columns) ||
00627       (height != (unsigned int) annotate_image->rows))
00628     {
00629       char
00630         image_geometry[MaxTextExtent];
00631 
00632       /*
00633         Scale image.
00634       */
00635       (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
00636         width,height);
00637       (void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
00638         exception);
00639     }
00640   if (annotate_info->degrees != 0.0)
00641     {
00642       Image
00643         *rotate_image;
00644 
00645       int
00646         rotations;
00647 
00648       MagickRealType
00649         normalized_degrees;
00650 
00651       /*
00652         Rotate image.
00653       */
00654       rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
00655       if (rotate_image == (Image *) NULL)
00656         return(MagickFalse);
00657       annotate_image=DestroyImage(annotate_image);
00658       annotate_image=rotate_image;
00659       /*
00660         Annotation is relative to the degree of rotation.
00661       */
00662       normalized_degrees=annotate_info->degrees;
00663       while (normalized_degrees < -45.0)
00664         normalized_degrees+=360.0;
00665       for (rotations=0; normalized_degrees > 45.0; rotations++)
00666         normalized_degrees-=90.0;
00667       switch (rotations % 4)
00668       {
00669         default:
00670         case 0:
00671           break;
00672         case 1:
00673         {
00674           /*
00675             Rotate 90 degrees.
00676           */
00677           x-=(int) annotate_image->columns/2;
00678           y+=(int) annotate_image->columns/2;
00679           break;
00680         }
00681         case 2:
00682         {
00683           /*
00684             Rotate 180 degrees.
00685           */
00686           x=x-(int) annotate_image->columns;
00687           break;
00688         }
00689         case 3:
00690         {
00691           /*
00692             Rotate 270 degrees.
00693           */
00694           x=x-(int) annotate_image->columns/2;
00695           y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
00696           break;
00697         }
00698       }
00699     }
00700   /*
00701     Composite text onto the image.
00702   */
00703   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
00704   matte=image->matte;
00705   (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
00706     OverCompositeOp : CopyCompositeOp,annotate_image,(ssize_t) x,(ssize_t) y,
00707     exception);
00708   image->matte=matte;
00709   annotate_image=DestroyImage(annotate_image);
00710   return(MagickTrue);
00711 }
00712 
00713 /*
00714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00715 %                                                                             %
00716 %                                                                             %
00717 %                                                                             %
00718 %   X B e s t F o n t                                                         %
00719 %                                                                             %
00720 %                                                                             %
00721 %                                                                             %
00722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00723 %
00724 %  XBestFont() returns the "best" font.  "Best" is defined as a font specified
00725 %  in the X resource database or a font such that the text width displayed
00726 %  with the font does not exceed the specified maximum width.
00727 %
00728 %  The format of the XBestFont method is:
00729 %
00730 %      XFontStruct *XBestFont(Display *display,
00731 %        const XResourceInfo *resource_info,const MagickBooleanType text_font)
00732 %
00733 %  A description of each parameter follows:
00734 %
00735 %    o font: XBestFont returns a pointer to a XFontStruct structure.
00736 %
00737 %    o display: Specifies a connection to an X server;  returned from
00738 %      XOpenDisplay.
00739 %
00740 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
00741 %
00742 %    o text_font:  True is font should be mono-spaced (typewriter style).
00743 %
00744 */
00745 
00746 static char **FontToList(char *font)
00747 {
00748   char
00749     **fontlist;
00750 
00751   register char
00752     *p,
00753     *q;
00754 
00755   register int
00756     i;
00757 
00758   unsigned int
00759     fonts;
00760 
00761   if (font == (char *) NULL)
00762     return((char **) NULL);
00763   /*
00764     Convert string to an ASCII list.
00765   */
00766   fonts=1U;
00767   for (p=font; *p != '\0'; p++)
00768     if ((*p == ':') || (*p == ';') || (*p == ','))
00769       fonts++;
00770   fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
00771   if (fontlist == (char **) NULL)
00772     {
00773       ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
00774         font);
00775       return((char **) NULL);
00776     }
00777   p=font;
00778   for (i=0; i < (int) fonts; i++)
00779   {
00780     for (q=p; *q != '\0'; q++)
00781       if ((*q == ':') || (*q == ';') || (*q == ','))
00782         break;
00783     fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
00784       sizeof(*fontlist[i]));
00785     if (fontlist[i] == (char *) NULL)
00786       {
00787         ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
00788           font);
00789         return((char **) NULL);
00790       }
00791     (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
00792     p=q+1;
00793   }
00794   fontlist[i]=(char *) NULL;
00795   return(fontlist);
00796 }
00797 
00798 MagickPrivate XFontStruct *XBestFont(Display *display,
00799   const XResourceInfo *resource_info,const MagickBooleanType text_font)
00800 {
00801   static const char
00802     *Fonts[]=
00803     {
00804       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
00805       "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
00806       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
00807       "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
00808       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
00809       "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
00810       "variable",
00811       "fixed",
00812       (char *) NULL
00813     },
00814     *TextFonts[]=
00815     {
00816       "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
00817       "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
00818       "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
00819       "fixed",
00820       (char *) NULL
00821     };
00822 
00823   char
00824     *font_name;
00825 
00826   register const char
00827     **p;
00828 
00829   XFontStruct
00830     *font_info;
00831 
00832   font_info=(XFontStruct *) NULL;
00833   font_name=resource_info->font;
00834   if (text_font != MagickFalse)
00835     font_name=resource_info->text_font;
00836   if ((font_name != (char *) NULL) && (*font_name != '\0'))
00837     {
00838       char
00839         **fontlist;
00840 
00841       register int
00842         i;
00843 
00844       /*
00845         Load preferred font specified in the X resource database.
00846       */
00847       fontlist=FontToList(font_name);
00848       if (fontlist != (char **) NULL)
00849         {
00850           for (i=0; fontlist[i] != (char *) NULL; i++)
00851           {
00852             if (font_info == (XFontStruct *) NULL)
00853               font_info=XLoadQueryFont(display,fontlist[i]);
00854             fontlist[i]=DestroyString(fontlist[i]);
00855           }
00856           fontlist=(char **) RelinquishMagickMemory(fontlist);
00857         }
00858       if (font_info == (XFontStruct *) NULL)
00859         ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
00860     }
00861   /*
00862     Load fonts from list of fonts until one is found.
00863   */
00864   p=Fonts;
00865   if (text_font != MagickFalse)
00866     p=TextFonts;
00867   if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
00868     p++;
00869   while (*p != (char *) NULL)
00870   {
00871     if (font_info != (XFontStruct *) NULL)
00872       break;
00873     font_info=XLoadQueryFont(display,(char *) *p);
00874     p++;
00875   }
00876   return(font_info);
00877 }
00878 
00879 /*
00880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00881 %                                                                             %
00882 %                                                                             %
00883 %                                                                             %
00884 %   X B e s t I c o n S i z e                                                 %
00885 %                                                                             %
00886 %                                                                             %
00887 %                                                                             %
00888 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00889 %
00890 %  XBestIconSize() returns the "best" icon size.  "Best" is defined as an icon
00891 %  size that maintains the aspect ratio of the image.  If the window manager
00892 %  has preferred icon sizes, one of the preferred sizes is used.
00893 %
00894 %  The format of the XBestIconSize method is:
00895 %
00896 %      void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
00897 %
00898 %  A description of each parameter follows:
00899 %
00900 %    o display: Specifies a connection to an X server;  returned from
00901 %      XOpenDisplay.
00902 %
00903 %    o image: the image.
00904 %
00905 */
00906 MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
00907   Image *image)
00908 {
00909   int
00910     i,
00911     number_sizes;
00912 
00913   MagickRealType
00914     scale_factor;
00915 
00916   unsigned int
00917     height,
00918     icon_height,
00919     icon_width,
00920     width;
00921 
00922   Window
00923     root_window;
00924 
00925   XIconSize
00926     *icon_size,
00927     *size_list;
00928 
00929   /*
00930     Determine if the window manager has specified preferred icon sizes.
00931   */
00932   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00933   assert(display != (Display *) NULL);
00934   assert(window != (XWindowInfo *) NULL);
00935   assert(image != (Image *) NULL);
00936   window->width=MaxIconSize;
00937   window->height=MaxIconSize;
00938   icon_size=(XIconSize *) NULL;
00939   number_sizes=0;
00940   root_window=XRootWindow(display,window->screen);
00941   if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
00942     if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
00943       icon_size=size_list;
00944   if (icon_size == (XIconSize *) NULL)
00945     {
00946       /*
00947         Window manager does not restrict icon size.
00948       */
00949       icon_size=XAllocIconSize();
00950       if (icon_size == (XIconSize *) NULL)
00951         {
00952           ThrowXWindowFatalException(ResourceLimitError,
00953             "MemoryAllocationFailed",image->filename);
00954           return;
00955         }
00956       icon_size->min_width=1;
00957       icon_size->max_width=MaxIconSize;
00958       icon_size->min_height=1;
00959       icon_size->max_height=MaxIconSize;
00960       icon_size->width_inc=1;
00961       icon_size->height_inc=1;
00962     }
00963   /*
00964     Determine aspect ratio of image.
00965   */
00966   width=(unsigned int) image->columns;
00967   height=(unsigned int) image->rows;
00968   i=0;
00969   if (window->crop_geometry)
00970     (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
00971   /*
00972     Look for an icon size that maintains the aspect ratio of image.
00973   */
00974   scale_factor=(MagickRealType) icon_size->max_width/width;
00975   if (scale_factor > ((MagickRealType) icon_size->max_height/height))
00976     scale_factor=(MagickRealType) icon_size->max_height/height;
00977   icon_width=(unsigned int) icon_size->min_width;
00978   while ((int) icon_width < icon_size->max_width)
00979   {
00980     if (icon_width >= (unsigned int) (scale_factor*width+0.5))
00981       break;
00982     icon_width+=icon_size->width_inc;
00983   }
00984   icon_height=(unsigned int) icon_size->min_height;
00985   while ((int) icon_height < icon_size->max_height)
00986   {
00987     if (icon_height >= (unsigned int) (scale_factor*height+0.5))
00988       break;
00989     icon_height+=icon_size->height_inc;
00990   }
00991   (void) XFree((void *) icon_size);
00992   window->width=icon_width;
00993   window->height=icon_height;
00994 }
00995 
00996 /*
00997 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00998 %                                                                             %
00999 %                                                                             %
01000 %                                                                             %
01001 %   X B e s t P i x e l                                                       %
01002 %                                                                             %
01003 %                                                                             %
01004 %                                                                             %
01005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01006 %
01007 %  XBestPixel() returns a pixel from an array of pixels that is closest to the
01008 %  requested color.  If the color array is NULL, the colors are obtained from
01009 %  the X server.
01010 %
01011 %  The format of the XBestPixel method is:
01012 %
01013 %      void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
01014 %        unsigned int number_colors,XColor *color)
01015 %
01016 %  A description of each parameter follows:
01017 %
01018 %    o pixel: XBestPixel returns the pixel value closest to the requested
01019 %      color.
01020 %
01021 %    o display: Specifies a connection to an X server;  returned from
01022 %      XOpenDisplay.
01023 %
01024 %    o colormap: Specifies the ID of the X server colormap.
01025 %
01026 %    o colors: Specifies an array of XColor structures.
01027 %
01028 %    o number_colors: Specifies the number of XColor structures in the
01029 %      color definition array.
01030 %
01031 %    o color: Specifies the desired RGB value to find in the colors array.
01032 %
01033 */
01034 MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
01035   XColor *colors,unsigned int number_colors,XColor *color)
01036 {
01037   MagickBooleanType
01038     query_server;
01039 
01040   PixelInfo
01041     pixel;
01042 
01043   MagickRealType
01044     min_distance;
01045 
01046   register MagickRealType
01047     distance;
01048 
01049   register int
01050     i,
01051     j;
01052 
01053   Status
01054     status;
01055 
01056   /*
01057     Find closest representation for the requested RGB color.
01058   */
01059   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01060   assert(display != (Display *) NULL);
01061   assert(color != (XColor *) NULL);
01062   status=XAllocColor(display,colormap,color);
01063   if (status != False)
01064     return;
01065   query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
01066   if (query_server != MagickFalse)
01067     {
01068       /*
01069         Read X server colormap.
01070       */
01071       colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
01072       if (colors == (XColor *) NULL)
01073         {
01074           ThrowXWindowFatalException(ResourceLimitError,
01075             "MemoryAllocationFailed","...");
01076           return;
01077         }
01078       for (i=0; i < (int) number_colors; i++)
01079         colors[i].pixel=(size_t) i;
01080       if (number_colors > 256)
01081         number_colors=256;
01082       (void) XQueryColors(display,colormap,colors,(int) number_colors);
01083     }
01084   min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
01085     QuantumRange+1.0);
01086   j=0;
01087   for (i=0; i < (int) number_colors; i++)
01088   {
01089     pixel.red=colors[i].red-(MagickRealType) color->red;
01090     distance=pixel.red*pixel.red;
01091     if (distance > min_distance)
01092       continue;
01093     pixel.green=colors[i].green-(MagickRealType) color->green;
01094     distance+=pixel.green*pixel.green;
01095     if (distance > min_distance)
01096       continue;
01097     pixel.blue=colors[i].blue-(MagickRealType) color->blue;
01098     distance+=pixel.blue*pixel.blue;
01099     if (distance > min_distance)
01100       continue;
01101     min_distance=distance;
01102     color->pixel=colors[i].pixel;
01103     j=i;
01104   }
01105   (void) XAllocColor(display,colormap,&colors[j]);
01106   if (query_server != MagickFalse)
01107     colors=(XColor *) RelinquishMagickMemory(colors);
01108 }
01109 
01110 /*
01111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01112 %                                                                             %
01113 %                                                                             %
01114 %                                                                             %
01115 %   X B e s t V i s u a l I n f o                                             %
01116 %                                                                             %
01117 %                                                                             %
01118 %                                                                             %
01119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01120 %
01121 %  XBestVisualInfo() returns visual information for a visual that is the "best"
01122 %  the server supports.  "Best" is defined as:
01123 %
01124 %    1. Restrict the visual list to those supported by the default screen.
01125 %
01126 %    2. If a visual type is specified, restrict the visual list to those of
01127 %       that type.
01128 %
01129 %    3. If a map type is specified, choose the visual that matches the id
01130 %       specified by the Standard Colormap.
01131 %
01132 %    4  From the list of visuals, choose one that can display the most
01133 %       simultaneous colors.  If more than one visual can display the same
01134 %       number of simultaneous colors, one is chosen based on a rank.
01135 %
01136 %  The format of the XBestVisualInfo method is:
01137 %
01138 %      XVisualInfo *XBestVisualInfo(Display *display,
01139 %        XStandardColormap *map_info,XResourceInfo *resource_info)
01140 %
01141 %  A description of each parameter follows:
01142 %
01143 %    o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
01144 %      structure.
01145 %
01146 %    o display: Specifies a connection to an X server;  returned from
01147 %      XOpenDisplay.
01148 %
01149 %    o map_info: If map_type is specified, this structure is initialized
01150 %      with info from the Standard Colormap.
01151 %
01152 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01153 %
01154 */
01155 
01156 static inline int MagickMax(const int x,const int y)
01157 {
01158   if (x > y)
01159     return(x);
01160   return(y);
01161 }
01162 
01163 static inline size_t MagickMin(const unsigned int x,
01164   const unsigned int y)
01165 {
01166   if (x < y)
01167     return(x);
01168   return(y);
01169 }
01170 
01171 MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
01172   XStandardColormap *map_info,XResourceInfo *resource_info)
01173 {
01174 #define MaxStandardColormaps  7
01175 #define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
01176   (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
01177    visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
01178    (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
01179 
01180   char
01181     *map_type,
01182     *visual_type;
01183 
01184   int
01185     visual_mask;
01186 
01187   register int
01188     i;
01189 
01190   size_t
01191     one;
01192 
01193   static int
01194     number_visuals;
01195 
01196   static XVisualInfo
01197     visual_template;
01198 
01199   XVisualInfo
01200     *visual_info,
01201     *visual_list;
01202 
01203   /*
01204     Restrict visual search by screen number.
01205   */
01206   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01207   assert(display != (Display *) NULL);
01208   assert(map_info != (XStandardColormap *) NULL);
01209   assert(resource_info != (XResourceInfo *) NULL);
01210   map_type=resource_info->map_type;
01211   visual_type=resource_info->visual_type;
01212   visual_mask=VisualScreenMask;
01213   visual_template.screen=XDefaultScreen(display);
01214   visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
01215   one=1;
01216   if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
01217     if (resource_info->colors <= (one << (size_t) visual_template.depth))
01218       visual_mask|=VisualDepthMask;
01219   if (visual_type != (char *) NULL)
01220     {
01221       /*
01222         Restrict visual search by class or visual id.
01223       */
01224       if (LocaleCompare("staticgray",visual_type) == 0)
01225         {
01226           visual_mask|=VisualClassMask;
01227           visual_template.klass=StaticGray;
01228         }
01229       else
01230         if (LocaleCompare("grayscale",visual_type) == 0)
01231           {
01232             visual_mask|=VisualClassMask;
01233             visual_template.klass=GrayScale;
01234           }
01235         else
01236           if (LocaleCompare("staticcolor",visual_type) == 0)
01237             {
01238               visual_mask|=VisualClassMask;
01239               visual_template.klass=StaticColor;
01240             }
01241           else
01242             if (LocaleCompare("pseudocolor",visual_type) == 0)
01243               {
01244                 visual_mask|=VisualClassMask;
01245                 visual_template.klass=PseudoColor;
01246               }
01247             else
01248               if (LocaleCompare("truecolor",visual_type) == 0)
01249                 {
01250                   visual_mask|=VisualClassMask;
01251                   visual_template.klass=TrueColor;
01252                 }
01253               else
01254                 if (LocaleCompare("directcolor",visual_type) == 0)
01255                   {
01256                     visual_mask|=VisualClassMask;
01257                     visual_template.klass=DirectColor;
01258                   }
01259                 else
01260                   if (LocaleCompare("default",visual_type) == 0)
01261                     {
01262                       visual_mask|=VisualIDMask;
01263                       visual_template.visualid=XVisualIDFromVisual(
01264                         XDefaultVisual(display,XDefaultScreen(display)));
01265                     }
01266                   else
01267                     if (isdigit((int) ((unsigned char) *visual_type)) != 0)
01268                       {
01269                         visual_mask|=VisualIDMask;
01270                         visual_template.visualid=
01271                           strtol(visual_type,(char **) NULL,0);
01272                       }
01273                     else
01274                       ThrowXWindowFatalException(XServerError,
01275                         "UnrecognizedVisualSpecifier",visual_type);
01276     }
01277   /*
01278     Get all visuals that meet our criteria so far.
01279   */
01280   number_visuals=0;
01281   visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
01282     &number_visuals);
01283   visual_mask=VisualScreenMask | VisualIDMask;
01284   if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
01285     {
01286       /*
01287         Failed to get visual;  try using the default visual.
01288       */
01289       ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
01290         visual_type);
01291       visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
01292         XDefaultScreen(display)));
01293       visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
01294         &number_visuals);
01295       if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
01296         return((XVisualInfo *) NULL);
01297       ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
01298         XVisualClassName(visual_list->klass));
01299     }
01300   resource_info->color_recovery=MagickFalse;
01301   if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
01302     {
01303       Atom
01304         map_property;
01305 
01306       char
01307         map_name[MaxTextExtent];
01308 
01309       int
01310         j,
01311         number_maps;
01312 
01313       Status
01314         status;
01315 
01316       Window
01317         root_window;
01318 
01319       XStandardColormap
01320         *map_list;
01321 
01322       /*
01323         Choose a visual associated with a standard colormap.
01324       */
01325       root_window=XRootWindow(display,XDefaultScreen(display));
01326       status=False;
01327       if (LocaleCompare(map_type,"list") != 0)
01328         {
01329           /*
01330             User specified Standard Colormap.
01331           */
01332           (void) FormatLocaleString((char *) map_name,MaxTextExtent,
01333             "RGB_%s_MAP",map_type);
01334           LocaleUpper(map_name);
01335           map_property=XInternAtom(display,(char *) map_name,MagickTrue);
01336           if (map_property != (Atom) NULL)
01337             status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
01338               map_property);
01339         }
01340       else
01341         {
01342           static const char
01343             *colormap[MaxStandardColormaps]=
01344             {
01345               "_HP_RGB_SMOOTH_MAP_LIST",
01346               "RGB_BEST_MAP",
01347               "RGB_DEFAULT_MAP",
01348               "RGB_GRAY_MAP",
01349               "RGB_RED_MAP",
01350               "RGB_GREEN_MAP",
01351               "RGB_BLUE_MAP",
01352             };
01353 
01354           /*
01355             Choose a standard colormap from a list.
01356           */
01357           for (i=0; i < MaxStandardColormaps; i++)
01358           {
01359             map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
01360             if (map_property == (Atom) NULL)
01361               continue;
01362             status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
01363               map_property);
01364             if (status != False)
01365               break;
01366           }
01367           resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
01368         }
01369       if (status == False)
01370         {
01371           ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
01372             map_type);
01373           return((XVisualInfo *) NULL);
01374         }
01375       /*
01376         Search all Standard Colormaps and visuals for ids that match.
01377       */
01378       *map_info=map_list[0];
01379 #if !defined(PRE_R4_ICCCM)
01380       visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
01381       for (i=0; i < number_maps; i++)
01382         for (j=0; j < number_visuals; j++)
01383           if (map_list[i].visualid ==
01384               XVisualIDFromVisual(visual_list[j].visual))
01385             {
01386               *map_info=map_list[i];
01387               visual_template.visualid=XVisualIDFromVisual(
01388                 visual_list[j].visual);
01389               break;
01390             }
01391       if (map_info->visualid != visual_template.visualid)
01392         {
01393           ThrowXWindowFatalException(XServerError,
01394             "UnableToMatchVisualToStandardColormap",map_type);
01395           return((XVisualInfo *) NULL);
01396         }
01397 #endif
01398       if (map_info->colormap == (Colormap) NULL)
01399         {
01400           ThrowXWindowFatalException(XServerError,
01401             "StandardColormapIsNotInitialized",map_type);
01402           return((XVisualInfo *) NULL);
01403         }
01404       (void) XFree((void *) map_list);
01405     }
01406   else
01407     {
01408       static const unsigned int
01409         rank[]=
01410           {
01411             StaticGray,
01412             GrayScale,
01413             StaticColor,
01414             DirectColor,
01415             TrueColor,
01416             PseudoColor
01417           };
01418 
01419       XVisualInfo
01420         *p;
01421 
01422       /*
01423         Pick one visual that displays the most simultaneous colors.
01424       */
01425       visual_info=visual_list;
01426       p=visual_list;
01427       for (i=1; i < number_visuals; i++)
01428       {
01429         p++;
01430         if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
01431           visual_info=p;
01432         else
01433           if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
01434             if (rank[p->klass] > rank[visual_info->klass])
01435               visual_info=p;
01436       }
01437       visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
01438     }
01439   (void) XFree((void *) visual_list);
01440   /*
01441     Retrieve only one visual by its screen & id number.
01442   */
01443   visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
01444     &number_visuals);
01445   if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
01446     return((XVisualInfo *) NULL);
01447   return(visual_info);
01448 }
01449 
01450 /*
01451 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01452 %                                                                             %
01453 %                                                                             %
01454 %                                                                             %
01455 %   X C h e c k D e f i n e C u r s o r                                       %
01456 %                                                                             %
01457 %                                                                             %
01458 %                                                                             %
01459 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01460 %
01461 %  XCheckDefineCursor() prevents cursor changes on the root window.
01462 %
01463 %  The format of the XXCheckDefineCursor method is:
01464 %
01465 %      XCheckDefineCursor(display,window,cursor)
01466 %
01467 %  A description of each parameter follows:
01468 %
01469 %    o display: Specifies a connection to an X server;  returned from
01470 %      XOpenDisplay.
01471 %
01472 %    o window: the window.
01473 %
01474 %    o cursor: the cursor.
01475 %
01476 */
01477 MagickPrivate int XCheckDefineCursor(Display *display,Window window,
01478   Cursor cursor)
01479 {
01480   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01481   assert(display != (Display *) NULL);
01482   if (window == XRootWindow(display,XDefaultScreen(display)))
01483     return(0);
01484   return(XDefineCursor(display,window,cursor));
01485 }
01486 
01487 /*
01488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01489 %                                                                             %
01490 %                                                                             %
01491 %                                                                             %
01492 %   X C h e c k R e f r e s h W i n d o w s                                   %
01493 %                                                                             %
01494 %                                                                             %
01495 %                                                                             %
01496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01497 %
01498 %  XCheckRefreshWindows() checks the X server for exposure events for a
01499 %  particular window and updates the areassociated with the exposure event.
01500 %
01501 %  The format of the XCheckRefreshWindows method is:
01502 %
01503 %      void XCheckRefreshWindows(Display *display,XWindows *windows)
01504 %
01505 %  A description of each parameter follows:
01506 %
01507 %    o display: Specifies a connection to an X server;  returned from
01508 %      XOpenDisplay.
01509 %
01510 %    o windows: Specifies a pointer to a XWindows structure.
01511 %
01512 */
01513 MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
01514 {
01515   Window
01516     id;
01517 
01518   XEvent
01519     event;
01520 
01521   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01522   assert(display != (Display *) NULL);
01523   assert(windows != (XWindows *) NULL);
01524   XDelay(display,SuspendTime);
01525   id=windows->command.id;
01526   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
01527     (void) XCommandWidget(display,windows,(char const **) NULL,&event);
01528   id=windows->image.id;
01529   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
01530     XRefreshWindow(display,&windows->image,&event);
01531   XDelay(display,SuspendTime << 1);
01532   id=windows->command.id;
01533   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
01534     (void) XCommandWidget(display,windows,(char const **) NULL,&event);
01535   id=windows->image.id;
01536   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
01537     XRefreshWindow(display,&windows->image,&event);
01538 }
01539 
01540 /*
01541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01542 %                                                                             %
01543 %                                                                             %
01544 %                                                                             %
01545 %   X C l i e n t M e s s a g e                                               %
01546 %                                                                             %
01547 %                                                                             %
01548 %                                                                             %
01549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01550 %
01551 %  XClientMessage() sends a reason to a window with XSendEvent.  The reason is
01552 %  initialized with a particular protocol type and atom.
01553 %
01554 %  The format of the XClientMessage function is:
01555 %
01556 %      XClientMessage(display,window,protocol,reason,timestamp)
01557 %
01558 %  A description of each parameter follows:
01559 %
01560 %    o display: Specifies a pointer to the Display structure;  returned from
01561 %      XOpenDisplay.
01562 %
01563 %    o window: Specifies a pointer to a Window structure.
01564 %
01565 %    o protocol: Specifies an atom value.
01566 %
01567 %    o reason: Specifies an atom value which is the reason to send.
01568 %
01569 %    o timestamp: Specifies a value of type Time.
01570 %
01571 */
01572 MagickPrivate void XClientMessage(Display *display,const Window window,
01573   const Atom protocol,const Atom reason,const Time timestamp)
01574 {
01575   XClientMessageEvent
01576     client_event;
01577 
01578   assert(display != (Display *) NULL);
01579   client_event.type=ClientMessage;
01580   client_event.window=window;
01581   client_event.message_type=protocol;
01582   client_event.format=32;
01583   client_event.data.l[0]=(long) reason;
01584   client_event.data.l[1]=(long) timestamp;
01585   (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
01586 }
01587 
01588 /*
01589 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01590 %                                                                             %
01591 %                                                                             %
01592 %                                                                             %
01593 +   X C l i e n t W i n d o w                                                 %
01594 %                                                                             %
01595 %                                                                             %
01596 %                                                                             %
01597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01598 %
01599 %  XClientWindow() finds a window, at or below the specified window, which has
01600 %  a WM_STATE property.  If such a window is found, it is returned, otherwise
01601 %  the argument window is returned.
01602 %
01603 %  The format of the XClientWindow function is:
01604 %
01605 %      client_window=XClientWindow(display,target_window)
01606 %
01607 %  A description of each parameter follows:
01608 %
01609 %    o client_window: XClientWindow returns a window, at or below the specified
01610 %      window, which has a WM_STATE property otherwise the argument
01611 %      target_window is returned.
01612 %
01613 %    o display: Specifies a pointer to the Display structure;  returned from
01614 %      XOpenDisplay.
01615 %
01616 %    o target_window: Specifies the window to find a WM_STATE property.
01617 %
01618 */
01619 static Window XClientWindow(Display *display,Window target_window)
01620 {
01621   Atom
01622     state,
01623     type;
01624 
01625   int
01626     format;
01627 
01628   Status
01629     status;
01630 
01631   unsigned char
01632     *data;
01633 
01634   unsigned long
01635     after,
01636     number_items;
01637 
01638   Window
01639     client_window;
01640 
01641   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01642   assert(display != (Display *) NULL);
01643   state=XInternAtom(display,"WM_STATE",MagickTrue);
01644   if (state == (Atom) NULL)
01645     return(target_window);
01646   type=(Atom) NULL;
01647   status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
01648     (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
01649   if ((status == Success) && (type != (Atom) NULL))
01650     return(target_window);
01651   client_window=XWindowByProperty(display,target_window,state);
01652   if (client_window == (Window) NULL)
01653     return(target_window);
01654   return(client_window);
01655 }
01656 
01657 /*
01658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01659 %                                                                             %
01660 %                                                                             %
01661 %                                                                             %
01662 +   X C o m p o n e n t T e r m i n u s                                       %
01663 %                                                                             %
01664 %                                                                             %
01665 %                                                                             %
01666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01667 %
01668 %  XComponentTerminus() destroys the module component.
01669 %
01670 %  The format of the XComponentTerminus method is:
01671 %
01672 %      XComponentTerminus(void)
01673 %
01674 */
01675 MagickPrivate void XComponentTerminus(void)
01676 {
01677   DestroyXResources();
01678 }
01679 
01680 /*
01681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01682 %                                                                             %
01683 %                                                                             %
01684 %                                                                             %
01685 %   X C o n f i g u r e I m a g e C o l o r m a p                             %
01686 %                                                                             %
01687 %                                                                             %
01688 %                                                                             %
01689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01690 %
01691 %  XConfigureImageColormap() creates a new X colormap.
01692 %
01693 %  The format of the XConfigureImageColormap method is:
01694 %
01695 %      void XConfigureImageColormap(Display *display,
01696 %        XResourceInfo *resource_info,XWindows *windows,Image *image,
01697 %        ExceptionInfo *exception)
01698 %
01699 %  A description of each parameter follows:
01700 %
01701 %    o display: Specifies a connection to an X server; returned from
01702 %      XOpenDisplay.
01703 %
01704 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01705 %
01706 %    o windows: Specifies a pointer to a XWindows structure.
01707 %
01708 %    o image: the image.
01709 %
01710 %    o exception: return any errors or warnings in this structure.
01711 %
01712 */
01713 MagickPrivate void XConfigureImageColormap(Display *display,
01714   XResourceInfo *resource_info,XWindows *windows,Image *image,
01715   ExceptionInfo *exception)
01716 {
01717   Colormap
01718     colormap;
01719 
01720   /*
01721     Make standard colormap.
01722   */
01723   XSetCursorState(display,windows,MagickTrue);
01724   XCheckRefreshWindows(display,windows);
01725   XMakeStandardColormap(display,windows->visual_info,resource_info,image,
01726     windows->map_info,windows->pixel_info,exception);
01727   colormap=windows->map_info->colormap;
01728   (void) XSetWindowColormap(display,windows->image.id,colormap);
01729   (void) XSetWindowColormap(display,windows->command.id,colormap);
01730   (void) XSetWindowColormap(display,windows->widget.id,colormap);
01731   if (windows->magnify.mapped != MagickFalse)
01732     (void) XSetWindowColormap(display,windows->magnify.id,colormap);
01733   if (windows->pan.mapped != MagickFalse)
01734     (void) XSetWindowColormap(display,windows->pan.id,colormap);
01735   XSetCursorState(display,windows,MagickFalse);
01736   XClientMessage(display,windows->image.id,windows->im_protocols,
01737     windows->im_update_colormap,CurrentTime);
01738 }
01739 
01740 /*
01741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01742 %                                                                             %
01743 %                                                                             %
01744 %                                                                             %
01745 %   X C o n s t r a i n W i n d o w P o s i t i o n                           %
01746 %                                                                             %
01747 %                                                                             %
01748 %                                                                             %
01749 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01750 %
01751 %  XConstrainWindowPosition() assures a window is positioned within the X
01752 %  server boundaries.
01753 %
01754 %  The format of the XConstrainWindowPosition method is:
01755 %
01756 %      void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
01757 %
01758 %  A description of each parameter follows:
01759 %
01760 %    o display: Specifies a pointer to the Display structure;  returned from
01761 %      XOpenDisplay.
01762 %
01763 %    o window_info: Specifies a pointer to a XWindowInfo structure.
01764 %
01765 */
01766 MagickPrivate void XConstrainWindowPosition(Display *display,
01767   XWindowInfo *window_info)
01768 {
01769   int
01770     limit;
01771 
01772   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01773   assert(display != (Display *) NULL);
01774   assert(window_info != (XWindowInfo *) NULL);
01775   limit=XDisplayWidth(display,window_info->screen)-window_info->width;
01776   if (window_info->x < 0)
01777     window_info->x=0;
01778   else
01779     if (window_info->x > (int) limit)
01780       window_info->x=(int) limit;
01781   limit=XDisplayHeight(display,window_info->screen)-window_info->height;
01782   if (window_info->y < 0)
01783     window_info->y=0;
01784   else
01785     if (window_info->y > limit)
01786       window_info->y=limit;
01787 }
01788 
01789 /*
01790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01791 %                                                                             %
01792 %                                                                             %
01793 %                                                                             %
01794 %   X D e l a y                                                               %
01795 %                                                                             %
01796 %                                                                             %
01797 %                                                                             %
01798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01799 %
01800 %  XDelay() suspends program execution for the number of milliseconds
01801 %  specified.
01802 %
01803 %  The format of the Delay method is:
01804 %
01805 %      void XDelay(Display *display,const size_t milliseconds)
01806 %
01807 %  A description of each parameter follows:
01808 %
01809 %    o display: Specifies a pointer to the Display structure;  returned from
01810 %      XOpenDisplay.
01811 %
01812 %    o milliseconds: Specifies the number of milliseconds to delay before
01813 %      returning.
01814 %
01815 */
01816 MagickPrivate void XDelay(Display *display,const size_t milliseconds)
01817 {
01818   assert(display != (Display *) NULL);
01819   (void) XFlush(display);
01820   MagickDelay(milliseconds);
01821 }
01822 
01823 /*
01824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01825 %                                                                             %
01826 %                                                                             %
01827 %                                                                             %
01828 %   X D e s t r o y R e s o u r c e I n f o                                   %
01829 %                                                                             %
01830 %                                                                             %
01831 %                                                                             %
01832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01833 %
01834 %  XDestroyResourceInfo() frees memory associated with the XResourceInfo
01835 %  structure.
01836 %
01837 %  The format of the XDestroyResourceInfo method is:
01838 %
01839 %      void XDestroyResourceInfo(XResourceInfo *resource_info)
01840 %
01841 %  A description of each parameter follows:
01842 %
01843 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01844 %
01845 */
01846 MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
01847 {
01848   if (resource_info->image_geometry != (char *) NULL)
01849     resource_info->image_geometry=(char *)
01850       RelinquishMagickMemory(resource_info->image_geometry);
01851   if (resource_info->quantize_info != (QuantizeInfo *) NULL)
01852     resource_info->quantize_info=DestroyQuantizeInfo(
01853       resource_info->quantize_info);
01854   if (resource_info->client_name != (char *) NULL)
01855     resource_info->client_name=(char *)
01856       RelinquishMagickMemory(resource_info->client_name);
01857   if (resource_info->name != (char *) NULL)
01858     resource_info->name=DestroyString(resource_info->name);
01859   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
01860 }
01861 
01862 /*
01863 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01864 %                                                                             %
01865 %                                                                             %
01866 %                                                                             %
01867 %   X D e s t r o y W i n d o w C o l o r s                                   %
01868 %                                                                             %
01869 %                                                                             %
01870 %                                                                             %
01871 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01872 %
01873 %  XDestroyWindowColors() frees X11 color resources previously saved on a
01874 %  window by XRetainWindowColors or programs like xsetroot.
01875 %
01876 %  The format of the XDestroyWindowColors method is:
01877 %
01878 %      void XDestroyWindowColors(Display *display,Window window)
01879 %
01880 %  A description of each parameter follows:
01881 %
01882 %    o display: Specifies a connection to an X server; returned from
01883 %      XOpenDisplay.
01884 %
01885 %    o window: Specifies a pointer to a Window structure.
01886 %
01887 */
01888 MagickPrivate void XDestroyWindowColors(Display *display,Window window)
01889 {
01890   Atom
01891     property,
01892     type;
01893 
01894   int
01895     format;
01896 
01897   Status
01898     status;
01899 
01900   unsigned char
01901     *data;
01902 
01903   unsigned long
01904     after,
01905     length;
01906 
01907   /*
01908     If there are previous resources on the root window, destroy them.
01909   */
01910   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01911   assert(display != (Display *) NULL);
01912   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
01913   if (property == (Atom) NULL)
01914     {
01915       ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
01916         "_XSETROOT_ID");
01917       return;
01918     }
01919   status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
01920     (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
01921   if (status != Success)
01922     return;
01923   if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
01924     {
01925       (void) XKillClient(display,(XID) (*((Pixmap *) data)));
01926       (void) XDeleteProperty(display,window,property);
01927     }
01928   if (type != None)
01929     (void) XFree((void *) data);
01930 }
01931 
01932 /*
01933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01934 %                                                                             %
01935 %                                                                             %
01936 %                                                                             %
01937 %   X D i s p l a y I m a g e I n f o                                         %
01938 %                                                                             %
01939 %                                                                             %
01940 %                                                                             %
01941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01942 %
01943 %  XDisplayImageInfo() displays information about an X image.
01944 %
01945 %  The format of the XDisplayImageInfo method is:
01946 %
01947 %      void XDisplayImageInfo(Display *display,
01948 %        const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
01949 %        Image *image,ExceptionInfo *exception)
01950 %
01951 %  A description of each parameter follows:
01952 %
01953 %    o display: Specifies a connection to an X server;  returned from
01954 %      XOpenDisplay.
01955 %
01956 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01957 %
01958 %    o windows: Specifies a pointer to a XWindows structure.
01959 %
01960 %    o undo_image: the undo image.
01961 %
01962 %    o image: the image.
01963 %
01964 %    o exception: return any errors or warnings in this structure.
01965 %
01966 */
01967 MagickPrivate void XDisplayImageInfo(Display *display,
01968   const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
01969   Image *image,ExceptionInfo *exception)
01970 {
01971   char
01972     filename[MaxTextExtent],
01973     *text,
01974     **textlist;
01975 
01976   FILE
01977     *file;
01978 
01979   int
01980     unique_file;
01981 
01982   register ssize_t
01983     i;
01984 
01985   size_t
01986     number_pixels;
01987 
01988   ssize_t
01989     bytes;
01990 
01991   unsigned int
01992     levels;
01993 
01994   /*
01995     Write info about the X server to a file.
01996   */
01997   assert(display != (Display *) NULL);
01998   assert(resource_info != (XResourceInfo *) NULL);
01999   assert(windows != (XWindows *) NULL);
02000   assert(image != (Image *) NULL);
02001   if (image->debug)
02002     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02003   file=(FILE *) NULL;
02004   unique_file=AcquireUniqueFileResource(filename);
02005   if (unique_file != -1)
02006     file=fdopen(unique_file,"w");
02007   if ((unique_file == -1) || (file == (FILE *) NULL))
02008     {
02009       XNoticeWidget(display,windows,"Unable to display image info",filename);
02010       return;
02011     }
02012   if (resource_info->gamma_correct != MagickFalse)
02013     if (resource_info->display_gamma != (char *) NULL)
02014       (void) FormatLocaleFile(file,"Display\n  gamma: %s\n\n",
02015         resource_info->display_gamma);
02016   /*
02017     Write info about the X image to a file.
02018   */
02019   (void) FormatLocaleFile(file,"X\n  visual: %s\n",
02020     XVisualClassName((int) windows->image.storage_class));
02021   (void) FormatLocaleFile(file,"  depth: %d\n",windows->image.ximage->depth);
02022   if (windows->visual_info->colormap_size != 0)
02023     (void) FormatLocaleFile(file,"  colormap size: %d\n",
02024       windows->visual_info->colormap_size);
02025   if (resource_info->colormap== SharedColormap)
02026     (void) FormatLocaleFile(file,"  colormap type: Shared\n");
02027   else
02028     (void) FormatLocaleFile(file,"  colormap type: Private\n");
02029   (void) FormatLocaleFile(file,"  geometry: %dx%d\n",
02030     windows->image.ximage->width,windows->image.ximage->height);
02031   if (windows->image.crop_geometry != (char *) NULL)
02032     (void) FormatLocaleFile(file,"  crop geometry: %s\n",
02033       windows->image.crop_geometry);
02034   if (windows->image.pixmap == (Pixmap) NULL)
02035     (void) FormatLocaleFile(file,"  type: X Image\n");
02036   else
02037     (void) FormatLocaleFile(file,"  type: Pixmap\n");
02038   if (windows->image.shape != MagickFalse)
02039     (void) FormatLocaleFile(file,"  non-rectangular shape: True\n");
02040   else
02041     (void) FormatLocaleFile(file,"  non-rectangular shape: False\n");
02042   if (windows->image.shared_memory != MagickFalse)
02043     (void) FormatLocaleFile(file,"  shared memory: True\n");
02044   else
02045     (void) FormatLocaleFile(file,"  shared memory: False\n");
02046   (void) FormatLocaleFile(file,"\n");
02047   if (resource_info->font != (char *) NULL)
02048     (void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
02049   if (resource_info->text_font != (char *) NULL)
02050     (void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
02051   /*
02052     Write info about the undo cache to a file.
02053   */
02054   bytes=0;
02055   for (levels=0; undo_image != (Image *) NULL; levels++)
02056   {
02057     number_pixels=undo_image->list->columns*undo_image->list->rows;
02058     bytes+=number_pixels*sizeof(PixelInfo);
02059     undo_image=GetPreviousImageInList(undo_image);
02060   }
02061   (void) FormatLocaleFile(file,"Undo Edit Cache\n  levels: %u\n",levels);
02062   (void) FormatLocaleFile(file,"  bytes: %.20gmb\n",(double)
02063     ((bytes+(1 << 19)) >> 20));
02064   (void) FormatLocaleFile(file,"  limit: %.20gmb\n\n",(double)
02065     resource_info->undo_cache);
02066   /*
02067     Write info about the image to a file.
02068   */
02069   (void) IdentifyImage(image,file,MagickTrue,exception);
02070   (void) fclose(file);
02071   text=FileToString(filename,~0,exception);
02072   (void) RelinquishUniqueFileResource(filename);
02073   if (text == (char *) NULL)
02074     {
02075       XNoticeWidget(display,windows,"MemoryAllocationFailed",
02076         "UnableToDisplayImageInfo");
02077       return;
02078     }
02079   textlist=StringToList(text);
02080   if (textlist != (char **) NULL)
02081     {
02082       char
02083         title[MaxTextExtent];
02084 
02085       /*
02086         Display information about the image in the Text View widget.
02087       */
02088       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
02089       (void) FormatLocaleString(title,MaxTextExtent,"Image Info: %s",
02090         image->filename);
02091       XTextViewWidget(display,resource_info,windows,MagickTrue,title,
02092         (char const **) textlist);
02093       for (i=0; textlist[i] != (char *) NULL; i++)
02094         textlist[i]=DestroyString(textlist[i]);
02095       textlist=(char **) RelinquishMagickMemory(textlist);
02096     }
02097   text=DestroyString(text);
02098 }
02099 
02100 /*
02101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02102 %                                                                             %
02103 %                                                                             %
02104 %                                                                             %
02105 +     X D i t h e r I m a g e                                                 %
02106 %                                                                             %
02107 %                                                                             %
02108 %                                                                             %
02109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02110 %
02111 %  XDitherImage() dithers the reference image as required by the HP Color
02112 %  Recovery algorithm.  The color values are quantized to 3 bits of red and
02113 %  green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
02114 %  standard colormap.
02115 %
02116 %  The format of the XDitherImage method is:
02117 %
02118 %      void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
02119 %
02120 %  A description of each parameter follows:
02121 %
02122 %    o image: the image.
02123 %
02124 %    o ximage: Specifies a pointer to a XImage structure;  returned from
02125 %      XCreateImage.
02126 %
02127 %    o exception: return any errors or warnings in this structure.
02128 %
02129 */
02130 static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
02131 {
02132   static const short int
02133     dither_red[2][16]=
02134     {
02135       {-16,  4, -1, 11,-14,  6, -3,  9,-15,  5, -2, 10,-13,  7, -4,  8},
02136       { 15, -5,  0,-12, 13, -7,  2,-10, 14, -6,  1,-11, 12, -8,  3, -9}
02137     },
02138     dither_green[2][16]=
02139     {
02140       { 11,-15,  7, -3,  8,-14,  4, -2, 10,-16,  6, -4,  9,-13,  5, -1},
02141       {-12, 14, -8,  2, -9, 13, -5,  1,-11, 15, -7,  3,-10, 12, -6,  0}
02142     },
02143     dither_blue[2][16]=
02144     {
02145       { -3,  9,-13,  7, -1, 11,-15,  5, -4,  8,-14,  6, -2, 10,-16,  4},
02146       {  2,-10, 12, -8,  0,-12, 14, -6,  3, -9, 13, -7,  1,-11, 15, -5}
02147     };
02148 
02149   CacheView
02150     *image_view;
02151 
02152   int
02153     value,
02154     y;
02155 
02156   PixelInfo
02157     color;
02158 
02159   register char
02160     *q;
02161 
02162   register const Quantum
02163     *p;
02164 
02165   register int
02166     i,
02167     j,
02168     x;
02169 
02170   unsigned int
02171     scanline_pad;
02172 
02173   register size_t
02174     pixel;
02175 
02176   unsigned char
02177     *blue_map[2][16],
02178     *green_map[2][16],
02179     *red_map[2][16];
02180 
02181   /*
02182     Allocate and initialize dither maps.
02183   */
02184   for (i=0; i < 2; i++)
02185     for (j=0; j < 16; j++)
02186     {
02187       red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02188         sizeof(*red_map));
02189       green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02190         sizeof(*green_map));
02191       blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02192         sizeof(*blue_map));
02193       if ((red_map[i][j] == (unsigned char *) NULL) ||
02194           (green_map[i][j] == (unsigned char *) NULL) ||
02195           (blue_map[i][j] == (unsigned char *) NULL))
02196         {
02197           ThrowXWindowFatalException(ResourceLimitError,
02198             "MemoryAllocationFailed",image->filename);
02199           return;
02200         }
02201     }
02202   /*
02203     Initialize dither tables.
02204   */
02205   for (i=0; i < 2; i++)
02206     for (j=0; j < 16; j++)
02207       for (x=0; x < 256; x++)
02208       {
02209         value=x-16;
02210         if (x < 48)
02211           value=x/2+8;
02212         value+=dither_red[i][j];
02213         red_map[i][j][x]=(unsigned char)
02214           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02215         value=x-16;
02216         if (x < 48)
02217           value=x/2+8;
02218         value+=dither_green[i][j];
02219         green_map[i][j][x]=(unsigned char)
02220           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02221         value=x-32;
02222         if (x < 112)
02223           value=x/2+24;
02224         value+=((size_t) dither_blue[i][j] << 1);
02225         blue_map[i][j][x]=(unsigned char)
02226           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02227       }
02228   /*
02229     Dither image.
02230   */
02231   scanline_pad=(unsigned int) (ximage->bytes_per_line-
02232     ((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
02233   i=0;
02234   j=0;
02235   q=ximage->data;
02236   image_view=AcquireCacheView(image);
02237   for (y=0; y < (int) image->rows; y++)
02238   {
02239     p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
02240       exception);
02241     if (p == (const Quantum *) NULL)
02242       break;
02243     for (x=0; x < (int) image->columns; x++)
02244     {
02245       color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
02246         ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
02247       color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
02248         ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
02249       color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
02250         ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
02251       pixel=(size_t) (((size_t) color.red & 0xe0) |
02252         (((size_t) color.green & 0xe0) >> 3) |
02253         (((size_t) color.blue & 0xc0) >> 6));
02254       *q++=(char) pixel;
02255       p+=GetPixelChannels(image);
02256       j++;
02257       if (j == 16)
02258         j=0;
02259     }
02260     q+=scanline_pad;
02261     i++;
02262     if (i == 2)
02263       i=0;
02264   }
02265   image_view=DestroyCacheView(image_view);
02266   /*
02267     Free allocated memory.
02268   */
02269   for (i=0; i < 2; i++)
02270     for (j=0; j < 16; j++)
02271     {
02272       green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
02273       blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
02274       red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
02275     }
02276 }
02277 
02278 /*
02279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02280 %                                                                             %
02281 %                                                                             %
02282 %                                                                             %
02283 %   X D r a w I m a g e                                                       %
02284 %                                                                             %
02285 %                                                                             %
02286 %                                                                             %
02287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02288 %
02289 %  XDrawImage() draws a line on the image.
02290 %
02291 %  The format of the XDrawImage method is:
02292 %
02293 %    MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
02294 %      XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
02295 %
02296 %  A description of each parameter follows:
02297 %
02298 %    o display: Specifies a connection to an X server;  returned from
02299 %      XOpenDisplay.
02300 %
02301 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02302 %
02303 %    o draw_info: Specifies a pointer to a XDrawInfo structure.
02304 %
02305 %    o image: the image.
02306 %
02307 %    o exception: return any errors or warnings in this structure.
02308 %
02309 */
02310 MagickPrivate MagickBooleanType XDrawImage(Display *display,
02311   const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
02312   ExceptionInfo *exception)
02313 {
02314   CacheView
02315     *draw_view;
02316 
02317   GC
02318     draw_context;
02319 
02320   Image
02321     *draw_image;
02322 
02323   int
02324     x,
02325     y;
02326 
02327   MagickBooleanType
02328     matte;
02329 
02330   Quantum
02331     virtual_pixel[CompositePixelChannel];
02332 
02333   Pixmap
02334     draw_pixmap;
02335 
02336   unsigned int
02337     depth,
02338     height,
02339     width;
02340 
02341   Window
02342     root_window;
02343 
02344   XGCValues
02345     context_values;
02346 
02347   XImage
02348     *draw_ximage;
02349 
02350   /*
02351     Initialize drawd image.
02352   */
02353   assert(display != (Display *) NULL);
02354   assert(pixel != (XPixelInfo *) NULL);
02355   assert(draw_info != (XDrawInfo *) NULL);
02356   assert(image != (Image *) NULL);
02357   if (image->debug != MagickFalse)
02358     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02359   /*
02360     Initialize drawd pixmap.
02361   */
02362   root_window=XRootWindow(display,XDefaultScreen(display));
02363   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
02364   draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
02365     draw_info->height,depth);
02366   if (draw_pixmap == (Pixmap) NULL)
02367     return(MagickFalse);
02368   /*
02369     Initialize graphics info.
02370   */
02371   context_values.background=(size_t) (~0);
02372   context_values.foreground=0;
02373   context_values.line_width=(int) draw_info->line_width;
02374   draw_context=XCreateGC(display,root_window,(size_t)
02375     (GCBackground | GCForeground | GCLineWidth),&context_values);
02376   if (draw_context == (GC) NULL)
02377     return(MagickFalse);
02378   /*
02379     Clear pixmap.
02380   */
02381   (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
02382     draw_info->height);
02383   /*
02384     Draw line to pixmap.
02385   */
02386   (void) XSetBackground(display,draw_context,0);
02387   (void) XSetForeground(display,draw_context,(size_t) (~0));
02388   if (draw_info->stipple !=  (Pixmap) NULL)
02389     {
02390       (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
02391       (void) XSetStipple(display,draw_context,draw_info->stipple);
02392     }
02393   switch (draw_info->element)
02394   {
02395     case PointElement:
02396     default:
02397     {
02398       (void) XDrawLines(display,draw_pixmap,draw_context,
02399         draw_info->coordinate_info,(int) draw_info->number_coordinates,
02400         CoordModeOrigin);
02401       break;
02402     }
02403     case LineElement:
02404     {
02405       (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
02406         draw_info->line_info.y1,draw_info->line_info.x2,
02407         draw_info->line_info.y2);
02408       break;
02409     }
02410     case RectangleElement:
02411     {
02412       (void) XDrawRectangle(display,draw_pixmap,draw_context,
02413         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02414         (unsigned int) draw_info->rectangle_info.width,
02415         (unsigned int) draw_info->rectangle_info.height);
02416       break;
02417     }
02418     case FillRectangleElement:
02419     {
02420       (void) XFillRectangle(display,draw_pixmap,draw_context,
02421         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02422         (unsigned int) draw_info->rectangle_info.width,
02423         (unsigned int) draw_info->rectangle_info.height);
02424       break;
02425     }
02426     case CircleElement:
02427     case EllipseElement:
02428     {
02429       (void) XDrawArc(display,draw_pixmap,draw_context,
02430         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02431         (unsigned int) draw_info->rectangle_info.width,
02432         (unsigned int) draw_info->rectangle_info.height,0,360*64);
02433       break;
02434     }
02435     case FillCircleElement:
02436     case FillEllipseElement:
02437     {
02438       (void) XFillArc(display,draw_pixmap,draw_context,
02439         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02440         (unsigned int) draw_info->rectangle_info.width,
02441         (unsigned int) draw_info->rectangle_info.height,0,360*64);
02442       break;
02443     }
02444     case PolygonElement:
02445     {
02446       XPoint
02447         *coordinate_info;
02448 
02449       coordinate_info=draw_info->coordinate_info;
02450       (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
02451         (int) draw_info->number_coordinates,CoordModeOrigin);
02452       (void) XDrawLine(display,draw_pixmap,draw_context,
02453         coordinate_info[draw_info->number_coordinates-1].x,
02454         coordinate_info[draw_info->number_coordinates-1].y,
02455         coordinate_info[0].x,coordinate_info[0].y);
02456       break;
02457     }
02458     case FillPolygonElement:
02459     {
02460       (void) XFillPolygon(display,draw_pixmap,draw_context,
02461         draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
02462         CoordModeOrigin);
02463       break;
02464     }
02465   }
02466   (void) XFreeGC(display,draw_context);
02467   /*
02468     Initialize X image.
02469   */
02470   draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
02471     draw_info->height,AllPlanes,ZPixmap);
02472   if (draw_ximage == (XImage *) NULL)
02473     return(MagickFalse);
02474   (void) XFreePixmap(display,draw_pixmap);
02475   /*
02476     Initialize draw image.
02477   */
02478   draw_image=AcquireImage((ImageInfo *) NULL,exception);
02479   if (draw_image == (Image *) NULL)
02480     return(MagickFalse);
02481   draw_image->columns=draw_info->width;
02482   draw_image->rows=draw_info->height;
02483   /*
02484     Transfer drawn X image to image.
02485   */
02486   width=(unsigned int) image->columns;
02487   height=(unsigned int) image->rows;
02488   x=0;
02489   y=0;
02490   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02491   (void) GetOneVirtualPixel(image,(ssize_t) x,(ssize_t) y,virtual_pixel,
02492     exception);
02493   draw_image->background_color.red=virtual_pixel[RedPixelChannel];
02494   draw_image->background_color.green=virtual_pixel[GreenPixelChannel];
02495   draw_image->background_color.blue=virtual_pixel[BluePixelChannel];
02496   draw_image->background_color.alpha=virtual_pixel[AlphaPixelChannel];
02497   if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
02498     return(MagickFalse);
02499   draw_image->matte=MagickTrue;
02500   draw_view=AcquireCacheView(draw_image);
02501   for (y=0; y < (int) draw_image->rows; y++)
02502   {
02503     register int
02504       x;
02505 
02506     register Quantum
02507       *restrict q;
02508 
02509     q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
02510       1,exception);
02511     if (q == (Quantum *) NULL)
02512       break;
02513     for (x=0; x < (int) draw_image->columns; x++)
02514     {
02515       if (XGetPixel(draw_ximage,x,y) == 0)
02516         {
02517           /*
02518             Set this pixel to the background color.
02519           */
02520           SetPixelInfoPixel(draw_image,&draw_image->background_color,q);
02521           SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
02522             OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
02523         }
02524       else
02525         {
02526           /*
02527             Set this pixel to the pen color.
02528           */
02529           SetPixelRed(draw_image,ScaleShortToQuantum(
02530             pixel->pen_color.red),q);
02531           SetPixelGreen(draw_image,ScaleShortToQuantum(
02532             pixel->pen_color.green),q);
02533           SetPixelBlue(draw_image,ScaleShortToQuantum(
02534             pixel->pen_color.blue),q);
02535           SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
02536             OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
02537         }
02538       q+=GetPixelChannels(draw_image);
02539     }
02540     if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
02541       break;
02542   }
02543   draw_view=DestroyCacheView(draw_view);
02544   XDestroyImage(draw_ximage);
02545   /*
02546     Determine draw geometry.
02547   */
02548   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02549   if ((width != (unsigned int) draw_image->columns) ||
02550       (height != (unsigned int) draw_image->rows))
02551     {
02552       char
02553         image_geometry[MaxTextExtent];
02554 
02555       /*
02556         Scale image.
02557       */
02558       (void) FormatLocaleString(image_geometry,MaxTextExtent,"%ux%u",
02559         width,height);
02560       (void) TransformImage(&draw_image,(char *) NULL,image_geometry,
02561         exception);
02562     }
02563   if (draw_info->degrees != 0.0)
02564     {
02565       Image
02566         *rotate_image;
02567 
02568       int
02569         rotations;
02570 
02571       MagickRealType
02572         normalized_degrees;
02573 
02574       /*
02575         Rotate image.
02576       */
02577       rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
02578       if (rotate_image == (Image *) NULL)
02579         return(MagickFalse);
02580       draw_image=DestroyImage(draw_image);
02581       draw_image=rotate_image;
02582       /*
02583         Annotation is relative to the degree of rotation.
02584       */
02585       normalized_degrees=draw_info->degrees;
02586       while (normalized_degrees < -45.0)
02587         normalized_degrees+=360.0;
02588       for (rotations=0; normalized_degrees > 45.0; rotations++)
02589         normalized_degrees-=90.0;
02590       switch (rotations % 4)
02591       {
02592         default:
02593         case 0:
02594           break;
02595         case 1:
02596         {
02597           /*
02598             Rotate 90 degrees.
02599           */
02600           x=x-(int) draw_image->columns/2;
02601           y=y+(int) draw_image->columns/2;
02602           break;
02603         }
02604         case 2:
02605         {
02606           /*
02607             Rotate 180 degrees.
02608           */
02609           x=x-(int) draw_image->columns;
02610           break;
02611         }
02612         case 3:
02613         {
02614           /*
02615             Rotate 270 degrees.
02616           */
02617           x=x-(int) draw_image->columns/2;
02618           y=y-(int) (draw_image->rows-(draw_image->columns/2));
02619           break;
02620         }
02621       }
02622     }
02623   /*
02624     Composite text onto the image.
02625   */
02626   draw_view=AcquireCacheView(draw_image);
02627   for (y=0; y < (int) draw_image->rows; y++)
02628   {
02629     register int
02630       x;
02631 
02632     register Quantum
02633       *restrict q;
02634 
02635     q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
02636       exception);
02637     if (q == (Quantum *) NULL)
02638       break;
02639     for (x=0; x < (int) draw_image->columns; x++)
02640     {
02641       if (GetPixelAlpha(image,q) != TransparentAlpha)
02642         SetPixelAlpha(draw_image,OpaqueAlpha,q);
02643       q+=GetPixelChannels(draw_image);
02644     }
02645     if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
02646       break;
02647   }
02648   draw_view=DestroyCacheView(draw_view);
02649   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02650   if (draw_info->stencil == TransparentStencil)
02651     (void) CompositeImage(image,CopyAlphaCompositeOp,draw_image,(ssize_t) x,
02652       (ssize_t) y,exception);
02653   else
02654     {
02655       matte=image->matte;
02656       (void) CompositeImage(image,OverCompositeOp,draw_image,(ssize_t) x,
02657         (ssize_t) y,exception);
02658       image->matte=matte;
02659     }
02660   draw_image=DestroyImage(draw_image);
02661   return(MagickTrue);
02662 }
02663 
02664 /*
02665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02666 %                                                                             %
02667 %                                                                             %
02668 %                                                                             %
02669 %   X E r r o r                                                               %
02670 %                                                                             %
02671 %                                                                             %
02672 %                                                                             %
02673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02674 %
02675 %  XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
02676 %  and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
02677 %  for XQueryColor.  It returns MagickFalse in those cases.  Otherwise it
02678 %  returns True.
02679 %
02680 %  The format of the XError function is:
02681 %
02682 %      int XError(display,error)
02683 %
02684 %  A description of each parameter follows:
02685 %
02686 %    o display: Specifies a pointer to the Display structure;  returned from
02687 %      XOpenDisplay.
02688 %
02689 %    o error: Specifies the error event.
02690 %
02691 */
02692 
02693 #if defined(__cplusplus) || defined(c_plusplus)
02694 extern "C" {
02695 #endif
02696 
02697 MagickExport int XError(Display *display,XErrorEvent *error)
02698 {
02699   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02700   assert(display != (Display *) NULL);
02701   assert(error != (XErrorEvent *) NULL);
02702   xerror_alert=MagickTrue;
02703   switch (error->request_code)
02704   {
02705     case X_GetGeometry:
02706     {
02707       if ((int) error->error_code == BadDrawable)
02708         return(MagickFalse);
02709       break;
02710     }
02711     case X_GetWindowAttributes:
02712     case X_QueryTree:
02713     {
02714       if ((int) error->error_code == BadWindow)
02715         return(MagickFalse);
02716       break;
02717     }
02718     case X_QueryColors:
02719     {
02720       if ((int) error->error_code == BadValue)
02721         return(MagickFalse);
02722       break;
02723     }
02724   }
02725   return(MagickTrue);
02726 }
02727 
02728 #if defined(__cplusplus) || defined(c_plusplus)
02729 }
02730 #endif
02731 
02732 /*
02733 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02734 %                                                                             %
02735 %                                                                             %
02736 %                                                                             %
02737 %   X F r e e R e s o u r c e s                                               %
02738 %                                                                             %
02739 %                                                                             %
02740 %                                                                             %
02741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02742 %
02743 %  XFreeResources() frees X11 resources.
02744 %
02745 %  The format of the XFreeResources method is:
02746 %
02747 %      void XFreeResources(Display *display,XVisualInfo *visual_info,
02748 %        XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
02749 %        XResourceInfo *resource_info,XWindowInfo *window_info)
02750 %        resource_info,window_info)
02751 %
02752 %  A description of each parameter follows:
02753 %
02754 %    o display: Specifies a connection to an X server; returned from
02755 %      XOpenDisplay.
02756 %
02757 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02758 %      returned from XGetVisualInfo.
02759 %
02760 %    o map_info: If map_type is specified, this structure is initialized
02761 %      with info from the Standard Colormap.
02762 %
02763 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02764 %
02765 %    o font_info: Specifies a pointer to a XFontStruct structure.
02766 %
02767 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
02768 %
02769 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
02770 %
02771 */
02772 MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
02773   XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
02774   XResourceInfo *resource_info,XWindowInfo *window_info)
02775 {
02776   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02777   assert(display != (Display *) NULL);
02778   assert(resource_info != (XResourceInfo *) NULL);
02779   if (window_info != (XWindowInfo *) NULL)
02780     {
02781       /*
02782         Free X image.
02783       */
02784       if (window_info->ximage != (XImage *) NULL)
02785         XDestroyImage(window_info->ximage);
02786       if (window_info->id != (Window) NULL)
02787         {
02788           /*
02789             Free destroy window and free cursors.
02790           */
02791           if (window_info->id != XRootWindow(display,visual_info->screen))
02792             (void) XDestroyWindow(display,window_info->id);
02793           if (window_info->annotate_context != (GC) NULL)
02794             (void) XFreeGC(display,window_info->annotate_context);
02795           if (window_info->highlight_context != (GC) NULL)
02796             (void) XFreeGC(display,window_info->highlight_context);
02797           if (window_info->widget_context != (GC) NULL)
02798             (void) XFreeGC(display,window_info->widget_context);
02799           if (window_info->cursor != (Cursor) NULL)
02800             (void) XFreeCursor(display,window_info->cursor);
02801           window_info->cursor=(Cursor) NULL;
02802           if (window_info->busy_cursor != (Cursor) NULL)
02803             (void) XFreeCursor(display,window_info->busy_cursor);
02804           window_info->busy_cursor=(Cursor) NULL;
02805         }
02806     }
02807   /*
02808     Free font.
02809   */
02810   if (font_info != (XFontStruct *) NULL)
02811     {
02812       (void) XFreeFont(display,font_info);
02813       font_info=(XFontStruct *) NULL;
02814     }
02815   if (map_info != (XStandardColormap *) NULL)
02816     {
02817       /*
02818         Free X Standard Colormap.
02819       */
02820       if (resource_info->map_type == (char *) NULL)
02821         (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
02822       (void) XFree((void *) map_info);
02823     }
02824   /*
02825     Free X visual info.
02826   */
02827   if (visual_info != (XVisualInfo *) NULL)
02828     (void) XFree((void *) visual_info);
02829   if (resource_info->close_server != MagickFalse)
02830     (void) XCloseDisplay(display);
02831 }
02832 
02833 /*
02834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02835 %                                                                             %
02836 %                                                                             %
02837 %                                                                             %
02838 %   X F r e e S t a n d a r d C o l o r m a p                                 %
02839 %                                                                             %
02840 %                                                                             %
02841 %                                                                             %
02842 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02843 %
02844 %  XFreeStandardColormap() frees an X11 colormap.
02845 %
02846 %  The format of the XFreeStandardColormap method is:
02847 %
02848 %      void XFreeStandardColormap(Display *display,
02849 %        const XVisualInfo *visual_info,XStandardColormap *map_info,
02850 %        XPixelInfo *pixel)
02851 %
02852 %  A description of each parameter follows:
02853 %
02854 %    o display: Specifies a connection to an X server; returned from
02855 %      XOpenDisplay.
02856 %
02857 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02858 %      returned from XGetVisualInfo.
02859 %
02860 %    o map_info: If map_type is specified, this structure is initialized
02861 %      with info from the Standard Colormap.
02862 %
02863 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02864 %
02865 */
02866 MagickPrivate void XFreeStandardColormap(Display *display,
02867   const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
02868 {
02869   /*
02870     Free colormap.
02871   */
02872   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02873   assert(display != (Display *) NULL);
02874   assert(visual_info != (XVisualInfo *) NULL);
02875   assert(map_info != (XStandardColormap *) NULL);
02876   (void) XFlush(display);
02877   if (map_info->colormap != (Colormap) NULL)
02878     {
02879       if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
02880         (void) XFreeColormap(display,map_info->colormap);
02881       else
02882         if (pixel != (XPixelInfo *) NULL)
02883           if ((visual_info->klass != TrueColor) &&
02884               (visual_info->klass != DirectColor))
02885             (void) XFreeColors(display,map_info->colormap,pixel->pixels,
02886               (int) pixel->colors,0);
02887     }
02888   map_info->colormap=(Colormap) NULL;
02889   if (pixel != (XPixelInfo *) NULL)
02890     {
02891       if (pixel->pixels != (unsigned long *) NULL)
02892         pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
02893       pixel->pixels=(unsigned long *) NULL;
02894     }
02895 }
02896 
02897 /*
02898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02899 %                                                                             %
02900 %                                                                             %
02901 %                                                                             %
02902 %   X G e t A n n o t a t e I n f o                                           %
02903 %                                                                             %
02904 %                                                                             %
02905 %                                                                             %
02906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02907 %
02908 %  XGetAnnotateInfo() initializes the AnnotateInfo structure.
02909 %
02910 %  The format of the XGetAnnotateInfo method is:
02911 %
02912 %      void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
02913 %
02914 %  A description of each parameter follows:
02915 %
02916 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
02917 %
02918 */
02919 MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
02920 {
02921   /*
02922     Initialize annotate structure.
02923   */
02924   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02925   assert(annotate_info != (XAnnotateInfo *) NULL);
02926   annotate_info->x=0;
02927   annotate_info->y=0;
02928   annotate_info->width=0;
02929   annotate_info->height=0;
02930   annotate_info->stencil=ForegroundStencil;
02931   annotate_info->degrees=0.0;
02932   annotate_info->font_info=(XFontStruct *) NULL;
02933   annotate_info->text=(char *) NULL;
02934   *annotate_info->geometry='\0';
02935   annotate_info->previous=(XAnnotateInfo *) NULL;
02936   annotate_info->next=(XAnnotateInfo *) NULL;
02937   (void) XSupportsLocale();
02938   (void) XSetLocaleModifiers("");
02939 }
02940 
02941 /*
02942 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02943 %                                                                             %
02944 %                                                                             %
02945 %                                                                             %
02946 %   X G e t M a p I n f o                                                     %
02947 %                                                                             %
02948 %                                                                             %
02949 %                                                                             %
02950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02951 %
02952 %  XGetMapInfo() initializes the XStandardColormap structure.
02953 %
02954 %  The format of the XStandardColormap method is:
02955 %
02956 %      void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
02957 %        XStandardColormap *map_info)
02958 %
02959 %  A description of each parameter follows:
02960 %
02961 %    o colormap: Specifies the ID of the X server colormap.
02962 %
02963 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02964 %      returned from XGetVisualInfo.
02965 %
02966 %    o map_info: Specifies a pointer to a X11 XStandardColormap structure.
02967 %
02968 */
02969 MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
02970   const Colormap colormap,XStandardColormap *map_info)
02971 {
02972   /*
02973     Initialize map info.
02974   */
02975   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02976   assert(visual_info != (XVisualInfo *) NULL);
02977   assert(map_info != (XStandardColormap *) NULL);
02978   map_info->colormap=colormap;
02979   map_info->red_max=visual_info->red_mask;
02980   map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
02981   if (map_info->red_max != 0)
02982     while ((map_info->red_max & 0x01) == 0)
02983     {
02984       map_info->red_max>>=1;
02985       map_info->red_mult<<=1;
02986     }
02987   map_info->green_max=visual_info->green_mask;
02988   map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
02989   if (map_info->green_max != 0)
02990     while ((map_info->green_max & 0x01) == 0)
02991     {
02992       map_info->green_max>>=1;
02993       map_info->green_mult<<=1;
02994     }
02995   map_info->blue_max=visual_info->blue_mask;
02996   map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
02997   if (map_info->blue_max != 0)
02998     while ((map_info->blue_max & 0x01) == 0)
02999     {
03000       map_info->blue_max>>=1;
03001       map_info->blue_mult<<=1;
03002     }
03003   map_info->base_pixel=0;
03004 }
03005 
03006 /*
03007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03008 %                                                                             %
03009 %                                                                             %
03010 %                                                                             %
03011 %   X G e t P i x e l I n f o                                                 %
03012 %                                                                             %
03013 %                                                                             %
03014 %                                                                             %
03015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03016 %
03017 %  XGetPixelInfo() initializes the PixelInfo structure.
03018 %
03019 %  The format of the XGetPixelInfo method is:
03020 %
03021 %      void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
03022 %        const XStandardColormap *map_info,const XResourceInfo *resource_info,
03023 %        Image *image,XPixelInfo *pixel)
03024 %        pixel)
03025 %
03026 %  A description of each parameter follows:
03027 %
03028 %    o display: Specifies a connection to an X server; returned from
03029 %      XOpenDisplay.
03030 %
03031 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
03032 %      returned from XGetVisualInfo.
03033 %
03034 %    o map_info: If map_type is specified, this structure is initialized
03035 %      with info from the Standard Colormap.
03036 %
03037 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
03038 %
03039 %    o image: the image.
03040 %
03041 %    o pixel: Specifies a pointer to a XPixelInfo structure.
03042 %
03043 */
03044 MagickPrivate void XGetPixelInfo(Display *display,
03045   const XVisualInfo *visual_info,const XStandardColormap *map_info,
03046   const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
03047 {
03048   static const char
03049     *PenColors[MaxNumberPens]=
03050     {
03051       "#000000000000",  /* black */
03052       "#00000000ffff",  /* blue */
03053       "#0000ffffffff",  /* cyan */
03054       "#0000ffff0000",  /* green */
03055       "#bdbdbdbdbdbd",  /* gray */
03056       "#ffff00000000",  /* red */
03057       "#ffff0000ffff",  /* magenta */
03058       "#ffffffff0000",  /* yellow */
03059       "#ffffffffffff",  /* white */
03060       "#bdbdbdbdbdbd",  /* gray */
03061       "#bdbdbdbdbdbd"   /* gray */
03062     };
03063 
03064   Colormap
03065     colormap;
03066 
03067   register ssize_t
03068     i;
03069 
03070   Status
03071     status;
03072 
03073   unsigned int
03074     packets;
03075 
03076   /*
03077     Initialize pixel info.
03078   */
03079   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03080   assert(display != (Display *) NULL);
03081   assert(visual_info != (XVisualInfo *) NULL);
03082   assert(map_info != (XStandardColormap *) NULL);
03083   assert(resource_info != (XResourceInfo *) NULL);
03084   assert(pixel != (XPixelInfo *) NULL);
03085   pixel->colors=0;
03086   if (image != (Image *) NULL)
03087     if (image->storage_class == PseudoClass)
03088       pixel->colors=(ssize_t) image->colors;
03089   packets=(unsigned int)
03090     MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
03091   if (pixel->pixels != (unsigned long *) NULL)
03092     pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
03093   pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
03094     sizeof(pixel->pixels));
03095   if (pixel->pixels == (unsigned long *) NULL)
03096     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
03097       image->filename);
03098   /*
03099     Set foreground color.
03100   */
03101   colormap=map_info->colormap;
03102   (void) XParseColor(display,colormap,(char *) ForegroundColor,
03103     &pixel->foreground_color);
03104   status=XParseColor(display,colormap,resource_info->foreground_color,
03105     &pixel->foreground_color);
03106   if (status == False)
03107     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03108       resource_info->foreground_color);
03109   pixel->foreground_color.pixel=
03110     XStandardPixel(map_info,&pixel->foreground_color);
03111   pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
03112   /*
03113     Set background color.
03114   */
03115   (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
03116   status=XParseColor(display,colormap,resource_info->background_color,
03117     &pixel->background_color);
03118   if (status == False)
03119     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03120       resource_info->background_color);
03121   pixel->background_color.pixel=
03122     XStandardPixel(map_info,&pixel->background_color);
03123   pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
03124   /*
03125     Set border color.
03126   */
03127   (void) XParseColor(display,colormap,(char *) BorderColor,
03128     &pixel->border_color);
03129   status=XParseColor(display,colormap,resource_info->border_color,
03130     &pixel->border_color);
03131   if (status == False)
03132     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03133       resource_info->border_color);
03134   pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
03135   pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
03136   /*
03137     Set matte color.
03138   */
03139   pixel->matte_color=pixel->background_color;
03140   if (resource_info->matte_color != (char *) NULL)
03141     {
03142       /*
03143         Matte color is specified as a X resource or command line argument.
03144       */
03145       status=XParseColor(display,colormap,resource_info->matte_color,
03146         &pixel->matte_color);
03147       if (status == False)
03148         ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03149           resource_info->matte_color);
03150       pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
03151       pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
03152     }
03153   /*
03154     Set highlight color.
03155   */
03156   pixel->highlight_color.red=(unsigned short) ((
03157     pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
03158     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03159   pixel->highlight_color.green=(unsigned short) ((
03160     pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
03161     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03162   pixel->highlight_color.blue=(unsigned short) ((
03163     pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
03164     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03165   pixel->highlight_color.pixel=
03166     XStandardPixel(map_info,&pixel->highlight_color);
03167   pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
03168   /*
03169     Set shadow color.
03170   */
03171   pixel->shadow_color.red=(unsigned short) (((MagickRealType)
03172     pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
03173   pixel->shadow_color.green=(unsigned short) (((MagickRealType)
03174     pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
03175   pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
03176     pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
03177   pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
03178   pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
03179   /*
03180     Set depth color.
03181   */
03182   pixel->depth_color.red=(unsigned short) (((MagickRealType)
03183     pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
03184   pixel->depth_color.green=(unsigned short) (((MagickRealType)
03185     pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
03186   pixel->depth_color.blue=(unsigned short) (((MagickRealType)
03187     pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
03188   pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
03189   pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
03190   /*
03191     Set trough color.
03192   */
03193   pixel->trough_color.red=(unsigned short) (((MagickRealType)
03194     pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
03195   pixel->trough_color.green=(unsigned short) (((MagickRealType)
03196     pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
03197   pixel->trough_color.blue=(unsigned short) (((MagickRealType)
03198     pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
03199   pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
03200   pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
03201   /*
03202     Set pen color.
03203   */
03204   for (i=0; i < MaxNumberPens; i++)
03205   {
03206     (void) XParseColor(display,colormap,(char *) PenColors[i],
03207       &pixel->pen_colors[i]);
03208     status=XParseColor(display,colormap,resource_info->pen_colors[i],
03209       &pixel->pen_colors[i]);
03210     if (status == False)
03211       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03212         resource_info->pen_colors[i]);
03213     pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
03214     pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
03215   }
03216   pixel->box_color=pixel->background_color;
03217   pixel->pen_color=pixel->foreground_color;
03218   pixel->box_index=0;
03219   pixel->pen_index=1;
03220   if (image != (Image *) NULL)
03221     {
03222       if ((resource_info->gamma_correct != MagickFalse) &&
03223           (image->gamma != 0.0))
03224         {
03225           GeometryInfo
03226             geometry_info;
03227 
03228           MagickStatusType
03229             flags;
03230 
03231           /*
03232             Initialize map relative to display and image gamma.
03233           */
03234           flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
03235           red_gamma=geometry_info.rho;
03236           green_gamma=geometry_info.sigma;
03237           if ((flags & SigmaValue) == 0)
03238             green_gamma=red_gamma;
03239           blue_gamma=geometry_info.xi;
03240           if ((flags & XiValue) == 0)
03241             blue_gamma=red_gamma;
03242           red_gamma*=image->gamma;
03243           green_gamma*=image->gamma;
03244           blue_gamma*=image->gamma;
03245         }
03246       if (image->storage_class == PseudoClass)
03247         {
03248           /*
03249             Initialize pixel array for images of type PseudoClass.
03250           */
03251           for (i=0; i < (ssize_t) image->colors; i++)
03252             pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
03253           for (i=0; i < MaxNumberPens; i++)
03254             pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
03255           pixel->colors+=MaxNumberPens;
03256         }
03257     }
03258 }
03259 
03260 /*
03261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03262 %                                                                             %
03263 %                                                                             %
03264 %                                                                             %
03265 %   X G e t R e s o u r c e C l a s s                                         %
03266 %                                                                             %
03267 %                                                                             %
03268 %                                                                             %
03269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03270 %
03271 %  XGetResourceClass() queries the X server for the specified resource name or
03272 %  class.  If the resource name or class is not defined in the database, the
03273 %  supplied default value is returned.
03274 %
03275 %  The format of the XGetResourceClass method is:
03276 %
03277 %      char *XGetResourceClass(XrmDatabase database,const char *client_name,
03278 %        const char *keyword,char *resource_default)
03279 %
03280 %  A description of each parameter follows:
03281 %
03282 %    o database: Specifies a resource database; returned from
03283 %      XrmGetStringDatabase.
03284 %
03285 %    o client_name:  Specifies the application name used to retrieve resource
03286 %      info from the X server database.
03287 %
03288 %    o keyword: Specifies the keyword of the value being retrieved.
03289 %
03290 %    o resource_default: Specifies the default value to return if the query
03291 %      fails to find the specified keyword/class.
03292 %
03293 */
03294 MagickExport char *XGetResourceClass(XrmDatabase database,
03295   const char *client_name,const char *keyword,char *resource_default)
03296 {
03297   char
03298     resource_class[MaxTextExtent],
03299     resource_name[MaxTextExtent];
03300 
03301   static char
03302     *resource_type;
03303 
03304   Status
03305     status;
03306 
03307   XrmValue
03308     resource_value;
03309 
03310   if (database == (XrmDatabase) NULL)
03311     return(resource_default);
03312   *resource_name='\0';
03313   *resource_class='\0';
03314   if (keyword != (char *) NULL)
03315     {
03316       int
03317         c,
03318         k;
03319 
03320       /*
03321         Initialize resource keyword and class.
03322       */
03323       (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",
03324         client_name,keyword);
03325       c=(int) (*client_name);
03326       if ((c >= XK_a) && (c <= XK_z))
03327         c-=(XK_a-XK_A);
03328       else
03329         if ((c >= XK_agrave) && (c <= XK_odiaeresis))
03330           c-=(XK_agrave-XK_Agrave);
03331         else
03332           if ((c >= XK_oslash) && (c <= XK_thorn))
03333             c-=(XK_oslash-XK_Ooblique);
03334       k=(int) (*keyword);
03335       if ((k >= XK_a) && (k <= XK_z))
03336         k-=(XK_a-XK_A);
03337       else
03338         if ((k >= XK_agrave) && (k <= XK_odiaeresis))
03339           k-=(XK_agrave-XK_Agrave);
03340         else
03341           if ((k >= XK_oslash) && (k <= XK_thorn))
03342             k-=(XK_oslash-XK_Ooblique);
03343       (void) FormatLocaleString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
03344         client_name+1,k,keyword+1);
03345     }
03346   status=XrmGetResource(database,resource_name,resource_class,&resource_type,
03347     &resource_value);
03348   if (status == False)
03349     return(resource_default);
03350   return(resource_value.addr);
03351 }
03352 
03353 /*
03354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03355 %                                                                             %
03356 %                                                                             %
03357 %                                                                             %
03358 %   X G e t R e s o u r c e D a t a b a s e                                   %
03359 %                                                                             %
03360 %                                                                             %
03361 %                                                                             %
03362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03363 %
03364 %  XGetResourceDatabase() creates a new resource database and initializes it.
03365 %
03366 %  The format of the XGetResourceDatabase method is:
03367 %
03368 %      XrmDatabase XGetResourceDatabase(Display *display,
03369 %        const char *client_name)
03370 %
03371 %  A description of each parameter follows:
03372 %
03373 %    o database: XGetResourceDatabase() returns the database after it is
03374 %      initialized.
03375 %
03376 %    o display: Specifies a connection to an X server;  returned from
03377 %      XOpenDisplay.
03378 %
03379 %    o client_name:  Specifies the application name used to retrieve resource
03380 %      info from the X server database.
03381 %
03382 */
03383 MagickExport XrmDatabase XGetResourceDatabase(Display *display,
03384   const char *client_name)
03385 {
03386   char
03387     filename[MaxTextExtent];
03388 
03389   int
03390     c;
03391 
03392   register const char
03393     *p;
03394 
03395   XrmDatabase
03396     resource_database,
03397     server_database;
03398 
03399   if (display == (Display *) NULL)
03400     return((XrmDatabase) NULL);
03401   assert(client_name != (char *) NULL);
03402   /*
03403     Initialize resource database.
03404   */
03405   XrmInitialize();
03406   (void) XGetDefault(display,(char *) client_name,"dummy");
03407   resource_database=XrmGetDatabase(display);
03408   /*
03409     Combine application database.
03410   */
03411   if (client_name != (char *) NULL)
03412     {
03413       /*
03414         Get basename of client.
03415       */
03416       p=client_name+(strlen(client_name)-1);
03417       while ((p > client_name) && (*p != '/'))
03418         p--;
03419       if (*p == '/')
03420         client_name=p+1;
03421     }
03422   c=(int) (*client_name);
03423   if ((c >= XK_a) && (c <= XK_z))
03424     c-=(XK_a-XK_A);
03425   else
03426     if ((c >= XK_agrave) && (c <= XK_odiaeresis))
03427       c-=(XK_agrave-XK_Agrave);
03428     else
03429       if ((c >= XK_oslash) && (c <= XK_thorn))
03430         c-=(XK_oslash-XK_Ooblique);
03431 #if defined(X11_APPLICATION_PATH)
03432   (void) FormatLocaleString(filename,MaxTextExtent,"%s%c%s",
03433     X11_APPLICATION_PATH,c,client_name+1);
03434   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
03435 #endif
03436   if (XResourceManagerString(display) != (char *) NULL)
03437     {
03438       /*
03439         Combine server database.
03440       */
03441       server_database=XrmGetStringDatabase(XResourceManagerString(display));
03442       XrmCombineDatabase(server_database,&resource_database,MagickFalse);
03443     }
03444   /*
03445     Merge user preferences database.
03446   */
03447 #if defined(X11_PREFERENCES_PATH)
03448   (void) FormatLocaleString(filename,MaxTextExtent,"%s%src",
03449     X11_PREFERENCES_PATH,client_name);
03450   ExpandFilename(filename);
03451   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
03452 #endif
03453   return(resource_database);
03454 }
03455 
03456 /*
03457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03458 %                                                                             %
03459 %                                                                             %
03460 %                                                                             %
03461 %   X G e t R e s o u r c e I n f o                                           %
03462 %                                                                             %
03463 %                                                                             %
03464 %                                                                             %
03465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03466 %
03467 %  XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
03468 %
03469 %  The format of the XGetResourceInfo method is:
03470 %
03471 %      void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
03472 %        const char *client_name,XResourceInfo *resource_info)
03473 %
03474 %  A description of each parameter follows:
03475 %
03476 %    o image_info: the image info.
03477 %
03478 %    o database: Specifies a resource database; returned from
03479 %      XrmGetStringDatabase.
03480 %
03481 %    o client_name:  Specifies the application name used to retrieve
03482 %      resource info from the X server database.
03483 %
03484 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
03485 %
03486 */
03487 MagickExport void XGetResourceInfo(const ImageInfo *image_info,
03488   XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
03489 {
03490   char
03491     *directory,
03492     *resource_value;
03493 
03494   /*
03495     Initialize resource info fields.
03496   */
03497   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03498   assert(resource_info != (XResourceInfo *) NULL);
03499   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
03500   resource_info->resource_database=database;
03501   resource_info->image_info=(ImageInfo *) image_info;
03502   (void) SetImageInfoProgressMonitor(resource_info->image_info,
03503     XMagickProgressMonitor,(void *) NULL);
03504   resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
03505   resource_info->close_server=MagickTrue;
03506   resource_info->client_name=AcquireString(client_name);
03507   resource_value=XGetResourceClass(database,client_name,"backdrop",
03508     (char *) "False");
03509   resource_info->backdrop=IsMagickTrue(resource_value);
03510   resource_info->background_color=XGetResourceInstance(database,client_name,
03511     "background",(char *) "#d6d6d6d6d6d6");
03512   resource_info->border_color=XGetResourceInstance(database,client_name,
03513     "borderColor",BorderColor);
03514   resource_value=XGetResourceClass(database,client_name,"borderWidth",
03515     (char *) "2");
03516   resource_info->border_width=(unsigned int) StringToUnsignedLong(
03517     resource_value);
03518   resource_value=XGetResourceClass(database,client_name,"colormap",
03519     (char *) "shared");
03520   resource_info->colormap=UndefinedColormap;
03521   if (LocaleCompare("private",resource_value) == 0)
03522     resource_info->colormap=PrivateColormap;
03523   if (LocaleCompare("shared",resource_value) == 0)
03524     resource_info->colormap=SharedColormap;
03525   if (resource_info->colormap == UndefinedColormap)
03526     ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
03527       resource_value);
03528   resource_value=XGetResourceClass(database,client_name,
03529     "colorRecovery",(char *) "False");
03530   resource_info->color_recovery=IsMagickTrue(resource_value);
03531   resource_value=XGetResourceClass(database,client_name,"confirmExit",
03532     (char *) "False");
03533   resource_info->confirm_exit=IsMagickTrue(resource_value);
03534   resource_value=XGetResourceClass(database,client_name,"confirmEdit",
03535     (char *) "False");
03536   resource_info->confirm_edit=IsMagickTrue(resource_value);
03537   resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
03538   resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
03539   resource_info->display_gamma=XGetResourceClass(database,client_name,
03540     "displayGamma",(char *) "2.2");
03541   resource_value=XGetResourceClass(database,client_name,"displayWarnings",
03542     (char *) "True");
03543   resource_info->display_warnings=IsMagickTrue(resource_value);
03544   resource_info->font=XGetResourceClass(database,client_name,"font",
03545     (char *) NULL);
03546   resource_info->font=XGetResourceClass(database,client_name,"fontList",
03547     resource_info->font);
03548   resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
03549     (char *) "fixed");
03550   resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
03551     (char *) "variable");
03552   resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
03553     (char *) "5x8");
03554   resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
03555     (char *) "6x10");
03556   resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
03557     (char *) "7x13bold");
03558   resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
03559     (char *) "8x13bold");
03560   resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
03561     (char *) "9x15bold");
03562   resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
03563     (char *) "10x20");
03564   resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
03565     (char *) "12x24");
03566   resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
03567     (char *) "fixed");
03568   resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
03569     (char *) "fixed");
03570   resource_info->foreground_color=XGetResourceInstance(database,client_name,
03571     "foreground",ForegroundColor);
03572   resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
03573     (char *) "True");
03574   resource_info->gamma_correct=IsMagickTrue(resource_value);
03575   resource_info->image_geometry=ConstantString(XGetResourceClass(database,
03576     client_name,"geometry",(char *) NULL));
03577   resource_value=XGetResourceClass(database,client_name,"gravity",
03578     (char *) "Center");
03579   resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
03580     MagickFalse,resource_value);
03581   directory=getcwd(resource_info->home_directory,MaxTextExtent);
03582   (void) directory;
03583   resource_info->icon_geometry=XGetResourceClass(database,client_name,
03584     "iconGeometry",(char *) NULL);
03585   resource_value=XGetResourceClass(database,client_name,"iconic",
03586     (char *) "False");
03587   resource_info->iconic=IsMagickTrue(resource_value);
03588   resource_value=XGetResourceClass(database,client_name,"immutable",
03589     LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
03590     (char *) "False");
03591   resource_info->immutable=IsMagickTrue(resource_value);
03592   resource_value=XGetResourceClass(database,client_name,"magnify",
03593     (char *) "3");
03594   resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
03595   resource_info->map_type=XGetResourceClass(database,client_name,"map",
03596     (char *) NULL);
03597   resource_info->matte_color=XGetResourceInstance(database,client_name,
03598     "mattecolor",(char *) NULL);
03599   resource_info->name=ConstantString(XGetResourceClass(database,client_name,
03600     "name",(char *) NULL));
03601   resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
03602     (char *) "black");
03603   resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
03604     (char *) "blue");
03605   resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
03606     (char *) "cyan");
03607   resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
03608     (char *) "green");
03609   resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
03610     (char *) "gray");
03611   resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
03612     (char *) "red");
03613   resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
03614     (char *) "magenta");
03615   resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
03616     (char *) "yellow");
03617   resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
03618     (char *) "white");
03619   resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
03620     (char *) "gray");
03621   resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
03622     (char *) "gray");
03623   resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
03624   resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
03625   resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
03626   resource_info->quantum=StringToLong(resource_value);
03627   resource_info->text_font=XGetResourceClass(database,client_name,(char *)
03628     "font",(char *) "fixed");
03629   resource_info->text_font=XGetResourceClass(database,client_name,
03630     "textFontList",resource_info->text_font);
03631   resource_info->title=XGetResourceClass(database,client_name,"title",
03632     (char *) NULL);
03633   resource_value=XGetResourceClass(database,client_name,"undoCache",
03634     (char *) "16");
03635   resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
03636   resource_value=XGetResourceClass(database,client_name,"update",
03637     (char *) "False");
03638   resource_info->update=IsMagickTrue(resource_value);
03639   resource_value=XGetResourceClass(database,client_name,"usePixmap",
03640     (char *) "True");
03641   resource_info->use_pixmap=IsMagickTrue(resource_value);
03642   resource_value=XGetResourceClass(database,client_name,"sharedMemory",
03643     (char *) "True");
03644   resource_info->use_shared_memory=IsMagickTrue(resource_value);
03645   resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
03646     (char *) NULL);
03647   resource_info->window_group=XGetResourceClass(database,client_name,
03648     "windowGroup",(char *) NULL);
03649   resource_info->window_id=XGetResourceClass(database,client_name,"window",
03650     (char *) NULL);
03651   resource_info->write_filename=XGetResourceClass(database,client_name,
03652     "writeFilename",(char *) NULL);
03653 }
03654 
03655 /*
03656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03657 %                                                                             %
03658 %                                                                             %
03659 %                                                                             %
03660 %   X G e t R e s o u r c e I n s t a n c e                                   %
03661 %                                                                             %
03662 %                                                                             %
03663 %                                                                             %
03664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03665 %
03666 %  XGetResourceInstance() queries the X server for the specified resource name.
03667 %  If the resource name is not defined in the database, the supplied default
03668 %  value is returned.
03669 %
03670 %  The format of the XGetResourceInstance method is:
03671 %
03672 %      char *XGetResourceInstance(XrmDatabase database,const char *client_name,
03673 %        const char *keyword,const char *resource_default)
03674 %
03675 %  A description of each parameter follows:
03676 %
03677 %    o database: Specifies a resource database; returned from
03678 %      XrmGetStringDatabase.
03679 %
03680 %    o client_name:  Specifies the application name used to retrieve
03681 %      resource info from the X server database.
03682 %
03683 %    o keyword: Specifies the keyword of the value being retrieved.
03684 %
03685 %    o resource_default: Specifies the default value to return if the query
03686 %      fails to find the specified keyword/class.
03687 %
03688 */
03689 MagickExport char *XGetResourceInstance(XrmDatabase database,
03690   const char *client_name,const char *keyword,const char *resource_default)
03691 {
03692   char
03693     *resource_type,
03694     resource_name[MaxTextExtent];
03695 
03696   Status
03697     status;
03698 
03699   XrmValue
03700     resource_value;
03701 
03702   if (database == (XrmDatabase) NULL)
03703     return((char *) resource_default);
03704   *resource_name='\0';
03705   if (keyword != (char *) NULL)
03706     (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.%s",client_name,
03707       keyword);
03708   status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
03709     &resource_value);
03710   if (status == False)
03711     return((char *) resource_default);
03712   return(resource_value.addr);
03713 }
03714 
03715 /*
03716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03717 %                                                                             %
03718 %                                                                             %
03719 %                                                                             %
03720 %   X G e t S c r e e n D e n s i t y                                         %
03721 %                                                                             %
03722 %                                                                             %
03723 %                                                                             %
03724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03725 %
03726 %  XGetScreenDensity() returns the density of the X server screen in
03727 %  dots-per-inch.
03728 %
03729 %  The format of the XGetScreenDensity method is:
03730 %
03731 %      char *XGetScreenDensity(Display *display)
03732 %
03733 %  A description of each parameter follows:
03734 %
03735 %    o density: XGetScreenDensity() returns the density of the X screen in
03736 %      dots-per-inch.
03737 %
03738 %    o display: Specifies a connection to an X server;  returned from
03739 %      XOpenDisplay.
03740 %
03741 */
03742 MagickExport char *XGetScreenDensity(Display *display)
03743 {
03744   char
03745     density[MaxTextExtent];
03746 
03747   double
03748     x_density,
03749     y_density;
03750 
03751   /*
03752     Set density as determined by screen size.
03753   */
03754   x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
03755     ((double) DisplayWidthMM(display,XDefaultScreen(display))));
03756   y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
03757     ((double) DisplayHeightMM(display,XDefaultScreen(display))));
03758   (void) FormatLocaleString(density,MaxTextExtent,"%gx%g",x_density,
03759     y_density);
03760   return(GetPageGeometry(density));
03761 }
03762 
03763 /*
03764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03765 %                                                                             %
03766 %                                                                             %
03767 %                                                                             %
03768 +   X G e t S u b w i n d o w                                                 %
03769 %                                                                             %
03770 %                                                                             %
03771 %                                                                             %
03772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03773 %
03774 %  XGetSubwindow() returns the subwindow of a window chosen the user with the
03775 %  pointer and a button press.
03776 %
03777 %  The format of the XGetSubwindow method is:
03778 %
03779 %      Window XGetSubwindow(Display *display,Window window,int x,int y)
03780 %
03781 %  A description of each parameter follows:
03782 %
03783 %    o subwindow: XGetSubwindow() returns NULL if no subwindow is found
03784 %      otherwise the subwindow is returned.
03785 %
03786 %    o display: Specifies a connection to an X server;  returned from
03787 %      XOpenDisplay.
03788 %
03789 %    o window: Specifies a pointer to a Window.
03790 %
03791 %    o x: the x coordinate of the pointer relative to the origin of the
03792 %      window.
03793 %
03794 %    o y: the y coordinate of the pointer relative to the origin of the
03795 %      window.
03796 %
03797 */
03798 static Window XGetSubwindow(Display *display,Window window,int x,int y)
03799 {
03800   int
03801     x_offset,
03802     y_offset;
03803 
03804   Status
03805     status;
03806 
03807   Window
03808     source_window,
03809     target_window;
03810 
03811   assert(display != (Display *) NULL);
03812   source_window=XRootWindow(display,XDefaultScreen(display));
03813   if (window == (Window) NULL)
03814     return(source_window);
03815   target_window=window;
03816   for ( ; ; )
03817   {
03818     status=XTranslateCoordinates(display,source_window,window,x,y,
03819       &x_offset,&y_offset,&target_window);
03820     if (status != True)
03821       break;
03822     if (target_window == (Window) NULL)
03823       break;
03824     source_window=window;
03825     window=target_window;
03826     x=x_offset;
03827     y=y_offset;
03828   }
03829   if (target_window == (Window) NULL)
03830     target_window=window;
03831   return(target_window);
03832 }
03833 
03834 /*
03835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03836 %                                                                             %
03837 %                                                                             %
03838 %                                                                             %
03839 %   X G e t W i n d o w C o l o r                                             %
03840 %                                                                             %
03841 %                                                                             %
03842 %                                                                             %
03843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03844 %
03845 %  XGetWindowColor() returns the color of a pixel interactively chosen from the
03846 %  X server.
03847 %
03848 %  The format of the XGetWindowColor method is:
03849 %
03850 %      MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
03851 %        char *name,ExceptionInfo *exception)
03852 %
03853 %  A description of each parameter follows:
03854 %
03855 %    o display: Specifies a connection to an X server;  returned from
03856 %      XOpenDisplay.
03857 %
03858 %    o windows: Specifies a pointer to a XWindows structure.
03859 %
03860 %    o name: the name of the color if found in the X Color Database is
03861 %      returned in this character string.
03862 %
03863 %    o exception: return any errors or warnings in this structure.
03864 %
03865 */
03866 MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
03867   XWindows *windows,char *name,ExceptionInfo *exception)
03868 {
03869   int
03870     x,
03871     y;
03872 
03873   PixelInfo
03874     pixel;
03875 
03876   RectangleInfo
03877     crop_info;
03878 
03879   Status
03880     status;
03881 
03882   Window
03883     child,
03884     client_window,
03885     root_window,
03886     target_window;
03887 
03888   XColor
03889     color;
03890 
03891   XImage
03892     *ximage;
03893 
03894   XWindowAttributes
03895     window_attributes;
03896 
03897   /*
03898     Choose a pixel from the X server.
03899   */
03900   assert(display != (Display *) NULL);
03901   assert(name != (char *) NULL);
03902   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
03903   *name='\0';
03904   target_window=XSelectWindow(display,&crop_info);
03905   if (target_window == (Window) NULL)
03906     return(MagickFalse);
03907   root_window=XRootWindow(display,XDefaultScreen(display));
03908   client_window=target_window;
03909   if (target_window != root_window)
03910     {
03911       unsigned int
03912         d;
03913 
03914       /*
03915         Get client window.
03916       */
03917       status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
03918       if (status != False)
03919         {
03920           client_window=XClientWindow(display,target_window);
03921           target_window=client_window;
03922         }
03923     }
03924   /*
03925     Verify window is viewable.
03926   */
03927   status=XGetWindowAttributes(display,target_window,&window_attributes);
03928   if ((status == False) || (window_attributes.map_state != IsViewable))
03929     return(MagickFalse);
03930   /*
03931     Get window X image.
03932   */
03933   (void) XTranslateCoordinates(display,root_window,target_window,
03934     (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
03935   ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
03936   if (ximage == (XImage *) NULL)
03937     return(MagickFalse);
03938   color.pixel=XGetPixel(ximage,0,0);
03939   XDestroyImage(ximage);
03940   /*
03941     Match color against the color database.
03942   */
03943   (void) XQueryColor(display,window_attributes.colormap,&color);
03944   pixel.red=ScaleShortToQuantum(color.red);
03945   pixel.green=ScaleShortToQuantum(color.green);
03946   pixel.blue=ScaleShortToQuantum(color.blue);
03947   pixel.alpha=OpaqueAlpha;
03948   (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
03949     exception);
03950   return(MagickTrue);
03951 }
03952 
03953 /*
03954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03955 %                                                                             %
03956 %                                                                             %
03957 %                                                                             %
03958 +   X G e t W i n d o w I m a g e                                             %
03959 %                                                                             %
03960 %                                                                             %
03961 %                                                                             %
03962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03963 %
03964 %  XGetWindowImage() reads an image from the target X window and returns it.
03965 %  XGetWindowImage() optionally descends the window hierarchy and overlays the
03966 %  target image with each child image in an optimized fashion.  Any child
03967 %  window that have the same visual, colormap, and are contained by its parent
03968 %  are exempted.
03969 %
03970 %  The format of the XGetWindowImage method is:
03971 %
03972 %      Image *XGetWindowImage(Display *display,const Window window,
03973 %        const unsigned int borders,const unsigned int level,
03974 %        ExceptionInfo *exception)
03975 %
03976 %  A description of each parameter follows:
03977 %
03978 %    o display: Specifies a connection to an X server;  returned from
03979 %      XOpenDisplay.
03980 %
03981 %    o window: Specifies the window to obtain the image from.
03982 %
03983 %    o borders: Specifies whether borders pixels are to be saved with
03984 %      the image.
03985 %
03986 %    o level: Specifies an unsigned integer representing the level of
03987 %      decent in the window hierarchy.  This value must be zero or one on
03988 %      the initial call to XGetWindowImage.  A value of zero returns after
03989 %      one call.  A value of one causes the function to descend the window
03990 %      hierarchy and overlay the target image with each subwindow image.
03991 %
03992 %    o exception: return any errors or warnings in this structure.
03993 %
03994 */
03995 static Image *XGetWindowImage(Display *display,const Window window,
03996   const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
03997 {
03998   typedef struct _ColormapInfo
03999   {
04000     Colormap
04001       colormap;
04002 
04003     XColor
04004       *colors;
04005 
04006     struct _ColormapInfo
04007       *next;
04008   } ColormapInfo;
04009 
04010   typedef struct _WindowInfo
04011   {
04012     Window
04013       window,
04014       parent;
04015 
04016     Visual
04017       *visual;
04018 
04019     Colormap
04020       colormap;
04021 
04022     XSegment
04023       bounds;
04024 
04025     RectangleInfo
04026       crop_info;
04027   } WindowInfo;
04028 
04029   int
04030     display_height,
04031     display_width,
04032     id,
04033     x_offset,
04034     y_offset;
04035 
04036   Quantum
04037     index;
04038 
04039   RectangleInfo
04040     crop_info;
04041 
04042   register int
04043     i;
04044 
04045   static ColormapInfo
04046     *colormap_info = (ColormapInfo *) NULL;
04047 
04048   static int
04049     max_windows = 0,
04050     number_windows = 0;
04051 
04052   static WindowInfo
04053     *window_info;
04054 
04055   Status
04056     status;
04057 
04058   Window
04059     child,
04060     root_window;
04061 
04062   XWindowAttributes
04063     window_attributes;
04064 
04065   /*
04066     Verify window is viewable.
04067   */
04068   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
04069   assert(display != (Display *) NULL);
04070   status=XGetWindowAttributes(display,window,&window_attributes);
04071   if ((status == False) || (window_attributes.map_state != IsViewable))
04072     return((Image *) NULL);
04073   /*
04074     Cropping rectangle is relative to root window.
04075   */
04076   root_window=XRootWindow(display,XDefaultScreen(display));
04077   (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
04078     &y_offset,&child);
04079   crop_info.x=(ssize_t) x_offset;
04080   crop_info.y=(ssize_t) y_offset;
04081   crop_info.width=(size_t) window_attributes.width;
04082   crop_info.height=(size_t) window_attributes.height;
04083   if (borders != MagickFalse)
04084     {
04085       /*
04086         Include border in image.
04087       */
04088       crop_info.x-=(ssize_t) window_attributes.border_width;
04089       crop_info.y-=(ssize_t) window_attributes.border_width;
04090       crop_info.width+=(size_t) (window_attributes.border_width << 1);
04091       crop_info.height+=(size_t) (window_attributes.border_width << 1);
04092     }
04093   /*
04094     Crop to root window.
04095   */
04096   if (crop_info.x < 0)
04097     {
04098       crop_info.width+=crop_info.x;
04099       crop_info.x=0;
04100     }
04101   if (crop_info.y < 0)
04102     {
04103       crop_info.height+=crop_info.y;
04104       crop_info.y=0;
04105     }
04106   display_width=XDisplayWidth(display,XDefaultScreen(display));
04107   if ((int) (crop_info.x+crop_info.width) > display_width)
04108     crop_info.width=(size_t) (display_width-crop_info.x);
04109   display_height=XDisplayHeight(display,XDefaultScreen(display));
04110   if ((int) (crop_info.y+crop_info.height) > display_height)
04111     crop_info.height=(size_t) (display_height-crop_info.y);
04112   /*
04113     Initialize window info attributes.
04114   */
04115   if (number_windows >= max_windows)
04116     {
04117       /*
04118         Allocate or resize window info buffer.
04119       */
04120       max_windows+=1024;
04121       if (window_info == (WindowInfo *) NULL)
04122         window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
04123           sizeof(*window_info));
04124       else
04125         window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
04126           max_windows,sizeof(*window_info));
04127     }
04128   if (window_info == (WindowInfo *) NULL)
04129     {
04130       ThrowXWindowFatalException(ResourceLimitError,
04131         "MemoryAllocationFailed","...");
04132       return((Image *) NULL);
04133     }
04134   id=number_windows++;
04135   window_info[id].window=window;
04136   window_info[id].visual=window_attributes.visual;
04137   window_info[id].colormap=window_attributes.colormap;
04138   window_info[id].bounds.x1=(short) crop_info.x;
04139   window_info[id].bounds.y1=(short) crop_info.y;
04140   window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
04141   window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
04142   crop_info.x-=x_offset;
04143   crop_info.y-=y_offset;
04144   window_info[id].crop_info=crop_info;
04145   if (level != 0)
04146     {
04147       unsigned int
04148         number_children;
04149 
04150       Window
04151         *children;
04152 
04153       /*
04154         Descend the window hierarchy.
04155       */
04156       status=XQueryTree(display,window,&root_window,&window_info[id].parent,
04157         &children,&number_children);
04158       for (i=0; i < id; i++)
04159         if ((window_info[i].window == window_info[id].parent) &&
04160             (window_info[i].visual == window_info[id].visual) &&
04161             (window_info[i].colormap == window_info[id].colormap))
04162           {
04163             if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
04164                 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
04165                 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
04166                 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
04167               {
04168                 /*
04169                   Eliminate windows not circumscribed by their parent.
04170                 */
04171                 number_windows--;
04172                 break;
04173               }
04174           }
04175       if ((status == True) && (number_children != 0))
04176         {
04177           for (i=0; i < (int) number_children; i++)
04178             (void) XGetWindowImage(display,children[i],MagickFalse,level+1,
04179               exception);
04180           (void) XFree((void *) children);
04181         }
04182     }
04183   if (level <= 1)
04184     {
04185       CacheView
04186         *composite_view;
04187 
04188       ColormapInfo
04189         *next;
04190 
04191       Image
04192         *composite_image,
04193         *image;
04194 
04195       int
04196         y;
04197 
04198       MagickBooleanType
04199         import;
04200 
04201       register int
04202         j,
04203         x;
04204 
04205       register Quantum
04206         *restrict q;
04207 
04208       register size_t
04209         pixel;
04210 
04211       unsigned int
04212         number_colors;
04213 
04214       XColor
04215         *colors;
04216 
04217       XImage
04218         *ximage;
04219 
04220       /*
04221         Get X image for each window in the list.
04222       */
04223       image=NewImageList();
04224       for (id=0; id < number_windows; id++)
04225       {
04226         /*
04227           Does target window intersect top level window?
04228         */
04229         import=
04230           ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
04231            (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
04232            (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
04233            (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
04234           MagickTrue : MagickFalse;
04235         /*
04236           Is target window contained by another window with the same colormap?
04237         */
04238         for (j=0; j < id; j++)
04239           if ((window_info[id].visual == window_info[j].visual) &&
04240               (window_info[id].colormap == window_info[j].colormap))
04241             {
04242               if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
04243                   (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
04244                   (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
04245                   (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
04246                   import=MagickFalse;
04247             }
04248           else
04249             if ((window_info[id].visual != window_info[j].visual) ||
04250                 (window_info[id].colormap != window_info[j].colormap))
04251               {
04252                 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
04253                     (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
04254                     (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
04255                     (window_info[id].bounds.y1 < window_info[j].bounds.y2))
04256                   import=MagickTrue;
04257               }
04258         if (import == MagickFalse)
04259           continue;
04260         /*
04261           Get X image.
04262         */
04263         ximage=XGetImage(display,window_info[id].window,(int)
04264           window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
04265           (unsigned int) window_info[id].crop_info.width,(unsigned int)
04266           window_info[id].crop_info.height,AllPlanes,ZPixmap);
04267         if (ximage == (XImage *) NULL)
04268           continue;
04269         /*
04270           Initialize window colormap.
04271         */
04272         number_colors=0;
04273         colors=(XColor *) NULL;
04274         if (window_info[id].colormap != (Colormap) NULL)
04275           {
04276             ColormapInfo
04277               *p;
04278 
04279             /*
04280               Search colormap list for window colormap.
04281             */
04282             number_colors=(unsigned int) window_info[id].visual->map_entries;
04283             for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
04284               if (p->colormap == window_info[id].colormap)
04285                 break;
04286             if (p == (ColormapInfo *) NULL)
04287               {
04288                 /*
04289                   Get the window colormap.
04290                 */
04291                 colors=(XColor *) AcquireQuantumMemory(number_colors,
04292                   sizeof(*colors));
04293                 if (colors == (XColor *) NULL)
04294                   {
04295                     XDestroyImage(ximage);
04296                     return((Image *) NULL);
04297                   }
04298                 if ((window_info[id].visual->klass != DirectColor) &&
04299                     (window_info[id].visual->klass != TrueColor))
04300                   for (i=0; i < (int) number_colors; i++)
04301                   {
04302                     colors[i].pixel=(size_t) i;
04303                     colors[i].pad='\0';
04304                   }
04305                 else
04306                   {
04307                     size_t
04308                       blue,
04309                       blue_bit,
04310                       green,
04311                       green_bit,
04312                       red,
04313                       red_bit;
04314 
04315                     /*
04316                       DirectColor or TrueColor visual.
04317                     */
04318                     red=0;
04319                     green=0;
04320                     blue=0;
04321                     red_bit=window_info[id].visual->red_mask &
04322                       (~(window_info[id].visual->red_mask)+1);
04323                     green_bit=window_info[id].visual->green_mask &
04324                       (~(window_info[id].visual->green_mask)+1);
04325                     blue_bit=window_info[id].visual->blue_mask &
04326                       (~(window_info[id].visual->blue_mask)+1);
04327                     for (i=0; i < (int) number_colors; i++)
04328                     {
04329                       colors[i].pixel=(unsigned long) (red | green | blue);
04330                       colors[i].pad='\0';
04331                       red+=red_bit;
04332                       if (red > window_info[id].visual->red_mask)
04333                         red=0;
04334                       green+=green_bit;
04335                       if (green > window_info[id].visual->green_mask)
04336                         green=0;
04337                       blue+=blue_bit;
04338                       if (blue > window_info[id].visual->blue_mask)
04339                         blue=0;
04340                     }
04341                   }
04342                 (void) XQueryColors(display,window_info[id].colormap,colors,
04343                   (int) number_colors);
04344                 /*
04345                   Append colormap to colormap list.
04346                 */
04347                 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
04348                 if (p == (ColormapInfo *) NULL)
04349                   return((Image *) NULL);
04350                 p->colormap=window_info[id].colormap;
04351                 p->colors=colors;
04352                 p->next=colormap_info;
04353                 colormap_info=p;
04354               }
04355             colors=p->colors;
04356           }
04357         /*
04358           Allocate image structure.
04359         */
04360         composite_image=AcquireImage((ImageInfo *) NULL,exception);
04361         if (composite_image == (Image *) NULL)
04362           {
04363             XDestroyImage(ximage);
04364             return((Image *) NULL);
04365           }
04366         /*
04367           Convert X image to MIFF format.
04368         */
04369         if ((window_info[id].visual->klass != TrueColor) &&
04370             (window_info[id].visual->klass != DirectColor))
04371           composite_image->storage_class=PseudoClass;
04372         composite_image->columns=(size_t) ximage->width;
04373         composite_image->rows=(size_t) ximage->height;
04374         composite_view=AcquireCacheView(composite_image);
04375         switch (composite_image->storage_class)
04376         {
04377           case DirectClass:
04378           default:
04379           {
04380             register size_t
04381               color,
04382               index;
04383 
04384             size_t
04385               blue_mask,
04386               blue_shift,
04387               green_mask,
04388               green_shift,
04389               red_mask,
04390               red_shift;
04391 
04392             /*
04393               Determine shift and mask for red, green, and blue.
04394             */
04395             red_mask=window_info[id].visual->red_mask;
04396             red_shift=0;
04397             while ((red_mask != 0) && ((red_mask & 0x01) == 0))
04398             {
04399               red_mask>>=1;
04400               red_shift++;
04401             }
04402             green_mask=window_info[id].visual->green_mask;
04403             green_shift=0;
04404             while ((green_mask != 0) && ((green_mask & 0x01) == 0))
04405             {
04406               green_mask>>=1;
04407               green_shift++;
04408             }
04409             blue_mask=window_info[id].visual->blue_mask;
04410             blue_shift=0;
04411             while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
04412             {
04413               blue_mask>>=1;
04414               blue_shift++;
04415             }
04416             /*
04417               Convert X image to DirectClass packets.
04418             */
04419             if ((number_colors != 0) &&
04420                 (window_info[id].visual->klass == DirectColor))
04421               for (y=0; y < (int) composite_image->rows; y++)
04422               {
04423                 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
04424                   composite_image->columns,1,exception);
04425                 if (q == (Quantum *) NULL)
04426                   break;
04427                 for (x=0; x < (int) composite_image->columns; x++)
04428                 {
04429                   pixel=XGetPixel(ximage,x,y);
04430                   index=(pixel >> red_shift) & red_mask;
04431                   SetPixelRed(composite_image,
04432                     ScaleShortToQuantum(colors[index].red),q);
04433                   index=(pixel >> green_shift) & green_mask;
04434                   SetPixelGreen(composite_image,
04435                     ScaleShortToQuantum(colors[index].green),q);
04436                   index=(pixel >> blue_shift) & blue_mask;
04437                   SetPixelBlue(composite_image,
04438                     ScaleShortToQuantum(colors[index].blue),q);
04439                   q+=GetPixelChannels(composite_image);
04440                 }
04441                 status=SyncCacheViewAuthenticPixels(composite_view,exception);
04442                 if (status == MagickFalse)
04443                   break;
04444               }
04445             else
04446               for (y=0; y < (int) composite_image->rows; y++)
04447               {
04448                 q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
04449                   composite_image->columns,1,exception);
04450                 if (q == (Quantum *) NULL)
04451                   break;
04452                 for (x=0; x < (int) composite_image->columns; x++)
04453                 {
04454                   pixel=XGetPixel(ximage,x,y);
04455                   color=(pixel >> red_shift) & red_mask;
04456                   color=(65535UL*color)/red_mask;
04457                   SetPixelRed(composite_image,
04458                     ScaleShortToQuantum((unsigned short) color),q);
04459                   color=(pixel >> green_shift) & green_mask;
04460                   color=(65535UL*color)/green_mask;
04461                   SetPixelGreen(composite_image,
04462                     ScaleShortToQuantum((unsigned short) color),q);
04463                   color=(pixel >> blue_shift) & blue_mask;
04464                   color=(65535UL*color)/blue_mask;
04465                   SetPixelBlue(composite_image,
04466                     ScaleShortToQuantum((unsigned short) color),q);
04467                   q+=GetPixelChannels(composite_image);
04468                 }
04469                 status=SyncCacheViewAuthenticPixels(composite_view,exception);
04470                 if (status == MagickFalse)
04471                   break;
04472               }
04473             break;
04474           }
04475           case PseudoClass:
04476           {
04477             /*
04478               Create colormap.
04479             */
04480             status=AcquireImageColormap(composite_image,number_colors,
04481               exception);
04482             if (status == MagickFalse)
04483               {
04484                 XDestroyImage(ximage);
04485                 composite_image=DestroyImage(composite_image);
04486                 return((Image *) NULL);
04487               }
04488             for (i=0; i < (int) composite_image->colors; i++)
04489             {
04490               composite_image->colormap[colors[i].pixel].red=
04491                 ScaleShortToQuantum(colors[i].red);
04492               composite_image->colormap[colors[i].pixel].green=
04493                 ScaleShortToQuantum(colors[i].green);
04494               composite_image->colormap[colors[i].pixel].blue=
04495                 ScaleShortToQuantum(colors[i].blue);
04496             }
04497             /*
04498               Convert X image to PseudoClass packets.
04499             */
04500             for (y=0; y < (int) composite_image->rows; y++)
04501             {
04502               q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
04503                 composite_image->columns,1,exception);
04504               if (q == (Quantum *) NULL)
04505                 break;
04506               for (x=0; x < (int) composite_image->columns; x++)
04507               {
04508                 index=(Quantum) XGetPixel(ximage,x,y);
04509                 SetPixelIndex(composite_image,index,q);
04510                 SetPixelInfoPixel(composite_image,
04511                   composite_image->colormap+(ssize_t) index,q);
04512                 q+=GetPixelChannels(composite_image);
04513               }
04514               status=SyncCacheViewAuthenticPixels(composite_view,exception);
04515               if (status == MagickFalse)
04516                 break;
04517             }
04518             break;
04519           }
04520         }
04521         composite_view=DestroyCacheView(composite_view);
04522         XDestroyImage(ximage);
04523         if (image == (Image *) NULL)
04524           {
04525             image=composite_image;
04526             continue;
04527           }
04528         /*
04529           Composite any children in back-to-front order.
04530         */
04531         (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
04532           &x_offset,&y_offset,&child);
04533         x_offset-=(int) crop_info.x;
04534         if (x_offset < 0)
04535           x_offset=0;
04536         y_offset-=(int) crop_info.y;
04537         if (y_offset < 0)
04538           y_offset=0;
04539         (void) CompositeImage(image,CopyCompositeOp,composite_image,(ssize_t)
04540           x_offset,(ssize_t) y_offset,exception);
04541       }
04542       /*
04543         Relinquish resources.
04544       */
04545       while (colormap_info != (ColormapInfo *) NULL)
04546       {
04547         next=colormap_info->next;
04548         colormap_info->colors=(XColor *) RelinquishMagickMemory(
04549           colormap_info->colors);
04550         colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
04551         colormap_info=next;
04552       }
04553       /*
04554         Relinquish resources and restore initial state.
04555       */
04556       window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
04557       max_windows=0;
04558       number_windows=0;
04559       colormap_info=(ColormapInfo *) NULL;
04560       return(image);
04561     }
04562   return((Image *) NULL);
04563 }
04564 
04565 /*
04566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04567 %                                                                             %
04568 %                                                                             %
04569 %                                                                             %
04570 %   X G e t W i n d o w I n f o                                               %
04571 %                                                                             %
04572 %                                                                             %
04573 %                                                                             %
04574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04575 %
04576 %  XGetWindowInfo() initializes the XWindowInfo structure.
04577 %
04578 %  The format of the XGetWindowInfo method is:
04579 %
04580 %      void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
04581 %        XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
04582 %        XResourceInfo *resource_info,XWindowInfo *window)
04583 %        resource_info,window)
04584 %
04585 %  A description of each parameter follows:
04586 %
04587 %    o display: Specifies a connection to an X server; returned from
04588 %      XOpenDisplay.
04589 %
04590 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
04591 %      returned from XGetVisualInfo.
04592 %
04593 %    o map_info: If map_type is specified, this structure is initialized
04594 %      with info from the Standard Colormap.
04595 %
04596 %    o pixel: Specifies a pointer to a XPixelInfo structure.
04597 %
04598 %    o font_info: Specifies a pointer to a XFontStruct structure.
04599 %
04600 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
04601 %
04602 */
04603 MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
04604   XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
04605   XResourceInfo *resource_info,XWindowInfo *window)
04606 {
04607   /*
04608     Initialize window info.
04609   */
04610   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
04611   assert(display != (Display *) NULL);
04612   assert(visual_info != (XVisualInfo *) NULL);
04613   assert(map_info != (XStandardColormap *) NULL);
04614   assert(pixel != (XPixelInfo *) NULL);
04615   assert(resource_info != (XResourceInfo *) NULL);
04616   assert(window != (XWindowInfo *) NULL);
04617   if (window->id != (Window) NULL)
04618     {
04619       if (window->cursor != (Cursor) NULL)
04620         (void) XFreeCursor(display,window->cursor);
04621       if (window->busy_cursor != (Cursor) NULL)
04622         (void) XFreeCursor(display,window->busy_cursor);
04623       if (window->highlight_stipple != (Pixmap) NULL)
04624         (void) XFreePixmap(display,window->highlight_stipple);
04625       if (window->shadow_stipple != (Pixmap) NULL)
04626         (void) XFreePixmap(display,window->shadow_stipple);
04627       if (window->name == (char *) NULL)
04628         window->name=AcquireString("");
04629       if (window->icon_name == (char *) NULL)
04630         window->icon_name=AcquireString("");
04631     }
04632   else
04633     {
04634       /*
04635         Initialize these attributes just once.
04636       */
04637       window->id=(Window) NULL;
04638       if (window->name == (char *) NULL)
04639         window->name=AcquireString("");
04640       if (window->icon_name == (char *) NULL)
04641         window->icon_name=AcquireString("");
04642       window->x=XDisplayWidth(display,visual_info->screen) >> 1;
04643       window->y=XDisplayWidth(display,visual_info->screen) >> 1;
04644       window->ximage=(XImage *) NULL;
04645       window->matte_image=(XImage *) NULL;
04646       window->pixmap=(Pixmap) NULL;
04647       window->matte_pixmap=(Pixmap) NULL;
04648       window->mapped=MagickFalse;
04649       window->stasis=MagickFalse;
04650       window->shared_memory=MagickTrue;
04651       window->segment_info=(void *) NULL;
04652 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
04653       {
04654         XShmSegmentInfo
04655           *segment_info;
04656 
04657         if (window->segment_info == (void *) NULL)
04658           window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
04659         segment_info=(XShmSegmentInfo *) window->segment_info;
04660         segment_info[0].shmid=(-1);
04661         segment_info[0].shmaddr=(char *) NULL;
04662         segment_info[1].shmid=(-1);
04663         segment_info[1].shmaddr=(char *) NULL;
04664       }
04665 #endif
04666     }
04667   /*
04668     Initialize these attributes every time function is called.
04669   */
04670   window->screen=visual_info->screen;
04671   window->root=XRootWindow(display,visual_info->screen);
04672   window->visual=visual_info->visual;
04673   window->storage_class=(unsigned int) visual_info->klass;
04674   window->depth=(unsigned int) visual_info->depth;
04675   window->visual_info=visual_info;
04676   window->map_info=map_info;
04677   window->pixel_info=pixel;
04678   window->font_info=font_info;
04679   window->cursor=XCreateFontCursor(display,XC_left_ptr);
04680   window->busy_cursor=XCreateFontCursor(display,XC_watch);
04681   window->geometry=(char *) NULL;
04682   window->icon_geometry=(char *) NULL;
04683   if (resource_info->icon_geometry != (char *) NULL)
04684     (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
04685   window->crop_geometry=(char *) NULL;
04686   window->flags=(size_t) PSize;
04687   window->width=1;
04688   window->height=1;
04689   window->min_width=1;
04690   window->min_height=1;
04691   window->width_inc=1;
04692   window->height_inc=1;
04693   window->border_width=resource_info->border_width;
04694   window->annotate_context=pixel->annotate_context;
04695   window->highlight_context=pixel->highlight_context;
04696   window->widget_context=pixel->widget_context;
04697   window->shadow_stipple=(Pixmap) NULL;
04698   window->highlight_stipple=(Pixmap) NULL;
04699   window->use_pixmap=MagickTrue;
04700   window->immutable=MagickFalse;
04701   window->shape=MagickFalse;
04702   window->data=0;
04703   window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
04704     CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
04705     CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
04706   window->attributes.background_pixel=pixel->background_color.pixel;
04707   window->attributes.background_pixmap=(Pixmap) NULL;
04708   window->attributes.bit_gravity=ForgetGravity;
04709   window->attributes.backing_store=WhenMapped;
04710   window->attributes.save_under=MagickTrue;
04711   window->attributes.border_pixel=pixel->border_color.pixel;
04712   window->attributes.colormap=map_info->colormap;
04713   window->attributes.cursor=window->cursor;
04714   window->attributes.do_not_propagate_mask=NoEventMask;
04715   window->attributes.event_mask=NoEventMask;
04716   window->attributes.override_redirect=MagickFalse;
04717   window->attributes.win_gravity=NorthWestGravity;
04718   window->orphan=MagickFalse;
04719 }
04720 
04721 /*
04722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04723 %                                                                             %
04724 %                                                                             %
04725 %                                                                             %
04726 %   X H i g h l i g h t E l l i p s e                                         %
04727 %                                                                             %
04728 %                                                                             %
04729 %                                                                             %
04730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04731 %
04732 %  XHighlightEllipse() puts a border on the X server around a region defined by
04733 %  highlight_info.
04734 %
04735 %  The format of the XHighlightEllipse method is:
04736 %
04737 %      void XHighlightEllipse(Display *display,Window window,
04738 %        GC annotate_context,const RectangleInfo *highlight_info)
04739 %
04740 %  A description of each parameter follows:
04741 %
04742 %    o display: Specifies a connection to an X server; returned from
04743 %      XOpenDisplay.
04744 %
04745 %    o window: Specifies a pointer to a Window structure.
04746 %
04747 %    o annotate_context: Specifies a pointer to a GC structure.
04748 %
04749 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
04750 %      contains the extents of any highlighting rectangle.
04751 %
04752 */
04753 MagickPrivate void XHighlightEllipse(Display *display,Window window,
04754   GC annotate_context,const RectangleInfo *highlight_info)
04755 {
04756   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
04757   assert(display != (Display *) NULL);
04758   assert(window != (Window) NULL);
04759   assert(annotate_context != (GC) NULL);
04760   assert(highlight_info != (RectangleInfo *) NULL);
04761   if ((highlight_info->width < 4) || (highlight_info->height < 4))
04762     return;
04763   (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
04764     (int) highlight_info->y,(unsigned int) highlight_info->width-1,
04765     (unsigned int) highlight_info->height-1,0,360*64);
04766   (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
04767     (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
04768     (unsigned int) highlight_info->height-3,0,360*64);
04769 }
04770 
04771 /*
04772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04773 %                                                                             %
04774 %                                                                             %
04775 %                                                                             %
04776 %   X H i g h l i g h t L i n e                                               %
04777 %                                                                             %
04778 %                                                                             %
04779 %                                                                             %
04780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04781 %
04782 %  XHighlightLine() puts a border on the X server around a region defined by
04783 %  highlight_info.
04784 %
04785 %  The format of the XHighlightLine method is:
04786 %
04787 %      void XHighlightLine(Display *display,Window window,GC annotate_context,
04788 %        const XSegment *highlight_info)
04789 %
04790 %  A description of each parameter follows:
04791 %
04792 %    o display: Specifies a connection to an X server; returned from
04793 %      XOpenDisplay.
04794 %
04795 %    o window: Specifies a pointer to a Window structure.
04796 %
04797 %    o annotate_context: Specifies a pointer to a GC structure.
04798 %
04799 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
04800 %      contains the extents of any highlighting rectangle.
04801 %
04802 */
04803 MagickPrivate void XHighlightLine(Display *display,Window window,
04804   GC annotate_context,const XSegment *highlight_info)
04805 {
04806   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
04807   assert(display != (Display *) NULL);
04808   assert(window != (Window) NULL);
04809   assert(annotate_context != (GC) NULL);
04810   assert(highlight_info != (XSegment *) NULL);
04811   (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
04812     highlight_info->y1,highlight_info->x2,highlight_info->y2);
04813 }
04814 
04815 /*
04816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04817 %                                                                             %
04818 %                                                                             %
04819 %                                                                             %
04820 %   X H i g h l i g h t R e c t a n g l e                                     %
04821 %                                                                             %
04822 %                                                                             %
04823 %                                                                             %
04824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04825 %
04826 %  XHighlightRectangle() puts a border on the X server around a region defined
04827 %  by highlight_info.
04828 %
04829 %  The format of the XHighlightRectangle method is:
04830 %
04831 %      void XHighlightRectangle(Display *display,Window window,
04832 %        GC annotate_context,const RectangleInfo *highlight_info)
04833 %
04834 %  A description of each parameter follows:
04835 %
04836 %    o display: Specifies a connection to an X server; returned from
04837 %      XOpenDisplay.
04838 %
04839 %    o window: Specifies a pointer to a Window structure.
04840 %
04841 %    o annotate_context: Specifies a pointer to a GC structure.
04842 %
04843 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
04844 %      contains the extents of any highlighting rectangle.
04845 %
04846 */
04847 MagickPrivate void XHighlightRectangle(Display *display,Window window,
04848   GC annotate_context,const RectangleInfo *highlight_info)
04849 {
04850   assert(display != (Display *) NULL);
04851   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
04852   assert(window != (Window) NULL);
04853   assert(annotate_context != (GC) NULL);
04854   assert(highlight_info != (RectangleInfo *) NULL);
04855   if ((highlight_info->width < 4) || (highlight_info->height < 4))
04856     return;
04857   (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
04858     (int) highlight_info->y,(unsigned int) highlight_info->width-1,
04859     (unsigned int) highlight_info->height-1);
04860   (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
04861     1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
04862     (unsigned int) highlight_info->height-3);
04863 }
04864 
04865 /*
04866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04867 %                                                                             %
04868 %                                                                             %
04869 %                                                                             %
04870 %   X I m p o r t I m a g e                                                   %
04871 %                                                                             %
04872 %                                                                             %
04873 %                                                                             %
04874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04875 %
04876 %  XImportImage() reads an image from an X window.
04877 %
04878 %  The format of the XImportImage method is:
04879 %
04880 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
04881 %        ExceptionInfo *exception)
04882 %
04883 %  A description of each parameter follows:
04884 %
04885 %    o image_info: the image info.
04886 %
04887 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
04888 %
04889 %    o exception: return any errors or warnings in this structure.
04890 %
04891 */
04892 MagickExport Image *XImportImage(const ImageInfo *image_info,
04893   XImportInfo *ximage_info,ExceptionInfo *exception)
04894 {
04895   Colormap
04896     *colormaps;
04897 
04898   Display
04899     *display;
04900 
04901   Image
04902     *image;
04903 
04904   int
04905     number_colormaps,
04906     number_windows,
04907     x;
04908 
04909   RectangleInfo
04910     crop_info;
04911 
04912   Status
04913     status;
04914 
04915   Window
04916     *children,
04917     client,
04918     prior_target,
04919     root,
04920     target;
04921 
04922   XTextProperty
04923     window_name;
04924 
04925   /*
04926     Open X server connection.
04927   */
04928   assert(image_info != (const ImageInfo *) NULL);
04929   assert(image_info->signature == MagickSignature);
04930   if (image_info->debug != MagickFalse)
04931     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
04932       image_info->filename);
04933   assert(ximage_info != (XImportInfo *) NULL);
04934   display=XOpenDisplay(image_info->server_name);
04935   if (display == (Display *) NULL)
04936     {
04937       ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
04938         XDisplayName(image_info->server_name));
04939       return((Image *) NULL);
04940     }
04941   /*
04942     Set our forgiving exception handler.
04943   */
04944   (void) XSetErrorHandler(XError);
04945   /*
04946     Select target window.
04947   */
04948   crop_info.x=0;
04949   crop_info.y=0;
04950   crop_info.width=0;
04951   crop_info.height=0;
04952   root=XRootWindow(display,XDefaultScreen(display));
04953   target=(Window) NULL;
04954   if ((image_info->filename != (char *) NULL) &&
04955       (*image_info->filename != '\0'))
04956     {
04957       if (LocaleCompare(image_info->filename,"root") == 0)
04958         target=root;
04959       else
04960         {
04961           /*
04962             Select window by ID or name.
04963           */
04964           if (isdigit((unsigned char) *image_info->filename) != 0)
04965             target=XWindowByID(display,root,(Window)
04966               strtol(image_info->filename,(char **) NULL,0));
04967           if (target == (Window) NULL)
04968             target=XWindowByName(display,root,image_info->filename);
04969           if (target == (Window) NULL)
04970             ThrowXWindowFatalException(XServerError,
04971               "NoWindowWithSpecifiedIDExists",image_info->filename);
04972         }
04973     }
04974   /*
04975     If target window is not defined, interactively select one.
04976   */
04977   prior_target=target;
04978   if (target == (Window) NULL)
04979     target=XSelectWindow(display,&crop_info);
04980   if (target == (Window) NULL)
04981     ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
04982       image_info->filename);
04983   client=target;   /* obsolete */
04984   if (target != root)
04985     {
04986       unsigned int
04987         d;
04988 
04989       status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
04990       if (status != False)
04991         {
04992           for ( ; ; )
04993           {
04994             Window
04995               parent;
04996 
04997             /*
04998               Find window manager frame.
04999             */
05000             status=XQueryTree(display,target,&root,&parent,&children,&d);
05001             if ((status != False) && (children != (Window *) NULL))
05002               (void) XFree((char *) children);
05003             if ((status == False) || (parent == (Window) NULL) ||
05004                 (parent == root))
05005               break;
05006             target=parent;
05007           }
05008           /*
05009             Get client window.
05010           */
05011           client=XClientWindow(display,target);
05012           if (ximage_info->frame == MagickFalse)
05013             target=client;
05014           if ((ximage_info->frame == MagickFalse) &&
05015               (prior_target != MagickFalse))
05016             target=prior_target;
05017         }
05018     }
05019   if (ximage_info->screen)
05020     {
05021       int
05022         y;
05023 
05024       Window
05025         child;
05026 
05027       XWindowAttributes
05028         window_attributes;
05029 
05030       /*
05031         Obtain window image directly from screen.
05032       */
05033       status=XGetWindowAttributes(display,target,&window_attributes);
05034       if (status == False)
05035         {
05036           ThrowXWindowFatalException(XServerError,
05037             "UnableToReadXWindowAttributes",image_info->filename);
05038           (void) XCloseDisplay(display);
05039           return((Image *) NULL);
05040         }
05041       (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
05042       crop_info.x=(ssize_t) x;
05043       crop_info.y=(ssize_t) y;
05044       crop_info.width=(size_t) window_attributes.width;
05045       crop_info.height=(size_t) window_attributes.height;
05046       if (ximage_info->borders != 0)
05047         {
05048           /*
05049             Include border in image.
05050           */
05051           crop_info.x-=window_attributes.border_width;
05052           crop_info.y-=window_attributes.border_width;
05053           crop_info.width+=window_attributes.border_width << 1;
05054           crop_info.height+=window_attributes.border_width << 1;
05055         }
05056       target=root;
05057     }
05058   /*
05059     If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
05060   */
05061   number_windows=0;
05062   status=XGetWMColormapWindows(display,target,&children,&number_windows);
05063   if ((status == True) && (number_windows > 0))
05064     {
05065       ximage_info->descend=MagickTrue;
05066       (void) XFree ((char *) children);
05067     }
05068   colormaps=XListInstalledColormaps(display,target,&number_colormaps);
05069   if (number_colormaps > 0)
05070     {
05071       if (number_colormaps > 1)
05072         ximage_info->descend=MagickTrue;
05073       (void) XFree((char *) colormaps);
05074     }
05075   /*
05076     Alert the user not to alter the screen.
05077   */
05078   if (ximage_info->silent == MagickFalse)
05079     (void) XBell(display,0);
05080   /*
05081     Get image by window id.
05082   */
05083   (void) XGrabServer(display);
05084   image=XGetWindowImage(display,target,ximage_info->borders,
05085     ximage_info->descend ? 1U : 0U,exception);
05086   (void) XUngrabServer(display);
05087   if (image == (Image *) NULL)
05088     ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
05089       image_info->filename)
05090   else
05091     {
05092       (void) CopyMagickString(image->filename,image_info->filename,
05093         MaxTextExtent);
05094       if ((crop_info.width != 0) && (crop_info.height != 0))
05095         {
05096           Image
05097             *clone_image,
05098             *crop_image;
05099 
05100           /*
05101             Crop image as defined by the cropping rectangle.
05102           */
05103           clone_image=CloneImage(image,0,0,MagickTrue,exception);
05104           if (clone_image != (Image *) NULL)
05105             {
05106               crop_image=CropImage(clone_image,&crop_info,exception);
05107               if (crop_image != (Image *) NULL)
05108                 {
05109                   image=DestroyImage(image);
05110                   image=crop_image;
05111                 }
05112             }
05113         }
05114       status=XGetWMName(display,target,&window_name);
05115       if (status == True)
05116         {
05117           if ((image_info->filename != (char *) NULL) &&
05118               (*image_info->filename == '\0'))
05119             (void) CopyMagickString(image->filename,(char *) window_name.value,
05120               (size_t) window_name.nitems+1);
05121           (void) XFree((void *) window_name.value);
05122         }
05123     }
05124   if (ximage_info->silent == MagickFalse)
05125     {
05126       /*
05127         Alert the user we're done.
05128       */
05129       (void) XB