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