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-2009 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 static Window XClientWindow(Display *display,Window target_window)
01582 {
01583   Atom
01584     state,
01585     type;
01586 
01587   int
01588     format;
01589 
01590   Status
01591     status;
01592 
01593   unsigned char
01594     *data;
01595 
01596   unsigned long
01597     after,
01598     number_items;
01599 
01600   Window
01601     client_window;
01602 
01603   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01604   assert(display != (Display *) NULL);
01605   state=XInternAtom(display,"WM_STATE",MagickTrue);
01606   if (state == (Atom) NULL)
01607     return(target_window);
01608   type=(Atom) NULL;
01609   status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
01610     (Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
01611   if ((status == Success) && (type != (Atom) NULL))
01612     return(target_window);
01613   client_window=XWindowByProperty(display,target_window,state);
01614   if (client_window == (Window) NULL)
01615     return(target_window);
01616   return(client_window);
01617 }
01618 
01619 /*
01620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01621 %                                                                             %
01622 %                                                                             %
01623 %                                                                             %
01624 +   X C o m p o n e n t T e r m i n u s                                       %
01625 %                                                                             %
01626 %                                                                             %
01627 %                                                                             %
01628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01629 %
01630 %  XComponentTerminus() destroys the module component.
01631 %
01632 %  The format of the XComponentTerminus method is:
01633 %
01634 %      XComponentTerminus(void)
01635 %
01636 */
01637 MagickExport void XComponentTerminus(void)
01638 {
01639   DestroyXResources();
01640 }
01641 
01642 /*
01643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01644 %                                                                             %
01645 %                                                                             %
01646 %                                                                             %
01647 %   X C o n f i g u r e I m a g e C o l o r m a p                             %
01648 %                                                                             %
01649 %                                                                             %
01650 %                                                                             %
01651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01652 %
01653 %  XConfigureImageColormap() creates a new X colormap.
01654 %
01655 %  The format of the XConfigureImageColormap method is:
01656 %
01657 %      void XConfigureImageColormap(Display *display,
01658 %        XResourceInfo *resource_info,XWindows *windows,Image *image)
01659 %
01660 %  A description of each parameter follows:
01661 %
01662 %    o display: Specifies a connection to an X server; returned from
01663 %      XOpenDisplay.
01664 %
01665 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01666 %
01667 %    o windows: Specifies a pointer to a XWindows structure.
01668 %
01669 %    o image: the image.
01670 %
01671 */
01672 MagickExport void XConfigureImageColormap(Display *display,
01673   XResourceInfo *resource_info,XWindows *windows,Image *image)
01674 {
01675   Colormap
01676     colormap;
01677 
01678   /*
01679     Make standard colormap.
01680   */
01681   XSetCursorState(display,windows,MagickTrue);
01682   XCheckRefreshWindows(display,windows);
01683   XMakeStandardColormap(display,windows->visual_info,resource_info,image,
01684     windows->map_info,windows->pixel_info);
01685   colormap=windows->map_info->colormap;
01686   (void) XSetWindowColormap(display,windows->image.id,colormap);
01687   (void) XSetWindowColormap(display,windows->command.id,colormap);
01688   (void) XSetWindowColormap(display,windows->widget.id,colormap);
01689   if (windows->magnify.mapped != MagickFalse)
01690     (void) XSetWindowColormap(display,windows->magnify.id,colormap);
01691   if (windows->pan.mapped != MagickFalse)
01692     (void) XSetWindowColormap(display,windows->pan.id,colormap);
01693   XSetCursorState(display,windows,MagickFalse);
01694   XClientMessage(display,windows->image.id,windows->im_protocols,
01695     windows->im_update_colormap,CurrentTime);
01696 }
01697 
01698 /*
01699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01700 %                                                                             %
01701 %                                                                             %
01702 %                                                                             %
01703 %   X C o n s t r a i n W i n d o w P o s i t i o n                           %
01704 %                                                                             %
01705 %                                                                             %
01706 %                                                                             %
01707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01708 %
01709 %  XConstrainWindowPosition() assures a window is positioned within the X
01710 %  server boundaries.
01711 %
01712 %  The format of the XConstrainWindowPosition method is:
01713 %
01714 %      void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
01715 %
01716 %  A description of each parameter follows:
01717 %
01718 %    o display: Specifies a pointer to the Display structure;  returned from
01719 %      XOpenDisplay.
01720 %
01721 %    o window_info: Specifies a pointer to a XWindowInfo structure.
01722 %
01723 */
01724 MagickExport void XConstrainWindowPosition(Display *display,
01725   XWindowInfo *window_info)
01726 {
01727   int
01728     limit;
01729 
01730   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01731   assert(display != (Display *) NULL);
01732   assert(window_info != (XWindowInfo *) NULL);
01733   limit=XDisplayWidth(display,window_info->screen)-window_info->width;
01734   if (window_info->x < 0)
01735     window_info->x=0;
01736   else
01737     if (window_info->x > (int) limit)
01738       window_info->x=(int) limit;
01739   limit=XDisplayHeight(display,window_info->screen)-window_info->height;
01740   if (window_info->y < 0)
01741     window_info->y=0;
01742   else
01743     if (window_info->y > limit)
01744       window_info->y=limit;
01745 }
01746 
01747 /*
01748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01749 %                                                                             %
01750 %                                                                             %
01751 %                                                                             %
01752 %   X D e l a y                                                               %
01753 %                                                                             %
01754 %                                                                             %
01755 %                                                                             %
01756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01757 %
01758 %  XDelay() suspends program execution for the number of milliseconds
01759 %  specified.
01760 %
01761 %  The format of the Delay method is:
01762 %
01763 %      void XDelay(Display *display,const unsigned long milliseconds)
01764 %
01765 %  A description of each parameter follows:
01766 %
01767 %    o display: Specifies a pointer to the Display structure;  returned from
01768 %      XOpenDisplay.
01769 %
01770 %    o milliseconds: Specifies the number of milliseconds to delay before
01771 %      returning.
01772 %
01773 */
01774 MagickExport void XDelay(Display *display,const unsigned long milliseconds)
01775 {
01776   assert(display != (Display *) NULL);
01777   (void) XFlush(display);
01778   if (milliseconds == 0)
01779     return;
01780 #if defined(__WINDOWS__)
01781   Sleep(milliseconds);
01782 #elif defined(vms)
01783   {
01784     float
01785       timer;
01786 
01787     timer=milliseconds/1000.0;
01788     lib$wait(&timer);
01789   }
01790 #elif defined(MAGICKCORE_HAVE_USLEEP)
01791   usleep(1000*milliseconds);
01792 #elif defined(MAGICKCORE_HAVE_SELECT)
01793   {
01794     struct timeval
01795       timer;
01796 
01797     timer.tv_sec=(long) milliseconds/1000;
01798     timer.tv_usec=(long) (milliseconds % 1000)*1000;
01799     (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
01800   }
01801 #elif defined(MAGICKCORE_HAVE_POLL)
01802   (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
01803 #elif defined(__BEOS__)
01804   snooze(1000*milliseconds);
01805 #else
01806 # error "Time delay method not defined."
01807 #endif
01808 }
01809 
01810 /*
01811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01812 %                                                                             %
01813 %                                                                             %
01814 %                                                                             %
01815 %   X D e s t r o y R e s o u r c e I n f o                                   %
01816 %                                                                             %
01817 %                                                                             %
01818 %                                                                             %
01819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01820 %
01821 %  XDestroyResourceInfo() frees memory associated with the XResourceInfo
01822 %  structure.
01823 %
01824 %  The format of the XDestroyResourceInfo method is:
01825 %
01826 %      void XDestroyResourceInfo(XResourceInfo *resource_info)
01827 %
01828 %  A description of each parameter follows:
01829 %
01830 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01831 %
01832 */
01833 MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
01834 {
01835   if (resource_info->image_geometry != (char *) NULL)
01836     resource_info->image_geometry=(char *)
01837       RelinquishMagickMemory(resource_info->image_geometry);
01838   if (resource_info->quantize_info != (QuantizeInfo *) NULL)
01839     resource_info->quantize_info=DestroyQuantizeInfo(
01840       resource_info->quantize_info);
01841   if (resource_info->client_name != (char *) NULL)
01842     resource_info->client_name=(char *)
01843       RelinquishMagickMemory(resource_info->client_name);
01844   if (resource_info->name != (char *) NULL)
01845     resource_info->name=DestroyString(resource_info->name);
01846   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
01847 }
01848 
01849 /*
01850 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01851 %                                                                             %
01852 %                                                                             %
01853 %                                                                             %
01854 %   X D e s t r o y W i n d o w C o l o r s                                   %
01855 %                                                                             %
01856 %                                                                             %
01857 %                                                                             %
01858 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01859 %
01860 %  XDestroyWindowColors() frees X11 color resources previously saved on a
01861 %  window by XRetainWindowColors or programs like xsetroot.
01862 %
01863 %  The format of the XDestroyWindowColors method is:
01864 %
01865 %      void XDestroyWindowColors(Display *display,Window window)
01866 %
01867 %  A description of each parameter follows:
01868 %
01869 %    o display: Specifies a connection to an X server; returned from
01870 %      XOpenDisplay.
01871 %
01872 %    o window: Specifies a pointer to a Window structure.
01873 %
01874 */
01875 MagickExport void XDestroyWindowColors(Display *display,Window window)
01876 {
01877   Atom
01878     property,
01879     type;
01880 
01881   int
01882     format;
01883 
01884   Status
01885     status;
01886 
01887   unsigned char
01888     *data;
01889 
01890   unsigned long
01891     after,
01892     length;
01893 
01894   /*
01895     If there are previous resources on the root window, destroy them.
01896   */
01897   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01898   assert(display != (Display *) NULL);
01899   property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
01900   if (property == (Atom) NULL)
01901     {
01902       ThrowXWindowFatalException(XServerError,"UnableToCreateProperty",
01903         "_XSETROOT_ID");
01904       return;
01905     }
01906   status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
01907     (Atom) AnyPropertyType,&type,&format,&length,&after,&data);
01908   if (status != Success)
01909     return;
01910   if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
01911     {
01912       (void) XKillClient(display,(XID) (*((Pixmap *) data)));
01913       (void) XDeleteProperty(display,window,property);
01914     }
01915   if (type != None)
01916     (void) XFree((void *) data);
01917 }
01918 
01919 /*
01920 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01921 %                                                                             %
01922 %                                                                             %
01923 %                                                                             %
01924 %   X D i s p l a y I m a g e I n f o                                         %
01925 %                                                                             %
01926 %                                                                             %
01927 %                                                                             %
01928 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01929 %
01930 %  XDisplayImageInfo() displays information about an X image.
01931 %
01932 %  The format of the XDisplayImageInfo method is:
01933 %
01934 %      void XDisplayImageInfo(Display *display,
01935 %        const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
01936 %        Image *image)
01937 %
01938 %  A description of each parameter follows:
01939 %
01940 %    o display: Specifies a connection to an X server;  returned from
01941 %      XOpenDisplay.
01942 %
01943 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
01944 %
01945 %    o windows: Specifies a pointer to a XWindows structure.
01946 %
01947 %    o undo_image: the undo image.
01948 %
01949 %    o image: the image.
01950 %
01951 */
01952 MagickExport void XDisplayImageInfo(Display *display,
01953   const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
01954   Image *image)
01955 {
01956   char
01957     filename[MaxTextExtent],
01958     *text,
01959     **textlist;
01960 
01961   FILE
01962     *file;
01963 
01964   int
01965     unique_file;
01966 
01967   long
01968     bytes;
01969 
01970   register long
01971     i;
01972 
01973   unsigned int
01974     levels;
01975 
01976   unsigned long
01977     number_pixels;
01978 
01979   /*
01980     Write info about the X server to a file.
01981   */
01982   assert(display != (Display *) NULL);
01983   assert(resource_info != (XResourceInfo *) NULL);
01984   assert(windows != (XWindows *) NULL);
01985   assert(image != (Image *) NULL);
01986   if (image->debug)
01987     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01988   file=(FILE *) NULL;
01989   unique_file=AcquireUniqueFileResource(filename);
01990   if (unique_file != -1)
01991     file=fdopen(unique_file,"w");
01992   if ((unique_file == -1) || (file == (FILE *) NULL))
01993     {
01994       XNoticeWidget(display,windows,"Unable to display image info",filename);
01995       return;
01996     }
01997   if (resource_info->gamma_correct != MagickFalse)
01998     if (resource_info->display_gamma != (char *) NULL)
01999       (void) fprintf(file,"Display\n  gamma: %s\n\n",
02000         resource_info->display_gamma);
02001   /*
02002     Write info about the X image to a file.
02003   */
02004   (void) fprintf(file,"X\n  visual: %s\n",
02005     XVisualClassName((int) windows->image.storage_class));
02006   (void) fprintf(file,"  depth: %d\n",windows->image.ximage->depth);
02007   if (windows->visual_info->colormap_size != 0)
02008     (void) fprintf(file,"  colormap size: %d\n",
02009       windows->visual_info->colormap_size);
02010   if (resource_info->colormap== SharedColormap)
02011     (void) fprintf(file,"  colormap type: Shared\n");
02012   else
02013     (void) fprintf(file,"  colormap type: Private\n");
02014   (void) fprintf(file,"  geometry: %dx%d\n",windows->image.ximage->width,
02015     windows->image.ximage->height);
02016   if (windows->image.crop_geometry != (char *) NULL)
02017     (void) fprintf(file,"  crop geometry: %s\n",windows->image.crop_geometry);
02018   if (windows->image.pixmap == (Pixmap) NULL)
02019     (void) fprintf(file,"  type: X Image\n");
02020   else
02021     (void) fprintf(file,"  type: Pixmap\n");
02022   if (windows->image.shape != MagickFalse)
02023     (void) fprintf(file,"  non-rectangular shape: True\n");
02024   else
02025     (void) fprintf(file,"  non-rectangular shape: False\n");
02026   if (windows->image.shared_memory != MagickFalse)
02027     (void) fprintf(file,"  shared memory: True\n");
02028   else
02029     (void) fprintf(file,"  shared memory: False\n");
02030   (void) fprintf(file,"\n");
02031   if (resource_info->font != (char *) NULL)
02032     (void) fprintf(file,"Font: %s\n\n",resource_info->font);
02033   if (resource_info->text_font != (char *) NULL)
02034     (void) fprintf(file,"Text font: %s\n\n",resource_info->text_font);
02035   /*
02036     Write info about the undo cache to a file.
02037   */
02038   bytes=0;
02039   for (levels=0; undo_image != (Image *) NULL; levels++)
02040   {
02041     number_pixels=undo_image->list->columns*undo_image->list->rows;
02042     bytes+=number_pixels*sizeof(PixelPacket);
02043     undo_image=GetPreviousImageInList(undo_image);
02044   }
02045   (void) fprintf(file,"Undo Edit Cache\n  levels: %u\n",levels);
02046   (void) fprintf(file,"  bytes: %lumb\n",(unsigned long)
02047     (bytes+(1 << 19)) >> 20);
02048   (void) fprintf(file,"  limit: %lumb\n\n",resource_info->undo_cache);
02049   /*
02050     Write info about the image to a file.
02051   */
02052   (void) IdentifyImage(image,file,MagickTrue);
02053   (void) fclose(file);
02054   text=FileToString(filename,~0,&image->exception);
02055   (void) RelinquishUniqueFileResource(filename);
02056   if (text == (char *) NULL)
02057     {
02058       XNoticeWidget(display,windows,"MemoryAllocationFailed",
02059         "UnableToDisplayImageInfo");
02060       return;
02061     }
02062   textlist=StringToList(text);
02063   if (textlist != (char **) NULL)
02064     {
02065       char
02066         title[MaxTextExtent];
02067 
02068       /*
02069         Display information about the image in the Text View widget.
02070       */
02071       (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
02072       (void) FormatMagickString(title,MaxTextExtent,"Image Info: %s",
02073         image->filename);
02074       XTextViewWidget(display,resource_info,windows,MagickTrue,title,
02075         (char const **) textlist);
02076       for (i=0; textlist[i] != (char *) NULL; i++)
02077         textlist[i]=DestroyString(textlist[i]);
02078       textlist=(char **) RelinquishMagickMemory(textlist);
02079     }
02080   text=DestroyString(text);
02081 }
02082 
02083 /*
02084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02085 %                                                                             %
02086 %                                                                             %
02087 %                                                                             %
02088 +     X D i t h e r I m a g e                                                 %
02089 %                                                                             %
02090 %                                                                             %
02091 %                                                                             %
02092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02093 %
02094 %  XDitherImage() dithers the reference image as required by the HP Color
02095 %  Recovery algorithm.  The color values are quantized to 3 bits of red and
02096 %  green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
02097 %  standard colormap.
02098 %
02099 %  The format of the XDitherImage method is:
02100 %
02101 %      void XDitherImage(Image *image,XImage *ximage)
02102 %
02103 %  A description of each parameter follows:
02104 %
02105 %    o image: the image.
02106 %
02107 %    o ximage: Specifies a pointer to a XImage structure;  returned from
02108 %      XCreateImage.
02109 %
02110 %
02111 */
02112 static void XDitherImage(Image *image,XImage *ximage)
02113 {
02114   static const short int
02115     dither_red[2][16]=
02116     {
02117       {-16,  4, -1, 11,-14,  6, -3,  9,-15,  5, -2, 10,-13,  7, -4,  8},
02118       { 15, -5,  0,-12, 13, -7,  2,-10, 14, -6,  1,-11, 12, -8,  3, -9}
02119     },
02120     dither_green[2][16]=
02121     {
02122       { 11,-15,  7, -3,  8,-14,  4, -2, 10,-16,  6, -4,  9,-13,  5, -1},
02123       {-12, 14, -8,  2, -9, 13, -5,  1,-11, 15, -7,  3,-10, 12, -6,  0}
02124     },
02125     dither_blue[2][16]=
02126     {
02127       { -3,  9,-13,  7, -1, 11,-15,  5, -4,  8,-14,  6, -2, 10,-16,  4},
02128       {  2,-10, 12, -8,  0,-12, 14, -6,  3, -9, 13, -7,  1,-11, 15, -5}
02129     };
02130 
02131   PixelPacket
02132     color;
02133 
02134   int
02135     y;
02136 
02137   long
02138     value;
02139 
02140   register char
02141     *q;
02142 
02143   register const PixelPacket
02144     *p;
02145 
02146   register int
02147     i,
02148     j,
02149     x;
02150 
02151   unsigned int
02152     scanline_pad;
02153 
02154   register unsigned long
02155     pixel;
02156 
02157   unsigned char
02158     *blue_map[2][16],
02159     *green_map[2][16],
02160     *red_map[2][16];
02161 
02162   /*
02163     Allocate and initialize dither maps.
02164   */
02165   for (i=0; i < 2; i++)
02166     for (j=0; j < 16; j++)
02167     {
02168       red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02169         sizeof(*red_map));
02170       green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02171         sizeof(*green_map));
02172       blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02173         sizeof(*blue_map));
02174       if ((red_map[i][j] == (unsigned char *) NULL) ||
02175           (green_map[i][j] == (unsigned char *) NULL) ||
02176           (blue_map[i][j] == (unsigned char *) NULL))
02177         {
02178           ThrowXWindowFatalException(ResourceLimitError,
02179             "MemoryAllocationFailed",image->filename);
02180           return;
02181         }
02182     }
02183   /*
02184     Initialize dither tables.
02185   */
02186   for (i=0; i < 2; i++)
02187     for (j=0; j < 16; j++)
02188       for (x=0; x < 256; x++)
02189       {
02190         value=x-16;
02191         if (x < 48)
02192           value=x/2+8;
02193         value+=dither_red[i][j];
02194         red_map[i][j][x]=(unsigned char)
02195           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02196         value=x-16;
02197         if (x < 48)
02198           value=x/2+8;
02199         value+=dither_green[i][j];
02200         green_map[i][j][x]=(unsigned char)
02201           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02202         value=x-32;
02203         if (x < 112)
02204           value=x/2+24;
02205         value+=((unsigned long) dither_blue[i][j] << 1);
02206         blue_map[i][j][x]=(unsigned char)
02207           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02208       }
02209   /*
02210     Dither image.
02211   */
02212   scanline_pad=(unsigned int) (ximage->bytes_per_line-
02213     ((unsigned long) (ximage->width*ximage->bits_per_pixel) >> 3));
02214   i=0;
02215   j=0;
02216   q=ximage->data;
02217   for (y=0; y < (int) image->rows; y++)
02218   {
02219     p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
02220     if (p == (const PixelPacket *) NULL)
02221       break;
02222     for (x=0; x < (int) image->columns; x++)
02223     {
02224       color.red=RoundToQuantum((MagickRealType) (red_map[i][j][(int)
02225         ScaleQuantumToChar(p->red)] << 8));
02226       color.green=RoundToQuantum((MagickRealType) (green_map[i][j][(int)
02227         ScaleQuantumToChar(p->green)] << 8));
02228       color.blue=RoundToQuantum((MagickRealType) (blue_map[i][j][(int)
02229         ScaleQuantumToChar(p->blue)] << 8));
02230       pixel=(unsigned long) (((unsigned long) color.red & 0xe0) |
02231         (((unsigned long) color.green & 0xe0) >> 3) |
02232         (((unsigned long) color.blue & 0xc0) >> 6));
02233       *q++=(char) pixel;
02234       p++;
02235       j++;
02236       if (j == 16)
02237         j=0;
02238     }
02239     q+=scanline_pad;
02240     i++;
02241     if (i == 2)
02242       i=0;
02243   }
02244   /*
02245     Free allocated memory.
02246   */
02247   for (i=0; i < 2; i++)
02248     for (j=0; j < 16; j++)
02249     {
02250       green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
02251       blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
02252       red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
02253     }
02254 }
02255 
02256 /*
02257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02258 %                                                                             %
02259 %                                                                             %
02260 %                                                                             %
02261 %   X D r a w I m a g e                                                       %
02262 %                                                                             %
02263 %                                                                             %
02264 %                                                                             %
02265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02266 %
02267 %  XDrawImage() draws a line on the image.
02268 %
02269 %  The format of the XDrawImage method is:
02270 %
02271 %    MagickBooleanType XDrawImage(display,pixel,draw_info,image)
02272 %
02273 %  A description of each parameter follows:
02274 %
02275 %    o display: Specifies a connection to an X server;  returned from
02276 %      XOpenDisplay.
02277 %
02278 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02279 %
02280 %    o draw_info: Specifies a pointer to a XDrawInfo structure.
02281 %
02282 %    o image: the image.
02283 %
02284 */
02285 MagickExport MagickBooleanType XDrawImage(Display *display,
02286   const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
02287 {
02288   ExceptionInfo
02289     *exception;
02290 
02291   GC
02292     draw_context;
02293 
02294   Image
02295     *draw_image;
02296 
02297   int
02298     x,
02299     y;
02300 
02301   MagickBooleanType
02302     matte;
02303 
02304   Pixmap
02305     draw_pixmap;
02306 
02307   unsigned int
02308     depth,
02309     height,
02310     width;
02311 
02312   Window
02313     root_window;
02314 
02315   XGCValues
02316     context_values;
02317 
02318   XImage
02319     *draw_ximage;
02320 
02321   /*
02322     Initialize drawd image.
02323   */
02324   assert(display != (Display *) NULL);
02325   assert(pixel != (XPixelInfo *) NULL);
02326   assert(draw_info != (XDrawInfo *) NULL);
02327   assert(image != (Image *) NULL);
02328   if (image->debug != MagickFalse)
02329     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02330   /*
02331     Initialize drawd pixmap.
02332   */
02333   root_window=XRootWindow(display,XDefaultScreen(display));
02334   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
02335   draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
02336     draw_info->height,depth);
02337   if (draw_pixmap == (Pixmap) NULL)
02338     return(MagickFalse);
02339   /*
02340     Initialize graphics info.
02341   */
02342   context_values.background=(unsigned long) (~0);
02343   context_values.foreground=0;
02344   context_values.line_width=(int) draw_info->line_width;
02345   draw_context=XCreateGC(display,root_window,(unsigned long)
02346     (GCBackground | GCForeground | GCLineWidth),&context_values);
02347   if (draw_context == (GC) NULL)
02348     return(MagickFalse);
02349   /*
02350     Clear pixmap.
02351   */
02352   (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
02353     draw_info->height);
02354   /*
02355     Draw line to pixmap.
02356   */
02357   (void) XSetBackground(display,draw_context,0);
02358   (void) XSetForeground(display,draw_context,(unsigned long) (~0));
02359   (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
02360   (void) XSetStipple(display,draw_context,draw_info->stipple);
02361   switch (draw_info->element)
02362   {
02363     case PointElement:
02364     default:
02365     {
02366       (void) XDrawLines(display,draw_pixmap,draw_context,
02367         draw_info->coordinate_info,(int) draw_info->number_coordinates,
02368         CoordModeOrigin);
02369       break;
02370     }
02371     case LineElement:
02372     {
02373       (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
02374         draw_info->line_info.y1,draw_info->line_info.x2,
02375         draw_info->line_info.y2);
02376       break;
02377     }
02378     case RectangleElement:
02379     {
02380       (void) XDrawRectangle(display,draw_pixmap,draw_context,
02381         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02382         (unsigned int) draw_info->rectangle_info.width,
02383         (unsigned int) draw_info->rectangle_info.height);
02384       break;
02385     }
02386     case FillRectangleElement:
02387     {
02388       (void) XFillRectangle(display,draw_pixmap,draw_context,
02389         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02390         (unsigned int) draw_info->rectangle_info.width,
02391         (unsigned int) draw_info->rectangle_info.height);
02392       break;
02393     }
02394     case CircleElement:
02395     case EllipseElement:
02396     {
02397       (void) XDrawArc(display,draw_pixmap,draw_context,
02398         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02399         (unsigned int) draw_info->rectangle_info.width,
02400         (unsigned int) draw_info->rectangle_info.height,0,360*64);
02401       break;
02402     }
02403     case FillCircleElement:
02404     case FillEllipseElement:
02405     {
02406       (void) XFillArc(display,draw_pixmap,draw_context,
02407         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02408         (unsigned int) draw_info->rectangle_info.width,
02409         (unsigned int) draw_info->rectangle_info.height,0,360*64);
02410       break;
02411     }
02412     case PolygonElement:
02413     {
02414       XPoint
02415         *coordinate_info;
02416 
02417       coordinate_info=draw_info->coordinate_info;
02418       (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
02419         (int) draw_info->number_coordinates,CoordModeOrigin);
02420       (void) XDrawLine(display,draw_pixmap,draw_context,
02421         coordinate_info[draw_info->number_coordinates-1].x,
02422         coordinate_info[draw_info->number_coordinates-1].y,
02423         coordinate_info[0].x,coordinate_info[0].y);
02424       break;
02425     }
02426     case FillPolygonElement:
02427     {
02428       (void) XFillPolygon(display,draw_pixmap,draw_context,
02429         draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
02430         CoordModeOrigin);
02431       break;
02432     }
02433   }
02434   (void) XFreeGC(display,draw_context);
02435   /*
02436     Initialize X image.
02437   */
02438   draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
02439     draw_info->height,AllPlanes,ZPixmap);
02440   if (draw_ximage == (XImage *) NULL)
02441     return(MagickFalse);
02442   (void) XFreePixmap(display,draw_pixmap);
02443   /*
02444     Initialize draw image.
02445   */
02446   draw_image=AcquireImage((ImageInfo *) NULL);
02447   if (draw_image == (Image *) NULL)
02448     return(MagickFalse);
02449   draw_image->columns=draw_info->width;
02450   draw_image->rows=draw_info->height;
02451   /*
02452     Transfer drawn X image to image.
02453   */
02454   width=(unsigned int) image->columns;
02455   height=(unsigned int) image->rows;
02456   x=0;
02457   y=0;
02458   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02459   (void) GetOneVirtualPixel(image,x,y,&draw_image->background_color,
02460     &image->exception);
02461   if (SetImageStorageClass(draw_image,DirectClass) == MagickFalse)
02462     return(MagickFalse);
02463   draw_image->matte=MagickTrue;
02464   exception=(&image->exception);
02465   for (y=0; y < (int) draw_image->rows; y++)
02466   {
02467     register long
02468       x;
02469 
02470     register PixelPacket
02471       *__restrict q;
02472 
02473     q=QueueAuthenticPixels(draw_image,0,y,draw_image->columns,1,exception);
02474     if (q == (PixelPacket *) NULL)
02475       break;
02476     for (x=0; x < (long) draw_image->columns; x++)
02477     {
02478       if (XGetPixel(draw_ximage,x,y) == 0)
02479         {
02480           /*
02481             Set this pixel to the background color.
02482           */
02483           *q=draw_image->background_color;
02484           q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
02485             TransparentOpacity : OpaqueOpacity);
02486         }
02487       else
02488         {
02489           /*
02490             Set this pixel to the pen color.
02491           */
02492           q->red=ScaleShortToQuantum(pixel->pen_color.red);
02493           q->green=ScaleShortToQuantum(pixel->pen_color.green);
02494           q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
02495           q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
02496             OpaqueOpacity : TransparentOpacity);
02497         }
02498       q++;
02499     }
02500     if (SyncAuthenticPixels(draw_image,exception) == MagickFalse)
02501       break;
02502   }
02503   XDestroyImage(draw_ximage);
02504   /*
02505     Determine draw geometry.
02506   */
02507   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02508   if ((width != (unsigned int) draw_image->columns) ||
02509       (height != (unsigned int) draw_image->rows))
02510     {
02511       char
02512         image_geometry[MaxTextExtent];
02513 
02514       /*
02515         Scale image.
02516       */
02517       (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
02518         width,height);
02519       (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
02520     }
02521   if (draw_info->degrees != 0.0)
02522     {
02523       Image
02524         *rotate_image;
02525 
02526       int
02527         rotations;
02528 
02529       MagickRealType
02530         normalized_degrees;
02531 
02532       /*
02533         Rotate image.
02534       */
02535       rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
02536       if (rotate_image == (Image *) NULL)
02537         return(MagickFalse);
02538       draw_image=DestroyImage(draw_image);
02539       draw_image=rotate_image;
02540       /*
02541         Annotation is relative to the degree of rotation.
02542       */
02543       normalized_degrees=draw_info->degrees;
02544       while (normalized_degrees < -45.0)
02545         normalized_degrees+=360.0;
02546       for (rotations=0; normalized_degrees > 45.0; rotations++)
02547         normalized_degrees-=90.0;
02548       switch (rotations % 4)
02549       {
02550         default:
02551         case 0:
02552           break;
02553         case 1:
02554         {
02555           /*
02556             Rotate 90 degrees.
02557           */
02558           x=x-(int) draw_image->columns/2;
02559           y=y+(int) draw_image->columns/2;
02560           break;
02561         }
02562         case 2:
02563         {
02564           /*
02565             Rotate 180 degrees.
02566           */
02567           x=x-(int) draw_image->columns;
02568           break;
02569         }
02570         case 3:
02571         {
02572           /*
02573             Rotate 270 degrees.
02574           */
02575           x=x-(int) draw_image->columns/2;
02576           y=y-(int) (draw_image->rows-(draw_image->columns/2));
02577           break;
02578         }
02579       }
02580     }
02581   /*
02582     Composite text onto the image.
02583   */
02584   for (y=0; y < (int) draw_image->rows; y++)
02585   {
02586     register long
02587       x;
02588 
02589     register PixelPacket
02590       *__restrict q;
02591 
02592     q=GetAuthenticPixels(draw_image,0,y,draw_image->columns,1,exception);
02593     if (q == (PixelPacket *) NULL)
02594       break;
02595     for (x=0; x < (long) draw_image->columns; x++)
02596     {
02597       if (q->opacity != (Quantum) TransparentOpacity)
02598         q->opacity=OpaqueOpacity;
02599       q++;
02600     }
02601     if (SyncAuthenticPixels(draw_image,exception) == MagickFalse)
02602       break;
02603   }
02604   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02605   if (draw_info->stencil == TransparentStencil)
02606     (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,x,y);
02607   else
02608     {
02609       matte=image->matte;
02610       (void) CompositeImage(image,OverCompositeOp,draw_image,x,y);
02611       image->matte=matte;
02612     }
02613   draw_image=DestroyImage(draw_image);
02614   return(MagickTrue);
02615 }
02616 
02617 /*
02618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02619 %                                                                             %
02620 %                                                                             %
02621 %                                                                             %
02622 %   X E r r o r                                                               %
02623 %                                                                             %
02624 %                                                                             %
02625 %                                                                             %
02626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02627 %
02628 %  XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
02629 %  and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
02630 %  for XQueryColor.  It returns MagickFalse in those cases.  Otherwise it returns
02631 %  True.
02632 %
02633 %  The format of the XError function is:
02634 %
02635 %      XError(display,error)
02636 %
02637 %  A description of each parameter follows:
02638 %
02639 %    o display: Specifies a pointer to the Display structure;  returned from
02640 %      XOpenDisplay.
02641 %
02642 %    o error: Specifies the error event.
02643 %
02644 */
02645 
02646 #if defined(__cplusplus) || defined(c_plusplus)
02647 extern "C" {
02648 #endif
02649 
02650 MagickExport int XError(Display *display,XErrorEvent *error)
02651 {
02652   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02653   assert(display != (Display *) NULL);
02654   assert(error != (XErrorEvent *) NULL);
02655   xerror_alert=MagickTrue;
02656   switch (error->request_code)
02657   {
02658     case X_GetGeometry:
02659     {
02660       if ((int) error->error_code == BadDrawable)
02661         return(MagickFalse);
02662       break;
02663     }
02664     case X_GetWindowAttributes:
02665     case X_QueryTree:
02666     {
02667       if ((int) error->error_code == BadWindow)
02668         return(MagickFalse);
02669       break;
02670     }
02671     case X_QueryColors:
02672     {
02673       if ((int) error->error_code == BadValue)
02674         return(MagickFalse);
02675       break;
02676     }
02677   }
02678   return(MagickTrue);
02679 }
02680 
02681 #if defined(__cplusplus) || defined(c_plusplus)
02682 }
02683 #endif
02684 
02685 /*
02686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02687 %                                                                             %
02688 %                                                                             %
02689 %                                                                             %
02690 %   X F r e e R e s o u r c e s                                               %
02691 %                                                                             %
02692 %                                                                             %
02693 %                                                                             %
02694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02695 %
02696 %  XFreeResources() frees X11 resources.
02697 %
02698 %  The format of the XFreeResources method is:
02699 %
02700 %      void XFreeResources(Display *display,XVisualInfo *visual_info,
02701 %        XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
02702 %        XResourceInfo *resource_info,XWindowInfo *window_info)
02703 %        resource_info,window_info)
02704 %
02705 %  A description of each parameter follows:
02706 %
02707 %    o display: Specifies a connection to an X server; returned from
02708 %      XOpenDisplay.
02709 %
02710 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02711 %      returned from XGetVisualInfo.
02712 %
02713 %    o map_info: If map_type is specified, this structure is initialized
02714 %      with info from the Standard Colormap.
02715 %
02716 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02717 %
02718 %    o font_info: Specifies a pointer to a XFontStruct structure.
02719 %
02720 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
02721 %
02722 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
02723 %
02724 */
02725 MagickExport void XFreeResources(Display *display,XVisualInfo *visual_info,
02726   XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
02727   XResourceInfo *resource_info,XWindowInfo *window_info)
02728 {
02729   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02730   assert(display != (Display *) NULL);
02731   assert(resource_info != (XResourceInfo *) NULL);
02732   if (window_info != (XWindowInfo *) NULL)
02733     {
02734       /*
02735         Free X image.
02736       */
02737       if (window_info->ximage != (XImage *) NULL)
02738         XDestroyImage(window_info->ximage);
02739       if (window_info->id != (Window) NULL)
02740         {
02741           /*
02742             Free destroy window and free cursors.
02743           */
02744           if (window_info->id != XRootWindow(display,visual_info->screen))
02745             (void) XDestroyWindow(display,window_info->id);
02746           if (window_info->annotate_context != (GC) NULL)
02747             (void) XFreeGC(display,window_info->annotate_context);
02748           if (window_info->highlight_context != (GC) NULL)
02749             (void) XFreeGC(display,window_info->highlight_context);
02750           if (window_info->widget_context != (GC) NULL)
02751             (void) XFreeGC(display,window_info->widget_context);
02752           if (window_info->cursor != (Cursor) NULL)
02753             (void) XFreeCursor(display,window_info->cursor);
02754           window_info->cursor=(Cursor) NULL;
02755           if (window_info->busy_cursor != (Cursor) NULL)
02756             (void) XFreeCursor(display,window_info->busy_cursor);
02757           window_info->busy_cursor=(Cursor) NULL;
02758         }
02759     }
02760   /*
02761     Free font.
02762   */
02763   if (font_info != (XFontStruct *) NULL)
02764     (void) XFreeFont(display,font_info);
02765   if (map_info != (XStandardColormap *) NULL)
02766     {
02767       /*
02768         Free X Standard Colormap.
02769       */
02770       if (resource_info->map_type == (char *) NULL)
02771         (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
02772       (void) XFree((void *) map_info);
02773     }
02774   /*
02775     Free X visual info.
02776   */
02777   if (visual_info != (XVisualInfo *) NULL)
02778     (void) XFree((void *) visual_info);
02779   if (resource_info->close_server != MagickFalse)
02780     (void) XCloseDisplay(display);
02781 }
02782 
02783 /*
02784 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02785 %                                                                             %
02786 %                                                                             %
02787 %                                                                             %
02788 %   X F r e e S t a n d a r d C o l o r m a p                                 %
02789 %                                                                             %
02790 %                                                                             %
02791 %                                                                             %
02792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02793 %
02794 %  XFreeStandardColormap() frees an X11 colormap.
02795 %
02796 %  The format of the XFreeStandardColormap method is:
02797 %
02798 %      void XFreeStandardColormap(Display *display,
02799 %        const XVisualInfo *visual_info,XStandardColormap *map_info,
02800 %        XPixelInfo *pixel)
02801 %
02802 %  A description of each parameter follows:
02803 %
02804 %    o display: Specifies a connection to an X server; returned from
02805 %      XOpenDisplay.
02806 %
02807 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02808 %      returned from XGetVisualInfo.
02809 %
02810 %    o map_info: If map_type is specified, this structure is initialized
02811 %      with info from the Standard Colormap.
02812 %
02813 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02814 %
02815 */
02816 MagickExport void XFreeStandardColormap(Display *display,
02817   const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
02818 {
02819   /*
02820     Free colormap.
02821   */
02822   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02823   assert(display != (Display *) NULL);
02824   assert(visual_info != (XVisualInfo *) NULL);
02825   assert(map_info != (XStandardColormap *) NULL);
02826   (void) XFlush(display);
02827   if (map_info->colormap != (Colormap) NULL)
02828     {
02829       if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
02830         (void) XFreeColormap(display,map_info->colormap);
02831       else
02832         if (pixel != (XPixelInfo *) NULL)
02833           if ((visual_info->klass != TrueColor) &&
02834               (visual_info->klass != DirectColor))
02835             (void) XFreeColors(display,map_info->colormap,pixel->pixels,
02836               (int) pixel->colors,0);
02837     }
02838   map_info->colormap=(Colormap) NULL;
02839   if (pixel != (XPixelInfo *) NULL)
02840     {
02841       if (pixel->pixels != (unsigned long *) NULL)
02842         pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
02843       pixel->pixels=(unsigned long *) NULL;
02844     }
02845 }
02846 
02847 /*
02848 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02849 %                                                                             %
02850 %                                                                             %
02851 %                                                                             %
02852 %   X G e t A n n o t a t e I n f o                                           %
02853 %                                                                             %
02854 %                                                                             %
02855 %                                                                             %
02856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02857 %
02858 %  XGetAnnotateInfo() initializes the AnnotateInfo structure.
02859 %
02860 %  The format of the XGetAnnotateInfo method is:
02861 %
02862 %      void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
02863 %
02864 %  A description of each parameter follows:
02865 %
02866 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
02867 %
02868 */
02869 MagickExport void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
02870 {
02871   /*
02872     Initialize annotate structure.
02873   */
02874   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02875   assert(annotate_info != (XAnnotateInfo *) NULL);
02876   annotate_info->x=0;
02877   annotate_info->y=0;
02878   annotate_info->width=0;
02879   annotate_info->height=0;
02880   annotate_info->stencil=ForegroundStencil;
02881   annotate_info->degrees=0.0;
02882   annotate_info->font_info=(XFontStruct *) NULL;
02883   annotate_info->text=(char *) NULL;
02884   *annotate_info->geometry='\0';
02885   annotate_info->previous=(XAnnotateInfo *) NULL;
02886   annotate_info->next=(XAnnotateInfo *) NULL;
02887   (void) XSupportsLocale();
02888   (void) XSetLocaleModifiers("");
02889 }
02890 
02891 /*
02892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02893 %                                                                             %
02894 %                                                                             %
02895 %                                                                             %
02896 %   X G e t M a p I n f o                                                     %
02897 %                                                                             %
02898 %                                                                             %
02899 %                                                                             %
02900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02901 %
02902 %  XGetMapInfo() initializes the XStandardColormap structure.
02903 %
02904 %  The format of the XStandardColormap method is:
02905 %
02906 %      void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
02907 %        XStandardColormap *map_info)
02908 %
02909 %  A description of each parameter follows:
02910 %
02911 %    o colormap: Specifies the ID of the X server colormap.
02912 %
02913 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02914 %      returned from XGetVisualInfo.
02915 %
02916 %    o map_info: Specifies a pointer to a X11 XStandardColormap structure.
02917 %
02918 */
02919 MagickExport void XGetMapInfo(const XVisualInfo *visual_info,
02920   const Colormap colormap,XStandardColormap *map_info)
02921 {
02922   /*
02923     Initialize map info.
02924   */
02925   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02926   assert(visual_info != (XVisualInfo *) NULL);
02927   assert(map_info != (XStandardColormap *) NULL);
02928   map_info->colormap=colormap;
02929   map_info->red_max=visual_info->red_mask;
02930   map_info->red_mult=(unsigned long) (map_info->red_max != 0 ? 1 : 0);
02931   if (map_info->red_max != 0)
02932     while ((map_info->red_max & 0x01) == 0)
02933     {
02934       map_info->red_max>>=1;
02935       map_info->red_mult<<=1;
02936     }
02937   map_info->green_max=visual_info->green_mask;
02938   map_info->green_mult=(unsigned long) (map_info->green_max != 0 ? 1 : 0);
02939   if (map_info->green_max != 0)
02940     while ((map_info->green_max & 0x01) == 0)
02941     {
02942       map_info->green_max>>=1;
02943       map_info->green_mult<<=1;
02944     }
02945   map_info->blue_max=visual_info->blue_mask;
02946   map_info->blue_mult=(unsigned long) (map_info->blue_max != 0 ? 1 : 0);
02947   if (map_info->blue_max != 0)
02948     while ((map_info->blue_max & 0x01) == 0)
02949     {
02950       map_info->blue_max>>=1;
02951       map_info->blue_mult<<=1;
02952     }
02953   map_info->base_pixel=0;
02954 }
02955 
02956 /*
02957 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02958 %                                                                             %
02959 %                                                                             %
02960 %                                                                             %
02961 %   X G e t P i x e l I n f o                                                 %
02962 %                                                                             %
02963 %                                                                             %
02964 %                                                                             %
02965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02966 %
02967 %  XGetPixelPacket() initializes the PixelPacket structure.
02968 %
02969 %  The format of the XGetPixelPacket method is:
02970 %
02971 %      void XGetPixelPacket(Display *display,const XVisualInfo *visual_info,
02972 %        const XStandardColormap *map_info,const XResourceInfo *resource_info,
02973 %        Image *image,XPixelInfo *pixel)
02974 %        pixel)
02975 %
02976 %  A description of each parameter follows:
02977 %
02978 %    o display: Specifies a connection to an X server; returned from
02979 %      XOpenDisplay.
02980 %
02981 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02982 %      returned from XGetVisualInfo.
02983 %
02984 %    o map_info: If map_type is specified, this structure is initialized
02985 %      with info from the Standard Colormap.
02986 %
02987 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
02988 %
02989 %    o image: the image.
02990 %
02991 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02992 %
02993 */
02994 MagickExport void XGetPixelPacket(Display *display,
02995   const XVisualInfo *visual_info,const XStandardColormap *map_info,
02996   const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
02997 {
02998   static const char
02999     *PenColors[MaxNumberPens]=
03000     {
03001       "#000000000000",  /* black */
03002       "#00000000ffff",  /* blue */
03003       "#0000ffffffff",  /* cyan */
03004       "#0000ffff0000",  /* green */
03005       "#bdbdbdbdbdbd",  /* gray */
03006       "#ffff00000000",  /* red */
03007       "#ffff0000ffff",  /* magenta */
03008       "#ffffffff0000",  /* yellow */
03009       "#ffffffffffff",  /* white */
03010       "#bdbdbdbdbdbd",  /* gray */
03011       "#bdbdbdbdbdbd"   /* gray */
03012     };
03013 
03014   Colormap
03015     colormap;
03016 
03017   register long
03018     i;
03019 
03020   Status
03021     status;
03022 
03023   unsigned int
03024     packets;
03025 
03026   /*
03027     Initialize pixel info.
03028   */
03029   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03030   assert(display != (Display *) NULL);
03031   assert(visual_info != (XVisualInfo *) NULL);
03032   assert(map_info != (XStandardColormap *) NULL);
03033   assert(resource_info != (XResourceInfo *) NULL);
03034   assert(pixel != (XPixelInfo *) NULL);
03035   pixel->colors=0;
03036   if (image != (Image *) NULL)
03037     if (image->storage_class == PseudoClass)
03038       pixel->colors=image->colors;
03039   packets=(unsigned int)
03040     MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
03041   if (pixel->pixels != (unsigned long *) NULL)
03042     pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
03043   pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
03044     sizeof(pixel->pixels));
03045   if (pixel->pixels == (unsigned long *) NULL)
03046     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
03047       image->filename);
03048   /*
03049     Set foreground color.
03050   */
03051   colormap=map_info->colormap;
03052   (void) XParseColor(display,colormap,(char *) ForegroundColor,
03053     &pixel->foreground_color);
03054   status=XParseColor(display,colormap,resource_info->foreground_color,
03055     &pixel->foreground_color);
03056   if (status == False)
03057     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03058       resource_info->foreground_color);
03059   pixel->foreground_color.pixel=
03060     XStandardPixel(map_info,&pixel->foreground_color);
03061   pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
03062   /*
03063     Set background color.
03064   */
03065   (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
03066   status=XParseColor(display,colormap,resource_info->background_color,
03067     &pixel->background_color);
03068   if (status == False)
03069     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03070       resource_info->background_color);
03071   pixel->background_color.pixel=
03072     XStandardPixel(map_info,&pixel->background_color);
03073   pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
03074   /*
03075     Set border color.
03076   */
03077   (void) XParseColor(display,colormap,(char *) BorderColor,
03078     &pixel->border_color);
03079   status=XParseColor(display,colormap,resource_info->border_color,
03080     &pixel->border_color);
03081   if (status == False)
03082     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03083       resource_info->border_color);
03084   pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
03085   pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
03086   /*
03087     Set matte color.
03088   */
03089   pixel->matte_color=pixel->background_color;
03090   if (resource_info->matte_color != (char *) NULL)
03091     {
03092       /*
03093         Matte color is specified as a X resource or command line argument.
03094       */
03095       status=XParseColor(display,colormap,resource_info->matte_color,
03096         &pixel->matte_color);
03097       if (status == False)
03098         ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03099           resource_info->matte_color);
03100       pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
03101       pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
03102     }
03103   /*
03104     Set highlight color.
03105   */
03106   pixel->highlight_color.red=(unsigned short) ((
03107     pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
03108     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03109   pixel->highlight_color.green=(unsigned short) ((
03110     pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
03111     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03112   pixel->highlight_color.blue=(unsigned short) ((
03113     pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
03114     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03115   pixel->highlight_color.pixel=
03116     XStandardPixel(map_info,&pixel->highlight_color);
03117   pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
03118   /*
03119     Set shadow color.
03120   */
03121   pixel->shadow_color.red=(unsigned short) (((MagickRealType)
03122     pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
03123   pixel->shadow_color.green=(unsigned short) (((MagickRealType)
03124     pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
03125   pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
03126     pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
03127   pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
03128   pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
03129   /*
03130     Set depth color.
03131   */
03132   pixel->depth_color.red=(unsigned short) (((MagickRealType)
03133     pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
03134   pixel->depth_color.green=(unsigned short) (((MagickRealType)
03135     pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
03136   pixel->depth_color.blue=(unsigned short) (((MagickRealType)
03137     pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
03138   pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
03139   pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
03140   /*
03141     Set trough color.
03142   */
03143   pixel->trough_color.red=(unsigned short) (((MagickRealType)
03144     pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
03145   pixel->trough_color.green=(unsigned short) (((MagickRealType)
03146     pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
03147   pixel->trough_color.blue=(unsigned short) (((MagickRealType)
03148     pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
03149   pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
03150   pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
03151   /*
03152     Set pen color.
03153   */
03154   for (i=0; i < MaxNumberPens; i++)
03155   {
03156     (void) XParseColor(display,colormap,(char *) PenColors[i],
03157       &pixel->pen_colors[i]);
03158     status=XParseColor(display,colormap,resource_info->pen_colors[i],
03159       &pixel->pen_colors[i]);
03160     if (status == False)
03161       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03162         resource_info->pen_colors[i]);
03163     pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
03164     pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
03165   }
03166   pixel->box_color=pixel->background_color;
03167   pixel->pen_color=pixel->foreground_color;
03168   pixel->box_index=0;
03169   pixel->pen_index=1;
03170   if (image != (Image *) NULL)
03171     {
03172       if ((resource_info->gamma_correct != MagickFalse) &&
03173           (image->gamma != 0.0))
03174         {
03175           GeometryInfo
03176             geometry_info;
03177 
03178           MagickStatusType
03179             flags;
03180 
03181           /*
03182             Initialize map relative to display and image gamma.
03183           */
03184           flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
03185           red_gamma=geometry_info.rho;
03186           green_gamma=geometry_info.sigma;
03187           if ((flags & SigmaValue) == 0)
03188             green_gamma=red_gamma;
03189           blue_gamma=geometry_info.xi;
03190           if ((flags & XiValue) == 0)
03191             blue_gamma=red_gamma;
03192           red_gamma*=image->gamma;
03193           green_gamma*=image->gamma;
03194           blue_gamma*=image->gamma;
03195         }
03196       if (image->storage_class == PseudoClass)
03197         {
03198           /*
03199             Initialize pixel array for images of type PseudoClass.
03200           */
03201           for (i=0; i < (long) image->colors; i++)
03202             pixel->pixels[i]=
03203               XGammaPixel(map_info,image->colormap+i);
03204           for (i=0; i < MaxNumberPens; i++)
03205             pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
03206           pixel->colors+=MaxNumberPens;
03207         }
03208     }
03209 }
03210 
03211 /*
03212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03213 %                                                                             %
03214 %                                                                             %
03215 %                                                                             %
03216 %   X G e t R e s o u r c e C l a s s                                         %
03217 %                                                                             %
03218 %                                                                             %
03219 %                                                                             %
03220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03221 %
03222 %  XGetResourceClass() queries the X server for the specified resource name or
03223 %  class.  If the resource name or class is not defined in the database, the
03224 %  supplied default value is returned.
03225 %
03226 %  The format of the XGetResourceClass method is:
03227 %
03228 %      char *XGetResourceClass(XrmDatabase database,const char *client_name,
03229 %        const char *keyword,char *resource_default)
03230 %
03231 %  A description of each parameter follows:
03232 %
03233 %    o database: Specifies a resource database; returned from
03234 %      XrmGetStringDatabase.
03235 %
03236 %    o client_name:  Specifies the application name used to retrieve resource
03237 %      info from the X server database.
03238 %
03239 %    o keyword: Specifies the keyword of the value being retrieved.
03240 %
03241 %    o resource_default: Specifies the default value to return if the query
03242 %      fails to find the specified keyword/class.
03243 %
03244 */
03245 MagickExport char *XGetResourceClass(XrmDatabase database,
03246   const char *client_name,const char *keyword,char *resource_default)
03247 {
03248   char
03249     resource_class[MaxTextExtent],
03250     resource_name[MaxTextExtent];
03251 
03252   static char
03253     *resource_type;
03254 
03255   Status
03256     status;
03257 
03258   XrmValue
03259     resource_value;
03260 
03261   if (database == (XrmDatabase) NULL)
03262     return(resource_default);
03263   *resource_name='\0';
03264   *resource_class='\0';
03265   if (keyword != (char *) NULL)
03266     {
03267       int
03268         c,
03269         k;
03270 
03271       /*
03272         Initialize resource keyword and class.
03273       */
03274       (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",
03275         client_name,keyword);
03276       c=(int) (*client_name);
03277       if ((c >= XK_a) && (c <= XK_z))
03278         c-=(XK_a-XK_A);
03279       else
03280         if ((c >= XK_agrave) && (c <= XK_odiaeresis))
03281           c-=(XK_agrave-XK_Agrave);
03282         else
03283           if ((c >= XK_oslash) && (c <= XK_thorn))
03284             c-=(XK_oslash-XK_Ooblique);
03285       k=(int) (*keyword);
03286       if ((k >= XK_a) && (k <= XK_z))
03287         k-=(XK_a-XK_A);
03288       else
03289         if ((k >= XK_agrave) && (k <= XK_odiaeresis))
03290           k-=(XK_agrave-XK_Agrave);
03291         else
03292           if ((k >= XK_oslash) && (k <= XK_thorn))
03293             k-=(XK_oslash-XK_Ooblique);
03294       (void) FormatMagickString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
03295         client_name+1,k,keyword+1);
03296     }
03297   status=XrmGetResource(database,resource_name,resource_class,&resource_type,
03298     &resource_value);
03299   if (status == False)
03300     return(resource_default);
03301   return(resource_value.addr);
03302 }
03303 
03304 /*
03305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03306 %                                                                             %
03307 %                                                                             %
03308 %                                                                             %
03309 %   X G e t R e s o u r c e D a t a b a s e                                   %
03310 %                                                                             %
03311 %                                                                             %
03312 %                                                                             %
03313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03314 %
03315 %  XGetResourceDatabase() creates a new resource database and initializes it.
03316 %
03317 %  The format of the XGetResourceDatabase method is:
03318 %
03319 %      XrmDatabase XGetResourceDatabase(Display *display,
03320 %        const char *client_name)
03321 %
03322 %  A description of each parameter follows:
03323 %
03324 %    o database: XGetResourceDatabase() returns the database after it is
03325 %      initialized.
03326 %
03327 %    o display: Specifies a connection to an X server;  returned from
03328 %      XOpenDisplay.
03329 %
03330 %    o client_name:  Specifies the application name used to retrieve resource
03331 %      info from the X server database.
03332 %
03333 */
03334 MagickExport XrmDatabase XGetResourceDatabase(Display *display,
03335   const char *client_name)
03336 {
03337   char
03338     filename[MaxTextExtent];
03339 
03340   int
03341     c;
03342 
03343   register const char
03344     *p;
03345 
03346   XrmDatabase
03347     resource_database,
03348     server_database;
03349 
03350   if (display == (Display *) NULL)
03351     return((XrmDatabase) NULL);
03352   assert(client_name != (char *) NULL);
03353   /*
03354     Initialize resource database.
03355   */
03356   XrmInitialize();
03357   (void) XGetDefault(display,(char *) client_name,"dummy");
03358   resource_database=XrmGetDatabase(display);
03359   /*
03360     Combine application database.
03361   */
03362   if (client_name != (char *) NULL)
03363     {
03364       /*
03365         Get basename of client.
03366       */
03367       p=client_name+(strlen(client_name)-1);
03368       while ((p > client_name) && (*p != '/'))
03369         p--;
03370       if (*p == '/')
03371         client_name=p+1;
03372     }
03373   c=(int) (*client_name);
03374   if ((c >= XK_a) && (c <= XK_z))
03375     c-=(XK_a-XK_A);
03376   else
03377     if ((c >= XK_agrave) && (c <= XK_odiaeresis))
03378       c-=(XK_agrave-XK_Agrave);
03379     else
03380       if ((c >= XK_oslash) && (c <= XK_thorn))
03381         c-=(XK_oslash-XK_Ooblique);
03382 #if defined(X11_APPLICATION_PATH)
03383   (void) FormatMagickString(filename,MaxTextExtent,"%s%c%s",
03384     X11_APPLICATION_PATH,c,client_name+1);
03385   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
03386 #endif
03387   if (XResourceManagerString(display) != (char *) NULL)
03388     {
03389       /*
03390         Combine server database.
03391       */
03392       server_database=XrmGetStringDatabase(XResourceManagerString(display));
03393       XrmCombineDatabase(server_database,&resource_database,MagickFalse);
03394     }
03395   /*
03396     Merge user preferences database.
03397   */
03398 #if defined(X11_PREFERENCES_PATH)
03399   (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
03400     X11_PREFERENCES_PATH,client_name);
03401   ExpandFilename(filename);
03402   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
03403 #endif
03404   return(resource_database);
03405 }
03406 
03407 /*
03408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03409 %                                                                             %
03410 %                                                                             %
03411 %                                                                             %
03412 %   X G e t R e s o u r c e I n f o                                           %
03413 %                                                                             %
03414 %                                                                             %
03415 %                                                                             %
03416 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03417 %
03418 %  XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
03419 %
03420 %  The format of the XGetResourceInfo method is:
03421 %
03422 %      void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
03423 %        const char *client_name,XResourceInfo *resource_info)
03424 %
03425 %  A description of each parameter follows:
03426 %
03427 %    o image_info: the image info.
03428 %
03429 %    o database: Specifies a resource database; returned from
03430 %      XrmGetStringDatabase.
03431 %
03432 %    o client_name:  Specifies the application name used to retrieve
03433 %      resource info from the X server database.
03434 %
03435 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
03436 %
03437 */
03438 MagickExport void XGetResourceInfo(const ImageInfo *image_info,
03439   XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
03440 {
03441   char
03442     *cwd,
03443     *resource_value;
03444 
03445   /*
03446     Initialize resource info fields.
03447   */
03448   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03449   assert(resource_info != (XResourceInfo *) NULL);
03450   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
03451   resource_info->resource_database=database;
03452   resource_info->image_info=(ImageInfo *) image_info;
03453   (void) SetImageInfoProgressMonitor(resource_info->image_info,
03454     XMagickProgressMonitor,(void *) NULL);
03455   resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
03456   resource_info->close_server=MagickTrue;
03457   resource_info->client_name=AcquireString(client_name);
03458   resource_value=XGetResourceClass(database,client_name,"backdrop",
03459     (char *) "False");
03460   resource_info->backdrop=IsMagickTrue(resource_value);
03461   resource_info->background_color=XGetResourceInstance(database,client_name,
03462     "background",(char *) "#d6d6d6d6d6d6");
03463   resource_info->border_color=XGetResourceInstance(database,client_name,
03464     "borderColor",BorderColor);
03465   resource_value=XGetResourceClass(database,client_name,"borderWidth",
03466     (char *) "2");
03467   resource_info->border_width=(unsigned int) atoi(resource_value);
03468   resource_value=XGetResourceClass(database,client_name,"colormap",
03469     (char *) "shared");
03470   resource_info->colormap=UndefinedColormap;
03471   if (LocaleCompare("private",resource_value) == 0)
03472     resource_info->colormap=PrivateColormap;
03473   if (LocaleCompare("shared",resource_value) == 0)
03474     resource_info->colormap=SharedColormap;
03475   if (resource_info->colormap == UndefinedColormap)
03476     ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
03477       resource_value);
03478   resource_value=XGetResourceClass(database,client_name,
03479     "colorRecovery",(char *) "False");
03480   resource_info->color_recovery=IsMagickTrue(resource_value);
03481   resource_value=XGetResourceClass(database,client_name,"confirmExit",
03482     (char *) "False");
03483   resource_info->confirm_exit=IsMagickTrue(resource_value);
03484   resource_value=XGetResourceClass(database,client_name,"confirmEdit",
03485     (char *) "False");
03486   resource_info->confirm_edit=IsMagickTrue(resource_value);
03487   resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
03488   resource_info->delay=(unsigned int) atoi(resource_value);
03489   resource_info->display_gamma=XGetResourceClass(database,client_name,
03490     "displayGamma",(char *) "2.2");
03491   resource_value=XGetResourceClass(database,client_name,"displayWarnings",
03492     (char *) "True");
03493   resource_info->display_warnings=IsMagickTrue(resource_value);
03494   resource_info->font=XGetResourceClass(database,client_name,"font",
03495     (char *) NULL);
03496   resource_info->font=XGetResourceClass(database,client_name,"fontList",
03497     resource_info->font);
03498   resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
03499     (char *) "fixed");
03500   resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
03501     (char *) "variable");
03502   resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
03503     (char *) "5x8");
03504   resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
03505     (char *) "6x10");
03506   resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
03507     (char *) "7x13bold");
03508   resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
03509     (char *) "8x13bold");
03510   resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
03511     (char *) "9x15bold");
03512   resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
03513     (char *) "10x20");
03514   resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
03515     (char *) "12x24");
03516   resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
03517     (char *) "fixed");
03518   resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
03519     (char *) "fixed");
03520   resource_info->foreground_color=XGetResourceInstance(database,client_name,
03521     "foreground",ForegroundColor);
03522   resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
03523     (char *) "True");
03524   resource_info->gamma_correct=IsMagickTrue(resource_value);
03525   resource_info->image_geometry=ConstantString(XGetResourceClass(database,
03526     client_name,"geometry",(char *) NULL));
03527   resource_value=XGetResourceClass(database,client_name,"gravity",
03528     (char *) "Center");
03529   resource_info->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
03530     MagickFalse,resource_value);
03531   cwd=getcwd(resource_info->home_directory,MaxTextExtent);
03532   resource_info->icon_geometry=XGetResourceClass(database,client_name,
03533     "iconGeometry",(char *) NULL);
03534   resource_value=XGetResourceClass(database,client_name,"iconic",
03535     (char *) "False");
03536   resource_info->iconic=IsMagickTrue(resource_value);
03537   resource_value=XGetResourceClass(database,client_name,"immutable",
03538     LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
03539     (char *) "False");
03540   resource_info->immutable=IsMagickTrue(resource_value);
03541   resource_value=XGetResourceClass(database,client_name,"magnify",
03542     (char *) "3");
03543   resource_info->magnify=(unsigned int) atoi(resource_value);
03544   resource_info->map_type=XGetResourceClass(database,client_name,"map",
03545     (char *) NULL);
03546   resource_info->matte_color=XGetResourceInstance(database,client_name,
03547     "mattecolor",(char *) NULL);
03548   resource_info->name=ConstantString(XGetResourceClass(database,client_name,
03549     "name",(char *) NULL));
03550   resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
03551     (char *) "black");
03552   resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
03553     (char *) "blue");
03554   resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
03555     (char *) "cyan");
03556   resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
03557     (char *) "green");
03558   resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
03559     (char *) "gray");
03560   resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
03561     (char *) "red");
03562   resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
03563     (char *) "magenta");
03564   resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
03565     (char *) "yellow");
03566   resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
03567     (char *) "white");
03568   resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
03569     (char *) "gray");
03570   resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
03571     (char *) "gray");
03572   resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
03573   resource_info->pause=(unsigned int) atoi(resource_value);
03574   resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
03575   resource_info->quantum=atoi(resource_value);
03576   resource_info->text_font=XGetResourceClass(database,client_name,(char *)
03577     "font",(char *) "fixed");
03578   resource_info->text_font=XGetResourceClass(database,client_name,
03579     "textFontList",resource_info->text_font);
03580   resource_info->title=XGetResourceClass(database,client_name,"title",
03581     (char *) NULL);
03582   resource_value=XGetResourceClass(database,client_name,"undoCache",
03583     (char *) "16");
03584   resource_info->undo_cache=(unsigned int) atol(resource_value);
03585   resource_value=XGetResourceClass(database,client_name,"update",
03586     (char *) "False");
03587   resource_info->update=IsMagickTrue(resource_value);
03588   resource_value=XGetResourceClass(database,client_name,"usePixmap",
03589     (char *) "True");
03590   resource_info->use_pixmap=IsMagickTrue(resource_value);
03591   resource_value=XGetResourceClass(database,client_name,"sharedMemory",
03592     (char *) "True");
03593   resource_info->use_shared_memory=IsMagickTrue(resource_value);
03594   resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
03595     (char *) NULL);
03596   resource_info->window_group=XGetResourceClass(database,client_name,
03597     "windowGroup",(char *) NULL);
03598   resource_info->window_id=XGetResourceClass(database,client_name,"window",
03599     (char *) NULL);
03600   resource_info->write_filename=XGetResourceClass(database,client_name,
03601     "writeFilename",(char *) NULL);
03602 }
03603 
03604 /*
03605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03606 %                                                                             %
03607 %                                                                             %
03608 %                                                                             %
03609 %   X G e t R e s o u r c e I n s t a n c e                                   %
03610 %                                                                             %
03611 %                                                                             %
03612 %                                                                             %
03613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03614 %
03615 %  XGetResourceInstance() queries the X server for the specified resource name.
03616 %  If the resource name is not defined in the database, the supplied default
03617 %  value is returned.
03618 %
03619 %  The format of the XGetResourceInstance method is:
03620 %
03621 %      char *XGetResourceInstance(XrmDatabase database,const char *client_name,
03622 %        const char *keyword,const char *resource_default)
03623 %
03624 %  A description of each parameter follows:
03625 %
03626 %    o database: Specifies a resource database; returned from
03627 %      XrmGetStringDatabase.
03628 %
03629 %    o client_name:  Specifies the application name used to retrieve
03630 %      resource info from the X server database.
03631 %
03632 %    o keyword: Specifies the keyword of the value being retrieved.
03633 %
03634 %    o resource_default: Specifies the default value to return if the query
03635 %      fails to find the specified keyword/class.
03636 %
03637 */
03638 MagickExport char *XGetResourceInstance(XrmDatabase database,
03639   const char *client_name,const char *keyword,const char *resource_default)
03640 {
03641   char
03642     *resource_type,
03643     resource_name[MaxTextExtent];
03644 
03645   Status
03646     status;
03647 
03648   XrmValue
03649     resource_value;
03650 
03651   if (database == (XrmDatabase) NULL)
03652     return((char *) resource_default);
03653   *resource_name='\0';
03654   if (keyword != (char *) NULL)
03655     (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",client_name,
03656       keyword);
03657   status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
03658     &resource_value);
03659   if (status == False)
03660     return((char *) resource_default);
03661   return(resource_value.addr);
03662 }
03663 
03664 /*
03665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03666 %                                                                             %
03667 %                                                                             %
03668 %                                                                             %
03669 %   X G e t S c r e e n D e n s i t y                                         %
03670 %                                                                             %
03671 %                                                                             %
03672 %                                                                             %
03673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03674 %
03675 %  XGetScreenDensity() returns the density of the X server screen in
03676 %  dots-per-inch.
03677 %
03678 %  The format of the XGetScreenDensity method is:
03679 %
03680 %      char *XGetScreenDensity(Display *display)
03681 %
03682 %  A description of each parameter follows:
03683 %
03684 %    o density: XGetScreenDensity() returns the density of the X screen in
03685 %      dots-per-inch.
03686 %
03687 %    o display: Specifies a connection to an X server;  returned from
03688 %      XOpenDisplay.
03689 %
03690 */
03691 MagickExport char *XGetScreenDensity(Display *display)
03692 {
03693   char
03694     density[MaxTextExtent];
03695 
03696   double
03697     x_density,
03698     y_density;
03699 
03700   /*
03701     Set density as determined by screen size.
03702   */
03703   x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
03704     ((double) DisplayWidthMM(display,XDefaultScreen(display))));
03705   y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
03706     ((double) DisplayHeightMM(display,XDefaultScreen(display))));
03707   (void) FormatMagickString(density,MaxTextExtent,"%gx%g",x_density,y_density);
03708   return(GetPageGeometry(density));
03709 }
03710 
03711 /*
03712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03713 %                                                                             %
03714 %                                                                             %
03715 %                                                                             %
03716 +   X G e t S u b w i n d o w                                                 %
03717 %                                                                             %
03718 %                                                                             %
03719 %                                                                             %
03720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03721 %
03722 %  XGetSubwindow() returns the subwindow of a window chosen the user with the
03723 %  pointer and a button press.
03724 %
03725 %  The format of the XGetSubwindow method is:
03726 %
03727 %      Window XGetSubwindow(Display *display,Window window,int x,int y)
03728 %
03729 %  A description of each parameter follows:
03730 %
03731 %    o subwindow: XGetSubwindow() returns NULL if no subwindow is found
03732 %      otherwise the subwindow is returned.
03733 %
03734 %    o display: Specifies a connection to an X server;  returned from
03735 %      XOpenDisplay.
03736 %
03737 %    o window: Specifies a pointer to a Window.
03738 %
03739 %    o x: the x coordinate of the pointer relative to the origin of the
03740 %      window.
03741 %
03742 %    o y: the y coordinate of the pointer relative to the origin of the
03743 %      window.
03744 %
03745 %
03746 */
03747 static Window XGetSubwindow(Display *display,Window window,int x,int y)
03748 {
03749   int
03750     x_offset,
03751     y_offset;
03752 
03753   Status
03754     status;
03755 
03756   Window
03757     source_window,
03758     target_window;
03759 
03760   assert(display != (Display *) NULL);
03761   source_window=XRootWindow(display,XDefaultScreen(display));
03762   if (window == (Window) NULL)
03763     return(source_window);
03764   target_window=window;
03765   for ( ; ; )
03766   {
03767     status=XTranslateCoordinates(display,source_window,window,x,y,
03768       &x_offset,&y_offset,&target_window);
03769     if (status != True)
03770       break;
03771     if (target_window == (Window) NULL)
03772       break;
03773     source_window=window;
03774     window=target_window;
03775     x=x_offset;
03776     y=y_offset;
03777   }
03778   if (target_window == (Window) NULL)
03779     target_window=window;
03780   return(target_window);
03781 }
03782 
03783 /*
03784 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03785 %                                                                             %
03786 %                                                                             %
03787 %                                                                             %
03788 %   X G e t W i n d o w C o l o r                                             %
03789 %                                                                             %
03790 %                                                                             %
03791 %                                                                             %
03792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03793 %
03794 %  XGetWindowColor() returns the color of a pixel interactively chosen from the
03795 %  X server.
03796 %
03797 %  The format of the XGetWindowColor method is:
03798 %
03799 %      MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
03800 %        char *name)
03801 %
03802 %  A description of each parameter follows:
03803 %
03804 %    o display: Specifies a connection to an X server;  returned from
03805 %      XOpenDisplay.
03806 %
03807 %    o windows: Specifies a pointer to a XWindows structure.
03808 %
03809 %    o name: the name of the color if found in the X Color Database is
03810 %      returned in this character string.
03811 %
03812 */
03813 MagickExport MagickBooleanType XGetWindowColor(Display *display,
03814   XWindows *windows,char *name)
03815 {
03816   int
03817     x,
03818     y;
03819 
03820   PixelPacket
03821     pixel;
03822 
03823   RectangleInfo
03824     crop_info;
03825 
03826   Status
03827     status;
03828 
03829   Window
03830     child,
03831     client_window,
03832     root_window,
03833     target_window;
03834 
03835   XColor
03836     color;
03837 
03838   XImage
03839     *ximage;
03840 
03841   XWindowAttributes
03842     window_attributes;
03843 
03844   /*
03845     Choose a pixel from the X server.
03846   */
03847   assert(display != (Display *) NULL);
03848   assert(name != (char *) NULL);
03849   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
03850   *name='\0';
03851   target_window=XSelectWindow(display,&crop_info);
03852   if (target_window == (Window) NULL)
03853     return(MagickFalse);
03854   root_window=XRootWindow(display,XDefaultScreen(display));
03855   client_window=target_window;
03856   if (target_window != root_window)
03857     {
03858       unsigned int
03859         d;
03860 
03861       /*
03862         Get client window.
03863       */
03864       status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
03865       if (status != False)
03866         {
03867           client_window=XClientWindow(display,target_window);
03868           target_window=client_window;
03869         }
03870     }
03871   /*
03872     Verify window is viewable.
03873   */
03874   status=XGetWindowAttributes(display,target_window,&window_attributes);
03875   if ((status == False) || (window_attributes.map_state != IsViewable))
03876     return(MagickFalse);
03877   /*
03878     Get window X image.
03879   */
03880   (void) XTranslateCoordinates(display,root_window,target_window,
03881     (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
03882   ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
03883   if (ximage == (XImage *) NULL)
03884     return(MagickFalse);
03885   color.pixel=XGetPixel(ximage,0,0);
03886   XDestroyImage(ximage);
03887   /*
03888     Match color against the color database.
03889   */
03890   (void) XQueryColor(display,window_attributes.colormap,&color);
03891   pixel.red=ScaleShortToQuantum(color.red);
03892   pixel.green=ScaleShortToQuantum(color.green);
03893   pixel.blue=ScaleShortToQuantum(color.blue);
03894   pixel.opacity=OpaqueOpacity;
03895   (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
03896     &windows->image.image->exception);
03897   return(MagickTrue);
03898 }
03899 
03900 /*
03901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03902 %                                                                             %
03903 %                                                                             %
03904 %                                                                             %
03905 +   X G e t W i n d o w I m a g e                                             %
03906 %                                                                             %
03907 %                                                                             %
03908 %                                                                             %
03909 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03910 %
03911 %  XGetWindowImage() reads an image from the target X window and returns it.
03912 %  XGetWindowImage() optionally descends the window hierarchy and overlays the
03913 %  target image with each child image in an optimized fashion.  Any child
03914 %  window that have the same visual, colormap, and are contained by its parent
03915 %  are exempted.
03916 %
03917 %  The format of the XGetWindowImage method is:
03918 %
03919 %      Image *XGetWindowImage(Display *display,const Window window,
03920 %        const unsigned int borders,const unsigned int level)
03921 %
03922 %  A description of each parameter follows:
03923 %
03924 %    o display: Specifies a connection to an X server;  returned from
03925 %      XOpenDisplay.
03926 %
03927 %    o window: Specifies the window to obtain the image from.
03928 %
03929 %    o borders: Specifies whether borders pixels are to be saved with
03930 %      the image.
03931 %
03932 %    o level: Specifies an unsigned integer representing the level of
03933 %      decent in the window hierarchy.  This value must be zero or one on
03934 %      the initial call to XGetWindowImage.  A value of zero returns after
03935 %      one call.  A value of one causes the function to descend the window
03936 %      hierarchy and overlay the target image with each subwindow image.
03937 %
03938 %
03939 */
03940 static Image *XGetWindowImage(Display *display,const Window window,
03941   const unsigned int borders,const unsigned int level)
03942 {
03943   typedef struct _ColormapInfo
03944   {
03945     Colormap
03946       colormap;
03947 
03948     XColor
03949       *colors;
03950 
03951     struct _ColormapInfo
03952       *next;
03953   } ColormapInfo;
03954 
03955   typedef struct _WindowInfo
03956   {
03957     Window
03958       window,
03959       parent;
03960 
03961     Visual
03962       *visual;
03963 
03964     Colormap
03965       colormap;
03966 
03967     XSegment
03968       bounds;
03969 
03970     RectangleInfo
03971       crop_info;
03972   } WindowInfo;
03973 
03974   IndexPacket
03975     index;
03976 
03977   int
03978     display_height,
03979     display_width,
03980     id,
03981     x_offset,
03982     y_offset;
03983 
03984   RectangleInfo
03985     crop_info;
03986 
03987   register IndexPacket
03988     *indexes;
03989 
03990   register int
03991     i;
03992 
03993   static ColormapInfo
03994     *colormap_info = (ColormapInfo *) NULL;
03995 
03996   static int
03997     max_windows = 0,
03998     number_windows = 0;
03999 
04000   static WindowInfo
04001     *window_info;
04002 
04003   Status
04004     status;
04005 
04006   Window
04007     child,
04008     root_window;
04009 
04010   XWindowAttributes
04011     window_attributes;
04012 
04013   /*
04014     Verify window is viewable.
04015   */
04016   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
04017   assert(display != (Display *) NULL);
04018   status=XGetWindowAttributes(display,window,&window_attributes);
04019   if ((status == False) || (window_attributes.map_state != IsViewable))
04020     return((Image *) NULL);
04021   /*
04022     Cropping rectangle is relative to root window.
04023   */
04024   root_window=XRootWindow(display,XDefaultScreen(display));
04025   (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
04026     &y_offset,&child);
04027   crop_info.x=(long) x_offset;
04028   crop_info.y=(long) y_offset;
04029   crop_info.width=(unsigned long) window_attributes.width;
04030   crop_info.height=(unsigned long) window_attributes.height;
04031   if (borders != MagickFalse)
04032     {
04033       /*
04034         Include border in image.
04035       */
04036       crop_info.x-=(long) window_attributes.border_width;
04037       crop_info.y-=(long) window_attributes.border_width;
04038       crop_info.width+=(unsigned long) (window_attributes.border_width << 1);
04039       crop_info.height+=(unsigned long) (window_attributes.border_width << 1);
04040     }
04041   /*
04042     Crop to root window.
04043   */
04044   if (crop_info.x < 0)
04045     {
04046       crop_info.width+=crop_info.x;
04047       crop_info.x=0;
04048     }
04049   if (crop_info.y < 0)
04050     {
04051       crop_info.height+=crop_info.y;
04052       crop_info.y=0;
04053     }
04054   display_width=XDisplayWidth(display,XDefaultScreen(display));
04055   if ((int) (crop_info.x+crop_info.width) > display_width)
04056     crop_info.width=(unsigned long) (display_width-crop_info.x);
04057   display_height=XDisplayHeight(display,XDefaultScreen(display));
04058   if ((int) (crop_info.y+crop_info.height) > display_height)
04059     crop_info.height=(unsigned long) (display_height-crop_info.y);
04060   /*
04061     Initialize window info attributes.
04062   */
04063   if (number_windows >= max_windows)
04064     {
04065       /*
04066         Allocate or resize window info buffer.
04067       */
04068       max_windows+=1024;
04069       if (window_info == (WindowInfo *) NULL)
04070         window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
04071           sizeof(*window_info));
04072       else
04073         window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
04074           max_windows,sizeof(*window_info));
04075     }
04076   if (window_info == (WindowInfo *) NULL)
04077     {
04078       ThrowXWindowFatalException(ResourceLimitError,
04079         "MemoryAllocationFailed","...");
04080       return((Image *) NULL);
04081     }
04082   id=number_windows++;
04083   window_info[id].window=window;
04084   window_info[id].visual=window_attributes.visual;
04085   window_info[id].colormap=window_attributes.colormap;
04086   window_info[id].bounds.x1=(short) crop_info.x;
04087   window_info[id].bounds.y1=(short) crop_info.y;
04088   window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
04089   window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
04090   crop_info.x-=x_offset;
04091   crop_info.y-=y_offset;
04092   window_info[id].crop_info=crop_info;
04093   if (level != 0)
04094     {
04095       unsigned int
04096         number_children;
04097 
04098       Window
04099         *children;
04100 
04101       /*
04102         Descend the window hierarchy.
04103       */
04104       status=XQueryTree(display,window,&root_window,&window_info[id].parent,
04105         &children,&number_children);
04106       for (i=0; i < id; i++)
04107         if ((window_info[i].window == window_info[id].parent) &&
04108             (window_info[i].visual == window_info[id].visual) &&
04109             (window_info[i].colormap == window_info[id].colormap))
04110           {
04111             if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
04112                 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
04113                 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
04114                 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
04115               {
04116                 /*
04117                   Eliminate windows not circumscribed by their parent.
04118                 */
04119                 number_windows--;
04120                 break;
04121               }
04122           }
04123       if ((status == True) && (number_children != 0))
04124         {
04125           for (i=0; i < (int) number_children; i++)
04126             (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
04127           (void) XFree((void *) children);
04128         }
04129     }
04130   if (level <= 1)
04131     {
04132       ColormapInfo
04133         *next;
04134 
04135       ExceptionInfo
04136         *exception;
04137 
04138       Image
04139         *composite_image,
04140         *image;
04141 
04142       int
04143         y;
04144 
04145       MagickBooleanType
04146         import;
04147 
04148       register int
04149         j,
04150         x;
04151 
04152       register PixelPacket
04153         *__restrict q;
04154 
04155       register unsigned long
04156         pixel;
04157 
04158       unsigned int
04159         number_colors;
04160 
04161       XColor
04162         *colors;
04163 
04164       XImage
04165         *ximage;
04166 
04167       /*
04168         Get X image for each window in the list.
04169       */
04170       image=NewImageList();
04171       for (id=0; id < number_windows; id++)
04172       {
04173         /*
04174           Does target window intersect top level window?
04175         */
04176         import=
04177           ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
04178            (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
04179            (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
04180            (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
04181           MagickTrue : MagickFalse;
04182         /*
04183           Is target window contained by another window with the same colormap?
04184         */
04185         for (j=0; j < id; j++)
04186           if ((window_info[id].visual == window_info[j].visual) &&
04187               (window_info[id].colormap == window_info[j].colormap))
04188             {
04189               if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
04190                   (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
04191                   (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
04192                   (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
04193                   import=MagickFalse;
04194             }
04195           else
04196             if ((window_info[id].visual != window_info[j].visual) ||
04197                 (window_info[id].colormap != window_info[j].colormap))
04198               {
04199                 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
04200                     (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
04201                     (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
04202                     (window_info[id].bounds.y1 < window_info[j].bounds.y2))
04203                   import=MagickTrue;
04204               }
04205         if (import == MagickFalse)
04206           continue;
04207         /*
04208           Get X image.
04209         */
04210         ximage=XGetImage(display,window_info[id].window,(int)
04211           window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
04212           (unsigned int) window_info[id].crop_info.width,(unsigned int)
04213           window_info[id].crop_info.height,AllPlanes,ZPixmap);
04214         if (ximage == (XImage *) NULL)
04215           continue;
04216         /*
04217           Initialize window colormap.
04218         */
04219         number_colors=0;
04220         colors=(XColor *) NULL;
04221         if (window_info[id].colormap != (Colormap) NULL)
04222           {
04223             ColormapInfo
04224               *p;
04225 
04226             /*
04227               Search colormap list for window colormap.
04228             */
04229             number_colors=(unsigned int) window_info[id].visual->map_entries;
04230             for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
04231               if (p->colormap == window_info[id].colormap)
04232                 break;
04233             if (p == (ColormapInfo *) NULL)
04234               {
04235                 /*
04236                   Get the window colormap.
04237                 */
04238                 colors=(XColor *) AcquireQuantumMemory(number_colors,
04239                   sizeof(*colors));
04240                 if (colors == (XColor *) NULL)
04241                   {
04242                     XDestroyImage(ximage);
04243                     return((Image *) NULL);
04244                   }
04245                 if ((window_info[id].visual->klass != DirectColor) &&
04246                     (window_info[id].visual->klass != TrueColor))
04247                   for (i=0; i < (int) number_colors; i++)
04248                   {
04249                     colors[i].pixel=(unsigned long) i;
04250                     colors[i].pad='\0';
04251                   }
04252                 else
04253                   {
04254                     unsigned long
04255                       blue,
04256                       blue_bit,
04257                       green,
04258                       green_bit,
04259                       red,
04260                       red_bit;
04261 
04262                     /*
04263                       DirectColor or TrueColor visual.
04264                     */
04265                     red=0;
04266                     green=0;
04267                     blue=0;
04268                     red_bit=window_info[id].visual->red_mask &
04269                       (~(window_info[id].visual->red_mask)+1);
04270                     green_bit=window_info[id].visual->green_mask &
04271                       (~(window_info[id].visual->green_mask)+1);
04272                     blue_bit=window_info[id].visual->blue_mask &
04273                       (~(window_info[id].visual->blue_mask)+1);
04274                     for (i=0; i < (int) number_colors; i++)
04275                     {
04276                       colors[i].pixel=red | green | blue;
04277                       colors[i].pad='\0';
04278                       red+=red_bit;
04279                       if (red > window_info[id].visual->red_mask)
04280                         red=0;
04281                       green+=green_bit;
04282                       if (green > window_info[id].visual->green_mask)
04283                         green=0;
04284                       blue+=blue_bit;
04285                       if (blue > window_info[id].visual->blue_mask)
04286                         blue=0;
04287                     }
04288                   }
04289                 (void) XQueryColors(display,window_info[id].colormap,colors,
04290                   (int) number_colors);
04291                 /*
04292                   Append colormap to colormap list.
04293                 */
04294                 p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
04295                 if (p == (ColormapInfo *) NULL)
04296                   return((Image *) NULL);
04297                 p->colormap=window_info[id].colormap;
04298                 p->colors=colors;
04299                 p->next=colormap_info;
04300                 colormap_info=p;
04301               }
04302             colors=p->colors;
04303           }
04304         /*
04305           Allocate image structure.
04306         */
04307         composite_image=AcquireImage((ImageInfo *) NULL);
04308         if (composite_image == (Image *) NULL)
04309           {
04310             XDestroyImage(ximage);
04311             return((Image *) NULL);
04312           }
04313         /*
04314           Convert X image to MIFF format.
04315         */
04316         if ((window_info[id].visual->klass != TrueColor) &&
04317             (window_info[id].visual->klass != DirectColor))
04318           composite_image->storage_class=PseudoClass;
04319         composite_image->columns=(unsigned long) ximage->width;
04320         composite_image->rows=(unsigned long) ximage->height;
04321         exception=(&composite_image->exception);
04322         switch (composite_image->storage_class)
04323         {
04324           case DirectClass:
04325           default:
04326           {
04327             register unsigned long
04328               color,
04329               index;
04330 
04331             unsigned long
04332               blue_mask,
04333               blue_shift,
04334               green_mask,
04335               green_shift,
04336               red_mask,
04337               red_shift;
04338 
04339             /*
04340               Determine shift and mask for red, green, and blue.
04341             */
04342             red_mask=window_info[id].visual->red_mask;
04343             red_shift=0;
04344             while ((red_mask != 0) && ((red_mask & 0x01) == 0))
04345             {
04346               red_mask>>=1;
04347               red_shift++;
04348             }
04349             green_mask=window_info[id].visual->green_mask;
04350             green_shift=0;
04351             while ((green_mask != 0) && ((green_mask & 0x01) == 0))
04352             {
04353               green_mask>>=1;
04354               green_shift++;
04355             }
04356             blue_mask=window_info[id].visual->blue_mask;
04357             blue_shift=0;
04358             while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
04359             {
04360               blue_mask>>=1;
04361               blue_shift++;
04362             }
04363             /*
04364               Convert X image to DirectClass packets.
04365             */
04366             if ((number_colors != 0) &&
04367                 (window_info[id].visual->klass == DirectColor))
04368               for (y=0; y < (int) composite_image->rows; y++)
04369               {
04370                 q=QueueAuthenticPixels(composite_image,0,y,
04371                   composite_image->columns,1,exception);
04372                 if (q == (PixelPacket *) NULL)
04373                   break;
04374                 for (x=0; x < (int) composite_image->columns; x++)
04375                 {
04376                   pixel=XGetPixel(ximage,x,y);
04377                   index=(pixel >> red_shift) & red_mask;
04378                   q->red=ScaleShortToQuantum(colors[index].red);
04379                   index=(pixel >> green_shift) & green_mask;
04380                   q->green=ScaleShortToQuantum(colors[index].green);
04381                   index=(pixel >> blue_shift) & blue_mask;
04382                   q->blue=ScaleShortToQuantum(colors[index].blue);
04383                   q++;
04384                 }
04385                 if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
04386                   break;
04387               }
04388             else
04389               for (y=0; y < (int) composite_image->rows; y++)
04390               {
04391                 q=QueueAuthenticPixels(composite_image,0,y,
04392                   composite_image->columns,1,exception);
04393                 if (q == (PixelPacket *) NULL)
04394                   break;
04395                 for (x=0; x < (int) composite_image->columns; x++)
04396                 {
04397                   pixel=XGetPixel(ximage,x,y);
04398                   color=(pixel >> red_shift) & red_mask;
04399                   color=(65535UL*color)/red_mask;
04400                   q->red=ScaleShortToQuantum((unsigned short) color);
04401                   color=(pixel >> green_shift) & green_mask;
04402                   color=(65535UL*color)/green_mask;
04403                   q->green=ScaleShortToQuantum((unsigned short) color);
04404                   color=(pixel >> blue_shift) & blue_mask;
04405                   color=(65535UL*color)/blue_mask;
04406                   q->blue=ScaleShortToQuantum((unsigned short) color);
04407                   q++;
04408                 }
04409                 if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
04410                   break;
04411               }
04412             break;
04413           }
04414           case PseudoClass:
04415           {
04416             /*
04417               Create colormap.
04418             */
04419             if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
04420               {
04421                 XDestroyImage(ximage);
04422                 composite_image=DestroyImage(composite_image);
04423                 return((Image *) NULL);
04424               }
04425             for (i=0; i < (int) composite_image->colors; i++)
04426             {
04427               composite_image->colormap[colors[i].pixel].red=
04428                 ScaleShortToQuantum(colors[i].red);
04429               composite_image->colormap[colors[i].pixel].green=
04430                 ScaleShortToQuantum(colors[i].green);
04431               composite_image->colormap[colors[i].pixel].blue=
04432                 ScaleShortToQuantum(colors[i].blue);
04433             }
04434             /*
04435               Convert X image to PseudoClass packets.
04436             */
04437             for (y=0; y < (int) composite_image->rows; y++)
04438             {
04439               q=QueueAuthenticPixels(composite_image,0,y,composite_image->columns,1,exception);
04440               if (q == (PixelPacket *) NULL)
04441                 break;
04442               indexes=GetAuthenticIndexQueue(composite_image);
04443               for (x=0; x < (int) composite_image->columns; x++)
04444               {
04445                 index=(IndexPacket) XGetPixel(ximage,x,y);
04446                 indexes[x]=index;
04447                 *q++=composite_image->colormap[(long) index];
04448               }
04449               if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
04450                 break;
04451             }
04452