xwindow.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %              X   X  W   W  IIIII  N   N  DDDD    OOO   W   W                %
00007 %               X X   W   W    I    NN  N  D   D  O   O  W   W                %
00008 %                X    W   W    I    N N N  D   D  O   O  W   W                %
00009 %               X X   W W W    I    N  NN  D   D  O   O  W W W                %
00010 %              X   X   W W   IIIII  N   N  DDDD    OOO    W W                 %
00011 %                                                                             %
00012 %                                                                             %
00013 %                       MagickCore X11 Utility Methods                        %
00014 %                                                                             %
00015 %                               Software Design                               %
00016 %                                 John Cristy                                 %
00017 %                                  July 1992                                  %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "magick/studio.h"
00043 #include "magick/animate.h"
00044 #include "magick/artifact.h"
00045 #include "magick/blob.h"
00046 #include "magick/cache.h"
00047 #include "magick/client.h"
00048 #include "magick/color.h"
00049 #include "magick/color-private.h"
00050 #include "magick/composite.h"
00051 #include "magick/display.h"
00052 #include "magick/exception.h"
00053 #include "magick/exception-private.h"
00054 #include "magick/geometry.h"
00055 #include "magick/identify.h"
00056 #include "magick/image.h"
00057 #include "magick/image-private.h"
00058 #include "magick/list.h"
00059 #include "magick/locale_.h"
00060 #include "magick/log.h"
00061 #include "magick/magick.h"
00062 #include "magick/memory_.h"
00063 #include "magick/monitor.h"
00064 #include "magick/option.h"
00065 #include "magick/PreRvIcccm.h"
00066 #include "magick/quantize.h"
00067 #include "magick/quantum.h"
00068 #include "magick/quantum-private.h"
00069 #include "magick/resource_.h"
00070 #include "magick/resize.h"
00071 #include "magick/shear.h"
00072 #include "magick/statistic.h"
00073 #include "magick/string_.h"
00074 #include "magick/string-private.h"
00075 #include "magick/transform.h"
00076 #include "magick/utility.h"
00077 #include "magick/widget.h"
00078 #include "magick/xwindow.h"
00079 #include "magick/xwindow-private.h"
00080 #include "magick/version.h"
00081 #if defined(__BEOS__)
00082 #include <OS.h>
00083 #endif
00084 #if defined(MAGICKCORE_X11_DELEGATE)
00085 #include <X11/Xproto.h>
00086 #include <X11/Xlocale.h>
00087 #if defined(MAGICK_HAVE_POLL)
00088 # include <sys/poll.h>
00089 #endif
00090 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
00091 #if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
00092 # include <machine/param.h>
00093 #endif
00094 #include <sys/ipc.h>
00095 #include <sys/shm.h>
00096 #include <X11/extensions/XShm.h>
00097 #endif
00098 #if defined(MAGICKCORE_HAVE_SHAPE)
00099 #include <X11/extensions/shape.h>
00100 #endif
00101 
00102 /*
00103   X defines.
00104 */
00105 #define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
00106   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
00107   QuantumRange)))
00108 #define XGammaPixel(map,color)  (unsigned long) (map->base_pixel+ \
00109   ((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
00110     map->red_mult)+ \
00111   ((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
00112     map->green_mult)+ \
00113   ((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
00114     map->blue_mult))
00115 #define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
00116   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
00117   QuantumRange)))
00118 #define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
00119   (color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
00120   QuantumRange)))
00121 #define XStandardPixel(map,color)  (unsigned long) (map->base_pixel+ \
00122   (((color)->red*map->red_max/65535L)*map->red_mult)+ \
00123   (((color)->green*map->green_max/65535L)*map->green_mult)+ \
00124   (((color)->blue*map->blue_max/65535L)*map->blue_mult))
00125 
00126 #define AccentuateModulate  ScaleCharToQuantum(80)
00127 #define HighlightModulate  ScaleCharToQuantum(125)
00128 #define ShadowModulate  ScaleCharToQuantum(135)
00129 #define DepthModulate  ScaleCharToQuantum(185)
00130 #define TroughModulate  ScaleCharToQuantum(110)
00131 
00132 #define XLIB_ILLEGAL_ACCESS  1
00133 #undef ForgetGravity
00134 #undef NorthWestGravity
00135 #undef NorthGravity
00136 #undef NorthEastGravity
00137 #undef WestGravity
00138 #undef CenterGravity
00139 #undef EastGravity
00140 #undef SouthWestGravity
00141 #undef SouthGravity
00142 #undef SouthEastGravity
00143 #undef StaticGravity
00144 
00145 #undef index
00146 #if defined(hpux9)
00147 #define XFD_SET  int
00148 #else
00149 #define XFD_SET  fd_set
00150 #endif
00151 
00152 /*
00153   Enumeration declarations.
00154 */
00155 typedef enum
00156 {
00157 #undef DoRed
00158   DoRed = 0x0001,
00159 #undef DoGreen
00160   DoGreen = 0x0002,
00161 #undef DoBlue
00162   DoBlue = 0x0004,
00163   DoMatte = 0x0008
00164 } XColorFlags;
00165 
00166 /*
00167   Typedef declarations.
00168 */
00169 typedef struct _DiversityPacket
00170 {
00171   Quantum
00172     red,
00173     green,
00174     blue;
00175 
00176   unsigned short
00177     index;
00178 
00179   unsigned long
00180     count;
00181 } DiversityPacket;
00182 
00183 /*
00184   Constant declaractions.
00185 */
00186 static MagickBooleanType
00187   xerror_alert = MagickFalse;
00188 
00189 /*
00190   Method prototypes.
00191 */
00192 static const char
00193   *XVisualClassName(const int);
00194 
00195 static MagickRealType
00196   blue_gamma = 1.0,
00197   green_gamma = 1.0,
00198   red_gamma = 1.0;
00199 
00200 static MagickBooleanType
00201   XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
00202 
00203 static void
00204   XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
00205     XImage *,XImage *),
00206   XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
00207     XImage *,XImage *);
00208 
00209 static Window
00210   XSelectWindow(Display *,RectangleInfo *);
00211 
00212 /*
00213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00214 %                                                                             %
00215 %                                                                             %
00216 %                                                                             %
00217 %   D e s t r o y X R e s o u r c e s                                         %
00218 %                                                                             %
00219 %                                                                             %
00220 %                                                                             %
00221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00222 %
00223 %  DestroyXResources() destroys any X resources.
00224 %
00225 %  The format of the DestroyXResources method is:
00226 %
00227 %      void DestroyXResources()
00228 %
00229 %  A description of each parameter follows:
00230 %
00231 */
00232 MagickExport void DestroyXResources(void)
00233 {
00234   register int
00235     i;
00236 
00237   unsigned int
00238     number_windows;
00239 
00240   XWindowInfo
00241     *magick_windows[MaxXWindows];
00242 
00243   XWindows
00244     *windows;
00245 
00246   DestroyXWidget();
00247   windows=XSetWindows((XWindows *) ~0);
00248   if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
00249     return;
00250   number_windows=0;
00251   magick_windows[number_windows++]=(&windows->context);
00252   magick_windows[number_windows++]=(&windows->group_leader);
00253   magick_windows[number_windows++]=(&windows->backdrop);
00254   magick_windows[number_windows++]=(&windows->icon);
00255   magick_windows[number_windows++]=(&windows->image);
00256   magick_windows[number_windows++]=(&windows->info);
00257   magick_windows[number_windows++]=(&windows->magnify);
00258   magick_windows[number_windows++]=(&windows->pan);
00259   magick_windows[number_windows++]=(&windows->command);
00260   magick_windows[number_windows++]=(&windows->widget);
00261   magick_windows[number_windows++]=(&windows->popup);
00262   magick_windows[number_windows++]=(&windows->context);
00263   for (i=0; i < (int) number_windows; i++)
00264   {
00265     if (magick_windows[i]->mapped != MagickFalse)
00266       {
00267         (void) XWithdrawWindow(windows->display,magick_windows[i]->id,
00268           magick_windows[i]->screen);
00269         magick_windows[i]->mapped=MagickFalse;
00270       }
00271     if (magick_windows[i]->name != (char *) NULL)
00272       magick_windows[i]->name=(char *)
00273         RelinquishMagickMemory(magick_windows[i]->name);
00274     if (magick_windows[i]->icon_name != (char *) NULL)
00275       magick_windows[i]->icon_name=(char *)
00276         RelinquishMagickMemory(magick_windows[i]->icon_name);
00277     if (magick_windows[i]->cursor != (Cursor) NULL)
00278       {
00279         (void) XFreeCursor(windows->display,magick_windows[i]->cursor);
00280         magick_windows[i]->cursor=(Cursor) NULL;
00281       }
00282     if (magick_windows[i]->busy_cursor != (Cursor) NULL)
00283       {
00284         (void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
00285         magick_windows[i]->busy_cursor=(Cursor) NULL;
00286       }
00287     if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
00288       {
00289         (void) XFreePixmap(windows->display,
00290           magick_windows[i]->highlight_stipple);
00291         magick_windows[i]->highlight_stipple=(Pixmap) NULL;
00292       }
00293     if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
00294       {
00295         (void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
00296         magick_windows[i]->shadow_stipple=(Pixmap) NULL;
00297       }
00298     if (magick_windows[i]->ximage != (XImage *) NULL)
00299       {
00300         XDestroyImage(magick_windows[i]->ximage);
00301         magick_windows[i]->ximage=(XImage *) NULL;
00302       }
00303     if (magick_windows[i]->pixmap != (Pixmap) NULL)
00304       {
00305         (void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
00306         magick_windows[i]->pixmap=(Pixmap) NULL;
00307       }
00308     if (magick_windows[i]->id != (Window) NULL)
00309       {
00310         (void) XDestroyWindow(windows->display,magick_windows[i]->id);
00311         magick_windows[i]->id=(Window) NULL;
00312       }
00313     if (magick_windows[i]->destroy != MagickFalse)
00314       {
00315         if (magick_windows[i]->image != (Image *) NULL)
00316           {
00317             magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
00318             magick_windows[i]->image=NewImageList();
00319           }
00320         if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
00321           {
00322             (void) XFreePixmap(windows->display,
00323               magick_windows[i]->matte_pixmap);
00324             magick_windows[i]->matte_pixmap=(Pixmap) NULL;
00325           }
00326       }
00327     if (magick_windows[i]->segment_info != (void *) NULL)
00328       {
00329 #if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
00330         XShmSegmentInfo
00331           *segment_info;
00332 
00333         segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
00334         if (segment_info != (XShmSegmentInfo *) NULL)
00335           if (segment_info[0].shmid >= 0)
00336             {
00337               if (segment_info[0].shmaddr != NULL)
00338                 (void) shmdt(segment_info[0].shmaddr);
00339               (void) shmctl(segment_info[0].shmid,IPC_RMID,0);
00340               segment_info[0].shmaddr=NULL;
00341               segment_info[0].shmid=(-1);
00342             }
00343 #endif
00344         magick_windows[i]->segment_info=(void *)
00345           RelinquishMagickMemory(magick_windows[i]->segment_info);
00346       }
00347   }
00348   windows->icon_resources=(XResourceInfo *)
00349     RelinquishMagickMemory(windows->icon_resources);
00350   if (windows->icon_pixel != (XPixelInfo *) NULL)
00351     {
00352       if (windows->icon_pixel->pixels != (unsigned long *) NULL)
00353         windows->icon_pixel->pixels=(unsigned long *)
00354           RelinquishMagickMemory(windows->icon_pixel->pixels);
00355       if (windows->icon_pixel->annotate_context != (GC) NULL)
00356         XFreeGC(windows->display,windows->icon_pixel->annotate_context);
00357       windows->icon_pixel=(XPixelInfo *)
00358         RelinquishMagickMemory(windows->icon_pixel);
00359     }
00360   if (windows->pixel_info != (XPixelInfo *) NULL)
00361     {
00362       if (windows->pixel_info->pixels != (unsigned long *) NULL)
00363         windows->pixel_info->pixels=(unsigned long *)
00364           RelinquishMagickMemory(windows->pixel_info->pixels);
00365       if (windows->pixel_info->annotate_context != (GC) NULL)
00366         XFreeGC(windows->display,windows->pixel_info->annotate_context);
00367       if (windows->pixel_info->widget_context != (GC) NULL)
00368         XFreeGC(windows->display,windows->pixel_info->widget_context);
00369       if (windows->pixel_info->highlight_context != (GC) NULL)
00370         XFreeGC(windows->display,windows->pixel_info->highlight_context);
00371       windows->pixel_info=(XPixelInfo *)
00372         RelinquishMagickMemory(windows->pixel_info);
00373     }
00374   if (windows->font_info != (XFontStruct *) NULL)
00375     {
00376       XFreeFont(windows->display,windows->font_info);
00377       windows->font_info=(XFontStruct *) NULL;
00378     }
00379   if (windows->class_hints != (XClassHint *) NULL)
00380     {
00381       if (windows->class_hints->res_name != (char *) NULL)
00382         XFree(windows->class_hints->res_name);
00383       if (windows->class_hints->res_class != (char *) NULL)
00384         XFree(windows->class_hints->res_class);
00385       XFree(windows->class_hints);
00386       windows->class_hints=(XClassHint *) NULL;
00387     }
00388   if (windows->manager_hints != (XWMHints *) NULL)
00389     {
00390       XFree(windows->manager_hints);
00391       windows->manager_hints=(XWMHints *) NULL;
00392     }
00393   if (windows->map_info != (XStandardColormap *) NULL)
00394     {
00395       XFree(windows->map_info);
00396       windows->map_info=(XStandardColormap *) NULL;
00397     }
00398   if (windows->icon_map != (XStandardColormap *) NULL)
00399     {
00400       XFree(windows->icon_map);
00401       windows->icon_map=(XStandardColormap *) NULL;
00402     }
00403   if (windows->visual_info != (XVisualInfo *) NULL)
00404     {
00405       XFree(windows->visual_info);
00406       windows->visual_info=(XVisualInfo *) NULL;
00407     }
00408   if (windows->icon_visual != (XVisualInfo *) NULL)
00409     {
00410       XFree(windows->icon_visual);
00411       windows->icon_visual=(XVisualInfo *) NULL;
00412     }
00413   (void) XSetWindows((XWindows *) NULL);
00414 }
00415 
00416 /*
00417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00418 %                                                                             %
00419 %                                                                             %
00420 %                                                                             %
00421 %   X A n n o t a t e I m a g e                                               %
00422 %                                                                             %
00423 %                                                                             %
00424 %                                                                             %
00425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00426 %
00427 %  XAnnotateImage() annotates the image with text.
00428 %
00429 %  The format of the XAnnotateImage method is:
00430 %
00431 %      MagickBooleanType XAnnotateImage(Display *display,
00432 %        const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
00433 %
00434 %  A description of each parameter follows:
00435 %
00436 %    o display: Specifies a connection to an X server;  returned from
00437 %      XOpenDisplay.
00438 %
00439 %    o pixel: Specifies a pointer to a XPixelInfo structure.
00440 %
00441 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
00442 %
00443 %    o image: the image.
00444 %
00445 */
00446 MagickExport MagickBooleanType XAnnotateImage(Display *display,
00447   const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image)
00448 {
00449   GC
00450     annotate_context;
00451 
00452   ExceptionInfo
00453     *exception;
00454 
00455   Image
00456     *annotate_image;
00457 
00458   int
00459     x,
00460     y;
00461 
00462   MagickBooleanType
00463     matte;
00464 
00465   Pixmap
00466     annotate_pixmap;
00467 
00468   unsigned int
00469     depth,
00470     height,
00471     width;
00472 
00473   Window
00474     root_window;
00475 
00476   XGCValues
00477     context_values;
00478 
00479   XImage
00480     *annotate_ximage;
00481 
00482   /*
00483     Initialize annotated image.
00484   */
00485   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00486   assert(display != (Display *) NULL);
00487   assert(pixel != (XPixelInfo *) NULL);
00488   assert(annotate_info != (XAnnotateInfo *) NULL);
00489   assert(image != (Image *) NULL);
00490   /*
00491     Initialize annotated pixmap.
00492   */
00493   root_window=XRootWindow(display,XDefaultScreen(display));
00494   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
00495   annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
00496     annotate_info->height,depth);
00497   if (annotate_pixmap == (Pixmap) NULL)
00498     return(MagickFalse);
00499   /*
00500     Initialize graphics info.
00501   */
00502   context_values.background=0;
00503   context_values.foreground=(unsigned long) (~0);
00504   context_values.font=annotate_info->font_info->fid;
00505   annotate_context=XCreateGC(display,root_window,(unsigned long)
00506     GCBackground | GCFont | GCForeground,&context_values);
00507   if (annotate_context == (GC) NULL)
00508     return(MagickFalse);
00509   /*
00510     Draw text to pixmap.
00511   */
00512   (void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
00513     (int) annotate_info->font_info->ascent,annotate_info->text,
00514     (int) strlen(annotate_info->text));
00515   (void) XFreeGC(display,annotate_context);
00516   /*
00517     Initialize annotated X image.
00518   */
00519   annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
00520     annotate_info->height,AllPlanes,ZPixmap);
00521   if (annotate_ximage == (XImage *) NULL)
00522     return(MagickFalse);
00523   (void) XFreePixmap(display,annotate_pixmap);
00524   /*
00525     Initialize annotated image.
00526   */
00527   annotate_image=AcquireImage((ImageInfo *) NULL);
00528   if (annotate_image == (Image *) NULL)
00529     return(MagickFalse);
00530   annotate_image->columns=annotate_info->width;
00531   annotate_image->rows=annotate_info->height;
00532   /*
00533     Transfer annotated X image to image.
00534   */
00535   width=(unsigned int) image->columns;
00536   height=(unsigned int) image->rows;
00537   x=0;
00538   y=0;
00539   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
00540   (void) GetOneVirtualPixel(image,x,y,&annotate_image->background_color,
00541     &image->exception);
00542   if (annotate_info->stencil == ForegroundStencil)
00543     annotate_image->matte=MagickTrue;
00544   exception=(&image->exception);
00545   for (y=0; y < (int) annotate_image->rows; y++)
00546   {
00547     register long
00548       x;
00549 
00550     register PixelPacket
00551       *restrict q;
00552 
00553     q=GetAuthenticPixels(annotate_image,0,y,annotate_image->columns,1,
00554       exception);
00555     if (q == (PixelPacket *) NULL)
00556       break;
00557     for (x=0; x < (long) annotate_image->columns; x++)
00558     {
00559       SetOpacityPixelComponent(q,OpaqueOpacity);
00560       if (XGetPixel(annotate_ximage,x,y) == 0)
00561         {
00562           /*
00563             Set this pixel to the background color.
00564           */
00565           q->red=ScaleShortToQuantum(pixel->box_color.red);
00566           q->green=ScaleShortToQuantum(pixel->box_color.green);
00567           q->blue=ScaleShortToQuantum(pixel->box_color.blue);
00568           if ((annotate_info->stencil == ForegroundStencil) ||
00569               (annotate_info->stencil == OpaqueStencil))
00570             q->opacity=(Quantum) TransparentOpacity;
00571         }
00572       else
00573         {
00574           /*
00575             Set this pixel to the pen color.
00576           */
00577           q->red=ScaleShortToQuantum(pixel->pen_color.red);
00578           q->green=ScaleShortToQuantum(pixel->pen_color.green);
00579           q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
00580           if (annotate_info->stencil == BackgroundStencil)
00581             q->opacity=(Quantum) TransparentOpacity;
00582         }
00583       q++;
00584     }
00585     if (SyncAuthenticPixels(annotate_image,exception) == MagickFalse)
00586       break;
00587   }
00588   XDestroyImage(annotate_ximage);
00589   /*
00590     Determine annotate geometry.
00591   */
00592   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
00593   if ((width != (unsigned int) annotate_image->columns) ||
00594       (height != (unsigned int) annotate_image->rows))
00595     {
00596       char
00597         image_geometry[MaxTextExtent];
00598 
00599       /*
00600         Scale image.
00601       */
00602       (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
00603         width,height);
00604       (void) TransformImage(&annotate_image,(char *) NULL,image_geometry);
00605     }
00606   if (annotate_info->degrees != 0.0)
00607     {
00608       Image
00609         *rotate_image;
00610 
00611       int
00612         rotations;
00613 
00614       MagickRealType
00615         normalized_degrees;
00616 
00617       /*
00618         Rotate image.
00619       */
00620       rotate_image=
00621         RotateImage(annotate_image,annotate_info->degrees,&image->exception);
00622       if (rotate_image == (Image *) NULL)
00623         return(MagickFalse);
00624       annotate_image=DestroyImage(annotate_image);
00625       annotate_image=rotate_image;
00626       /*
00627         Annotation is relative to the degree of rotation.
00628       */
00629       normalized_degrees=annotate_info->degrees;
00630       while (normalized_degrees < -45.0)
00631         normalized_degrees+=360.0;
00632       for (rotations=0; normalized_degrees > 45.0; rotations++)
00633         normalized_degrees-=90.0;
00634       switch (rotations % 4)
00635       {
00636         default:
00637         case 0:
00638           break;
00639         case 1:
00640         {
00641           /*
00642             Rotate 90 degrees.
00643           */
00644           x-=(int) annotate_image->columns/2;
00645           y+=(int) annotate_image->columns/2;
00646           break;
00647         }
00648         case 2:
00649         {
00650           /*
00651             Rotate 180 degrees.
00652           */
00653           x=x-(int) annotate_image->columns;
00654           break;
00655         }
00656         case 3:
00657         {
00658           /*
00659             Rotate 270 degrees.
00660           */
00661           x=x-(int) annotate_image->columns/2;
00662           y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
00663           break;
00664         }
00665       }
00666     }
00667   /*
00668     Composite text onto the image.
00669   */
00670   (void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
00671   matte=image->matte;
00672   (void) CompositeImage(image,annotate_image->matte != MagickFalse ?
00673     OverCompositeOp : CopyCompositeOp,annotate_image,x,y);
00674   image->matte=matte;
00675   annotate_image=DestroyImage(annotate_image);
00676   return(MagickTrue);
00677 }
00678 
00679 /*
00680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00681 %                                                                             %
00682 %                                                                             %
00683 %                                                                             %
00684 %   X B e s t F o n t                                                         %
00685 %                                                                             %
00686 %                                                                             %
00687 %                                                                             %
00688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00689 %
00690 %  XBestFont() returns the "best" font.  "Best" is defined as a font specified
00691 %  in the X resource database or a font such that the text width displayed
00692 %  with the font does not exceed the specified maximum width.
00693 %
00694 %  The format of the XBestFont method is:
00695 %
00696 %      XFontStruct *XBestFont(Display *display,
00697 %        const XResourceInfo *resource_info,const MagickBooleanType text_font)
00698 %
00699 %  A description of each parameter follows:
00700 %
00701 %    o font: XBestFont returns a pointer to a XFontStruct structure.
00702 %
00703 %    o display: Specifies a connection to an X server;  returned from
00704 %      XOpenDisplay.
00705 %
00706 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
00707 %
00708 %    o text_font:  True is font should be mono-spaced (typewriter style).
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 static void XDitherImage(Image *image,XImage *ximage)
02112 {
02113   static const short int
02114     dither_red[2][16]=
02115     {
02116       {-16,  4, -1, 11,-14,  6, -3,  9,-15,  5, -2, 10,-13,  7, -4,  8},
02117       { 15, -5,  0,-12, 13, -7,  2,-10, 14, -6,  1,-11, 12, -8,  3, -9}
02118     },
02119     dither_green[2][16]=
02120     {
02121       { 11,-15,  7, -3,  8,-14,  4, -2, 10,-16,  6, -4,  9,-13,  5, -1},
02122       {-12, 14, -8,  2, -9, 13, -5,  1,-11, 15, -7,  3,-10, 12, -6,  0}
02123     },
02124     dither_blue[2][16]=
02125     {
02126       { -3,  9,-13,  7, -1, 11,-15,  5, -4,  8,-14,  6, -2, 10,-16,  4},
02127       {  2,-10, 12, -8,  0,-12, 14, -6,  3, -9, 13, -7,  1,-11, 15, -5}
02128     };
02129 
02130   PixelPacket
02131     color;
02132 
02133   int
02134     y;
02135 
02136   long
02137     value;
02138 
02139   register char
02140     *q;
02141 
02142   register const PixelPacket
02143     *p;
02144 
02145   register int
02146     i,
02147     j,
02148     x;
02149 
02150   unsigned int
02151     scanline_pad;
02152 
02153   register unsigned long
02154     pixel;
02155 
02156   unsigned char
02157     *blue_map[2][16],
02158     *green_map[2][16],
02159     *red_map[2][16];
02160 
02161   /*
02162     Allocate and initialize dither maps.
02163   */
02164   for (i=0; i < 2; i++)
02165     for (j=0; j < 16; j++)
02166     {
02167       red_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02168         sizeof(*red_map));
02169       green_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02170         sizeof(*green_map));
02171       blue_map[i][j]=(unsigned char *) AcquireQuantumMemory(256UL,
02172         sizeof(*blue_map));
02173       if ((red_map[i][j] == (unsigned char *) NULL) ||
02174           (green_map[i][j] == (unsigned char *) NULL) ||
02175           (blue_map[i][j] == (unsigned char *) NULL))
02176         {
02177           ThrowXWindowFatalException(ResourceLimitError,
02178             "MemoryAllocationFailed",image->filename);
02179           return;
02180         }
02181     }
02182   /*
02183     Initialize dither tables.
02184   */
02185   for (i=0; i < 2; i++)
02186     for (j=0; j < 16; j++)
02187       for (x=0; x < 256; x++)
02188       {
02189         value=x-16;
02190         if (x < 48)
02191           value=x/2+8;
02192         value+=dither_red[i][j];
02193         red_map[i][j][x]=(unsigned char)
02194           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02195         value=x-16;
02196         if (x < 48)
02197           value=x/2+8;
02198         value+=dither_green[i][j];
02199         green_map[i][j][x]=(unsigned char)
02200           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02201         value=x-32;
02202         if (x < 112)
02203           value=x/2+24;
02204         value+=((unsigned long) dither_blue[i][j] << 1);
02205         blue_map[i][j][x]=(unsigned char)
02206           ((value < 0) ? 0 : (value > 255) ? 255 : value);
02207       }
02208   /*
02209     Dither image.
02210   */
02211   scanline_pad=(unsigned int) (ximage->bytes_per_line-
02212     ((unsigned long) (ximage->width*ximage->bits_per_pixel) >> 3));
02213   i=0;
02214   j=0;
02215   q=ximage->data;
02216   for (y=0; y < (int) image->rows; y++)
02217   {
02218     p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
02219     if (p == (const PixelPacket *) NULL)
02220       break;
02221     for (x=0; x < (int) image->columns; x++)
02222     {
02223       color.red=ClampToQuantum((MagickRealType) (red_map[i][j][(int)
02224         ScaleQuantumToChar(GetRedPixelComponent(p))] << 8));
02225       color.green=ClampToQuantum((MagickRealType) (green_map[i][j][(int)
02226         ScaleQuantumToChar(GetGreenPixelComponent(p))] << 8));
02227       color.blue=ClampToQuantum((MagickRealType) (blue_map[i][j][(int)
02228         ScaleQuantumToChar(GetBluePixelComponent(p))] << 8));
02229       pixel=(unsigned long) (((unsigned long) color.red & 0xe0) |
02230         (((unsigned long) color.green & 0xe0) >> 3) |
02231         (((unsigned long) color.blue & 0xc0) >> 6));
02232       *q++=(char) pixel;
02233       p++;
02234       j++;
02235       if (j == 16)
02236         j=0;
02237     }
02238     q+=scanline_pad;
02239     i++;
02240     if (i == 2)
02241       i=0;
02242   }
02243   /*
02244     Free allocated memory.
02245   */
02246   for (i=0; i < 2; i++)
02247     for (j=0; j < 16; j++)
02248     {
02249       green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
02250       blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
02251       red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
02252     }
02253 }
02254 
02255 /*
02256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02257 %                                                                             %
02258 %                                                                             %
02259 %                                                                             %
02260 %   X D r a w I m a g e                                                       %
02261 %                                                                             %
02262 %                                                                             %
02263 %                                                                             %
02264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02265 %
02266 %  XDrawImage() draws a line on the image.
02267 %
02268 %  The format of the XDrawImage method is:
02269 %
02270 %    MagickBooleanType XDrawImage(display,pixel,draw_info,image)
02271 %
02272 %  A description of each parameter follows:
02273 %
02274 %    o display: Specifies a connection to an X server;  returned from
02275 %      XOpenDisplay.
02276 %
02277 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02278 %
02279 %    o draw_info: Specifies a pointer to a XDrawInfo structure.
02280 %
02281 %    o image: the image.
02282 %
02283 */
02284 MagickExport MagickBooleanType XDrawImage(Display *display,
02285   const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image)
02286 {
02287   ExceptionInfo
02288     *exception;
02289 
02290   GC
02291     draw_context;
02292 
02293   Image
02294     *draw_image;
02295 
02296   int
02297     x,
02298     y;
02299 
02300   MagickBooleanType
02301     matte;
02302 
02303   Pixmap
02304     draw_pixmap;
02305 
02306   unsigned int
02307     depth,
02308     height,
02309     width;
02310 
02311   Window
02312     root_window;
02313 
02314   XGCValues
02315     context_values;
02316 
02317   XImage
02318     *draw_ximage;
02319 
02320   /*
02321     Initialize drawd image.
02322   */
02323   assert(display != (Display *) NULL);
02324   assert(pixel != (XPixelInfo *) NULL);
02325   assert(draw_info != (XDrawInfo *) NULL);
02326   assert(image != (Image *) NULL);
02327   if (image->debug != MagickFalse)
02328     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02329   /*
02330     Initialize drawd pixmap.
02331   */
02332   root_window=XRootWindow(display,XDefaultScreen(display));
02333   depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
02334   draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
02335     draw_info->height,depth);
02336   if (draw_pixmap == (Pixmap) NULL)
02337     return(MagickFalse);
02338   /*
02339     Initialize graphics info.
02340   */
02341   context_values.background=(unsigned long) (~0);
02342   context_values.foreground=0;
02343   context_values.line_width=(int) draw_info->line_width;
02344   draw_context=XCreateGC(display,root_window,(unsigned long)
02345     (GCBackground | GCForeground | GCLineWidth),&context_values);
02346   if (draw_context == (GC) NULL)
02347     return(MagickFalse);
02348   /*
02349     Clear pixmap.
02350   */
02351   (void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
02352     draw_info->height);
02353   /*
02354     Draw line to pixmap.
02355   */
02356   (void) XSetBackground(display,draw_context,0);
02357   (void) XSetForeground(display,draw_context,(unsigned long) (~0));
02358   (void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
02359   (void) XSetStipple(display,draw_context,draw_info->stipple);
02360   switch (draw_info->element)
02361   {
02362     case PointElement:
02363     default:
02364     {
02365       (void) XDrawLines(display,draw_pixmap,draw_context,
02366         draw_info->coordinate_info,(int) draw_info->number_coordinates,
02367         CoordModeOrigin);
02368       break;
02369     }
02370     case LineElement:
02371     {
02372       (void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
02373         draw_info->line_info.y1,draw_info->line_info.x2,
02374         draw_info->line_info.y2);
02375       break;
02376     }
02377     case RectangleElement:
02378     {
02379       (void) XDrawRectangle(display,draw_pixmap,draw_context,
02380         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02381         (unsigned int) draw_info->rectangle_info.width,
02382         (unsigned int) draw_info->rectangle_info.height);
02383       break;
02384     }
02385     case FillRectangleElement:
02386     {
02387       (void) XFillRectangle(display,draw_pixmap,draw_context,
02388         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02389         (unsigned int) draw_info->rectangle_info.width,
02390         (unsigned int) draw_info->rectangle_info.height);
02391       break;
02392     }
02393     case CircleElement:
02394     case EllipseElement:
02395     {
02396       (void) XDrawArc(display,draw_pixmap,draw_context,
02397         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02398         (unsigned int) draw_info->rectangle_info.width,
02399         (unsigned int) draw_info->rectangle_info.height,0,360*64);
02400       break;
02401     }
02402     case FillCircleElement:
02403     case FillEllipseElement:
02404     {
02405       (void) XFillArc(display,draw_pixmap,draw_context,
02406         (int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
02407         (unsigned int) draw_info->rectangle_info.width,
02408         (unsigned int) draw_info->rectangle_info.height,0,360*64);
02409       break;
02410     }
02411     case PolygonElement:
02412     {
02413       XPoint
02414         *coordinate_info;
02415 
02416       coordinate_info=draw_info->coordinate_info;
02417       (void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
02418         (int) draw_info->number_coordinates,CoordModeOrigin);
02419       (void) XDrawLine(display,draw_pixmap,draw_context,
02420         coordinate_info[draw_info->number_coordinates-1].x,
02421         coordinate_info[draw_info->number_coordinates-1].y,
02422         coordinate_info[0].x,coordinate_info[0].y);
02423       break;
02424     }
02425     case FillPolygonElement:
02426     {
02427       (void) XFillPolygon(display,draw_pixmap,draw_context,
02428         draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
02429         CoordModeOrigin);
02430       break;
02431     }
02432   }
02433   (void) XFreeGC(display,draw_context);
02434   /*
02435     Initialize X image.
02436   */
02437   draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
02438     draw_info->height,AllPlanes,ZPixmap);
02439   if (draw_ximage == (XImage *) NULL)
02440     return(MagickFalse);
02441   (void) XFreePixmap(display,draw_pixmap);
02442   /*
02443     Initialize draw image.
02444   */
02445   draw_image=AcquireImage((ImageInfo *) NULL);
02446   if (draw_image == (Image *) NULL)
02447     return(MagickFalse);
02448   draw_image->columns=draw_info->width;
02449   draw_image->rows=draw_info->height;
02450   /*
02451     Transfer drawn X image to image.
02452   */
02453   width=(unsigned int) image->columns;
02454   height=(unsigned int) image->rows;
02455   x=0;
02456   y=0;
02457   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02458   (void) GetOneVirtualPixel(image,x,y,&draw_image->background_color,
02459     &image->exception);
02460   if (SetImageStorageClass(draw_image,DirectClass) == MagickFalse)
02461     return(MagickFalse);
02462   draw_image->matte=MagickTrue;
02463   exception=(&image->exception);
02464   for (y=0; y < (int) draw_image->rows; y++)
02465   {
02466     register long
02467       x;
02468 
02469     register PixelPacket
02470       *restrict q;
02471 
02472     q=QueueAuthenticPixels(draw_image,0,y,draw_image->columns,1,exception);
02473     if (q == (PixelPacket *) NULL)
02474       break;
02475     for (x=0; x < (long) draw_image->columns; x++)
02476     {
02477       if (XGetPixel(draw_ximage,x,y) == 0)
02478         {
02479           /*
02480             Set this pixel to the background color.
02481           */
02482           *q=draw_image->background_color;
02483           q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
02484             TransparentOpacity : OpaqueOpacity);
02485         }
02486       else
02487         {
02488           /*
02489             Set this pixel to the pen color.
02490           */
02491           q->red=ScaleShortToQuantum(pixel->pen_color.red);
02492           q->green=ScaleShortToQuantum(pixel->pen_color.green);
02493           q->blue=ScaleShortToQuantum(pixel->pen_color.blue);
02494           q->opacity=(Quantum) (draw_info->stencil == OpaqueStencil ?
02495             OpaqueOpacity : TransparentOpacity);
02496         }
02497       q++;
02498     }
02499     if (SyncAuthenticPixels(draw_image,exception) == MagickFalse)
02500       break;
02501   }
02502   XDestroyImage(draw_ximage);
02503   /*
02504     Determine draw geometry.
02505   */
02506   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02507   if ((width != (unsigned int) draw_image->columns) ||
02508       (height != (unsigned int) draw_image->rows))
02509     {
02510       char
02511         image_geometry[MaxTextExtent];
02512 
02513       /*
02514         Scale image.
02515       */
02516       (void) FormatMagickString(image_geometry,MaxTextExtent,"%ux%u",
02517         width,height);
02518       (void) TransformImage(&draw_image,(char *) NULL,image_geometry);
02519     }
02520   if (draw_info->degrees != 0.0)
02521     {
02522       Image
02523         *rotate_image;
02524 
02525       int
02526         rotations;
02527 
02528       MagickRealType
02529         normalized_degrees;
02530 
02531       /*
02532         Rotate image.
02533       */
02534       rotate_image=RotateImage(draw_image,draw_info->degrees,&image->exception);
02535       if (rotate_image == (Image *) NULL)
02536         return(MagickFalse);
02537       draw_image=DestroyImage(draw_image);
02538       draw_image=rotate_image;
02539       /*
02540         Annotation is relative to the degree of rotation.
02541       */
02542       normalized_degrees=draw_info->degrees;
02543       while (normalized_degrees < -45.0)
02544         normalized_degrees+=360.0;
02545       for (rotations=0; normalized_degrees > 45.0; rotations++)
02546         normalized_degrees-=90.0;
02547       switch (rotations % 4)
02548       {
02549         default:
02550         case 0:
02551           break;
02552         case 1:
02553         {
02554           /*
02555             Rotate 90 degrees.
02556           */
02557           x=x-(int) draw_image->columns/2;
02558           y=y+(int) draw_image->columns/2;
02559           break;
02560         }
02561         case 2:
02562         {
02563           /*
02564             Rotate 180 degrees.
02565           */
02566           x=x-(int) draw_image->columns;
02567           break;
02568         }
02569         case 3:
02570         {
02571           /*
02572             Rotate 270 degrees.
02573           */
02574           x=x-(int) draw_image->columns/2;
02575           y=y-(int) (draw_image->rows-(draw_image->columns/2));
02576           break;
02577         }
02578       }
02579     }
02580   /*
02581     Composite text onto the image.
02582   */
02583   for (y=0; y < (int) draw_image->rows; y++)
02584   {
02585     register long
02586       x;
02587 
02588     register PixelPacket
02589       *restrict q;
02590 
02591     q=GetAuthenticPixels(draw_image,0,y,draw_image->columns,1,exception);
02592     if (q == (PixelPacket *) NULL)
02593       break;
02594     for (x=0; x < (long) draw_image->columns; x++)
02595     {
02596       if (q->opacity != (Quantum) TransparentOpacity)
02597         SetOpacityPixelComponent(q,OpaqueOpacity);
02598       q++;
02599     }
02600     if (SyncAuthenticPixels(draw_image,exception) == MagickFalse)
02601       break;
02602   }
02603   (void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
02604   if (draw_info->stencil == TransparentStencil)
02605     (void) CompositeImage(image,CopyOpacityCompositeOp,draw_image,x,y);
02606   else
02607     {
02608       matte=image->matte;
02609       (void) CompositeImage(image,OverCompositeOp,draw_image,x,y);
02610       image->matte=matte;
02611     }
02612   draw_image=DestroyImage(draw_image);
02613   return(MagickTrue);
02614 }
02615 
02616 /*
02617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02618 %                                                                             %
02619 %                                                                             %
02620 %                                                                             %
02621 %   X E r r o r                                                               %
02622 %                                                                             %
02623 %                                                                             %
02624 %                                                                             %
02625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02626 %
02627 %  XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
02628 %  and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
02629 %  for XQueryColor.  It returns MagickFalse in those cases.  Otherwise it returns
02630 %  True.
02631 %
02632 %  The format of the XError function is:
02633 %
02634 %      XError(display,error)
02635 %
02636 %  A description of each parameter follows:
02637 %
02638 %    o display: Specifies a pointer to the Display structure;  returned from
02639 %      XOpenDisplay.
02640 %
02641 %    o error: Specifies the error event.
02642 %
02643 */
02644 
02645 #if defined(__cplusplus) || defined(c_plusplus)
02646 extern "C" {
02647 #endif
02648 
02649 MagickExport int XError(Display *display,XErrorEvent *error)
02650 {
02651   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02652   assert(display != (Display *) NULL);
02653   assert(error != (XErrorEvent *) NULL);
02654   xerror_alert=MagickTrue;
02655   switch (error->request_code)
02656   {
02657     case X_GetGeometry:
02658     {
02659       if ((int) error->error_code == BadDrawable)
02660         return(MagickFalse);
02661       break;
02662     }
02663     case X_GetWindowAttributes:
02664     case X_QueryTree:
02665     {
02666       if ((int) error->error_code == BadWindow)
02667         return(MagickFalse);
02668       break;
02669     }
02670     case X_QueryColors:
02671     {
02672       if ((int) error->error_code == BadValue)
02673         return(MagickFalse);
02674       break;
02675     }
02676   }
02677   return(MagickTrue);
02678 }
02679 
02680 #if defined(__cplusplus) || defined(c_plusplus)
02681 }
02682 #endif
02683 
02684 /*
02685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02686 %                                                                             %
02687 %                                                                             %
02688 %                                                                             %
02689 %   X F r e e R e s o u r c e s                                               %
02690 %                                                                             %
02691 %                                                                             %
02692 %                                                                             %
02693 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02694 %
02695 %  XFreeResources() frees X11 resources.
02696 %
02697 %  The format of the XFreeResources method is:
02698 %
02699 %      void XFreeResources(Display *display,XVisualInfo *visual_info,
02700 %        XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
02701 %        XResourceInfo *resource_info,XWindowInfo *window_info)
02702 %        resource_info,window_info)
02703 %
02704 %  A description of each parameter follows:
02705 %
02706 %    o display: Specifies a connection to an X server; returned from
02707 %      XOpenDisplay.
02708 %
02709 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02710 %      returned from XGetVisualInfo.
02711 %
02712 %    o map_info: If map_type is specified, this structure is initialized
02713 %      with info from the Standard Colormap.
02714 %
02715 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02716 %
02717 %    o font_info: Specifies a pointer to a XFontStruct structure.
02718 %
02719 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
02720 %
02721 %    o window_info: Specifies a pointer to a X11 XWindowInfo structure.
02722 %
02723 */
02724 MagickExport void XFreeResources(Display *display,XVisualInfo *visual_info,
02725   XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
02726   XResourceInfo *resource_info,XWindowInfo *window_info)
02727 {
02728   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02729   assert(display != (Display *) NULL);
02730   assert(resource_info != (XResourceInfo *) NULL);
02731   if (window_info != (XWindowInfo *) NULL)
02732     {
02733       /*
02734         Free X image.
02735       */
02736       if (window_info->ximage != (XImage *) NULL)
02737         XDestroyImage(window_info->ximage);
02738       if (window_info->id != (Window) NULL)
02739         {
02740           /*
02741             Free destroy window and free cursors.
02742           */
02743           if (window_info->id != XRootWindow(display,visual_info->screen))
02744             (void) XDestroyWindow(display,window_info->id);
02745           if (window_info->annotate_context != (GC) NULL)
02746             (void) XFreeGC(display,window_info->annotate_context);
02747           if (window_info->highlight_context != (GC) NULL)
02748             (void) XFreeGC(display,window_info->highlight_context);
02749           if (window_info->widget_context != (GC) NULL)
02750             (void) XFreeGC(display,window_info->widget_context);
02751           if (window_info->cursor != (Cursor) NULL)
02752             (void) XFreeCursor(display,window_info->cursor);
02753           window_info->cursor=(Cursor) NULL;
02754           if (window_info->busy_cursor != (Cursor) NULL)
02755             (void) XFreeCursor(display,window_info->busy_cursor);
02756           window_info->busy_cursor=(Cursor) NULL;
02757         }
02758     }
02759   /*
02760     Free font.
02761   */
02762   if (font_info != (XFontStruct *) NULL)
02763     (void) XFreeFont(display,font_info);
02764   if (map_info != (XStandardColormap *) NULL)
02765     {
02766       /*
02767         Free X Standard Colormap.
02768       */
02769       if (resource_info->map_type == (char *) NULL)
02770         (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
02771       (void) XFree((void *) map_info);
02772     }
02773   /*
02774     Free X visual info.
02775   */
02776   if (visual_info != (XVisualInfo *) NULL)
02777     (void) XFree((void *) visual_info);
02778   if (resource_info->close_server != MagickFalse)
02779     (void) XCloseDisplay(display);
02780 }
02781 
02782 /*
02783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02784 %                                                                             %
02785 %                                                                             %
02786 %                                                                             %
02787 %   X F r e e S t a n d a r d C o l o r m a p                                 %
02788 %                                                                             %
02789 %                                                                             %
02790 %                                                                             %
02791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02792 %
02793 %  XFreeStandardColormap() frees an X11 colormap.
02794 %
02795 %  The format of the XFreeStandardColormap method is:
02796 %
02797 %      void XFreeStandardColormap(Display *display,
02798 %        const XVisualInfo *visual_info,XStandardColormap *map_info,
02799 %        XPixelInfo *pixel)
02800 %
02801 %  A description of each parameter follows:
02802 %
02803 %    o display: Specifies a connection to an X server; returned from
02804 %      XOpenDisplay.
02805 %
02806 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02807 %      returned from XGetVisualInfo.
02808 %
02809 %    o map_info: If map_type is specified, this structure is initialized
02810 %      with info from the Standard Colormap.
02811 %
02812 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02813 %
02814 */
02815 MagickExport void XFreeStandardColormap(Display *display,
02816   const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
02817 {
02818   /*
02819     Free colormap.
02820   */
02821   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02822   assert(display != (Display *) NULL);
02823   assert(visual_info != (XVisualInfo *) NULL);
02824   assert(map_info != (XStandardColormap *) NULL);
02825   (void) XFlush(display);
02826   if (map_info->colormap != (Colormap) NULL)
02827     {
02828       if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
02829         (void) XFreeColormap(display,map_info->colormap);
02830       else
02831         if (pixel != (XPixelInfo *) NULL)
02832           if ((visual_info->klass != TrueColor) &&
02833               (visual_info->klass != DirectColor))
02834             (void) XFreeColors(display,map_info->colormap,pixel->pixels,
02835               (int) pixel->colors,0);
02836     }
02837   map_info->colormap=(Colormap) NULL;
02838   if (pixel != (XPixelInfo *) NULL)
02839     {
02840       if (pixel->pixels != (unsigned long *) NULL)
02841         pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
02842       pixel->pixels=(unsigned long *) NULL;
02843     }
02844 }
02845 
02846 /*
02847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02848 %                                                                             %
02849 %                                                                             %
02850 %                                                                             %
02851 %   X G e t A n n o t a t e I n f o                                           %
02852 %                                                                             %
02853 %                                                                             %
02854 %                                                                             %
02855 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02856 %
02857 %  XGetAnnotateInfo() initializes the AnnotateInfo structure.
02858 %
02859 %  The format of the XGetAnnotateInfo method is:
02860 %
02861 %      void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
02862 %
02863 %  A description of each parameter follows:
02864 %
02865 %    o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
02866 %
02867 */
02868 MagickExport void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
02869 {
02870   /*
02871     Initialize annotate structure.
02872   */
02873   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02874   assert(annotate_info != (XAnnotateInfo *) NULL);
02875   annotate_info->x=0;
02876   annotate_info->y=0;
02877   annotate_info->width=0;
02878   annotate_info->height=0;
02879   annotate_info->stencil=ForegroundStencil;
02880   annotate_info->degrees=0.0;
02881   annotate_info->font_info=(XFontStruct *) NULL;
02882   annotate_info->text=(char *) NULL;
02883   *annotate_info->geometry='\0';
02884   annotate_info->previous=(XAnnotateInfo *) NULL;
02885   annotate_info->next=(XAnnotateInfo *) NULL;
02886   (void) XSupportsLocale();
02887   (void) XSetLocaleModifiers("");
02888 }
02889 
02890 /*
02891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02892 %                                                                             %
02893 %                                                                             %
02894 %                                                                             %
02895 %   X G e t M a p I n f o                                                     %
02896 %                                                                             %
02897 %                                                                             %
02898 %                                                                             %
02899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02900 %
02901 %  XGetMapInfo() initializes the XStandardColormap structure.
02902 %
02903 %  The format of the XStandardColormap method is:
02904 %
02905 %      void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
02906 %        XStandardColormap *map_info)
02907 %
02908 %  A description of each parameter follows:
02909 %
02910 %    o colormap: Specifies the ID of the X server colormap.
02911 %
02912 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02913 %      returned from XGetVisualInfo.
02914 %
02915 %    o map_info: Specifies a pointer to a X11 XStandardColormap structure.
02916 %
02917 */
02918 MagickExport void XGetMapInfo(const XVisualInfo *visual_info,
02919   const Colormap colormap,XStandardColormap *map_info)
02920 {
02921   /*
02922     Initialize map info.
02923   */
02924   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
02925   assert(visual_info != (XVisualInfo *) NULL);
02926   assert(map_info != (XStandardColormap *) NULL);
02927   map_info->colormap=colormap;
02928   map_info->red_max=visual_info->red_mask;
02929   map_info->red_mult=(unsigned long) (map_info->red_max != 0 ? 1 : 0);
02930   if (map_info->red_max != 0)
02931     while ((map_info->red_max & 0x01) == 0)
02932     {
02933       map_info->red_max>>=1;
02934       map_info->red_mult<<=1;
02935     }
02936   map_info->green_max=visual_info->green_mask;
02937   map_info->green_mult=(unsigned long) (map_info->green_max != 0 ? 1 : 0);
02938   if (map_info->green_max != 0)
02939     while ((map_info->green_max & 0x01) == 0)
02940     {
02941       map_info->green_max>>=1;
02942       map_info->green_mult<<=1;
02943     }
02944   map_info->blue_max=visual_info->blue_mask;
02945   map_info->blue_mult=(unsigned long) (map_info->blue_max != 0 ? 1 : 0);
02946   if (map_info->blue_max != 0)
02947     while ((map_info->blue_max & 0x01) == 0)
02948     {
02949       map_info->blue_max>>=1;
02950       map_info->blue_mult<<=1;
02951     }
02952   map_info->base_pixel=0;
02953 }
02954 
02955 /*
02956 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02957 %                                                                             %
02958 %                                                                             %
02959 %                                                                             %
02960 %   X G e t P i x e l I n f o                                                 %
02961 %                                                                             %
02962 %                                                                             %
02963 %                                                                             %
02964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
02965 %
02966 %  XGetPixelPacket() initializes the PixelPacket structure.
02967 %
02968 %  The format of the XGetPixelPacket method is:
02969 %
02970 %      void XGetPixelPacket(Display *display,const XVisualInfo *visual_info,
02971 %        const XStandardColormap *map_info,const XResourceInfo *resource_info,
02972 %        Image *image,XPixelInfo *pixel)
02973 %        pixel)
02974 %
02975 %  A description of each parameter follows:
02976 %
02977 %    o display: Specifies a connection to an X server; returned from
02978 %      XOpenDisplay.
02979 %
02980 %    o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
02981 %      returned from XGetVisualInfo.
02982 %
02983 %    o map_info: If map_type is specified, this structure is initialized
02984 %      with info from the Standard Colormap.
02985 %
02986 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
02987 %
02988 %    o image: the image.
02989 %
02990 %    o pixel: Specifies a pointer to a XPixelInfo structure.
02991 %
02992 */
02993 MagickExport void XGetPixelPacket(Display *display,
02994   const XVisualInfo *visual_info,const XStandardColormap *map_info,
02995   const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
02996 {
02997   static const char
02998     *PenColors[MaxNumberPens]=
02999     {
03000       "#000000000000",  /* black */
03001       "#00000000ffff",  /* blue */
03002       "#0000ffffffff",  /* cyan */
03003       "#0000ffff0000",  /* green */
03004       "#bdbdbdbdbdbd",  /* gray */
03005       "#ffff00000000",  /* red */
03006       "#ffff0000ffff",  /* magenta */
03007       "#ffffffff0000",  /* yellow */
03008       "#ffffffffffff",  /* white */
03009       "#bdbdbdbdbdbd",  /* gray */
03010       "#bdbdbdbdbdbd"   /* gray */
03011     };
03012 
03013   Colormap
03014     colormap;
03015 
03016   register long
03017     i;
03018 
03019   Status
03020     status;
03021 
03022   unsigned int
03023     packets;
03024 
03025   /*
03026     Initialize pixel info.
03027   */
03028   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03029   assert(display != (Display *) NULL);
03030   assert(visual_info != (XVisualInfo *) NULL);
03031   assert(map_info != (XStandardColormap *) NULL);
03032   assert(resource_info != (XResourceInfo *) NULL);
03033   assert(pixel != (XPixelInfo *) NULL);
03034   pixel->colors=0;
03035   if (image != (Image *) NULL)
03036     if (image->storage_class == PseudoClass)
03037       pixel->colors=image->colors;
03038   packets=(unsigned int)
03039     MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
03040   if (pixel->pixels != (unsigned long *) NULL)
03041     pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
03042   pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
03043     sizeof(pixel->pixels));
03044   if (pixel->pixels == (unsigned long *) NULL)
03045     ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
03046       image->filename);
03047   /*
03048     Set foreground color.
03049   */
03050   colormap=map_info->colormap;
03051   (void) XParseColor(display,colormap,(char *) ForegroundColor,
03052     &pixel->foreground_color);
03053   status=XParseColor(display,colormap,resource_info->foreground_color,
03054     &pixel->foreground_color);
03055   if (status == False)
03056     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03057       resource_info->foreground_color);
03058   pixel->foreground_color.pixel=
03059     XStandardPixel(map_info,&pixel->foreground_color);
03060   pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
03061   /*
03062     Set background color.
03063   */
03064   (void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
03065   status=XParseColor(display,colormap,resource_info->background_color,
03066     &pixel->background_color);
03067   if (status == False)
03068     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03069       resource_info->background_color);
03070   pixel->background_color.pixel=
03071     XStandardPixel(map_info,&pixel->background_color);
03072   pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
03073   /*
03074     Set border color.
03075   */
03076   (void) XParseColor(display,colormap,(char *) BorderColor,
03077     &pixel->border_color);
03078   status=XParseColor(display,colormap,resource_info->border_color,
03079     &pixel->border_color);
03080   if (status == False)
03081     ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03082       resource_info->border_color);
03083   pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
03084   pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
03085   /*
03086     Set matte color.
03087   */
03088   pixel->matte_color=pixel->background_color;
03089   if (resource_info->matte_color != (char *) NULL)
03090     {
03091       /*
03092         Matte color is specified as a X resource or command line argument.
03093       */
03094       status=XParseColor(display,colormap,resource_info->matte_color,
03095         &pixel->matte_color);
03096       if (status == False)
03097         ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03098           resource_info->matte_color);
03099       pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
03100       pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
03101     }
03102   /*
03103     Set highlight color.
03104   */
03105   pixel->highlight_color.red=(unsigned short) ((
03106     pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
03107     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03108   pixel->highlight_color.green=(unsigned short) ((
03109     pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
03110     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03111   pixel->highlight_color.blue=(unsigned short) ((
03112     pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
03113     (ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
03114   pixel->highlight_color.pixel=
03115     XStandardPixel(map_info,&pixel->highlight_color);
03116   pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
03117   /*
03118     Set shadow color.
03119   */
03120   pixel->shadow_color.red=(unsigned short) (((MagickRealType)
03121     pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
03122   pixel->shadow_color.green=(unsigned short) (((MagickRealType)
03123     pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
03124   pixel->shadow_color.blue=(unsigned short) (((MagickRealType)
03125     pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
03126   pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
03127   pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
03128   /*
03129     Set depth color.
03130   */
03131   pixel->depth_color.red=(unsigned short) (((MagickRealType)
03132     pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
03133   pixel->depth_color.green=(unsigned short) (((MagickRealType)
03134     pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
03135   pixel->depth_color.blue=(unsigned short) (((MagickRealType)
03136     pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
03137   pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
03138   pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
03139   /*
03140     Set trough color.
03141   */
03142   pixel->trough_color.red=(unsigned short) (((MagickRealType)
03143     pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
03144   pixel->trough_color.green=(unsigned short) (((MagickRealType)
03145     pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
03146   pixel->trough_color.blue=(unsigned short) (((MagickRealType)
03147     pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
03148   pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
03149   pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
03150   /*
03151     Set pen color.
03152   */
03153   for (i=0; i < MaxNumberPens; i++)
03154   {
03155     (void) XParseColor(display,colormap,(char *) PenColors[i],
03156       &pixel->pen_colors[i]);
03157     status=XParseColor(display,colormap,resource_info->pen_colors[i],
03158       &pixel->pen_colors[i]);
03159     if (status == False)
03160       ThrowXWindowFatalException(XServerError,"ColorIsNotKnownToServer",
03161         resource_info->pen_colors[i]);
03162     pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
03163     pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
03164   }
03165   pixel->box_color=pixel->background_color;
03166   pixel->pen_color=pixel->foreground_color;
03167   pixel->box_index=0;
03168   pixel->pen_index=1;
03169   if (image != (Image *) NULL)
03170     {
03171       if ((resource_info->gamma_correct != MagickFalse) &&
03172           (image->gamma != 0.0))
03173         {
03174           GeometryInfo
03175             geometry_info;
03176 
03177           MagickStatusType
03178             flags;
03179 
03180           /*
03181             Initialize map relative to display and image gamma.
03182           */
03183           flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
03184           red_gamma=geometry_info.rho;
03185           green_gamma=geometry_info.sigma;
03186           if ((flags & SigmaValue) == 0)
03187             green_gamma=red_gamma;
03188           blue_gamma=geometry_info.xi;
03189           if ((flags & XiValue) == 0)
03190             blue_gamma=red_gamma;
03191           red_gamma*=image->gamma;
03192           green_gamma*=image->gamma;
03193           blue_gamma*=image->gamma;
03194         }
03195       if (image->storage_class == PseudoClass)
03196         {
03197           /*
03198             Initialize pixel array for images of type PseudoClass.
03199           */
03200           for (i=0; i < (long) image->colors; i++)
03201             pixel->pixels[i]=
03202               XGammaPixel(map_info,image->colormap+i);
03203           for (i=0; i < MaxNumberPens; i++)
03204             pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
03205           pixel->colors+=MaxNumberPens;
03206         }
03207     }
03208 }
03209 
03210 /*
03211 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03212 %                                                                             %
03213 %                                                                             %
03214 %                                                                             %
03215 %   X G e t R e s o u r c e C l a s s                                         %
03216 %                                                                             %
03217 %                                                                             %
03218 %                                                                             %
03219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03220 %
03221 %  XGetResourceClass() queries the X server for the specified resource name or
03222 %  class.  If the resource name or class is not defined in the database, the
03223 %  supplied default value is returned.
03224 %
03225 %  The format of the XGetResourceClass method is:
03226 %
03227 %      char *XGetResourceClass(XrmDatabase database,const char *client_name,
03228 %        const char *keyword,char *resource_default)
03229 %
03230 %  A description of each parameter follows:
03231 %
03232 %    o database: Specifies a resource database; returned from
03233 %      XrmGetStringDatabase.
03234 %
03235 %    o client_name:  Specifies the application name used to retrieve resource
03236 %      info from the X server database.
03237 %
03238 %    o keyword: Specifies the keyword of the value being retrieved.
03239 %
03240 %    o resource_default: Specifies the default value to return if the query
03241 %      fails to find the specified keyword/class.
03242 %
03243 */
03244 MagickExport char *XGetResourceClass(XrmDatabase database,
03245   const char *client_name,const char *keyword,char *resource_default)
03246 {
03247   char
03248     resource_class[MaxTextExtent],
03249     resource_name[MaxTextExtent];
03250 
03251   static char
03252     *resource_type;
03253 
03254   Status
03255     status;
03256 
03257   XrmValue
03258     resource_value;
03259 
03260   if (database == (XrmDatabase) NULL)
03261     return(resource_default);
03262   *resource_name='\0';
03263   *resource_class='\0';
03264   if (keyword != (char *) NULL)
03265     {
03266       int
03267         c,
03268         k;
03269 
03270       /*
03271         Initialize resource keyword and class.
03272       */
03273       (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",
03274         client_name,keyword);
03275       c=(int) (*client_name);
03276       if ((c >= XK_a) && (c <= XK_z))
03277         c-=(XK_a-XK_A);
03278       else
03279         if ((c >= XK_agrave) && (c <= XK_odiaeresis))
03280           c-=(XK_agrave-XK_Agrave);
03281         else
03282           if ((c >= XK_oslash) && (c <= XK_thorn))
03283             c-=(XK_oslash-XK_Ooblique);
03284       k=(int) (*keyword);
03285       if ((k >= XK_a) && (k <= XK_z))
03286         k-=(XK_a-XK_A);
03287       else
03288         if ((k >= XK_agrave) && (k <= XK_odiaeresis))
03289           k-=(XK_agrave-XK_Agrave);
03290         else
03291           if ((k >= XK_oslash) && (k <= XK_thorn))
03292             k-=(XK_oslash-XK_Ooblique);
03293       (void) FormatMagickString(resource_class,MaxTextExtent,"%c%s.%c%s",c,
03294         client_name+1,k,keyword+1);
03295     }
03296   status=XrmGetResource(database,resource_name,resource_class,&resource_type,
03297     &resource_value);
03298   if (status == False)
03299     return(resource_default);
03300   return(resource_value.addr);
03301 }
03302 
03303 /*
03304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03305 %                                                                             %
03306 %                                                                             %
03307 %                                                                             %
03308 %   X G e t R e s o u r c e D a t a b a s e                                   %
03309 %                                                                             %
03310 %                                                                             %
03311 %                                                                             %
03312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03313 %
03314 %  XGetResourceDatabase() creates a new resource database and initializes it.
03315 %
03316 %  The format of the XGetResourceDatabase method is:
03317 %
03318 %      XrmDatabase XGetResourceDatabase(Display *display,
03319 %        const char *client_name)
03320 %
03321 %  A description of each parameter follows:
03322 %
03323 %    o database: XGetResourceDatabase() returns the database after it is
03324 %      initialized.
03325 %
03326 %    o display: Specifies a connection to an X server;  returned from
03327 %      XOpenDisplay.
03328 %
03329 %    o client_name:  Specifies the application name used to retrieve resource
03330 %      info from the X server database.
03331 %
03332 */
03333 MagickExport XrmDatabase XGetResourceDatabase(Display *display,
03334   const char *client_name)
03335 {
03336   char
03337     filename[MaxTextExtent];
03338 
03339   int
03340     c;
03341 
03342   register const char
03343     *p;
03344 
03345   XrmDatabase
03346     resource_database,
03347     server_database;
03348 
03349   if (display == (Display *) NULL)
03350     return((XrmDatabase) NULL);
03351   assert(client_name != (char *) NULL);
03352   /*
03353     Initialize resource database.
03354   */
03355   XrmInitialize();
03356   (void) XGetDefault(display,(char *) client_name,"dummy");
03357   resource_database=XrmGetDatabase(display);
03358   /*
03359     Combine application database.
03360   */
03361   if (client_name != (char *) NULL)
03362     {
03363       /*
03364         Get basename of client.
03365       */
03366       p=client_name+(strlen(client_name)-1);
03367       while ((p > client_name) && (*p != '/'))
03368         p--;
03369       if (*p == '/')
03370         client_name=p+1;
03371     }
03372   c=(int) (*client_name);
03373   if ((c >= XK_a) && (c <= XK_z))
03374     c-=(XK_a-XK_A);
03375   else
03376     if ((c >= XK_agrave) && (c <= XK_odiaeresis))
03377       c-=(XK_agrave-XK_Agrave);
03378     else
03379       if ((c >= XK_oslash) && (c <= XK_thorn))
03380         c-=(XK_oslash-XK_Ooblique);
03381 #if defined(X11_APPLICATION_PATH)
03382   (void) FormatMagickString(filename,MaxTextExtent,"%s%c%s",
03383     X11_APPLICATION_PATH,c,client_name+1);
03384   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
03385 #endif
03386   if (XResourceManagerString(display) != (char *) NULL)
03387     {
03388       /*
03389         Combine server database.
03390       */
03391       server_database=XrmGetStringDatabase(XResourceManagerString(display));
03392       XrmCombineDatabase(server_database,&resource_database,MagickFalse);
03393     }
03394   /*
03395     Merge user preferences database.
03396   */
03397 #if defined(X11_PREFERENCES_PATH)
03398   (void) FormatMagickString(filename,MaxTextExtent,"%s%src",
03399     X11_PREFERENCES_PATH,client_name);
03400   ExpandFilename(filename);
03401   (void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
03402 #endif
03403   return(resource_database);
03404 }
03405 
03406 /*
03407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03408 %                                                                             %
03409 %                                                                             %
03410 %                                                                             %
03411 %   X G e t R e s o u r c e I n f o                                           %
03412 %                                                                             %
03413 %                                                                             %
03414 %                                                                             %
03415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03416 %
03417 %  XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
03418 %
03419 %  The format of the XGetResourceInfo method is:
03420 %
03421 %      void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
03422 %        const char *client_name,XResourceInfo *resource_info)
03423 %
03424 %  A description of each parameter follows:
03425 %
03426 %    o image_info: the image info.
03427 %
03428 %    o database: Specifies a resource database; returned from
03429 %      XrmGetStringDatabase.
03430 %
03431 %    o client_name:  Specifies the application name used to retrieve
03432 %      resource info from the X server database.
03433 %
03434 %    o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
03435 %
03436 */
03437 MagickExport void XGetResourceInfo(const ImageInfo *image_info,
03438   XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
03439 {
03440   char
03441     *cwd,
03442     *resource_value;
03443 
03444   /*
03445     Initialize resource info fields.
03446   */
03447   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
03448   assert(resource_info != (XResourceInfo *) NULL);
03449   (void) ResetMagickMemory(resource_info,0,sizeof(*resource_info));
03450   resource_info->resource_database=database;
03451   resource_info->image_info=(ImageInfo *) image_info;
03452   (void) SetImageInfoProgressMonitor(resource_info->image_info,
03453     XMagickProgressMonitor,(void *) NULL);
03454   resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
03455   resource_info->close_server=MagickTrue;
03456   resource_info->client_name=AcquireString(client_name);
03457   resource_value=XGetResourceClass(database,client_name,"backdrop",
03458     (char *) "False");
03459   resource_info->backdrop=IsMagickTrue(resource_value);
03460   resource_info->background_color=XGetResourceInstance(database,client_name,
03461     "background",(char *) "#d6d6d6d6d6d6");
03462   resource_info->border_color=XGetResourceInstance(database,client_name,
03463     "borderColor",BorderColor);
03464   resource_value=XGetResourceClass(database,client_name,"borderWidth",
03465     (char *) "2");
03466   resource_info->border_width=(unsigned int) StringToUnsignedLong(resource_value);
03467   resource_value=XGetResourceClass(database,client_name,"colormap",
03468     (char *) "shared");
03469   resource_info->colormap=UndefinedColormap;
03470   if (LocaleCompare("private",resource_value) == 0)
03471     resource_info->colormap=PrivateColormap;
03472   if (LocaleCompare("shared",resource_value) == 0)
03473     resource_info->colormap=SharedColormap;
03474   if (resource_info->colormap == UndefinedColormap)
03475     ThrowXWindowFatalException(OptionError,"UnrecognizedColormapType",
03476       resource_value);
03477   resource_value=XGetResourceClass(database,client_name,
03478     "colorRecovery",(char *) "False");
03479   resource_info->color_recovery=IsMagickTrue(resource_value);
03480   resource_value=XGetResourceClass(database,client_name,"confirmExit",
03481     (char *) "False");
03482   resource_info->confirm_exit=IsMagickTrue(resource_value);
03483   resource_value=XGetResourceClass(database,client_name,"confirmEdit",
03484     (char *) "False");
03485   resource_info->confirm_edit=IsMagickTrue(resource_value);
03486   resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
03487   resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
03488   resource_info->display_gamma=XGetResourceClass(database,client_name,
03489     "displayGamma",(char *) "2.2");
03490   resource_value=XGetResourceClass(database,client_name,"displayWarnings",
03491     (char *) "True");
03492   resource_info->display_warnings=IsMagickTrue(resource_value);
03493   resource_info->font=XGetResourceClass(database,client_name,"font",
03494     (char *) NULL);
03495   resource_info->font=XGetResourceClass(database,client_name,"fontList",
03496     resource_info->font);
03497   resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
03498     (char *) "fixed");
03499   resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
03500     (char *) "variable");
03501   resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
03502     (char *) "5x8");
03503   resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
03504     (char *) "6x10");
03505   resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
03506     (char *) "7x13bold");
03507   resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
03508     (char *) "8x13bold");
03509   resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
03510     (char *) "9x15bold");
03511   resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
03512     (char *) "10x20");
03513   resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
03514     (char *) "12x24");
03515   resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
03516     (char *) "fixed");
03517   resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
03518     (char *) "fixed");
03519   resource_info->foreground_color=XGetResourceInstance(database,client_name,
03520     "foreground",ForegroundColor);
03521   resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
03522     (char *) "True");
03523   resource_info->gamma_correct=IsMagickTrue(resource_value);
03524   resource_info->image_geometry=ConstantString(XGetResourceClass(database,
03525     client_name,"geometry",(char *) NULL));
03526   resource_value=XGetResourceClass(database,client_name,"gravity",
03527     (char *) "Center");
03528   resource_info->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
03529     MagickFalse,resource_value);
03530   cwd=getcwd(resource_info->home_directory,MaxTextExtent);
03531   resource_info->icon_geometry=XGetResourceClass(database,client_name,
03532     "iconGeometry",(char *) NULL);
03533   resource_value=XGetResourceClass(database,client_name,"iconic",
03534     (char *) "False");
03535   resource_info->iconic=IsMagickTrue(resource_value);
03536   resource_value=XGetResourceClass(database,client_name,"immutable",
03537     LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
03538     (char *) "False");
03539   resource_info->immutable=IsMagickTrue(resource_value);
03540   resource_value=XGetResourceClass(database,client_name,"magnify",
03541     (char *) "3");
03542   resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
03543   resource_info->map_type=XGetResourceClass(database,client_name,"map",
03544     (char *) NULL);
03545   resource_info->matte_color=XGetResourceInstance(database,client_name,
03546     "mattecolor",(char *) NULL);
03547   resource_info->name=ConstantString(XGetResourceClass(database,client_name,
03548     "name",(char *) NULL));
03549   resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
03550     (char *) "black");
03551   resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
03552     (char *) "blue");
03553   resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
03554     (char *) "cyan");
03555   resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
03556     (char *) "green");
03557   resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
03558     (char *) "gray");
03559   resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
03560     (char *) "red");
03561   resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
03562     (char *) "magenta");
03563   resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
03564     (char *) "yellow");
03565   resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
03566     (char *) "white");
03567   resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
03568     (char *) "gray");
03569   resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
03570     (char *) "gray");
03571   resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
03572   resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
03573   resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
03574   resource_info->quantum=StringToLong(resource_value);
03575   resource_info->text_font=XGetResourceClass(database,client_name,(char *)
03576     "font",(char *) "fixed");
03577   resource_info->text_font=XGetResourceClass(database,client_name,
03578     "textFontList",resource_info->text_font);
03579   resource_info->title=XGetResourceClass(database,client_name,"title",
03580     (char *) NULL);
03581   resource_value=XGetResourceClass(database,client_name,"undoCache",
03582     (char *) "16");
03583   resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
03584   resource_value=XGetResourceClass(database,client_name,"update",
03585     (char *) "False");
03586   resource_info->update=IsMagickTrue(resource_value);
03587   resource_value=XGetResourceClass(database,client_name,"usePixmap",
03588     (char *) "True");
03589   resource_info->use_pixmap=IsMagickTrue(resource_value);
03590   resource_value=XGetResourceClass(database,client_name,"sharedMemory",
03591     (char *) "True");
03592   resource_info->use_shared_memory=IsMagickTrue(resource_value);
03593   resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
03594     (char *) NULL);
03595   resource_info->window_group=XGetResourceClass(database,client_name,
03596     "windowGroup",(char *) NULL);
03597   resource_info->window_id=XGetResourceClass(database,client_name,"window",
03598     (char *) NULL);
03599   resource_info->write_filename=XGetResourceClass(database,client_name,
03600     "writeFilename",(char *) NULL);
03601 }
03602 
03603 /*
03604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03605 %                                                                             %
03606 %                                                                             %
03607 %                                                                             %
03608 %   X G e t R e s o u r c e I n s t a n c e                                   %
03609 %                                                                             %
03610 %                                                                             %
03611 %                                                                             %
03612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03613 %
03614 %  XGetResourceInstance() queries the X server for the specified resource name.
03615 %  If the resource name is not defined in the database, the supplied default
03616 %  value is returned.
03617 %
03618 %  The format of the XGetResourceInstance method is:
03619 %
03620 %      char *XGetResourceInstance(XrmDatabase database,const char *client_name,
03621 %        const char *keyword,const char *resource_default)
03622 %
03623 %  A description of each parameter follows:
03624 %
03625 %    o database: Specifies a resource database; returned from
03626 %      XrmGetStringDatabase.
03627 %
03628 %    o client_name:  Specifies the application name used to retrieve
03629 %      resource info from the X server database.
03630 %
03631 %    o keyword: Specifies the keyword of the value being retrieved.
03632 %
03633 %    o resource_default: Specifies the default value to return if the query
03634 %      fails to find the specified keyword/class.
03635 %
03636 */
03637 MagickExport char *XGetResourceInstance(XrmDatabase database,
03638   const char *client_name,const char *keyword,const char *resource_default)
03639 {
03640   char
03641     *resource_type,
03642     resource_name[MaxTextExtent];
03643 
03644   Status
03645     status;
03646 
03647   XrmValue
03648     resource_value;
03649 
03650   if (database == (XrmDatabase) NULL)
03651     return((char *) resource_default);
03652   *resource_name='\0';
03653   if (keyword != (char *) NULL)
03654     (void) FormatMagickString(resource_name,MaxTextExtent,"%s.%s",client_name,
03655       keyword);
03656   status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
03657     &resource_value);
03658   if (status == False)
03659     return((char *) resource_default);
03660   return(resource_value.addr);
03661 }
03662 
03663 /*
03664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03665 %                                                                             %
03666 %                                                                             %
03667 %                                                                             %
03668 %   X G e t S c r e e n D e n s i t y                                         %
03669 %                                                                             %
03670 %                                                                             %
03671 %                                                                             %
03672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03673 %
03674 %  XGetScreenDensity() returns the density of the X server screen in
03675 %  dots-per-inch.
03676 %
03677 %  The format of the XGetScreenDensity method is:
03678 %
03679 %      char *XGetScreenDensity(Display *display)
03680 %
03681 %  A description of each parameter follows:
03682 %
03683 %    o density: XGetScreenDensity() returns the density of the X screen in
03684 %      dots-per-inch.
03685 %
03686 %    o display: Specifies a connection to an X server;  returned from
03687 %      XOpenDisplay.
03688 %
03689 */
03690 MagickExport char *XGetScreenDensity(Display *display)
03691 {
03692   char
03693     density[MaxTextExtent];
03694 
03695   double
03696     x_density,
03697     y_density;
03698 
03699   /*
03700     Set density as determined by screen size.
03701   */
03702   x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
03703     ((double) DisplayWidthMM(display,XDefaultScreen(display))));
03704   y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
03705     ((double) DisplayHeightMM(display,XDefaultScreen(display))));
03706   (void) FormatMagickString(density,MaxTextExtent,"%gx%g",x_density,
03707     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 static Window XGetSubwindow(Display *display,Window window,int x,int y)
03747 {
03748   int
03749     x_offset,
03750     y_offset;
03751 
03752   Status
03753     status;
03754 
03755   Window
03756     source_window,
03757     target_window;
03758 
03759   assert(display != (Display *) NULL);
03760   source_window=XRootWindow(display,XDefaultScreen(display));
03761   if (window == (Window) NULL)
03762     return(source_window);
03763   target_window=window;
03764   for ( ; ; )
03765   {
03766     status=XTranslateCoordinates(display,source_window,window,x,y,
03767       &x_offset,&y_offset,&target_window);
03768     if (status != True)
03769       break;
03770     if (target_window == (Window) NULL)
03771       break;
03772     source_window=window;
03773     window=target_window;
03774     x=x_offset;
03775     y=y_offset;
03776   }
03777   if (target_window == (Window) NULL)
03778     target_window=window;
03779   return(target_window);
03780 }
03781 
03782 /*
03783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03784 %                                                                             %
03785 %                                                                             %
03786 %                                                                             %
03787 %   X G e t W i n d o w C o l o r                                             %
03788 %                                                                             %
03789 %                                                                             %
03790 %                                                                             %
03791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03792 %
03793 %  XGetWindowColor() returns the color of a pixel interactively chosen from the
03794 %  X server.
03795 %
03796 %  The format of the XGetWindowColor method is:
03797 %
03798 %      MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
03799 %        char *name)
03800 %
03801 %  A description of each parameter follows:
03802 %
03803 %    o display: Specifies a connection to an X server;  returned from
03804 %      XOpenDisplay.
03805 %
03806 %    o windows: Specifies a pointer to a XWindows structure.
03807 %
03808 %    o name: the name of the color if found in the X Color Database is
03809 %      returned in this character string.
03810 %
03811 */
03812 MagickExport MagickBooleanType XGetWindowColor(Display *display,
03813   XWindows *windows,char *name)
03814 {
03815   int
03816     x,
03817     y;
03818 
03819   PixelPacket
03820     pixel;
03821 
03822   RectangleInfo
03823     crop_info;
03824 
03825   Status
03826     status;
03827 
03828   Window
03829     child,
03830     client_window,
03831     root_window,
03832     target_window;
03833 
03834   XColor
03835     color;
03836 
03837   XImage
03838     *ximage;
03839 
03840   XWindowAttributes
03841     window_attributes;
03842 
03843   /*
03844     Choose a pixel from the X server.
03845   */
03846   assert(display != (Display *) NULL);
03847   assert(name != (char *) NULL);
03848   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
03849   *name='\0';
03850   target_window=XSelectWindow(display,&crop_info);
03851   if (target_window == (Window) NULL)
03852     return(MagickFalse);
03853   root_window=XRootWindow(display,XDefaultScreen(display));
03854   client_window=target_window;
03855   if (target_window != root_window)
03856     {
03857       unsigned int
03858         d;
03859 
03860       /*
03861         Get client window.
03862       */
03863       status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
03864       if (status != False)
03865         {
03866           client_window=XClientWindow(display,target_window);
03867           target_window=client_window;
03868         }
03869     }
03870   /*
03871     Verify window is viewable.
03872   */
03873   status=XGetWindowAttributes(display,target_window,&window_attributes);
03874   if ((status == False) || (window_attributes.map_state != IsViewable))
03875     return(MagickFalse);
03876   /*
03877     Get window X image.
03878   */
03879   (void) XTranslateCoordinates(display,root_window,target_window,
03880     (int) crop_info.x,(int) crop_info.y,&x,&y,&child);
03881   ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
03882   if (ximage == (XImage *) NULL)
03883     return(MagickFalse);
03884   color.pixel=XGetPixel(ximage,0,0);
03885   XDestroyImage(ximage);
03886   /*
03887     Match color against the color database.
03888   */
03889   (void) XQueryColor(display,window_attributes.colormap,&color);
03890   pixel.red=ScaleShortToQuantum(color.red);
03891   pixel.green=ScaleShortToQuantum(color.green);
03892   pixel.blue=ScaleShortToQuantum(color.blue);
03893   pixel.opacity=OpaqueOpacity;
03894   (void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
03895     &windows->image.image->exception);
03896   return(MagickTrue);
03897 }
03898 
03899 /*
03900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03901 %                                                                             %
03902 %                                                                             %
03903 %                                                                             %
03904 +   X G e t W i n d o w I m a g e                                             %
03905 %                                                                             %
03906 %                                                                             %
03907 %                                                                             %
03908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
03909 %
03910 %  XGetWindowImage() reads an image from the target X window and returns it.
03911 %  XGetWindowImage() optionally descends the window hierarchy and overlays the
03912 %  target image with each child image in an optimized fashion.  Any child
03913 %  window that have the same visual, colormap, and are contained by its parent
03914 %  are exempted.
03915 %
03916 %  The format of the XGetWindowImage method is:
03917 %
03918 %      Image *XGetWindowImage(Display *display,const Window window,
03919 %        const unsigned int borders,const unsigned int level)
03920 %
03921 %  A description of each parameter follows:
03922 %
03923 %    o display: Specifies a connection to an X server;  returned from
03924 %      XOpenDisplay.
03925 %
03926 %    o window: Specifies the window to obtain the image from.
03927 %
03928 %    o borders: Specifies whether borders pixels are to be saved with
03929 %      the image.
03930 %
03931 %    o level: Specifies an unsigned integer representing the level of
03932 %      decent in the window hierarchy.  This value must be zero or one on
03933 %      the initial call to XGetWindowImage.  A value of zero returns after
03934 %      one call.  A value of one causes the function to descend the window
03935 %      hierarchy and overlay the target image with each subwindow image.
03936 %
03937 */
03938 static Image *XGetWindowImage(Display *display,const Window window,
03939   const unsigned int borders,const unsigned int level)
03940 {
03941   typedef struct _ColormapInfo
03942   {
03943     Colormap
03944       colormap;
03945 
03946     XColor
03947       *colors;
03948 
03949     struct _ColormapInfo
03950       *next;
03951   } ColormapInfo;
03952 
03953   typedef struct _WindowInfo
03954   {
03955     Window
03956       window,
03957       parent;
03958 
03959     Visual
03960       *visual;
03961 
03962     Colormap
03963       colormap;
03964 
03965     XSegment
03966       bounds;
03967 
03968     RectangleInfo
03969       crop_info;
03970   } WindowInfo;
03971 
03972   IndexPacket
03973     index;
03974 
03975   int
03976     display_height,
03977     display_width,
03978     id,
03979     x_offset,
03980     y_offset;
03981 
03982   RectangleInfo
03983     crop_info;
03984 
03985   register IndexPacket
03986     *indexes;
03987 
03988   register int
03989     i;
03990 
03991   static ColormapInfo
03992     *colormap_info = (ColormapInfo *) NULL;
03993 
03994   static int
03995     max_windows = 0,
03996     number_windows = 0;
03997 
03998   static WindowInfo
03999     *window_info;
04000 
04001   Status
04002     status;
04003 
04004   Window
04005     child,
04006     root_window;
04007 
04008   XWindowAttributes
04009     window_attributes;
04010 
04011   /*
04012     Verify window is viewable.
04013   */
04014   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
04015   assert(display != (Display *) NULL);
04016   status=XGetWindowAttributes(display,window,&window_attributes);
04017   if ((status == False) || (window_attributes.map_state != IsViewable))
04018     return((Image *) NULL);
04019   /*
04020     Cropping rectangle is relative to root window.
04021   */
04022   root_window=XRootWindow(display,XDefaultScreen(display));
04023   (void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
04024     &y_offset,&child);
04025   crop_info.x=(long) x_offset;
04026   crop_info.y=(long) y_offset;
04027   crop_info.width=(unsigned long) window_attributes.width;
04028   crop_info.height=(unsigned long) window_attributes.height;
04029   if (borders != MagickFalse)
04030     {
04031       /*
04032         Include border in image.
04033       */
04034       crop_info.x-=(long) window_attributes.border_width;
04035       crop_info.y-=(long) window_attributes.border_width;
04036       crop_info.width+=(unsigned long) (window_attributes.border_width << 1);
04037       crop_info.height+=(unsigned long) (window_attributes.border_width << 1);
04038     }
04039   /*
04040     Crop to root window.
04041   */
04042   if (crop_info.x < 0)
04043     {
04044       crop_info.width+=crop_info.x;
04045       crop_info.x=0;
04046     }
04047   if (crop_info.y < 0)
04048     {
04049       crop_info.height+=crop_info.y;
04050       crop_info.y=0;
04051     }
04052   display_width=XDisplayWidth(display,XDefaultScreen(display));
04053   if ((int) (crop_info.x+crop_info.width) > display_width)
04054     crop_info.width=(unsigned long) (display_width-crop_info.x);
04055   display_height=XDisplayHeight(display,XDefaultScreen(display));
04056   if ((int) (crop_info.y+crop_info.height) > display_height)
04057     crop_info.height=(unsigned long) (display_height-crop_info.y);
04058   /*
04059     Initialize window info attributes.
04060   */
04061   if (number_windows >= max_windows)
04062     {
04063       /*
04064         Allocate or resize window info buffer.
04065       */
04066       max_windows+=1024;
04067       if (window_info == (WindowInfo *) NULL)
04068         window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
04069           sizeof(*window_info));
04070       else
04071         window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
04072           max_windows,sizeof(*window_info));
04073     }
04074   if (window_info == (WindowInfo *) NULL)
04075     {
04076       ThrowXWindowFatalException(ResourceLimitError,
04077         "MemoryAllocationFailed","...");
04078       return((Image *) NULL);
04079     }
04080   id=number_windows++;
04081   window_info[id].window=window;
04082   window_info[id].visual=window_attributes.visual;
04083   window_info[id].colormap=window_attributes.colormap;
04084   window_info[id].bounds.x1=(short) crop_info.x;
04085   window_info[id].bounds.y1=(short) crop_info.y;
04086   window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
04087   window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
04088   crop_info.x-=x_offset;
04089   crop_info.y-=y_offset;
04090   window_info[id].crop_info=crop_info;
04091   if (level != 0)
04092     {
04093       unsigned int
04094         number_children;
04095 
04096       Window
04097         *children;
04098 
04099       /*
04100         Descend the window hierarchy.
04101       */
04102       status=XQueryTree(display,window,&root_window,&window_info[id].parent,
04103         &children,&number_children);
04104       for (i=0; i < id; i++)
04105         if ((window_info[i].window == window_info[id].parent) &&
04106             (window_info[i].visual == window_info[id].visual) &&
04107             (window_info[i].colormap == window_info[id].colormap))
04108           {
04109             if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) ||
04110                 (window_info[id].bounds.x1 >= window_info[i].bounds.x2) ||
04111                 (window_info[id].bounds.y1 <= window_info[i].bounds.y1) ||
04112                 (window_info[id].bounds.y1 >= window_info[i].bounds.y2))
04113               {
04114                 /*
04115                   Eliminate windows not circumscribed by their parent.
04116                 */
04117                 number_windows--;
04118                 break;
04119               }
04120           }
04121       if ((status == True) && (number_children != 0))
04122         {
04123           for (i=0; i < (int) number_children; i++)
04124             (void) XGetWindowImage(display,children[i],MagickFalse,level+1);
04125           (void) XFree((void *) children);
04126         }
04127     }
04128   if (level <= 1)
04129     {
04130       ColormapInfo
04131         *next;
04132 
04133       ExceptionInfo
04134         *exception;
04135 
04136       Image
04137         *composite_image,
04138         *image;
04139 
04140       int
04141         y;
04142 
04143       MagickBooleanType
04144         import;
04145 
04146       register int
04147         j,
04148         x;
04149 
04150       register PixelPacket
04151         *restrict q;
04152 
04153       register unsigned long
04154         pixel;
04155 
04156       unsigned int
04157         number_colors;
04158 
04159       XColor
04160         *colors;
04161 
04162       XImage
04163         *ximage;
04164 
04165       /*
04166         Get X image for each window in the list.
04167       */
04168       image=NewImageList();
04169       for (id=0; id < number_windows; id++)
04170       {
04171         /*
04172           Does target window intersect top level window?
04173         */
04174         import=
04175           ((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
04176            (window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
04177            (window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
04178            (window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
04179           MagickTrue : MagickFalse;
04180         /*
04181           Is target window contained by another window with the same colormap?
04182         */
04183         for (j=0; j < id; j++)
04184           if ((window_info[id].visual == window_info[j].visual) &&
04185               (window_info[id].colormap == window_info[j].colormap))
04186             {
04187               if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) ||
04188                   (window_info[id].bounds.x1 >= window_info[j].bounds.x2) ||
04189                   (window_info[id].bounds.y1 <= window_info[j].bounds.y1) ||
04190                   (window_info[id].bounds.y1 >= window_info[j].bounds.y2))
04191                   import=MagickFalse;
04192             }
04193           else
04194             if ((window_info[id].visual != window_info[j].visual) ||
04195                 (window_info[id].colormap != window_info[j].colormap))
04196               {
04197                 if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) &&
04198                     (window_info[id].bounds.x1 < window_info[j].bounds.x2) &&
04199                     (window_info[id].bounds.y2 > window_info[j].bounds.y1) &&
04200                     (window_info[id].bounds.y1 < window_info[j].bounds.y2))
04201                   import=MagickTrue;
04202               }
04203         if (import == MagickFalse)
04204           continue;
04205         /*
04206           Get X image.
04207         */
04208         ximage=XGetImage(display,window_info[id].window,(int)
04209           window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
04210           (unsigned int) window_info[id].crop_info.width,(unsigned int)
04211           window_info[id].crop_info.height,AllPlanes,ZPixmap);
04212         if (ximage == (XImage *) NULL)
04213           continue;
04214         /*
04215           Initialize window colormap.
04216         */
04217         number_colors=0;
04218         colors=(XColor *) NULL;
04219         if (window_info[id].colormap != (Colormap) NULL)
04220           {
04221             ColormapInfo
04222               *p;
04223 
04224             /*
04225               Search colormap list for window colormap.
04226             */
04227             number_colors=(unsigned int) window_info[id].visual->map_entries;
04228             for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
04229               if (p->colormap == window_info[id].colormap)
04230                 break;
04231             if (p == (ColormapInfo *) NULL)
04232               {
04233                 /*
04234                   Get the window colormap.
04235                 */
04236                 colors=(XColor *) AcquireQuantumMemory(number_colors,
04237                   sizeof(*colors));
04238                 if (colors == (XColor *) NULL)
04239                   {
04240                     XDestroyImage(ximage);
04241                     return((Image *) NULL);
04242                   }
04243                 if ((window_info[id].visual->klass != DirectColor) &&
04244                     (window_info[id].visual->klass != TrueColor))
04245                   for (i=0; i < (int) number_colors; i++)
04246                   {
04247                     colors[i].pixel=(unsigned long) i;
04248                     colors[i].pad='\0';
04249                   }
04250                 else
04251                   {
04252                     unsigned long
04253                       blue,
04254                       blue_bit,
04255                       green,
04256                       green_bit,
04257                       red,
04258                       red_bit;
04259 
04260                     /*
04261                       DirectColor or TrueColor visual.
04262                     */
04263                     red=0;
04264                     green=0;
04265                     blue=0;
04266                     red_bit=window_info[id].visual->red_mask &
04267                       (~(window_info[id].visual->red_mask)+1);
04268                     green_bit=window_info[id].visual->green_mask &
04269                       (~(window_info[id].visual->green_mask)+1);
04270                     blue_bit=window_info[id].visual->blue_mask &
04271                       (~(window_info[id].visual->blue_mask)+1);
04272                     for (i=0; i < (int) number_colors; i++)
04273                     {
04274                       colors[i].pixel=red | green | blue;
04275                       colors[i].pad='\0';
04276                       red+=red_bit;
04277                       if (red > window_info[id].visual->red_mask)
04278                         red=0;
04279                       green+=green_bit;
04280                       if (green > window_info[id].visual->green_mask)
04281                         green=0;
04282                       blue+=blue_bit;
04283                       if (blue > window_info[id].visual->blue_mask)
04284                         blue=0;
04285                     }
04286                   }
04287                 (void) XQueryColors(display,window_info[id].colormap,colors,
04288                   (int) number_colors);
04289                 /*
04290                   Append colormap to colormap list.
04291                 */
04292                 p=(ColormapInfo *) AcquireAlignedMemory(1,sizeof(*p));
04293                 if (p == (ColormapInfo *) NULL)
04294                   return((Image *) NULL);
04295                 p->colormap=window_info[id].colormap;
04296                 p->colors=colors;
04297                 p->next=colormap_info;
04298                 colormap_info=p;
04299               }
04300             colors=p->colors;
04301           }
04302         /*
04303           Allocate image structure.
04304         */
04305         composite_image=AcquireImage((ImageInfo *) NULL);
04306         if (composite_image == (Image *) NULL)
04307           {
04308             XDestroyImage(ximage);
04309             return((Image *) NULL);
04310           }
04311         /*
04312           Convert X image to MIFF format.
04313         */
04314         if ((window_info[id].visual->klass != TrueColor) &&
04315             (window_info[id].visual->klass != DirectColor))
04316           composite_image->storage_class=PseudoClass;
04317         composite_image->columns=(unsigned long) ximage->width;
04318         composite_image->rows=(unsigned long) ximage->height;
04319         exception=(&composite_image->exception);
04320         switch (composite_image->storage_class)
04321         {
04322           case DirectClass:
04323           default:
04324           {
04325             register unsigned long
04326               color,
04327               index;
04328 
04329             unsigned long
04330               blue_mask,
04331               blue_shift,
04332               green_mask,
04333               green_shift,
04334               red_mask,
04335               red_shift;
04336 
04337             /*
04338               Determine shift and mask for red, green, and blue.
04339             */
04340             red_mask=window_info[id].visual->red_mask;
04341             red_shift=0;
04342             while ((red_mask != 0) && ((red_mask & 0x01) == 0))
04343             {
04344               red_mask>>=1;
04345               red_shift++;
04346             }
04347             green_mask=window_info[id].visual->green_mask;
04348             green_shift=0;
04349             while ((green_mask != 0) && ((green_mask & 0x01) == 0))
04350             {
04351               green_mask>>=1;
04352               green_shift++;
04353             }
04354             blue_mask=window_info[id].visual->blue_mask;
04355             blue_shift=0;
04356             while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
04357             {
04358               blue_mask>>=1;
04359               blue_shift++;
04360             }
04361             /*
04362               Convert X image to DirectClass packets.
04363             */
04364             if ((number_colors != 0) &&
04365                 (window_info[id].visual->klass == DirectColor))
04366               for (y=0; y < (int) composite_image->rows; y++)
04367               {
04368                 q=QueueAuthenticPixels(composite_image,0,y,
04369                   composite_image->columns,1,exception);
04370                 if (q == (PixelPacket *) NULL)
04371                   break;
04372                 for (x=0; x < (int) composite_image->columns; x++)
04373                 {
04374                   pixel=XGetPixel(ximage,x,y);
04375                   index=(pixel >> red_shift) & red_mask;
04376                   q->red=ScaleShortToQuantum(colors[index].red);
04377                   index=(pixel >> green_shift) & green_mask;
04378                   q->green=ScaleShortToQuantum(colors[index].green);
04379                   index=(pixel >> blue_shift) & blue_mask;
04380                   q->blue=ScaleShortToQuantum(colors[index].blue);
04381                   q++;
04382                 }
04383                 if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
04384                   break;
04385               }
04386             else
04387               for (y=0; y < (int) composite_image->rows; y++)
04388               {
04389                 q=QueueAuthenticPixels(composite_image,0,y,
04390                   composite_image->columns,1,exception);
04391                 if (q == (PixelPacket *) NULL)
04392                   break;
04393                 for (x=0; x < (int) composite_image->columns; x++)
04394                 {
04395                   pixel=XGetPixel(ximage,x,y);
04396                   color=(pixel >> red_shift) & red_mask;
04397                   color=(65535UL*color)/red_mask;
04398                   q->red=ScaleShortToQuantum((unsigned short) color);
04399                   color=(pixel >> green_shift) & green_mask;
04400                   color=(65535UL*color)/green_mask;
04401                   q->green=ScaleShortToQuantum((unsigned short) color);
04402                   color=(pixel >> blue_shift) & blue_mask;
04403                   color=(65535UL*color)/blue_mask;
04404                   q->blue=ScaleShortToQuantum((unsigned short) color);
04405                   q++;
04406                 }
04407                 if (SyncAuthenticPixels(composite_image,exception) == MagickFalse)
04408                   break;
04409               }
04410             break;
04411           }
04412           case PseudoClass:
04413           {
04414             /*
04415               Create colormap.
04416             */
04417             if (AcquireImageColormap(composite_image,number_colors) == MagickFalse)
04418               {
04419                 XDestroyImage(ximage);
04420                 composite_image=DestroyImage(composite_image);
04421                 return((Image *) NULL);
04422               }
04423             for (i=0; i < (int) composite_image->colors; i++)
04424             {
04425               composite_image->colormap[colors[i].pixel].red=
04426                 ScaleShortToQuantum(colors[i].red);
04427               composite_image->colormap[colors[i].pixel].green=
04428                 ScaleShortToQuantum(colors[i].green);
04429               composite_image->colormap[colors[i].pixel].blue=
04430                 ScaleShortToQuantum(colors[i].blue);
04431             }
04432             /*
04433               Convert X image to PseudoClass packets.
04434             */
04435             for (y=0; y < (int) composite_image->rows; y++)
04436             {
04437               q=QueueAuthenticPixels(composite_image,0,y,composite_image->columns,1,exception);
04438               if (q == (PixelPacket *) NULL)
04439                 break;
04440               indexes=GetAuthenticIndexQueue(composite_image);
04441               for (x=0; x < (int) composite_image->columns; x++)
04442               {