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-2010 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 "magick/studio.h"
00043 #include "magick/animate.h"
00044 #include "magick/artifact.h"
00045 #include "magick/blob.h"
00046 #include "magick/cache.h"
00047 #include "magick/client.h"
00048 #include "magick/color.h"
00049 #include "magick/color-private.h"
00050 #include "magick/composite.h"
00051 #include "magick/display.h"
00052 #include "magick/exception.h"
00053 #include "magick/exception-private.h"
00054 #include "magick/geometry.h"
00055 #include "magick/identify.h"
00056 #include "magick/image.h"
00057 #include "magick/image-private.h"
00058 #include "magick/list.h"
00059 #include "magick/locale_.h"
00060 #include "magick/log.h"
00061 #include "magick/magick.h"
00062 #include "magick/memory_.h"
00063 #include "magick/monitor.h"
00064 #include "magick/option.h"
00065 #include "magick/PreRvIcccm.h"
00066 #include "magick/quantize.h"
00067 #include "magick/quantum.h"
00068 #include "magick/quantum-private.h"
00069 #include "magick/resource_.h"
00070 #include "magick/resize.h"
00071 #include "magick/shear.h"
00072 #include "magick/statistic.h"
00073 #include "magick/string_.h"
00074 #include "magick/transform.h"
00075 #include "magick/utility.h"
00076 #include "magick/widget.h"
00077 #include "magick/xwindow.h"
00078 #include "magick/xwindow-private.h"
00079 #include "magick/version.h"
00080 #if defined(__BEOS__)
00081 #include <OS.h>
00082 #endif
00083 #if defined(MAGICKCORE_X11_DELEGATE)
00084 #include <X11/Xproto.h>
00085 #include <X11/Xlocale.h>
00086 #if defined(MAGICK_HAVE_POLL)
00087 # include <sys/poll.h>
00088 #endif
00089 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
00090 #if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
00091 # include <machine/param.h>
00092 #endif
00093 #include <sys/ipc.h>
00094 #include <sys/shm.h>
00095 #include <X11/extensions/XShm.h>
00096 #endif
00097 #if defined(MAGICKCORE_HAVE_SHAPE)
00098 #include <X11/extensions/shape.h>
00099 #endif
00100 
00101 /*
00102   X defines.
00103 */
00104 #define XBlueGamma(color) RoundToQuantum(blue_gamma == 1.0 ? (double) \
00105   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
00106   QuantumRange)))
00107 #define XGammaPixel(map,color)  (unsigned long) (map->base_pixel+ \
00108   ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
00109     map->red_mult)+ \
00110   ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
00111     map->green_mult)+ \
00112   ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
00113     map->blue_mult))
00114 #define XGreenGamma(color) RoundToQuantum(green_gamma == 1.0 ? (double) \
00115   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
00116   QuantumRange)))
00117 #define XRedGamma(color) RoundToQuantum(red_gamma == 1.0 ? (double) \
00118   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
00119   QuantumRange)))
00120 #define XStandardPixel(map,color)  (unsigned long) (map->base_pixel+ \
00121   (((color)->red*map->red_max/65535L)*map->red_mult)+ \
00122   (((color)->green*map->green_max/65535L)*map->green_mult)+ \
00123   (((color)->blue*map->blue_max/65535L)*map->blue_mult))
00124 
00125 #define AccentuateModulate  ScaleCharToQuantum(80)
00126 #define HighlightModulate  ScaleCharToQuantum(125)
00127 #define ShadowModulate  ScaleCharToQuantum(135)
00128 #define DepthModulate  ScaleCharToQuantum(185)
00129 #define TroughModulate  ScaleCharToQuantum(110)
00130 
00131 #define XLIB_ILLEGAL_ACCESS  1
00132 #undef ForgetGravity
00133 #undef NorthWestGravity
00134 #undef NorthGravity
00135 #undef NorthEastGravity
00136 #undef WestGravity
00137 #undef CenterGravity
00138 #undef EastGravity
00139 #undef SouthWestGravity
00140 #undef SouthGravity
00141 #undef SouthEastGravity
00142 #undef StaticGravity
00143 
00144 #undef index
00145 #if defined(hpux9)
00146 #define XFD_SET  int
00147 #else
00148 #define XFD_SET  fd_set
00149 #endif
00150 
00151 /*
00152   Enumeration declarations.
00153 */
00154 typedef enum
00155 {
00156 #undef DoRed
00157   DoRed = 0x0001,
00158 #undef DoGreen
00159   DoGreen = 0x0002,
00160 #undef DoBlue
00161   DoBlue = 0x0004,
00162   DoMatte = 0x0008
00163 } XColorFlags;
00164 
00165 /*
00166   Typedef declarations.
00167 */
00168 typedef struct _DiversityPacket
00169 {
00170   Quantum
00171     red,
00172     green,
00173     blue;
00174 
00175   unsigned short
00176     index;
00177 
00178   unsigned long
00179     count;
00180 } DiversityPacket;
00181 
00182 /*
00183   Constant declaractions.
00184 */
00185 static MagickBooleanType
00186   xerror_alert = MagickFalse;
00187 
00188 /*
00189   Method prototypes.
00190 */
00191 static const char
00192   *XVisualClassName(const int);
00193 
00194 static MagickRealType
00195   blue_gamma = 1.0,
00196   green_gamma = 1.0,
00197   red_gamma = 1.0;
00198 
00199 static MagickBooleanType
00200   XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
00201 
00202 static void
00203   XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
00204     XImage *,XImage *),
00205   XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
00206     XImage *,XImage *);
00207 
00208 static Window
00209   XSelectWindow(Display *,RectangleInfo *);
00210 
00211 /*
00212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00213 %                                                                             %
00214 %                                                                             %
00215 %                                                                             %
00216 %   D e s t r o y X R e s o u r c e s                                         %
00217 %                                                                             %
00218 %                                                                             %
00219 %                                                                             %
00220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00221 %
00222 %  DestroyXResources() destroys any X resources.
00223 %
00224 %  The format of the DestroyXResources method is:
00225 %
00226 %      void DestroyXResources()
00227 %
00228 %  A description of each parameter follows:
00229 %
00230 */
00231 MagickExport void DestroyXResources(void)
00232 {
00233   register int
00234     i;
00235 
00236   unsigned int
00237     number_windows;
00238 
00239   XWindowInfo
00240     *magick_windows[MaxXWindows];
00241 
00242   XWindows
00243     *windows;
00244 
00245   DestroyXWidget();
00246   windows=XSetWindows((XWindows *) ~0);
00247   if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
00248     return;
00249   number_windows=0;
00250   magick_windows[number_windows++]=(&windows->context);
00251   magick_windows[number_windows++]=(&windows->group_leader);
00252   magick_windows[number_windows++]=(&windows->backdrop);
00253   magick_windows[number_windows++]=(&windows->icon);
00254   magick_windows[number_windows++]=(&windows->image);
00255   magick_windows[number_windows++]=(&windows->info);
00256   magick_windows[number_windows++]=(&windows->magnify);
00257   magick_windows[number_windows++]=(&windows->pan);
00258   magick_windows[number_windows++]=(&windows->command);
00259   magick_windows[number_windows++]=(&windows->widget);
00260   magick_windows[number_windows++]=(&windows->popup);
00261   magick_windows[number_windows++]=(&windows->context);
00262   for (i=0; i < (int) number_windows; i++)
00263   {
00264     if (magick_windows[i]->mapped != MagickFalse)
00265       {
00266         (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
00267           magick_windows[i]->screen);
00268         magick_windows[i]->mapped=MagickFalse;
00269       }
00270     if (magick_windows[i]->name != (char *) NULL)
00271       magick_windows[i]->name=(char *)
00272         RelinquishMagickMemory(magick_windows[i]->name);
00273     if (magick_windows[i]->icon_name != (char *) NULL)
00274       magick_windows[i]->icon_name=(char *)
00275         RelinquishMagickMemory(magick_windows[i]->icon_name);
00276     if (magick_windows[i]->cursor != (Cursor) NULL)
00277       {
00278         (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
00279         magick_windows[i]->cursor=(Cursor) NULL;
00280       }
00281     if (magick_windows[i]->busy_cursor != (Cursor) NULL)
00282       {
00283         (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
00284         magick_windows[i]->busy_cursor=(Cursor) NULL;
00285       }
00286     if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
00287       {
00288         (void) XFreePixmap(windows->display,
00289           magick_windows[i]->highlight_stipple);
00290         magick_windows[i]->highlight_stipple=(Pixmap) NULL;
00291       }
00292     if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
00293       {
00294         (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
00295         magick_windows[i]->shadow_stipple=(Pixmap) NULL;
00296       }
00297     if (magick_windows[i]->ximage != (XImage *) NULL)
00298       {
00299         XDestroyImage(magick_windows[i]->ximage);
00300         magick_windows[i]->ximage=(XImage *) NULL;
00301       }
00302     if (magick_windows[i]->pixmap != (Pixmap) NULL)
00303       {
00304         (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
00305         magick_windows[i]->pixmap=(Pixmap) NULL;
00306       }
00307     if (magick_windows[i]->id != (Window) NULL)
00308       {
00309         (void) XDestroyWindow(windows->display,magick_windows[i]->id);
00310         magick_windows[i]->id=(Window) NULL;
00311       }
00312     if (magick_windows[i]->destroy != MagickFalse)
00313       {
00314         if (magick_windows[i]->image != (Image *) NULL)
00315           {
00316             magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
00317             magick_windows[i]->image=NewImageList();
00318           }
00319         if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
00320           {
00321             (void) XFreePixmap(windows->display,
00322               magick_windows[i]->matte_pixmap);
00323             magick_windows[i]->matte_pixmap=(Pixmap) NULL;
00324           }
00325       }
00326     if (magick_windows[i]->segment_info != (void *) NULL)
00327       {
00328 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
00329         XShmSegmentInfo
00330           *segment_info;
00331 
00332         segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
00333         if (segment_info != (XShmSegmentInfo *) NULL)
00334           if (segment_info[0].shmid >= 0)
00335             {
00336               if (segment_info[0].shmaddr != NULL)
00337                 (void) shmdt(segment_info[0].shmaddr);
00338               (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
00339               segment_info[0].shmaddr=NULL;
00340               segment_info[0].shmid=(-1);
00341             }
00342 #endif
00343         magick_windows[i]->segment_info=(void *)
00344           RelinquishMagickMemory(magick_windows[i]->segment_info);
00345       }
00346   }
00347   windows->icon_resources=(XResourceInfo *)
00348     RelinquishMagickMemory(windows->icon_resources);
00349   if (windows->icon_pixel != (XPixelInfo *) NULL)
00350     {
00351       if (windows->icon_pixel->pixels != (unsigned long *) NULL)
00352         windows->icon_pixel->pixels=(unsigned long *)
00353           RelinquishMagickMemory(windows->icon_pixel->pixels);
00354       if (windows->icon_pixel->annotate_context != (GC) NULL)
00355         XFreeGC(windows->display,windows->icon_pixel->annotate_context);
00356       windows->icon_pixel=(XPixelInfo *)
00357         RelinquishMagickMemory(windows->icon_pixel);
00358     }
00359   if (windows->pixel_info != (XPixelInfo *) NULL)
00360     {
00361       if (windows->pixel_info->pixels != (unsigned long *) NULL)
00362         windows->pixel_info->pixels=(unsigned long *)
00363           RelinquishMagickMemory(windows->pixel_info->pixels);
00364       if (windows->pixel_info->annotate_context != (GC) NULL)
00365         XFreeGC(windows->display,windows->pixel_info->annotate_context);
00366       if (windows->pixel_info->widget_context != (GC) NULL)
00367         XFreeGC(windows->display,windows->pixel_info->widget_context);
00368       if (windows->pixel_info->highlight_context != (GC) NULL)
00369         XFreeGC(windows->display,windows->pixel_info->highlight_context);
00370       windows->pixel_info=(XPixelInfo *)
00371         RelinquishMagickMemory(windows->pixel_info);
00372     }
00373   if (windows->font_info != (XFontStruct *) NULL)
00374     {
00375       XFreeFont(windows->display,windows->font_info);
00376       windows->font_info=(XFontStruct *) NULL;
00377     }
00378   if (windows->class_hints != (XClassHint *) NULL)
00379     {
00380       if (windows->class_hints->res_name != (char *) NULL)
00381         XFree(windows->class_hints->res_name);
00382       if (windows->class_hints->res_class != (char *) NULL)
00383         XFree(windows->class_hints->res_class);
00384       XFree(windows->class_hints);
00385       windows->class_hints=(XClassHint *) NULL;
00386     }
00387   if (windows->manager_hints != (XWMHints *) NULL)
00388     {
00389       XFree(windows->manager_hints);
00390       windows->manager_hints=(XWMHints *) NULL;
00391     }
00392   if (windows->map_info != (XStandardColormap *) NULL)
00393     {
00394       XFree(windows->map_info);
00395       windows->map_info=(XStandardColormap *) NULL;
00396     }
00397   if (windows->icon_map != (XStandardColormap *) NULL)
00398     {
00399       XFree(windows->icon_map);
00400       windows->icon_map=(XStandardColormap *) NULL;
00401     }
00402   if (windows->visual_info != (XVisualInfo *) NULL)
00403     {
00404       XFree(windows->visual_info);
00405       windows->visual_info=(XVisualInfo *) NULL;
00406     }
00407   if (windows->icon_visual != (XVisualInfo *) NULL)
00408     {
00409       XFree(windows->icon_visual);
00410       windows->icon_visual=(XVisualInfo *) NULL;
00411     }
00412   (void) XSetWindows((XWindows *) NULL);
00413 }
00414 
00415 /*
00416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00417 %                                                                             %
00418 %                                                                             %
00419 %                                                                             %
00420 %   X A n n o t a t e I m a g e                                               %
00421 %                                                                             %
00422 %                                                                             %
00423 %                                                                             %
00424 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00425 %
00426 %  XAnnotateImage() annotates the image with text.
00427 %
00428 %  The format of the XAnnotateImage method is:
00429 %
00430 %      MagickBooleanType XAnnotateImage(Display *display,
00431 %        const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
00432 %
00433 %  A description of each parameter follows:
00434 %
00435 %    o display: Specifies a connection to an X server;  returned from
00436 %      XOpenDisplay.
00437 %
00438 %    o pixel: Specifies a pointer to a XPixelInfo structure.
00439 %
00440 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
00441 %
00442 %    o image: the image.
00443 %
00444 */
00445 MagickExport MagickBooleanType XAnnotateImage(Display *display,
00446   const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
00447 {
00448   GC
00449     annotate_context;
00450 
00451   ExceptionInfo
00452     *exception;
00453 
00454   Image
00455     *annotate_image;
00456 
00457   int
00458     x,
00459     y;
00460 
00461   MagickBooleanType
00462     matte;
00463 
00464   Pixmap
00465     annotate_pixmap;
00466 
00467   unsigned int
00468     depth,
00469     height,
00470     width;
00471 
00472   Window
00473     root_window;
00474 
00475   XGCValues
00476     context_values;
00477 
00478   XImage
00479     *annotate_ximage;
00480 
00481   /*
00482     Initialize annotated image.
00483   */
00484   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00485   assert(display != (Display *) NULL);
00486   assert(pixel != (XPixelInfo *) NULL);
00487   assert(annotate_info != (XAnnotateInfo *) NULL);
00488   assert(image != (Image *) NULL);
00489   /*
00490     Initialize annotated pixmap.
00491   */
00492   root_window=XRootWindow(display,XDefaultScreen(display));
00493   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
00494   annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
00495     annotate_info->height,depth);
00496   if (annotate_pixmap == (Pixmap) NULL)
00497     return(MagickFalse);
00498   /*
00499     Initialize graphics info.
00500   */
00501   context_values.background=0;
00502   context_values.foreground=(unsigned long) (~0);
00503   context_values.font=annotate_info->font_info->fid;
00504   annotate_context=XCreateGC(display,root_window,(unsigned long)
00505     GCBackground | GCFont | GCForeground,&context_values);
00506   if (annotate_context == (GC) NULL)
00507     return(MagickFalse);
00508   /*
00509     Draw text to pixmap.
00510   */
00511   (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
00512     (int) annotate_info->font_info->ascent,annotate_info->text,
00513     (int) strlen(annotate_info->text));
00514   (void) XFreeGC(display,annotate_context);
00515   /*
00516     Initialize annotated X image.
00517   */
00518   annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
00519     annotate_info->height,AllPlanes,ZPixmap);
00520   if (annotate_ximage == (XImage *) NULL)
00521     return(MagickFalse);
00522   (void) XFreePixmap(display,annotate_pixmap);
00523   /*
00524     Initialize annotated image.
00525   */
00526   annotate_image=AcquireImage((ImageInfo *) NULL);
00527   if (annotate_image == (Image *) NULL)
00528     return(MagickFalse);
00529   annotate_image->columns=annotate_info->width;
00530   annotate_image->rows=annotate_info->height;
00531   /*
00532     Transfer annotated X image to image.
00533   */
00534   width=(unsigned int) image->columns;
00535   height=(unsigned int) image->rows;
00536   x=0;
00537   y=0;
00538   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
00539   (void) GetOneVirtualPixel(image,x,y,&annotate_image->background_color,
00540     &image->exception);
00541   if (annotate_info->stencil == ForegroundStencil)
00542     annotate_image->matte=MagickTrue;
00543   exception=(&image->exception);
00544   for (y=0; y < (int) annotate_image->rows; y++)
00545   {
00546     register long
00547       x;
00548 
00549     register PixelPacket
00550       *__restrict q;
00551 
00552     q=GetAuthenticPixels(annotate_image,0,y,annotate_image->columns,1,
00553       exception);
00554     if (q == (PixelPacket *) NULL)
00555       break;
00556     for (x=0; x < (long) annotate_image->columns; x++)
00557     {
00558       q->opacity=OpaqueOpacity;
00559       if (XGetPixel(annotate_ximage,x,y) == 0)
00560         {
00561           /*
00562             Set this pixel to the background color.
00563           */
00564           q->red=ScaleShortToQuantum(pixel->box_color.red);
00565           q->green=ScaleShortToQuantum(pixel->box_color.green);
00566           q->blue=ScaleShortToQuantum(pixel->box_color.blue);
00567           if ((annotate_info->stencil == ForegroundStencil) ||
00568               (annotate_info->stencil == OpaqueStencil))
00569             q->opacity=(Quantum) TransparentOpacity;
00570         }
00571       else
00572         {
00573           /*
00574             Set this pixel to the pen color.
00575           */
00576           q->red=ScaleShortToQuantum(pixel->pen_color.red);
00577           q->green=ScaleShortToQuantum(pixel->pen_color.green);
00578           q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
00579           if (annotate_info->stencil == BackgroundStencil)
00580             q->opacity=(Quantum) TransparentOpacity;
00581         }
00582       q++;
00583     }
00584     if (SyncAuthenticPixels(annotate_image,exception) == MagickFalse)
00585       break;
00586   }
00587   XDestroyImage(annotate_ximage);
00588   /*
00589     Determine annotate geometry.
00590   */
00591   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
00592   if ((width != (unsigned int) annotate_image->columns) ||
00593       (height != (unsigned int) annotate_image->rows))
00594     {
00595       char
00596         image_geometry[MaxTextExtent];
00597 
00598       /*
00599         Scale image.
00600       */
00601       (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
00602         width,height);
00603       (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
00604     }
00605   if (annotate_info->degrees != 0.0)
00606     {
00607       Image
00608         *rotate_image;
00609 
00610       int
00611         rotations;
00612 
00613       MagickRealType
00614         normalized_degrees;
00615 
00616       /*
00617         Rotate image.
00618       */
00619       rotate_image=
00620         RotateImage(annotate_image,annotate_info->degrees,&image->exception);
00621       if (rotate_image == (Image *) NULL)
00622         return(MagickFalse);
00623       annotate_image=DestroyImage(annotate_image);
00624       annotate_image=rotate_image;
00625       /*
00626         Annotation is relative to the degree of rotation.
00627       */
00628       normalized_degrees=annotate_info->degrees;
00629       while (normalized_degrees < -45.0)
00630         normalized_degrees+=360.0;
00631       for (rotations=0; normalized_degrees > 45.0; rotations++)
00632         normalized_degrees-=90.0;
00633       switch (rotations % 4)
00634       {
00635         default:
00636         case 0:
00637           break;
00638         case 1:
00639         {
00640           /*
00641             Rotate 90 degrees.
00642           */
00643           x-=(int) annotate_image->columns/2;
00644           y+=(int) annotate_image->columns/2;
00645           break;
00646         }
00647         case 2:
00648         {
00649           /*
00650             Rotate 180 degrees.
00651           */
00652           x=x-(int) annotate_image->columns;
00653           break;
00654         }
00655         case 3:
00656         {
00657           /*
00658             Rotate 270 degrees.
00659           */
00660           x=x-(int) annotate_image->columns/2;
00661           y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
00662           break;
00663         }
00664       }
00665     }
00666   /*
00667     Composite text onto the image.
00668   */
00669   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
00670   matte=image->matte;
00671   (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
00672     OverCompositeOp : CopyCompositeOp,annotate_image,x,y);
00673   image->matte=matte;
00674   annotate_image=DestroyImage(annotate_image);
00675   return(MagickTrue);
00676 }
00677 
00678 /*
00679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00680 %                                                                             %
00681 %                                                                             %
00682 %                                                                             %
00683 %   X B e s t F o n t                                                         %
00684 %                                                                             %
00685 %                                                                             %
00686 %                                                                             %
00687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00688 %
00689 %  XBestFont() returns the "best" font.  "Best" is defined as a font specified
00690 %  in the X resource database or a font such that the text width displayed
00691 %  with the font does not exceed the specified maximum width.
00692 %
00693 %  The format of the XBestFont method is:
00694 %
00695 %      XFontStruct *XBestFont(Display *display,
00696 %        const XResourceInfo *resource_info,const MagickBooleanType text_font)
00697 %
00698 %  A description of each parameter follows:
00699 %
00700 %    o font: XBestFont returns a pointer to a XFontStruct structure.
00701 %
00702 %    o display: Specifies a connection to an X server;  returned from
00703 %      XOpenDisplay.
00704 %
00705 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
00706 %
00707 %    o text_font:  True is font should be mono-spaced (typewriter style).
00708 %
00709 %
00710 */
00711 
00712 static char **FontToList(char *font)
00713 {
00714   char
00715     **fontlist;
00716 
00717   register char
00718     *p,
00719     *q;
00720 
00721   register int
00722     i;
00723 
00724   unsigned int
00725     fonts;
00726 
00727   if (font == (char *) NULL)
00728     return((char **) NULL);
00729   /*
00730     Convert string to an ASCII list.
00731   */
00732   fonts=1U;
00733   for (p=font; *p != '\0'; p++)
00734     if ((*p == ':') || (*p == ';') || (*p == ','))
00735       fonts++;
00736   fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
00737   if (fontlist == (char **) NULL)
00738     {
00739       ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
00740         font);
00741       return((char **) NULL);
00742     }
00743   p=font;
00744   for (i=0; i < (int) fonts; i++)
00745   {
00746     for (q=p; *q != '\0'; q++)
00747       if ((*q == ':') || (*q == ';') || (*q == ','))
00748         break;
00749     fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
00750       sizeof(*fontlist[i]));
00751     if (fontlist[i] == (char *) NULL)
00752       {
00753         ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
00754           font);
00755         return((char **) NULL);
00756       }
00757     (void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
00758     p=q+1;
00759   }
00760   fontlist[i]=(char *) NULL;
00761   return(fontlist);
00762 }
00763 
00764 MagickExport XFontStruct *XBestFont(Display *display,
00765   const XResourceInfo *resource_info,const MagickBooleanType text_font)
00766 {
00767   static const char
00768     *Fonts[]=
00769     {
00770       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
00771       "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
00772       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
00773       "-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
00774       "-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
00775       "-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
00776       "variable",
00777       "fixed",
00778       (char *) NULL
00779     },
00780     *TextFonts[]=
00781     {
00782       "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
00783       "-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
00784       "-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
00785       "fixed",
00786       (char *) NULL
00787     };
00788 
00789   char
00790     *font_name;
00791 
00792   register const char
00793     **p;
00794 
00795   XFontStruct
00796     *font_info;
00797 
00798   font_info=(XFontStruct *) NULL;
00799   font_name=resource_info->font;
00800   if (text_font != MagickFalse)
00801     font_name=resource_info->text_font;
00802   if ((font_name != (char *) NULL) && (*font_name != '\0'))
00803     {
00804       char
00805         **fontlist;
00806 
00807       register int
00808         i;
00809 
00810       /*
00811         Load preferred font specified in the X resource database.
00812       */
00813       fontlist=FontToList(font_name);
00814       if (fontlist != (char **) NULL)
00815         {
00816           for (i=0; fontlist[i] != (char *) NULL; i++)
00817           {
00818             if (font_info == (XFontStruct *) NULL)
00819               font_info=XLoadQueryFont(display,fontlist[i]);
00820             fontlist[i]=DestroyString(fontlist[i]);
00821           }
00822           fontlist=(char **) RelinquishMagickMemory(fontlist);
00823         }
00824       if (font_info == (XFontStruct *) NULL)
00825         ThrowXWindowFatalException(XServerError,"UnableToLoadFont",font_name);
00826     }
00827   /*
00828     Load fonts from list of fonts until one is found.
00829   */
00830   p=Fonts;
00831   if (text_font != MagickFalse)
00832     p=TextFonts;
00833   if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
00834     p++;
00835   while (*p != (char *) NULL)
00836   {
00837     if (font_info != (XFontStruct *) NULL)
00838       break;
00839     font_info=XLoadQueryFont(display,(char *) *p);
00840     p++;
00841   }
00842   return(font_info);
00843 }
00844 
00845 /*
00846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00847 %                                                                             %
00848 %                                                                             %
00849 %                                                                             %
00850 %   X B e s t I c o n S i z e                                                 %
00851 %                                                                             %
00852 %                                                                             %
00853 %                                                                             %
00854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00855 %
00856 %  XBestIconSize() returns the "best" icon size.  "Best" is defined as an icon
00857 %  size that maintains the aspect ratio of the image.  If the window manager
00858 %  has preferred icon sizes, one of the preferred sizes is used.
00859 %
00860 %  The format of the XBestIconSize method is:
00861 %
00862 %      void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
00863 %
00864 %  A description of each parameter follows:
00865 %
00866 %    o display: Specifies a connection to an X server;  returned from
00867 %      XOpenDisplay.
00868 %
00869 %    o image: the image.
00870 %
00871 */
00872 MagickExport void XBestIconSize(Display *display,XWindowInfo *window,
00873   Image *image)
00874 {
00875   int
00876     i,
00877     number_sizes;
00878 
00879   MagickRealType
00880     scale_factor;
00881 
00882   unsigned int
00883     height,
00884     icon_height,
00885     icon_width,
00886     width;
00887 
00888   Window
00889     root_window;
00890 
00891   XIconSize
00892     *icon_size,
00893     *size_list;
00894 
00895   /*
00896     Determine if the window manager has specified preferred icon sizes.
00897   */
00898   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00899   assert(display != (Display *) NULL);
00900   assert(window != (XWindowInfo *) NULL);
00901   assert(image != (Image *) NULL);
00902   window->width=MaxIconSize;
00903   window->height=MaxIconSize;
00904   icon_size=(XIconSize *) NULL;
00905   number_sizes=0;
00906   root_window=XRootWindow(display,window->screen);
00907   if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
00908     if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
00909       icon_size=size_list;
00910   if (icon_size == (XIconSize *) NULL)
00911     {
00912       /*
00913         Window manager does not restrict icon size.
00914       */
00915       icon_size=XAllocIconSize();
00916       if (icon_size == (XIconSize *) NULL)
00917         {
00918           ThrowXWindowFatalException(ResourceLimitError,
00919             "MemoryAllocationFailed",image->filename);
00920           return;
00921         }
00922       icon_size->min_width=1;
00923       icon_size->max_width=MaxIconSize;
00924       icon_size->min_height=1;
00925       icon_size->max_height=MaxIconSize;
00926       icon_size->width_inc=1;
00927       icon_size->height_inc=1;
00928     }
00929   /*
00930     Determine aspect ratio of image.
00931   */
00932   width=(unsigned int) image->columns;
00933   height=(unsigned int) image->rows;
00934   i=0;
00935   if (window->crop_geometry)
00936     (void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
00937   /*
00938     Look for an icon size that maintains the aspect ratio of image.
00939   */
00940   scale_factor=(MagickRealType) icon_size->max_width/width;
00941   if (scale_factor > ((MagickRealType) icon_size->max_height/height))
00942     scale_factor=(MagickRealType) icon_size->max_height/height;
00943   icon_width=(unsigned int) icon_size->min_width;
00944   while ((int) icon_width < icon_size->max_width)
00945   {
00946     if (icon_width >= (unsigned int) (scale_factor*width+0.5))
00947       break;
00948     icon_width+=icon_size->width_inc;
00949   }
00950   icon_height=(unsigned int) icon_size->min_height;
00951   while ((int) icon_height < icon_size->max_height)
00952   {
00953     if (icon_height >= (unsigned int) (scale_factor*height+0.5))
00954       break;
00955     icon_height+=icon_size->height_inc;
00956   }
00957   (void) XFree((void *) icon_size);
00958   window->width=icon_width;
00959   window->height=icon_height;
00960 }
00961 
00962 /*
00963 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00964 %                                                                             %
00965 %                                                                             %
00966 %                                                                             %
00967 %   X B e s t P i x e l                                                       %
00968 %                                                                             %
00969 %                                                                             %
00970 %                                                                             %
00971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00972 %
00973 %  XBestPixel() returns a pixel from an array of pixels that is closest to the
00974 %  requested color.  If the color array is NULL, the colors are obtained from
00975 %  the X server.
00976 %
00977 %  The format of the XBestPixel method is:
00978 %
00979 %      void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
00980 %        unsigned int number_colors,XColor *color)
00981 %
00982 %  A description of each parameter follows:
00983 %
00984 %    o pixel: XBestPixel returns the pixel value closest to the requested
00985 %      color.
00986 %
00987 %    o display: Specifies a connection to an X server;  returned from
00988 %      XOpenDisplay.
00989 %
00990 %    o colormap: Specifies the ID of the X server colormap.
00991 %
00992 %    o colors: Specifies an array of XColor structures.
00993 %
00994 %    o number_colors: Specifies the number of XColor structures in the
00995 %      color definition array.
00996 %
00997 %    o color: Specifies the desired RGB value to find in the colors array.
00998 %
00999 */
01000 MagickExport void XBestPixel(Display *display,const Colormap colormap,
01001   XColor *colors,unsigned int number_colors,XColor *color)
01002 {
01003   MagickBooleanType
01004     query_server;
01005 
01006   MagickPixelPacket
01007     pixel;
01008 
01009   MagickRealType
01010     min_distance;
01011 
01012   register MagickRealType
01013     distance;
01014 
01015   register int
01016     i,
01017     j;
01018 
01019   Status
01020     status;
01021 
01022   /*
01023     Find closest representation for the requested RGB color.
01024   */
01025   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01026   assert(display != (Display *) NULL);
01027   assert(color != (XColor *) NULL);
01028   status=XAllocColor(display,colormap,color);
01029   if (status != False)
01030     return;
01031   query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
01032   if (query_server != MagickFalse)
01033     {
01034       /*
01035         Read X server colormap.
01036       */
01037       colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
01038       if (colors == (XColor *) NULL)
01039         {
01040           ThrowXWindowFatalException(ResourceLimitError,
01041             "MemoryAllocationFailed","...");
01042           return;
01043         }
01044       for (i=0; i < (int) number_colors; i++)
01045         colors[i].pixel=(unsigned long) i;
01046       if (number_colors > 256)
01047         number_colors=256;
01048       (void) XQueryColors(display,colormap,colors,(int) number_colors);
01049     }
01050   min_distance=3.0*((MagickRealType) QuantumRange+1.0)*((MagickRealType)
01051     QuantumRange+1.0);
01052   j=0;
01053   for (i=0; i < (int) number_colors; i++)
01054   {
01055     pixel.red=colors[i].red-(MagickRealType) color->red;
01056     distance=pixel.red*pixel.red;
01057     if (distance > min_distance)
01058       continue;
01059     pixel.green=colors[i].green-(MagickRealType) color->green;
01060     distance+=pixel.green*pixel.green;
01061     if (distance > min_distance)
01062       continue;
01063     pixel.blue=colors[i].blue-(MagickRealType) color->blue;
01064     distance+=pixel.blue*pixel.blue;
01065     if (distance > min_distance)
01066       continue;
01067     min_distance=distance;
01068     color->pixel=colors[i].pixel;
01069     j=i;
01070   }
01071   (void) XAllocColor(display,colormap,&colors[j]);
01072   if (query_server != MagickFalse)
01073     colors=(XColor *) RelinquishMagickMemory(colors);
01074 }
01075 
01076 /*
01077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01078 %                                                                             %
01079 %                                                                             %
01080 %                                                                             %
01081 %   X B e s t V i s u a l I n f o                                             %
01082 %                                                                             %
01083 %                                                                             %
01084 %                                                                             %
01085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01086 %
01087 %  XBestVisualInfo() returns visual information for a visual that is the "best"
01088 %  the server supports.  "Best" is defined as:
01089 %
01090 %    1. Restrict the visual list to those supported by the default screen.
01091 %
01092 %    2. If a visual type is specified, restrict the visual list to those of
01093 %       that type.
01094 %
01095 %    3. If a map type is specified, choose the visual that matches the id
01096 %       specified by the Standard Colormap.
01097 %
01098 %    4  From the list of visuals, choose one that can display the most
01099 %       simultaneous colors.  If more than one visual can display the same
01100 %       number of simultaneous colors, one is chosen based on a rank.
01101 %
01102 %  The format of the XBestVisualInfo method is:
01103 %
01104 %      XVisualInfo *XBestVisualInfo(Display *display,
01105 %        XStandardColormap *map_info,XResourceInfo *resource_info)
01106 %
01107 %  A description of each parameter follows:
01108 %
01109 %    o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
01110 %      structure.
01111 %
01112 %    o display: Specifies a connection to an X server;  returned from
01113 %      XOpenDisplay.
01114 %
01115 %    o map_info: If map_type is specified, this structure is initialized
01116 %      with info from the Standard Colormap.
01117 %
01118 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01119 %
01120 */
01121 
01122 static inline int MagickMax(const int x,const int y)
01123 {
01124   if (x > y)
01125     return(x);
01126   return(y);
01127 }
01128 
01129 static inline unsigned long MagickMin(const unsigned int x,
01130   const unsigned int y)
01131 {
01132   if (x < y)
01133     return(x);
01134   return(y);
01135 }
01136 
01137 MagickExport XVisualInfo *XBestVisualInfo(Display *display,
01138   XStandardColormap *map_info,XResourceInfo *resource_info)
01139 {
01140 #define MaxStandardColormaps  7
01141 #define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
01142   (visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
01143    visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
01144    (unsigned int) visual_info->colormap_size),1U << visual_info->depth)
01145 
01146   char
01147     *map_type,
01148     *visual_type;
01149 
01150   long
01151     visual_mask;
01152 
01153   register int
01154     i;
01155 
01156   static int
01157     number_visuals;
01158 
01159   static XVisualInfo
01160     visual_template;
01161 
01162   XVisualInfo
01163     *visual_info,
01164     *visual_list;
01165 
01166   /*
01167     Restrict visual search by screen number.
01168   */
01169   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01170   assert(display != (Display *) NULL);
01171   assert(map_info != (XStandardColormap *) NULL);
01172   assert(resource_info != (XResourceInfo *) NULL);
01173   map_type=resource_info->map_type;
01174   visual_type=resource_info->visual_type;
01175   visual_mask=VisualScreenMask;
01176   visual_template.screen=XDefaultScreen(display);
01177   visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
01178   if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
01179     if (resource_info->colors <= (1UL << (unsigned long) visual_template.depth))
01180       visual_mask|=VisualDepthMask;
01181   if (visual_type != (char *) NULL)
01182     {
01183       /*
01184         Restrict visual search by class or visual id.
01185       */
01186       if (LocaleCompare("staticgray",visual_type) == 0)
01187         {
01188           visual_mask|=VisualClassMask;
01189           visual_template.klass=StaticGray;
01190         }
01191       else
01192         if (LocaleCompare("grayscale",visual_type) == 0)
01193           {
01194             visual_mask|=VisualClassMask;
01195             visual_template.klass=GrayScale;
01196           }
01197         else
01198           if (LocaleCompare("staticcolor",visual_type) == 0)
01199             {
01200               visual_mask|=VisualClassMask;
01201               visual_template.klass=StaticColor;
01202             }
01203           else
01204             if (LocaleCompare("pseudocolor",visual_type) == 0)
01205               {
01206                 visual_mask|=VisualClassMask;
01207                 visual_template.klass=PseudoColor;
01208               }
01209             else
01210               if (LocaleCompare("truecolor",visual_type) == 0)
01211                 {
01212                   visual_mask|=VisualClassMask;
01213                   visual_template.klass=TrueColor;
01214                 }
01215               else
01216                 if (LocaleCompare("directcolor",visual_type) == 0)
01217                   {
01218                     visual_mask|=VisualClassMask;
01219                     visual_template.klass=DirectColor;
01220                   }
01221                 else
01222                   if (LocaleCompare("default",visual_type) == 0)
01223                     {
01224                       visual_mask|=VisualIDMask;
01225                       visual_template.visualid=XVisualIDFromVisual(
01226                         XDefaultVisual(display,XDefaultScreen(display)));
01227                     }
01228                   else
01229                     if (isdigit((int) ((unsigned char) *visual_type)) != 0)
01230                       {
01231                         visual_mask|=VisualIDMask;
01232                         visual_template.visualid=
01233                           strtol(visual_type,(char **) NULL,0);
01234                       }
01235                     else
01236                       ThrowXWindowFatalException(XServerError,
01237                         "UnrecognizedVisualSpecifier",visual_type);
01238     }
01239   /*
01240     Get all visuals that meet our criteria so far.
01241   */
01242   number_visuals=0;
01243   visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
01244     &number_visuals);
01245   visual_mask=VisualScreenMask | VisualIDMask;
01246   if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
01247     {
01248       /*
01249         Failed to get visual;  try using the default visual.
01250       */
01251       ThrowXWindowFatalException(XServerWarning,"UnableToGetVisual",
01252         visual_type);
01253       visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
01254         XDefaultScreen(display)));
01255       visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
01256         &number_visuals);
01257       if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
01258         return((XVisualInfo *) NULL);
01259       ThrowXWindowFatalException(XServerWarning,"UsingDefaultVisual",
01260         XVisualClassName(visual_list->klass));
01261     }
01262   resource_info->color_recovery=MagickFalse;
01263   if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
01264     {
01265       Atom
01266         map_property;
01267 
01268       char
01269         map_name[MaxTextExtent];
01270 
01271       int
01272         j,
01273         number_maps;
01274 
01275       Status
01276         status;
01277 
01278       Window
01279         root_window;
01280 
01281       XStandardColormap
01282         *map_list;
01283 
01284       /*
01285         Choose a visual associated with a standard colormap.
01286       */
01287       root_window=XRootWindow(display,XDefaultScreen(display));
01288       status=False;
01289       if (LocaleCompare(map_type,"list") != 0)
01290         {
01291           /*
01292             User specified Standard Colormap.
01293           */
01294           (void) FormatMagickString((char *) map_name,MaxTextExtent,
01295             "RGB_%s_MAP",map_type);
01296           LocaleUpper(map_name);
01297           map_property=XInternAtom(display,(char *) map_name,MagickTrue);
01298           if (map_property != (Atom) NULL)
01299             status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
01300               map_property);
01301         }
01302       else
01303         {
01304           static const char
01305             *colormap[MaxStandardColormaps]=
01306             {
01307               "_HP_RGB_SMOOTH_MAP_LIST",
01308               "RGB_BEST_MAP",
01309               "RGB_DEFAULT_MAP",
01310               "RGB_GRAY_MAP",
01311               "RGB_RED_MAP",
01312               "RGB_GREEN_MAP",
01313               "RGB_BLUE_MAP",
01314             };
01315 
01316           /*
01317             Choose a standard colormap from a list.
01318           */
01319           for (i=0; i < MaxStandardColormaps; i++)
01320           {
01321             map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
01322             if (map_property == (Atom) NULL)
01323               continue;
01324             status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
01325               map_property);
01326             if (status != False)
01327               break;
01328           }
01329           resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
01330         }
01331       if (status == False)
01332         {
01333           ThrowXWindowFatalException(XServerError,"UnableToGetStandardColormap",
01334             map_type);
01335           return((XVisualInfo *) NULL);
01336         }
01337       /*
01338         Search all Standard Colormaps and visuals for ids that match.
01339       */
01340       *map_info=map_list[0];
01341 #if !defined(PRE_R4_ICCCM)
01342       visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
01343       for (i=0; i < number_maps; i++)
01344         for (j=0; j < number_visuals; j++)
01345           if (map_list[i].visualid ==
01346               XVisualIDFromVisual(visual_list[j].visual))
01347             {
01348               *map_info=map_list[i];
01349               visual_template.visualid=XVisualIDFromVisual(
01350                 visual_list[j].visual);
01351               break;
01352             }
01353       if (map_info->visualid != visual_template.visualid)
01354         {
01355           ThrowXWindowFatalException(XServerError,
01356             "UnableToMatchVisualToStandardColormap",map_type);
01357           return((XVisualInfo *) NULL);
01358         }
01359 #endif
01360       if (map_info->colormap == (Colormap) NULL)
01361         {
01362           ThrowXWindowFatalException(XServerError,
01363             "StandardColormapIsNotInitialized",map_type);
01364           return((XVisualInfo *) NULL);
01365         }
01366       (void) XFree((void *) map_list);
01367     }
01368   else
01369     {
01370       static const unsigned int
01371         rank[]=
01372           {
01373             StaticGray,
01374             GrayScale,
01375             StaticColor,
01376             DirectColor,
01377             TrueColor,
01378             PseudoColor
01379           };
01380 
01381       XVisualInfo
01382         *p;
01383 
01384       /*
01385         Pick one visual that displays the most simultaneous colors.
01386       */
01387       visual_info=visual_list;
01388       p=visual_list;
01389       for (i=1; i < number_visuals; i++)
01390       {
01391         p++;
01392         if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
01393           visual_info=p;
01394         else
01395           if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
01396             if (rank[p->klass] > rank[visual_info->klass])
01397               visual_info=p;
01398       }
01399       visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
01400     }
01401   (void) XFree((void *) visual_list);
01402   /*
01403     Retrieve only one visual by its screen & id number.
01404   */
01405   visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
01406     &number_visuals);
01407   if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
01408     return((XVisualInfo *) NULL);
01409   return(visual_info);
01410 }
01411 
01412 /*
01413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01414 %                                                                             %
01415 %                                                                             %
01416 %                                                                             %
01417 %   X C h e c k D e f i n e C u r s o r                                       %
01418 %                                                                             %
01419 %                                                                             %
01420 %                                                                             %
01421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01422 %
01423 %  XCheckDefineCursor() prevents cursor changes on the root window.
01424 %
01425 %  The format of the XXCheckDefineCursor method is:
01426 %
01427 %      XCheckDefineCursor(display,window,cursor)
01428 %
01429 %  A description of each parameter follows:
01430 %
01431 %    o display: Specifies a connection to an X server;  returned from
01432 %      XOpenDisplay.
01433 %
01434 %    o window: the window.
01435 %
01436 %    o cursor: the cursor.
01437 %
01438 */
01439 MagickExport int XCheckDefineCursor(Display *display,Window window,
01440   Cursor cursor)
01441 {
01442   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01443   assert(display != (Display *) NULL);
01444   if (window == XRootWindow(display,XDefaultScreen(display)))
01445     return(0);
01446   return(XDefineCursor(display,window,cursor));
01447 }
01448 
01449 /*
01450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01451 %                                                                             %
01452 %                                                                             %
01453 %                                                                             %
01454 %   X C h e c k R e f r e s h W i n d o w s                                   %
01455 %                                                                             %
01456 %                                                                             %
01457 %                                                                             %
01458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01459 %
01460 %  XCheckRefreshWindows() checks the X server for exposure events for a
01461 %  particular window and updates the areassociated with the exposure event.
01462 %
01463 %  The format of the XCheckRefreshWindows method is:
01464 %
01465 %      void XCheckRefreshWindows(Display *display,XWindows *windows)
01466 %
01467 %  A description of each parameter follows:
01468 %
01469 %    o display: Specifies a connection to an X server;  returned from
01470 %      XOpenDisplay.
01471 %
01472 %    o windows: Specifies a pointer to a XWindows structure.
01473 %
01474 */
01475 MagickExport void XCheckRefreshWindows(Display *display,XWindows *windows)
01476 {
01477   Window
01478     id;
01479 
01480   XEvent
01481     event;
01482 
01483   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01484   assert(display != (Display *) NULL);
01485   assert(windows != (XWindows *) NULL);
01486   XDelay(display,SuspendTime);
01487   id=windows->command.id;
01488   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
01489     (void) XCommandWidget(display,windows,(char const **) NULL,&event);
01490   id=windows->image.id;
01491   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
01492     XRefreshWindow(display,&windows->image,&event);
01493   XDelay(display,SuspendTime << 1);
01494   id=windows->command.id;
01495   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
01496     (void) XCommandWidget(display,windows,(char const **) NULL,&event);
01497   id=windows->image.id;
01498   while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
01499     XRefreshWindow(display,&windows->image,&event);
01500 }
01501 
01502 /*
01503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01504 %                                                                             %
01505 %                                                                             %
01506 %                                                                             %
01507 %   X C l i e n t M e s s a g e                                               %
01508 %                                                                             %
01509 %                                                                             %
01510 %                                                                             %
01511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01512 %
01513 %  XClientMessage() sends a reason to a window with XSendEvent.  The reason is
01514 %  initialized with a particular protocol type and atom.
01515 %
01516 %  The format of the XClientMessage function is:
01517 %
01518 %      XClientMessage(display,window,protocol,reason,timestamp)
01519 %
01520 %  A description of each parameter follows:
01521 %
01522 %    o display: Specifies a pointer to the Display structure;  returned from
01523 %      XOpenDisplay.
01524 %
01525 %    o window: Specifies a pointer to a Window structure.
01526 %
01527 %    o protocol: Specifies an atom value.
01528 %
01529 %    o reason: Specifies an atom value which is the reason to send.
01530 %
01531 %    o timestamp: Specifies a value of type Time.
01532 %
01533 */
01534 MagickExport void XClientMessage(Display *display,const Window window,
01535   const Atom protocol,const Atom reason,const Time timestamp)
01536 {
01537   XClientMessageEvent
01538     client_event;
01539 
01540   assert(display != (Display *) NULL);
01541   client_event.type=ClientMessage;
01542   client_event.window=window;
01543   client_event.message_type=protocol;
01544   client_event.format=32;
01545   client_event.data.l[0]=(long) reason;
01546   client_event.data.l[1]=(long) timestamp;
01547   (void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *) &client_event);
01548 }
01549 
01550 /*
01551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01552 %                                                                             %
01553 %                                                                             %
01554 %                                                                             %
01555 +   X C l i e n t W i n d o w                                                 %
01556 %                                                                             %
01557 %                                                                             %
01558 %                                                                             %
01559 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01560 %
01561 %  XClientWindow() finds a window, at or below the specified window, which has
01562 %  a WM_STATE property.  If such a window is found, it is returned, otherwise
01563 %  the argument window is returned.
01564 %
01565 %  The format of the XClientWindow function is:
01566 %
01567 %      client_window=XClientWindow(display,target_window)
01568 %
01569 %  A description of each parameter follows:
01570 %
01571 %    o client_window: XClientWindow returns a window, at or below the specified
01572 %      window, which has a WM_STATE property otherwise the argument
01573 %      target_window is returned.
01574 %
01575 %    o display: Specifies a pointer to the Display structure;  returned from
01576 %      XOpenDisplay.
01577 %
01578 %    o target_window: Specifies the window to find a WM_STATE property.
01579 %
01580 %
01581 */
01582 static Window XClientWindow(Display *display,Window target_window)
01583 {
01584   Atom
01585     state,
01586     type;
01587 
01588   int
01589     format;
01590 
01591   Status
01592     status;
01593 
01594   unsigned char
01595     *data;
01596 
01597   unsigned long
01598     after,
01599     number_items;
01600 
01601   Window
01602     client_window;
01603 
01604   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01605   assert(display != (Display *) NULL);
01606   state=XInternAtom(display,"WM_STATE",MagickTrue);
01607   if (state == (Atom) NULL)
01608     return(target_window);
01609   type=(Atom) NULL;
01610   status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
01611     (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
01612   if ((status == Success) && (type != (Atom) NULL))
01613     return(target_window);
01614   client_window=XWindowByProperty(display,target_window,state);
01615   if (client_window == (Window) NULL)
01616     return(target_window);
01617   return(client_window);
01618 }
01619 
01620 /*
01621 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01622 %                                                                             %
01623 %                                                                             %
01624 %                                                                             %
01625 %   X C o n f i g u r e I m a g e C o l o r m a p                             %
01626 %                                                                             %
01627 %                                                                             %
01628 %                                                                             %
01629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01630 %
01631 %  XConfigureImageColormap() creates a new X colormap.
01632 %
01633 %  The format of the XConfigureImageColormap method is:
01634 %
01635 %      void XConfigureImageColormap(Display *display,
01636 %        XResourceInfo *resource_info,XWindows *windows,Image *image)
01637 %
01638 %  A description of each parameter follows:
01639 %
01640 %    o display: Specifies a connection to an X server; returned from
01641 %      XOpenDisplay.
01642 %
01643 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01644 %
01645 %    o windows: Specifies a pointer to a XWindows structure.
01646 %
01647 %    o image: the image.
01648 %
01649 */
01650 MagickExport void XConfigureImageColormap(Display *display,
01651   XResourceInfo *resource_info,XWindows *windows,Image *image)
01652 {
01653   Colormap
01654     colormap;
01655 
01656   /*
01657     Make standard colormap.
01658   */
01659   XSetCursorState(display,windows,MagickTrue);
01660   XCheckRefreshWindows(display,windows);
01661   XMakeStandardColormap(display,windows->visual_info,resource_info,image,
01662     windows->map_info,windows->pixel_info);
01663   colormap=windows->map_info->colormap;
01664   (void) XSetWindowColormap(display,windows->image.id,colormap);
01665   (void) XSetWindowColormap(display,windows->command.id,colormap);
01666   (void) XSetWindowColormap(display,windows->widget.id,colormap);
01667   if (windows->magnify.mapped != MagickFalse)
01668     (void) XSetWindowColormap(display,windows->magnify.id,colormap);
01669   if (windows->pan.mapped != MagickFalse)
01670     (void) XSetWindowColormap(display,windows->pan.id,colormap);
01671   XSetCursorState(display,windows,MagickFalse);
01672   XClientMessage(display,windows->image.id,windows->im_protocols,
01673     windows->im_update_colormap,CurrentTime);
01674 }
01675 
01676 /*
01677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01678 %                                                                             %
01679 %                                                                             %
01680 %                                                                             %
01681 %   X C o n s t r a i n W i n d o w P o s i t i o n                           %
01682 %                                                                             %
01683 %                                                                             %
01684 %                                                                             %
01685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01686 %
01687 %  XConstrainWindowPosition() assures a window is positioned within the X
01688 %  server boundaries.
01689 %
01690 %  The format of the XConstrainWindowPosition method is:
01691 %
01692 %      void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
01693 %
01694 %  A description of each parameter follows:
01695 %
01696 %    o display: Specifies a pointer to the Display structure;  returned from
01697 %      XOpenDisplay.
01698 %
01699 %    o window_info: Specifies a pointer to a XWindowInfo structure.
01700 %
01701 */
01702 MagickExport void XConstrainWindowPosition(Display *display,
01703   XWindowInfo *window_info)
01704 {
01705   int
01706     limit;
01707 
01708   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01709   assert(display != (Display *) NULL);
01710   assert(window_info != (XWindowInfo *) NULL);
01711   limit=XDisplayWidth(display,window_info->screen)-window_info->width;
01712   if (window_info->x < 0)
01713     window_info->x=0;
01714   else
01715     if (window_info->x > (int) limit)
01716       window_info->x=(int) limit;
01717   limit=XDisplayHeight(display,window_info->screen)-window_info->height;
01718   if (window_info->y < 0)
01719     window_info->y=0;
01720   else
01721     if (window_info->y > limit)
01722       window_info->y=limit;
01723 }
01724 
01725 /*
01726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01727 %                                                                             %
01728 %                                                                             %
01729 %                                                                             %
01730 %   X D e l a y                                                               %
01731 %                                                                             %
01732 %                                                                             %
01733 %                                                                             %
01734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01735 %
01736 %  XDelay() suspends program execution for the number of milliseconds
01737 %  specified.
01738 %
01739 %  The format of the Delay method is:
01740 %
01741 %      void XDelay(Display *display,const unsigned long milliseconds)
01742 %
01743 %  A description of each parameter follows:
01744 %
01745 %    o display: Specifies a pointer to the Display structure;  returned from
01746 %      XOpenDisplay.
01747 %
01748 %    o milliseconds: Specifies the number of milliseconds to delay before
01749 %      returning.
01750 %
01751 */
01752 MagickExport void XDelay(Display *display,const unsigned long milliseconds)
01753 {
01754   assert(display != (Display *) NULL);
01755   (void) XFlush(display);
01756   if (milliseconds == 0)
01757     return;
01758 #if defined(__WINDOWS__)
01759   Sleep(milliseconds);
01760 #elif defined(vms)
01761   {
01762     float
01763       timer;
01764 
01765     timer=milliseconds/1000.0;
01766     lib$wait(&timer);
01767   }
01768 #elif defined(MAGICKCORE_HAVE_USLEEP)
01769   usleep(1000*milliseconds);
01770 #elif defined(MAGICKCORE_HAVE_SELECT)
01771   {
01772     struct timeval
01773       timer;
01774 
01775     timer.tv_sec=(long) milliseconds/1000;
01776     timer.tv_usec=(long) (milliseconds % 1000)*1000;
01777     (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
01778   }
01779 #elif defined(MAGICKCORE_HAVE_POLL)
01780   (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
01781 #elif defined(__BEOS__)
01782   snooze(1000*milliseconds);
01783 #else
01784 # error "Time delay method not defined."
01785 #endif
01786 }
01787 
01788 /*
01789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01790 %                                                                             %
01791 %                                                                             %
01792 %                                                                             %
01793 %   X D e s t r o y R e s o u r c e I n f o                                   %
01794 %                                                                             %
01795 %                                                                             %
01796 %                                                                             %
01797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01798 %
01799 %  XDestroyResourceInfo() frees memory associated with the XResourceInfo
01800 %  structure.
01801 %
01802 %  The format of the XDestroyResourceInfo method is:
01803 %
01804 %      void XDestroyResourceInfo(XResourceInfo *resource_info)
01805 %
01806 %  A description of each parameter follows:
01807 %
01808 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01809 %
01810 */
01811 MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
01812 {
01813   if (resource_info->image_geometry != (char *) NULL)
01814     resource_info->image_geometry=(char *)
01815       RelinquishMagickMemory(resource_info->image_geometry);
01816   if (resource_info->quantize_info != (QuantizeInfo *) NULL)
01817     resource_info->quantize_info=DestroyQuantizeInfo(
01818       resource_info->quantize_info);
01819   if (resource_info->client_name != (char *) NULL)
01820     resource_info->client_name=(char *)
01821       RelinquishMagickMemory(resource_info->client_name);
01822   if (resource_info->name != (char *) NULL)
01823     resource_info->name=DestroyString(resource_info->name);
01824   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
01825 }
01826 
01827 /*
01828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01829 %                                                                             %
01830 %                                                                             %
01831 %                                                                             %
01832 %   X D e s t r o y W i n d o w C o l o r s                                   %
01833 %                                                                             %
01834 %                                                                             %
01835 %                                                                             %
01836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01837 %
01838 %  XDestroyWindowColors() frees X11 color resources previously saved on a
01839 %  window by XRetainWindowColors or programs like xsetroot.
01840 %
01841 %  The format of the XDestroyWindowColors method is:
01842 %
01843 %      void XDestroyWindowColors(Display *display,Window window)
01844 %
01845 %  A description of each parameter follows:
01846 %
01847 %    o display: Specifies a connection to an X server; returned from
01848 %      XOpenDisplay.
01849 %
01850 %    o window: Specifies a pointer to a Window structure.
01851 %
01852 */
01853 MagickExport void XDestroyWindowColors(Display *display,Window window)
01854 {
01855   Atom
01856     property,
01857     type;
01858 
01859   int
01860     format;
01861 
01862   Status
01863     status;
01864 
01865   unsigned char
01866     *data;
01867 
01868   unsigned long
01869     after,
01870     length;
01871 
01872   /*
01873     If there are previous resources on the root window, destroy them.
01874   */
01875   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01876   assert(display != (Display *) NULL);
01877   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
01878   if (property == (Atom) NULL)
01879     {
01880       ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
01881         "_XSETROOT_ID");
01882       return;
01883     }
01884   status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
01885     (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
01886   if (status != Success)
01887     return;
01888   if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
01889     {
01890       (void) XKillClient(display,(XID) (*((Pixmap *) data)));
01891       (void) XDeleteProperty(display,window,property);
01892     }
01893   if (type != None)
01894     (void) XFree((void *) data);
01895 }
01896 
01897 /*
01898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01899 %                                                                             %
01900 %                                                                             %
01901 %                                                                             %
01902 %   X D i s p l a y I m a g e I n f o                                         %
01903 %                                                                             %
01904 %                                                                             %
01905 %                                                                             %
01906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01907 %
01908 %  XDisplayImageInfo() displays information about an X image.
01909 %
01910 %  The format of the XDisplayImageInfo method is:
01911 %
01912 %      void XDisplayImageInfo(Display *display,
01913 %        const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
01914 %        Image *image)
01915 %
01916 %  A description of each parameter follows:
01917 %
01918 %    o display: Specifies a connection to an X server;  returned from
01919 %      XOpenDisplay.
01920 %
01921 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01922 %
01923 %    o windows: Specifies a pointer to a XWindows structure.
01924 %
01925 %    o undo_image: the undo image.
01926 %
01927 %    o image: the image.
01928 %
01929 */
01930 MagickExport void XDisplayImageInfo(Display *display,
01931   const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
01932   Image *image)
01933 {
01934   char
01935     filename[MaxTextExtent],
01936     *text,
01937     **textlist;
01938 
01939   FILE
01940     *file;
01941 
01942   int
01943     unique_file;
01944 
01945   long
01946     bytes;
01947 
01948   register long
01949     i;
01950 
01951   unsigned int
01952     levels;
01953 
01954   unsigned long
01955     number_pixels;
01956 
01957   /*
01958     Write info about the X server to a file.
01959   */
01960   assert(display != (Display *) NULL);
01961   assert(resource_info != (XResourceInfo *) NULL);
01962   assert(windows != (XWindows *) NULL);
01963   assert(image != (Image *) NULL);
01964   if (image->debug)
01965     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01966   file=(FILE *) NULL;
01967   unique_file=AcquireUniqueFileResource(filename);
01968   if (unique_file != -1)
01969     file=fdopen(unique_file,"w");
01970   if ((unique_file == -1) || (file == (FILE *) NULL))
01971     {
01972       XNoticeWidget(display,windows,"Unable to display image info",filename);
01973       return;
01974     }
01975   if (resource_info->gamma_correct != MagickFalse)
01976     if (resource_info->display_gamma != (char *) NULL)
01977       (void) fprintf(file,"Display\n  gamma: %s\n\n",
01978         resource_info->display_gamma);
01979   /*
01980     Write info about the X image to a file.
01981   */
01982   (void) fprintf(file,"X\n  visual: %s\n",
01983     XVisualClassName((int) windows->image.storage_class));
01984   (void) fprintf(file,"  depth: %d\n",windows->image.ximage->depth);
01985   if (windows->visual_info->colormap_size != 0)
01986     (void) fprintf(file,"  colormap size: %d\n",
01987       windows->visual_info->colormap_size);
01988   if (resource_info->colormap== SharedColormap)
01989     (void) fprintf(file,"  colormap type: Shared\n");
01990   else
01991     (void) fprintf(file,"  colormap type: Private\n");
01992   (void) fprintf(file,"  geometry: %dx%d\n",windows->image.ximage->width,
01993     windows->image.ximage->height);
01994   if (windows->image.crop_geometry != (char *) NULL)
01995     (void) fprintf(file,"  crop geometry: %s\n",windows->image.crop_geometry);
01996   if (windows->image.pixmap == (Pixmap) NULL)
01997     (void) fprintf(file,"  type: X Image\n");
01998   else
01999     (void) fprintf(file,"  type: Pixmap\n");
02000   if (windows->image.shape != MagickFalse)
02001     (void) fprintf(file,"  non-rectangular shape: True\n");
02002   else
02003     (void) fprintf(file,"  non-rectangular shape: False\n");
02004   if (windows->image.shared_memory != MagickFalse)
02005     (void) fprintf(file,"  shared memory: True\n");
02006   else
02007     (void) fprintf(file,"  shared memory: False\n");
02008   (void) fprintf(file,"\n");
02009   if (resource_info->font != (char *) NULL)
02010     (void) fprintf(file,"Font: %s\n\n",resource_info->font);
02011   if (resource_info->text_font != (char *) NULL)
02012     (void) fprintf(file,"Text font: %s\n\n",resource_info->text_font);
02013   /*
02014     Write info about the undo cache to a file.
02015   */
02016   bytes=0;
02017   for (levels=0; undo_image != (Image *) NULL; levels++)
02018   {
02019     number_pixels=undo_image->list->columns*undo_image->list->rows;
02020     bytes+=number_pixels*sizeof(PixelPacket);
02021     undo_image=GetPreviousImageInList(undo_image);
02022   }
02023   (void) fprintf(file,"Undo Edit Cache\n  levels: %u\n",levels);
02024   (void) fprintf(file,"  bytes: %lumb\n",(unsigned long)
02025     (bytes+(1 << 19)) >> 20);
02026   (void) fprintf(file,"  limit: %lumb\n\n",resource_info->undo_cache);
02027   /*
02028     Write info about the image to a file.
02029   */
02030   (void) IdentifyImage(image,file,MagickTrue);
02031   (void) fclose(file);
02032   text=FileToString(filename,~0,&image->exception);
02033   (void) RelinquishUniqueFileResource(filename);
02034   if (text == (char *) NULL)
02035     {
02036       XNoticeWidget(display,windows,"MemoryAllocationFailed",
02037         "UnableToDisplayImageInfo");
02038       return;
02039     }
02040   textlist=StringToList(text);
02041   if (textlist != (char **) NULL)
02042     {
02043       char
02044         title[MaxTextExtent];
02045 
02046       /*
02047         Display information about the image in the Text View widget.
02048       */
02049       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
02050       (void) FormatMagickString(title,MaxTextExtent,"Image Info: %s",
02051         image->filename);
02052       XTextViewWidget(display,resource_info,windows,MagickTrue,title,
02053         (char const **) textlist);
02054       for (i=0; textlist[i] != (char *) NULL; i++)
02055         textlist[i]=DestroyString(textlist[i]);
02056       textlist=(char **) RelinquishMagickMemory(textlist);
02057     }
02058   text=DestroyString(text);
02059 }
02060 
02061 /*
02062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02063 %                                                                             %
02064 %                                                                             %
02065 %                                                                             %
02066 +     X D i t h e r I m a g e                                                 %
02067 %                                                                             %
02068 %                                                                             %
02069 %                                                                             %
02070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02071 %
02072 %  XDitherImage() dithers the reference image as required by the HP Color
02073 %  Recovery algorithm.  The color values are quantized to 3 bits of red and
02074 %  green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
02075 %  standard colormap.
02076 %
02077 %  The format of the XDitherImage method is:
02078 %
02079 %      void XDitherImage(Image *image,XImage *ximage)
02080 %
02081 %  A description of each parameter follows:
02082 %
02083 %    o image: the image.
02084 %
02085 %    o ximage: Specifies a pointer to a XImage structure;  returned from
02086 %      XCreateImage.
02087 %
02088 %
02089 */
02090 static void XDitherImage(Image *image,XImage *ximage)
02091 {
02092   static const short int
02093     dither_red[2][16]=
02094     {
02095       {-16,  4, -1, 11,-14,  6, -3,  9,-15,  5, -2, 10,-13,  7, -4,  8},
02096       { 15, -5,  0,-12, 13, -7,  2,-10, 14, -6,  1,-11, 12, -8,  3, -9}
02097     },
02098     dither_green[2][16]=
02099     {
02100       { 11,-15,  7, -3,  8,-14,  4, -2, 10,-16,  6, -4,  9,-13,  5, -1},
02101       {-12, 14, -8,  2, -9, 13, -5,  1,-11, 15, -7,  3,-10, 12, -6,  0}
02102     },
02103     dither_blue[2][16]=
02104     {
02105       { -3,  9,-13,  7, -1, 11,-15,  5, -4,  8,-14,  6, -2, 10,-16,  4},
02106       {  2,-10, 12, -8,  0,-12, 14, -6,  3, -9, 13, -7,  1,-11, 15, -5}
02107     };
02108 
02109   PixelPacket
02110     color;
02111 
02112   int
02113     y;
02114 
02115   long
02116     value;
02117 
02118   register char
02119     *q;
02120 
02121   register const PixelPacket
02122     *p;
02123 
02124   register int
02125     i,
02126     j,
02127     x;
02128 
02129   unsigned int
02130     scanline_pad;
02131 
02132   register unsigned long
02133     pixel;
02134 
02135   unsigned char
02136     *blue_map[2][16],
02137     *green_map[2][16],
02138     *red_map[2][16];
02139 
02140   /*
02141     Allocate and initialize dither maps.
02142   */
02143   for (i=0; i < 2; i++)
02144     for (j=0; j < 16; j++)
02145     {
02146       red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02147         sizeof(*red_map));
02148       green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02149         sizeof(*green_map));
02150       blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02151         sizeof(*blue_map));
02152       if ((red_map[i][j] == (unsigned char *) NULL) ||
02153           (green_map[i][j] == (unsigned char *) NULL) ||
02154           (blue_map[i][j] == (unsigned char *) NULL))
02155         {
02156           ThrowXWindowFatalException(ResourceLimitError,
02157             "MemoryAllocationFailed",image->filename);
02158           return;
02159         }
02160     }
02161   /*
02162     Initialize dither tables.
02163   */
02164   for (i=0; i < 2; i++)
02165     for (j=0; j < 16; j++)
02166       for (x=0; x < 256; x++)
02167       {
02168         value=x-16;
02169         if (x < 48)
02170           value=x/2+8;
02171         value+=dither_red[i][j];
02172         red_map[i][j][x]=(unsigned char)
02173           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02174         value=x-16;
02175         if (x < 48)
02176           value=x/2+8;
02177         value+=dither_green[i][j];
02178         green_map[i][j][x]=(unsigned char)
02179           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02180         value=x-32;
02181         if (x < 112)
02182           value=x/2+24;
02183         value+=((unsigned long) dither_blue[i][j] << 1);
02184         blue_map[i][j][x]=(unsigned char)
02185           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02186       }
02187   /*
02188     Dither image.
02189   */
02190   scanline_pad=(unsigned int) (ximage->bytes_per_line-
02191     ((unsigned long) (ximage->width*ximage->bits_per_pixel) >> 3));
02192   i=0;
02193   j=0;
02194   q=ximage->data;
02195   for (y=0; y < (int) image->rows; y++)
02196   {
02197     p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
02198     if (p == (const PixelPacket *) NULL)
02199       break;
02200     for (x=0; x < (int) image->columns; x++)
02201     {
02202       color.red=RoundToQuantum((MagickRealType) (red_map[i][j][(int)
02203         ScaleQuantumToChar(p->red)] << 8));
02204       color.green=RoundToQuantum((MagickRealType) (green_map[i][j][(int)
02205         ScaleQuantumToChar(p->green)] << 8));
02206       color.blue=RoundToQuantum((MagickRealType) (blue_map[i][j][(int)
02207         ScaleQuantumToChar(p->blue)] << 8));
02208       pixel=(unsigned long) (((unsigned long) color.red & 0xe0) |
02209         (((unsigned long) color.green & 0xe0) >> 3) |
02210         (((unsigned long) color.blue & 0xc0) >> 6));
02211       *q++=(char) pixel;
02212       p++;
02213       j++;
02214       if (j == 16)
02215         j=0;
02216     }
02217     q+=scanline_pad;
02218     i++;
02219     if (i == 2)
02220       i=0;
02221   }
02222   /*
02223     Free allocated memory.
02224   */
02225   for (i=0; i < 2; i++)
02226     for (j=0; j < 16; j++)
02227     {
02228       green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
02229       blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
02230       red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
02231     }
02232 }
02233 
02234 /*
02235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02236 %                                                                             %
02237 %                                                                             %
02238 %                                                                             %
02239 %   X D r a w I m a g e                                                       %
02240 %                                                                             %
02241 %                                                                             %
02242 %                                                                             %
02243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02244 %
02245 %  XDrawImage() draws a line on the image.
02246 %
02247 %  The format of the XDrawImage method is:
02248 %
02249 %    MagickBooleanType XDrawImage(display,pixel,draw_info,image)
02250 %
02251 %  A description of each parameter follows:
02252 %
02253 %    o display: Specifies a connection to an X server;  returned from
02254 %      XOpenDisplay.
02255 %
02256 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02257 %
02258 %    o draw_info: Specifies a pointer to a XDrawInfo structure.
02259 %
02260 %    o image: the image.
02261 %
02262 */
02263 MagickExport MagickBooleanType XDrawImage(Display *display,
02264   const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
02265 {
02266   ExceptionInfo
02267     *exception;
02268 
02269   GC
02270     draw_context;
02271 
02272   Image
02273     *draw_image;
02274 
02275   int
02276     x,
02277     y;
02278 
02279   MagickBooleanType
02280     matte;
02281 
02282   Pixmap
02283     draw_pixmap;
02284 
02285   unsigned int
02286     depth,
02287     height,
02288     width;
02289 
02290   Window
02291     root_window;
02292 
02293   XGCValues
02294     context_values;
02295 
02296   XImage
02297     *draw_ximage;
02298 
02299   /*
02300     Initialize drawd image.
02301   */
02302   assert(display != (Display *) NULL);
02303   assert(pixel != (XPixelInfo *) NULL);
02304   assert(draw_info != (XDrawInfo *) NULL);
02305   assert(image != (Image *) NULL);
02306   if (image->debug != MagickFalse)
02307     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02308   /*
02309     Initialize drawd pixmap.
02310   */
02311   root_window=XRootWindow(display,XDefaultScreen(display));
02312   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
02313   draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
02314     draw_info->height,depth);
02315   if (draw_pixmap == (Pixmap) NULL)
02316     return(MagickFalse);
02317   /*
02318     Initialize graphics info.
02319   */
02320   context_values.background=(unsigned long) (~0);
02321   context_values.foreground=0;
02322   context_values.line_width=(int) draw_info->line_width;
02323   draw_context=XCreateGC(display,root_window,(unsigned long)
02324     (GCBackground | GCForeground | GCLineWidth),&context_values);
02325   if (draw_context == (GC) NULL)
02326     return(MagickFalse);
02327   /*
02328     Clear pixmap.
02329   */
02330   (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
02331     draw_info->height);
02332   /*
02333     Draw line to pixmap.
02334   */
02335   (void) XSetBackground(display,draw_context,0);
02336   (void) XSetForeground(display,draw_context,(unsigned long) (~0));
02337   (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
02338   (void) XSetStipple(display,draw_context,draw_info->stipple);
02339   switch (draw_info->element)
02340   {
02341     case PointElement:
02342     default:
02343     {
02344       (void) XDrawLines(display,draw_pixmap,draw_context,
02345         draw_info->coordinate_info,(int) draw_info->number_coordinates,
02346         CoordModeOrigin);
02347       break;
02348     }
02349     case LineElement:
02350     {
02351       (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
02352         draw_info->line_info.y1,draw_info->line_info.x2,
02353         draw_info->line_info.y2);
02354       break;
02355     }
02356     case RectangleElement:
02357     {
02358       (void) XDrawRectangle(display,draw_pixmap,draw_context,
02359         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02360         (unsigned int) draw_info->rectangle_info.width,
02361         (unsigned int) draw_info->rectangle_info.height);
02362       break;
02363     }
02364     case FillRectangleElement:
02365     {
02366       (void) XFillRectangle(display,draw_pixmap,draw_context,
02367         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02368         (unsigned int) draw_info->rectangle_info.width,
02369         (unsigned int) draw_info->rectangle_info.height);
02370       break;
02371     }
02372     case CircleElement:
02373     case EllipseElement:
02374     {
02375       (void) XDrawArc(display,draw_pixmap,draw_context,
02376         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02377         (unsigned int) draw_info->rectangle_info.width,
02378         (unsigned int) draw_info->rectangle_info.height,0,360*64);
02379       break;
02380     }
02381     case FillCircleElement:
02382     case FillEllipseElement:
02383     {
02384       (void) XFillArc(display,draw_pixmap,draw_context,
02385         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02386         (unsigned int) draw_info->rectangle_info.width,
02387         (unsigned int) draw_info->rectangle_info.height,0,360*64);
02388       break;
02389     }
02390     case PolygonElement:
02391     {
02392       XPoint
02393         *coordinate_info;
02394 
02395       coordinate_info=draw_info->coordinate_info;
02396       (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
02397         (int) draw_info->number_coordinates,CoordModeOrigin);
02398       (void) XDrawLine(display,draw_pixmap,draw_context,
02399         coordinate_info[draw_info->number_coordinates-1].x,
02400         coordinate_info[draw_info->number_coordinates-1].y,
02401         coordinate_info[0].x,coordinate_info[0].y);
02402       break;
02403     }
02404     case FillPolygonElement:
02405     {
02406       (void) XFillPolygon(display,draw_pixmap,draw_context,
02407         draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
02408         CoordModeOrigin);
02409       break;
02410     }
02411   }
02412   (void) XFreeGC(display,draw_context);
02413   /*
02414     Initialize X image.
02415   */
02416   draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
02417     draw_info->height,AllPlanes,ZPixmap);
02418   if (draw_ximage == (XImage *) NULL)
02419     return(MagickFalse);
02420   (void) XFreePixmap(display,draw_pixmap);
02421   /*
02422     Initialize draw image.
02423   */
02424   draw_image=AcquireImage((ImageInfo *) NULL);
02425   if (draw_image == (Image *) NULL)
02426     return(MagickFalse);
02427   draw_image->columns=draw_info->width;
02428   draw_image->rows=draw_info->height;
02429   /*
02430     Transfer drawn X image to image.
02431   */
02432   width=(unsigned int) image->columns;
02433   height=(unsigned int) image->rows;
02434   x=0;
02435   y=0;
02436   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02437   (void) GetOneVirtualPixel(image,x,y,&draw_image->background_color,
02438     &image->exception);
02439   if (SetImageStorageClass(draw_image,DirectClass) == MagickFalse)
02440     return(MagickFalse);
02441   draw_image->matte=MagickTrue;
02442   exception=(&image->exception);
02443   for (y=0; y < (int) draw_image->rows; y++)
02444   {
02445     register long
02446       x;
02447 
02448     register PixelPacket
02449       *__restrict q;
02450 
02451     q=QueueAuthenticPixels(draw_image,0,y,draw_image->columns,1,exception);
02452     if (q == (PixelPacket *) NULL)
02453       break;
02454     for (x=0; x < (long) draw_image->columns; x++)
02455     {
02456       if (XGetPixel(draw_ximage,x,y) == 0)
02457         {
02458           /*
02459             Set this pixel to the background color.
02460           */
02461           *q=draw_image->background_color;
02462           q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
02463             TransparentOpacity : OpaqueOpacity);
02464         }
02465       else
02466         {
02467           /*
02468             Set this pixel to the pen color.
02469           */
02470           q->red=ScaleShortToQuantum(pixel->pen_color.red);
02471           q->green=ScaleShortToQuantum(pixel->pen_color.green);
02472           q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
02473           q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
02474             OpaqueOpacity : TransparentOpacity);
02475         }
02476       q++;
02477     }
02478     if (SyncAuthenticPixels(draw_image,exception) == MagickFalse)
02479       break;
02480   }
02481   XDestroyImage(draw_ximage);
02482   /*
02483     Determine draw geometry.
02484   */
02485   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02486   if ((width != (unsigned int) draw_image->columns) ||
02487       (height != (unsigned int) draw_image->rows))
02488     {
02489       char
02490         image_geometry[MaxTextExtent];
02491 
02492       /*
02493         Scale image.
02494       */
02495       (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
02496         width,height);
02497       (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
02498     }
02499   if (draw_info->degrees != 0.0)
02500     {
02501       Image
02502         *rotate_image;
02503 
02504       int
02505         rotations;
02506 
02507       MagickRealType
02508         normalized_degrees;
02509 
02510       /*
02511         Rotate image.
02512       */
02513       rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
02514       if (rotate_image == (Image *) NULL)
02515         return(MagickFalse);
02516       draw_image=DestroyImage(draw_image);
02517       draw_image=rotate_image;
02518       /*
02519         Annotation is relative to the degree of rotation.
02520       */
02521       normalized_degrees=draw_info->degrees;
02522       while (normalized_degrees < -45.0)
02523         normalized_degrees+=360.0;
02524       for (rotations=0; normalized_degrees > 45.0; rotations++)
02525         normalized_degrees-=90.0;
02526       switch (rotations % 4)
02527       {
02528         default:
02529         case 0:
02530           break;
02531         case 1:
02532         {
02533           /*
02534             Rotate 90 degrees.
02535           */
02536           x=x-(int) draw_image->columns/2;
02537           y=y+(int) draw_image->columns/2;
02538           break;
02539         }
02540         case 2:
02541         {
02542           /*
02543             Rotate 180 degrees.
02544           */
02545           x=x-(int) draw_image->columns;
02546           break;
02547         }
02548         case 3:
02549         {
02550           /*
02551             Rotate 270 degrees.
02552           */
02553           x=x-(int) draw_image->columns/2;
02554           y=y-(int) (draw_image->rows-(draw_image->columns/2));
02555           break;
02556         }
02557       }
02558     }
02559   /*
02560     Composite text onto the image.
02561   */
02562   for (y=0; y < (int) draw_image->rows; y++)
02563   {
02564     register long
02565       x;
02566 
02567     register PixelPacket
02568       *__restrict q;
02569 
02570     q=GetAuthenticPixels(draw_image,0,y,draw_image->columns,1,exception);
02571     if (q == (PixelPacket *) NULL)
02572       break;
02573     for (x=0; x < (long) draw_image->columns; x++)
02574     {
02575       if (q->opacity != (Quantum) TransparentOpacity)
02576         q->opacity=OpaqueOpacity;
02577       q++;
02578     }
02579     if (SyncAuthenticPixels(draw_image,exception) == MagickFalse)
02580       break;
02581   }
02582   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02583   if (draw_info->stencil == TransparentStencil)
02584     (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,x,y);
02585   else
02586     {
02587       matte=image->matte;
02588       (void) CompositeImage(image,OverCompositeOp,draw_image,x,y);
02589       image->matte=matte;
02590     }
02591   draw_image=DestroyImage(draw_image);
02592   return(MagickTrue);
02593 }
02594 
02595 /*
02596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02597 %                                                                             %
02598 %                                                                             %
02599 %                                                                             %
02600 %   X E r r o r                                                               %
02601 %                                                                             %
02602 %                                                                             %
02603 %                                                                             %
02604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02605 %
02606 %  XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
02607 %  and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
02608 %  for XQueryColor.  It returns MagickFalse in those cases.  Otherwise it returns
02609 %  True.
02610 %
02611 %  The format of the XError function is:
02612 %
02613 %      XError(display,error)
02614 %
02615 %  A description of each parameter follows:
02616 %
02617 %    o display: Specifies a pointer to the Display structure;  returned from
02618 %      XOpenDisplay.
02619 %
02620 %    o error: Specifies the error event.
02621 %
02622 */
02623 
02624 #if defined(__cplusplus) || defined(c_plusplus)
02625 extern "C" {
02626 #endif
02627 
02628 MagickExport int XError(Display *display,XErrorEvent *error)
02629 {
02630   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02631   assert(display != (Display *) NULL);
02632   assert(error != (XErrorEvent *) NULL);
02633   xerror_alert=MagickTrue;
02634   switch (error->request_code)
02635   {
02636     case X_GetGeometry:
02637     {
02638       if ((int) error->error_code == BadDrawable)
02639         return(MagickFalse);
02640       break;
02641     }
02642     case X_GetWindowAttributes:
02643     case X_QueryTree:
02644     {
02645       if ((int) error->error_code == BadWindow)
02646         return(MagickFalse);
02647       break;
02648     }
02649     case X_QueryColors:
02650     {
02651       if ((int) error->error_code == BadValue)
02652         return(MagickFalse);
02653       break;
02654     }
02655   }
02656   return(MagickTrue);
02657 }
02658 
02659 #if defined(__cplusplus) || defined(c_plusplus)
02660 }
02661 #endif
02662 
02663 /*
02664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02665 %                                                                             %
02666 %                                                                             %
02667 %                                                                             %
02668 %   X F r e e R e s o u r c e s                                               %
02669 %                                                                             %
02670 %                                                                             %
02671 %                                                                             %
02672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02673 %
02674 %  XFreeResources() frees X11 resources.
02675 %
02676 %  The format of the XFreeResources method is:
02677 %
02678 %      void XFreeResources(Display *display,XVisualInfo *visual_info,
02679 %        XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
02680 %        XResourceInfo *resource_info,XWindowInfo *window_info)
02681 %        resource_info,window_info)
02682 %
02683 %  A description of each parameter follows:
02684 %
02685 %    o display: Specifies a connection to an X server; returned from
02686 %      XOpenDisplay.
02687 %
02688 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02689 %      returned from XGetVisualInfo.
02690 %
02691 %    o map_info: If map_type is specified, this structure is initialized
02692 %      with info from the Standard Colormap.
02693 %
02694 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02695 %
02696 %    o font_info: Specifies a pointer to a XFontStruct structure.
02697 %
02698 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
02699 %
02700 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
02701 %
02702 */
02703 MagickExport void XFreeResources(Display *display,XVisualInfo *visual_info,
02704   XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
02705   XResourceInfo *resource_info,XWindowInfo *window_info)
02706 {
02707   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02708   assert(display != (Display *) NULL);
02709   assert(resource_info != (XResourceInfo *) NULL);
02710   if (window_info != (XWindowInfo *) NULL)
02711     {
02712       /*
02713         Free X image.
02714       */
02715       if (window_info->ximage != (XImage *) NULL)
02716         XDestroyImage(window_info->ximage);
02717       if (window_info->id != (Window) NULL)
02718         {
02719           /*
02720             Free destroy window and free cursors.
02721           */
02722           if (window_info->id != XRootWindow(display,visual_info->screen))
02723             (void) XDestroyWindow(display,window_info->id);
02724           if (window_info->annotate_context != (GC) NULL)
02725             (void) XFreeGC(display,window_info->annotate_context);
02726           if (window_info->highlight_context != (GC) NULL)
02727             (void) XFreeGC(display,window_info->highlight_context);
02728           if (window_info->widget_context != (GC) NULL)
02729             (void) XFreeGC(display,window_info->widget_context);
02730           if (window_info->cursor != (Cursor) NULL)
02731             (void) XFreeCursor(display,window_info->cursor);
02732           window_info->cursor=(Cursor) NULL;
02733           if (window_info->busy_cursor != (Cursor) NULL)
02734             (void) XFreeCursor(display,window_info->busy_cursor);
02735           window_info->busy_cursor=(Cursor) NULL;
02736         }
02737     }
02738   /*
02739     Free font.
02740   */
02741   if (font_info != (XFontStruct *) NULL)
02742     (void) XFreeFont(display,font_info);
02743   if (map_info != (XStandardColormap *) NULL)
02744     {
02745       /*
02746         Free X Standard Colormap.
02747       */
02748       if (resource_info->map_type == (char *) NULL)
02749         (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
02750       (void) XFree((void *) map_info);
02751     }
02752   /*
02753     Free X visual info.
02754   */
02755   if (visual_info != (XVisualInfo *) NULL)
02756     (void) XFree((void *) visual_info);
02757   if (resource_info->close_server != MagickFalse)
02758     (void) XCloseDisplay(display);
02759 }
02760 
02761 /*
02762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02763 %                                                                             %
02764 %                                                                             %
02765 %                                                                             %
02766 %   X F r e e S t a n d a r d C o l o r m a p                                 %
02767 %                                                                             %
02768 %                                                                             %
02769 %                                                                             %
02770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02771 %
02772 %  XFreeStandardColormap() frees an X11 colormap.
02773 %
02774 %  The format of the XFreeStandardColormap method is:
02775 %
02776 %      void XFreeStandardColormap(Display *display,
02777 %        const XVisualInfo *visual_info,XStandardColormap *map_info,
02778 %        XPixelInfo *pixel)
02779 %
02780 %  A description of each parameter follows:
02781 %
02782 %    o display: Specifies a connection to an X server; returned from
02783 %      XOpenDisplay.
02784 %
02785 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02786 %      returned from XGetVisualInfo.
02787 %
02788 %    o map_info: If map_type is specified, this structure is initialized
02789 %      with info from the Standard Colormap.
02790 %
02791 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02792 %
02793 */
02794 MagickExport void XFreeStandardColormap(Display *display,
02795   const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
02796 {
02797   /*
02798     Free colormap.
02799   */
02800   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02801   assert(display != (Display *) NULL);
02802   assert(visual_info != (XVisualInfo *) NULL);
02803   assert(map_info != (XStandardColormap *) NULL);
02804   (void) XFlush(display);
02805   if (map_info->colormap != (Colormap) NULL)
02806     {
02807       if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
02808         (void) XFreeColormap(display,map_info->colormap);
02809       else
02810         if (pixel != (XPixelInfo *) NULL)
02811           if ((visual_info->klass != TrueColor) &&
02812               (visual_info->klass != DirectColor))
02813             (void) XFreeColors(display,map_info->colormap,pixel->pixels,
02814               (int) pixel->colors,0);
02815     }
02816   map_info->colormap=(Colormap) NULL;
02817   if (pixel != (XPixelInfo *) NULL)
02818     {
02819       if (pixel->pixels != (unsigned long *) NULL)
02820         pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
02821       pixel->pixels=(unsigned long *) NULL;
02822     }
02823 }
02824 
02825 /*
02826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02827 %                                                                             %
02828 %                                                                             %
02829 %                                                                             %
02830 %   X G e t A n n o t a t e I n f o                                           %
02831 %                                                                             %
02832 %                                                                             %
02833 %                                                                             %
02834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02835 %
02836 %  XGetAnnotateInfo() initializes the AnnotateInfo structure.
02837 %
02838 %  The format of the XGetAnnotateInfo method is:
02839 %
02840 %      void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
02841 %
02842 %  A description of each parameter follows:
02843 %
02844 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
02845 %
02846 */
02847 MagickExport void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
02848 {
02849   /*
02850     Initialize annotate structure.
02851   */
02852   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02853   assert(annotate_info != (XAnnotateInfo *) NULL);
02854   annotate_info->x=0;
02855   annotate_info->y=0;
02856   annotate_info->width=0;
02857   annotate_info->height=0;
02858   annotate_info->stencil=ForegroundStencil;
02859   annotate_info->degrees=0.0;
02860   annotate_info->font_info=(XFontStruct *) NULL;
02861   annotate_info->text=(char *) NULL;
02862   *annotate_info->geometry='\0';
02863   annotate_info->previous=(XAnnotateInfo *) NULL;
02864   annotate_info->next=(XAnnotateInfo *) NULL;
02865   (void) XSupportsLocale();
02866   (void) XSetLocaleModifiers("");
02867 }
02868 
02869 /*
02870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02871 %                                                                             %
02872 %                                                                             %
02873 %                                                                             %
02874 %   X G e t M a p I n f o                                                     %
02875 %                                                                             %
02876 %                                                                             %
02877 %                                                                             %
02878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02879 %
02880 %  XGetMapInfo() initializes the XStandardColormap structure.
02881 %
02882 %  The format of the XStandardColormap method is:
02883 %
02884 %      void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
02885 %        XStandardColormap *map_info)
02886 %
02887 %  A description of each parameter follows:
02888 %
02889 %    o colormap: Specifies the ID of the X server colormap.
02890 %
02891 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02892 %      returned from XGetVisualInfo.
02893 %
02894 %    o map_info: Specifies a pointer to a X11 XStandardColormap structure.
02895 %
02896 */
02897 MagickExport void XGetMapInfo(const XVisualInfo *visual_info,
02898   const Colormap colormap,XStandardColormap *map_info)
02899 {
02900   /*
02901     Initialize map info.
02902   */
02903   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02904   assert(visual_info != (XVisualInfo *) NULL);
02905   assert(map_info != (XStandardColormap *) NULL);
02906   map_info->colormap=colormap;
02907   map_info->red_max=visual_info->red_mask;
02908   map_info->red_mult=(unsigned long) (map_info->red_max != 0 ? 1 : 0);
02909   if (map_info->red_max != 0)
02910     while ((map_info->red_max & 0x01) == 0)
02911     {
02912       map_info->red_max>>=1;
02913       map_info->red_mult<<=1;
02914     }
02915   map_info->green_max=visual_info->green_mask;
02916   map_info->green_mult=(unsigned long) (map_info->green_max != 0 ? 1 : 0);
02917   if (map_info->green_max != 0)
02918     while ((map_info->green_max & 0x01) == 0)
02919     {
02920       map_info->green_max>>=1;
02921       map_info->green_mult<<=1;
02922     }
02923   map_info->blue_max=visual_info->blue_mask;
02924   map_info->blue_mult=(unsigned long) (map_info->blue_max != 0 ? 1 : 0);
02925   if (map_info->blue_max != 0)
02926     while ((map_info->blue_max & 0x01) == 0)
02927     {
02928       map_info->blue_max>>=1;
02929       map_info->blue_mult<<=1;
02930     }
02931   map_info->base_pixel=0;
02932 }
02933 
02934 /*
02935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02936 %                                                                             %
02937 %                                                                             %
02938 %                                                                             %
02939 %   X G e t P i x e l I n f o                                                 %
02940 %                                                                             %
02941 %                                                                             %
02942 %                                                                             %
02943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02944 %
02945 %  XGetPixelPacket() initializes the PixelPacket structure.
02946 %
02947 %  The format of the XGetPixelPacket method is:
02948 %
02949 %      void XGetPixelPacket(Display *display,const XVisualInfo *visual_info,
02950 %        const XStandardColormap *map_info,const XResourceInfo *resource_info,
02951 %        Image *image,XPixelInfo *pixel)
02952 %        pixel)
02953 %
02954 %  A description of each parameter follows:
02955 %
02956 %    o display: Specifies a connection to an X server; returned from
02957 %      XOpenDisplay.
02958 %
02959 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02960 %      returned from XGetVisualInfo.
02961 %
02962 %    o map_info: If map_type is specified, this structure is initialized
02963 %      with info from the Standard Colormap.
02964 %
02965 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
02966 %
02967 %    o image: the image.
02968 %
02969 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02970 %
02971 */
02972 MagickExport void XGetPixelPacket(Display *display,
02973   const XVisualInfo *visual_info,const XStandardColormap *map_info,
02974   const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
02975 {
02976   static const char
02977     *PenColors[MaxNumberPens]=
02978     {
02979       "#000000000000",  /* black */
02980       "#00000000ffff",  /* blue */
02981       "#0000ffffffff",  /* cyan */
02982       "#0000ffff0000",  /* green */
02983       "#bdbdbdbdbdbd",  /* gray */
02984       "#ffff00000000",  /* red */
02985       "#ffff0000ffff",  /* magenta */
02986       "#ffffffff0000",  /* yellow */
02987       "#ffffffffffff",  /* white */
02988       "#bdbdbdbdbdbd",  /* gray */
02989       "#bdbdbdbdbdbd"   /* gray */
02990     };
02991 
02992   Colormap
02993     colormap;
02994 
02995   register long
02996     i;
02997 
02998   Status
02999     status;
03000 
03001   unsigned int
03002     packets;
03003 
03004   /*
03005     Initialize pixel info.
03006   */
03007   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03008   assert(display != (Display *) NULL);
03009   assert(visual_info != (XVisualInfo *) NULL);
03010   assert(map_info != (XStandardColormap *) NULL);
03011   assert(resource_info != (XResourceInfo *) NULL);
03012   assert(pixel != (XPixelInfo *) NULL);
03013   pixel->colors=0;
03014   if (image != (Image *) NULL)
03015     if (image->storage_class == PseudoClass)
03016       pixel->colors=image->colors;
03017   packets=(unsigned int)
03018     MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
03019   if (pixel->pixels != (unsigned long *) NULL)
03020     pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
03021   pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
03022     sizeof(pixel->pixels));
03023   if (pixel->pixels == (unsigned long *) NULL)
03024     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
03025       image->filename);
03026   /*
03027     Set foreground color.
03028   */
03029   colormap=map_info->colormap;
03030   (void) XParseColor(display,colormap,(char *) ForegroundColor,
03031     &pixel->foreground_color);
03032   status=XParseColor(display,colormap,resource_info->foreground_color,
03033     &pixel->foreground_color);
03034   if (status == False)
03035     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03036       resource_info->foreground_color);
03037   pixel->foreground_color.pixel=
03038     XStandardPixel(map_info,&pixel->foreground_color);
03039   pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
03040   /*
03041     Set background color.
03042   */
03043   (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
03044   status=XParseColor(display,colormap,resource_info->background_color,
03045     &pixel->background_color);
03046   if (status == False)
03047     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03048       resource_info->background_color);
03049   pixel->background_color.pixel=
03050     XStandardPixel(map_info,&pixel->background_color);
03051   pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
03052   /*
03053     Set border color.
03054   */
03055   (void) XParseColor(display,colormap,(char *) BorderColor,
03056     &pixel->border_color);
03057   status=XParseColor(display,colormap,resource_info->border_color,
03058     &pixel->border_color);
03059   if (status == False)
03060     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03061       resource_info->border_color);
03062   pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
03063   pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
03064   /*
03065     Set matte color.
03066   */
03067   pixel->matte_color=pixel->background_color;
03068   if (resource_info->matte_color != (char *) NULL)
03069     {
03070       /*
03071         Matte color is specified as a X resource or command line argument.
03072       */
03073       status=XParseColor(display,colormap,resource_info->matte_color,
03074         &pixel->matte_color);
03075       if (status == False)
03076         ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03077           resource_info->matte_color);
03078       pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
03079       pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
03080     }
03081   /*
03082     Set highlight color.
03083   */
03084   pixel->highlight_color.red=(unsigned short) ((
03085     pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
03086     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03087   pixel->highlight_color.green=(unsigned short) ((
03088     pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
03089     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03090   pixel->highlight_color.blue=(unsigned short) ((
03091     pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
03092     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03093   pixel->highlight_color.pixel=
03094     XStandardPixel(map_info,&pixel->highlight_color);
03095   pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
03096   /*
03097     Set shadow color.
03098   */
03099   pixel->shadow_color.red=(unsigned short) (((MagickRealType)
03100     pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
03101   pixel->shadow_color.green=(unsigned short) (((MagickRealType)
03102     pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
03103   pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
03104     pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
03105   pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
03106   pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
03107   /*
03108     Set depth color.
03109   */
03110   pixel->depth_color.red=(unsigned short) (((MagickRealType)
03111     pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
03112   pixel->depth_color.green=(unsigned short) (((MagickRealType)
03113     pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
03114   pixel->depth_color.blue=(unsigned short) (((MagickRealType)
03115     pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
03116   pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
03117   pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
03118   /*
03119     Set trough color.
03120   */
03121   pixel->trough_color.red=(unsigned short) (((MagickRealType)
03122     pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
03123   pixel->trough_color.green=(unsigned short) (((MagickRealType)
03124     pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
03125   pixel->trough_color.blue=(unsigned short) (((MagickRealType)
03126     pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
03127   pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
03128   pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
03129   /*
03130     Set pen color.
03131   */
03132   for (i=0; i < MaxNumberPens; i++)
03133   {
03134     (void) XParseColor(display,colormap,(char *) PenColors[i],
03135       &pixel->pen_colors[i]);
03136     status=XParseColor(display,colormap,resource_info->pen_colors[i],
03137       &pixel->pen_colors[i]);
03138     if (status == False)
03139       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03140         resource_info->pen_colors[i]);
03141     pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
03142     pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
03143   }
03144   pixel->box_color=pixel->background_color;
03145   pixel->pen_color=pixel->foreground_color;
03146   pixel->box_index=0;
03147   pixel->pen_index=1;
03148   if (image != (Image *) NULL)
03149     {
03150       if ((resource_info->gamma_correct != MagickFalse) &&
03151           (image->gamma != 0.0))
03152         {
03153           GeometryInfo
03154             geometry_info;
03155 
03156           MagickStatusType
03157             flags;
03158 
03159           /*
03160             Initialize map relative to display and image gamma.
03161           */
03162           flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
03163           red_gamma=geometry_info.rho;
03164           green_gamma=geometry_info.sigma;
03165           if ((flags & SigmaValue) == 0)
03166             green_gamma=red_gamma;
03167           blue_gamma=geometry_info.xi;
03168           if ((flags & XiValue) == 0)
03169             blue_gamma=red_gamma;
03170           red_gamma*=image->gamma;
03171           green_gamma*=image->gamma;
03172           blue_gamma*=image->gamma;
03173         }
03174       if (image->storage_class == PseudoClass)
03175         {
03176           /*
03177             Initialize pixel array for images of type PseudoClass.
03178           */
03179           for (i=0; i < (long) image->colors; i++)
03180             pixel->pixels[i]=
03181               XGammaPixel(map_info,image->colormap+i);
03182           for (i=0; i < MaxNumberPens; i++)
03183             pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
03184           pixel->colors+=MaxNumberPens;
03185         }
03186     }
03187 }
03188 
03189 /*
03190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03191 %                                                                             %
03192 %                                                                             %
03193 %                                                                             %
03194 %   X G e t R e s o u r c e C l a s s                                         %
03195 %                                                                             %
03196 %                                                                             %
03197 %                                                                             %
03198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03199 %
03200 %  XGetResourceClass() queries the X server for the specified resource name or
03201 %  class.  If the resource name or class is not defined in the database, the
03202 %  supplied default value is returned.
03203 %
03204 %  The format of the XGetResourceClass method is:
03205 %
03206 %      char *XGetResourceClass(XrmDatabase database,const char *client_name,
03207 %        const char *keyword,char *resource_default)
03208 %
03209 %  A description of each parameter follows:
03210 %
03211 %    o database: Specifies a resource database; returned from
03212 %      XrmGetStringDatabase.
03213 %
03214 %    o client_name:  Specifies the application name used to retrieve resource
03215 %      info from the X server database.
03216 %
03217 %    o keyword: Specifies the keyword of the value being retrieved.
03218 %
03219 %    o resource_default: Specifies the default value to return if the query
03220 %      fails to find the specified keyword/class.
03221 %
03222 */
03223 MagickExport char *XGetResourceClass(XrmDatabase database,
03224   const char *client_name,const char *keyword,char *resource_default)
03225 {
03226   char
03227     resource_class[MaxTextExtent],
03228     resource_name[MaxTextExtent];
03229 
03230   static char
03231     *resource_type;
03232 
03233   Status
03234     status;
03235 
03236   XrmValue
03237     resource_value;
03238 
03239   if (database == (XrmDatabase) NULL)
03240     return(resource_default);
03241   *resource_name='\0';
03242   *resource_class='\0';
03243   if (keyword != (char *) NULL)
03244     {
03245       int
03246         c,
03247         k;
03248 
03249       /*
03250         Initialize resource keyword and class.
03251       */
03252       (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",
03253         client_name,keyword);
03254       c=(int) (*client_name);
03255       if ((c >= XK_a) && (c <= XK_z))
03256         c-=(XK_a-XK_A);
03257       else
03258         if ((c >= XK_agrave) && (c <= XK_odiaeresis))
03259           c-=(XK_agrave-XK_Agrave);
03260         else
03261           if ((c >= XK_oslash) && (c <= XK_thorn))
03262             c-=(XK_oslash-XK_Ooblique);
03263       k=(int) (*keyword);
03264       if ((k >= XK_a) && (k <= XK_z))
03265         k-=(XK_a-XK_A);
03266       else
03267         if ((k >= XK_agrave) && (k <= XK_odiaeresis))
03268           k-=(XK_agrave-XK_Agrave);
03269         else
03270           if ((k >= XK_oslash) && (k <= XK_thorn))
03271             k-=(XK_oslash-XK_Ooblique);
03272       (void) FormatMagickString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
03273         client_name+1,k,keyword+1);
03274     }
03275   status=XrmGetResource(database,resource_name,resource_class,&resource_type,
03276     &resource_value);
03277   if (status == False)
03278     return(resource_default);
03279   return(resource_value.addr);
03280 }
03281 
03282 /*
03283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03284 %                                                                             %
03285 %                                                                             %
03286 %                                                                             %
03287 %   X G e t R e s o u r c e D a t a b a s e                                   %
03288 %                                                                             %
03289 %                                                                             %
03290 %                                                                             %
03291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03292 %
03293 %  XGetResourceDatabase() creates a new resource database and initializes it.
03294 %
03295 %  The format of the XGetResourceDatabase method is:
03296 %
03297 %      XrmDatabase XGetResourceDatabase(Display *display,
03298 %        const char *client_name)
03299 %
03300 %  A description of each parameter follows:
03301 %
03302 %    o database: XGetResourceDatabase() returns the database after it is
03303 %      initialized.
03304 %
03305 %    o display: Specifies a connection to an X server;  returned from
03306 %      XOpenDisplay.
03307 %
03308 %    o client_name:  Specifies the application name used to retrieve resource
03309 %      info from the X server database.
03310 %
03311 */
03312 MagickExport XrmDatabase XGetResourceDatabase(Display *display,
03313   const char *client_name)
03314 {
03315   char
03316     filename[MaxTextExtent];
03317 
03318   int
03319     c;
03320 
03321   register const char
03322     *p;
03323 
03324   XrmDatabase
03325     resource_database,
03326     server_database;
03327 
03328   if (display == (Display *) NULL)
03329     return((XrmDatabase) NULL);
03330   assert(client_name != (char *) NULL);
03331   /*
03332     Initialize resource database.
03333   */
03334   XrmInitialize();
03335   (void) XGetDefault(display,(char *) client_name,"dummy");
03336   resource_database=XrmGetDatabase(display);
03337   /*
03338     Combine application database.
03339   */
03340   if (client_name != (char *) NULL)
03341     {
03342       /*
03343         Get basename of client.
03344       */
03345       p=client_name+(strlen(client_name)-1);
03346       while ((p > client_name) && (*p != '/'))
03347         p--;
03348       if (*p == '/')
03349         client_name=p+1;
03350     }
03351   c=(int) (*client_name);
03352   if ((c >= XK_a) && (c <= XK_z))
03353     c-=(XK_a-XK_A);
03354   else
03355     if ((c >= XK_agrave) && (c <= XK_odiaeresis))
03356       c-=(XK_agrave-XK_Agrave);
03357     else
03358       if ((c >= XK_oslash) && (c <= XK_thorn))
03359         c-=(XK_oslash-XK_Ooblique);
03360 #if defined(X11_APPLICATION_PATH)
03361   (void) FormatMagickString(filename,MaxTextExtent,"%s%c%s",
03362     X11_APPLICATION_PATH,c,client_name+1);
03363   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
03364 #endif
03365   if (XResourceManagerString(display) != (char *) NULL)
03366     {
03367       /*
03368         Combine server database.
03369       */
03370       server_database=XrmGetStringDatabase(XResourceManagerString(display));
03371       XrmCombineDatabase(server_database,&resource_database,MagickFalse);
03372     }
03373   /*
03374     Merge user preferences database.
03375   */
03376 #if defined(X11_PREFERENCES_PATH)
03377   (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
03378     X11_PREFERENCES_PATH,client_name);
03379   ExpandFilename(filename);
03380   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
03381 #endif
03382   return(resource_database);
03383 }
03384 
03385 /*
03386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03387 %                                                                             %
03388 %                                                                             %
03389 %                                                                             %
03390 %   X G e t R e s o u r c e I n f o                                           %
03391 %                                                                             %
03392 %                                                                             %
03393 %                                                                             %
03394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03395 %
03396 %  XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
03397 %
03398 %  The format of the XGetResourceInfo method is:
03399 %
03400 %      void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
03401 %        const char *client_name,XResourceInfo *resource_info)
03402 %
03403 %  A description of each parameter follows:
03404 %
03405 %    o image_info: the image info.
03406 %
03407 %    o database: Specifies a resource database; returned from
03408 %      XrmGetStringDatabase.
03409 %
03410 %    o client_name:  Specifies the application name used to retrieve
03411 %      resource info from the X server database.
03412 %
03413 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
03414 %
03415 */
03416 MagickExport void XGetResourceInfo(const ImageInfo *image_info,
03417   XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
03418 {
03419   char
03420     *cwd,
03421     *resource_value;
03422 
03423   /*
03424     Initialize resource info fields.
03425   */
03426   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03427   assert(resource_info != (XResourceInfo *) NULL);
03428   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
03429   resource_info->resource_database=database;
03430   resource_info->image_info=(ImageInfo *) image_info;
03431   (void) SetImageInfoProgressMonitor(resource_info->image_info,
03432     XMagickProgressMonitor,(void *) NULL);
03433   resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
03434   resource_info->close_server=MagickTrue;
03435   resource_info->client_name=AcquireString(client_name);
03436   resource_value=XGetResourceClass(database,client_name,"backdrop",
03437     (char *) "False");
03438   resource_info->backdrop=IsMagickTrue(resource_value);
03439   resource_info->background_color=XGetResourceInstance(database,client_name,
03440     "background",(char *) "#d6d6d6d6d6d6");
03441   resource_info->border_color=XGetResourceInstance(database,client_name,
03442     "borderColor",BorderColor);
03443   resource_value=XGetResourceClass(database,client_name,"borderWidth",
03444     (char *) "2");
03445   resource_info->border_width=(unsigned int) atoi(resource_value);
03446   resource_value=XGetResourceClass(database,client_name,"colormap",
03447     (char *) "shared");
03448   resource_info->colormap=UndefinedColormap;
03449   if (LocaleCompare("private",resource_value) == 0)
03450     resource_info->colormap=PrivateColormap;
03451   if (LocaleCompare("shared",resource_value) == 0)
03452     resource_info->colormap=SharedColormap;
03453   if (resource_info->colormap == UndefinedColormap)
03454     ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
03455       resource_value);
03456   resource_value=XGetResourceClass(database,client_name,
03457     "colorRecovery",(char *) "False");
03458   resource_info->color_recovery=IsMagickTrue(resource_value);
03459   resource_value=XGetResourceClass(database,client_name,"confirmExit",
03460     (char *) "False");
03461   resource_info->confirm_exit=IsMagickTrue(resource_value);
03462   resource_value=XGetResourceClass(database,client_name,"confirmEdit",
03463     (char *) "False");
03464   resource_info->confirm_edit=IsMagickTrue(resource_value);
03465   resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
03466   resource_info->delay=(unsigned int) atoi(resource_value);
03467   resource_info->display_gamma=XGetResourceClass(database,client_name,
03468     "displayGamma",(char *) "2.2");
03469   resource_value=XGetResourceClass(database,client_name,"displayWarnings",
03470     (char *) "True");
03471   resource_info->display_warnings=IsMagickTrue(resource_value);
03472   resource_info->font=XGetResourceClass(database,client_name,"font",
03473     (char *) NULL);
03474   resource_info->font=XGetResourceClass(database,client_name,"fontList",
03475     resource_info->font);
03476   resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
03477     (char *) "fixed");
03478   resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
03479     (char *) "variable");
03480   resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
03481     (char *) "5x8");
03482   resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
03483     (char *) "6x10");
03484   resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
03485     (char *) "7x13bold");
03486   resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
03487     (char *) "8x13bold");
03488   resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
03489     (char *) "9x15bold");
03490   resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
03491     (char *) "10x20");
03492   resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
03493     (char *) "12x24");
03494   resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
03495     (char *) "fixed");
03496   resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
03497     (char *) "fixed");
03498   resource_info->foreground_color=XGetResourceInstance(database,client_name,
03499     "foreground",ForegroundColor);
03500   resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
03501     (char *) "True");
03502   resource_info->gamma_correct=IsMagickTrue(resource_value);
03503   resource_info->image_geometry=ConstantString(XGetResourceClass(database,
03504     client_name,"geometry",(char *) NULL));
03505   resource_value=XGetResourceClass(database,client_name,"gravity",
03506     (char *) "Center");
03507   resource_info->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
03508     MagickFalse,resource_value);
03509   cwd=getcwd(resource_info->home_directory,MaxTextExtent);
03510   resource_info->icon_geometry=XGetResourceClass(database,client_name,
03511     "iconGeometry",(char *) NULL);
03512   resource_value=XGetResourceClass(database,client_name,"iconic",
03513     (char *) "False");
03514   resource_info->iconic=IsMagickTrue(resource_value);
03515   resource_value=XGetResourceClass(database,client_name,"immutable",
03516     LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
03517     (char *) "False");
03518   resource_info->immutable=IsMagickTrue(resource_value);
03519   resource_value=XGetResourceClass(database,client_name,"magnify",
03520     (char *) "3");
03521   resource_info->magnify=(unsigned int) atoi(resource_value);
03522   resource_info->map_type=XGetResourceClass(database,client_name,"map",
03523     (char *) NULL);
03524   resource_info->matte_color=XGetResourceInstance(database,client_name,
03525     "mattecolor",(char *) NULL);
03526   resource_info->name=ConstantString(XGetResourceClass(database,client_name,
03527     "name",(char *) NULL));
03528   resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
03529     (char *) "black");
03530   resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
03531     (char *) "blue");
03532   resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
03533     (char *) "cyan");
03534   resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
03535     (char *) "green");
03536   resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
03537     (char *) "gray");
03538   resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
03539     (char *) "red");
03540   resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
03541     (char *) "magenta");
03542   resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
03543     (char *) "yellow");
03544   resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
03545     (char *) "white");
03546   resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
03547     (char *) "gray");
03548   resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
03549     (char *) "gray");
03550   resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
03551   resource_info->pause=(unsigned int) atoi(resource_value);
03552   resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
03553   resource_info->quantum=atoi(resource_value);
03554   resource_info->text_font=XGetResourceClass(database,client_name,(char *)
03555     "font",(char *) "fixed");
03556   resource_info->text_font=XGetResourceClass(database,client_name,
03557     "textFontList",resource_info->text_font);
03558   resource_info->title=XGetResourceClass(database,client_name,"title",
03559     (char *) NULL);
03560   resource_value=XGetResourceClass(database,client_name,"undoCache",
03561     (char *) "16");
03562   resource_info->undo_cache=(unsigned int) atol(resource_value);
03563   resource_value=XGetResourceClass(database,client_name,"update",
03564     (char *) "False");
03565   resource_info->update=IsMagickTrue(resource_value);
03566   resource_value=XGetResourceClass(database,client_name,"usePixmap",
03567     (char *) "True");
03568   resource_info->use_pixmap=IsMagickTrue(resource_value);
03569   resource_value=XGetResourceClass(database,client_name,"sharedMemory",
03570     (char *) "True");
03571   resource_info->use_shared_memory=IsMagickTrue(resource_value);
03572   resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
03573     (char *) NULL);
03574   resource_info->window_group=XGetResourceClass(database,client_name,
03575     "windowGroup",(char *) NULL);
03576   resource_info->window_id=XGetResourceClass(database,client_name,"window",
03577     (char *) NULL);
03578   resource_info->write_filename=XGetResourceClass(database,client_name,
03579     "writeFilename",(char *) NULL);
03580 }
03581 
03582 /*
03583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03584 %                                                                             %
03585 %                                                                             %
03586 %                                                                             %
03587 %   X G e t R e s o u r c e I n s t a n c e                                   %
03588 %                                                                             %
03589 %                                                                             %
03590 %                                                                             %
03591 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03592 %
03593 %  XGetResourceInstance() queries the X server for the specified resource name.
03594 %  If the resource name is not defined in the database, the supplied default
03595 %  value is returned.
03596 %
03597 %  The format of the XGetResourceInstance method is:
03598 %
03599 %      char *XGetResourceInstance(XrmDatabase database,const char *client_name,
03600 %        const char *keyword,const char *resource_default)
03601 %
03602 %  A description of each parameter follows:
03603 %
03604 %    o database: Specifies a resource database; returned from
03605 %      XrmGetStringDatabase.
03606 %
03607 %    o client_name:  Specifies the application name used to retrieve
03608 %      resource info from the X server database.
03609 %
03610 %    o keyword: Specifies the keyword of the value being retrieved.
03611 %
03612 %    o resource_default: Specifies the default value to return if the query
03613 %      fails to find the specified keyword/class.
03614 %
03615 */
03616 MagickExport char *XGetResourceInstance(XrmDatabase database,
03617   const char *client_name,const char *keyword,const char *resource_default)
03618 {
03619   char
03620     *resource_type,
03621     resource_name[MaxTextExtent];
03622 
03623   Status
03624     status;
03625 
03626   XrmValue
03627     resource_value;
03628 
03629   if (database == (XrmDatabase) NULL)
03630     return((char *) resource_default);
03631   *resource_name='\0';
03632   if (keyword != (char *) NULL)
03633     (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",client_name,
03634       keyword);
03635   status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
03636     &resource_value);
03637   if (status == False)
03638     return((char *) resource_default);
03639   return(resource_value.addr);
03640 }
03641 
03642 /*
03643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03644 %                                                                             %
03645 %                                                                             %
03646 %                                                                             %
03647 %   X G e t S c r e e n D e n s i t y                                         %
03648 %                                                                             %
03649 %                                                                             %
03650 %                                                                             %
03651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03652 %
03653 %  XGetScreenDensity() returns the density of the X server screen in
03654 %  dots-per-inch.
03655 %
03656 %  The format of the XGetScreenDensity method is:
03657 %
03658 %      char *XGetScreenDensity(Display *display)
03659 %
03660 %  A description of each parameter follows:
03661 %
03662 %    o density: XGetScreenDensity() returns the density of the X screen in
03663 %      dots-per-inch.
03664 %
03665 %    o display: Specifies a connection to an X server;  returned from
03666 %      XOpenDisplay.
03667 %
03668 */
03669 MagickExport char *XGetScreenDensity(Display *display)
03670 {
03671   char
03672     density[MaxTextExtent];
03673 
03674   double
03675     x_density,
03676     y_density;
03677 
03678   /*
03679     Set density as determined by screen size.
03680   */
03681   x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
03682     ((double) DisplayWidthMM(display,XDefaultScreen(display))));
03683   y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
03684     ((double) DisplayHeightMM(display,XDefaultScreen(display))));
03685   (void) FormatMagickString(density,MaxTextExtent,"%gx%g",x_density,y_density);
03686   return(GetPageGeometry(density));
03687 }
03688 
03689 /*
03690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03691 %                                                                             %
03692 %                                                                             %
03693 %                                                                             %
03694 +   X G e t S u b w i n d o w                                                 %
03695 %                                                                             %
03696 %                                                                             %
03697 %                                                                             %
03698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03699 %
03700 %  XGetSubwindow() returns the subwindow of a window chosen the user with the
03701 %  pointer and a button press.
03702 %
03703 %  The format of the XGetSubwindow method is:
03704 %
03705 %      Window XGetSubwindow(Display *display,Window window,int x,int y)
03706 %
03707 %  A description of each parameter follows:
03708 %
03709 %    o subwindow: XGetSubwindow() returns NULL if no subwindow is found
03710 %      otherwise the subwindow is returned.
03711 %
03712 %    o display: Specifies a connection to an X server;  returned from
03713 %      XOpenDisplay.
03714 %
03715 %    o window: Specifies a pointer to a Window.
03716 %
03717 %    o x: the x coordinate of the pointer relative to the origin of the
03718 %      window.
03719 %
03720 %    o y: the y coordinate of the pointer relative to the origin of the
03721 %      window.
03722 %
03723 %
03724 */
03725 static Window XGetSubwindow(Display *display,Window window,int x,int y)
03726 {
03727   int
03728     x_offset,
03729     y_offset;
03730 
03731   Status
03732     status;
03733 
03734   Window
03735     source_window,
03736     target_window;
03737 
03738   assert(display != (Display *) NULL);
03739   source_window=XRootWindow(display,XDefaultScreen(display));
03740   if (window == (Window) NULL)
03741     return(source_window);
03742   target_window=window;
03743   for ( ; ; )
03744   {
03745     status=XTranslateCoordinates(display,source_window,window,x,y,
03746       &x_offset,&y_offset,&target_window);
03747     if (status != True)
03748       break;
03749     if (target_window == (Window) NULL)
03750       break;
03751     source_window=window;
03752     window=target_window;
03753     x=x_offset;
03754     y=y_offset;
03755   }
03756   if (target_window == (Window) NULL)
03757     target_window=window;
03758   return(target_window);
03759 }
03760 
03761 /*
03762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03763 %                                                                             %
03764 %                                                                             %
03765 %                                                                             %
03766 %   X G e t W i n d o w C o l o r                                             %
03767 %                                                                             %
03768 %                                                                             %
03769 %                                                                             %
03770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03771 %
03772 %  XGetWindowColor() returns the color of a pixel interactively chosen from the
03773 %  X server.
03774 %
03775 %  The format of the XGetWindowColor method is:
03776 %
03777 %      MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
03778 %        char *name)
03779 %
03780 %  A description of each parameter follows:
03781 %
03782 %    o display: Specifies a connection to an X server;  returned from
03783 %      XOpenDisplay.
03784 %
03785 %    o windows: Specifies a pointer to a XWindows structure.
03786 %
03787 %    o name: the name of the color if found in the X Color Database is
03788 %      returned in this character string.
03789 %
03790 */
03791 MagickExport MagickBooleanType XGetWindowColor(Display *display,
03792   XWindows *windows,char *name)
03793 {
03794   int
03795     x,
03796     y;
03797 
03798   PixelPacket
03799     pixel;
03800 
03801   RectangleInfo
03802     crop_info;
03803 
03804   Status
03805     status;
03806 
03807   Window
03808     child,
03809     client_window,
03810     root_window,
03811     target_window;
03812 
03813   XColor
03814     color;
03815 
03816   XImage
03817     *ximage;
03818 
03819   XWindowAttributes
03820     window_attributes;
03821 
03822   /*
03823     Choose a pixel from the X server.
03824   */
03825   assert(display != (Display *) NULL);
03826   assert(name != (char *) NULL);
03827   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
03828   *name='\0';
03829   target_window=XSelectWindow(display,&crop_info);
03830   if (target_window == (Window) NULL)
03831     return(MagickFalse);
03832   root_window=XRootWindow(display,XDefaultScreen(display));
03833   client_window=target_window;
03834   if (target_window != root_window)
03835     {
03836       unsigned int
03837         d;
03838 
03839       /*
03840         Get client window.
03841       */
03842       status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
03843       if (status != False)
03844         {
03845           client_window=XClientWindow(display,target_window);
03846           target_window=client_window;
03847         }
03848     }
03849   /*
03850     Verify window is viewable.
03851   */
03852   status=XGetWindowAttributes(display,target_window,&window_attributes);
03853   if ((status == False) || (window_attributes.map_state != IsViewable))
03854     return(MagickFalse);
03855   /*
03856     Get window X image.
03857   */
03858   (void) XTranslateCoordinates(display,root_window,target_window,
03859     (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
03860   ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
03861   if (ximage == (XImage *) NULL)
03862     return(MagickFalse);
03863   color.pixel=XGetPixel(ximage,0,0);
03864   XDestroyImage(ximage);
03865   /*
03866     Match color against the color database.
03867   */
03868   (void) XQueryColor(display,window_attributes.colormap,&color);
03869   pixel.red=ScaleShortToQuantum(color.red);
03870   pixel.green=ScaleShortToQuantum(color.green);
03871   pixel.blue=ScaleShortToQuantum(color.blue);
03872   pixel.opacity=OpaqueOpacity;
03873   (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
03874     &windows->image.image->exception);
03875   return(MagickTrue);
03876 }
03877 
03878 /*
03879 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03880 %                                                                             %
03881 %                                                                             %
03882 %                                                                             %
03883 +   X G e t W i n d o w I m a g e                                             %
03884 %                                                                             %
03885 %                                                                             %
03886 %                                                                             %
03887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03888 %
03889 %  XGetWindowImage() reads an image from the target X window and returns it.
03890 %  XGetWindowImage() optionally descends the window hierarchy and overlays the
03891 %  target image with each child image in an optimized fashion.  Any child
03892 %  window that have the same visual, colormap, and are contained by its parent
03893 %  are exempted.
03894 %
03895 %  The format of the XGetWindowImage method is:
03896 %
03897 %      Image *XGetWindowImage(Display *display,const Window window,
03898 %        const unsigned int borders,const unsigned int level)
03899 %
03900 %  A description of each parameter follows:
03901 %
03902 %    o display: Specifies a connection to an X server;  returned from
03903 %      XOpenDisplay.
03904 %
03905 %    o window: Specifies the window to obtain the image from.
03906 %
03907 %    o borders: Specifies whether borders pixels are to be saved with
03908 %      the image.
03909 %
03910 %    o level: Specifies an unsigned integer representing the level of
03911 %      decent in the window hierarchy.  This value must be zero or one on
03912 %      the initial call to XGetWindowImage.  A value of zero returns after
03913 %      one call.  A value of one causes the function to descend the window
03914 %      hierarchy and overlay the target image with each subwindow image.
03915 %
03916 %
03917 */
03918 static Image *XGetWindowImage(Display *display,const Window window,
03919   const unsigned int borders,const unsigned int level)
03920 {
03921   typedef struct _ColormapInfo
03922   {
03923     Colormap
03924       colormap;
03925 
03926     XColor
03927       *colors;
03928 
03929     struct _ColormapInfo
03930       *next;
03931   } ColormapInfo;
03932 
03933   typedef struct _WindowInfo
03934   {
03935     Window
03936       window,
03937       parent;
03938 
03939     Visual
03940       *visual;
03941 
03942     Colormap
03943       colormap;
03944 
03945     XSegment
03946       bounds;
03947 
03948     RectangleInfo
03949       crop_info;
03950   } WindowInfo;
03951 
03952   IndexPacket
03953     index;
03954 
03955   int
03956     display_height,
03957     display_width,
03958     id,
03959     x_offset,
03960     y_offset;
03961 
03962   RectangleInfo
03963     crop_info;
03964 
03965   register IndexPacket
03966     *indexes;
03967 
03968   register int
03969     i;
03970 
03971   static ColormapInfo
03972     *colormap_info = (ColormapInfo *) NULL;
03973 
03974   static int
03975     max_windows = 0,
03976     number_windows = 0;
03977 
03978   static WindowInfo
03979     *window_info;
03980 
03981   Status
03982     status;
03983 
03984   Window
03985     child,
03986     root_window;
03987 
03988   XWindowAttributes
03989     window_attributes;
03990 
03991   /*
03992     Verify window is viewable.
03993   */
03994   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03995   assert(display != (Display *) NULL);
03996   status=XGetWindowAttributes(display,window,&window_attributes);
03997   if ((status == False) || (window_attributes.map_state != IsViewable))
03998     return((Image *) NULL);
03999   /*
04000     Cropping rectangle is relative to root window.
04001   */
04002   root_window=XRootWindow(display,XDefaultScreen(display));
04003   (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
04004     &y_offset,&child);
04005   crop_info.x=(long) x_offset;
04006   crop_info.y=(long) y_offset;
04007   crop_info.width=(unsigned long) window_attributes.width;
04008   crop_info.height=(unsigned long) window_attributes.height;
04009   if (borders != MagickFalse)
04010     {
04011       /*
04012         Include border in image.
04013       */
04014       crop_info.x-=(long) window_attributes.border_width;
04015       crop_info.y-=(long) window_attributes.border_width;
04016       crop_info.width+=(unsigned long) (window_attributes.border_width << 1);
04017       crop_info.height+=(unsigned long) (window_attributes.border_width << 1);
04018     }
04019   /*
04020     Crop to root window.
04021   */
04022   if (crop_info.x < 0)
04023     {
04024       crop_info.width+=crop_info.x;
04025       crop_info.x=0;
04026     }
04027   if (crop_info.y < 0)
04028     {
04029       crop_info.height+=crop_info.y;
04030       crop_info.y=0;
04031     }
04032   display_width=XDisplayWidth(display,XDefaultScreen(display));
04033   if ((int) (crop_info.x+crop_info.width) > display_width)
04034     crop_info.width=(unsigned long) (display_width-crop_info.x);
04035   display_height=XDisplayHeight(display,XDefaultScreen(display));
04036   if ((int) (crop_info.y+crop_info.height) > display_height)
04037     crop_info.height=(unsigned long) (display_height-crop_info.y);
04038   /*
04039     Initialize window info attributes.
04040   */
04041   if (number_windows >= max_windows)
04042     {
04043       /*
04044         Allocate or resize window info buffer.
04045       */
04046       max_windows+=1024;
04047       if (window_info == (WindowInfo *) NULL)
04048         window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
04049           sizeof(*window_info));
04050       else
04051         window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
04052           max_windows,sizeof(*window_info));
04053     }
04054   if (window_info == (WindowInfo *) NULL)
04055     {
04056       ThrowXWindowFatalException(ResourceLimitError,
04057         "MemoryAllocationFailed","...");
04058       return((Image *) NULL);
04059     }
04060   id=number_windows++;
04061   window_info[id].window=window;
04062   window_info[id].visual=window_attributes.visual;
04063   window_info[id].colormap=window_attributes.colormap;
04064   window_info[id].bounds.x1=(short) crop_info.x;
04065   window_info[id].bounds.y1=(short) crop_info.y;
04066   window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
04067   window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
04068   crop_info.x-=x_offset;
04069   crop_info.y-=y_offset;
04070   window_info[id].crop_info=crop_info;
04071   if (level != 0)
04072     {
04073       unsigned int
04074         number_children;
04075 
04076       Window
04077         *children;
04078 
04079       /*
04080         Descend the window hierarchy.
04081       */
04082       status=XQueryTree(display,window,&root_window,&window_info[id].parent,
04083         &children,&number_children);
04084       for (i=0; i < id; i++)
04085         if ((window_info[i].window == window_info[id].parent) &&
04086             (window_info[i].visual == window_info[id].visual) &&
04087             (window_info[i].colormap == window_info[id].colormap))
04088           {
04089             if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
04090                 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
04091                 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
04092                 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
04093               {
04094                 /*
04095                   Eliminate windows not circumscribed by their parent.
04096                 */
04097                 number_windows--;
04098                 break;
04099               }
04100           }
04101       if ((status == True) && (number_children != 0))
04102         {
04103           for (i=0; i < (int) number_children; i++)
04104             (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
04105           (void) XFree((void *) children);
04106         }
04107     }
04108   if (level <= 1)
04109     {
04110       ColormapInfo
04111         *next;
04112 
04113       ExceptionInfo
04114         *exception;
04115 
04116       Image
04117         *composite_image,
04118         *image;
04119 
04120       int
04121         y;
04122 
04123       MagickBooleanType
04124         import;
04125 
04126       register int
04127         j,
04128         x;
04129 
04130       register PixelPacket
04131         *__restrict q;
04132 
04133       register unsigned long
04134         pixel;
04135 
04136       unsigned int
04137         number_colors;
04138 
04139       XColor
04140         *colors;
04141 
04142       XImage
04143         *ximage;
04144 
04145       /*
04146         Get X image for each window in the list.
04147       */
04148       image=NewImageList();
04149       for (id=0; id < number_windows; id++)
04150       {
04151         /*
04152           Does target window intersect top level window?
04153         */
04154         import=
04155           ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
04156            (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
04157            (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
04158            (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
04159           MagickTrue : MagickFalse;
04160         /*
04161           Is target window contained by another window with the same colormap?
04162         */
04163         for (j=0; j < id; j++)
04164           if ((window_info[id].visual == window_info[j].visual) &&
04165               (window_info[id].colormap == window_info[j].colormap))
04166             {
04167               if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
04168                   (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
04169                   (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
04170                   (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
04171                   import=MagickFalse;
04172             }
04173           else
04174             if ((window_info[id].visual != window_info[j].visual) ||
04175                 (window_info[id].colormap != window_info[j].colormap))
04176               {
04177                 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
04178                     (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
04179                     (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
04180                     (window_info[id].bounds.y1 < window_info[j].bounds.y2))
04181                   import=MagickTrue;
04182               }
04183         if (import == MagickFalse)
04184           continue;
04185         /*
04186           Get X image.
04187         */
04188         ximage=XGetImage(display,window_info[id].window,(int)
04189           window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
04190           (unsigned int) window_info[id].crop_info.width,(unsigned int)
04191           window_info[id].crop_info.height,AllPlanes,ZPixmap);
04192         if (ximage == (XImage *) NULL)
04193           continue;
04194         /*
04195           Initialize window colormap.
04196         */
04197         number_colors=0;
04198         colors=(XColor *) NULL;
04199         if (window_info[id].colormap != (Colormap) NULL)
04200           {
04201             ColormapInfo
04202               *p;
04203 
04204             /*
04205               Search colormap list for window colormap.
04206             */
04207             number_colors=(unsigned int) window_info[id].visual->map_entries;
04208             for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
04209               if (p->colormap == window_info[id].colormap)
04210                 break;
04211             if (p == (ColormapInfo *) NULL)
04212               {
04213                 /*
04214                   Get the window colormap.
04215                 */
04216                 colors=(XColor *) AcquireQuantumMemory(number_colors,
04217                   sizeof(*colors));
04218                 if (colors == (XColor *) NULL)
04219                   {
04220                     XDestroyImage(ximage);
04221                     return((Image *) NULL);
04222                   }
04223                 if ((window_info[id].visual->klass != DirectColor) &&
04224                     (window_info[id].visual->klass != TrueColor))
04225                   for (i=0; i < (int) number_colors; i++)
04226                   {
04227                     colors[i].pixel=(unsigned long) i;
04228                     colors[i].pad='\0';
04229                   }
04230                 else
04231                   {
04232                     unsigned long
04233                       blue,
04234                       blue_bit,
04235                       green,
04236                       green_bit,
04237                       red,
04238                       red_bit;
04239 
04240                     /*
04241                       DirectColor or TrueColor visual.
04242                     */
04243                     red=0;
04244                     green=0;
04245                     blue=0;
04246                     red_bit=window_info[id].visual->red_mask &
04247                       (~(window_info[id].visual->red_mask)+1);
04248                     green_bit=window_info[id].visual->green_mask &
04249                       (~(window_info[id].visual->green_mask)+1);
04250                     blue_bit=window_info[id].visual->blue_mask &
04251                       (~(window_info[id].visual->blue_mask)+1);
04252                     for (i=0; i < (int) number_colors; i++)
04253                     {
04254                       colors[i].pixel=red | green | blue;
04255                       colors[i].pad='\0';
04256                       red+=red_bit;
04257                       if (red > window_info[id].visual->red_mask)
04258                         red=0;
04259                       green+=green_bit;
04260                       if (green > window_info[id].visual->green_mask)
04261                         green=0;
04262                       blue+=blue_bit;
04263                       if (blue > window_info[id].visual->blue_mask)
04264                         blue=0;
04265                     }
04266                   }
04267                 (void) XQueryColors(display,window_info[id].colormap,colors,
04268                   (int) number_colors);
04269                 /*
04270                   Append colormap to colormap list.
04271                 */
04272                 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
04273                 if (p == (ColormapInfo *) NULL)
04274                   return((Image *) NULL);
04275                 p->colormap=window_info[id].colormap;
04276                 p->colors=colors;
04277                 p->next=colormap_info;
04278                 colormap_info=p;
04279               }
04280             colors=p->colors;
04281           }
04282         /*
04283           Allocate image structure.
04284         */
04285         composite_image=AcquireImage((ImageInfo *) NULL);
04286         if (composite_image == (Image *) NULL)
04287           {
04288             XDestroyImage(ximage);
04289             return((Image *) NULL);
04290           }
04291         /*
04292           Convert X image to MIFF format.
04293         */
04294         if ((window_info[id].visual->klass != TrueColor) &&
04295             (window_info[id].visual->klass != DirectColor))
04296           composite_image->storage_class=PseudoClass;
04297         composite_image->columns=(unsigned long) ximage->width;
04298         composite_image->rows=(unsigned long) ximage->height;
04299         exception=(&composite_image->exception);
04300         switch (composite_image->storage_class)
04301         {
04302           case DirectClass:
04303           default:
04304           {
04305             register unsigned long
04306               color,
04307               index;
04308 
04309             unsigned long
04310               blue_mask,
04311               blue_shift,
04312               green_mask,
04313               green_shift,
04314               red_mask,
04315               red_shift;
04316 
04317             /*
04318               Determine shift and mask for red, green, and blue.
04319             */
04320             red_mask=window_info[id].visual->red_mask;
04321             red_shift=0;
04322             while ((red_mask != 0) && ((red_mask & 0x01) == 0))
04323             {
04324               red_mask>>=1;
04325               red_shift++;
04326             }
04327             green_mask=window_info[id].visual->green_mask;
04328             green_shift=0;
04329             while ((green_mask != 0) && ((green_mask & 0x01) == 0))
04330             {
04331               green_mask>>=1;
04332               green_shift++;
04333             }
04334             blue_mask=window_info[id].visual->blue_mask;
04335             blue_shift=0;
04336             while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
04337             {
04338               blue_mask>>=1;
04339               blue_shift++;
04340             }
04341             /*
04342               Convert X image to DirectClass packets.
04343             */
04344             if ((number_colors != 0) &&
04345                 (window_info[id].visual->klass == DirectColor))
04346               for (y=0; y < (int) composite_image->rows; y++)
04347               {
04348                 q=QueueAuthenticPixels(composite_image,0,y,
04349                   composite_image->columns,1,exception);
04350                 if (q == (PixelPacket *) NULL)
04351                   break;
04352                 for (x=0; x < (int) composite_image->columns; x++)
04353                 {
04354                   pixel=XGetPixel(ximage,x,y);
04355                   index=(pixel >> red_shift) & red_mask;
04356                   q->red=ScaleShortToQuantum(colors[index].red);
04357                   index=(pixel >> green_shift) & green_mask;
04358                   q->green=ScaleShortToQuantum(colors[index].green);
04359                   index=(pixel >> blue_shift) & blue_mask;
04360                   q->blue=ScaleShortToQuantum(colors[index].blue);
04361                   q++;
04362                 }
04363                 if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
04364                   break;
04365               }
04366             else
04367               for (y=0; y < (int) composite_image->rows; y++)
04368               {
04369                 q=QueueAuthenticPixels(composite_image,0,y,
04370                   composite_image->columns,1,exception);
04371                 if (q == (PixelPacket *) NULL)
04372                   break;
04373                 for (x=0; x < (int) composite_image->columns; x++)
04374                 {
04375                   pixel=XGetPixel(ximage,x,y);
04376                   color=(pixel >> red_shift) & red_mask;
04377                   color=(65535UL*color)/red_mask;
04378                   q->red=ScaleShortToQuantum((unsigned short) color);
04379                   color=(pixel >> green_shift) & green_mask;
04380                   color=(65535UL*color)/green_mask;
04381                   q->green=ScaleShortToQuantum((unsigned short) color);
04382                   color=(pixel >> blue_shift) & blue_mask;
04383                   color=(65535UL*color)/blue_mask;
04384                   q->blue=ScaleShortToQuantum((unsigned short) color);
04385                   q++;
04386                 }
04387                 if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
04388                   break;
04389               }
04390             break;
04391           }
04392           case PseudoClass:
04393           {
04394             /*
04395               Create colormap.
04396             */
04397             if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
04398               {
04399                 XDestroyImage(ximage);
04400                 composite_image=DestroyImage(composite_image);
04401                 return((Image *) NULL);
04402               }
04403             for (i=0; i < (int) composite_image->colors; i++)
04404             {
04405               composite_image->colormap[colors[i].pixel].red=
04406                 ScaleShortToQuantum(colors[i].red);
04407               composite_image->colormap[colors[i].pixel].green=
04408                 ScaleShortToQuantum(colors[i].green);
04409               composite_image->colormap[colors[i].pixel].blue=
04410                 ScaleShortToQuantum(colors[i].blue);
04411             }
04412             /*
04413               Convert X image to PseudoClass packets.
04414             */
04415             for (y=0; y < (int) composite_image->rows; y++)
04416             {
04417               q=QueueAuthenticPixels(composite_image,0,y,composite_image->columns,1,exception);
04418               if (q == (PixelPacket *) NULL)
04419                 break;
04420               indexes=GetAuthenticIndexQueue(composite_image);
04421               for (x=0; x < (int) composite_image->columns; x++)
04422               {
04423                 index=(IndexPacket) XGetPixel(ximage,x,y);
04424                 indexes[x]=index;
04425                 *q++=composite_image->colormap[(long) index];
04426               }
04427               if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
04428                 break;
04429             }
04430             break;
04431           }
04432         }
04433         XDestroyImage(ximage);
04434         if (image == (Image *) NULL)
04435           {
04436             image=composite_image;
04437             continue;
04438           }
04439         /*
04440           Composite any children in back-to-front order.
04441         */
04442         (void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
04443           &x_offset,&y_offset,&child);
04444         x_offset-=(int) crop_info.x;
04445         if (x_offset < 0)
04446           x_offset=0;
04447         y_offset-=(int) crop_info.y;
04448         if (y_offset < 0)
04449           y_offset=0;
04450         (void) CompositeImage(image,CopyCompositeOp,composite_image,x_offset,
04451           y_offset);
04452       }
04453       /*
04454         Relinquish resources.
04455       */
04456       while (colormap_info != (ColormapInfo *) NULL)
04457       {
04458         next=colormap_info->next;
04459         colormap_info->colors=(XColor *)
04460           RelinquishMagickMemory(colormap_info->colors);
04461         colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
04462         colormap_info=next;
04463       }
04464       /*
04465         Relinquish resources and restore initial state.
04466       */
04467       window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
04468       max_windows=0;
04469       number_windows=0;
04470       colormap_info=(ColormapInfo *) NULL;
04471       return(image);
04472     }
04473   return((Image *) NULL);
04474 }
04475 
04476 /*
04477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04478 %                                                                             %
04479 %                                                                             %
04480 %                                                                             %
04481 %   X G e t W i n d o w I n f o                                               %
04482 %                                                                             %
04483 %                                                                             %
04484 %                                                                             %
04485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04486 %
04487 %  XGetWindowInfo() initializes the XWindowInfo structure.
04488 %
04489 %  The format of the XGetWindowInfo method is:
04490 %
04491 %      void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
04492 %        XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
04493 %        XResourceInfo *resource_info,XWindowInfo *window)
04494 %        resource_info,window)
04495 %
04496 %  A description of each parameter follows:
04497 %
04498 %    o display: Specifies a connection to an X server; returned from
04499 %      XOpenDisplay.
04500 %
04501 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
04502 %      returned from XGetVisualInfo.
04503 %
04504 %    o map_info: If map_type is specified, this structure is initialized
04505 %      with info from the Standard Colormap.
04506 %
04507 %    o pixel: Specifies a pointer to a XPixelInfo structure.
04508 %
04509 %    o font_info: Specifies a pointer to a XFontStruct structure.
04510 %
04511 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
04512 %
04513 */
04514 MagickExport void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
04515   XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
04516   XResourceInfo *resource_info,XWindowInfo *window)
04517 {
04518   /*
04519     Initialize window info.
04520   */
04521   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
04522   assert(display != (Display *) NULL);
04523   assert(visual_info != (XVisualInfo *) NULL);
04524   assert(map_info != (XStandardColormap *) NULL);
04525   assert(pixel != (XPixelInfo *) NULL);
04526   assert(resource_info != (XResourceInfo *) NULL);
04527   assert(window != (XWindowInfo *) NULL);
04528   if (window->id != (Window) NULL)
04529     {
04530       if (window->cursor != (Cursor) NULL)
04531         (void) XFreeCursor(display,window->cursor);
04532       if (window->busy_cursor != (Cursor) NULL)
04533         (void) XFreeCursor(display,window->busy_cursor);
04534       if (window->highlight_stipple != (Pixmap) NULL)
04535         (void) XFreePixmap(display,window->highlight_stipple);
04536       if (window->shadow_stipple != (Pixmap) NULL)
04537         (void) XFreePixmap(display,window->shadow_stipple);
04538       if (window->name == (char *) NULL)
04539         window->name=AcquireString("");
04540       if (window->icon_name == (char *) NULL)
04541         window->icon_name=AcquireString("");
04542     }
04543   else
04544     {
04545       /*
04546         Initialize these attributes just once.
04547       */
04548       window->id=(Window) NULL;
04549       if (window->name == (char *) NULL)
04550         window->name=AcquireString("");
04551       if (window->icon_name == (char *) NULL)
04552         window->icon_name=AcquireString("");
04553       window->x=XDisplayWidth(display,visual_info->screen) >> 1;
04554       window->y=XDisplayWidth(display,visual_info->screen) >> 1;
04555       window->ximage=(XImage *) NULL;
04556       window->matte_image=(XImage *) NULL;
04557       window->pixmap=(Pixmap) NULL;
04558       window->matte_pixmap=(Pixmap) NULL;
04559       window->mapped=MagickFalse;
04560       window->stasis=MagickFalse;
04561       window->shared_memory=MagickTrue;
04562       window->segment_info=(void *) NULL;
04563 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
04564       {
04565         XShmSegmentInfo
04566           *segment_info;
04567 
04568         if (window->segment_info == (void *) NULL)
04569           window->segment_info=AcquireQuantumMemory(2,sizeof(*segment_info));
04570         segment_info=(XShmSegmentInfo *) window->segment_info;
04571         segment_info[0].shmid=(-1);
04572         segment_info[0].shmaddr=(char *) NULL;
04573         segment_info[1].shmid=(-1);
04574         segment_info[1].shmaddr=(char *) NULL;
04575       }
04576 #endif
04577     }
04578   /*
04579     Initialize these attributes every time function is called.
04580   */
04581   window->screen=visual_info->screen;
04582   window->root=XRootWindow(display,visual_info->screen);
04583   window->visual=visual_info->visual;
04584   window->storage_class=(unsigned int) visual_info->klass;
04585   window->depth=(unsigned int) visual_info->depth;
04586   window->visual_info=visual_info;
04587   window->map_info=map_info;
04588   window->pixel_info=pixel;
04589   window->font_info=font_info;
04590   window->cursor=XCreateFontCursor(display,XC_left_ptr);
04591   window->busy_cursor=XCreateFontCursor(display,XC_watch);
04592   window->geometry=(char *) NULL;
04593   window->icon_geometry=(char *) NULL;
04594   if (resource_info->icon_geometry != (char *) NULL)
04595     (void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
04596   window->crop_geometry=(char *) NULL;
04597   window->flags=(unsigned long) PSize;
04598   window->width=1;
04599   window->height=1;
04600   window->min_width=1;
04601   window->min_height=1;
04602   window->width_inc=1;
04603   window->height_inc=1;
04604   window->border_width=resource_info->border_width;
04605   window->annotate_context=pixel->annotate_context;
04606   window->highlight_context=pixel->highlight_context;
04607   window->widget_context=pixel->widget_context;
04608   window->shadow_stipple=(Pixmap) NULL;
04609   window->highlight_stipple=(Pixmap) NULL;
04610   window->use_pixmap=MagickTrue;
04611   window->immutable=MagickFalse;
04612   window->shape=MagickFalse;
04613   window->data=0;
04614   window->mask=(unsigned long) (CWBackingStore | CWBackPixel | CWBackPixmap |
04615     CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
04616     CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
04617   window->attributes.background_pixel=pixel->background_color.pixel;
04618   window->attributes.background_pixmap=(Pixmap) NULL;
04619   window->attributes.bit_gravity=ForgetGravity;
04620   window->attributes.backing_store=WhenMapped;
04621   window->attributes.save_under=MagickTrue;
04622   window->attributes.border_pixel=pixel->border_color.pixel;
04623   window->attributes.colormap=map_info->colormap;
04624   window->attributes.cursor=window->cursor;
04625   window->attributes.do_not_propagate_mask=NoEventMask;
04626   window->attributes.event_mask=NoEventMask;
04627   window->attributes.override_redirect=MagickFalse;
04628   window->attributes.win_gravity=NorthWestGravity;
04629   window->orphan=MagickFalse;
04630 }
04631 
04632 /*
04633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04634 %                                                                             %
04635 %                                                                             %
04636 %                                                                             %
04637 %   X H i g h l i g h t E l l i p s e                                         %
04638 %                                                                             %
04639 %                                                                             %
04640 %                                                                             %
04641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04642 %
04643 %  XHighlightEllipse() puts a border on the X server around a region defined by
04644 %  highlight_info.
04645 %
04646 %  The format of the XHighlightEllipse method is:
04647 %
04648 %      void XHighlightEllipse(Display *display,Window window,
04649 %        GC annotate_context,const RectangleInfo *highlight_info)
04650 %
04651 %  A description of each parameter follows:
04652 %
04653 %    o display: Specifies a connection to an X server; returned from
04654 %      XOpenDisplay.
04655 %
04656 %    o window: Specifies a pointer to a Window structure.
04657 %
04658 %    o annotate_context: Specifies a pointer to a GC structure.
04659 %
04660 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
04661 %      contains the extents of any highlighting rectangle.
04662 %
04663 */
04664 MagickExport void XHighlightEllipse(Display *display,Window window,
04665   GC annotate_context,const RectangleInfo *highlight_info)
04666 {
04667   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
04668   assert(display != (Display *) NULL);
04669   assert(window != (Window) NULL);
04670   assert(annotate_context != (GC) NULL);
04671   assert(highlight_info != (RectangleInfo *) NULL);
04672   if ((highlight_info->width < 4) || (highlight_info->height < 4))
04673     return;
04674   (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
04675     (int) highlight_info->y,(unsigned int) highlight_info->width-1,
04676     (unsigned int) highlight_info->height-1,0,360*64);
04677   (void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
04678     (int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
04679     (unsigned int) highlight_info->height-3,0,360*64);
04680 }
04681 
04682 /*
04683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04684 %                                                                             %
04685 %                                                                             %
04686 %                                                                             %
04687 %   X H i g h l i g h t L i n e                                               %
04688 %                                                                             %
04689 %                                                                             %
04690 %                                                                             %
04691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04692 %
04693 %  XHighlightLine() puts a border on the X server around a region defined by
04694 %  highlight_info.
04695 %
04696 %  The format of the XHighlightLine method is:
04697 %
04698 %      void XHighlightLine(Display *display,Window window,GC annotate_context,
04699 %        const XSegment *highlight_info)
04700 %
04701 %  A description of each parameter follows:
04702 %
04703 %    o display: Specifies a connection to an X server; returned from
04704 %      XOpenDisplay.
04705 %
04706 %    o window: Specifies a pointer to a Window structure.
04707 %
04708 %    o annotate_context: Specifies a pointer to a GC structure.
04709 %
04710 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
04711 %      contains the extents of any highlighting rectangle.
04712 %
04713 */
04714 MagickExport void XHighlightLine(Display *display,Window window,
04715   GC annotate_context,const XSegment *highlight_info)
04716 {
04717   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
04718   assert(display != (Display *) NULL);
04719   assert(window != (Window) NULL);
04720   assert(annotate_context != (GC) NULL);
04721   assert(highlight_info != (XSegment *) NULL);
04722   (void) XDrawLine(display,window,annotate_context,highlight_info->x1,
04723     highlight_info->y1,highlight_info->x2,highlight_info->y2);
04724 }
04725 
04726 /*
04727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04728 %                                                                             %
04729 %                                                                             %
04730 %                                                                             %
04731 %   X H i g h l i g h t R e c t a n g l e                                     %
04732 %                                                                             %
04733 %                                                                             %
04734 %                                                                             %
04735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04736 %
04737 %  XHighlightRectangle() puts a border on the X server around a region defined
04738 %  by highlight_info.
04739 %
04740 %  The format of the XHighlightRectangle method is:
04741 %
04742 %      void XHighlightRectangle(Display *display,Window window,
04743 %        GC annotate_context,const RectangleInfo *highlight_info)
04744 %
04745 %  A description of each parameter follows:
04746 %
04747 %    o display: Specifies a connection to an X server; returned from
04748 %      XOpenDisplay.
04749 %
04750 %    o window: Specifies a pointer to a Window structure.
04751 %
04752 %    o annotate_context: Specifies a pointer to a GC structure.
04753 %
04754 %    o highlight_info: Specifies a pointer to a RectangleInfo structure.  It
04755 %      contains the extents of any highlighting rectangle.
04756 %
04757 */
04758 MagickExport void XHighlightRectangle(Display *display,Window window,
04759   GC annotate_context,const RectangleInfo *highlight_info)
04760 {
04761   assert(display != (Display *) NULL);
04762   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
04763   assert(window != (Window) NULL);
04764   assert(annotate_context != (GC) NULL);
04765   assert(highlight_info != (RectangleInfo *) NULL);
04766   if ((highlight_info->width < 4) || (highlight_info->height < 4))
04767     return;
04768   (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
04769     (int) highlight_info->y,(unsigned int) highlight_info->width-1,
04770     (unsigned int) highlight_info->height-1);
04771   (void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
04772     1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
04773     (unsigned int) highlight_info->height-3);
04774 }
04775 
04776 /*
04777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04778 %                                                                             %
04779 %                                                                             %
04780 %                                                                             %
04781 %   X I m p o r t I m a g e                                                   %
04782 %                                                                             %
04783 %                                                                             %
04784 %                                                                             %
04785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
04786 %
04787 %  XImportImage() reads an image from an X window.
04788 %
04789 %  The format of the XImportImage method is:
04790 %
04791 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
04792 %
04793 %  A description of each parameter follows:
04794 %
04795 %    o image_info: the image info.
04796 %
04797 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
04798 %
04799 */
04800 MagickExport Image *XImportImage(const ImageInfo *image_info,
04801   XImportInfo *ximage_info)
04802 {
04803   Colormap
04804     *colormaps;
04805 
04806   Display
04807     *display;
04808 
04809   Image
04810     *image;
04811 
04812   int
04813     number_colormaps,
04814     number_windows,
04815     x;
04816 
04817   RectangleInfo
04818     crop_info;
04819 
04820   Status
04821     status;
04822 
04823   Window
04824     *children,
04825     client,
04826     prior_target,
04827     root,
04828     target;
04829 
04830   XTextProperty
04831     window_name;
04832 
04833   /*
04834     Open X server connection.
04835   */
04836   assert(image_info != (const ImageInfo *) NULL);
04837   assert(image_info->signature == MagickSignature);
04838   if (image_info->debug != MagickFalse)
04839     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
04840       image_info->filename);
04841   assert(ximage_info != (XImportInfo *) NULL);
04842   display=XOpenDisplay(image_info->server_name);
04843   if (display == (Display *) NULL)
04844     {
04845       ThrowXWindowFatalException(XServerError,"UnableToOpenXServer",
04846         XDisplayName(image_info->server_name));
04847       return((Image *) NULL);
04848     }
04849   /*
04850     Set our forgiving exception handler.
04851   */
04852   (void) XSetErrorHandler(XError);
04853   /*
04854     Select target window.
04855   */
04856   crop_info.x=0;
04857   crop_info.y=0;
04858   crop_info.width=0;
04859   crop_info.height=0;
04860   root=XRootWindow(display,XDefaultScreen(display));
04861   target=(Window) NULL;
04862   if ((image_info->filename != (char *) NULL) &&
04863       (*image_info->filename != '\0'))
04864     {
04865       if (LocaleCompare(image_info->filename,"root") == 0)
04866         target=root;
04867       else
04868         {
04869           /*
04870             Select window by ID or name.
04871           */
04872           if (isdigit((unsigned char) *image_info->filename) != 0)
04873             target=XWindowByID(display,root,(Window)
04874               strtol(image_info->filename,(char **) NULL,0));
04875           if (target == (Window) NULL)
04876             target=XWindowByName(display,root,image_info->filename);
04877           if (target == (Window) NULL)
04878             ThrowXWindowFatalException(XServerError,
04879               "NoWindowWithSpecifiedIDExists",image_info->filename);
04880         }
04881     }
04882   /*
04883     If target window is not defined, interactively select one.
04884   */
04885   prior_target=target;
04886   if (target == (Window) NULL)
04887     target=XSelectWindow(display,&crop_info);
04888   if (target == (Window) NULL)
04889     ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
04890       image_info->filename);
04891   client=target;   /* obsolete */
04892   if (target != root)
04893     {
04894       unsigned int
04895         d;
04896 
04897       status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
04898       if (status != False)
04899         {
04900           for ( ; ; )
04901           {
04902             Window
04903               parent;
04904 
04905             /*
04906               Find window manager frame.
04907             */
04908             status=XQueryTree(display,target,&root,&parent,&children,&d);
04909             if ((status != False) && (children != (Window *) NULL))
04910               (void) XFree((char *) children);
04911             if ((status == False) || (parent == (Window) NULL) ||
04912                 (parent == root))
04913               break;
04914             target=parent;
04915           }
04916           /*
04917             Get client window.
04918           */
04919           client=XClientWindow(display,target);
04920           if (ximage_info->frame == MagickFalse)
04921             target=client;
04922           if ((ximage_info->frame == MagickFalse) &&
04923               (prior_target != MagickFalse))
04924             target=prior_target;
04925           XDelay(display,SuspendTime << 4);
04926         }
04927     }
04928   if (ximage_info->screen)
04929     {
04930       int
04931         y;
04932 
04933       Window
04934         child;
04935 
04936       XWindowAttributes
04937         window_attributes;
04938 
04939       /*
04940         Obtain window image directly from screen.
04941       */
04942       status=XGetWindowAttributes(display,target,&window_attributes);
04943       if (status == False)
04944         {
04945           ThrowXWindowFatalException(XServerError,
04946             "UnableToReadXWindowAttributes",image_info->filename);
04947           (void) XCloseDisplay(display);
04948           return((Image *) NULL);
04949         }
04950       (void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
04951       crop_info.x=x;
04952       crop_info.y=y;
04953       crop_info.width=(unsigned long) window_attributes.width;
04954       crop_info.height=(unsigned long) window_attributes.height;
04955       if (ximage_info->borders)
04956         {
04957           /*
04958             Include border in image.
04959           */
04960           crop_info.x-=window_attributes.border_width;
04961           crop_info.y-=window_attributes.border_width;
04962           crop_info.width+=window_attributes.border_width << 1;
04963           crop_info.height+=window_attributes.border_width << 1;
04964         }
04965       target=root;
04966     }
04967   /*
04968     If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
04969   */
04970   number_windows=0;
04971   status=XGetWMColormapWindows(display,target,&children,&number_windows);
04972   if ((status == True) && (number_windows > 0))
04973     {
04974       ximage_info->descend=MagickTrue;
04975       (void) XFree ((char *) children);
04976     }
04977   colormaps=XListInstalledColormaps(display,target,&number_colormaps);
04978   if (number_colormaps > 0)
04979     {
04980       if (number_colormaps > 1)
04981         ximage_info->descend=MagickTrue;
04982       (void) XFree((char *) colormaps);
04983     }
04984   /*
04985     Alert the user not to alter the screen.
04986   */
04987   if (ximage_info->silent == MagickFalse)
04988     (void) XBell(display,0);
04989   /*
04990     Get image by window id.
04991   */
04992   (void) XGrabServer(display);
04993   image=XGetWindowImage(display,target,ximage_info->borders,
04994     ximage_info->descend ? 1U : 0U);
04995   (void) XUngrabServer(display);
04996   if (image == (Image *) NULL)
04997     ThrowXWindowFatalException(XServerError,"UnableToReadXWindowImage",
04998       image_info->filename)
04999   else
05000     {
05001       (void) CopyMagickString(image->filename,image_info->filename,
05002         MaxTextExtent);
05003       if ((crop_info.width != 0) && (crop_info.height != 0))
05004         {
05005           Image
05006             *clone_image,
05007             *crop_image;
05008 
05009           /*
05010             Crop image as defined by the cropping rectangle.
05011           */
05012           clone_image=CloneImage(image,0,0,MagickTrue,&image->exception);
05013           if (clone_image != (Image *) NULL)
05014             {
05015               crop_image=CropImage(clone_image,&crop_info,&image->exception);
05016               if (crop_image != (Image *) NULL)
05017                 {
05018                   image=DestroyImage(image);
05019                   image=crop_image;
05020                 }
05021             }
05022         }
05023       status=XGetWMName(display,target,&window_name);
05024       if (status == True)
05025         {
05026           if ((image_info->filename != (char *) NULL) &&
05027               (*image_info->filename == '\0'))
05028             (void) CopyMagickString(image->filename,(char *) window_name.value,
05029               (size_t) window_name.nitems+1);
05030           (void) XFree((void *) window_name.value);
05031         }
05032     }
05033   if (ximage_info->silent == MagickFalse)
05034     {
05035       /*
05036         Alert the user we're done.
05037       */
05038       (void) XBell(display,0);
05039       (void) XBell(display,0);
05040     }
05041   (void) XCloseDisplay(display);
05042   return(image);
05043 }
05044 
05045 /*
05046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
05047 %                                                                             %
05048 %                                                                             %
05049 %                                                                             %
05050 %   X I n i t i a l i z e W i n d o w s                                       %
05051 %                                                                             %
05052 %                                                                             %
05053 %                                                                             %
05054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
05055 %
05056 %  XInitializeWindows() initializes the XWindows structure.
05057 %
05058 %  The format of the XInitializeWindows method is:
05059 %
05060 %      XWindows *XInitializeWindows(Display *display,
05061 %        XResourceInfo *resource_info)
05062 %
05063 %  A description of each parameter follows:
05064 %
05065 %    o windows: XInitializeWindows returns a pointer to a XWindows structure.
05066 %
05067 %    o display: Specifies a connection to an X server;  returned from
05068 %      XOpenDisplay.
05069 %
05070 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
05071 %
05072 */
05073 MagickExport XWindows *XInitializeWindows(Display *display,
05074   XResourceInfo *resource_info)
05075 {
05076   Window
05077     root_window;
05078 
05079   XWindows
05080     *windows;
05081 
05082   /*
05083     Allocate windows structure.
05084   */
05085   windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
05086   if (windows == (XWindows *) NULL)
05087     {
05088       ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
05089         "...");
05090       return((XWindows *) NULL);
05091     }
05092   (void) ResetMagickMemory(windows,0,sizeof(*windows));
05093   windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
05094     sizeof(*windows->pixel_info));
05095   windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
05096     sizeof(*windows->icon_pixel));
05097   windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
05098     sizeof(*windows->icon_resources));
05099   if ((windows->pixel_info == (XPixelInfo *) NULL) ||
05100       (windows->icon_pixel == (XPixelInfo *) NULL) ||
05101       (windows->icon_resources == (XResourceInfo *) NULL))
05102     {
05103       ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
05104         "...");
05105       return((XWindows *) NULL);
05106     }
05107   /*
05108     Initialize windows structure.
05109   */
05110   windows->display=display;
05111   windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
05112   windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
05113   windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
05114   windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
05115   windows->im_remote_command=
05116     XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
05117   windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
05118   windows->im_update_colormap=
05119     XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
05120   windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
05121   windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
05122   windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
05123   windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
05124   windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
05125 #if defined(__WINDOWS__)
05126   (void) XSynchronize(display,IsWindows95());
05127 #endif
05128   if (IsEventLogging())
05129     {
05130       (void) XSynchronize(display,MagickTrue);
05131       (void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
05132         GetMagickVersion((unsigned long *) NULL));
05133       (void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
05134       (void) LogMagickEvent(X11Event,GetMagickModule(),
05135         "  Window Manager: 0x%lx",windows->wm_protocols);
05136       (void) LogMagickEvent(X11Event,GetMagickModule(),
05137         "    delete window: 0x%lx",windows->wm_delete_window);
05138       (void) LogMagickEvent(X11Event,GetMagickModule(),"    take focus: 0x%lx",
05139         windows->wm_take_focus);
05140       (void) LogMagickEvent(X11Event,GetMagickModule(),"  ImageMagick: 0x%lx",
05141         windows->im_protocols);
05142       (void) LogMagickEvent(X11Event,GetMagickModule(),
05143         "    remote command: 0x%lx",windows->im_remote_command);
05144       (void) LogMagickEvent(X11Event,GetMagickModule(),
05145         "    update widget: 0x%lx",windows->im_update_widget);
05146       (void) LogMagickEvent(X11Event,GetMagickModule(),
05147         "    update colormap: 0x%lx",windows->im_update_colormap);
05148       (void) LogMagickEvent(X11Event,GetMagickModule(),
05149         "    former image: 0x%lx",windows->im_former_image);
05150       (void) LogMagickEvent(X11Event,GetMagickModule(),"    next image: 0x%lx",
05151         windows->im_next_image);
05152       (void) LogMagickEvent(X11Event,GetMagickModule(),
05153         "    retain colors: 0x%lx",windows->im_retain_colors);
05154       (void) LogMagickEvent(X11Event,GetMagickModule(),"    exit: 0x%lx",
05155         windows->im_exit);
05156       (void) LogMagickEvent(X11Event,GetMagickModule(),"  Drag and Drop: 0x%lx",
05157         windows->dnd_protocols);
05158     }
05159   /*
05160     Allocate standard colormap.
05161   */
05162   windows->map_info=XAllocStandardColormap();
05163   windows->icon_map=XAllocStandardColormap();
05164   if ((windows->map_info == (XStandardColormap *) NULL) ||
05165       (windows->icon_map == (XStandardColormap *) NULL))
05166     ThrowXWindowFatalException(ResourceLimitFatalError,
05167       "MemoryAllocationFailed","...");
05168   windows->map_info->colormap=(Colormap) NULL;
05169   windows->icon_map->colormap=(Colormap) NULL;
05170   windows->pixel_info->pixels=(unsigned long *) NULL;
05171   windows->pixel_info->annotate_context=(GC) NULL;
05172   windows->pixel_info->highlight_context=(GC) NULL;
05173   windows->pixel_info->widget_context=(GC) NULL;
05174   windows->font_info=(XFontStruct *) NULL;
05175   windows->icon_pixel->annotate_context=(GC) NULL;
05176   windows->icon_pixel->pixels=(unsigned long *) NULL;
05177   /*
05178     Allocate visual.
05179   */
05180   *windows->icon_resources=(*resource_info);
05181   windows->icon_resources->visual_type=(char *) "default";
05182   windows->icon_resources->colormap=SharedColormap;
05183   windows->visual_info=
05184     XBestVisualInfo(display,windows->map_info,resource_info);
05185   windows->icon_visual=
05186     XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
05187   if ((windows->visual_info == (XVisualInfo *) NULL) ||
05188       (windows->icon_visual == (XVisualInfo *) NULL))
05189     ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
05190       resource_info->visual_type);
05191   if (IsEventLogging())
05192     {
05193       (void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
05194       (void) LogMagickEvent(X11Event,GetMagickModule(),"  visual id: 0x%lx",
05195         windows->visual_info->visualid);
05196       (void) LogMagickEvent(X11Event,GetMagickModule(),"  class: %s",
05197         XVisualClassName(windows->visual_info->klass));
05198       (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d planes",
05199         windows->visual_info->depth);
05200       (void) LogMagickEvent(X11Event,GetMagickModule(),
05201         "  size of colormap: %d entries",windows->visual_info->colormap_size);
05202       (void) LogMagickEvent(X11Event,GetMagickModule(),
05203         "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",
05204         windows->visual_info->red_mask,windows->visual_info->green_mask,
05205         windows->visual_info->blue_mask);
05206       (void) LogMagickEvent(X11Event,GetMagickModule(),
05207         "  significant bits in color: %d bits",
05208         windows->visual_info->bits_per_rgb);
05209     }
05210   /*
05211     Allocate class and manager hints.
05212   */
05213   windows->class_hints=XAllocClassHint();
05214   windows->manager_hints=XAllocWMHints();
05215   if ((windows->class_hints == (XClassHint *) NULL) ||
05216       (windows->manager_hints == (XWMHints *) NULL))
05217     ThrowXWindowFatalException(ResourceLimitFatalError,
05218       "MemoryAllocationFailed","...");
05219   /*
05220     Determine group leader if we have one.
05221   */
05222   root_window=XRootWindow(display,windows->visual_info->screen);
05223   windows->group_leader.id=(Window) NULL;
05224   if (resource_info->window_group != (char *) NULL)
05225     {
05226       if (isdigit((unsigned char) *resource_info->window_group) != 0)
05227         windows->group_leader.id=XWindowByID(display,root_window,(Window)
05228           strtol((char *) resource_info->window_group,(char **) NULL,0));
05229       if (windows->group_leader.id == (Window) NULL)
05230         windows->group_leader.id=
05231           XWindowByName(display,root_window,resource_info->window_group);
05232     }
05233   return(windows);
05234 }
05235 
05236 /*
05237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
05238 %                                                                             %
05239 %                                                                             %
05240 %                                                                             %
05241 %   X M a k e C u r s o r                                                     %
05242 %                                                                             %
05243 %                                                                             %
05244 %                                                                             %
05245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
05246 %
05247 %  XMakeCursor() creates a crosshairs X11 cursor.
05248 %
05249 %  The format of the XMakeCursor method is:
05250 %
05251 %      Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
05252 %        char *background_color,char *foreground_color)
05253 %
05254 %  A description of each parameter follows:
05255 %
05256 %    o display: Specifies a connection to an X server;  returned from
05257 %      XOpenDisplay.
05258 %
05259 %    o window: Specifies the ID of the window for which the cursor is
05260 %      assigned.
05261 %
05262 %    o colormap: Specifies the ID of the colormap from which the background
05263 %      and foreground color will be retrieved.
05264 %
05265 %    o background_color: Specifies the color to use for the cursor background.
05266 %
05267 %    o foreground_color: Specifies the color to use for the cursor foreground.
05268 %
05269 */
05270 MagickExport Cursor XMakeCursor(Display *display,Window window,
05271   Colormap colormap,char *background_color,char *foreground_color)
05272 {
05273 #define scope_height 17
05274 #define scope_x_hot 8
05275 #define scope_y_hot 8
05276 #define scope_width 17
05277 
05278   static const unsigned char
05279     scope_bits[] =
05280     {
05281       0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
05282       0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
05283       0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
05284       0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
05285       0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
05286     },
05287     scope_mask_bits[] =
05288     {
05289       0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
05290       0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
05291       0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
05292       0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
05293       0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
05294     };
05295 
05296   Cursor
05297     cursor;
05298 
05299   Pixmap
05300     mask,
05301     source;
05302 
05303   XColor
05304     background,
05305     foreground;
05306 
05307   assert(display != (Display *) NULL);
05308   assert(window != (Window) NULL);
05309   assert(colormap != (Colormap) NULL);
05310   assert(background_color != (char *) NULL);
05311   assert(foreground_color != (char *) NULL);
05312   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
05313   source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
05314     scope_height);
05315   mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
05316     scope_width,scope_height);
05317   if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
05318     {
05319       ThrowXWindowFatalException(XServerError,"UnableToCreatePixmap","...");
05320       return((Cursor) NULL);
05321     }
05322   (void) XParseColor(display,colormap,background_color,&background);
05323   (void) XParseColor(display,colormap,foreground_color,&foreground);
05324   cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
05325     scope_x_hot,scope_y_hot);
05326   (void) XFreePixmap(display,source);
05327   (void) XFreePixmap(display,mask);
05328   return(cursor);
05329 }
05330 
05331 /*
05332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
05333 %                                                                             %
05334 %                                                                             %
05335 %                                                                             %
05336 %   X M a k e I m a g e                                                       %
05337 %                                                                             %
05338 %                                                                             %
05339 %                                                                             %
05340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
05341 %
05342 %  XMakeImage() creates an X11 image.  If the image size differs from the X11
05343 %  image size, the image is first resized.
05344 %
05345 %  The format of the XMakeImage method is:
05346 %
05347 %      MagickBooleanType XMakeImage(Display *display,
05348 %        const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
05349 %        unsigned int width,unsigned int height)
05350 %
05351 %  A description of each parameter follows:
05352 %
05353 %    o display: Specifies a connection to an X server; returned from
05354 %      XOpenDisplay.
05355 %
05356 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
05357 %
05358 %    o window: Specifies a pointer to a XWindowInfo structure.
05359 %
05360 %    o image: the image.
05361 %
05362 %    o width: Specifies the width in pixels of the rectangular area to
05363 %      display.
05364 %
05365 %    o height: Specifies the height in pixels of the rectangular area to
05366 %      display.
05367 %
05368 */
05369 MagickExport MagickBooleanType XMakeImage(Display *display,
05370   const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
05371   unsigned int width,unsigned int height)
05372 {
05373 #define CheckOverflowException(length,width,height) \
05374   (((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
05375 
05376   int
05377     depth,
05378     format;
05379 
05380   size_t
05381     length;
05382 
05383   XImage
05384     *matte_image,
05385     *ximage;
05386 
05387   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
05388   assert(display != (Display *) NULL);
05389   assert(resource_info != (XResourceInfo *) NULL);
05390   assert(window != (XWindowInfo *) NULL);
05391   assert(width != 0);
05392   assert(height != 0);
05393   if ((window->width == 0) || (window->height == 0))
05394     return(MagickFalse);
05395   /*
05396     Apply user transforms to the image.
05397   */
05398   (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
05399   (void) XFlush(display);
05400   depth=(int) window->depth;
05401   if (window->destroy)
05402     window->image=DestroyImage(window->image);
05403   window->image=image;
05404   window->destroy=MagickFalse;
05405   if (window->image != (Image *) NULL)
05406     {
05407       if (window->crop_geometry != (char *) NULL)
05408         {
05409           Image
05410             *crop_image;
05411 
05412           RectangleInfo
05413             crop_info;
05414 
05415           /*
05416             Crop image.
05417           */
05418           window->image->page.x=0;
05419           window->image->page.y=0;
05420           (void) ParsePageGeometry(window->image,window->crop_geometry,
05421             &crop_info,&image->exception);
05422           crop_image=CropImage(window->image,&crop_info,&image->exception);
05423           if (crop_image != (Image *) NULL)
05424             {
05425               if (window->image != image)
05426                 window->image=DestroyImage(window->image);
05427               window->image=crop_image;
05428               window->destroy=MagickTrue;
05429             }
05430         }
05431       if ((width != (unsigned int) window->image->columns) ||
05432           (height != (unsigned int) window->image->rows))
05433         {
05434           Image
05435             *resize_image;
05436 
05437           /*
05438             Resize image.
05439           */
05440           resize_image=NewImageList();
05441           if (window->pixel_info->colors != 0)
05442             resize_image=SampleImage(window->image,width,height,
05443               &image->exception);
05444           else
05445             resize_image=ThumbnailImage(window->image,width,height,
05446               &image->exception);
05447           if (resize_image != (Image *) NULL)
05448             {
05449               if (window->image != image)
05450                 window->image=DestroyImage(window->image);
05451               window->image=resize_image;
05452               window->destroy=MagickTrue;
05453             }
05454         }
05455       width=(unsigned int) window->image->columns;
05456       height=(unsigned int) window->image->rows;
05457     }
05458   /*
05459     Create X image.
05460   */
05461   ximage=(XImage *) NULL;
05462   format=(depth == 1) ? XYBitmap : ZPixmap;
05463 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
05464   if (window->shared_memory != MagickFalse)
05465     {
05466       XShmSegmentInfo
05467         *segment_info;
05468 
05469       segment_info=(XShmSegmentInfo *) window->segment_info;
05470       segment_info[1].shmid=(-1);
05471       segment_info[1].shmaddr=(char *) NULL;
05472       ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
05473         (char *) NULL,&segment_info[1],width,height);
05474       if (ximage == (XImage *) NULL)
05475         window->shared_memory=MagickFalse;
05476       length=(size_t) ximage->bytes_per_line*ximage->height;
05477       if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
05478         window->shared_memory=MagickFalse;
05479       if (window->shared_memory != MagickFalse)
05480         segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
05481       if (window->shared_memory != MagickFalse)
05482         segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
05483       if (segment_info[1].shmid < 0)
05484         window->shared_memory=MagickFalse;
05485       if (window->shared_memory != MagickFalse)
05486         (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
05487       else
05488         {
05489           if (ximage != (XImage *) NULL)
05490             XDestroyImage(ximage);
05491           ximage=(XImage *) NULL;
05492           if (segment_info[1].shmaddr)
05493             {
05494               (void) shmdt(segment_info[1].shmaddr);
05495               segment_info[1].shmaddr=(char *) NULL;
05496             }
05497           if (segment_info[1].shmid >= 0)
05498             {
05499               (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
05500               segment_info[1].shmid=(-1);
05501             }
05502         }
05503     }
05504 #endif
05505   /*
05506     Allocate X image pixel data.
05507   */
05508 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
05509   if (window->shared_memory)
05510     {
05511       Status
05512         status;
05513 
05514       XShmSegmentInfo
05515         *segment_info;
05516 
05517       (void) XSync(display,MagickFalse);
05518       xerror_alert=MagickFalse;
05519       segment_info=(XShmSegmentInfo *) window->segment_info;
05520       ximage->data=segment_info[1].shmaddr;
05521       segment_info[1].readOnly=MagickFalse;
05522       status=XShmAttach(display,&segment_info[1]);
05523       if (status != False)
05524         (void) XSync(display,MagickFalse);
05525       if ((status == False) || (xerror_alert != MagickFalse))
05526         {
05527           window->shared_memory=MagickFalse;
05528           if (status != False)
05529             XShmDetach(display,&segment_info[1]);
05530           if (ximage != (XImage *) NULL)
05531             {
05532               ximage->data=NULL;
05533               XDestroyImage(ximage);
05534               ximage=(XImage *) NULL;
05535             }
05536           if (segment_info[1].shmid >= 0)
05537             {
05538               if (segment_info[1].shmaddr != NULL)
05539                 (void) shmdt(segment_info[1].shmaddr);
05540               (void) shmctl(segment_info[1].shmid,IPC_RMID,0);
05541               segment_info[1].shmid=(-1);
05542               segment_info[1].shmaddr=(char *) NULL;
05543             }
05544         }
05545     }
05546 #endif
05547   if (window->shared_memory == MagickFalse)
05548     ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
05549       (char *) NULL,width,height,XBitmapPad(display),0);
05550   if (ximage == (XImage *) NULL)
05551     {
05552       /*
05553         Unable to create X image.
05554       */
05555       (void) XCheckDefineCursor(display,window->id,window->cursor);
05556       return(MagickFalse);
05557     }
05558   length=(size_t) ximage->bytes_per_line*ximage->height;
05559   if (IsEventLogging())
05560     {
05561       (void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
05562       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %dx%d",
05563         ximage->width,ximage->height);
05564       (void) LogMagickEvent(X11Event,GetMagickModule(),"  format: %d",
05565         ximage->format);
05566       (void) LogMagickEvent(X11Event,GetMagickModule(),"  byte order: %d",
05567         ximage->byte_order);
05568       (void) LogMagickEvent(X11Event,GetMagickModule(),
05569         "  bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
05570         ximage->bitmap_bit_order,ximage->bitmap_pad);
05571       (void) LogMagickEvent(X11Event,GetMagickModule(),"  depth: %d",
05572         ximage->depth);
05573       (void) LogMagickEvent(X11Event,GetMagickModule(),"  bytes per line: %d",
05574         ximage->bytes_per_line);
05575       (void) LogMagickEvent(X11Event,GetMagickModule(),"  bits per pixel: %d",
05576         ximage->bits_per_pixel);
05577       (void) LogMagickEvent(X11Event,GetMagickModule(),
05578         "  red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
05579         ximage->green_mask,ximage->blue_mask);
05580     }
05581   if (window->shared_memory == MagickFalse)
05582     {
05583       if (ximage->format != XYBitmap)
05584         ximage->data=(char *) AcquireQuantumMemory((size_t)
05585           ximage->bytes_per_line,(size_t) ximage->height);
05586       else
05587         ximage->data=(char *) AcquireQuantumMemory((size_t)
05588           ximage->bytes_per_line*ximage->depth,(size_t) ximage->height);
05589     }
05590   if (ximage->data == (char *) NULL)
05591     {
05592       /*
05593         Unable to allocate pixel data.
05594       */
05595       XDestroyImage(ximage);
05596       ximage=(XImage *) NULL;
05597       (void) XCheckDefineCursor(display,window->id,window->cursor);
05598       return(MagickFalse);
05599     }
05600   if (window->ximage != (XImage *) NULL)
05601     {
05602       /*
05603         Destroy previous X image.
05604       */
05605       length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
05606 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
05607       if (window->segment_info != (XShmSegmentInfo *) NULL)
05608         {
05609           XShmSegmentInfo
05610             *segment_info;
05611 
05612           segment_info=(XShmSegmentInfo *) window->segment_info;
05613           if (segment_info[0].shmid >= 0)
05614             {
05615               (void) XSync(display,MagickFalse);
05616               (void) XShmDetach(display,&segment_info[0]);
05617               (void) XSync(display,MagickFalse);
05618               if (segment_info[0].shmaddr != (char *) NULL)
05619                 (void) shmdt(segment_info[0].shmaddr);
05620               (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
05621               segment_info[0].shmid=(-1);
05622               segment_info[0].shmaddr=(char *) NULL;
05623               window->ximage->data=(char *) NULL;
05624           }
05625         }
05626 #endif
05627       if (window->ximage->data != (char *) NULL)
05628         free(window->ximage->data);
05629       window->ximage->data=(char *) NULL;
05630       XDestroyImage(window->ximage);
05631       window->ximage=(XImage *) NULL;
05632     }
05633 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
05634   if (window->segment_info != (XShmSegmentInfo *) NULL)
05635     {
05636       XShmSegmentInfo
05637         *segment_info;
05638 
05639       segment_info=(XShmSegmentInfo *) window->segment_info;
05640       segment_info[0]=segment_info[1];
05641     }
05642 #endif
05643   window->ximage=ximage;
05644   matte_image=(XImage *) NULL;
05645   if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
05646     if ((window->image->matte != MagickFalse) &&
05647         ((long) width <= XDisplayWidth(display,window->screen)) &&
05648         ((long) height <= XDisplayHeight(display,window->screen)))
05649       {
05650         /*
05651           Create matte image.
05652         */
05653         matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
05654           (char *) NULL,width,height,XBitmapPad(display),0);
05655         if (IsEventLogging())
05656           {
05657             (void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
05658             (void) LogMagickEvent(X11Event,GetMagickModule(),
05659               "  width, height: %dx%d",matte_image->width,matte_image->height);
05660           }
05661         if (matte_image != (XImage *) NULL)
05662           {
05663             /*
05664               Allocate matte image pixel data.
05665             */
05666             matte_image->data=(char *) AcquireQuantumMemory((size_t)
05667               matte_image->bytes_per_line*matte_image->depth,
05668               (size_t) matte_image->height);
05669             if (matte_image->data == (char *) NULL)
05670               {
05671                 XDestroyImage(matte_image);
05672                 matte_image=(XImage *) NULL;
05673               }
05674           }
05675       }
05676   if (window->matte_image != (XImage *) NULL)
05677     {
05678       /*
05679         Free matte image.
05680       */
05681       if (window->matte_image->data != (char *) NULL)
05682         free(window->matte_image->data);
05683       window->matte_image->data=(char *) NULL;
05684       XDestroyImage(window->matte_image);
05685       window->matte_image=(XImage *) NULL;
05686     }
05687   window->matte_image=matte_image;
05688   if (window->matte_pixmap != (Pixmap) NULL)
05689     {
05690       (void) XFreePixmap(display,window->matte_pixmap);
05691       window->matte_pixmap=(Pixmap) NULL;
05692 #if defined(MAGICKCORE_HAVE_SHAPE)
05693       if (window->shape != MagickFalse)
05694         XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
05695 #endif
05696     }
05697   window->stasis=MagickFalse;
05698   /*
05699     Convert pixels to X image data.
05700   */
05701   if (window->image != (Image *) NULL)
05702     {
05703       if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
05704           (ximage->bitmap_bit_order == LSBFirst)))
05705         XMakeImageLSBFirst(resource_info,window,window->image,ximage,
05706           matte_image);
05707       else
05708         XMakeImageMSBFirst(resource_info,window,window->image,ximage,
05709           matte_image);
05710     }
05711   if (window->matte_image != (XImage *) NULL)
05712     {
05713       /*
05714         Create matte pixmap.
05715       */
05716       window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
05717       if (window->matte_pixmap != (Pixmap) NULL)
05718         {
05719           GC
05720             graphics_context;
05721 
05722           XGCValues
05723             context_values;
05724 
05725           /*
05726             Copy matte image to matte pixmap.
05727           */
05728           context_values.background=1;
05729           context_values.foreground=0;
05730           graphics_context=XCreateGC(display,window->matte_pixmap,
05731             (unsigned long) (GCBackground | GCForeground),&context_values);
05732           (void) XPutImage(display,window->matte_pixmap,graphics_context,
05733             window->matte_image,0,0,0,0,width,height);
05734           (void) XFreeGC(display,graphics_context);
05735 #if defined(MAGICKCORE_HAVE_SHAPE)
05736           if (window->shape != MagickFalse)
05737             XShapeCombineMask(display,window->id,ShapeBounding,0,0,
05738               window->matte_pixmap,ShapeSet);
05739 #endif
05740         }
05741       }
05742   (void) XMakePixmap(display,resource_info,window);
05743   /*
05744     Restore cursor.
05745   */
05746   (void) XCheckDefineCursor(display,window->id,window->cursor);
05747   return(MagickTrue);
05748 }
05749 
05750 /*
05751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
05752 %                                                                             %
05753 %                                                                             %
05754 %                                                                             %
05755 +   X M a k e I m a g e L S B F i r s t                                       %
05756 %                                                                             %
05757 %                                                                             %
05758 %                                                                             %
05759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
05760 %
05761 %  XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
05762 %  pixels are copied in least-significant bit and byte first order.  The
05763 %  server's scanline pad is respected.  Rather than using one or two general
05764 %  cases, many special cases are found here to help speed up the image
05765 %  conversion.
05766 %
05767 %  The format of the XMakeImageLSBFirst method is:
05768 %
05769 %      void XMakeImageLSBFirst(Display *display,XWindows *windows)
05770 %
05771 %  A description of each parameter follows:
05772 %
05773 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
05774 %
05775 %    o window: Specifies a pointer to a XWindowInfo structure.
05776 %
05777 %    o image: the image.
05778 %
05779 %    o ximage: Specifies a pointer to a XImage structure;  returned from
05780 %      XCreateImage.
05781 %
05782 %    o matte_image: Specifies a pointer to a XImage structure;  returned from
05783 %      XCreateImage.
05784 %
05785 */
05786 static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
05787   const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
05788 {
05789   Image
05790     *canvas;
05791 
05792   int
05793     y;
05794 
05795   register const IndexPacket
05796     *indexes;
05797 
05798   register const PixelPacket
05799     *p;
05800 
05801   register int
05802     x;
05803 
05804   register unsigned char
05805     *q;
05806 
05807   unsigned char
05808     bit,
05809     byte;
05810 
05811   unsigned int
05812     scanline_pad;
05813 
05814   unsigned long
05815     pixel,
05816     *pixels;
05817 
05818   XStandardColormap
05819     *map_info;
05820 
05821   assert(resource_info != (XResourceInfo *) NULL);
05822   assert(window != (XWindowInfo *) NULL);
05823   assert(image != (Image *) NULL);
05824   if (image->debug != MagickFalse)
05825     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
05826   canvas=image;
05827   if ((image->storage_class == DirectClass) && (image->matte != MagickFalse))
05828     {
05829       char
05830         size[MaxTextExtent];
05831 
05832       Image
05833         *pattern;
05834 
05835       ImageInfo
05836         *image_info;
05837 
05838       image_info=AcquireImageInfo();
05839       (void) CopyMagickString(image_info->filename,
05840         resource_info->image_info->texture != (char *) NULL ?
05841         resource_info->image_info->texture : "pattern:checkerboard",
05842         MaxTextExtent);
05843       (void) FormatMagickString(size,MaxTextExtent,"%lux%lu",image->columns,
05844         image->rows);
05845       image_info->size=ConstantString(size);
05846       pattern=ReadImage(image_info,&image->exception);
05847       image_info=DestroyImageInfo(image_info);
05848       if (pattern != (Image *) NULL)
05849         {
05850           canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
05851           if (canvas != (Image *) NULL)
05852             (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
05853           pattern=DestroyImage(pattern);
05854         }
05855     }
05856   scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
05857     ximage->bits_per_pixel) >> 3));
05858   map_info=window->map_info;
05859   pixels=window->pixel_info->pixels;
05860   q=(unsigned char *) ximage->data;
05861   x=0;
05862   if (ximage->format == XYBitmap)
05863     {
05864       register unsigned short
05865         polarity;
05866 
05867       unsigned char
05868         background,
05869         foreground;
05870 
05871       /*
05872         Convert canvas to big-endian bitmap.
05873       */
05874       background=(unsigned char)
05875         (XPixelIntensity(&window->pixel_info->foreground_color) <
05876          XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
05877       foreground=(unsigned char)
05878         (XPixelIntensity(&window->pixel_info->background_color) <
05879          XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
05880       polarity=(unsigned short) ((PixelIntensityToQuantum(
05881         &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
05882       if (canvas->colors == 2)
05883         polarity=PixelIntensity(&canvas->colormap[0]) <
05884           PixelIntensity(&canvas->colormap[1]);
05885       for (y=0; y < (int) canvas->rows; y++)
05886       {
05887         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
05888         if (p == (const PixelPacket *) NULL)
05889           break;
05890         indexes=GetVirtualIndexQueue(canvas);
05891         bit=0;
05892         byte=0;
05893         for (x=0; x < (int) canvas->columns; x++)
05894         {
05895           byte>>=1;
05896           if (indexes[x] == (IndexPacket) polarity)
05897             byte|=foreground;
05898           else
05899             byte|=background;
05900           bit++;
05901           if (bit == 8)
05902             {
05903               *q++=byte;
05904               bit=0;
05905               byte=0;
05906             }
05907         }
05908         if (bit != 0)
05909           *q=byte >> (8-bit);
05910         q+=scanline_pad;
05911       }
05912     }
05913   else
05914     if (window->pixel_info->colors != 0)
05915       switch (ximage->bits_per_pixel)
05916       {
05917         case 2:
05918         {
05919           register unsigned int
05920             nibble;
05921 
05922           /*
05923             Convert to 2 bit color-mapped X canvas.
05924           */
05925           for (y=0; y < (int) canvas->rows; y++)
05926           {
05927             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
05928             if (p == (const PixelPacket *) NULL)
05929               break;
05930             indexes=GetVirtualIndexQueue(canvas);
05931             nibble=0;
05932             for (x=0; x < (int) canvas->columns; x++)
05933             {
05934               pixel=pixels[(long) indexes[x]] & 0x0f;
05935               switch (nibble)
05936               {
05937                 case 0:
05938                 {
05939                   *q=(unsigned char) pixel;
05940                   nibble++;
05941                   break;
05942                 }
05943                 case 1:
05944                 {
05945                   *q|=(unsigned char) (pixel << 2);
05946                   nibble++;
05947                   break;
05948                 }
05949                 case 2:
05950                 {
05951                   *q|=(unsigned char) (pixel << 4);
05952                   nibble++;
05953                   break;
05954                 }
05955                 case 3:
05956                 {
05957                   *q|=(unsigned char) (pixel << 6);
05958                   q++;
05959                   nibble=0;
05960                   break;
05961                 }
05962               }
05963             }
05964             q+=scanline_pad;
05965           }
05966           break;
05967         }
05968         case 4:
05969         {
05970           register unsigned int
05971             nibble;
05972 
05973           /*
05974             Convert to 4 bit color-mapped X canvas.
05975           */
05976           for (y=0; y < (int) canvas->rows; y++)
05977           {
05978             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
05979             if (p == (const PixelPacket *) NULL)
05980               break;
05981             indexes=GetVirtualIndexQueue(canvas);
05982             nibble=0;
05983             for (x=0; x < (int) canvas->columns; x++)
05984             {
05985               pixel=pixels[(long) indexes[x]] & 0xf;
05986               switch (nibble)
05987               {
05988                 case 0:
05989                 {
05990                   *q=(unsigned char) pixel;
05991                   nibble++;
05992                   break;
05993                 }
05994                 case 1:
05995                 {
05996                   *q|=(unsigned char) (pixel << 4);
05997                   q++;
05998                   nibble=0;
05999                   break;
06000                 }
06001               }
06002             }
06003             q+=scanline_pad;
06004           }
06005           break;
06006         }
06007         case 6:
06008         case 8:
06009         {
06010           /*
06011             Convert to 8 bit color-mapped X canvas.
06012           */
06013           if (resource_info->color_recovery &&
06014               resource_info->quantize_info->dither)
06015             {
06016               XDitherImage(canvas,ximage);
06017               break;
06018             }
06019           for (y=0; y < (int) canvas->rows; y++)
06020           {
06021             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06022             if (p == (const PixelPacket *) NULL)
06023               break;
06024             indexes=GetVirtualIndexQueue(canvas);
06025             for (x=0; x < (int) canvas->columns; x++)
06026             {
06027               pixel=pixels[(long) indexes[x]];
06028               *q++=(unsigned char) pixel;
06029             }
06030             q+=scanline_pad;
06031           }
06032           break;
06033         }
06034         default:
06035         {
06036           register int
06037             k;
06038 
06039           register unsigned int
06040             bytes_per_pixel;
06041 
06042           unsigned char
06043             channel[sizeof(unsigned long)];
06044 
06045           /*
06046             Convert to multi-byte color-mapped X canvas.
06047           */
06048           bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
06049           for (y=0; y < (int) canvas->rows; y++)
06050           {
06051             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06052             if (p == (const PixelPacket *) NULL)
06053               break;
06054             indexes=GetVirtualIndexQueue(canvas);
06055             for (x=0; x < (int) canvas->columns; x++)
06056             {
06057               pixel=pixels[(long) indexes[x]];
06058               for (k=0; k < (int) bytes_per_pixel; k++)
06059               {
06060                 channel[k]=(unsigned char) pixel;
06061                 pixel>>=8;
06062               }
06063               for (k=0; k < (int) bytes_per_pixel; k++)
06064                 *q++=channel[k];
06065             }
06066             q+=scanline_pad;
06067           }
06068           break;
06069         }
06070       }
06071     else
06072       switch (ximage->bits_per_pixel)
06073       {
06074         case 2:
06075         {
06076           register unsigned int
06077             nibble;
06078 
06079           /*
06080             Convert to contiguous 2 bit continuous-tone X canvas.
06081           */
06082           for (y=0; y < (int) canvas->rows; y++)
06083           {
06084             nibble=0;
06085             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06086             if (p == (const PixelPacket *) NULL)
06087               break;
06088             for (x=0; x < (int) canvas->columns; x++)
06089             {
06090               pixel=XGammaPixel(map_info,p);
06091               pixel&=0xf;
06092               switch (nibble)
06093               {
06094                 case 0:
06095                 {
06096                   *q=(unsigned char) pixel;
06097                   nibble++;
06098                   break;
06099                 }
06100                 case 1:
06101                 {
06102                   *q|=(unsigned char) (pixel << 2);
06103                   nibble++;
06104                   break;
06105                 }
06106                 case 2:
06107                 {
06108                   *q|=(unsigned char) (pixel << 4);
06109                   nibble++;
06110                   break;
06111                 }
06112                 case 3:
06113                 {
06114                   *q|=(unsigned char) (pixel << 6);
06115                   q++;
06116                   nibble=0;
06117                   break;
06118                 }
06119               }
06120               p++;
06121             }
06122             q+=scanline_pad;
06123           }
06124           break;
06125         }
06126         case 4:
06127         {
06128           register unsigned int
06129             nibble;
06130 
06131           /*
06132             Convert to contiguous 4 bit continuous-tone X canvas.
06133           */
06134           for (y=0; y < (int) canvas->rows; y++)
06135           {
06136             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06137             if (p == (const PixelPacket *) NULL)
06138               break;
06139             nibble=0;
06140             for (x=0; x < (int) canvas->columns; x++)
06141             {
06142               pixel=XGammaPixel(map_info,p);
06143               pixel&=0xf;
06144               switch (nibble)
06145               {
06146                 case 0:
06147                 {
06148                   *q=(unsigned char) pixel;
06149                   nibble++;
06150                   break;
06151                 }
06152                 case 1:
06153                 {
06154                   *q|=(unsigned char) (pixel << 4);
06155                   q++;
06156                   nibble=0;
06157                   break;
06158                 }
06159               }
06160               p++;
06161             }
06162             q+=scanline_pad;
06163           }
06164           break;
06165         }
06166         case 6:
06167         case 8:
06168         {
06169           /*
06170             Convert to contiguous 8 bit continuous-tone X canvas.
06171           */
06172           if (resource_info->color_recovery &&
06173               resource_info->quantize_info->dither)
06174             {
06175               XDitherImage(canvas,ximage);
06176               break;
06177             }
06178           for (y=0; y < (int) canvas->rows; y++)
06179           {
06180             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06181             if (p == (const PixelPacket *) NULL)
06182               break;
06183             for (x=0; x < (int) canvas->columns; x++)
06184             {
06185               pixel=XGammaPixel(map_info,p);
06186               *q++=(unsigned char) pixel;
06187               p++;
06188             }
06189             q+=scanline_pad;
06190           }
06191           break;
06192         }
06193         default:
06194         {
06195           if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
06196               (map_info->green_max == 255) && (map_info->blue_max == 255) &&
06197               (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
06198               (map_info->blue_mult == 1))
06199             {
06200               /*
06201                 Convert to 32 bit continuous-tone X canvas.
06202               */
06203               for (y=0; y < (int) canvas->rows; y++)
06204               {
06205                 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
06206                   &canvas->exception);
06207                 if (p == (const PixelPacket *) NULL)
06208                   break;
06209                 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
06210                     (blue_gamma != 1.0))
06211                   {
06212                     /*
06213                       Gamma correct canvas.
06214                     */
06215                     for (x=(int) canvas->columns-1; x >= 0; x--)
06216                     {
06217                       *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
06218                       *q++=ScaleQuantumToChar(XGreenGamma(p->green));
06219                       *q++=ScaleQuantumToChar(XRedGamma(p->red));
06220                       *q++=0;
06221                       p++;
06222                     }
06223                     continue;
06224                   }
06225                 for (x=(int) canvas->columns-1; x >= 0; x--)
06226                 {
06227                   *q++=ScaleQuantumToChar((Quantum) p->blue);
06228                   *q++=ScaleQuantumToChar((Quantum) p->green);
06229                   *q++=ScaleQuantumToChar((Quantum) p->red);
06230                   *q++=0;
06231                   p++;
06232                 }
06233               }
06234             }
06235           else
06236             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
06237                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
06238                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
06239                 (map_info->blue_mult == 65536L))
06240               {
06241                 /*
06242                   Convert to 32 bit continuous-tone X canvas.
06243                 */
06244                 for (y=0; y < (int) canvas->rows; y++)
06245                 {
06246                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
06247                     &canvas->exception);
06248                   if (p == (const PixelPacket *) NULL)
06249                     break;
06250                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
06251                       (blue_gamma != 1.0))
06252                     {
06253                       /*
06254                         Gamma correct canvas.
06255                       */
06256                       for (x=(int) canvas->columns-1; x >= 0; x--)
06257                       {
06258                         *q++=ScaleQuantumToChar(XRedGamma(p->red));
06259                         *q++=ScaleQuantumToChar(XGreenGamma(p->green));
06260                         *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
06261                         *q++=0;
06262                         p++;
06263                       }
06264                       continue;
06265                     }
06266                   for (x=(int) canvas->columns-1; x >= 0; x--)
06267                   {
06268                     *q++=ScaleQuantumToChar((Quantum) p->red);
06269                     *q++=ScaleQuantumToChar((Quantum) p->green);
06270                     *q++=ScaleQuantumToChar((Quantum) p->blue);
06271                     *q++=0;
06272                     p++;
06273                   }
06274                 }
06275               }
06276             else
06277               {
06278                 register int
06279                   k;
06280 
06281                 register unsigned int
06282                   bytes_per_pixel;
06283 
06284                 unsigned char
06285                   channel[sizeof(unsigned long)];
06286 
06287                 /*
06288                   Convert to multi-byte continuous-tone X canvas.
06289                 */
06290                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
06291                 for (y=0; y < (int) canvas->rows; y++)
06292                 {
06293                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
06294                     &canvas->exception);
06295                   if (p == (PixelPacket *) NULL)
06296                     break;
06297                   for (x=0; x < (long) canvas->columns; x++)
06298                   {
06299                     pixel=XGammaPixel(map_info,p);
06300                     for (k=0; k < (int) bytes_per_pixel; k++)
06301                     {
06302                       channel[k]=(unsigned char) pixel;
06303                       pixel>>=8;
06304                     }
06305                     for (k=0; k < (int) bytes_per_pixel; k++)
06306                       *q++=channel[k];
06307                     p++;
06308                   }
06309                   q+=scanline_pad;
06310                 }
06311               }
06312           break;
06313         }
06314       }
06315   if (matte_image != (XImage *) NULL)
06316     {
06317       /*
06318         Initialize matte canvas.
06319       */
06320       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
06321         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
06322       q=(unsigned char *) matte_image->data;
06323       for (y=0; y < (int) canvas->rows; y++)
06324       {
06325         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06326         if (p == (const PixelPacket *) NULL)
06327           break;
06328         bit=0;
06329         byte=0;
06330         for (x=(int) canvas->columns-1; x >= 0; x--)
06331         {
06332           byte>>=1;
06333           if (p->opacity > (long) (QuantumRange/2))
06334             byte|=0x80;
06335           bit++;
06336           if (bit == 8)
06337             {
06338               *q++=byte;
06339               bit=0;
06340               byte=0;
06341             }
06342           p++;
06343         }
06344         if (bit != 0)
06345           *q=byte >> (8-bit);
06346         q+=scanline_pad;
06347       }
06348     }
06349   if (canvas != image)
06350     canvas=DestroyImage(canvas);
06351 }
06352 
06353 /*
06354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
06355 %                                                                             %
06356 %                                                                             %
06357 %                                                                             %
06358 +   X M a k e I m a g e M S B F i r s t                                       %
06359 %                                                                             %
06360 %                                                                             %
06361 %                                                                             %
06362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
06363 %
06364 %  XMakeImageMSBFirst() initializes the pixel data of an X11 Image.  The X
06365 %  image pixels are copied in most-significant bit and byte first order.  The
06366 %  server's scanline pad is also respected. Rather than using one or two
06367 %  general cases, many special cases are found here to help speed up the image
06368 %  conversion.
06369 %
06370 %  The format of the XMakeImageMSBFirst method is:
06371 %
06372 %      XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image)
06373 %
06374 %  A description of each parameter follows:
06375 %
06376 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
06377 %
06378 %    o window: Specifies a pointer to a XWindowInfo structure.
06379 %
06380 %    o image: the image.
06381 %
06382 %    o ximage: Specifies a pointer to a XImage structure;  returned from
06383 %      XCreateImage.
06384 %
06385 %    o matte_image: Specifies a pointer to a XImage structure;  returned from
06386 %      XCreateImage.
06387 %
06388 %
06389 */
06390 static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
06391   const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image)
06392 {
06393   Image
06394     *canvas;
06395 
06396   int
06397     y;
06398 
06399   register int
06400     x;
06401 
06402   register const IndexPacket
06403     *indexes;
06404 
06405   register const PixelPacket
06406     *p;
06407 
06408   register unsigned char
06409     *q;
06410 
06411   unsigned char
06412     bit,
06413     byte;
06414 
06415   unsigned int
06416     scanline_pad;
06417 
06418   unsigned long
06419     pixel,
06420     *pixels;
06421 
06422   XStandardColormap
06423     *map_info;
06424 
06425   assert(resource_info != (XResourceInfo *) NULL);
06426   assert(window != (XWindowInfo *) NULL);
06427   assert(image != (Image *) NULL);
06428   if (image->debug != MagickFalse)
06429     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
06430   canvas=image;
06431   if ((image->storage_class == DirectClass) && (image->matte != MagickFalse))
06432     {
06433       char
06434         size[MaxTextExtent];
06435 
06436       Image
06437         *pattern;
06438 
06439       ImageInfo
06440         *image_info;
06441 
06442       image_info=AcquireImageInfo();
06443       (void) CopyMagickString(image_info->filename,
06444         resource_info->image_info->texture != (char *) NULL ?
06445         resource_info->image_info->texture : "pattern:checkerboard",
06446         MaxTextExtent);
06447       (void) FormatMagickString(size,MaxTextExtent,"%lux%lu",image->columns,
06448         image->rows);
06449       image_info->size=ConstantString(size);
06450       pattern=ReadImage(image_info,&image->exception);
06451       image_info=DestroyImageInfo(image_info);
06452       if (pattern != (Image *) NULL)
06453         {
06454           canvas=CloneImage(image,0,0,MagickTrue,&image->exception);
06455           if (canvas != (Image *) NULL)
06456             (void) CompositeImage(canvas,DstOverCompositeOp,pattern,0,0);
06457           pattern=DestroyImage(pattern);
06458         }
06459     }
06460   scanline_pad=(unsigned int) (ximage->bytes_per_line-
06461     ((ximage->width*ximage->bits_per_pixel) >> 3));
06462   map_info=window->map_info;
06463   pixels=window->pixel_info->pixels;
06464   q=(unsigned char *) ximage->data;
06465   x=0;
06466   if (ximage->format == XYBitmap)
06467     {
06468       register unsigned short
06469         polarity;
06470 
06471       unsigned char
06472         background,
06473         foreground;
06474 
06475       /*
06476         Convert canvas to big-endian bitmap.
06477       */
06478       background=(unsigned char)
06479         (XPixelIntensity(&window->pixel_info->foreground_color) <
06480          XPixelIntensity(&window->pixel_info->background_color) ?  0x01 : 0x00);
06481       foreground=(unsigned char)
06482         (XPixelIntensity(&window->pixel_info->background_color) <
06483          XPixelIntensity(&window->pixel_info->foreground_color) ?  0x01 : 0x00);
06484       polarity=(unsigned short) ((PixelIntensityToQuantum(
06485         &canvas->colormap[0])) < ((Quantum) QuantumRange/2) ? 1 : 0);
06486       if (canvas->colors == 2)
06487         polarity=PixelIntensity(&canvas->colormap[0]) <
06488           PixelIntensity(&canvas->colormap[1]);
06489       for (y=0; y < (int) canvas->rows; y++)
06490       {
06491         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06492         if (p == (const PixelPacket *) NULL)
06493           break;
06494         indexes=GetVirtualIndexQueue(canvas);
06495         bit=0;
06496         byte=0;
06497         for (x=(int) canvas->columns-1; x >= 0; x--)
06498         {
06499           byte<<=1;
06500           if (indexes[x] == (IndexPacket) polarity)
06501             byte|=foreground;
06502           else
06503             byte|=background;
06504           bit++;
06505           if (bit == 8)
06506             {
06507               *q++=byte;
06508               bit=0;
06509               byte=0;
06510             }
06511         }
06512         if (bit != 0)
06513           *q=byte << (8-bit);
06514         q+=scanline_pad;
06515       }
06516     }
06517   else
06518     if (window->pixel_info->colors != 0)
06519       switch (ximage->bits_per_pixel)
06520       {
06521         case 2:
06522         {
06523           register unsigned int
06524             nibble;
06525 
06526           /*
06527             Convert to 2 bit color-mapped X canvas.
06528           */
06529           for (y=0; y < (int) canvas->rows; y++)
06530           {
06531             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06532             if (p == (const PixelPacket *) NULL)
06533               break;
06534             indexes=GetVirtualIndexQueue(canvas);
06535             nibble=0;
06536             for (x=0; x < (int) canvas->columns; x++)
06537             {
06538               pixel=pixels[(long) indexes[x]] & 0xf;
06539               switch (nibble)
06540               {
06541                 case 0:
06542                 {
06543                   *q=(unsigned char) (pixel << 6);
06544                   nibble++;
06545                   break;
06546                 }
06547                 case 1:
06548                 {
06549                   *q|=(unsigned char) (pixel << 4);
06550                   nibble++;
06551                   break;
06552                 }
06553                 case 2:
06554                 {
06555                   *q|=(unsigned char) (pixel << 2);
06556                   nibble++;
06557                   break;
06558                 }
06559                 case 3:
06560                 {
06561                   *q|=(unsigned char) pixel;
06562                   q++;
06563                   nibble=0;
06564                   break;
06565                 }
06566               }
06567             }
06568             q+=scanline_pad;
06569           }
06570           break;
06571         }
06572         case 4:
06573         {
06574           register unsigned int
06575             nibble;
06576 
06577           /*
06578             Convert to 4 bit color-mapped X canvas.
06579           */
06580           for (y=0; y < (int) canvas->rows; y++)
06581           {
06582             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06583             if (p == (const PixelPacket *) NULL)
06584               break;
06585             indexes=GetVirtualIndexQueue(canvas);
06586             nibble=0;
06587             for (x=0; x < (int) canvas->columns; x++)
06588             {
06589               pixel=pixels[(long) indexes[x]] & 0xf;
06590               switch (nibble)
06591               {
06592                 case 0:
06593                 {
06594                   *q=(unsigned char) (pixel << 4);
06595                   nibble++;
06596                   break;
06597                 }
06598                 case 1:
06599                 {
06600                   *q|=(unsigned char) pixel;
06601                   q++;
06602                   nibble=0;
06603                   break;
06604                 }
06605               }
06606             }
06607             q+=scanline_pad;
06608           }
06609           break;
06610         }
06611         case 6:
06612         case 8:
06613         {
06614           /*
06615             Convert to 8 bit color-mapped X canvas.
06616           */
06617           if (resource_info->color_recovery &&
06618               resource_info->quantize_info->dither)
06619             {
06620               XDitherImage(canvas,ximage);
06621               break;
06622             }
06623           for (y=0; y < (int) canvas->rows; y++)
06624           {
06625             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06626             if (p == (const PixelPacket *) NULL)
06627               break;
06628             indexes=GetVirtualIndexQueue(canvas);
06629             for (x=0; x < (int) canvas->columns; x++)
06630             {
06631               pixel=pixels[(long) indexes[x]];
06632               *q++=(unsigned char) pixel;
06633             }
06634             q+=scanline_pad;
06635           }
06636           break;
06637         }
06638         default:
06639         {
06640           register int
06641             k;
06642 
06643           register unsigned int
06644             bytes_per_pixel;
06645 
06646           unsigned char
06647             channel[sizeof(unsigned long)];
06648 
06649           /*
06650             Convert to 8 bit color-mapped X canvas.
06651           */
06652           bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
06653           for (y=0; y < (int) canvas->rows; y++)
06654           {
06655             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06656             if (p == (const PixelPacket *) NULL)
06657               break;
06658             indexes=GetVirtualIndexQueue(canvas);
06659             for (x=0; x < (int) canvas->columns; x++)
06660             {
06661               pixel=pixels[(long) indexes[x]];
06662               for (k=(int) bytes_per_pixel-1; k >= 0; k--)
06663               {
06664                 channel[k]=(unsigned char) pixel;
06665                 pixel>>=8;
06666               }
06667               for (k=0; k < (int) bytes_per_pixel; k++)
06668                 *q++=channel[k];
06669             }
06670             q+=scanline_pad;
06671           }
06672           break;
06673         }
06674       }
06675     else
06676       switch (ximage->bits_per_pixel)
06677       {
06678         case 2:
06679         {
06680           register unsigned int
06681             nibble;
06682 
06683           /*
06684             Convert to 4 bit continuous-tone X canvas.
06685           */
06686           for (y=0; y < (int) canvas->rows; y++)
06687           {
06688             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06689             if (p == (const PixelPacket *) NULL)
06690               break;
06691             nibble=0;
06692             for (x=(int) canvas->columns-1; x >= 0; x--)
06693             {
06694               pixel=XGammaPixel(map_info,p);
06695               pixel&=0xf;
06696               switch (nibble)
06697               {
06698                 case 0:
06699                 {
06700                   *q=(unsigned char) (pixel << 6);
06701                   nibble++;
06702                   break;
06703                 }
06704                 case 1:
06705                 {
06706                   *q|=(unsigned char) (pixel << 4);
06707                   nibble++;
06708                   break;
06709                 }
06710                 case 2:
06711                 {
06712                   *q|=(unsigned char) (pixel << 2);
06713                   nibble++;
06714                   break;
06715                 }
06716                 case 3:
06717                 {
06718                   *q|=(unsigned char) pixel;
06719                   q++;
06720                   nibble=0;
06721                   break;
06722                 }
06723               }
06724               p++;
06725             }
06726             q+=scanline_pad;
06727           }
06728           break;
06729         }
06730         case 4:
06731         {
06732           register unsigned int
06733             nibble;
06734 
06735           /*
06736             Convert to 4 bit continuous-tone X canvas.
06737           */
06738           for (y=0; y < (int) canvas->rows; y++)
06739           {
06740             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06741             if (p == (const PixelPacket *) NULL)
06742               break;
06743             nibble=0;
06744             for (x=(int) canvas->columns-1; x >= 0; x--)
06745             {
06746               pixel=XGammaPixel(map_info,p);
06747               pixel&=0xf;
06748               switch (nibble)
06749               {
06750                 case 0:
06751                 {
06752                   *q=(unsigned char) (pixel << 4);
06753                   nibble++;
06754                   break;
06755                 }
06756                 case 1:
06757                 {
06758                   *q|=(unsigned char) pixel;
06759                   q++;
06760                   nibble=0;
06761                   break;
06762                 }
06763               }
06764               p++;
06765             }
06766             q+=scanline_pad;
06767           }
06768           break;
06769         }
06770         case 6:
06771         case 8:
06772         {
06773           /*
06774             Convert to 8 bit continuous-tone X canvas.
06775           */
06776           if (resource_info->color_recovery &&
06777               resource_info->quantize_info->dither)
06778             {
06779               XDitherImage(canvas,ximage);
06780               break;
06781             }
06782           for (y=0; y < (int) canvas->rows; y++)
06783           {
06784             p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06785             if (p == (const PixelPacket *) NULL)
06786               break;
06787             for (x=(int) canvas->columns-1; x >= 0; x--)
06788             {
06789               pixel=XGammaPixel(map_info,p);
06790               *q++=(unsigned char) pixel;
06791               p++;
06792             }
06793             q+=scanline_pad;
06794           }
06795           break;
06796         }
06797         default:
06798         {
06799           if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
06800               (map_info->green_max == 255) && (map_info->blue_max == 255) &&
06801               (map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
06802               (map_info->blue_mult == 1))
06803             {
06804               /*
06805                 Convert to 32 bit continuous-tone X canvas.
06806               */
06807               for (y=0; y < (int) canvas->rows; y++)
06808               {
06809                 p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
06810                   &canvas->exception);
06811                 if (p == (const PixelPacket *) NULL)
06812                   break;
06813                 if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
06814                     (blue_gamma != 1.0))
06815                   {
06816                     /*
06817                       Gamma correct canvas.
06818                     */
06819                     for (x=(int) canvas->columns-1; x >= 0; x--)
06820                     {
06821                       *q++=0;
06822                       *q++=ScaleQuantumToChar(XRedGamma(p->red));
06823                       *q++=ScaleQuantumToChar(XGreenGamma(p->green));
06824                       *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
06825                       p++;
06826                     }
06827                     continue;
06828                   }
06829                 for (x=(int) canvas->columns-1; x >= 0; x--)
06830                 {
06831                   *q++=0;
06832                   *q++=ScaleQuantumToChar((Quantum) p->red);
06833                   *q++=ScaleQuantumToChar((Quantum) p->green);
06834                   *q++=ScaleQuantumToChar((Quantum) p->blue);
06835                   p++;
06836                 }
06837               }
06838             }
06839           else
06840             if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
06841                 (map_info->green_max == 255) && (map_info->blue_max == 255) &&
06842                 (map_info->red_mult == 1) && (map_info->green_mult == 256) &&
06843                 (map_info->blue_mult == 65536L))
06844               {
06845                 /*
06846                   Convert to 32 bit continuous-tone X canvas.
06847                 */
06848                 for (y=0; y < (int) canvas->rows; y++)
06849                 {
06850                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
06851                     &canvas->exception);
06852                   if (p == (const PixelPacket *) NULL)
06853                     break;
06854                   if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
06855                       (blue_gamma != 1.0))
06856                     {
06857                       /*
06858                         Gamma correct canvas.
06859                       */
06860                       for (x=(int) canvas->columns-1; x >= 0; x--)
06861                       {
06862                         *q++=0;
06863                         *q++=ScaleQuantumToChar(XBlueGamma(p->blue));
06864                         *q++=ScaleQuantumToChar(XGreenGamma(p->green));
06865                         *q++=ScaleQuantumToChar(XRedGamma(p->red));
06866                         p++;
06867                       }
06868                       continue;
06869                     }
06870                   for (x=(int) canvas->columns-1; x >= 0; x--)
06871                   {
06872                     *q++=0;
06873                     *q++=ScaleQuantumToChar((Quantum) p->blue);
06874                     *q++=ScaleQuantumToChar((Quantum) p->green);
06875                     *q++=ScaleQuantumToChar((Quantum) p->red);
06876                     p++;
06877                   }
06878                 }
06879               }
06880             else
06881               {
06882                 register int
06883                   k;
06884 
06885                 register unsigned int
06886                   bytes_per_pixel;
06887 
06888                 unsigned char
06889                   channel[sizeof(unsigned long)];
06890 
06891                 /*
06892                   Convert to multi-byte continuous-tone X canvas.
06893                 */
06894                 bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
06895                 for (y=0; y < (int) canvas->rows; y++)
06896                 {
06897                   p=GetVirtualPixels(canvas,0,y,canvas->columns,1,
06898                     &canvas->exception);
06899                   if (p == (const PixelPacket *) NULL)
06900                     break;
06901                   for (x=(int) canvas->columns-1; x >= 0; x--)
06902                   {
06903                     pixel=XGammaPixel(map_info,p);
06904                     for (k=(int) bytes_per_pixel-1; k >= 0; k--)
06905                     {
06906                       channel[k]=(unsigned char) pixel;
06907                       pixel>>=8;
06908                     }
06909                     for (k=0; k < (int) bytes_per_pixel; k++)
06910                       *q++=channel[k];
06911                     p++;
06912                   }
06913                   q+=scanline_pad;
06914                 }
06915               }
06916           break;
06917         }
06918       }
06919   if (matte_image != (XImage *) NULL)
06920     {
06921       /*
06922         Initialize matte canvas.
06923       */
06924       scanline_pad=(unsigned int) (matte_image->bytes_per_line-
06925         ((matte_image->width*matte_image->bits_per_pixel) >> 3));
06926       q=(unsigned char *) matte_image->data;
06927       for (y=0; y < (int) canvas->rows; y++)
06928       {
06929         p=GetVirtualPixels(canvas,0,y,canvas->columns,1,&canvas->exception);
06930         if (p == (const PixelPacket *) NULL)
06931           break;
06932         bit=0;
06933         byte=0;
06934         for (x=(int) canvas->columns-1; x >= 0; x--)
06935         {
06936           byte<<=1;
06937           if (p->opacity > (long) (QuantumRange/2))
06938             byte|=0x01;
06939           bit++;
06940           if (bit == 8)
06941             {
06942               *q++=byte;
06943               bit=0;
06944               byte=0;
06945             }
06946           p++;
06947         }
06948         if (bit != 0)
06949           *q=byte << (8-bit);
06950         q+=scanline_pad;
06951       }
06952     }
06953   if (canvas != image)
06954     canvas=DestroyImage(canvas);
06955 }
06956 
06957 /*
06958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
06959 %                                                                             %
06960 %                                                                             %
06961 %                                                                             %
06962 %   X M a k e M a g n i f y I m a g e                                         %
06963 %                                                                             %
06964 %                                                                             %
06965 %                                                                             %
06966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
06967 %
06968 %  XMakeMagnifyImage() magnifies a region of an X image and displays it.
06969 %
06970 %  The format of the XMakeMagnifyImage method is:
06971 %
06972 %      void XMakeMagnifyImage(display,windows)
06973 %
06974 %  A description of each parameter follows:
06975 %
06976 %    o display: Specifies a connection to an X server;  returned from
06977 %      XOpenDisplay.
06978 %
06979 %    o windows: Specifies a pointer to a XWindows structure.
06980 %
06981 */
06982 MagickExport void XMakeMagnifyImage(Display *display,XWindows *windows)
06983 {
06984   char
06985     tuple[MaxTextExtent];
06986 
06987   int
06988     y;
06989 
06990   long
06991     n;
06992 
06993   MagickPixelPacket
06994     pixel;
06995 
06996   register int
06997     x;
06998 
06999   register long
07000     i;
07001 
07002   register unsigned char
07003     *p,
07004     *q;
07005 
07006   static unsigned int
07007     previous_magnify = 0;
07008 
07009   static XWindowInfo
07010     magnify_window;
07011 
07012   unsigned int
07013     height,
07014     j,
07015     k,
07016     l,
07017     magnify,
07018     scanline_pad,
07019     width;
07020 
07021   XImage
07022     *ximage;
07023 
07024   /*
07025     Check boundary conditions.
07026   */
07027   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
07028   assert(display != (Display *) NULL);
07029   assert(windows != (XWindows *) NULL);
07030   magnify=1;
07031   for (n=1; n < (long) windows->magnify.data; n++)
07032     magnify<<=1;
07033   while ((magnify*windows->image.ximage->width) < windows->magnify.width)
07034     magnify<<=1;
07035   while ((magnify*windows->image.ximage->height) < windows->magnify.height)
07036     magnify<<=1;
07037   while (magnify > windows->magnify.width)
07038     magnify>>=1;
07039   while (magnify > windows->magnify.height)
07040     magnify>>=1;
07041   if (magnify != previous_magnify)
07042     {
07043       Status
07044         status;
07045 
07046       XTextProperty
07047         window_name;
07048 
07049       /*
07050         New magnify factor:  update magnify window name.
07051       */
07052       i=0;
07053       while ((1 << i) <= (int) magnify)
07054         i++;
07055       (void) FormatMagickString(windows->magnify.name,MaxTextExtent,
07056         "Magnify %luX",i);
07057       status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
07058       if (status != False)
07059         {
07060           XSetWMName(display,windows->magnify.id,&window_name);
07061           XSetWMIconName(display,windows->magnify.id,&window_name);
07062           (void) XFree((void *) window_name.value);
07063         }
07064     }
07065   previous_magnify=magnify;
07066   ximage=windows->image.ximage;
07067   width=(unsigned int) windows->magnify.ximage->width;
07068   height=(unsigned int) windows->magnify.ximage->height;
07069   if ((windows->magnify.x < 0) ||
07070       (windows->magnify.x >= windows->image.ximage->width))
07071     windows->magnify.x=windows->image.ximage->width >> 1;
07072   x=windows->magnify.x-((width/magnify) >> 1);
07073   if (x < 0)
07074     x=0;
07075   else
07076     if (x > (int) (ximage->width-(width/magnify)))
07077       x=ximage->width-width/magnify;
07078   if ((windows->magnify.y < 0) ||
07079       (windows->magnify.y >= windows->image.ximage->height))
07080     windows->magnify.y=windows->image.ximage->height >> 1;
07081   y=windows->magnify.y-((height/magnify) >> 1);
07082   if (y < 0)
07083     y=0;
07084   else
07085     if (y > (int) (ximage->height-(height/magnify)))
07086       y=ximage->height-height/magnify;
07087   q=(unsigned char *) windows->magnify.ximage->data;
07088   scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
07089     ((width*windows->magnify.ximage->bits_per_pixel) >> 3));
07090   if (ximage->bits_per_pixel < 8)
07091     {
07092       register unsigned char
07093         background,
07094         byte,
07095         foreground,
07096         p_bit,
07097         q_bit;
07098 
07099       register unsigned int
07100         plane;
07101 
07102       XPixelInfo
07103         *pixel_info;
07104 
07105       pixel_info=windows->magnify.pixel_info;
07106       switch (ximage->bitmap_bit_order)
07107       {
07108         case LSBFirst:
07109         {
07110           /*
07111             Magnify little-endian bitmap.
07112           */
07113           background=0x00;
07114           foreground=0x80;
07115           if (ximage->format == XYBitmap)
07116             {
07117               background=(unsigned char)
07118                 (XPixelIntensity(&pixel_info->foreground_color) <
07119                  XPixelIntensity(&pixel_info->background_color) ?  0x80 : 0x00);
07120               foreground=(unsigned char)
07121                 (XPixelIntensity(&pixel_info->background_color) <
07122                  XPixelIntensity(&pixel_info->foreground_color) ?  0x80 : 0x00);
07123               if (windows->magnify.depth > 1)
07124                 Swap(background,foreground);
07125             }
07126           for (i=0; i < (long) height; i+=magnify)
07127           {
07128             /*
07129               Propogate pixel magnify rows.
07130             */
07131             for (j=0; j < magnify; j++)
07132             {
07133               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
07134                 ((x*ximage->bits_per_pixel) >> 3);
07135               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
07136               q_bit=0;
07137               byte=0;
07138               for (k=0; k < width; k+=magnify)
07139               {
07140                 /*
07141                   Propogate pixel magnify columns.
07142                 */
07143                 for (l=0; l < magnify; l++)
07144                 {
07145                   /*
07146                     Propogate each bit plane.
07147                   */
07148                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
07149                   {
07150                     byte>>=1;
07151                     if (*p & (0x01 << (p_bit+plane)))
07152                       byte|=foreground;
07153                     else
07154                       byte|=background;
07155                     q_bit++;
07156                     if (q_bit == 8)
07157                       {
07158                         *q++=byte;
07159                         q_bit=0;
07160                         byte=0;
07161                       }
07162                   }
07163                 }
07164                 p_bit+=ximage->bits_per_pixel;
07165                 if (p_bit == 8)
07166                   {
07167                     p++;
07168                     p_bit=0;
07169                   }
07170                 if (q_bit != 0)
07171                   *q=byte >> (8-q_bit);
07172                 q+=scanline_pad;
07173               }
07174             }
07175             y++;
07176           }
07177           break;
07178         }
07179         case MSBFirst:
07180         default:
07181         {
07182           /*
07183             Magnify big-endian bitmap.
07184           */
07185           background=0x00;
07186           foreground=0x01;
07187           if (ximage->format == XYBitmap)
07188             {
07189               background=(unsigned char)
07190                 (XPixelIntensity(&pixel_info->foreground_color) <
07191                  XPixelIntensity(&pixel_info->background_color) ?  0x01 : 0x00);
07192               foreground=(unsigned char)
07193                 (XPixelIntensity(&pixel_info->background_color) <
07194                  XPixelIntensity(&pixel_info->foreground_color) ?  0x01 : 0x00);
07195               if (windows->magnify.depth > 1)
07196                 Swap(background,foreground);
07197             }
07198           for (i=0; i < (long) height; i+=magnify)
07199           {
07200             /*
07201               Propogate pixel magnify rows.
07202             */
07203             for (j=0; j < magnify; j++)
07204             {
07205               p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
07206                 ((x*ximage->bits_per_pixel) >> 3);
07207               p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
07208               q_bit=0;
07209               byte=0;
07210               for (k=0; k < width; k+=magnify)
07211               {
07212                 /*
07213                   Propogate pixel magnify columns.
07214                 */
07215                 for (l=0; l < magnify; l++)
07216                 {
07217                   /*
07218                     Propogate each bit plane.
07219                   */
07220                   for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
07221                   {
07222                     byte<<=1;
07223                     if (*p & (0x80 >> (p_bit+plane)))
07224                       byte|=foreground;
07225                     else
07226                       byte|=background;
07227                     q_bit++;
07228                     if (q_bit == 8)
07229                       {
07230                         *q++=byte;
07231                         q_bit=0;
07232                         byte=0;
07233                       }
07234                   }
07235                 }
07236                 p_bit+=ximage->bits_per_pixel;
07237                 if (p_bit == 8)
07238                   {
07239                     p++;
07240                     p_bit=0;
07241                   }
07242                 if (q_bit != 0)
07243                   *q=byte << (8-q_bit);
07244                 q+=scanline_pad;
07245               }
07246             }
07247             y++;
07248           }
07249           break;
07250         }
07251       }
07252     }
07253   else
07254     switch (ximage->bits_per_pixel)
07255     {
07256       case 6:
07257       case 8:
07258       {
07259         /*
07260           Magnify 8 bit X image.
07261         */
07262         for (i=0; i < (long) height; i+=magnify)
07263         {
07264           /*
07265             Propogate pixel magnify rows.
07266           */
07267           for (j=0; j < magnify; j++)
07268           {
07269             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
07270               ((x*ximage->bits_per_pixel) >> 3);
07271             for (k=0; k < width; k+=magnify)
07272             {
07273               /*
07274                 Propogate pixel magnify columns.
07275               */
07276               for (l=0; l < magnify; l++)
07277                 *q++=(*p);
07278               p++;
07279             }
07280             q+=scanline_pad;
07281           }
07282           y++;
07283         }
07284         break;
07285       }
07286       default:
07287       {
07288         register unsigned int
07289           bytes_per_pixel,
07290           m;
07291 
07292         /*
07293           Magnify multi-byte X image.
07294         */
07295         bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
07296         for (i=0; i < (long) height; i+=magnify)
07297         {
07298           /*
07299             Propogate pixel magnify rows.
07300           */
07301           for (j=0; j < magnify; j++)
07302           {
07303             p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
07304               ((x*ximage->bits_per_pixel) >> 3);
07305             for (k=0; k < width; k+=magnify)
07306             {
07307               /*
07308                 Propogate pixel magnify columns.
07309               */
07310               for (l=0; l < magnify; l++)
07311                 for (m=0; m < bytes_per_pixel; m++)
07312                   *q++=(*(p+m));
07313               p+=bytes_per_pixel;
07314             }
07315             q+=scanline_pad;
07316           }
07317           y++;
07318         }
07319         break;
07320       }
07321     }
07322   /*
07323     Copy X image to magnify pixmap.
07324   */
07325   x=windows->magnify.x-((width/magnify) >> 1);
07326   if (x < 0)
07327     x=(int) ((width >> 1)-windows->magnify.x*magnify);
07328   else
07329     if (x > (int) (ximage->width-(width/magnify)))
07330       x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
07331     else
07332       x=0;
07333   y=windows->magnify.y-((height/magnify) >> 1);
07334   if (y < 0)
07335     y=(int) ((height >> 1)-windows->magnify.y*magnify);
07336   else
07337     if (y > (int) (ximage->height-(height/magnify)))
07338       y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
07339     else
07340       y=0;
07341   if ((x != 0) || (y != 0))
07342     (void) XFillRectangle(display,windows->magnify.pixmap,
07343       windows->magnify.annotate_context,0,0,width,height);
07344   (void) XPutImage(display,windows->magnify.pixmap,
07345     windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
07346     height-y);
07347   if ((magnify > 1) && ((magnify <= (width >> 1)) &&
07348       (magnify <= (height >> 1))))
07349     {
07350       RectangleInfo
07351         highlight_info;
07352 
07353       /*
07354         Highlight center pixel.
07355       */
07356       highlight_info.x=(long) windows->magnify.width >> 1;
07357       highlight_info.y=(long) windows->magnify.height >> 1;
07358       highlight_info.width=magnify;
07359       highlight_info.height=magnify;
07360       (void) XDrawRectangle(display,windows->magnify.pixmap,
07361         windows->magnify.highlight_context,(int) highlight_info.x,
07362         (int) highlight_info.y,(unsigned int) highlight_info.width-1,
07363         (unsigned int) highlight_info.height-1);
07364       if (magnify > 2)
07365         (void) XDrawRectangle(display,windows->magnify.pixmap,
07366           windows->magnify.annotate_context,(int) highlight_info.x+1,
07367           (int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
07368           (unsigned int) highlight_info.height-3);
07369     }
07370   /*
07371     Show center pixel color.
07372   */
07373   (void) GetOneVirtualMagickPixel(windows->image.image,windows->magnify.x,
07374     windows->magnify.y,&pixel,&windows->image.image->exception);
07375   (void) FormatMagickString(tuple,MaxTextExtent,"%d,%d: ",
07376     windows->magnify.x,windows->magnify.y);
07377   (void) ConcatenateMagickString(tuple,"(",MaxTextExtent);
07378   ConcatenateColorComponent(&pixel,RedChannel,X11Compliance,tuple);
07379   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
07380   ConcatenateColorComponent(&pixel,GreenChannel,X11Compliance,tuple);
07381   (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
07382   ConcatenateColorComponent(&pixel,BlueChannel,X11Compliance,tuple);
07383   if (pixel.colorspace == CMYKColorspace)
07384     {
07385       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
07386       ConcatenateColorComponent(&pixel,IndexChannel,X11Compliance,tuple);
07387     }
07388   if (pixel.matte != MagickFalse)
07389     {
07390       (void) ConcatenateMagickString(tuple,",",MaxTextExtent);
07391       ConcatenateColorComponent(&pixel,OpacityChannel,X11Compliance,tuple);
07392     }
07393   (void) ConcatenateMagickString(tuple,")",MaxTextExtent);
07394   height=(unsigned int) windows->magnify.font_info->ascent+
07395     windows->magnify.font_info->descent;
07396   x=windows->magnify.font_info->max_bounds.width >> 1;
07397   y=windows->magnify.font_info->ascent+(height >> 2);
07398   (void) XDrawImageString(display,windows->magnify.pixmap,
07399     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
07400   GetColorTuple(&pixel,MagickTrue,tuple);
07401   y+=height;
07402   (void) XDrawImageString(display,windows->magnify.pixmap,
07403     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
07404   (void) QueryMagickColorname(windows->image.image,&pixel,SVGCompliance,tuple,
07405      &windows->image.image->exception);
07406   y+=height;
07407   (void) XDrawImageString(display,windows->magnify.pixmap,
07408     windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
07409   /*
07410     Refresh magnify window.
07411   */
07412   magnify_window=windows->magnify;
07413   magnify_window.x=0;
07414   magnify_window.y=0;
07415   XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
07416 }
07417 
07418 /*
07419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
07420 %                                                                             %
07421 %                                                                             %
07422 %                                                                             %
07423 %   X M a k e P i x m a p                                                     %
07424 %                                                                             %
07425 %                                                                             %
07426 %                                                                             %
07427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
07428 %
07429 %  XMakePixmap() creates an X11 pixmap.
07430 %
07431 %  The format of the XMakePixmap method is:
07432 %
07433 %      void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
07434 %        XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
07435 %        XPixelInfo *pixel)
07436 %
07437 %  A description of each parameter follows:
07438 %
07439 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
07440 %
07441 %    o display: Specifies a connection to an X server; returned from
07442 %      XOpenDisplay.
07443 %
07444 %    o window: Specifies a pointer to a XWindowInfo structure.
07445 %
07446 %
07447 */
07448 static MagickBooleanType XMakePixmap(Display *display,
07449   const XResourceInfo *resource_info,XWindowInfo *window)
07450 {
07451   unsigned int
07452     height,
07453     width;
07454 
07455   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
07456   assert(display != (Display *) NULL);
07457   assert(resource_info != (XResourceInfo *) NULL);
07458   assert(window != (XWindowInfo  *) NULL);
07459   if (window->pixmap != (Pixmap) NULL)
07460     {
07461       /*
07462         Destroy previous X pixmap.
07463       */
07464       (void) XFreePixmap(display,window->pixmap);
07465       window->pixmap=(Pixmap) NULL;
07466     }
07467   if (window->use_pixmap == MagickFalse)
07468     return(MagickFalse);
07469   if (window->ximage == (XImage *) NULL)
07470     return(MagickFalse);
07471   /*
07472     Display busy cursor.
07473   */
07474   (void) XCheckDefineCursor(display,window->id,window->busy_cursor);
07475   (void) XFlush(display);
07476   /*
07477     Create pixmap.
07478   */
07479   width=(unsigned int) window->ximage->width;
07480   height=(unsigned int) window->ximage->height;
07481   window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
07482   if (window->pixmap == (Pixmap) NULL)
07483     {
07484       /*
07485         Unable to allocate pixmap.
07486       */
07487       (void) XCheckDefineCursor(display,window->id,window->cursor);
07488       return(MagickFalse);
07489     }
07490   /*
07491     Copy X image to pixmap.
07492   */
07493 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
07494   if (window->shared_memory)
07495     (void) XShmPutImage(display,window->pixmap,window->annotate_context,
07496       window->ximage,0,0,0,0,width,height,MagickTrue);
07497 #endif
07498   if (window->shared_memory == MagickFalse)
07499     (void) XPutImage(display,window->pixmap,window->annotate_context,
07500       window->ximage,0,0,0,0,width,height);
07501   if (IsEventLogging())
07502     {
07503       (void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
07504       (void) LogMagickEvent(X11Event,GetMagickModule(),"  width, height: %ux%u",
07505         width,height);
07506     }
07507   /*
07508     Restore cursor.
07509   */
07510   (void) XCheckDefineCursor(display,window->id,window->cursor);
07511   return(MagickTrue);
07512 }
07513 
07514 /*
07515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
07516 %                                                                             %
07517 %                                                                             %
07518 %                                                                             %
07519 %   X M a k e S t a n d a r d C o l o r m a p                                 %
07520 %                                                                             %
07521 %                                                                             %
07522 %                                                                             %
07523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
07524 %
07525 %  XMakeStandardColormap() creates an X11 Standard Colormap.
07526 %
07527 %  The format of the XMakeStandardColormap method is:
07528 %
07529 %      XMakeStandardColormap(display,visual_info,resource_info,image,
07530 %        map_info,pixel)
07531 %
07532 %  A description of each parameter follows:
07533 %
07534 %    o display: Specifies a connection to an X server; returned from
07535 %      XOpenDisplay.
07536 %
07537 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
07538 %      returned from XGetVisualInfo.
07539 %
07540 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
07541 %
07542 %    o image: the image.
07543 %
07544 %    o map_info: If a Standard Colormap type is specified, this structure is
07545 %      initialized with info from the Standard Colormap.
07546 %
07547 %    o pixel: Specifies a pointer to a XPixelInfo structure.
07548 %
07549 %
07550 */
07551 
07552 #if defined(__cplusplus) || defined(c_plusplus)
07553 extern "C" {
07554 #endif
07555 
07556 static inline MagickRealType DiversityPixelIntensity(
07557   const DiversityPacket *pixel)
07558 {
07559   MagickRealType
07560     intensity;
07561 
07562   intensity=0.299*pixel->red+0.587*pixel->green+0.114*pixel->blue;
07563   return(intensity);
07564 }
07565 
07566 static int IntensityCompare(const void *x,const void *y)
07567 {
07568   DiversityPacket
07569     *color_1,
07570     *color_2;
07571 
07572   int
07573     diversity;
07574 
07575   color_1=(DiversityPacket *) x;
07576   color_2=(DiversityPacket *) y;
07577   diversity=(int) (DiversityPixelIntensity(color_2)-
07578     DiversityPixelIntensity(color_1));
07579   return(diversity);
07580 }
07581 
07582 static int PopularityCompare(const void *x,const void *y)
07583 {
07584   DiversityPacket
07585     *color_1,
07586     *color_2;
07587 
07588   color_1=(DiversityPacket *) x;
07589   color_2=(DiversityPacket *) y;
07590   return((int) color_2->count-(int) color_1->count);
07591 }
07592 
07593 #if defined(__cplusplus) || defined(c_plusplus)
07594 }
07595 #endif
07596 
07597 static inline Quantum ScaleXToQuantum(const unsigned long x,
07598   const unsigned long scale)
07599 {
07600   return((Quantum) (((MagickRealType) QuantumRange*x)/scale+0.5));
07601 }
07602 
07603 MagickExport void XMakeStandardColormap(Display *display,
07604   XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
07605   XStandardColormap *map_info,XPixelInfo *pixel)
07606 {
07607   Colormap
07608     colormap;
07609 
07610   ExceptionInfo
07611     *exception;
07612 
07613   register IndexPacket
07614     *indexes;
07615 
07616   register long
07617     i;
07618 
07619   Status
07620     status;
07621 
07622   unsigned long
07623     number_colors,
07624     retain_colors;
07625 
07626   unsigned short
07627     gray_value;
07628 
07629   XColor
07630     color,
07631     *colors,
07632     *p;
07633 
07634   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
07635   assert(display != (Display *) NULL);
07636   assert(visual_info != (XVisualInfo *) NULL);
07637   assert(map_info != (XStandardColormap *) NULL);
07638   assert(resource_info != (XResourceInfo *) NULL);
07639   assert(pixel != (XPixelInfo *) NULL);
07640   exception=(&image->exception);
07641   if (resource_info->map_type != (char *) NULL)
07642     {
07643       /*
07644         Standard Colormap is already defined (i.e. xstdcmap).
07645       */
07646       XGetPixelPacket(display,visual_info,map_info,resource_info,image,
07647         pixel);
07648       number_colors=(unsigned int) (map_info->base_pixel+
07649         (map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
07650       if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
07651         if ((image->matte == MagickFalse) &&
07652             (resource_info->color_recovery == MagickFalse) &&
07653             resource_info->quantize_info->dither &&
07654             (number_colors < MaxColormapSize))
07655           {
07656             Image
07657               *affinity_image;
07658 
07659             register PixelPacket
07660               *__restrict q;
07661 
07662             /*
07663               Improve image appearance with error diffusion.
07664             */
07665             affinity_image=AcquireImage((ImageInfo *) NULL);
07666             if (affinity_image == (Image *) NULL)
07667               ThrowXWindowFatalException(ResourceLimitFatalError,
07668                 "UnableToDitherImage",image->filename);
07669             affinity_image->columns=number_colors;
07670             affinity_image->rows=1;
07671             /*
07672               Initialize colormap image.
07673             */
07674             q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
07675               1,exception);
07676             if (q != (PixelPacket *) NULL)
07677               {
07678                 for (i=0; i < (long) number_colors; i++)
07679                 {
07680                   q->red=(Quantum) 0;
07681                   if (map_info->red_max != 0)
07682                     q->red=ScaleXToQuantum((unsigned long) (i/
07683                       map_info->red_mult),map_info->red_max);
07684                   q->green=(Quantum) 0;
07685                   if (map_info->green_max != 0)
07686                     q->green=ScaleXToQuantum((unsigned long) ((i/
07687                       map_info->green_mult) % (map_info->green_max+1)),
07688                       map_info->green_max);
07689                   q->blue=(Quantum) 0;
07690                   if (map_info->blue_max != 0)
07691                     q->blue=ScaleXToQuantum((unsigned long) (i %
07692                       map_info->green_mult),map_info->blue_max);
07693                   q->opacity=(Quantum) TransparentOpacity;
07694                   q++;
07695                 }
07696                 (void) SyncAuthenticPixels(affinity_image,exception);
07697                 (void) RemapImage(resource_info->quantize_info,image,
07698                   affinity_image);
07699               }
07700             XGetPixelPacket(display,visual_info,map_info,resource_info,image,
07701               pixel);
07702             (void) SetImageStorageClass(image,DirectClass);
07703             affinity_image=DestroyImage(affinity_image);
07704           }
07705       if (IsEventLogging())
07706         {
07707           (void) LogMagickEvent(X11Event,GetMagickModule(),
07708             "Standard Colormap:");
07709           (void) LogMagickEvent(X11Event,GetMagickModule(),
07710             "  colormap id: 0x%lx",map_info->colormap);
07711           (void) LogMagickEvent(X11Event,GetMagickModule(),
07712             "  red, green, blue max: %lu %lu %lu",map_info->red_max,
07713             map_info->green_max,map_info->blue_max);
07714           (void) LogMagickEvent(X11Event,GetMagickModule(),
07715             "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
07716             map_info->green_mult,map_info->blue_mult);
07717         }
07718       return;
07719     }
07720   if ((visual_info->klass != DirectColor) &&
07721       (visual_info->klass != TrueColor))
07722     if ((image->storage_class == DirectClass) ||
07723         ((int) image->colors > visual_info->colormap_size))
07724       {
07725         QuantizeInfo
07726           quantize_info;
07727 
07728         /*
07729           Image has more colors than the visual supports.
07730         */
07731         quantize_info=(*resource_info->quantize_info);
07732         quantize_info.number_colors=(unsigned long) visual_info->colormap_size;
07733         (void) QuantizeImage(&quantize_info,image);
07734       }
07735   /*
07736     Free previous and create new colormap.
07737   */
07738   (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
07739   colormap=XDefaultColormap(display,visual_info->screen);
07740   if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
07741     colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
07742       visual_info->visual,visual_info->klass == DirectColor ?
07743       AllocAll : AllocNone);
07744   if (colormap == (Colormap) NULL)
07745     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
07746       image->filename);
07747   /*
07748     Initialize the map and pixel info structures.
07749   */
07750   XGetMapInfo(visual_info,colormap,map_info);
07751   XGetPixelPacket(display,visual_info,map_info,resource_info,image,pixel);
07752   /*
07753     Allocating colors in server colormap is based on visual class.
07754   */
07755   switch (visual_info->klass)
07756   {
07757     case StaticGray:
07758     case StaticColor:
07759     {
07760       /*
07761         Define Standard Colormap for StaticGray or StaticColor visual.
07762       */
07763       number_colors=image->colors;
07764       colors=(XColor *) AcquireQuantumMemory((size_t)
07765         visual_info->colormap_size,sizeof(*colors));
07766       if (colors == (XColor *) NULL)
07767         ThrowXWindowFatalException(ResourceLimitFatalError,
07768           "UnableToCreateColormap",image->filename);
07769       p=colors;
07770       color.flags=(char) (DoRed | DoGreen | DoBlue);
07771       for (i=0; i < (long) image->colors; i++)
07772       {
07773         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
07774         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
07775         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
07776         if (visual_info->klass != StaticColor)
07777           {
07778             gray_value=(unsigned short) XPixelIntensity(&color);
07779             color.red=gray_value;
07780             color.green=gray_value;
07781             color.blue=gray_value;
07782           }
07783         status=XAllocColor(display,colormap,&color);
07784         if (status == False)
07785           {
07786             colormap=XCopyColormapAndFree(display,colormap);
07787             (void) XAllocColor(display,colormap,&color);
07788           }
07789         pixel->pixels[i]=color.pixel;
07790         *p++=color;
07791       }
07792       break;
07793     }
07794     case GrayScale:
07795     case PseudoColor:
07796     {
07797       unsigned int
07798         colormap_type;
07799 
07800       /*
07801         Define Standard Colormap for GrayScale or PseudoColor visual.
07802       */
07803       number_colors=image->colors;
07804       colors=(XColor *) AcquireQuantumMemory((size_t)
07805         visual_info->colormap_size,sizeof(*colors));
07806       if (colors == (XColor *) NULL)
07807         ThrowXWindowFatalException(ResourceLimitFatalError,
07808           "UnableToCreateColormap",image->filename);
07809       /*
07810         Preallocate our GUI colors.
07811       */
07812       (void) XAllocColor(display,colormap,&pixel->foreground_color);
07813       (void) XAllocColor(display,colormap,&pixel->background_color);
07814       (void) XAllocColor(display,colormap,&pixel->border_color);
07815       (void) XAllocColor(display,colormap,&pixel->matte_color);
07816       (void) XAllocColor(display,colormap,&pixel->highlight_color);
07817       (void) XAllocColor(display,colormap,&pixel->shadow_color);
07818       (void) XAllocColor(display,colormap,&pixel->depth_color);
07819       (void) XAllocColor(display,colormap,&pixel->trough_color);
07820       for (i=0; i < MaxNumberPens; i++)
07821         (void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
07822       /*
07823         Determine if image colors will "fit" into X server colormap.
07824       */
07825       colormap_type=resource_info->colormap;
07826       status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
07827         NULL,0,pixel->pixels,(unsigned int) image->colors);
07828       if (status != False)
07829         colormap_type=PrivateColormap;
07830       if (colormap_type == SharedColormap)
07831         {
07832           DiversityPacket
07833             *diversity;
07834 
07835           int
07836             y;
07837 
07838           register int
07839             x;
07840 
07841           unsigned short
07842             index;
07843 
07844           XColor
07845             *server_colors;
07846 
07847           /*
07848             Define Standard colormap for shared GrayScale or PseudoColor visual.
07849           */
07850           diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
07851             sizeof(*diversity));
07852           if (diversity == (DiversityPacket *) NULL)
07853             ThrowXWindowFatalException(ResourceLimitFatalError,
07854               "UnableToCreateColormap",image->filename);
07855           for (i=0; i < (long) image->colors; i++)
07856           {
07857             diversity[i].red=image->colormap[i].red;
07858             diversity[i].green=image->colormap[i].green;
07859             diversity[i].blue=image->colormap[i].blue;
07860             diversity[i].index=(unsigned short) i;
07861             diversity[i].count=0;
07862           }
07863           for (y=0; y < (int) image->rows; y++)
07864           {
07865             register long
07866               x;
07867 
07868             register PixelPacket
07869               *__restrict q;
07870 
07871             q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
07872             if (q == (PixelPacket *) NULL)
07873               break;
07874             indexes=GetAuthenticIndexQueue(image);
07875             for (x=(long) image->columns-1; x >= 0; x--)
07876               diversity[(long) indexes[x]].count++;
07877           }
07878           /*
07879             Sort colors by decreasing intensity.
07880           */
07881           qsort((void *) diversity,image->colors,sizeof(*diversity),
07882             IntensityCompare);
07883           for (i=0; i < (long) image->colors; )
07884           {
07885             diversity[i].count<<=4;  /* increase this colors popularity */
07886             i+=MagickMax((long) (image->colors >> 4),2);
07887           }
07888           diversity[image->colors-1].count<<=4;
07889           qsort((void *) diversity,image->colors,sizeof(*diversity),
07890             PopularityCompare);
07891           /*
07892             Allocate colors.
07893           */
07894           p=colors;
07895           color.flags=(char) (DoRed | DoGreen | DoBlue);
07896           for (i=0; i < (long) image->colors; i++)
07897           {
07898             index=diversity[i].index;
07899             color.red=
07900               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
07901             color.green=
07902               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
07903             color.blue=
07904               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
07905             if (visual_info->klass != PseudoColor)
07906               {
07907                 gray_value=(unsigned short) XPixelIntensity(&color);
07908                 color.red=gray_value;
07909                 color.green=gray_value;
07910                 color.blue=gray_value;
07911               }
07912             status=XAllocColor(display,colormap,&color);
07913             if (status == False)
07914               break;
07915             pixel->pixels[index]=color.pixel;
07916             *p++=color;
07917           }
07918           /*
07919             Read X server colormap.
07920           */
07921           server_colors=(XColor *) AcquireQuantumMemory((size_t)
07922             visual_info->colormap_size,sizeof(*server_colors));
07923           if (server_colors == (XColor *) NULL)
07924             ThrowXWindowFatalException(ResourceLimitFatalError,
07925               "UnableToCreateColormap",image->filename);
07926           for (x=visual_info->colormap_size-1; x >= 0; x--)
07927             server_colors[x].pixel=(unsigned long) x;
07928           (void) XQueryColors(display,colormap,server_colors,
07929             (int) MagickMin((unsigned int) visual_info->colormap_size,256));
07930           /*
07931             Select remaining colors from X server colormap.
07932           */
07933           for (; i < (long) image->colors; i++)
07934           {
07935             index=diversity[i].index;
07936             color.red=
07937               ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
07938             color.green=
07939               ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
07940             color.blue=
07941               ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
07942             if (visual_info->klass != PseudoColor)
07943               {
07944                 gray_value=(unsigned short) XPixelIntensity(&color);
07945                 color.red=gray_value;
07946                 color.green=gray_value;
07947                 color.blue=gray_value;
07948               }
07949             XBestPixel(display,colormap,server_colors,(unsigned int)
07950               visual_info->colormap_size,&color);
07951             pixel->pixels[index]=color.pixel;
07952             *p++=color;
07953           }
07954           if ((int) image->colors < visual_info->colormap_size)
07955             {
07956               /*
07957                 Fill up colors array-- more choices for pen colors.
07958               */
07959               retain_colors=MagickMin((unsigned int)
07960                (visual_info->colormap_size-image->colors),256);
07961               for (i=0; i < (long) retain_colors; i++)
07962                 *p++=server_colors[i];
07963               number_colors+=retain_colors;
07964             }
07965           server_colors=(XColor *) RelinquishMagickMemory(server_colors);
07966           diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
07967           break;
07968         }
07969       /*
07970         Define Standard colormap for private GrayScale or PseudoColor visual.
07971       */
07972       if (status == False)
07973         {
07974           /*
07975             Not enough colormap entries in the colormap-- Create a new colormap.
07976           */
07977           colormap=XCreateColormap(display,
07978             XRootWindow(display,visual_info->screen),visual_info->visual,
07979             AllocNone);
07980           if (colormap == (Colormap) NULL)
07981             ThrowXWindowFatalException(ResourceLimitFatalError,
07982               "UnableToCreateColormap",image->filename);
07983           map_info->colormap=colormap;
07984           if ((int) image->colors < visual_info->colormap_size)
07985             {
07986               /*
07987                 Retain colors from the default colormap to help lessens the
07988                 effects of colormap flashing.
07989               */
07990               retain_colors=MagickMin((unsigned int)
07991                 (visual_info->colormap_size-image->colors),256);
07992               p=colors+image->colors;
07993               for (i=0; i < (long) retain_colors; i++)
07994               {
07995                 p->pixel=(unsigned long) i;
07996                 p++;
07997               }
07998               (void) XQueryColors(display,
07999                 XDefaultColormap(display,visual_info->screen),
08000                 colors+image->colors,(int) retain_colors);
08001               /*
08002                 Transfer colors from default to private colormap.
08003               */
08004               (void) XAllocColorCells(display,colormap,MagickFalse,
08005                 (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
08006                 retain_colors);
08007               p=colors+image->colors;
08008               for (i=0; i < (long) retain_colors; i++)
08009               {
08010                 p->pixel=pixel->pixels[i];
08011                 p++;
08012               }
08013               (void) XStoreColors(display,colormap,colors+image->colors,
08014                 (int) retain_colors);
08015               number_colors+=retain_colors;
08016             }
08017           (void) XAllocColorCells(display,colormap,MagickFalse,
08018             (unsigned long *) NULL,0,pixel->pixels,(unsigned int)
08019             image->colors);
08020         }
08021       /*
08022         Store the image colormap.
08023       */
08024       p=colors;
08025       color.flags=(char) (DoRed | DoGreen | DoBlue);
08026       for (i=0; i < (long) image->colors; i++)
08027       {
08028         color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
08029         color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
08030         color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
08031         if (visual_info->klass != PseudoColor)
08032           {
08033             gray_value=(unsigned short) XPixelIntensity(&color);
08034             color.red=gray_value;
08035             color.green=gray_value;
08036             color.blue=gray_value;
08037           }
08038         color.pixel=pixel->pixels[i];
08039         *p++=color;
08040       }
08041       (void) XStoreColors(display,colormap,colors,(int) image->colors);
08042       break;
08043     }
08044     case TrueColor:
08045     case DirectColor:
08046     default:
08047     {
08048       MagickBooleanType
08049         linear_colormap;
08050 
08051       /*
08052         Define Standard Colormap for TrueColor or DirectColor visual.
08053       */
08054       number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
08055         (map_info->green_max*map_info->green_mult)+
08056         (map_info->blue_max*map_info->blue_mult)+1);
08057       linear_colormap=(number_colors > 4096) ||
08058         (((int) (map_info->red_max+1) == visual_info->colormap_size) &&
08059          ((int) (map_info->green_max+1) == visual_info->colormap_size) &&
08060          ((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
08061          MagickTrue : MagickFalse;
08062       if (linear_colormap != MagickFalse)
08063         number_colors=(unsigned long) visual_info->colormap_size;
08064       /*
08065         Allocate color array.
08066       */
08067       colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
08068       if (colors == (XColor *) NULL)
08069         ThrowXWindowFatalException(ResourceLimitFatalError,
08070           "UnableToCreateColormap",image->filename);
08071       /*
08072         Initialize linear color ramp.
08073       */
08074       p=colors;
08075       color.flags=(char) (DoRed | DoGreen | DoBlue);
08076       if (linear_colormap != MagickFalse)
08077         for (i=0; i < (long) number_colors; i++)
08078         {
08079           color.blue=(unsigned short) 0;
08080           if (map_info->blue_max != 0)
08081             color.blue=(unsigned short) ((unsigned long)
08082               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
08083           color.green=color.blue;
08084           color.red=color.blue;
08085           color.pixel=XStandardPixel(map_info,&color);
08086           *p++=color;
08087         }
08088       else
08089         for (i=0; i < (long) number_colors; i++)
08090         {
08091           color.red=(unsigned short) 0;
08092           if (map_info->red_max != 0)
08093             color.red=(unsigned short) ((unsigned long)
08094               ((65535L*(i/map_info->red_mult))/map_info->red_max));
08095           color.green=(unsigned int) 0;
08096           if (map_info->green_max != 0)
08097             color.green=(unsigned short) ((unsigned long)
08098               ((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
08099                 map_info->green_max));
08100           color.blue=(unsigned short) 0;
08101           if (map_info->blue_max != 0)
08102             color.blue=(unsigned short) ((unsigned long)
08103               ((65535L*(i % map_info->green_mult))/map_info->blue_max));
08104           color.pixel=XStandardPixel(map_info,&color);
08105           *p++=color;
08106         }
08107       if ((visual_info->klass == DirectColor) &&
08108           (colormap != XDefaultColormap(display,visual_info->screen)))
08109         (void) XStoreColors(display,colormap,colors,(int) number_colors);
08110       else
08111         for (i=0; i < (long) number_colors; i++)
08112           (void) XAllocColor(display,colormap,&colors[i]);
08113       break;
08114     }
08115   }
08116   if ((visual_info->klass != DirectColor) &&
08117       (visual_info->klass != TrueColor))
08118     {
08119       /*
08120         Set foreground, background, border, etc. pixels.
08121       */
08122       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
08123         &pixel->foreground_color);
08124       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
08125         &pixel->background_color);
08126       if (pixel->background_color.pixel == pixel->foreground_color.pixel)
08127         {
08128           /*
08129             Foreground and background colors must differ.
08130           */
08131           pixel->background_color.red=(~pixel->foreground_color.red);
08132           pixel->background_color.green=
08133             (~pixel->foreground_color.green);
08134           pixel->background_color.blue=
08135             (~pixel->foreground_color.blue);
08136           XBestPixel(display,colormap,colors,(unsigned int) number_colors,
08137             &pixel->background_color);
08138         }
08139       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
08140         &pixel->border_color);
08141       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
08142         &pixel->matte_color);
08143       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
08144         &pixel->highlight_color);
08145       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
08146         &pixel->shadow_color);
08147       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
08148         &pixel->depth_color);
08149       XBestPixel(display,colormap,colors,(unsigned int) number_colors,
08150         &pixel->trough_color);
08151       for (i=0; i < MaxNumberPens; i++)
08152       {
08153         XBestPixel(display,colormap,colors,(unsigned int) number_colors,
08154           &pixel->pen_colors[i]);
08155         pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
08156       }
08157       pixel->colors=image->colors+MaxNumberPens;
08158     }
08159   colors=(XColor *) RelinquishMagickMemory(colors);
08160   if (IsEventLogging())
08161     {
08162       (void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
08163       (void) LogMagickEvent(X11Event,GetMagickModule(),"  colormap id: 0x%lx",
08164         map_info->colormap);
08165       (void) LogMagickEvent(X11Event,GetMagickModule(),
08166         "  red, green, blue max: %lu %lu %lu",map_info->red_max,
08167         map_info->green_max,map_info->blue_max);
08168       (void) LogMagickEvent(X11Event,GetMagickModule(),
08169         "  red, green, blue mult: %lu %lu %lu",map_info->red_mult,
08170         map_info->green_mult,map_info->blue_mult);
08171     }
08172 }
08173 
08174 /*
08175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08176 %                                                                             %
08177 %                                                                             %
08178 %                                                                             %
08179 %   X M a k e W i n d o w                                                     %
08180 %                                                                             %
08181 %                                                                             %
08182 %                                                                             %
08183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08184 %
08185 %  XMakeWindow() creates an X11 window.
08186 %
08187 %  The format of the XMakeWindow method is:
08188 %
08189 %      void XMakeWindow(Display *display,Window parent,char **argv,int argc,
08190 %        XClassHint *class_hint,XWMHints *manager_hints,
08191 %        XWindowInfo *window_info)
08192 %
08193 %  A description of each parameter follows:
08194 %
08195 %    o display: Specifies a connection to an X server; returned from
08196 %      XOpenDisplay.
08197 %
08198 %    o parent: Specifies the parent window_info.
08199 %
08200 %    o argv: Specifies the application's argument list.
08201 %
08202 %    o argc: Specifies the number of arguments.
08203 %
08204 %    o class_hint: Specifies a pointer to a X11 XClassHint structure.
08205 %
08206 %    o manager_hints: Specifies a pointer to a X11 XWMHints structure.
08207 %
08208 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
08209 %
08210 */
08211 MagickExport void XMakeWindow(Display *display,Window parent,char **argv,
08212   int argc,XClassHint *class_hint,XWMHints *manager_hints,
08213   XWindowInfo *window_info)
08214 {
08215 #define MinWindowSize  64
08216 
08217   Atom
08218     atom_list[2];
08219 
08220   int
08221     gravity;
08222 
08223   static XTextProperty
08224     icon_name,
08225     window_name;
08226 
08227   Status
08228     status;
08229 
08230   XSizeHints
08231     *size_hints;
08232 
08233   /*
08234     Set window info hints.
08235   */
08236   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
08237   assert(display != (Display *) NULL);
08238   assert(window_info != (XWindowInfo *) NULL);
08239   size_hints=XAllocSizeHints();
08240   if (size_hints == (XSizeHints *) NULL)
08241     ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
08242   size_hints->flags=(long) window_info->flags;
08243   size_hints->x=window_info->x;
08244   size_hints->y=window_info->y;
08245   size_hints->width=(int) window_info->width;
08246   size_hints->height=(int) window_info->height;
08247   if (window_info->immutable != MagickFalse)
08248     {
08249       /*
08250         Window size cannot be changed.
08251       */
08252       size_hints->min_width=size_hints->width;
08253       size_hints->min_height=size_hints->height;
08254       size_hints->max_width=size_hints->width;
08255       size_hints->max_height=size_hints->height;
08256       size_hints->flags|=PMinSize;
08257       size_hints->flags|=PMaxSize;
08258     }
08259   else
08260     {
08261       /*
08262         Window size can be changed.
08263       */
08264       size_hints->min_width=(int) window_info->min_width;
08265       size_hints->min_height=(int) window_info->min_height;
08266       size_hints->flags|=PResizeInc;
08267       size_hints->width_inc=(int) window_info->width_inc;
08268       size_hints->height_inc=(int) window_info->height_inc;
08269 #if !defined(PRE_R4_ICCCM)
08270       size_hints->flags|=PBaseSize;
08271       size_hints->base_width=size_hints->width_inc;
08272       size_hints->base_height=size_hints->height_inc;
08273 #endif
08274     }
08275   gravity=NorthWestGravity;
08276   if (window_info->geometry != (char *) NULL)
08277     {
08278       char
08279         default_geometry[MaxTextExtent],
08280         geometry[MaxTextExtent];
08281 
08282       int
08283         flags;
08284 
08285       register char
08286         *p;
08287 
08288       /*
08289         User specified geometry.
08290       */
08291       (void) FormatMagickString(default_geometry,MaxTextExtent,"%dx%d",
08292         size_hints->width,size_hints->height);
08293       (void) CopyMagickString(geometry,window_info->geometry,MaxTextExtent);
08294       p=geometry;
08295       while (strlen(p) != 0)
08296       {
08297         if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
08298           p++;
08299         else
08300           (void) CopyMagickString(p,p+1,MaxTextExtent);
08301       }
08302       flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
08303         window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
08304         &size_hints->width,&size_hints->height,&gravity);
08305       if ((flags & WidthValue) && (flags & HeightValue))
08306         size_hints->flags|=USSize;
08307       if ((flags & XValue) && (flags & YValue))
08308         {
08309           size_hints->flags|=USPosition;
08310           window_info->x=size_hints->x;
08311           window_info->y=size_hints->y;
08312         }
08313     }
08314 #if !defined(PRE_R4_ICCCM)
08315   size_hints->win_gravity=gravity;
08316   size_hints->flags|=PWinGravity;
08317 #endif
08318   if (window_info->id == (Window) NULL)
08319     window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
08320       (unsigned int) size_hints->width,(unsigned int) size_hints->height,
08321       window_info->border_width,(int) window_info->depth,InputOutput,
08322       window_info->visual,window_info->mask,&window_info->attributes);
08323   else
08324     {
08325       MagickStatusType
08326         mask;
08327 
08328       XEvent
08329         sans_event;
08330 
08331       XWindowChanges
08332         window_changes;
08333 
08334       /*
08335         Window already exists;  change relevant attributes.
08336       */
08337       (void) XChangeWindowAttributes(display,window_info->id,window_info->mask,
08338         &window_info->attributes);
08339       mask=ConfigureNotify;
08340       while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
08341       window_changes.x=window_info->x;
08342       window_changes.y=window_info->y;
08343       window_changes.width=(int) window_info->width;
08344       window_changes.height=(int) window_info->height;
08345       mask=(MagickStatusType) (CWWidth | CWHeight);
08346       if (window_info->flags & USPosition)
08347         mask|=CWX | CWY;
08348       (void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
08349         mask,&window_changes);
08350     }
08351   if (window_info->id == (Window) NULL)
08352     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
08353       window_info->name);
08354   status=XStringListToTextProperty(&window_info->name,1,&window_name);
08355   if (status == False)
08356     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
08357       window_info->name);
08358   status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
08359   if (status == False)
08360     ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
08361       window_info->icon_name);
08362   if (window_info->icon_geometry != (char *) NULL)
08363     {
08364       int
08365         flags,
08366         height,
08367         width;
08368 
08369       /*
08370         User specified icon geometry.
08371       */
08372       size_hints->flags|=USPosition;
08373       flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
08374         (char *) NULL,0,size_hints,&manager_hints->icon_x,
08375         &manager_hints->icon_y,&width,&height,&gravity);
08376       if ((flags & XValue) && (flags & YValue))
08377         manager_hints->flags|=IconPositionHint;
08378     }
08379   XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
08380     size_hints,manager_hints,class_hint);
08381   if (window_name.value != (void *) NULL)
08382     {
08383       (void) XFree((void *) window_name.value);
08384       window_name.value=(unsigned char *) NULL;
08385       window_name.nitems=0;
08386     }
08387   if (icon_name.value != (void *) NULL)
08388     {
08389       (void) XFree((void *) icon_name.value);
08390       icon_name.value=(unsigned char *) NULL;
08391       icon_name.nitems=0;
08392     }
08393   atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
08394   atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
08395   (void) XSetWMProtocols(display,window_info->id,atom_list,2);
08396   (void) XFree((void *) size_hints);
08397   if (window_info->shape != MagickFalse)
08398     {
08399 #if defined(MAGICKCORE_HAVE_SHAPE)
08400       int
08401         error_base,
08402         event_base;
08403 
08404       /*
08405         Can we apply a non-rectangular shaping mask?
08406       */
08407       error_base=0;
08408       event_base=0;
08409       if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
08410         window_info->shape=MagickFalse;
08411 #else
08412       window_info->shape=MagickFalse;
08413 #endif
08414     }
08415   if (window_info->shared_memory)
08416     {
08417 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
08418       /*
08419         Can we use shared memory with this window?
08420       */
08421       if (XShmQueryExtension(display) == 0)
08422         window_info->shared_memory=MagickFalse;
08423 #else
08424       window_info->shared_memory=MagickFalse;
08425 #endif
08426     }
08427   window_info->image=NewImageList();
08428   window_info->destroy=MagickFalse;
08429 }
08430 
08431 /*
08432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08433 %                                                                             %
08434 %                                                                             %
08435 %                                                                             %
08436 %   X M a g i c k P r o g r e s s M o n i t o r                               %
08437 %                                                                             %
08438 %                                                                             %
08439 %                                                                             %
08440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08441 %
08442 %  XMagickProgressMonitor() displays the progress a task is making in
08443 %  completing a task.
08444 %
08445 %  The format of the XMagickProgressMonitor method is:
08446 %
08447 %      void XMagickProgressMonitor(const char *task,
08448 %        const MagickOffsetType quantum,const MagickSizeType span,
08449 %        void *client_data)
08450 %
08451 %  A description of each parameter follows:
08452 %
08453 %    o task: Identifies the task in progress.
08454 %
08455 %    o quantum: Specifies the quantum position within the span which represents
08456 %      how much progress has been made in completing a task.
08457 %
08458 %    o span: Specifies the span relative to completing a task.
08459 %
08460 %    o client_data: Pointer to any client data.
08461 %
08462 */
08463 
08464 static const char *GetLocaleMonitorMessage(const char *text)
08465 {
08466   char
08467     message[MaxTextExtent],
08468     tag[MaxTextExtent];
08469 
08470   const char
08471     *locale_message;
08472 
08473   register char
08474     *p;
08475 
08476   (void) CopyMagickMemory(tag,text,MaxTextExtent);
08477   p=strrchr(tag,'/');
08478   if (p != (char *) NULL)
08479     *p='\0';
08480   (void) FormatMagickString(message,MaxTextExtent,"Monitor/%s",tag);
08481   locale_message=GetLocaleMessage(message);
08482   if (locale_message == message)
08483     return(text);
08484   return(locale_message);
08485 }
08486 
08487 MagickExport MagickBooleanType XMagickProgressMonitor(const char *tag,
08488   const MagickOffsetType quantum,const MagickSizeType span,
08489   void *magick_unused(client_data))
08490 {
08491   XWindows
08492     *windows;
08493 
08494   windows=XSetWindows((XWindows *) ~0);
08495   if (windows == (XWindows *) NULL)
08496     return(MagickTrue);
08497   if (windows->info.mapped != MagickFalse)
08498     XProgressMonitorWidget(windows->display,windows,
08499       GetLocaleMonitorMessage(tag),quantum,span);
08500   return(MagickTrue);
08501 }
08502 
08503 /*
08504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08505 %                                                                             %
08506 %                                                                             %
08507 %                                                                             %
08508 %   X Q u e r y C o l o r D a t a b a s e                                     %
08509 %                                                                             %
08510 %                                                                             %
08511 %                                                                             %
08512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08513 %
08514 %  XQueryColorDatabase() looks up a RGB values for a color given in the target
08515 %  string.
08516 %
08517 %  The format of the XQueryColorDatabase method is:
08518 %
08519 %      MagickBooleanType XQueryColorDatabase(const char *target,XColor *color)
08520 %
08521 %  A description of each parameter follows:
08522 %
08523 %    o target: Specifies the color to lookup in the X color database.
08524 %
08525 %    o color: A pointer to an PixelPacket structure.  The RGB value of the target
08526 %      color is returned as this value.
08527 %
08528 */
08529 MagickExport MagickBooleanType XQueryColorDatabase(const char *target,
08530   XColor *color)
08531 {
08532   Colormap
08533     colormap;
08534 
08535   static Display
08536     *display = (Display *) NULL;
08537 
08538   Status
08539     status;
08540 
08541   XColor
08542     xcolor;
08543 
08544   /*
08545     Initialize color return value.
08546   */
08547   assert(color != (XColor *) NULL);
08548   color->red=0;
08549   color->green=0;
08550   color->blue=0;
08551   color->flags=(char) (DoRed | DoGreen | DoBlue);
08552   if ((target == (char *) NULL) || (*target == '\0'))
08553     target="#ffffffffffff";
08554   /*
08555     Let the X server define the color for us.
08556   */
08557   if (display == (Display *) NULL)
08558     display=XOpenDisplay((char *) NULL);
08559   if (display == (Display *) NULL)
08560     {
08561       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target);
08562       return(MagickFalse);
08563     }
08564   colormap=XDefaultColormap(display,XDefaultScreen(display));
08565   status=XParseColor(display,colormap,(char *) target,&xcolor);
08566   if (status == False)
08567     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",target)
08568   else
08569     {
08570       color->red=xcolor.red;
08571       color->green=xcolor.green;
08572       color->blue=xcolor.blue;
08573       color->flags=xcolor.flags;
08574     }
08575   return(status != False ? MagickTrue : MagickFalse);
08576 }
08577 
08578 /*
08579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08580 %                                                                             %
08581 %                                                                             %
08582 %                                                                             %
08583 %   X Q u e r y P o s i t i o n                                               %
08584 %                                                                             %
08585 %                                                                             %
08586 %                                                                             %
08587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08588 %
08589 %  XQueryPosition() gets the pointer coordinates relative to a window.
08590 %
08591 %  The format of the XQueryPosition method is:
08592 %
08593 %      void XQueryPosition(Display *display,const Window window,int *x,int *y)
08594 %
08595 %  A description of each parameter follows:
08596 %
08597 %    o display: Specifies a connection to an X server;  returned from
08598 %      XOpenDisplay.
08599 %
08600 %    o window: Specifies a pointer to a Window.
08601 %
08602 %    o x: Return the x coordinate of the pointer relative to the origin of the
08603 %      window.
08604 %
08605 %    o y: Return the y coordinate of the pointer relative to the origin of the
08606 %      window.
08607 %
08608 */
08609 MagickExport void XQueryPosition(Display *display,const Window window,int *x,int *y)
08610 {
08611   int
08612     x_root,
08613     y_root;
08614 
08615   unsigned int
08616     mask;
08617 
08618   Window
08619     root_window;
08620 
08621   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
08622   assert(display != (Display *) NULL);
08623   assert(window != (Window) NULL);
08624   assert(x != (int *) NULL);
08625   assert(y != (int *) NULL);
08626   (void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
08627     x,y,&mask);
08628 }
08629 
08630 /*
08631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08632 %                                                                             %
08633 %                                                                             %
08634 %                                                                             %
08635 %   X R e f r e s h W i n d o w                                               %
08636 %                                                                             %
08637 %                                                                             %
08638 %                                                                             %
08639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08640 %
08641 %  XRefreshWindow() refreshes an image in a X window.
08642 %
08643 %  The format of the XRefreshWindow method is:
08644 %
08645 %      void XRefreshWindow(Display *display,const XWindowInfo *window,
08646 %        const XEvent *event)
08647 %
08648 %  A description of each parameter follows:
08649 %
08650 %    o display: Specifies a connection to an X server;  returned from
08651 %      XOpenDisplay.
08652 %
08653 %    o window: Specifies a pointer to a XWindowInfo structure.
08654 %
08655 %    o event: Specifies a pointer to a XEvent structure.  If it is NULL,
08656 %      the entire image is refreshed.
08657 %
08658 */
08659 MagickExport void XRefreshWindow(Display *display,const XWindowInfo *window,
08660   const XEvent *event)
08661 {
08662   int
08663     x,
08664     y;
08665 
08666   unsigned int
08667     height,
08668     width;
08669 
08670   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
08671   assert(display != (Display *) NULL);
08672   assert(window != (XWindowInfo *) NULL);
08673   if (window->ximage == (XImage *) NULL)
08674     return;
08675   if (event != (XEvent *) NULL)
08676     {
08677       /*
08678         Determine geometry from expose event.
08679       */
08680       x=event->xexpose.x;
08681       y=event->xexpose.y;
08682       width=(unsigned int) event->xexpose.width;
08683       height=(unsigned int) event->xexpose.height;
08684     }
08685   else
08686     {
08687       XEvent
08688         sans_event;
08689 
08690       /*
08691         Refresh entire window; discard outstanding expose events.
08692       */
08693       x=0;
08694       y=0;
08695       width=window->width;
08696       height=window->height;
08697       while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
08698     }
08699   /*
08700     Check boundary conditions.
08701   */
08702   if ((window->ximage->width-(x+window->x)) < (int) width)
08703     width=(unsigned int) (window->ximage->width-(x+window->x));
08704   if ((window->ximage->height-(y+window->y)) < (int) height)
08705     height=(unsigned int) (window->ximage->height-(y+window->y));
08706   /*
08707     Refresh image.
08708   */
08709   if (window->matte_pixmap != (Pixmap) NULL)
08710     {
08711 #if defined(MAGICKCORE_HAVE_SHAPE)
08712       if (window->shape != MagickFalse)
08713         XShapeCombineMask(display,window->id,ShapeBounding,0,0,
08714           window->matte_pixmap,ShapeSet);
08715 #endif
08716       (void) XSetClipMask(display,window->annotate_context,
08717         window->matte_pixmap);
08718     }
08719   if (window->pixmap != (Pixmap) NULL)
08720     {
08721       if (window->depth > 1)
08722         (void) XCopyArea(display,window->pixmap,window->id,
08723           window->annotate_context,x+window->x,y+window->y,width,height,x,y);
08724       else
08725         (void) XCopyPlane(display,window->pixmap,window->id,
08726           window->highlight_context,x+window->x,y+window->y,width,height,x,y,
08727           1L);
08728     }
08729   else
08730     {
08731 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
08732       if (window->shared_memory)
08733         (void) XShmPutImage(display,window->id,window->annotate_context,
08734           window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
08735 #endif
08736       if (window->shared_memory == MagickFalse)
08737         (void) XPutImage(display,window->id,window->annotate_context,
08738           window->ximage,x+window->x,y+window->y,x,y,width,height);
08739     }
08740   if (window->matte_pixmap != (Pixmap) NULL)
08741     (void) XSetClipMask(display,window->annotate_context,None);
08742   (void) XFlush(display);
08743 }
08744 
08745 /*
08746 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08747 %                                                                             %
08748 %                                                                             %
08749 %                                                                             %
08750 %   X R e m o t e C o m m a n d                                               %
08751 %                                                                             %
08752 %                                                                             %
08753 %                                                                             %
08754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08755 %
08756 %  XRemoteCommand() forces a remote display(1) to display the specified
08757 %  image filename.
08758 %
08759 %  The format of the XRemoteCommand method is:
08760 %
08761 %      MagickBooleanType XRemoteCommand(Display *display,const char *window,
08762 %        const char *filename)
08763 %
08764 %  A description of each parameter follows:
08765 %
08766 %    o display: Specifies a connection to an X server; returned from
08767 %      XOpenDisplay.
08768 %
08769 %    o window: Specifies the name or id of an X window.
08770 %
08771 %    o filename: the name of the image filename to display.
08772 %
08773 */
08774 MagickExport MagickBooleanType XRemoteCommand(Display *display,
08775   const char *window,const char *filename)
08776 {
08777   Atom
08778     remote_atom;
08779 
08780   Window
08781     remote_window,
08782     root_window;
08783 
08784   assert(filename != (char *) NULL);
08785   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
08786   if (display == (Display *) NULL)
08787     display=XOpenDisplay((char *) NULL);
08788   if (display == (Display *) NULL)
08789     {
08790       ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
08791       return(MagickFalse);
08792     }
08793   remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
08794   remote_window=(Window) NULL;
08795   root_window=XRootWindow(display,XDefaultScreen(display));
08796   if (window != (char *) NULL)
08797     {
08798       /*
08799         Search window hierarchy and identify any clients by name or ID.
08800       */
08801       if (isdigit((unsigned char) *window) != 0)
08802         remote_window=XWindowByID(display,root_window,(Window)
08803           strtol((char *) window,(char **) NULL,0));
08804       if (remote_window == (Window) NULL)
08805         remote_window=XWindowByName(display,root_window,window);
08806     }
08807   if (remote_window == (Window) NULL)
08808     remote_window=XWindowByProperty(display,root_window,remote_atom);
08809   if (remote_window == (Window) NULL)
08810     {
08811       ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
08812         filename);
08813       return(MagickFalse);
08814     }
08815   /*
08816     Send remote command.
08817   */
08818   remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
08819   (void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
08820     PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
08821   (void) XSync(display,MagickFalse);
08822   return(MagickTrue);
08823 }
08824 
08825 /*
08826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08827 %                                                                             %
08828 %                                                                             %
08829 %                                                                             %
08830 %   X R e t a i n W i n d o w C o l o r s                                     %
08831 %                                                                             %
08832 %                                                                             %
08833 %                                                                             %
08834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08835 %
08836 %  XRetainWindowColors() sets X11 color resources on a window.  This preserves
08837 %  the colors associated with an image displayed on the window.
08838 %
08839 %  The format of the XRetainWindowColors method is:
08840 %
08841 %      void XRetainWindowColors(Display *display,const Window window)
08842 %
08843 %  A description of each parameter follows:
08844 %
08845 %    o display: Specifies a connection to an X server; returned from
08846 %      XOpenDisplay.
08847 %
08848 %    o window: Specifies a pointer to a XWindowInfo structure.
08849 %
08850 */
08851 MagickExport void XRetainWindowColors(Display *display,const Window window)
08852 {
08853   Atom
08854     property;
08855 
08856   Pixmap
08857     pixmap;
08858 
08859   /*
08860     Put property on the window.
08861   */
08862   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
08863   assert(display != (Display *) NULL);
08864   assert(window != (Window) NULL);
08865   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
08866   if (property == (Atom) NULL)
08867     {
08868       ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
08869         "_XSETROOT_ID");
08870       return;
08871     }
08872   pixmap=XCreatePixmap(display,window,1,1,1);
08873   if (pixmap == (Pixmap) NULL)
08874     {
08875       ThrowXWindowFatalException(XServerError,"UnableToCreateBitmap","");
08876       return;
08877     }
08878   (void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
08879     (unsigned char *) &pixmap,1);
08880   (void) XSetCloseDownMode(display,RetainPermanent);
08881 }
08882 
08883 /*
08884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08885 %                                                                             %
08886 %                                                                             %
08887 %                                                                             %
08888 %   X S e l e c t W i n d o w                                                 %
08889 %                                                                             %
08890 %                                                                             %
08891 %                                                                             %
08892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
08893 %
08894 %  XSelectWindow() allows a user to select a window using the mouse.  If the
08895 %  mouse moves, a cropping rectangle is drawn and the extents of the rectangle
08896 %  is returned in the crop_info structure.
08897 %
08898 %  The format of the XSelectWindow function is:
08899 %
08900 %      target_window=XSelectWindow(display,crop_info)
08901 %
08902 %  A description of each parameter follows:
08903 %
08904 %    o window: XSelectWindow returns the window id.
08905 %
08906 %    o display: Specifies a pointer to the Display structure;  returned from
08907 %      XOpenDisplay.
08908 %
08909 %    o crop_info: Specifies a pointer to a RectangleInfo structure.  It
08910 %      contains the extents of any cropping rectangle.
08911 %
08912 %
08913 */
08914 static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
08915 {
08916 #define MinimumCropArea  (unsigned int) 9
08917 
08918   Cursor
08919     target_cursor;
08920 
08921   GC
08922     annotate_context;
08923 
08924   int
08925     presses,
08926     x_offset,
08927     y_offset;
08928 
08929   Status
08930     status;
08931 
08932   Window
08933     root_window,
08934     target_window;
08935 
08936   XEvent
08937     event;
08938 
08939   XGCValues
08940     context_values;
08941 
08942   /*
08943     Initialize graphic context.
08944   */
08945   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
08946   assert(display != (Display *) NULL);
08947   assert(crop_info != (RectangleInfo *) NULL);
08948   root_window=XRootWindow(display,XDefaultScreen(display));
08949   context_values.background=XBlackPixel(display,XDefaultScreen(display));
08950   context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
08951   context_values.function=GXinvert;
08952   context_values.plane_mask=
08953     context_values.background ^ context_values.foreground;
08954   context_values.subwindow_mode=IncludeInferiors;
08955   annotate_context=XCreateGC(display,root_window,(unsigned long) (GCBackground |
08956     GCForeground | GCFunction | GCSubwindowMode),&context_values);
08957   if (annotate_context == (GC) NULL)
08958     return(MagickFalse);
08959   /*
08960     Grab the pointer using target cursor.
08961   */
08962   target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
08963     XDefaultScreen(display)),(char * ) "white",(char * ) "black");
08964   status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
08965     (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
08966     GrabModeAsync,root_window,target_cursor,CurrentTime);
08967   if (status != GrabSuccess)
08968     {
08969       ThrowXWindowFatalException(XServerError,"UnableToGrabMouse","");
08970       return((Window) NULL);
08971     }
08972   /*
08973     Select a window.
08974   */
08975   crop_info->width=0;
08976   crop_info->height=0;
08977   presses=0;
08978   target_window=(Window) NULL;
08979   x_offset=0;
08980   y_offset=0;
08981   do
08982   {
08983     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
08984       (void) XDrawRectangle(display,root_window,annotate_context,
08985         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
08986         (unsigned int) crop_info->height-1);
08987     /*
08988       Allow another event.
08989     */
08990     (void) XAllowEvents(display,SyncPointer,CurrentTime);
08991     (void) XWindowEvent(display,root_window,ButtonPressMask |
08992       ButtonReleaseMask | ButtonMotionMask,&event);
08993     if ((crop_info->width*crop_info->height) >= MinimumCropArea)
08994       (void) XDrawRectangle(display,root_window,annotate_context,
08995         (int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
08996         (unsigned int) crop_info->height-1);
08997     switch (event.type)
08998     {
08999       case ButtonPress:
09000       {
09001         target_window=XGetSubwindow(display,event.xbutton.subwindow,
09002           event.xbutton.x,event.xbutton.y);
09003         if (target_window == (Window) NULL)
09004           target_window=root_window;
09005         x_offset=event.xbutton.x_root;
09006         y_offset=event.xbutton.y_root;
09007         crop_info->x=x_offset;
09008         crop_info->y=y_offset;
09009         crop_info->width=0;
09010         crop_info->height=0;
09011         presses++;
09012         break;
09013       }
09014       case ButtonRelease:
09015       {
09016         presses--;
09017         break;
09018       }
09019       case MotionNotify:
09020       {
09021         /*
09022           Discard pending button motion events.
09023         */
09024         while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
09025         crop_info->x=event.xmotion.x;
09026         crop_info->y=event.xmotion.y;
09027         /*
09028           Check boundary conditions.
09029         */
09030         if ((int) crop_info->x < x_offset)
09031           crop_info->width=(unsigned int) (x_offset-crop_info->x);
09032         else
09033           {
09034             crop_info->width=(unsigned int) (crop_info->x-x_offset);
09035             crop_info->x=x_offset;
09036           }
09037         if ((int) crop_info->y < y_offset)
09038           crop_info->height=(unsigned int) (y_offset-crop_info->y);
09039         else
09040           {
09041             crop_info->height=(unsigned int) (crop_info->y-y_offset);
09042             crop_info->y=y_offset;
09043           }
09044       }
09045       default:
09046         break;
09047     }
09048   } while ((target_window == (Window) NULL) || (presses > 0));
09049   (void) XUngrabPointer(display,CurrentTime);
09050   (void) XFreeCursor(display,target_cursor);
09051   (void) XFreeGC(display,annotate_context);
09052   if ((crop_info->width*crop_info->height) < MinimumCropArea)
09053     {
09054       crop_info->width=0;
09055       crop_info->height=0;
09056     }
09057   if ((crop_info->width != 0) && (crop_info->height != 0))
09058     target_window=root_window;
09059   return(target_window);
09060 }
09061 
09062 /*
09063 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09064 %                                                                             %
09065 %                                                                             %
09066 %                                                                             %
09067 %   X S e t C u r s o r S t a t e                                             %
09068 %                                                                             %
09069 %                                                                             %
09070 %                                                                             %
09071 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09072 %
09073 %  XSetCursorState() sets the cursor state to busy, otherwise the cursor are
09074 %  reset to their default.
09075 %
09076 %  The format of the XXSetCursorState method is:
09077 %
09078 %      XSetCursorState(display,windows,const MagickStatusType state)
09079 %
09080 %  A description of each parameter follows:
09081 %
09082 %    o display: Specifies a connection to an X server;  returned from
09083 %      XOpenDisplay.
09084 %
09085 %    o windows: Specifies a pointer to a XWindows structure.
09086 %
09087 %    o state: An unsigned integer greater than 0 sets the cursor state
09088 %      to busy, otherwise the cursor are reset to their default.
09089 %
09090 */
09091 MagickExport void XSetCursorState(Display *display,XWindows *windows,
09092   const MagickStatusType state)
09093 {
09094   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
09095   assert(display != (Display *) NULL);
09096   assert(windows != (XWindows *) NULL);
09097   if (state)
09098     {
09099       (void) XCheckDefineCursor(display,windows->image.id,
09100         windows->image.busy_cursor);
09101       (void) XCheckDefineCursor(display,windows->pan.id,
09102         windows->pan.busy_cursor);
09103       (void) XCheckDefineCursor(display,windows->magnify.id,
09104         windows->magnify.busy_cursor);
09105       (void) XCheckDefineCursor(display,windows->command.id,
09106         windows->command.busy_cursor);
09107     }
09108   else
09109     {
09110       (void) XCheckDefineCursor(display,windows->image.id,
09111         windows->image.cursor);
09112       (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
09113       (void) XCheckDefineCursor(display,windows->magnify.id,
09114         windows->magnify.cursor);
09115       (void) XCheckDefineCursor(display,windows->command.id,
09116         windows->command.cursor);
09117       (void) XCheckDefineCursor(display,windows->command.id,
09118         windows->widget.cursor);
09119       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
09120     }
09121   windows->info.mapped=MagickFalse;
09122 }
09123 
09124 /*
09125 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09126 %                                                                             %
09127 %                                                                             %
09128 %                                                                             %
09129 %   X S e t W i n d o w s                                                     %
09130 %                                                                             %
09131 %                                                                             %
09132 %                                                                             %
09133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09134 %
09135 %  XSetWindows() sets the X windows structure if the windows info is specified.
09136 %  Otherwise the current windows structure is returned.
09137 %
09138 %  The format of the XSetWindows method is:
09139 %
09140 %      XWindows *XSetWindows(XWindows *windows_info)
09141 %
09142 %  A description of each parameter follows:
09143 %
09144 %    o windows_info: Initialize the Windows structure with this information.
09145 %
09146 */
09147 MagickExport XWindows *XSetWindows(XWindows *windows_info)
09148 {
09149   static XWindows
09150     *windows = (XWindows *) NULL;
09151 
09152   if (windows_info != (XWindows *) ~0)
09153     {
09154       windows=(XWindows *) RelinquishMagickMemory(windows);
09155       windows=windows_info;
09156     }
09157   return(windows);
09158 }
09159 /*
09160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09161 %                                                                             %
09162 %                                                                             %
09163 %                                                                             %
09164 %   X U s e r P r e f e r e n c e s                                           %
09165 %                                                                             %
09166 %                                                                             %
09167 %                                                                             %
09168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09169 %
09170 %  XUserPreferences() saves the preferences in a configuration file in the
09171 %  users' home directory.
09172 %
09173 %  The format of the XUserPreferences method is:
09174 %
09175 %      void XUserPreferences(XResourceInfo *resource_info)
09176 %
09177 %  A description of each parameter follows:
09178 %
09179 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
09180 %
09181 */
09182 MagickExport void XUserPreferences(XResourceInfo *resource_info)
09183 {
09184 #if defined(X11_PREFERENCES_PATH)
09185   char
09186     cache[MaxTextExtent],
09187     filename[MaxTextExtent],
09188     specifier[MaxTextExtent];
09189 
09190   const char
09191     *value;
09192 
09193   XrmDatabase
09194     preferences_database;
09195 
09196   /*
09197     Save user preferences to the client configuration file.
09198   */
09199   assert(resource_info != (XResourceInfo *) NULL);
09200   preferences_database=XrmGetStringDatabase("");
09201   (void) FormatMagickString(specifier,MaxTextExtent,"%s.backdrop",
09202     GetClientName());
09203   value=resource_info->backdrop ? "True" : "False";
09204   XrmPutStringResource(&preferences_database,specifier,(char *) value);
09205   (void) FormatMagickString(specifier,MaxTextExtent,"%s.colormap",
09206     GetClientName());
09207   value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
09208   XrmPutStringResource(&preferences_database,specifier,(char *) value);
09209   (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmExit",
09210     GetClientName());
09211   value=resource_info->confirm_exit ? "True" : "False";
09212   XrmPutStringResource(&preferences_database,specifier,(char *) value);
09213   (void) FormatMagickString(specifier,MaxTextExtent,"%s.confirmEdit",
09214     GetClientName());
09215   value=resource_info->confirm_edit ? "True" : "False";
09216   XrmPutStringResource(&preferences_database,specifier,(char *) value);
09217   (void) FormatMagickString(specifier,MaxTextExtent,"%s.displayWarnings",
09218     GetClientName());
09219   value=resource_info->display_warnings ? "True" : "False";
09220   XrmPutStringResource(&preferences_database,specifier,(char *) value);
09221   (void) FormatMagickString(specifier,MaxTextExtent,"%s.dither",
09222     GetClientName());
09223   value=resource_info->quantize_info->dither ? "True" : "False";
09224   XrmPutStringResource(&preferences_database,specifier,(char *) value);
09225   (void) FormatMagickString(specifier,MaxTextExtent,"%s.gammaCorrect",
09226     GetClientName());
09227   value=resource_info->gamma_correct ? "True" : "False";
09228   XrmPutStringResource(&preferences_database,specifier,(char *) value);
09229   (void) FormatMagickString(specifier,MaxTextExtent,"%s.undoCache",
09230     GetClientName());
09231   (void) FormatMagickString(cache,MaxTextExtent,"%lu",
09232     resource_info->undo_cache);
09233   XrmPutStringResource(&preferences_database,specifier,cache);
09234   (void) FormatMagickString(specifier,MaxTextExtent,"%s.usePixmap",
09235     GetClientName());
09236   value=resource_info->use_pixmap ? "True" : "False";
09237   XrmPutStringResource(&preferences_database,specifier,(char *) value);
09238   (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
09239     X11_PREFERENCES_PATH,GetClientName());
09240   ExpandFilename(filename);
09241   XrmPutFileDatabase(preferences_database,filename);
09242 #endif
09243 }
09244 
09245 /*
09246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09247 %                                                                             %
09248 %                                                                             %
09249 %                                                                             %
09250 %   X V i s u a l C l a s s N a m e                                           %
09251 %                                                                             %
09252 %                                                                             %
09253 %                                                                             %
09254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09255 %
09256 %  XVisualClassName() returns the visual class name as a character string.
09257 %
09258 %  The format of the XVisualClassName method is:
09259 %
09260 %      char *XVisualClassName(const int visual_class)
09261 %
09262 %  A description of each parameter follows:
09263 %
09264 %    o visual_type: XVisualClassName returns the visual class as a character
09265 %      string.
09266 %
09267 %    o class: Specifies the visual class.
09268 %
09269 %
09270 */
09271 static const char *XVisualClassName(const int visual_class)
09272 {
09273   switch (visual_class)
09274   {
09275     case StaticGray: return("StaticGray");
09276     case GrayScale: return("GrayScale");
09277     case StaticColor: return("StaticColor");
09278     case PseudoColor: return("PseudoColor");
09279     case TrueColor: return("TrueColor");
09280     case DirectColor: return("DirectColor");
09281   }
09282   return("unknown visual class");
09283 }
09284 
09285 /*
09286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09287 %                                                                             %
09288 %                                                                             %
09289 %                                                                             %
09290 %   X W a r n i n g                                                           %
09291 %                                                                             %
09292 %                                                                             %
09293 %                                                                             %
09294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09295 %
09296 %  XWarning() displays a warning reason in a Notice widget.
09297 %
09298 %  The format of the XWarning method is:
09299 %
09300 %      void XWarning(const unsigned int warning,const char *reason,
09301 %        const char *description)
09302 %
09303 %  A description of each parameter follows:
09304 %
09305 %    o warning: Specifies the numeric warning category.
09306 %
09307 %    o reason: Specifies the reason to display before terminating the
09308 %      program.
09309 %
09310 %    o description: Specifies any description to the reason.
09311 %
09312 */
09313 MagickExport void XWarning(const ExceptionType magick_unused(warning),
09314   const char *reason,const char *description)
09315 {
09316   char
09317     text[MaxTextExtent];
09318 
09319   XWindows
09320     *windows;
09321 
09322   if (reason == (char *) NULL)
09323     return;
09324   (void) CopyMagickString(text,reason,MaxTextExtent);
09325   (void) ConcatenateMagickString(text,":",MaxTextExtent);
09326   windows=XSetWindows((XWindows *) ~0);
09327   XNoticeWidget(windows->display,windows,text,(char *) description);
09328 }
09329 
09330 /*
09331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09332 %                                                                             %
09333 %                                                                             %
09334 %                                                                             %
09335 %   X W i n d o w B y I D                                                     %
09336 %                                                                             %
09337 %                                                                             %
09338 %                                                                             %
09339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09340 %
09341 %  XWindowByID() locates a child window with a given ID.  If not window with
09342 %  the given name is found, 0 is returned.   Only the window specified and its
09343 %  subwindows are searched.
09344 %
09345 %  The format of the XWindowByID function is:
09346 %
09347 %      child=XWindowByID(display,window,id)
09348 %
09349 %  A description of each parameter follows:
09350 %
09351 %    o child: XWindowByID returns the window with the specified
09352 %      id.  If no windows are found, XWindowByID returns 0.
09353 %
09354 %    o display: Specifies a pointer to the Display structure;  returned from
09355 %      XOpenDisplay.
09356 %
09357 %    o id: Specifies the id of the window to locate.
09358 %
09359 */
09360 MagickExport Window XWindowByID(Display *display,const Window root_window,
09361   const unsigned long id)
09362 {
09363   RectangleInfo
09364     rectangle_info;
09365 
09366   register int
09367     i;
09368 
09369   Status
09370     status;
09371 
09372   unsigned int
09373     number_children;
09374 
09375   Window
09376     child,
09377     *children,
09378     window;
09379 
09380   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
09381   assert(display != (Display *) NULL);
09382   assert(root_window != (Window) NULL);
09383   if (id == 0)
09384     return(XSelectWindow(display,&rectangle_info));
09385   if (root_window == id)
09386     return(id);
09387   status=XQueryTree(display,root_window,&child,&child,&children,
09388     &number_children);
09389   if (status == False)
09390     return((Window) NULL);
09391   window=(Window) NULL;
09392   for (i=0; i < (int) number_children; i++)
09393   {
09394     /*
09395       Search each child and their children.
09396     */
09397     window=XWindowByID(display,children[i],id);
09398     if (window != (Window) NULL)
09399       break;
09400   }
09401   if (children != (Window *) NULL)
09402     (void) XFree((void *) children);
09403   return(window);
09404 }
09405 
09406 /*
09407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09408 %                                                                             %
09409 %                                                                             %
09410 %                                                                             %
09411 %   X W i n d o w B y N a m e                                                 %
09412 %                                                                             %
09413 %                                                                             %
09414 %                                                                             %
09415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09416 %
09417 %  XWindowByName() locates a window with a given name on a display.  If no
09418 %  window with the given name is found, 0 is returned. If more than one window
09419 %  has the given name, the first one is returned.  Only root and its children
09420 %  are searched.
09421 %
09422 %  The format of the XWindowByName function is:
09423 %
09424 %      window=XWindowByName(display,root_window,name)
09425 %
09426 %  A description of each parameter follows:
09427 %
09428 %    o window: XWindowByName returns the window id.
09429 %
09430 %    o display: Specifies a pointer to the Display structure;  returned from
09431 %      XOpenDisplay.
09432 %
09433 %    o root_window: Specifies the id of the root window.
09434 %
09435 %    o name: Specifies the name of the window to locate.
09436 %
09437 */
09438 MagickExport Window XWindowByName(Display *display,const Window root_window,
09439   const char *name)
09440 {
09441   register int
09442     i;
09443 
09444   Status
09445     status;
09446 
09447   unsigned int
09448     number_children;
09449 
09450   Window
09451     *children,
09452     child,
09453     window;
09454 
09455   XTextProperty
09456     window_name;
09457 
09458   assert(display != (Display *) NULL);
09459   assert(root_window != (Window) NULL);
09460   assert(name != (char *) NULL);
09461   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
09462   if (XGetWMName(display,root_window,&window_name) != 0)
09463     if (LocaleCompare((char *) window_name.value,name) == 0)
09464       return(root_window);
09465   status=XQueryTree(display,root_window,&child,&child,&children,
09466     &number_children);
09467   if (status == False)
09468     return((Window) NULL);
09469   window=(Window) NULL;
09470   for (i=0; i < (int) number_children; i++)
09471   {
09472     /*
09473       Search each child and their children.
09474     */
09475     window=XWindowByName(display,children[i],name);
09476     if (window != (Window) NULL)
09477       break;
09478   }
09479   if (children != (Window *) NULL)
09480     (void) XFree((void *) children);
09481   return(window);
09482 }
09483 
09484 /*
09485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09486 %                                                                             %
09487 %                                                                             %
09488 %                                                                             %
09489 %   X W i n d o w B y P r o p e r y                                           %
09490 %                                                                             %
09491 %                                                                             %
09492 %                                                                             %
09493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09494 %
09495 %  XWindowByProperty() locates a child window with a given property. If not
09496 %  window with the given name is found, 0 is returned.  If more than one window
09497 %  has the given property, the first one is returned.  Only the window
09498 %  specified and its subwindows are searched.
09499 %
09500 %  The format of the XWindowByProperty function is:
09501 %
09502 %      child=XWindowByProperty(display,window,property)
09503 %
09504 %  A description of each parameter follows:
09505 %
09506 %    o child: XWindowByProperty returns the window id with the specified
09507 %      property.  If no windows are found, XWindowByProperty returns 0.
09508 %
09509 %    o display: Specifies a pointer to the Display structure;  returned from
09510 %      XOpenDisplay.
09511 %
09512 %    o property: Specifies the property of the window to locate.
09513 %
09514 */
09515 MagickExport Window XWindowByProperty(Display *display,const Window window,
09516   const Atom property)
09517 {
09518   Atom
09519     type;
09520 
09521   int
09522     format;
09523 
09524   Status
09525     status;
09526 
09527   unsigned char
09528     *data;
09529 
09530   unsigned int
09531     i,
09532     number_children;
09533 
09534   unsigned long
09535     after,
09536     number_items;
09537 
09538   Window
09539     child,
09540     *children,
09541     parent,
09542     root;
09543 
09544   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
09545   assert(display != (Display *) NULL);
09546   assert(window != (Window) NULL);
09547   assert(property != (Atom) NULL);
09548   status=XQueryTree(display,window,&root,&parent,&children,&number_children);
09549   if (status == False)
09550     return((Window) NULL);
09551   type=(Atom) NULL;
09552   child=(Window) NULL;
09553   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
09554   {
09555     status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
09556       (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
09557     if (data != NULL)
09558       (void) XFree((void *) data);
09559     if ((status == Success) && (type != (Atom) NULL))
09560       child=children[i];
09561   }
09562   for (i=0; (i < number_children) && (child == (Window) NULL); i++)
09563     child=XWindowByProperty(display,children[i],property);
09564   if (children != (Window *) NULL)
09565     (void) XFree((void *) children);
09566   return(child);
09567 }
09568 #else
09569 
09570 /*
09571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09572 %                                                                             %
09573 %                                                                             %
09574 %                                                                             %
09575 %   X I m p o r t I m a g e                                                   %
09576 %                                                                             %
09577 %                                                                             %
09578 %                                                                             %
09579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09580 %
09581 %  XImportImage() reads an image from an X window.
09582 %
09583 %  The format of the XImportImage method is:
09584 %
09585 %      Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info)
09586 %
09587 %  A description of each parameter follows:
09588 %
09589 %    o image_info: the image info..
09590 %
09591 %    o ximage_info: Specifies a pointer to an XImportInfo structure.
09592 %
09593 */
09594 MagickExport Image *XImportImage(const ImageInfo *image_info,
09595   XImportInfo *ximage_info)
09596 {
09597   assert(image_info != (const ImageInfo *) NULL);
09598   assert(image_info->signature == MagickSignature);
09599   if (image_info->debug != MagickFalse)
09600     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
09601       image_info->filename);
09602   assert(ximage_info != (XImportInfo *) NULL);
09603   return((Image *) NULL);
09604 }
09605 #endif
09606 
09607 /*
09608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09609 %                                                                             %
09610 %                                                                             %
09611 %                                                                             %
09612 %   X G e t I m p o r t I n f o                                               %
09613 %                                                                             %
09614 %                                                                             %
09615 %                                                                             %
09616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
09617 %
09618 %  XGetImportInfo() initializes the XImportInfo structure.
09619 %
09620 %  The format of the XGetImportInfo method is:
09621 %
09622 %      void XGetImportInfo(XImportInfo *ximage_info)
09623 %
09624 %  A description of each parameter follows:
09625 %
09626 %    o ximage_info: Specifies a pointer to an ImageInfo structure.
09627 %
09628 */
09629 MagickExport void XGetImportInfo(XImportInfo *ximage_info)
09630 {
09631   assert(ximage_info != (XImportInfo *) NULL);
09632   ximage_info->frame=MagickFalse;
09633   ximage_info->borders=MagickFalse;
09634   ximage_info->screen=MagickFalse;
09635   ximage_info->descend=MagickTrue;
09636   ximage_info->silent=MagickFalse;
09637 }

Generated on Thu Jul 2 12:03:25 2009 for MagickCore by  doxygen 1.5.8