blob: 88c83dcc2a8d513f66dcfe9697b1d3d336f2fcaf [file] [log] [blame]
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X X W W IIIII N N DDDD OOO W W %
% X X W W I NN N D D O O W W %
% X W W I N N N D D O O W W %
% X X W W W I N NN D D O O W W W %
% X X W W IIIII N N DDDD OOO W W %
% %
% %
% MagickCore X11 Utility Methods %
% %
% Software Design %
% Cristy %
% July 1992 %
% %
% %
% Copyright 1999-2020 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
% https://imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
% See the License for the specific language governing permissions and %
% limitations under the License. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
/*
Include declarations.
*/
#include "MagickCore/studio.h"
#include "MagickCore/animate.h"
#include "MagickCore/artifact.h"
#include "MagickCore/blob.h"
#include "MagickCore/cache.h"
#include "MagickCore/client.h"
#include "MagickCore/color.h"
#include "MagickCore/color-private.h"
#include "MagickCore/colormap.h"
#include "MagickCore/composite.h"
#include "MagickCore/constitute.h"
#include "MagickCore/display.h"
#include "MagickCore/distort.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/geometry.h"
#include "MagickCore/identify.h"
#include "MagickCore/image.h"
#include "MagickCore/image-private.h"
#include "MagickCore/list.h"
#include "MagickCore/locale_.h"
#include "MagickCore/log.h"
#include "MagickCore/magick.h"
#include "MagickCore/memory_.h"
#include "MagickCore/memory-private.h"
#include "MagickCore/monitor.h"
#include "MagickCore/nt-base-private.h"
#include "MagickCore/option.h"
#include "MagickCore/pixel-accessor.h"
#include "MagickCore/quantize.h"
#include "MagickCore/quantum.h"
#include "MagickCore/quantum-private.h"
#include "MagickCore/resource_.h"
#include "MagickCore/resize.h"
#include "MagickCore/statistic.h"
#include "MagickCore/string_.h"
#include "MagickCore/string-private.h"
#include "MagickCore/transform.h"
#include "MagickCore/transform-private.h"
#include "MagickCore/token.h"
#include "MagickCore/utility.h"
#include "MagickCore/utility-private.h"
#include "MagickCore/widget.h"
#include "MagickCore/widget-private.h"
#include "MagickCore/xwindow.h"
#include "MagickCore/xwindow-private.h"
#include "MagickCore/version.h"
#if defined(__BEOS__)
#include <OS.h>
#endif
#if defined(MAGICKCORE_X11_DELEGATE)
#include <X11/Xproto.h>
#include <X11/Xlocale.h>
#if defined(MAGICK_HAVE_POLL)
# include <sys/poll.h>
#endif
#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
#if defined(MAGICKCORE_HAVE_MACHINE_PARAM_H)
# include <machine/param.h>
#endif
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
#endif
#if defined(MAGICKCORE_HAVE_SHAPE)
#include <X11/extensions/shape.h>
#endif
/*
X defines.
*/
#define XBlueGamma(color) ClampToQuantum(blue_gamma == 1.0 ? (double) \
(color) : ((pow(((double) QuantumScale*(color)),1.0/(double) blue_gamma)* \
QuantumRange)))
#define XGammaPacket(map,color) (size_t) (map->base_pixel+ \
((ScaleQuantumToShort(XRedGamma((color)->red))*map->red_max/65535L)* \
map->red_mult)+ \
((ScaleQuantumToShort(XGreenGamma((color)->green))*map->green_max/65535L)* \
map->green_mult)+ \
((ScaleQuantumToShort(XBlueGamma((color)->blue))*map->blue_max/65535L)* \
map->blue_mult))
#define XGammaPixel(image,map,color) (size_t) (map->base_pixel+ \
((ScaleQuantumToShort(XRedGamma(GetPixelRed(image,color)))*map->red_max/65535L)* \
map->red_mult)+ \
((ScaleQuantumToShort(XGreenGamma(GetPixelGreen(image,color)))*map->green_max/65535L)* \
map->green_mult)+ \
((ScaleQuantumToShort(XBlueGamma(GetPixelBlue(image,color)))*map->blue_max/65535L)* \
map->blue_mult))
#define XGreenGamma(color) ClampToQuantum(green_gamma == 1.0 ? (double) \
(color) : ((pow(((double) QuantumScale*(color)),1.0/(double) green_gamma)* \
QuantumRange)))
#define XRedGamma(color) ClampToQuantum(red_gamma == 1.0 ? (double) \
(color) : ((pow(((double) QuantumScale*(color)),1.0/(double) red_gamma)* \
QuantumRange)))
#define XStandardPixel(map,color) (size_t) (map->base_pixel+ \
(((color)->red*map->red_max/65535L)*map->red_mult)+ \
(((color)->green*map->green_max/65535L)*map->green_mult)+ \
(((color)->blue*map->blue_max/65535L)*map->blue_mult))
#define AccentuateModulate ScaleCharToQuantum(80)
#define HighlightModulate ScaleCharToQuantum(125)
#define ShadowModulate ScaleCharToQuantum(135)
#define DepthModulate ScaleCharToQuantum(185)
#define TroughModulate ScaleCharToQuantum(110)
#define XLIB_ILLEGAL_ACCESS 1
#undef ForgetGravity
#undef NorthWestGravity
#undef NorthGravity
#undef NorthEastGravity
#undef WestGravity
#undef CenterGravity
#undef EastGravity
#undef SouthWestGravity
#undef SouthGravity
#undef SouthEastGravity
#undef StaticGravity
#undef index
#if defined(hpux9)
#define XFD_SET int
#else
#define XFD_SET fd_set
#endif
/*
Enumeration declarations.
*/
typedef enum
{
#undef DoRed
DoRed = 0x0001,
#undef DoGreen
DoGreen = 0x0002,
#undef DoBlue
DoBlue = 0x0004,
DoMatte = 0x0008
} XColorFlags;
/*
Typedef declarations.
*/
typedef struct _DiversityPacket
{
Quantum
red,
green,
blue;
unsigned short
index;
size_t
count;
} DiversityPacket;
/*
Constant declaractions.
*/
static MagickBooleanType
xerror_alert = MagickFalse;
/*
Method prototypes.
*/
static const char
*XVisualClassName(const int);
static double
blue_gamma = 1.0,
green_gamma = 1.0,
red_gamma = 1.0;
static MagickBooleanType
XMakePixmap(Display *,const XResourceInfo *,XWindowInfo *);
static void
XMakeImageLSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
XImage *,XImage *,ExceptionInfo *),
XMakeImageMSBFirst(const XResourceInfo *,const XWindowInfo *,Image *,
XImage *,XImage *,ExceptionInfo *);
static Window
XSelectWindow(Display *,RectangleInfo *);
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% D e s t r o y X R e s o u r c e s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DestroyXResources() destroys any X resources.
%
% The format of the DestroyXResources method is:
%
% void DestroyXResources()
%
% A description of each parameter follows:
%
*/
MagickExport void DestroyXResources(void)
{
register int
i;
unsigned int
number_windows;
XWindowInfo
*magick_windows[MaxXWindows];
XWindows
*windows;
DestroyXWidget();
windows=XSetWindows((XWindows *) ~0);
if ((windows == (XWindows *) NULL) || (windows->display == (Display *) NULL))
return;
number_windows=0;
magick_windows[number_windows++]=(&windows->context);
magick_windows[number_windows++]=(&windows->group_leader);
magick_windows[number_windows++]=(&windows->backdrop);
magick_windows[number_windows++]=(&windows->icon);
magick_windows[number_windows++]=(&windows->image);
magick_windows[number_windows++]=(&windows->info);
magick_windows[number_windows++]=(&windows->magnify);
magick_windows[number_windows++]=(&windows->pan);
magick_windows[number_windows++]=(&windows->command);
magick_windows[number_windows++]=(&windows->widget);
magick_windows[number_windows++]=(&windows->popup);
for (i=0; i < (int) number_windows; i++)
{
if (magick_windows[i]->mapped != MagickFalse)
{
(void) XWithdrawWindow(windows->display,magick_windows[i]->id,
magick_windows[i]->screen);
magick_windows[i]->mapped=MagickFalse;
}
if (magick_windows[i]->name != (char *) NULL)
magick_windows[i]->name=(char *)
RelinquishMagickMemory(magick_windows[i]->name);
if (magick_windows[i]->icon_name != (char *) NULL)
magick_windows[i]->icon_name=(char *)
RelinquishMagickMemory(magick_windows[i]->icon_name);
if (magick_windows[i]->cursor != (Cursor) NULL)
{
(void) XFreeCursor(windows->display,magick_windows[i]->cursor);
magick_windows[i]->cursor=(Cursor) NULL;
}
if (magick_windows[i]->busy_cursor != (Cursor) NULL)
{
(void) XFreeCursor(windows->display,magick_windows[i]->busy_cursor);
magick_windows[i]->busy_cursor=(Cursor) NULL;
}
if (magick_windows[i]->highlight_stipple != (Pixmap) NULL)
{
(void) XFreePixmap(windows->display,
magick_windows[i]->highlight_stipple);
magick_windows[i]->highlight_stipple=(Pixmap) NULL;
}
if (magick_windows[i]->shadow_stipple != (Pixmap) NULL)
{
(void) XFreePixmap(windows->display,magick_windows[i]->shadow_stipple);
magick_windows[i]->shadow_stipple=(Pixmap) NULL;
}
if (magick_windows[i]->matte_image != (XImage *) NULL)
{
XDestroyImage(magick_windows[i]->matte_image);
magick_windows[i]->matte_image=(XImage *) NULL;
}
if (magick_windows[i]->ximage != (XImage *) NULL)
{
XDestroyImage(magick_windows[i]->ximage);
magick_windows[i]->ximage=(XImage *) NULL;
}
if (magick_windows[i]->pixmap != (Pixmap) NULL)
{
(void) XFreePixmap(windows->display,magick_windows[i]->pixmap);
magick_windows[i]->pixmap=(Pixmap) NULL;
}
if (magick_windows[i]->id != (Window) NULL)
{
(void) XDestroyWindow(windows->display,magick_windows[i]->id);
magick_windows[i]->id=(Window) NULL;
}
if (magick_windows[i]->destroy != MagickFalse)
{
if (magick_windows[i]->image != (Image *) NULL)
{
magick_windows[i]->image=DestroyImage(magick_windows[i]->image);
magick_windows[i]->image=NewImageList();
}
if (magick_windows[i]->matte_pixmap != (Pixmap) NULL)
{
(void) XFreePixmap(windows->display,
magick_windows[i]->matte_pixmap);
magick_windows[i]->matte_pixmap=(Pixmap) NULL;
}
}
if (magick_windows[i]->segment_info != (void *) NULL)
{
#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
XShmSegmentInfo
*segment_info;
segment_info=(XShmSegmentInfo *) magick_windows[i]->segment_info;
if (segment_info != (XShmSegmentInfo *) NULL)
if (segment_info[0].shmid >= 0)
{
if (segment_info[0].shmaddr != NULL)
(void) shmdt(segment_info[0].shmaddr);
(void) shmctl(segment_info[0].shmid,IPC_RMID,0);
segment_info[0].shmaddr=NULL;
segment_info[0].shmid=(-1);
}
#endif
magick_windows[i]->segment_info=(void *)
RelinquishMagickMemory(magick_windows[i]->segment_info);
}
}
windows->icon_resources=(XResourceInfo *)
RelinquishMagickMemory(windows->icon_resources);
if (windows->icon_pixel != (XPixelInfo *) NULL)
{
if (windows->icon_pixel->pixels != (unsigned long *) NULL)
windows->icon_pixel->pixels=(unsigned long *)
RelinquishMagickMemory(windows->icon_pixel->pixels);
if (windows->icon_pixel->annotate_context != (GC) NULL)
XFreeGC(windows->display,windows->icon_pixel->annotate_context);
windows->icon_pixel=(XPixelInfo *)
RelinquishMagickMemory(windows->icon_pixel);
}
if (windows->pixel_info != (XPixelInfo *) NULL)
{
if (windows->pixel_info->pixels != (unsigned long *) NULL)
windows->pixel_info->pixels=(unsigned long *)
RelinquishMagickMemory(windows->pixel_info->pixels);
if (windows->pixel_info->annotate_context != (GC) NULL)
XFreeGC(windows->display,windows->pixel_info->annotate_context);
if (windows->pixel_info->widget_context != (GC) NULL)
XFreeGC(windows->display,windows->pixel_info->widget_context);
if (windows->pixel_info->highlight_context != (GC) NULL)
XFreeGC(windows->display,windows->pixel_info->highlight_context);
windows->pixel_info=(XPixelInfo *)
RelinquishMagickMemory(windows->pixel_info);
}
if (windows->font_info != (XFontStruct *) NULL)
{
XFreeFont(windows->display,windows->font_info);
windows->font_info=(XFontStruct *) NULL;
}
if (windows->class_hints != (XClassHint *) NULL)
{
if (windows->class_hints->res_name != (char *) NULL)
windows->class_hints->res_name=DestroyString(
windows->class_hints->res_name);
if (windows->class_hints->res_class != (char *) NULL)
windows->class_hints->res_class=DestroyString(
windows->class_hints->res_class);
XFree(windows->class_hints);
windows->class_hints=(XClassHint *) NULL;
}
if (windows->manager_hints != (XWMHints *) NULL)
{
XFree(windows->manager_hints);
windows->manager_hints=(XWMHints *) NULL;
}
if (windows->map_info != (XStandardColormap *) NULL)
{
XFree(windows->map_info);
windows->map_info=(XStandardColormap *) NULL;
}
if (windows->icon_map != (XStandardColormap *) NULL)
{
XFree(windows->icon_map);
windows->icon_map=(XStandardColormap *) NULL;
}
if (windows->visual_info != (XVisualInfo *) NULL)
{
XFree(windows->visual_info);
windows->visual_info=(XVisualInfo *) NULL;
}
if (windows->icon_visual != (XVisualInfo *) NULL)
{
XFree(windows->icon_visual);
windows->icon_visual=(XVisualInfo *) NULL;
}
(void) XSetWindows((XWindows *) NULL);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X A n n o t a t e I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XAnnotateImage() annotates the image with text.
%
% The format of the XAnnotateImage method is:
%
% MagickBooleanType XAnnotateImage(Display *display,
% const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o pixel: Specifies a pointer to a XPixelInfo structure.
%
% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
%
% o image: the image.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickPrivate MagickBooleanType XAnnotateImage(Display *display,
const XPixelInfo *pixel,XAnnotateInfo *annotate_info,Image *image,
ExceptionInfo *exception)
{
CacheView
*annotate_view;
GC
annotate_context;
Image
*annotate_image;
int
x,
y;
PixelTrait
alpha_trait;
Pixmap
annotate_pixmap;
unsigned int
depth,
height,
width;
Window
root_window;
XGCValues
context_values;
XImage
*annotate_ximage;
/*
Initialize annotated image.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(pixel != (XPixelInfo *) NULL);
assert(annotate_info != (XAnnotateInfo *) NULL);
assert(image != (Image *) NULL);
/*
Initialize annotated pixmap.
*/
root_window=XRootWindow(display,XDefaultScreen(display));
depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
annotate_pixmap=XCreatePixmap(display,root_window,annotate_info->width,
annotate_info->height,depth);
if (annotate_pixmap == (Pixmap) NULL)
return(MagickFalse);
/*
Initialize graphics info.
*/
context_values.background=0;
context_values.foreground=(size_t) (~0);
context_values.font=annotate_info->font_info->fid;
annotate_context=XCreateGC(display,root_window,(unsigned long)
(GCBackground | GCFont | GCForeground),&context_values);
if (annotate_context == (GC) NULL)
return(MagickFalse);
/*
Draw text to pixmap.
*/
(void) XDrawImageString(display,annotate_pixmap,annotate_context,0,
(int) annotate_info->font_info->ascent,annotate_info->text,
(int) strlen(annotate_info->text));
(void) XFreeGC(display,annotate_context);
/*
Initialize annotated X image.
*/
annotate_ximage=XGetImage(display,annotate_pixmap,0,0,annotate_info->width,
annotate_info->height,AllPlanes,ZPixmap);
if (annotate_ximage == (XImage *) NULL)
return(MagickFalse);
(void) XFreePixmap(display,annotate_pixmap);
/*
Initialize annotated image.
*/
annotate_image=AcquireImage((ImageInfo *) NULL,exception);
if (annotate_image == (Image *) NULL)
return(MagickFalse);
annotate_image->columns=annotate_info->width;
annotate_image->rows=annotate_info->height;
/*
Transfer annotated X image to image.
*/
width=(unsigned int) image->columns;
height=(unsigned int) image->rows;
x=0;
y=0;
(void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
(void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
(ssize_t) y,&annotate_image->background_color,exception);
if (annotate_info->stencil == ForegroundStencil)
annotate_image->alpha_trait=BlendPixelTrait;
annotate_view=AcquireAuthenticCacheView(annotate_image,exception);
for (y=0; y < (int) annotate_image->rows; y++)
{
register int
x;
register Quantum
*magick_restrict q;
q=GetCacheViewAuthenticPixels(annotate_view,0,(ssize_t) y,
annotate_image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
for (x=0; x < (int) annotate_image->columns; x++)
{
SetPixelAlpha(annotate_image,OpaqueAlpha,q);
if (XGetPixel(annotate_ximage,x,y) == 0)
{
/*
Set this pixel to the background color.
*/
SetPixelRed(annotate_image,ScaleShortToQuantum(
pixel->box_color.red),q);
SetPixelGreen(annotate_image,ScaleShortToQuantum(
pixel->box_color.green),q);
SetPixelBlue(annotate_image,ScaleShortToQuantum(
pixel->box_color.blue),q);
if ((annotate_info->stencil == ForegroundStencil) ||
(annotate_info->stencil == OpaqueStencil))
SetPixelAlpha(annotate_image,TransparentAlpha,q);
}
else
{
/*
Set this pixel to the pen color.
*/
SetPixelRed(annotate_image,ScaleShortToQuantum(
pixel->pen_color.red),q);
SetPixelGreen(annotate_image,ScaleShortToQuantum(
pixel->pen_color.green),q);
SetPixelBlue(annotate_image,ScaleShortToQuantum(
pixel->pen_color.blue),q);
if (annotate_info->stencil == BackgroundStencil)
SetPixelAlpha(annotate_image,TransparentAlpha,q);
}
q+=GetPixelChannels(annotate_image);
}
if (SyncCacheViewAuthenticPixels(annotate_view,exception) == MagickFalse)
break;
}
annotate_view=DestroyCacheView(annotate_view);
XDestroyImage(annotate_ximage);
/*
Determine annotate geometry.
*/
(void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
if ((width != (unsigned int) annotate_image->columns) ||
(height != (unsigned int) annotate_image->rows))
{
char
image_geometry[MagickPathExtent];
/*
Scale image.
*/
(void) FormatLocaleString(image_geometry,MagickPathExtent,"%ux%u",
width,height);
(void) TransformImage(&annotate_image,(char *) NULL,image_geometry,
exception);
}
if (annotate_info->degrees != 0.0)
{
Image
*rotate_image;
int
rotations;
double
normalized_degrees;
/*
Rotate image.
*/
rotate_image=RotateImage(annotate_image,annotate_info->degrees,exception);
if (rotate_image == (Image *) NULL)
return(MagickFalse);
annotate_image=DestroyImage(annotate_image);
annotate_image=rotate_image;
/*
Annotation is relative to the degree of rotation.
*/
normalized_degrees=annotate_info->degrees;
while (normalized_degrees < -45.0)
normalized_degrees+=360.0;
for (rotations=0; normalized_degrees > 45.0; rotations++)
normalized_degrees-=90.0;
switch (rotations % 4)
{
default:
case 0:
break;
case 1:
{
/*
Rotate 90 degrees.
*/
x-=(int) annotate_image->columns/2;
y+=(int) annotate_image->columns/2;
break;
}
case 2:
{
/*
Rotate 180 degrees.
*/
x=x-(int) annotate_image->columns;
break;
}
case 3:
{
/*
Rotate 270 degrees.
*/
x=x-(int) annotate_image->columns/2;
y=y-(int) (annotate_image->rows-(annotate_image->columns/2));
break;
}
}
}
/*
Composite text onto the image.
*/
(void) XParseGeometry(annotate_info->geometry,&x,&y,&width,&height);
alpha_trait=image->alpha_trait;
(void) CompositeImage(image,annotate_image,
annotate_image->alpha_trait != UndefinedPixelTrait ? OverCompositeOp :
CopyCompositeOp,MagickTrue,(ssize_t) x,(ssize_t) y,exception);
image->alpha_trait=alpha_trait;
annotate_image=DestroyImage(annotate_image);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X B e s t F o n t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XBestFont() returns the "best" font. "Best" is defined as a font specified
% in the X resource database or a font such that the text width displayed
% with the font does not exceed the specified maximum width.
%
% The format of the XBestFont method is:
%
% XFontStruct *XBestFont(Display *display,
% const XResourceInfo *resource_info,const MagickBooleanType text_font)
%
% A description of each parameter follows:
%
% o font: XBestFont returns a pointer to a XFontStruct structure.
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
% o text_font: True is font should be mono-spaced (typewriter style).
%
*/
static char **FontToList(char *font)
{
char
**fontlist;
register char
*p,
*q;
register int
i;
unsigned int
fonts;
if (font == (char *) NULL)
return((char **) NULL);
/*
Convert string to an ASCII list.
*/
fonts=1U;
for (p=font; *p != '\0'; p++)
if ((*p == ':') || (*p == ';') || (*p == ','))
fonts++;
fontlist=(char **) AcquireQuantumMemory((size_t) fonts+1UL,sizeof(*fontlist));
if (fontlist == (char **) NULL)
{
ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",font);
return((char **) NULL);
}
p=font;
for (i=0; i < (int) fonts; i++)
{
for (q=p; *q != '\0'; q++)
if ((*q == ':') || (*q == ';') || (*q == ','))
break;
fontlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+1UL,
sizeof(*fontlist[i]));
if (fontlist[i] == (char *) NULL)
{
ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",font);
return((char **) NULL);
}
(void) CopyMagickString(fontlist[i],p,(size_t) (q-p+1));
p=q+1;
}
fontlist[i]=(char *) NULL;
return(fontlist);
}
MagickPrivate XFontStruct *XBestFont(Display *display,
const XResourceInfo *resource_info,const MagickBooleanType text_font)
{
static const char
*Fonts[]=
{
"-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-1",
"-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-1",
"-*-helvetica-medium-r-normal--12-*-*-*-*-*-iso8859-15",
"-*-arial-medium-r-normal--12-*-*-*-*-*-iso8859-15",
"-*-helvetica-medium-r-normal--12-*-*-*-*-*-*-*",
"-*-arial-medium-r-normal--12-*-*-*-*-*-*-*",
"variable",
"fixed",
(char *) NULL
},
*TextFonts[]=
{
"-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1",
"-*-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-15",
"-*-fixed-medium-r-normal-*-12-*-*-*-*-*-*-*",
"fixed",
(char *) NULL
};
char
*font_name;
register const char
**p;
XFontStruct
*font_info;
font_info=(XFontStruct *) NULL;
font_name=resource_info->font;
if (text_font != MagickFalse)
font_name=resource_info->text_font;
if ((font_name != (char *) NULL) && (*font_name != '\0'))
{
char
**fontlist;
register int
i;
/*
Load preferred font specified in the X resource database.
*/
fontlist=FontToList(font_name);
if (fontlist != (char **) NULL)
{
for (i=0; fontlist[i] != (char *) NULL; i++)
{
if (font_info == (XFontStruct *) NULL)
font_info=XLoadQueryFont(display,fontlist[i]);
fontlist[i]=DestroyString(fontlist[i]);
}
fontlist=(char **) RelinquishMagickMemory(fontlist);
}
if (font_info == (XFontStruct *) NULL)
ThrowXWindowException(XServerError,"UnableToLoadFont",font_name);
}
/*
Load fonts from list of fonts until one is found.
*/
p=Fonts;
if (text_font != MagickFalse)
p=TextFonts;
if (XDisplayHeight(display,XDefaultScreen(display)) >= 748)
p++;
while (*p != (char *) NULL)
{
if (font_info != (XFontStruct *) NULL)
break;
font_info=XLoadQueryFont(display,(char *) *p);
p++;
}
return(font_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X B e s t I c o n S i z e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XBestIconSize() returns the "best" icon size. "Best" is defined as an icon
% size that maintains the aspect ratio of the image. If the window manager
% has preferred icon sizes, one of the preferred sizes is used.
%
% The format of the XBestIconSize method is:
%
% void XBestIconSize(Display *display,XWindowInfo *window,Image *image)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o image: the image.
%
*/
MagickPrivate void XBestIconSize(Display *display,XWindowInfo *window,
Image *image)
{
int
i,
number_sizes;
double
scale_factor;
unsigned int
height,
icon_height,
icon_width,
width;
Window
root_window;
XIconSize
*icon_size,
*size_list;
/*
Determine if the window manager has specified preferred icon sizes.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(window != (XWindowInfo *) NULL);
assert(image != (Image *) NULL);
window->width=MaxIconSize;
window->height=MaxIconSize;
icon_size=(XIconSize *) NULL;
number_sizes=0;
root_window=XRootWindow(display,window->screen);
if (XGetIconSizes(display,root_window,&size_list,&number_sizes) != 0)
if ((number_sizes > 0) && (size_list != (XIconSize *) NULL))
icon_size=size_list;
if (icon_size == (XIconSize *) NULL)
{
/*
Window manager does not restrict icon size.
*/
icon_size=XAllocIconSize();
if (icon_size == (XIconSize *) NULL)
{
ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
return;
}
icon_size->min_width=1;
icon_size->max_width=MaxIconSize;
icon_size->min_height=1;
icon_size->max_height=MaxIconSize;
icon_size->width_inc=1;
icon_size->height_inc=1;
}
/*
Determine aspect ratio of image.
*/
width=(unsigned int) image->columns;
height=(unsigned int) image->rows;
i=0;
if (window->crop_geometry)
(void) XParseGeometry(window->crop_geometry,&i,&i,&width,&height);
/*
Look for an icon size that maintains the aspect ratio of image.
*/
scale_factor=(double) icon_size->max_width/width;
if (scale_factor > ((double) icon_size->max_height/height))
scale_factor=(double) icon_size->max_height/height;
icon_width=(unsigned int) icon_size->min_width;
while ((int) icon_width < icon_size->max_width)
{
if (icon_width >= (unsigned int) (scale_factor*width+0.5))
break;
icon_width+=icon_size->width_inc;
}
icon_height=(unsigned int) icon_size->min_height;
while ((int) icon_height < icon_size->max_height)
{
if (icon_height >= (unsigned int) (scale_factor*height+0.5))
break;
icon_height+=icon_size->height_inc;
}
(void) XFree((void *) icon_size);
window->width=icon_width;
window->height=icon_height;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X B e s t P i x e l %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XBestPixel() returns a pixel from an array of pixels that is closest to the
% requested color. If the color array is NULL, the colors are obtained from
% the X server.
%
% The format of the XBestPixel method is:
%
% void XBestPixel(Display *display,const Colormap colormap,XColor *colors,
% unsigned int number_colors,XColor *color)
%
% A description of each parameter follows:
%
% o pixel: XBestPixel returns the pixel value closest to the requested
% color.
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o colormap: Specifies the ID of the X server colormap.
%
% o colors: Specifies an array of XColor structures.
%
% o number_colors: Specifies the number of XColor structures in the
% color definition array.
%
% o color: Specifies the desired RGB value to find in the colors array.
%
*/
MagickPrivate void XBestPixel(Display *display,const Colormap colormap,
XColor *colors,unsigned int number_colors,XColor *color)
{
MagickBooleanType
query_server;
PixelInfo
pixel;
double
min_distance;
register double
distance;
register int
i,
j;
Status
status;
/*
Find closest representation for the requested RGB color.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(color != (XColor *) NULL);
status=XAllocColor(display,colormap,color);
if (status != False)
return;
query_server=colors == (XColor *) NULL ? MagickTrue : MagickFalse;
if (query_server != MagickFalse)
{
/*
Read X server colormap.
*/
colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
if (colors == (XColor *) NULL)
{
ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
"...");
return;
}
for (i=0; i < (int) number_colors; i++)
colors[i].pixel=(size_t) i;
if (number_colors > 256)
number_colors=256;
(void) XQueryColors(display,colormap,colors,(int) number_colors);
}
min_distance=3.0*((double) QuantumRange+1.0)*((double)
QuantumRange+1.0);
j=0;
for (i=0; i < (int) number_colors; i++)
{
pixel.red=colors[i].red-(double) color->red;
distance=pixel.red*pixel.red;
if (distance > min_distance)
continue;
pixel.green=colors[i].green-(double) color->green;
distance+=pixel.green*pixel.green;
if (distance > min_distance)
continue;
pixel.blue=colors[i].blue-(double) color->blue;
distance+=pixel.blue*pixel.blue;
if (distance > min_distance)
continue;
min_distance=distance;
color->pixel=colors[i].pixel;
j=i;
}
(void) XAllocColor(display,colormap,&colors[j]);
if (query_server != MagickFalse)
colors=(XColor *) RelinquishMagickMemory(colors);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X B e s t V i s u a l I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XBestVisualInfo() returns visual information for a visual that is the "best"
% the server supports. "Best" is defined as:
%
% 1. Restrict the visual list to those supported by the default screen.
%
% 2. If a visual type is specified, restrict the visual list to those of
% that type.
%
% 3. If a map type is specified, choose the visual that matches the id
% specified by the Standard Colormap.
%
% 4 From the list of visuals, choose one that can display the most
% simultaneous colors. If more than one visual can display the same
% number of simultaneous colors, one is chosen based on a rank.
%
% The format of the XBestVisualInfo method is:
%
% XVisualInfo *XBestVisualInfo(Display *display,
% XStandardColormap *map_info,XResourceInfo *resource_info)
%
% A description of each parameter follows:
%
% o visual_info: XBestVisualInfo returns a pointer to a X11 XVisualInfo
% structure.
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o map_info: If map_type is specified, this structure is initialized
% with info from the Standard Colormap.
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
*/
MagickPrivate XVisualInfo *XBestVisualInfo(Display *display,
XStandardColormap *map_info,XResourceInfo *resource_info)
{
#define MaxStandardColormaps 7
#define XVisualColormapSize(visual_info) MagickMin((unsigned int) (\
(visual_info->klass == TrueColor) || (visual_info->klass == DirectColor) ? \
visual_info->red_mask | visual_info->green_mask | visual_info->blue_mask : \
(unsigned long) visual_info->colormap_size),1UL << visual_info->depth)
char
*map_type,
*visual_type;
int
visual_mask;
register int
i;
size_t
one;
static int
number_visuals;
static XVisualInfo
visual_template;
XVisualInfo
*visual_info,
*visual_list;
/*
Restrict visual search by screen number.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(map_info != (XStandardColormap *) NULL);
assert(resource_info != (XResourceInfo *) NULL);
map_type=resource_info->map_type;
visual_type=resource_info->visual_type;
visual_mask=VisualScreenMask;
visual_template.screen=XDefaultScreen(display);
visual_template.depth=XDefaultDepth(display,XDefaultScreen(display));
one=1;
if ((resource_info->immutable != MagickFalse) && (resource_info->colors != 0))
if (resource_info->colors <= (one << (size_t) visual_template.depth))
visual_mask|=VisualDepthMask;
if (visual_type != (char *) NULL)
{
/*
Restrict visual search by class or visual id.
*/
if (LocaleCompare("staticgray",visual_type) == 0)
{
visual_mask|=VisualClassMask;
visual_template.klass=StaticGray;
}
else
if (LocaleCompare("grayscale",visual_type) == 0)
{
visual_mask|=VisualClassMask;
visual_template.klass=GrayScale;
}
else
if (LocaleCompare("staticcolor",visual_type) == 0)
{
visual_mask|=VisualClassMask;
visual_template.klass=StaticColor;
}
else
if (LocaleCompare("pseudocolor",visual_type) == 0)
{
visual_mask|=VisualClassMask;
visual_template.klass=PseudoColor;
}
else
if (LocaleCompare("truecolor",visual_type) == 0)
{
visual_mask|=VisualClassMask;
visual_template.klass=TrueColor;
}
else
if (LocaleCompare("directcolor",visual_type) == 0)
{
visual_mask|=VisualClassMask;
visual_template.klass=DirectColor;
}
else
if (LocaleCompare("default",visual_type) == 0)
{
visual_mask|=VisualIDMask;
visual_template.visualid=XVisualIDFromVisual(
XDefaultVisual(display,XDefaultScreen(display)));
}
else
if (isdigit((int) ((unsigned char) *visual_type)) != 0)
{
visual_mask|=VisualIDMask;
visual_template.visualid=
strtol(visual_type,(char **) NULL,0);
}
else
ThrowXWindowException(XServerError,
"UnrecognizedVisualSpecifier",visual_type);
}
/*
Get all visuals that meet our criteria so far.
*/
number_visuals=0;
visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
&number_visuals);
visual_mask=VisualScreenMask | VisualIDMask;
if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
{
/*
Failed to get visual; try using the default visual.
*/
ThrowXWindowException(XServerWarning,"UnableToGetVisual",visual_type);
visual_template.visualid=XVisualIDFromVisual(XDefaultVisual(display,
XDefaultScreen(display)));
visual_list=XGetVisualInfo(display,visual_mask,&visual_template,
&number_visuals);
if ((number_visuals == 0) || (visual_list == (XVisualInfo *) NULL))
return((XVisualInfo *) NULL);
ThrowXWindowException(XServerWarning,"UsingDefaultVisual",
XVisualClassName(visual_list->klass));
}
resource_info->color_recovery=MagickFalse;
if ((map_info != (XStandardColormap *) NULL) && (map_type != (char *) NULL))
{
Atom
map_property;
char
map_name[MagickPathExtent];
int
j,
number_maps;
Status
status;
Window
root_window;
XStandardColormap
*map_list;
/*
Choose a visual associated with a standard colormap.
*/
root_window=XRootWindow(display,XDefaultScreen(display));
status=False;
number_maps=0;
if (LocaleCompare(map_type,"list") != 0)
{
/*
User specified Standard Colormap.
*/
(void) FormatLocaleString((char *) map_name,MagickPathExtent,
"RGB_%s_MAP",map_type);
LocaleUpper(map_name);
map_property=XInternAtom(display,(char *) map_name,MagickTrue);
if (map_property != (Atom) NULL)
status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
map_property);
}
else
{
static const char
*colormap[MaxStandardColormaps]=
{
"_HP_RGB_SMOOTH_MAP_LIST",
"RGB_BEST_MAP",
"RGB_DEFAULT_MAP",
"RGB_GRAY_MAP",
"RGB_RED_MAP",
"RGB_GREEN_MAP",
"RGB_BLUE_MAP",
};
/*
Choose a standard colormap from a list.
*/
for (i=0; i < MaxStandardColormaps; i++)
{
map_property=XInternAtom(display,(char *) colormap[i],MagickTrue);
if (map_property == (Atom) NULL)
continue;
status=XGetRGBColormaps(display,root_window,&map_list,&number_maps,
map_property);
if (status != False)
break;
}
resource_info->color_recovery=i == 0 ? MagickTrue : MagickFalse;
}
if (status == False)
{
ThrowXWindowException(XServerError,"UnableToGetStandardColormap",
map_type);
return((XVisualInfo *) NULL);
}
/*
Search all Standard Colormaps and visuals for ids that match.
*/
*map_info=map_list[0];
#if !defined(PRE_R4_ICCCM)
visual_template.visualid=XVisualIDFromVisual(visual_list[0].visual);
for (i=0; i < number_maps; i++)
for (j=0; j < number_visuals; j++)
if (map_list[i].visualid ==
XVisualIDFromVisual(visual_list[j].visual))
{
*map_info=map_list[i];
visual_template.visualid=XVisualIDFromVisual(
visual_list[j].visual);
break;
}
if (map_info->visualid != visual_template.visualid)
{
ThrowXWindowException(XServerError,
"UnableToMatchVisualToStandardColormap",map_type);
return((XVisualInfo *) NULL);
}
#endif
if (map_info->colormap == (Colormap) NULL)
{
ThrowXWindowException(XServerError,"StandardColormapIsNotInitialized",
map_type);
return((XVisualInfo *) NULL);
}
(void) XFree((void *) map_list);
}
else
{
static const unsigned int
rank[]=
{
StaticGray,
GrayScale,
StaticColor,
DirectColor,
TrueColor,
PseudoColor
};
XVisualInfo
*p;
/*
Pick one visual that displays the most simultaneous colors.
*/
visual_info=visual_list;
p=visual_list;
for (i=1; i < number_visuals; i++)
{
p++;
if (XVisualColormapSize(p) > XVisualColormapSize(visual_info))
visual_info=p;
else
if (XVisualColormapSize(p) == XVisualColormapSize(visual_info))
if (rank[p->klass] > rank[visual_info->klass])
visual_info=p;
}
visual_template.visualid=XVisualIDFromVisual(visual_info->visual);
}
(void) XFree((void *) visual_list);
/*
Retrieve only one visual by its screen & id number.
*/
visual_info=XGetVisualInfo(display,visual_mask,&visual_template,
&number_visuals);
if ((number_visuals == 0) || (visual_info == (XVisualInfo *) NULL))
return((XVisualInfo *) NULL);
return(visual_info);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X C h e c k D e f i n e C u r s o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XCheckDefineCursor() prevents cursor changes on the root window.
%
% The format of the XXCheckDefineCursor method is:
%
% XCheckDefineCursor(display,window,cursor)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o window: the window.
%
% o cursor: the cursor.
%
*/
MagickPrivate int XCheckDefineCursor(Display *display,Window window,
Cursor cursor)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
if (window == XRootWindow(display,XDefaultScreen(display)))
return(0);
return(XDefineCursor(display,window,cursor));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X C h e c k R e f r e s h W i n d o w s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XCheckRefreshWindows() checks the X server for exposure events for a
% particular window and updates the areassociated with the exposure event.
%
% The format of the XCheckRefreshWindows method is:
%
% void XCheckRefreshWindows(Display *display,XWindows *windows)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o windows: Specifies a pointer to a XWindows structure.
%
*/
MagickPrivate void XCheckRefreshWindows(Display *display,XWindows *windows)
{
Window
id;
XEvent
event;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(windows != (XWindows *) NULL);
XDelay(display,SuspendTime);
id=windows->command.id;
while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
(void) XCommandWidget(display,windows,(char const **) NULL,&event);
id=windows->image.id;
while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
XRefreshWindow(display,&windows->image,&event);
XDelay(display,SuspendTime << 1);
id=windows->command.id;
while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
(void) XCommandWidget(display,windows,(char const **) NULL,&event);
id=windows->image.id;
while (XCheckTypedWindowEvent(display,id,Expose,&event) != MagickFalse)
XRefreshWindow(display,&windows->image,&event);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X C l i e n t M e s s a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XClientMessage() sends a reason to a window with XSendEvent. The reason is
% initialized with a particular protocol type and atom.
%
% The format of the XClientMessage function is:
%
% XClientMessage(display,window,protocol,reason,timestamp)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window: Specifies a pointer to a Window structure.
%
% o protocol: Specifies an atom value.
%
% o reason: Specifies an atom value which is the reason to send.
%
% o timestamp: Specifies a value of type Time.
%
*/
MagickPrivate void XClientMessage(Display *display,const Window window,
const Atom protocol,const Atom reason,const Time timestamp)
{
XClientMessageEvent
client_event;
assert(display != (Display *) NULL);
(void) memset(&client_event,0,sizeof(client_event));
client_event.type=ClientMessage;
client_event.window=window;
client_event.message_type=protocol;
client_event.format=32;
client_event.data.l[0]=(long) reason;
client_event.data.l[1]=(long) timestamp;
(void) XSendEvent(display,window,MagickFalse,NoEventMask,(XEvent *)
&client_event);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X C l i e n t W i n d o w %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XClientWindow() finds a window, at or below the specified window, which has
% a WM_STATE property. If such a window is found, it is returned, otherwise
% the argument window is returned.
%
% The format of the XClientWindow function is:
%
% client_window=XClientWindow(display,target_window)
%
% A description of each parameter follows:
%
% o client_window: XClientWindow returns a window, at or below the specified
% window, which has a WM_STATE property otherwise the argument
% target_window is returned.
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o target_window: Specifies the window to find a WM_STATE property.
%
*/
static Window XClientWindow(Display *display,Window target_window)
{
Atom
state,
type;
int
format;
Status
status;
unsigned char
*data;
unsigned long
after,
number_items;
Window
client_window;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
state=XInternAtom(display,"WM_STATE",MagickTrue);
if (state == (Atom) NULL)
return(target_window);
type=(Atom) NULL;
status=XGetWindowProperty(display,target_window,state,0L,0L,MagickFalse,
(Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
if ((status == Success) && (type != (Atom) NULL))
return(target_window);
client_window=XWindowByProperty(display,target_window,state);
if (client_window == (Window) NULL)
return(target_window);
return(client_window);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X C o m p o n e n t T e r m i n u s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XComponentTerminus() destroys the module component.
%
% The format of the XComponentTerminus method is:
%
% XComponentTerminus(void)
%
*/
MagickPrivate void XComponentTerminus(void)
{
DestroyXResources();
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X C o n f i g u r e I m a g e C o l o r m a p %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XConfigureImageColormap() creates a new X colormap.
%
% The format of the XConfigureImageColormap method is:
%
% void XConfigureImageColormap(Display *display,
% XResourceInfo *resource_info,XWindows *windows,Image *image,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
% o windows: Specifies a pointer to a XWindows structure.
%
% o image: the image.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickPrivate void XConfigureImageColormap(Display *display,
XResourceInfo *resource_info,XWindows *windows,Image *image,
ExceptionInfo *exception)
{
Colormap
colormap;
/*
Make standard colormap.
*/
XSetCursorState(display,windows,MagickTrue);
XCheckRefreshWindows(display,windows);
XMakeStandardColormap(display,windows->visual_info,resource_info,image,
windows->map_info,windows->pixel_info,exception);
colormap=windows->map_info->colormap;
(void) XSetWindowColormap(display,windows->image.id,colormap);
(void) XSetWindowColormap(display,windows->command.id,colormap);
(void) XSetWindowColormap(display,windows->widget.id,colormap);
if (windows->magnify.mapped != MagickFalse)
(void) XSetWindowColormap(display,windows->magnify.id,colormap);
if (windows->pan.mapped != MagickFalse)
(void) XSetWindowColormap(display,windows->pan.id,colormap);
XSetCursorState(display,windows,MagickFalse);
XClientMessage(display,windows->image.id,windows->im_protocols,
windows->im_update_colormap,CurrentTime);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X C o n s t r a i n W i n d o w P o s i t i o n %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XConstrainWindowPosition() assures a window is positioned within the X
% server boundaries.
%
% The format of the XConstrainWindowPosition method is:
%
% void XConstrainWindowPosition(Display *display,XWindowInfo *window_info)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o window_info: Specifies a pointer to a XWindowInfo structure.
%
*/
MagickPrivate void XConstrainWindowPosition(Display *display,
XWindowInfo *window_info)
{
int
limit;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(window_info != (XWindowInfo *) NULL);
limit=XDisplayWidth(display,window_info->screen)-window_info->width;
if (window_info->x < 0)
window_info->x=0;
else
if (window_info->x > (int) limit)
window_info->x=(int) limit;
limit=XDisplayHeight(display,window_info->screen)-window_info->height;
if (window_info->y < 0)
window_info->y=0;
else
if (window_info->y > limit)
window_info->y=limit;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X D e l a y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDelay() suspends program execution for the number of milliseconds
% specified.
%
% The format of the Delay method is:
%
% void XDelay(Display *display,const size_t milliseconds)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o milliseconds: Specifies the number of milliseconds to delay before
% returning.
%
*/
MagickPrivate void XDelay(Display *display,const size_t milliseconds)
{
assert(display != (Display *) NULL);
(void) XFlush(display);
MagickDelay(milliseconds);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X D e s t r o y R e s o u r c e I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDestroyResourceInfo() frees memory associated with the XResourceInfo
% structure.
%
% The format of the XDestroyResourceInfo method is:
%
% void XDestroyResourceInfo(XResourceInfo *resource_info)
%
% A description of each parameter follows:
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
*/
MagickExport void XDestroyResourceInfo(XResourceInfo *resource_info)
{
if (resource_info->image_geometry != (char *) NULL)
resource_info->image_geometry=(char *)
RelinquishMagickMemory(resource_info->image_geometry);
if (resource_info->quantize_info != (QuantizeInfo *) NULL)
resource_info->quantize_info=DestroyQuantizeInfo(
resource_info->quantize_info);
if (resource_info->client_name != (char *) NULL)
resource_info->client_name=(char *)
RelinquishMagickMemory(resource_info->client_name);
if (resource_info->name != (char *) NULL)
resource_info->name=DestroyString(resource_info->name);
(void) memset(resource_info,0,sizeof(*resource_info));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X D e s t r o y W i n d o w C o l o r s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDestroyWindowColors() frees X11 color resources previously saved on a
% window by XRetainWindowColors or programs like xsetroot.
%
% The format of the XDestroyWindowColors method is:
%
% void XDestroyWindowColors(Display *display,Window window)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o window: Specifies a pointer to a Window structure.
%
*/
MagickPrivate void XDestroyWindowColors(Display *display,Window window)
{
Atom
property,
type;
int
format;
Status
status;
unsigned char
*data;
unsigned long
after,
length;
/*
If there are previous resources on the root window, destroy them.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
if (property == (Atom) NULL)
{
ThrowXWindowException(XServerError,"UnableToCreateProperty",
"_XSETROOT_ID");
return;
}
status=XGetWindowProperty(display,window,property,0L,1L,MagickTrue,
(Atom) AnyPropertyType,&type,&format,&length,&after,&data);
if (status != Success)
return;
if ((type == XA_PIXMAP) && (format == 32) && (length == 1) && (after == 0))
{
(void) XKillClient(display,(XID) (*((Pixmap *) data)));
(void) XDeleteProperty(display,window,property);
}
if (type != None)
(void) XFree((void *) data);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X D i s p l a y I m a g e I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDisplayImageInfo() displays information about an X image.
%
% The format of the XDisplayImageInfo method is:
%
% void XDisplayImageInfo(Display *display,
% const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
% Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
% o windows: Specifies a pointer to a XWindows structure.
%
% o undo_image: the undo image.
%
% o image: the image.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickPrivate void XDisplayImageInfo(Display *display,
const XResourceInfo *resource_info,XWindows *windows,Image *undo_image,
Image *image,ExceptionInfo *exception)
{
char
filename[MagickPathExtent],
*text,
**textlist;
FILE
*file;
int
unique_file;
register ssize_t
i;
size_t
number_pixels;
ssize_t
bytes;
unsigned int
levels;
/*
Write info about the X server to a file.
*/
assert(display != (Display *) NULL);
assert(resource_info != (XResourceInfo *) NULL);
assert(windows != (XWindows *) NULL);
assert(image != (Image *) NULL);
if (image->debug)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
file=(FILE *) NULL;
unique_file=AcquireUniqueFileResource(filename);
if (unique_file != -1)
file=fdopen(unique_file,"w");
if ((unique_file == -1) || (file == (FILE *) NULL))
{
XNoticeWidget(display,windows,"Unable to display image info",filename);
return;
}
if (resource_info->gamma_correct != MagickFalse)
if (resource_info->display_gamma != (char *) NULL)
(void) FormatLocaleFile(file,"Display\n gamma: %s\n\n",
resource_info->display_gamma);
/*
Write info about the X image to a file.
*/
(void) FormatLocaleFile(file,"X\n visual: %s\n",
XVisualClassName((int) windows->image.storage_class));
(void) FormatLocaleFile(file," depth: %d\n",windows->image.ximage->depth);
if (windows->visual_info->colormap_size != 0)
(void) FormatLocaleFile(file," colormap size: %d\n",
windows->visual_info->colormap_size);
if (resource_info->colormap== SharedColormap)
(void) FormatLocaleFile(file," colormap type: Shared\n");
else
(void) FormatLocaleFile(file," colormap type: Private\n");
(void) FormatLocaleFile(file," geometry: %dx%d\n",
windows->image.ximage->width,windows->image.ximage->height);
if (windows->image.crop_geometry != (char *) NULL)
(void) FormatLocaleFile(file," crop geometry: %s\n",
windows->image.crop_geometry);
if (windows->image.pixmap == (Pixmap) NULL)
(void) FormatLocaleFile(file," type: X Image\n");
else
(void) FormatLocaleFile(file," type: Pixmap\n");
if (windows->image.shape != MagickFalse)
(void) FormatLocaleFile(file," non-rectangular shape: True\n");
else
(void) FormatLocaleFile(file," non-rectangular shape: False\n");
if (windows->image.shared_memory != MagickFalse)
(void) FormatLocaleFile(file," shared memory: True\n");
else
(void) FormatLocaleFile(file," shared memory: False\n");
(void) FormatLocaleFile(file,"\n");
if (resource_info->font != (char *) NULL)
(void) FormatLocaleFile(file,"Font: %s\n\n",resource_info->font);
if (resource_info->text_font != (char *) NULL)
(void) FormatLocaleFile(file,"Text font: %s\n\n",resource_info->text_font);
/*
Write info about the undo cache to a file.
*/
bytes=0;
for (levels=0; undo_image != (Image *) NULL; levels++)
{
number_pixels=undo_image->list->columns*undo_image->list->rows;
bytes+=number_pixels*sizeof(PixelInfo);
undo_image=GetPreviousImageInList(undo_image);
}
(void) FormatLocaleFile(file,"Undo Edit Cache\n levels: %u\n",levels);
(void) FormatLocaleFile(file," bytes: %.20gmb\n",(double)
((bytes+(1 << 19)) >> 20));
(void) FormatLocaleFile(file," limit: %.20gmb\n\n",(double)
resource_info->undo_cache);
/*
Write info about the image to a file.
*/
(void) IdentifyImage(image,file,MagickTrue,exception);
(void) fclose(file);
text=FileToString(filename,~0UL,exception);
(void) RelinquishUniqueFileResource(filename);
if (text == (char *) NULL)
{
XNoticeWidget(display,windows,"MemoryAllocationFailed",
"UnableToDisplayImageInfo");
return;
}
textlist=StringToList(text);
if (textlist != (char **) NULL)
{
char
title[MagickPathExtent];
/*
Display information about the image in the Text View widget.
*/
(void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
(void) FormatLocaleString(title,MagickPathExtent,"Image Info: %s",
image->filename);
XTextViewWidget(display,resource_info,windows,MagickTrue,title,
(char const **) textlist);
for (i=0; textlist[i] != (char *) NULL; i++)
textlist[i]=DestroyString(textlist[i]);
textlist=(char **) RelinquishMagickMemory(textlist);
}
text=DestroyString(text);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X D i t h e r I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDitherImage() dithers the reference image as required by the HP Color
% Recovery algorithm. The color values are quantized to 3 bits of red and
% green, and 2 bits of blue (3/3/2) and can be used as indices into a 8-bit X
% standard colormap.
%
% The format of the XDitherImage method is:
%
% void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o ximage: Specifies a pointer to a XImage structure; returned from
% XCreateImage.
%
% o exception: return any errors or warnings in this structure.
%
*/
static void XDitherImage(Image *image,XImage *ximage,ExceptionInfo *exception)
{
static const short int
dither_red[2][16]=
{
{-16, 4, -1, 11,-14, 6, -3, 9,-15, 5, -2, 10,-13, 7, -4, 8},
{ 15, -5, 0,-12, 13, -7, 2,-10, 14, -6, 1,-11, 12, -8, 3, -9}
},
dither_green[2][16]=
{
{ 11,-15, 7, -3, 8,-14, 4, -2, 10,-16, 6, -4, 9,-13, 5, -1},
{-12, 14, -8, 2, -9, 13, -5, 1,-11, 15, -7, 3,-10, 12, -6, 0}
},
dither_blue[2][16]=
{
{ -3, 9,-13, 7, -1, 11,-15, 5, -4, 8,-14, 6, -2, 10,-16, 4},
{ 2,-10, 12, -8, 0,-12, 14, -6, 3, -9, 13, -7, 1,-11, 15, -5}
};
CacheView
*image_view;
int
value,
y;
PixelInfo
color;
register char
*q;
register const Quantum
*p;
register int
i,
j,
x;
unsigned int
scanline_pad;
register size_t
pixel;
unsigned char
*blue_map[2][16],
*green_map[2][16],
*red_map[2][16];
/*
Allocate and initialize dither maps.
*/
for (i=0; i < 2; i++)
for (j=0; j < 16; j++)
{
red_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
sizeof(*red_map));
green_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
sizeof(*green_map));
blue_map[i][j]=(unsigned char *) AcquireCriticalMemory(256UL*
sizeof(*blue_map));
}
/*
Initialize dither tables.
*/
for (i=0; i < 2; i++)
for (j=0; j < 16; j++)
for (x=0; x < 256; x++)
{
value=x-16;
if (x < 48)
value=x/2+8;
value+=dither_red[i][j];
red_map[i][j][x]=(unsigned char)
((value < 0) ? 0 : (value > 255) ? 255 : value);
value=x-16;
if (x < 48)
value=x/2+8;
value+=dither_green[i][j];
green_map[i][j][x]=(unsigned char)
((value < 0) ? 0 : (value > 255) ? 255 : value);
value=x-32;
if (x < 112)
value=x/2+24;
value+=((size_t) dither_blue[i][j] << 1);
blue_map[i][j][x]=(unsigned char)
((value < 0) ? 0 : (value > 255) ? 255 : value);
}
/*
Dither image.
*/
scanline_pad=(unsigned int) (ximage->bytes_per_line-
((size_t) (ximage->width*ximage->bits_per_pixel) >> 3));
i=0;
j=0;
q=ximage->data;
image_view=AcquireVirtualCacheView(image,exception);
for (y=0; y < (int) image->rows; y++)
{
p=GetCacheViewVirtualPixels(image_view,0,(ssize_t) y,image->columns,1,
exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (int) image->columns; x++)
{
color.red=(double) ClampToQuantum((double) (red_map[i][j][
(int) ScaleQuantumToChar(GetPixelRed(image,p))] << 8));
color.green=(double) ClampToQuantum((double) (green_map[i][j][
(int) ScaleQuantumToChar(GetPixelGreen(image,p))] << 8));
color.blue=(double) ClampToQuantum((double) (blue_map[i][j][
(int) ScaleQuantumToChar(GetPixelBlue(image,p))] << 8));
pixel=(size_t) (((size_t) color.red & 0xe0) |
(((size_t) color.green & 0xe0) >> 3) |
(((size_t) color.blue & 0xc0) >> 6));
*q++=(char) pixel;
p+=GetPixelChannels(image);
j++;
if (j == 16)
j=0;
}
q+=scanline_pad;
i++;
if (i == 2)
i=0;
}
image_view=DestroyCacheView(image_view);
/*
Free allocated memory.
*/
for (i=0; i < 2; i++)
for (j=0; j < 16; j++)
{
green_map[i][j]=(unsigned char *) RelinquishMagickMemory(green_map[i][j]);
blue_map[i][j]=(unsigned char *) RelinquishMagickMemory(blue_map[i][j]);
red_map[i][j]=(unsigned char *) RelinquishMagickMemory(red_map[i][j]);
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X D r a w I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XDrawImage() draws a line on the image.
%
% The format of the XDrawImage method is:
%
% MagickBooleanType XDrawImage(Display *display,const XPixelInfo *pixel,
% XDrawInfo *draw_info,Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o pixel: Specifies a pointer to a XPixelInfo structure.
%
% o draw_info: Specifies a pointer to a XDrawInfo structure.
%
% o image: the image.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickPrivate MagickBooleanType XDrawImage(Display *display,
const XPixelInfo *pixel,XDrawInfo *draw_info,Image *image,
ExceptionInfo *exception)
{
CacheView
*draw_view;
GC
draw_context;
Image
*draw_image;
int
x,
y;
PixelTrait
alpha_trait;
Pixmap
draw_pixmap;
unsigned int
depth,
height,
width;
Window
root_window;
XGCValues
context_values;
XImage
*draw_ximage;
/*
Initialize drawd image.
*/
assert(display != (Display *) NULL);
assert(pixel != (XPixelInfo *) NULL);
assert(draw_info != (XDrawInfo *) NULL);
assert(image != (Image *) NULL);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
/*
Initialize drawd pixmap.
*/
root_window=XRootWindow(display,XDefaultScreen(display));
depth=(unsigned int) XDefaultDepth(display,XDefaultScreen(display));
draw_pixmap=XCreatePixmap(display,root_window,draw_info->width,
draw_info->height,depth);
if (draw_pixmap == (Pixmap) NULL)
return(MagickFalse);
/*
Initialize graphics info.
*/
context_values.background=(size_t) (~0);
context_values.foreground=0;
context_values.line_width=(int) draw_info->line_width;
draw_context=XCreateGC(display,root_window,(size_t)
(GCBackground | GCForeground | GCLineWidth),&context_values);
if (draw_context == (GC) NULL)
return(MagickFalse);
/*
Clear pixmap.
*/
(void) XFillRectangle(display,draw_pixmap,draw_context,0,0,draw_info->width,
draw_info->height);
/*
Draw line to pixmap.
*/
(void) XSetBackground(display,draw_context,0);
(void) XSetForeground(display,draw_context,(size_t) (~0));
if (draw_info->stipple != (Pixmap) NULL)
{
(void) XSetFillStyle(display,draw_context,FillOpaqueStippled);
(void) XSetStipple(display,draw_context,draw_info->stipple);
}
switch (draw_info->element)
{
case PointElement:
default:
{
(void) XDrawLines(display,draw_pixmap,draw_context,
draw_info->coordinate_info,(int) draw_info->number_coordinates,
CoordModeOrigin);
break;
}
case LineElement:
{
(void) XDrawLine(display,draw_pixmap,draw_context,draw_info->line_info.x1,
draw_info->line_info.y1,draw_info->line_info.x2,
draw_info->line_info.y2);
break;
}
case RectangleElement:
{
(void) XDrawRectangle(display,draw_pixmap,draw_context,
(int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
(unsigned int) draw_info->rectangle_info.width,
(unsigned int) draw_info->rectangle_info.height);
break;
}
case FillRectangleElement:
{
(void) XFillRectangle(display,draw_pixmap,draw_context,
(int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
(unsigned int) draw_info->rectangle_info.width,
(unsigned int) draw_info->rectangle_info.height);
break;
}
case CircleElement:
case EllipseElement:
{
(void) XDrawArc(display,draw_pixmap,draw_context,
(int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
(unsigned int) draw_info->rectangle_info.width,
(unsigned int) draw_info->rectangle_info.height,0,360*64);
break;
}
case FillCircleElement:
case FillEllipseElement:
{
(void) XFillArc(display,draw_pixmap,draw_context,
(int) draw_info->rectangle_info.x,(int) draw_info->rectangle_info.y,
(unsigned int) draw_info->rectangle_info.width,
(unsigned int) draw_info->rectangle_info.height,0,360*64);
break;
}
case PolygonElement:
{
XPoint
*coordinate_info;
coordinate_info=draw_info->coordinate_info;
(void) XDrawLines(display,draw_pixmap,draw_context,coordinate_info,
(int) draw_info->number_coordinates,CoordModeOrigin);
(void) XDrawLine(display,draw_pixmap,draw_context,
coordinate_info[draw_info->number_coordinates-1].x,
coordinate_info[draw_info->number_coordinates-1].y,
coordinate_info[0].x,coordinate_info[0].y);
break;
}
case FillPolygonElement:
{
(void) XFillPolygon(display,draw_pixmap,draw_context,
draw_info->coordinate_info,(int) draw_info->number_coordinates,Complex,
CoordModeOrigin);
break;
}
}
(void) XFreeGC(display,draw_context);
/*
Initialize X image.
*/
draw_ximage=XGetImage(display,draw_pixmap,0,0,draw_info->width,
draw_info->height,AllPlanes,ZPixmap);
if (draw_ximage == (XImage *) NULL)
return(MagickFalse);
(void) XFreePixmap(display,draw_pixmap);
/*
Initialize draw image.
*/
draw_image=AcquireImage((ImageInfo *) NULL,exception);
if (draw_image == (Image *) NULL)
return(MagickFalse);
draw_image->columns=draw_info->width;
draw_image->rows=draw_info->height;
/*
Transfer drawn X image to image.
*/
width=(unsigned int) image->columns;
height=(unsigned int) image->rows;
x=0;
y=0;
(void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
(void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,(ssize_t) x,
(ssize_t) y,&draw_image->background_color,exception);
if (SetImageStorageClass(draw_image,DirectClass,exception) == MagickFalse)
return(MagickFalse);
draw_image->alpha_trait=BlendPixelTrait;
draw_view=AcquireAuthenticCacheView(draw_image,exception);
for (y=0; y < (int) draw_image->rows; y++)
{
register int
x;
register Quantum
*magick_restrict q;
q=QueueCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,
1,exception);
if (q == (Quantum *) NULL)
break;
for (x=0; x < (int) draw_image->columns; x++)
{
if (XGetPixel(draw_ximage,x,y) == 0)
{
/*
Set this pixel to the background color.
*/
SetPixelViaPixelInfo(draw_image,&draw_image->background_color,q);
SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
OpaqueStencil ? TransparentAlpha : OpaqueAlpha),q);
}
else
{
/*
Set this pixel to the pen color.
*/
SetPixelRed(draw_image,ScaleShortToQuantum(
pixel->pen_color.red),q);
SetPixelGreen(draw_image,ScaleShortToQuantum(
pixel->pen_color.green),q);
SetPixelBlue(draw_image,ScaleShortToQuantum(
pixel->pen_color.blue),q);
SetPixelAlpha(draw_image,(Quantum) (draw_info->stencil ==
OpaqueStencil ? OpaqueAlpha : TransparentAlpha),q);
}
q+=GetPixelChannels(draw_image);
}
if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
break;
}
draw_view=DestroyCacheView(draw_view);
XDestroyImage(draw_ximage);
/*
Determine draw geometry.
*/
(void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
if ((width != (unsigned int) draw_image->columns) ||
(height != (unsigned int) draw_image->rows))
{
char
image_geometry[MagickPathExtent];
/*
Scale image.
*/
(void) FormatLocaleString(image_geometry,MagickPathExtent,"%ux%u",
width,height);
(void) TransformImage(&draw_image,(char *) NULL,image_geometry,
exception);
}
if (draw_info->degrees != 0.0)
{
Image
*rotate_image;
int
rotations;
double
normalized_degrees;
/*
Rotate image.
*/
rotate_image=RotateImage(draw_image,draw_info->degrees,exception);
if (rotate_image == (Image *) NULL)
return(MagickFalse);
draw_image=DestroyImage(draw_image);
draw_image=rotate_image;
/*
Annotation is relative to the degree of rotation.
*/
normalized_degrees=draw_info->degrees;
while (normalized_degrees < -45.0)
normalized_degrees+=360.0;
for (rotations=0; normalized_degrees > 45.0; rotations++)
normalized_degrees-=90.0;
switch (rotations % 4)
{
default:
case 0:
break;
case 1:
{
/*
Rotate 90 degrees.
*/
x=x-(int) draw_image->columns/2;
y=y+(int) draw_image->columns/2;
break;
}
case 2:
{
/*
Rotate 180 degrees.
*/
x=x-(int) draw_image->columns;
break;
}
case 3:
{
/*
Rotate 270 degrees.
*/
x=x-(int) draw_image->columns/2;
y=y-(int) (draw_image->rows-(draw_image->columns/2));
break;
}
}
}
/*
Composite text onto the image.
*/
draw_view=AcquireAuthenticCacheView(draw_image,exception);
for (y=0; y < (int) draw_image->rows; y++)
{
register int
x;
register Quantum
*magick_restrict q;
q=GetCacheViewAuthenticPixels(draw_view,0,(ssize_t) y,draw_image->columns,1,
exception);
if (q == (Quantum *) NULL)
break;
for (x=0; x < (int) draw_image->columns; x++)
{
if (GetPixelAlpha(image,q) != TransparentAlpha)
SetPixelAlpha(draw_image,OpaqueAlpha,q);
q+=GetPixelChannels(draw_image);
}
if (SyncCacheViewAuthenticPixels(draw_view,exception) == MagickFalse)
break;
}
draw_view=DestroyCacheView(draw_view);
(void) XParseGeometry(draw_info->geometry,&x,&y,&width,&height);
if (draw_info->stencil == TransparentStencil)
(void) CompositeImage(image,draw_image,CopyAlphaCompositeOp,MagickTrue,
(ssize_t) x,(ssize_t) y,exception);
else
{
alpha_trait=image->alpha_trait;
(void) CompositeImage(image,draw_image,OverCompositeOp,MagickTrue,
(ssize_t) x,(ssize_t) y,exception);
image->alpha_trait=alpha_trait;
}
draw_image=DestroyImage(draw_image);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X E r r o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XError() ignores BadWindow errors for XQueryTree and XGetWindowAttributes,
% and ignores BadDrawable errors for XGetGeometry, and ignores BadValue errors
% for XQueryColor. It returns MagickFalse in those cases. Otherwise it
% returns True.
%
% The format of the XError function is:
%
% int XError(display,error)
%
% A description of each parameter follows:
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o error: Specifies the error event.
%
*/
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
MagickExport int XError(Display *display,XErrorEvent *error)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(error != (XErrorEvent *) NULL);
xerror_alert=MagickTrue;
switch (error->request_code)
{
case X_GetGeometry:
{
if ((int) error->error_code == BadDrawable)
return(MagickFalse);
break;
}
case X_GetWindowAttributes:
case X_QueryTree:
{
if ((int) error->error_code == BadWindow)
return(MagickFalse);
break;
}
case X_QueryColors:
{
if ((int) error->error_code == BadValue)
return(MagickFalse);
break;
}
}
return(MagickTrue);
}
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X F r e e R e s o u r c e s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XFreeResources() frees X11 resources.
%
% The format of the XFreeResources method is:
%
% void XFreeResources(Display *display,XVisualInfo *visual_info,
% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
% XResourceInfo *resource_info,XWindowInfo *window_info)
% resource_info,window_info)
%