/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% 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-2019 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]->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)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
% returned from XGetVisualInfo.
%
% o map_info: If map_type is specified, this structure is initialized
% with info from the Standard Colormap.
%
% o pixel: Specifies a pointer to a XPixelInfo structure.
%
% o font_info: Specifies a pointer to a XFontStruct structure.
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
*/
MagickPrivate void XFreeResources(Display *display,XVisualInfo *visual_info,
XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
XResourceInfo *resource_info,XWindowInfo *window_info)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(resource_info != (XResourceInfo *) NULL);
if (window_info != (XWindowInfo *) NULL)
{
/*
Free X image.
*/
if (window_info->ximage != (XImage *) NULL)
XDestroyImage(window_info->ximage);
if (window_info->id != (Window) NULL)
{
/*
Free destroy window and free cursors.
*/
if (window_info->id != XRootWindow(display,visual_info->screen))
(void) XDestroyWindow(display,window_info->id);
if (window_info->annotate_context != (GC) NULL)
(void) XFreeGC(display,window_info->annotate_context);
if (window_info->highlight_context != (GC) NULL)
(void) XFreeGC(display,window_info->highlight_context);
if (window_info->widget_context != (GC) NULL)
(void) XFreeGC(display,window_info->widget_context);
if (window_info->cursor != (Cursor) NULL)
(void) XFreeCursor(display,window_info->cursor);
window_info->cursor=(Cursor) NULL;
if (window_info->busy_cursor != (Cursor) NULL)
(void) XFreeCursor(display,window_info->busy_cursor);
window_info->busy_cursor=(Cursor) NULL;
}
}
/*
Free font.
*/
if (font_info != (XFontStruct *) NULL)
{
(void) XFreeFont(display,font_info);
font_info=(XFontStruct *) NULL;
}
if (map_info != (XStandardColormap *) NULL)
{
/*
Free X Standard Colormap.
*/
if (resource_info->map_type == (char *) NULL)
(void) XFreeStandardColormap(display,visual_info,map_info,pixel);
(void) XFree((void *) map_info);
}
/*
Free X visual info.
*/
if (visual_info != (XVisualInfo *) NULL)
(void) XFree((void *) visual_info);
if (resource_info->close_server != MagickFalse)
(void) XCloseDisplay(display);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X F r e e S t a n d a r d C o l o r m a p %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XFreeStandardColormap() frees an X11 colormap.
%
% The format of the XFreeStandardColormap method is:
%
% void XFreeStandardColormap(Display *display,
% const XVisualInfo *visual_info,XStandardColormap *map_info,
% XPixelInfo *pixel)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
% returned from XGetVisualInfo.
%
% o map_info: If map_type is specified, this structure is initialized
% with info from the Standard Colormap.
%
% o pixel: Specifies a pointer to a XPixelInfo structure.
%
*/
MagickPrivate void XFreeStandardColormap(Display *display,
const XVisualInfo *visual_info,XStandardColormap *map_info,XPixelInfo *pixel)
{
/*
Free colormap.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(visual_info != (XVisualInfo *) NULL);
assert(map_info != (XStandardColormap *) NULL);
(void) XFlush(display);
if (map_info->colormap != (Colormap) NULL)
{
if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
(void) XFreeColormap(display,map_info->colormap);
else
if (pixel != (XPixelInfo *) NULL)
if ((visual_info->klass != TrueColor) &&
(visual_info->klass != DirectColor))
(void) XFreeColors(display,map_info->colormap,pixel->pixels,
(int) pixel->colors,0);
}
map_info->colormap=(Colormap) NULL;
if (pixel != (XPixelInfo *) NULL)
{
if (pixel->pixels != (unsigned long *) NULL)
pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
pixel->pixels=(unsigned long *) NULL;
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X G e t A n n o t a t e I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetAnnotateInfo() initializes the AnnotateInfo structure.
%
% The format of the XGetAnnotateInfo method is:
%
% void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
%
% A description of each parameter follows:
%
% o annotate_info: Specifies a pointer to a XAnnotateInfo structure.
%
*/
MagickPrivate void XGetAnnotateInfo(XAnnotateInfo *annotate_info)
{
/*
Initialize annotate structure.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(annotate_info != (XAnnotateInfo *) NULL);
annotate_info->x=0;
annotate_info->y=0;
annotate_info->width=0;
annotate_info->height=0;
annotate_info->stencil=ForegroundStencil;
annotate_info->degrees=0.0;
annotate_info->font_info=(XFontStruct *) NULL;
annotate_info->text=(char *) NULL;
*annotate_info->geometry='\0';
annotate_info->previous=(XAnnotateInfo *) NULL;
annotate_info->next=(XAnnotateInfo *) NULL;
(void) XSupportsLocale();
(void) XSetLocaleModifiers("");
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X G e t M a p I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetMapInfo() initializes the XStandardColormap structure.
%
% The format of the XStandardColormap method is:
%
% void XGetMapInfo(const XVisualInfo *visual_info,const Colormap colormap,
% XStandardColormap *map_info)
%
% A description of each parameter follows:
%
% o colormap: Specifies the ID of the X server colormap.
%
% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
% returned from XGetVisualInfo.
%
% o map_info: Specifies a pointer to a X11 XStandardColormap structure.
%
*/
MagickPrivate void XGetMapInfo(const XVisualInfo *visual_info,
const Colormap colormap,XStandardColormap *map_info)
{
/*
Initialize map info.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(visual_info != (XVisualInfo *) NULL);
assert(map_info != (XStandardColormap *) NULL);
map_info->colormap=colormap;
map_info->red_max=visual_info->red_mask;
map_info->red_mult=(size_t) (map_info->red_max != 0 ? 1 : 0);
if (map_info->red_max != 0)
while ((map_info->red_max & 0x01) == 0)
{
map_info->red_max>>=1;
map_info->red_mult<<=1;
}
map_info->green_max=visual_info->green_mask;
map_info->green_mult=(size_t) (map_info->green_max != 0 ? 1 : 0);
if (map_info->green_max != 0)
while ((map_info->green_max & 0x01) == 0)
{
map_info->green_max>>=1;
map_info->green_mult<<=1;
}
map_info->blue_max=visual_info->blue_mask;
map_info->blue_mult=(size_t) (map_info->blue_max != 0 ? 1 : 0);
if (map_info->blue_max != 0)
while ((map_info->blue_max & 0x01) == 0)
{
map_info->blue_max>>=1;
map_info->blue_mult<<=1;
}
map_info->base_pixel=0;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X G e t P i x e l I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetPixelInfo() initializes the PixelInfo structure.
%
% The format of the XGetPixelInfo method is:
%
% void XGetPixelInfo(Display *display,const XVisualInfo *visual_info,
% const XStandardColormap *map_info,const XResourceInfo *resource_info,
% Image *image,XPixelInfo *pixel)
% pixel)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
% returned from XGetVisualInfo.
%
% 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.
%
% o image: the image.
%
% o pixel: Specifies a pointer to a XPixelInfo structure.
%
*/
MagickPrivate void XGetPixelInfo(Display *display,
const XVisualInfo *visual_info,const XStandardColormap *map_info,
const XResourceInfo *resource_info,Image *image,XPixelInfo *pixel)
{
static const char
*PenColors[MaxNumberPens]=
{
"#000000000000", /* black */
"#00000000ffff", /* blue */
"#0000ffffffff", /* cyan */
"#0000ffff0000", /* green */
"#bdbdbdbdbdbd", /* gray */
"#ffff00000000", /* red */
"#ffff0000ffff", /* magenta */
"#ffffffff0000", /* yellow */
"#ffffffffffff", /* white */
"#bdbdbdbdbdbd", /* gray */
"#bdbdbdbdbdbd" /* gray */
};
Colormap
colormap;
extern const char
BorderColor[],
ForegroundColor[];
register ssize_t
i;
Status
status;
unsigned int
packets;
/*
Initialize pixel info.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(visual_info != (XVisualInfo *) NULL);
assert(map_info != (XStandardColormap *) NULL);
assert(resource_info != (XResourceInfo *) NULL);
assert(pixel != (XPixelInfo *) NULL);
pixel->colors=0;
if (image != (Image *) NULL)
if (image->storage_class == PseudoClass)
pixel->colors=(ssize_t) image->colors;
packets=(unsigned int)
MagickMax((int) pixel->colors,visual_info->colormap_size)+MaxNumberPens;
if (pixel->pixels != (unsigned long *) NULL)
pixel->pixels=(unsigned long *) RelinquishMagickMemory(pixel->pixels);
pixel->pixels=(unsigned long *) AcquireQuantumMemory(packets,
sizeof(*pixel->pixels));
if (pixel->pixels == (unsigned long *) NULL)
ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToGetPixelInfo",
image->filename);
/*
Set foreground color.
*/
colormap=map_info->colormap;
(void) XParseColor(display,colormap,(char *) ForegroundColor,
&pixel->foreground_color);
status=XParseColor(display,colormap,resource_info->foreground_color,
&pixel->foreground_color);
if (status == False)
ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
resource_info->foreground_color);
pixel->foreground_color.pixel=
XStandardPixel(map_info,&pixel->foreground_color);
pixel->foreground_color.flags=(char) (DoRed | DoGreen | DoBlue);
/*
Set background color.
*/
(void) XParseColor(display,colormap,"#d6d6d6d6d6d6",&pixel->background_color);
status=XParseColor(display,colormap,resource_info->background_color,
&pixel->background_color);
if (status == False)
ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
resource_info->background_color);
pixel->background_color.pixel=
XStandardPixel(map_info,&pixel->background_color);
pixel->background_color.flags=(char) (DoRed | DoGreen | DoBlue);
/*
Set border color.
*/
(void) XParseColor(display,colormap,(char *) BorderColor,
&pixel->border_color);
status=XParseColor(display,colormap,resource_info->border_color,
&pixel->border_color);
if (status == False)
ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
resource_info->border_color);
pixel->border_color.pixel=XStandardPixel(map_info,&pixel->border_color);
pixel->border_color.flags=(char) (DoRed | DoGreen | DoBlue);
/*
Set matte color.
*/
pixel->matte_color=pixel->background_color;
if (resource_info->matte_color != (char *) NULL)
{
/*
Matte color is specified as a X resource or command line argument.
*/
status=XParseColor(display,colormap,resource_info->matte_color,
&pixel->matte_color);
if (status == False)
ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
resource_info->matte_color);
pixel->matte_color.pixel=XStandardPixel(map_info,&pixel->matte_color);
pixel->matte_color.flags=(char) (DoRed | DoGreen | DoBlue);
}
/*
Set highlight color.
*/
pixel->highlight_color.red=(unsigned short) (((double)
pixel->matte_color.red*ScaleQuantumToShort(HighlightModulate))/65535L+
(ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
pixel->highlight_color.green=(unsigned short) (((double)
pixel->matte_color.green*ScaleQuantumToShort(HighlightModulate))/65535L+
(ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
pixel->highlight_color.blue=(unsigned short) (((double)
pixel->matte_color.blue*ScaleQuantumToShort(HighlightModulate))/65535L+
(ScaleQuantumToShort((Quantum) (QuantumRange-HighlightModulate))));
pixel->highlight_color.pixel=XStandardPixel(map_info,&pixel->highlight_color);
pixel->highlight_color.flags=(char) (DoRed | DoGreen | DoBlue);
/*
Set shadow color.
*/
pixel->shadow_color.red=(unsigned short) (((double)
pixel->matte_color.red*ScaleQuantumToShort(ShadowModulate))/65535L);
pixel->shadow_color.green=(unsigned short) (((double)
pixel->matte_color.green*ScaleQuantumToShort(ShadowModulate))/65535L);
pixel->shadow_color.blue=(unsigned short) (((double)
pixel->matte_color.blue*ScaleQuantumToShort(ShadowModulate))/65535L);
pixel->shadow_color.pixel=XStandardPixel(map_info,&pixel->shadow_color);
pixel->shadow_color.flags=(char) (DoRed | DoGreen | DoBlue);
/*
Set depth color.
*/
pixel->depth_color.red=(unsigned short) (((double)
pixel->matte_color.red*ScaleQuantumToShort(DepthModulate))/65535L);
pixel->depth_color.green=(unsigned short) (((double)
pixel->matte_color.green*ScaleQuantumToShort(DepthModulate))/65535L);
pixel->depth_color.blue=(unsigned short) (((double)
pixel->matte_color.blue*ScaleQuantumToShort(DepthModulate))/65535L);
pixel->depth_color.pixel=XStandardPixel(map_info,&pixel->depth_color);
pixel->depth_color.flags=(char) (DoRed | DoGreen | DoBlue);
/*
Set trough color.
*/
pixel->trough_color.red=(unsigned short) (((double)
pixel->matte_color.red*ScaleQuantumToShort(TroughModulate))/65535L);
pixel->trough_color.green=(unsigned short) (((double)
pixel->matte_color.green*ScaleQuantumToShort(TroughModulate))/65535L);
pixel->trough_color.blue=(unsigned short) (((double)
pixel->matte_color.blue*ScaleQuantumToShort(TroughModulate))/65535L);
pixel->trough_color.pixel=XStandardPixel(map_info,&pixel->trough_color);
pixel->trough_color.flags=(char) (DoRed | DoGreen | DoBlue);
/*
Set pen color.
*/
for (i=0; i < MaxNumberPens; i++)
{
(void) XParseColor(display,colormap,(char *) PenColors[i],
&pixel->pen_colors[i]);
status=XParseColor(display,colormap,resource_info->pen_colors[i],
&pixel->pen_colors[i]);
if (status == False)
ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",
resource_info->pen_colors[i]);
pixel->pen_colors[i].pixel=XStandardPixel(map_info,&pixel->pen_colors[i]);
pixel->pen_colors[i].flags=(char) (DoRed | DoGreen | DoBlue);
}
pixel->box_color=pixel->background_color;
pixel->pen_color=pixel->foreground_color;
pixel->box_index=0;
pixel->pen_index=1;
if (image != (Image *) NULL)
{
if ((resource_info->gamma_correct != MagickFalse) &&
(image->gamma != 0.0))
{
GeometryInfo
geometry_info;
MagickStatusType
flags;
/*
Initialize map relative to display and image gamma.
*/
flags=ParseGeometry(resource_info->display_gamma,&geometry_info);
red_gamma=geometry_info.rho;
green_gamma=geometry_info.sigma;
if ((flags & SigmaValue) == 0)
green_gamma=red_gamma;
blue_gamma=geometry_info.xi;
if ((flags & XiValue) == 0)
blue_gamma=red_gamma;
red_gamma*=image->gamma;
green_gamma*=image->gamma;
blue_gamma*=image->gamma;
}
if (image->storage_class == PseudoClass)
{
/*
Initialize pixel array for images of type PseudoClass.
*/
for (i=0; i < (ssize_t) image->colors; i++)
pixel->pixels[i]=XGammaPacket(map_info,image->colormap+i);
for (i=0; i < MaxNumberPens; i++)
pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
pixel->colors+=MaxNumberPens;
}
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X G e t R e s o u r c e C l a s s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetResourceClass() queries the X server for the specified resource name or
% class. If the resource name or class is not defined in the database, the
% supplied default value is returned.
%
% The format of the XGetResourceClass method is:
%
% char *XGetResourceClass(XrmDatabase database,const char *client_name,
% const char *keyword,char *resource_default)
%
% A description of each parameter follows:
%
% o database: Specifies a resource database; returned from
% XrmGetStringDatabase.
%
% o client_name: Specifies the application name used to retrieve resource
% info from the X server database.
%
% o keyword: Specifies the keyword of the value being retrieved.
%
% o resource_default: Specifies the default value to return if the query
% fails to find the specified keyword/class.
%
*/
MagickExport char *XGetResourceClass(XrmDatabase database,
const char *client_name,const char *keyword,char *resource_default)
{
char
resource_class[MagickPathExtent],
resource_name[MagickPathExtent];
static char
*resource_type;
Status
status;
XrmValue
resource_value;
if (database == (XrmDatabase) NULL)
return(resource_default);
*resource_name='\0';
*resource_class='\0';
if (keyword != (char *) NULL)
{
int
c,
k;
/*
Initialize resource keyword and class.
*/
(void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",
client_name,keyword);
c=(int) (*client_name);
if ((c >= XK_a) && (c <= XK_z))
c-=(XK_a-XK_A);
else
if ((c >= XK_agrave) && (c <= XK_odiaeresis))
c-=(XK_agrave-XK_Agrave);
else
if ((c >= XK_oslash) && (c <= XK_thorn))
c-=(XK_oslash-XK_Ooblique);
k=(int) (*keyword);
if ((k >= XK_a) && (k <= XK_z))
k-=(XK_a-XK_A);
else
if ((k >= XK_agrave) && (k <= XK_odiaeresis))
k-=(XK_agrave-XK_Agrave);
else
if ((k >= XK_oslash) && (k <= XK_thorn))
k-=(XK_oslash-XK_Ooblique);
(void) FormatLocaleString(resource_class,MagickPathExtent,"%c%s.%c%s",c,
client_name+1,k,keyword+1);
}
status=XrmGetResource(database,resource_name,resource_class,&resource_type,
&resource_value);
if (status == False)
return(resource_default);
return(resource_value.addr);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X G e t R e s o u r c e D a t a b a s e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetResourceDatabase() creates a new resource database and initializes it.
%
% The format of the XGetResourceDatabase method is:
%
% XrmDatabase XGetResourceDatabase(Display *display,
% const char *client_name)
%
% A description of each parameter follows:
%
% o database: XGetResourceDatabase() returns the database after it is
% initialized.
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o client_name: Specifies the application name used to retrieve resource
% info from the X server database.
%
*/
MagickExport XrmDatabase XGetResourceDatabase(Display *display,
const char *client_name)
{
char
filename[MagickPathExtent];
int
c;
register const char
*p;
XrmDatabase
resource_database,
server_database;
if (display == (Display *) NULL)
return((XrmDatabase) NULL);
assert(client_name != (char *) NULL);
/*
Initialize resource database.
*/
XrmInitialize();
(void) XGetDefault(display,(char *) client_name,"dummy");
resource_database=XrmGetDatabase(display);
/*
Combine application database.
*/
p=client_name+(strlen(client_name)-1);
while ((p > client_name) && (*p != '/'))
p--;
if (*p == '/')
client_name=p+1;
c=(int) (*client_name);
if ((c >= XK_a) && (c <= XK_z))
c-=(XK_a-XK_A);
else
if ((c >= XK_agrave) && (c <= XK_odiaeresis))
c-=(XK_agrave-XK_Agrave);
else
if ((c >= XK_oslash) && (c <= XK_thorn))
c-=(XK_oslash-XK_Ooblique);
#if defined(X11_APPLICATION_PATH)
(void) FormatLocaleString(filename,MagickPathExtent,"%s%c%s",
X11_APPLICATION_PATH,c,client_name+1);
(void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
#endif
if (XResourceManagerString(display) != (char *) NULL)
{
/*
Combine server database.
*/
server_database=XrmGetStringDatabase(XResourceManagerString(display));
XrmCombineDatabase(server_database,&resource_database,MagickFalse);
}
/*
Merge user preferences database.
*/
#if defined(X11_PREFERENCES_PATH)
(void) FormatLocaleString(filename,MagickPathExtent,"%s%src",
X11_PREFERENCES_PATH,client_name);
ExpandFilename(filename);
(void) XrmCombineFileDatabase(filename,&resource_database,MagickFalse);
#endif
return(resource_database);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X G e t R e s o u r c e I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetResourceInfo(image_info,) initializes the ResourceInfo structure.
%
% The format of the XGetResourceInfo method is:
%
% void XGetResourceInfo(const ImageInfo *image_info,XrmDatabase database,
% const char *client_name,XResourceInfo *resource_info)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o database: Specifies a resource database; returned from
% XrmGetStringDatabase.
%
% o client_name: Specifies the application name used to retrieve
% resource info from the X server database.
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
*/
MagickExport void XGetResourceInfo(const ImageInfo *image_info,
XrmDatabase database,const char *client_name,XResourceInfo *resource_info)
{
char
*directory,
*resource_value;
extern const char
BorderColor[],
ForegroundColor[];
/*
Initialize resource info fields.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(resource_info != (XResourceInfo *) NULL);
(void) memset(resource_info,0,sizeof(*resource_info));
resource_info->resource_database=database;
resource_info->image_info=(ImageInfo *) image_info;
(void) SetImageInfoProgressMonitor(resource_info->image_info,
XMagickProgressMonitor,(void *) NULL);
resource_info->quantize_info=CloneQuantizeInfo((QuantizeInfo *) NULL);
resource_info->close_server=MagickTrue;
resource_info->client_name=AcquireString(client_name);
resource_value=XGetResourceClass(database,client_name,"backdrop",
(char *) "False");
resource_info->backdrop=IsStringTrue(resource_value);
resource_info->background_color=XGetResourceInstance(database,client_name,
"background",(char *) "#d6d6d6d6d6d6");
resource_info->border_color=XGetResourceInstance(database,client_name,
"borderColor",BorderColor);
resource_value=XGetResourceClass(database,client_name,"borderWidth",
(char *) "2");
resource_info->border_width=(unsigned int) StringToUnsignedLong(
resource_value);
resource_value=XGetResourceClass(database,client_name,"colormap",
(char *) "shared");
resource_info->colormap=UndefinedColormap;
if (LocaleCompare("private",resource_value) == 0)
resource_info->colormap=PrivateColormap;
if (LocaleCompare("shared",resource_value) == 0)
resource_info->colormap=SharedColormap;
if (resource_info->colormap == UndefinedColormap)
ThrowXWindowException(OptionError,"UnrecognizedColormapType",
resource_value);
resource_value=XGetResourceClass(database,client_name,
"colorRecovery",(char *) "False");
resource_info->color_recovery=IsStringTrue(resource_value);
resource_value=XGetResourceClass(database,client_name,"confirmExit",
(char *) "False");
resource_info->confirm_exit=IsStringTrue(resource_value);
resource_value=XGetResourceClass(database,client_name,"confirmEdit",
(char *) "False");
resource_info->confirm_edit=IsStringTrue(resource_value);
resource_value=XGetResourceClass(database,client_name,"delay",(char *) "1");
resource_info->delay=(unsigned int) StringToUnsignedLong(resource_value);
resource_info->display_gamma=XGetResourceClass(database,client_name,
"displayGamma",(char *) "2.2");
resource_value=XGetResourceClass(database,client_name,"displayWarnings",
(char *) "True");
resource_info->display_warnings=IsStringTrue(resource_value);
resource_info->font=XGetResourceClass(database,client_name,"font",
(char *) NULL);
resource_info->font=XGetResourceClass(database,client_name,"fontList",
resource_info->font);
resource_info->font_name[0]=XGetResourceClass(database,client_name,"font1",
(char *) "fixed");
resource_info->font_name[1]=XGetResourceClass(database,client_name,"font2",
(char *) "variable");
resource_info->font_name[2]=XGetResourceClass(database,client_name,"font3",
(char *) "5x8");
resource_info->font_name[3]=XGetResourceClass(database,client_name,"font4",
(char *) "6x10");
resource_info->font_name[4]=XGetResourceClass(database,client_name,"font5",
(char *) "7x13bold");
resource_info->font_name[5]=XGetResourceClass(database,client_name,"font6",
(char *) "8x13bold");
resource_info->font_name[6]=XGetResourceClass(database,client_name,"font7",
(char *) "9x15bold");
resource_info->font_name[7]=XGetResourceClass(database,client_name,"font8",
(char *) "10x20");
resource_info->font_name[8]=XGetResourceClass(database,client_name,"font9",
(char *) "12x24");
resource_info->font_name[9]=XGetResourceClass(database,client_name,"font0",
(char *) "fixed");
resource_info->font_name[10]=XGetResourceClass(database,client_name,"font0",
(char *) "fixed");
resource_info->foreground_color=XGetResourceInstance(database,client_name,
"foreground",ForegroundColor);
resource_value=XGetResourceClass(database,client_name,"gammaCorrect",
(char *) "False");
resource_info->gamma_correct=IsStringTrue(resource_value);
resource_info->image_geometry=ConstantString(XGetResourceClass(database,
client_name,"geometry",(char *) NULL));
resource_value=XGetResourceClass(database,client_name,"gravity",
(char *) "Center");
resource_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
MagickFalse,resource_value);
directory=getcwd(resource_info->home_directory,MagickPathExtent);
(void) directory;
resource_info->icon_geometry=XGetResourceClass(database,client_name,
"iconGeometry",(char *) NULL);
resource_value=XGetResourceClass(database,client_name,"iconic",
(char *) "False");
resource_info->iconic=IsStringTrue(resource_value);
resource_value=XGetResourceClass(database,client_name,"immutable",
LocaleCompare(client_name,"PerlMagick") == 0 ? (char *) "True" :
(char *) "False");
resource_info->immutable=IsStringTrue(resource_value);
resource_value=XGetResourceClass(database,client_name,"magnify",
(char *) "3");
resource_info->magnify=(unsigned int) StringToUnsignedLong(resource_value);
resource_info->map_type=XGetResourceClass(database,client_name,"map",
(char *) NULL);
resource_info->matte_color=XGetResourceInstance(database,client_name,
"mattecolor",(char *) NULL);
resource_info->name=ConstantString(XGetResourceClass(database,client_name,
"name",(char *) NULL));
resource_info->pen_colors[0]=XGetResourceClass(database,client_name,"pen1",
(char *) "black");
resource_info->pen_colors[1]=XGetResourceClass(database,client_name,"pen2",
(char *) "blue");
resource_info->pen_colors[2]=XGetResourceClass(database,client_name,"pen3",
(char *) "cyan");
resource_info->pen_colors[3]=XGetResourceClass(database,client_name,"pen4",
(char *) "green");
resource_info->pen_colors[4]=XGetResourceClass(database,client_name,"pen5",
(char *) "gray");
resource_info->pen_colors[5]=XGetResourceClass(database,client_name,"pen6",
(char *) "red");
resource_info->pen_colors[6]=XGetResourceClass(database,client_name,"pen7",
(char *) "magenta");
resource_info->pen_colors[7]=XGetResourceClass(database,client_name,"pen8",
(char *) "yellow");
resource_info->pen_colors[8]=XGetResourceClass(database,client_name,"pen9",
(char *) "white");
resource_info->pen_colors[9]=XGetResourceClass(database,client_name,"pen0",
(char *) "gray");
resource_info->pen_colors[10]=XGetResourceClass(database,client_name,"pen0",
(char *) "gray");
resource_value=XGetResourceClass(database,client_name,"pause",(char *) "0");
resource_info->pause=(unsigned int) StringToUnsignedLong(resource_value);
resource_value=XGetResourceClass(database,client_name,"quantum",(char *) "1");
resource_info->quantum=StringToLong(resource_value);
resource_info->text_font=XGetResourceClass(database,client_name,(char *)
"font",(char *) "fixed");
resource_info->text_font=XGetResourceClass(database,client_name,
"textFontList",resource_info->text_font);
resource_info->title=XGetResourceClass(database,client_name,"title",
(char *) NULL);
resource_value=XGetResourceClass(database,client_name,"undoCache",
(char *) "256");
resource_info->undo_cache=(unsigned int) StringToUnsignedLong(resource_value);
resource_value=XGetResourceClass(database,client_name,"update",
(char *) "False");
resource_info->update=IsStringTrue(resource_value);
resource_value=XGetResourceClass(database,client_name,"usePixmap",
(char *) "True");
resource_info->use_pixmap=IsStringTrue(resource_value);
resource_value=XGetResourceClass(database,client_name,"sharedMemory",
(char *) "True");
resource_info->use_shared_memory=IsStringTrue(resource_value);
resource_info->visual_type=XGetResourceClass(database,client_name,"visual",
(char *) NULL);
resource_info->window_group=XGetResourceClass(database,client_name,
"windowGroup",(char *) NULL);
resource_info->window_id=XGetResourceClass(database,client_name,"window",
(char *) NULL);
resource_info->write_filename=XGetResourceClass(database,client_name,
"writeFilename",(char *) NULL);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X G e t R e s o u r c e I n s t a n c e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetResourceInstance() queries the X server for the specified resource name.
% If the resource name is not defined in the database, the supplied default
% value is returned.
%
% The format of the XGetResourceInstance method is:
%
% char *XGetResourceInstance(XrmDatabase database,const char *client_name,
% const char *keyword,const char *resource_default)
%
% A description of each parameter follows:
%
% o database: Specifies a resource database; returned from
% XrmGetStringDatabase.
%
% o client_name: Specifies the application name used to retrieve
% resource info from the X server database.
%
% o keyword: Specifies the keyword of the value being retrieved.
%
% o resource_default: Specifies the default value to return if the query
% fails to find the specified keyword/class.
%
*/
MagickExport char *XGetResourceInstance(XrmDatabase database,
const char *client_name,const char *keyword,const char *resource_default)
{
char
*resource_type,
resource_name[MagickPathExtent];
Status
status;
XrmValue
resource_value;
if (database == (XrmDatabase) NULL)
return((char *) resource_default);
*resource_name='\0';
if (keyword != (char *) NULL)
(void) FormatLocaleString(resource_name,MagickPathExtent,"%s.%s",client_name,
keyword);
status=XrmGetResource(database,resource_name,"ImageMagick",&resource_type,
&resource_value);
if (status == False)
return((char *) resource_default);
return(resource_value.addr);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X G e t S c r e e n D e n s i t y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetScreenDensity() returns the density of the X server screen in
% dots-per-inch.
%
% The format of the XGetScreenDensity method is:
%
% char *XGetScreenDensity(Display *display)
%
% A description of each parameter follows:
%
% o density: XGetScreenDensity() returns the density of the X screen in
% dots-per-inch.
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
*/
MagickExport char *XGetScreenDensity(Display *display)
{
char
density[MagickPathExtent];
double
x_density,
y_density;
/*
Set density as determined by screen size.
*/
x_density=((((double) DisplayWidth(display,XDefaultScreen(display)))*25.4)/
((double) DisplayWidthMM(display,XDefaultScreen(display))));
y_density=((((double) DisplayHeight(display,XDefaultScreen(display)))*25.4)/
((double) DisplayHeightMM(display,XDefaultScreen(display))));
(void) FormatLocaleString(density,MagickPathExtent,"%gx%g",x_density,
y_density);
return(GetPageGeometry(density));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X G e t S u b w i n d o w %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetSubwindow() returns the subwindow of a window chosen the user with the
% pointer and a button press.
%
% The format of the XGetSubwindow method is:
%
% Window XGetSubwindow(Display *display,Window window,int x,int y)
%
% A description of each parameter follows:
%
% o subwindow: XGetSubwindow() returns NULL if no subwindow is found
% otherwise the subwindow is returned.
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o window: Specifies a pointer to a Window.
%
% o x: the x coordinate of the pointer relative to the origin of the
% window.
%
% o y: the y coordinate of the pointer relative to the origin of the
% window.
%
*/
static Window XGetSubwindow(Display *display,Window window,int x,int y)
{
int
x_offset,
y_offset;
Status
status;
Window
source_window,
target_window;
assert(display != (Display *) NULL);
source_window=XRootWindow(display,XDefaultScreen(display));
if (window == (Window) NULL)
return(source_window);
target_window=window;
for ( ; ; )
{
status=XTranslateCoordinates(display,source_window,window,x,y,
&x_offset,&y_offset,&target_window);
if (status != True)
break;
if (target_window == (Window) NULL)
break;
source_window=window;
window=target_window;
x=x_offset;
y=y_offset;
}
if (target_window == (Window) NULL)
target_window=window;
return(target_window);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X G e t W i n d o w C o l o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetWindowColor() returns the color of a pixel interactively chosen from the
% X server.
%
% The format of the XGetWindowColor method is:
%
% MagickBooleanType XGetWindowColor(Display *display,XWindows *windows,
% char *name,ExceptionInfo *exception)
%
% 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.
%
% o name: the name of the color if found in the X Color Database is
% returned in this character string.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickPrivate MagickBooleanType XGetWindowColor(Display *display,
XWindows *windows,char *name,ExceptionInfo *exception)
{
int
x,
y;
PixelInfo
pixel;
RectangleInfo
crop_info;
Status
status;
Window
child,
client_window,
root_window,
target_window;
XColor
color;
XImage
*ximage;
XWindowAttributes
window_attributes;
/*
Choose a pixel from the X server.
*/
assert(display != (Display *) NULL);
assert(name != (char *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
*name='\0';
target_window=XSelectWindow(display,&crop_info);
if (target_window == (Window) NULL)
return(MagickFalse);
root_window=XRootWindow(display,XDefaultScreen(display));
client_window=target_window;
if (target_window != root_window)
{
unsigned int
d;
/*
Get client window.
*/
status=XGetGeometry(display,target_window,&root_window,&x,&x,&d,&d,&d,&d);
if (status != False)
{
client_window=XClientWindow(display,target_window);
target_window=client_window;
}
}
/*
Verify window is viewable.
*/
status=XGetWindowAttributes(display,target_window,&window_attributes);
if ((status == False) || (window_attributes.map_state != IsViewable))
return(MagickFalse);
/*
Get window X image.
*/
(void) XTranslateCoordinates(display,root_window,target_window,
(int) crop_info.x,(int) crop_info.y,&x,&y,&child);
ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
if (ximage == (XImage *) NULL)
return(MagickFalse);
color.pixel=XGetPixel(ximage,0,0);
XDestroyImage(ximage);
/*
Match color against the color database.
*/
(void) XQueryColor(display,window_attributes.colormap,&color);
pixel.red=(double) ScaleShortToQuantum(color.red);
pixel.green=(double) ScaleShortToQuantum(color.green);
pixel.blue=(double) ScaleShortToQuantum(color.blue);
pixel.alpha=(MagickRealType) OpaqueAlpha;
(void) QueryColorname(windows->image.image,&pixel,X11Compliance,name,
exception);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X G e t W i n d o w I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetWindowImage() reads an image from the target X window and returns it.
% XGetWindowImage() optionally descends the window hierarchy and overlays the
% target image with each child image in an optimized fashion. Any child
% window that have the same visual, colormap, and are contained by its parent
% are exempted.
%
% The format of the XGetWindowImage method is:
%
% Image *XGetWindowImage(Display *display,const Window window,
% const unsigned int borders,const unsigned int level,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o window: Specifies the window to obtain the image from.
%
% o borders: Specifies whether borders pixels are to be saved with
% the image.
%
% o level: Specifies an unsigned integer representing the level of
% decent in the window hierarchy. This value must be zero or one on
% the initial call to XGetWindowImage. A value of zero returns after
% one call. A value of one causes the function to descend the window
% hierarchy and overlay the target image with each subwindow image.
%
% o exception: return any errors or warnings in this structure.
%
*/
static Image *XGetWindowImage(Display *display,const Window window,
const unsigned int borders,const unsigned int level,ExceptionInfo *exception)
{
typedef struct _ColormapInfo
{
Colormap
colormap;
XColor
*colors;
struct _ColormapInfo
*next;
} ColormapInfo;
typedef struct _WindowInfo
{
Window
window,
parent;
Visual
*visual;
Colormap
colormap;
XSegment
bounds;
RectangleInfo
crop_info;
} WindowInfo;
int
display_height,
display_width,
id,
x_offset,
y_offset;
Quantum
index;
RectangleInfo
crop_info;
register int
i;
static ColormapInfo
*colormap_info = (ColormapInfo *) NULL;
static int
max_windows = 0,
number_windows = 0;
static WindowInfo
*window_info;
Status
status;
Window
child,
root_window;
XWindowAttributes
window_attributes;
/*
Verify window is viewable.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
status=XGetWindowAttributes(display,window,&window_attributes);
if ((status == False) || (window_attributes.map_state != IsViewable))
return((Image *) NULL);
/*
Cropping rectangle is relative to root window.
*/
root_window=XRootWindow(display,XDefaultScreen(display));
(void) XTranslateCoordinates(display,window,root_window,0,0,&x_offset,
&y_offset,&child);
crop_info.x=(ssize_t) x_offset;
crop_info.y=(ssize_t) y_offset;
crop_info.width=(size_t) window_attributes.width;
crop_info.height=(size_t) window_attributes.height;
if (borders != MagickFalse)
{
/*
Include border in image.
*/
crop_info.x-=(ssize_t) window_attributes.border_width;
crop_info.y-=(ssize_t) window_attributes.border_width;
crop_info.width+=(size_t) (window_attributes.border_width << 1);
crop_info.height+=(size_t) (window_attributes.border_width << 1);
}
/*
Crop to root window.
*/
if (crop_info.x < 0)
{
crop_info.width+=crop_info.x;
crop_info.x=0;
}
if (crop_info.y < 0)
{
crop_info.height+=crop_info.y;
crop_info.y=0;
}
display_width=XDisplayWidth(display,XDefaultScreen(display));
if ((int) (crop_info.x+crop_info.width) > display_width)
crop_info.width=(size_t) (display_width-crop_info.x);
display_height=XDisplayHeight(display,XDefaultScreen(display));
if ((int) (crop_info.y+crop_info.height) > display_height)
crop_info.height=(size_t) (display_height-crop_info.y);
/*
Initialize window info attributes.
*/
if (number_windows >= max_windows)
{
/*
Allocate or resize window info buffer.
*/
max_windows+=1024;
if (window_info == (WindowInfo *) NULL)
window_info=(WindowInfo *) AcquireQuantumMemory((size_t) max_windows,
sizeof(*window_info));
else
window_info=(WindowInfo *) ResizeQuantumMemory(window_info,(size_t)
max_windows,sizeof(*window_info));
}
if (window_info == (WindowInfo *) NULL)
{
ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed","...");
return((Image *) NULL);
}
id=number_windows++;
window_info[id].window=window;
window_info[id].visual=window_attributes.visual;
window_info[id].colormap=window_attributes.colormap;
window_info[id].bounds.x1=(short) crop_info.x;
window_info[id].bounds.y1=(short) crop_info.y;
window_info[id].bounds.x2=(short) (crop_info.x+(int) crop_info.width-1);
window_info[id].bounds.y2=(short) (crop_info.y+(int) crop_info.height-1);
crop_info.x-=x_offset;
crop_info.y-=y_offset;
window_info[id].crop_info=crop_info;
if (level != 0)
{
unsigned int
number_children;
Window
*children;
/*
Descend the window hierarchy.
*/
status=XQueryTree(display,window,&root_window,&window_info[id].parent,
&children,&number_children);
for (i=0; i < id; i++)
if ((window_info[i].window == window_info[id].parent) &&
(window_info[i].visual == window_info[id].visual) &&
(window_info[i].colormap == window_info[id].colormap))
{
if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) ||
(window_info[id].bounds.x2 > window_info[i].bounds.x2) ||
(window_info[id].bounds.y1 < window_info[i].bounds.y1) ||
(window_info[id].bounds.y2 > window_info[i].bounds.y2))
{
/*
Eliminate windows not circumscribed by their parent.
*/
number_windows--;
break;
}
}
if ((status == True) && (number_children != 0))
{
for (i=0; i < (int) number_children; i++)
(void) XGetWindowImage(display,children[i],MagickFalse,level+1,
exception);
(void) XFree((void *) children);
}
}
if (level <= 1)
{
CacheView
*composite_view;
ColormapInfo
*next;
Image
*composite_image,
*image;
int
y;
MagickBooleanType
import;
register int
j,
x;
register Quantum
*magick_restrict q;
register size_t
pixel;
unsigned int
number_colors;
XColor
*colors;
XImage
*ximage;
/*
Get X image for each window in the list.
*/
image=NewImageList();
for (id=0; id < number_windows; id++)
{
/*
Does target window intersect top level window?
*/
import=((window_info[id].bounds.x2 >= window_info[0].bounds.x1) &&
(window_info[id].bounds.x1 <= window_info[0].bounds.x2) &&
(window_info[id].bounds.y2 >= window_info[0].bounds.y1) &&
(window_info[id].bounds.y1 <= window_info[0].bounds.y2)) ?
MagickTrue : MagickFalse;
/*
Is target window contained by another window with the same colormap?
*/
for (j=0; j < id; j++)
if ((window_info[id].visual == window_info[j].visual) &&
(window_info[id].colormap == window_info[j].colormap))
{
if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) &&
(window_info[id].bounds.x2 <= window_info[j].bounds.x2) &&
(window_info[id].bounds.y1 >= window_info[j].bounds.y1) &&
(window_info[id].bounds.y2 <= window_info[j].bounds.y2))
import=MagickFalse;
}
if (import == MagickFalse)
continue;
/*
Get X image.
*/
ximage=XGetImage(display,window_info[id].window,(int)
window_info[id].crop_info.x,(int) window_info[id].crop_info.y,
(unsigned int) window_info[id].crop_info.width,(unsigned int)
window_info[id].crop_info.height,AllPlanes,ZPixmap);
if (ximage == (XImage *) NULL)
continue;
/*
Initialize window colormap.
*/
number_colors=0;
colors=(XColor *) NULL;
if (window_info[id].colormap != (Colormap) NULL)
{
ColormapInfo
*p;
/*
Search colormap list for window colormap.
*/
number_colors=(unsigned int) window_info[id].visual->map_entries;
for (p=colormap_info; p != (ColormapInfo *) NULL; p=p->next)
if (p->colormap == window_info[id].colormap)
break;
if (p == (ColormapInfo *) NULL)
{
/*
Get the window colormap.
*/
colors=(XColor *) AcquireQuantumMemory(number_colors,
sizeof(*colors));
if (colors == (XColor *) NULL)
{
XDestroyImage(ximage);
return((Image *) NULL);
}
if ((window_info[id].visual->klass != DirectColor) &&
(window_info[id].visual->klass != TrueColor))
for (i=0; i < (int) number_colors; i++)
{
colors[i].pixel=(size_t) i;
colors[i].pad='\0';
}
else
{
size_t
blue,
blue_bit,
green,
green_bit,
red,
red_bit;
/*
DirectColor or TrueColor visual.
*/
red=0;
green=0;
blue=0;
red_bit=window_info[id].visual->red_mask &
(~(window_info[id].visual->red_mask)+1);
green_bit=window_info[id].visual->green_mask &
(~(window_info[id].visual->green_mask)+1);
blue_bit=window_info[id].visual->blue_mask &
(~(window_info[id].visual->blue_mask)+1);
for (i=0; i < (int) number_colors; i++)
{
colors[i].pixel=(unsigned long) (red | green | blue);
colors[i].pad='\0';
red+=red_bit;
if (red > window_info[id].visual->red_mask)
red=0;
green+=green_bit;
if (green > window_info[id].visual->green_mask)
green=0;
blue+=blue_bit;
if (blue > window_info[id].visual->blue_mask)
blue=0;
}
}
(void) XQueryColors(display,window_info[id].colormap,colors,
(int) number_colors);
/*
Append colormap to colormap list.
*/
p=(ColormapInfo *) AcquireMagickMemory(sizeof(*p));
if (p == (ColormapInfo *) NULL)
return((Image *) NULL);
p->colormap=window_info[id].colormap;
p->colors=colors;
p->next=colormap_info;
colormap_info=p;
}
colors=p->colors;
}
/*
Allocate image structure.
*/
composite_image=AcquireImage((ImageInfo *) NULL,exception);
if (composite_image == (Image *) NULL)
{
XDestroyImage(ximage);
return((Image *) NULL);
}
/*
Convert X image to MIFF format.
*/
if ((window_info[id].visual->klass != TrueColor) &&
(window_info[id].visual->klass != DirectColor))
composite_image->storage_class=PseudoClass;
composite_image->columns=(size_t) ximage->width;
composite_image->rows=(size_t) ximage->height;
composite_view=AcquireAuthenticCacheView(composite_image,exception);
switch (composite_image->storage_class)
{
case DirectClass:
default:
{
register size_t
color,
index;
size_t
blue_mask,
blue_shift,
green_mask,
green_shift,
red_mask,
red_shift;
/*
Determine shift and mask for red, green, and blue.
*/
red_mask=window_info[id].visual->red_mask;
red_shift=0;
while ((red_mask != 0) && ((red_mask & 0x01) == 0))
{
red_mask>>=1;
red_shift++;
}
green_mask=window_info[id].visual->green_mask;
green_shift=0;
while ((green_mask != 0) && ((green_mask & 0x01) == 0))
{
green_mask>>=1;
green_shift++;
}
blue_mask=window_info[id].visual->blue_mask;
blue_shift=0;
while ((blue_mask != 0) && ((blue_mask & 0x01) == 0))
{
blue_mask>>=1;
blue_shift++;
}
/*
Convert X image to DirectClass packets.
*/
if ((number_colors != 0) &&
(window_info[id].visual->klass == DirectColor))
for (y=0; y < (int) composite_image->rows; y++)
{
q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
composite_image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
for (x=0; x < (int) composite_image->columns; x++)
{
pixel=XGetPixel(ximage,x,y);
index=(pixel >> red_shift) & red_mask;
SetPixelRed(composite_image,
ScaleShortToQuantum(colors[index].red),q);
index=(pixel >> green_shift) & green_mask;
SetPixelGreen(composite_image,
ScaleShortToQuantum(colors[index].green),q);
index=(pixel >> blue_shift) & blue_mask;
SetPixelBlue(composite_image,
ScaleShortToQuantum(colors[index].blue),q);
q+=GetPixelChannels(composite_image);
}
status=SyncCacheViewAuthenticPixels(composite_view,exception);
if (status == MagickFalse)
break;
}
else
for (y=0; y < (int) composite_image->rows; y++)
{
q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
composite_image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
for (x=0; x < (int) composite_image->columns; x++)
{
pixel=XGetPixel(ximage,x,y);
color=(pixel >> red_shift) & red_mask;
if (red_mask != 0)
color=(65535UL*color)/red_mask;
SetPixelRed(composite_image,ScaleShortToQuantum(
(unsigned short) color),q);
color=(pixel >> green_shift) & green_mask;
if (green_mask != 0)
color=(65535UL*color)/green_mask;
SetPixelGreen(composite_image,ScaleShortToQuantum(
(unsigned short) color),q);
color=(pixel >> blue_shift) & blue_mask;
if (blue_mask != 0)
color=(65535UL*color)/blue_mask;
SetPixelBlue(composite_image,ScaleShortToQuantum(
(unsigned short) color),q);
q+=GetPixelChannels(composite_image);
}
status=SyncCacheViewAuthenticPixels(composite_view,exception);
if (status == MagickFalse)
break;
}
break;
}
case PseudoClass:
{
/*
Create colormap.
*/
status=AcquireImageColormap(composite_image,number_colors,
exception);
if (status == MagickFalse)
{
XDestroyImage(ximage);
composite_image=DestroyImage(composite_image);
return((Image *) NULL);
}
for (i=0; i < (int) composite_image->colors; i++)
{
composite_image->colormap[colors[i].pixel].red=(double)
ScaleShortToQuantum(colors[i].red);
composite_image->colormap[colors[i].pixel].green=(double)
ScaleShortToQuantum(colors[i].green);
composite_image->colormap[colors[i].pixel].blue=(double)
ScaleShortToQuantum(colors[i].blue);
}
/*
Convert X image to PseudoClass packets.
*/
for (y=0; y < (int) composite_image->rows; y++)
{
q=QueueCacheViewAuthenticPixels(composite_view,0,(ssize_t) y,
composite_image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
for (x=0; x < (int) composite_image->columns; x++)
{
index=(Quantum) XGetPixel(ximage,x,y);
SetPixelIndex(composite_image,index,q);
SetPixelViaPixelInfo(composite_image,
composite_image->colormap+(ssize_t) index,q);
q+=GetPixelChannels(composite_image);
}
status=SyncCacheViewAuthenticPixels(composite_view,exception);
if (status == MagickFalse)
break;
}
break;
}
}
composite_view=DestroyCacheView(composite_view);
XDestroyImage(ximage);
if (image == (Image *) NULL)
{
image=composite_image;
continue;
}
/*
Composite any children in back-to-front order.
*/
(void) XTranslateCoordinates(display,window_info[id].window,window,0,0,
&x_offset,&y_offset,&child);
x_offset-=(int) crop_info.x;
if (x_offset < 0)
x_offset=0;
y_offset-=(int) crop_info.y;
if (y_offset < 0)
y_offset=0;
(void) CompositeImage(image,composite_image,CopyCompositeOp,MagickTrue,
(ssize_t) x_offset,(ssize_t) y_offset,exception);
composite_image=DestroyImage(composite_image);
}
/*
Relinquish resources.
*/
while (colormap_info != (ColormapInfo *) NULL)
{
next=colormap_info->next;
colormap_info->colors=(XColor *) RelinquishMagickMemory(
colormap_info->colors);
colormap_info=(ColormapInfo *) RelinquishMagickMemory(colormap_info);
colormap_info=next;
}
/*
Relinquish resources and restore initial state.
*/
window_info=(WindowInfo *) RelinquishMagickMemory(window_info);
max_windows=0;
number_windows=0;
colormap_info=(ColormapInfo *) NULL;
return(image);
}
return((Image *) NULL);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X G e t W i n d o w I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetWindowInfo() initializes the XWindowInfo structure.
%
% The format of the XGetWindowInfo method is:
%
% void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
% XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
% XResourceInfo *resource_info,XWindowInfo *window)
% resource_info,window)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
% returned from XGetVisualInfo.
%
% o map_info: If map_type is specified, this structure is initialized
% with info from the Standard Colormap.
%
% o pixel: Specifies a pointer to a XPixelInfo structure.
%
% o font_info: Specifies a pointer to a XFontStruct structure.
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
*/
MagickPrivate void XGetWindowInfo(Display *display,XVisualInfo *visual_info,
XStandardColormap *map_info,XPixelInfo *pixel,XFontStruct *font_info,
XResourceInfo *resource_info,XWindowInfo *window)
{
/*
Initialize window info.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(visual_info != (XVisualInfo *) NULL);
assert(map_info != (XStandardColormap *) NULL);
assert(pixel != (XPixelInfo *) NULL);
assert(resource_info != (XResourceInfo *) NULL);
assert(window != (XWindowInfo *) NULL);
if (window->id != (Window) NULL)
{
if (window->cursor != (Cursor) NULL)
(void) XFreeCursor(display,window->cursor);
if (window->busy_cursor != (Cursor) NULL)
(void) XFreeCursor(display,window->busy_cursor);
if (window->highlight_stipple != (Pixmap) NULL)
(void) XFreePixmap(display,window->highlight_stipple);
if (window->shadow_stipple != (Pixmap) NULL)
(void) XFreePixmap(display,window->shadow_stipple);
if (window->name == (char *) NULL)
window->name=AcquireString("");
if (window->icon_name == (char *) NULL)
window->icon_name=AcquireString("");
}
else
{
/*
Initialize these attributes just once.
*/
window->id=(Window) NULL;
if (window->name == (char *) NULL)
window->name=AcquireString("");
if (window->icon_name == (char *) NULL)
window->icon_name=AcquireString("");
window->x=XDisplayWidth(display,visual_info->screen) >> 1;
window->y=XDisplayWidth(display,visual_info->screen) >> 1;
window->ximage=(XImage *) NULL;
window->matte_image=(XImage *) NULL;
window->pixmap=(Pixmap) NULL;
window->matte_pixmap=(Pixmap) NULL;
window->mapped=MagickFalse;
window->stasis=MagickFalse;
window->shared_memory=MagickTrue;
window->segment_info=(void *) NULL;
#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
{
XShmSegmentInfo
*segment_info;
if (window->segment_info == (void *) NULL)
window->segment_info=AcquireCriticalMemory(2*sizeof(*segment_info));
segment_info=(XShmSegmentInfo *) window->segment_info;
segment_info[0].shmid=(-1);
segment_info[0].shmaddr=(char *) NULL;
segment_info[1].shmid=(-1);
segment_info[1].shmaddr=(char *) NULL;
}
#endif
}
/*
Initialize these attributes every time function is called.
*/
window->screen=visual_info->screen;
window->root=XRootWindow(display,visual_info->screen);
window->visual=visual_info->visual;
window->storage_class=(unsigned int) visual_info->klass;
window->depth=(unsigned int) visual_info->depth;
window->visual_info=visual_info;
window->map_info=map_info;
window->pixel_info=pixel;
window->font_info=font_info;
window->cursor=XCreateFontCursor(display,XC_left_ptr);
window->busy_cursor=XCreateFontCursor(display,XC_watch);
window->geometry=(char *) NULL;
window->icon_geometry=(char *) NULL;
if (resource_info->icon_geometry != (char *) NULL)
(void) CloneString(&window->icon_geometry,resource_info->icon_geometry);
window->crop_geometry=(char *) NULL;
window->flags=(size_t) PSize;
window->width=1;
window->height=1;
window->min_width=1;
window->min_height=1;
window->width_inc=1;
window->height_inc=1;
window->border_width=resource_info->border_width;
window->annotate_context=pixel->annotate_context;
window->highlight_context=pixel->highlight_context;
window->widget_context=pixel->widget_context;
window->shadow_stipple=(Pixmap) NULL;
window->highlight_stipple=(Pixmap) NULL;
window->use_pixmap=MagickTrue;
window->immutable=MagickFalse;
window->shape=MagickFalse;
window->data=0;
window->mask=(int) (CWBackingStore | CWBackPixel | CWBackPixmap |
CWBitGravity | CWBorderPixel | CWColormap | CWCursor | CWDontPropagate |
CWEventMask | CWOverrideRedirect | CWSaveUnder | CWWinGravity);
window->attributes.background_pixel=pixel->background_color.pixel;
window->attributes.background_pixmap=(Pixmap) NULL;
window->attributes.bit_gravity=ForgetGravity;
window->attributes.backing_store=WhenMapped;
window->attributes.save_under=MagickTrue;
window->attributes.border_pixel=pixel->border_color.pixel;
window->attributes.colormap=map_info->colormap;
window->attributes.cursor=window->cursor;
window->attributes.do_not_propagate_mask=NoEventMask;
window->attributes.event_mask=NoEventMask;
window->attributes.override_redirect=MagickFalse;
window->attributes.win_gravity=NorthWestGravity;
window->orphan=MagickFalse;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X H i g h l i g h t E l l i p s e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XHighlightEllipse() puts a border on the X server around a region defined by
% highlight_info.
%
% The format of the XHighlightEllipse method is:
%
% void XHighlightEllipse(Display *display,Window window,
% GC annotate_context,const RectangleInfo *highlight_info)
%
% 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.
%
% o annotate_context: Specifies a pointer to a GC structure.
%
% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
% contains the extents of any highlighting rectangle.
%
*/
MagickPrivate void XHighlightEllipse(Display *display,Window window,
GC annotate_context,const RectangleInfo *highlight_info)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(window != (Window) NULL);
assert(annotate_context != (GC) NULL);
assert(highlight_info != (RectangleInfo *) NULL);
if ((highlight_info->width < 4) || (highlight_info->height < 4))
return;
(void) XDrawArc(display,window,annotate_context,(int) highlight_info->x,
(int) highlight_info->y,(unsigned int) highlight_info->width-1,
(unsigned int) highlight_info->height-1,0,360*64);
(void) XDrawArc(display,window,annotate_context,(int) highlight_info->x+1,
(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
(unsigned int) highlight_info->height-3,0,360*64);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X H i g h l i g h t L i n e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XHighlightLine() puts a border on the X server around a region defined by
% highlight_info.
%
% The format of the XHighlightLine method is:
%
% void XHighlightLine(Display *display,Window window,GC annotate_context,
% const XSegment *highlight_info)
%
% 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.
%
% o annotate_context: Specifies a pointer to a GC structure.
%
% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
% contains the extents of any highlighting rectangle.
%
*/
MagickPrivate void XHighlightLine(Display *display,Window window,
GC annotate_context,const XSegment *highlight_info)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(window != (Window) NULL);
assert(annotate_context != (GC) NULL);
assert(highlight_info != (XSegment *) NULL);
(void) XDrawLine(display,window,annotate_context,highlight_info->x1,
highlight_info->y1,highlight_info->x2,highlight_info->y2);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X H i g h l i g h t R e c t a n g l e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XHighlightRectangle() puts a border on the X server around a region defined
% by highlight_info.
%
% The format of the XHighlightRectangle method is:
%
% void XHighlightRectangle(Display *display,Window window,
% GC annotate_context,const RectangleInfo *highlight_info)
%
% 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.
%
% o annotate_context: Specifies a pointer to a GC structure.
%
% o highlight_info: Specifies a pointer to a RectangleInfo structure. It
% contains the extents of any highlighting rectangle.
%
*/
MagickPrivate void XHighlightRectangle(Display *display,Window window,
GC annotate_context,const RectangleInfo *highlight_info)
{
assert(display != (Display *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(window != (Window) NULL);
assert(annotate_context != (GC) NULL);
assert(highlight_info != (RectangleInfo *) NULL);
if ((highlight_info->width < 4) || (highlight_info->height < 4))
return;
(void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x,
(int) highlight_info->y,(unsigned int) highlight_info->width-1,
(unsigned int) highlight_info->height-1);
(void) XDrawRectangle(display,window,annotate_context,(int) highlight_info->x+
1,(int) highlight_info->y+1,(unsigned int) highlight_info->width-3,
(unsigned int) highlight_info->height-3);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X I m p o r t I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XImportImage() reads an image from an X window.
%
% The format of the XImportImage method is:
%
% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o ximage_info: Specifies a pointer to an XImportInfo structure.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport Image *XImportImage(const ImageInfo *image_info,
XImportInfo *ximage_info,ExceptionInfo *exception)
{
Colormap
*colormaps;
Display
*display;
Image
*image;
int
number_colormaps,
number_windows,
x;
RectangleInfo
crop_info;
Status
status;
Window
*children,
client,
prior_target,
root,
target;
XTextProperty
window_name;
/*
Open X server connection.
*/
assert(image_info != (const ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(ximage_info != (XImportInfo *) NULL);
display=XOpenDisplay(image_info->server_name);
if (display == (Display *) NULL)
{
ThrowXWindowException(XServerError,"UnableToOpenXServer",
XDisplayName(image_info->server_name));
return((Image *) NULL);
}
/*
Set our forgiving exception handler.
*/
(void) XSetErrorHandler(XError);
/*
Select target window.
*/
crop_info.x=0;
crop_info.y=0;
crop_info.width=0;
crop_info.height=0;
root=XRootWindow(display,XDefaultScreen(display));
target=(Window) NULL;
if (*image_info->filename != '\0')
{
if (LocaleCompare(image_info->filename,"root") == 0)
target=root;
else
{
/*
Select window by ID or name.
*/
if (isdigit((int) ((unsigned char) *image_info->filename)) != 0)
target=XWindowByID(display,root,(Window)
strtol(image_info->filename,(char **) NULL,0));
if (target == (Window) NULL)
target=XWindowByName(display,root,image_info->filename);
if (target == (Window) NULL)
ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
image_info->filename);
}
}
/*
If target window is not defined, interactively select one.
*/
prior_target=target;
if (target == (Window) NULL)
target=XSelectWindow(display,&crop_info);
if (target == (Window) NULL)
ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
image_info->filename);
client=target; /* obsolete */
if (target != root)
{
unsigned int
d;
status=XGetGeometry(display,target,&root,&x,&x,&d,&d,&d,&d);
if (status != False)
{
for ( ; ; )
{
Window
parent;
/*
Find window manager frame.
*/
status=XQueryTree(display,target,&root,&parent,&children,&d);
if ((status != False) && (children != (Window *) NULL))
(void) XFree((char *) children);
if ((status == False) || (parent == (Window) NULL) ||
(parent == root))
break;
target=parent;
}
/*
Get client window.
*/
client=XClientWindow(display,target);
if (ximage_info->frame == MagickFalse)
target=client;
if ((ximage_info->frame == MagickFalse) &&
(prior_target != MagickFalse))
target=prior_target;
}
}
if (ximage_info->screen)
{
int
y;
Window
child;
XWindowAttributes
window_attributes;
/*
Obtain window image directly from screen.
*/
status=XGetWindowAttributes(display,target,&window_attributes);
if (status == False)
{
ThrowXWindowException(XServerError,"UnableToReadXWindowAttributes",
image_info->filename);
(void) XCloseDisplay(display);
return((Image *) NULL);
}
(void) XTranslateCoordinates(display,target,root,0,0,&x,&y,&child);
crop_info.x=(ssize_t) x;
crop_info.y=(ssize_t) y;
crop_info.width=(size_t) window_attributes.width;
crop_info.height=(size_t) window_attributes.height;
if (ximage_info->borders != 0)
{
/*
Include border in image.
*/
crop_info.x-=window_attributes.border_width;
crop_info.y-=window_attributes.border_width;
crop_info.width+=window_attributes.border_width << 1;
crop_info.height+=window_attributes.border_width << 1;
}
target=root;
}
/*
If WM_COLORMAP_WINDOWS property is set or multiple colormaps, descend.
*/
number_windows=0;
status=XGetWMColormapWindows(display,target,&children,&number_windows);
if ((status == True) && (number_windows > 0))
{
ximage_info->descend=MagickTrue;
(void) XFree ((char *) children);
}
colormaps=XListInstalledColormaps(display,target,&number_colormaps);
if (number_colormaps > 0)
{
if (number_colormaps > 1)
ximage_info->descend=MagickTrue;
(void) XFree((char *) colormaps);
}
/*
Alert the user not to alter the screen.
*/
if (ximage_info->silent == MagickFalse)
(void) XBell(display,0);
/*
Get image by window id.
*/
(void) XGrabServer(display);
image=XGetWindowImage(display,target,ximage_info->borders,
ximage_info->descend ? 1U : 0U,exception);
(void) XUngrabServer(display);
if (image == (Image *) NULL)
ThrowXWindowException(XServerError,"UnableToReadXWindowImage",
image_info->filename)
else
{
(void) CopyMagickString(image->filename,image_info->filename,
MagickPathExtent);
if ((crop_info.width != 0) && (crop_info.height != 0))
{
Image
*clone_image,
*crop_image;
/*
Crop image as defined by the cropping rectangle.
*/
clone_image=CloneImage(image,0,0,MagickTrue,exception);
if (clone_image != (Image *) NULL)
{
crop_image=CropImage(clone_image,&crop_info,exception);
if (crop_image != (Image *) NULL)
{
image=DestroyImage(image);
image=crop_image;
}
}
}
status=XGetWMName(display,target,&window_name);
if (status == True)
{
if (*image_info->filename == '\0')
(void) CopyMagickString(image->filename,(char *) window_name.value,
(size_t) window_name.nitems+1);
(void) XFree((void *) window_name.value);
}
}
if (ximage_info->silent == MagickFalse)
{
/*
Alert the user we're done.
*/
(void) XBell(display,0);
(void) XBell(display,0);
}
(void) XCloseDisplay(display);
return(image);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X I n i t i a l i z e W i n d o w s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XInitializeWindows() initializes the XWindows structure.
%
% The format of the XInitializeWindows method is:
%
% XWindows *XInitializeWindows(Display *display,
% XResourceInfo *resource_info)
%
% A description of each parameter follows:
%
% o windows: XInitializeWindows returns a pointer to a XWindows structure.
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
*/
MagickPrivate XWindows *XInitializeWindows(Display *display,
XResourceInfo *resource_info)
{
Window
root_window;
XWindows
*windows;
/*
Allocate windows structure.
*/
windows=(XWindows *) AcquireMagickMemory(sizeof(*windows));
if (windows == (XWindows *) NULL)
{
ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
"...");
return((XWindows *) NULL);
}
(void) memset(windows,0,sizeof(*windows));
windows->pixel_info=(XPixelInfo *) AcquireMagickMemory(
sizeof(*windows->pixel_info));
windows->icon_pixel=(XPixelInfo *) AcquireMagickMemory(
sizeof(*windows->icon_pixel));
windows->icon_resources=(XResourceInfo *) AcquireMagickMemory(
sizeof(*windows->icon_resources));
if ((windows->pixel_info == (XPixelInfo *) NULL) ||
(windows->icon_pixel == (XPixelInfo *) NULL) ||
(windows->icon_resources == (XResourceInfo *) NULL))
{
ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
"...");
return((XWindows *) NULL);
}
/*
Initialize windows structure.
*/
windows->display=display;
windows->wm_protocols=XInternAtom(display,"WM_PROTOCOLS",MagickFalse);
windows->wm_delete_window=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
windows->wm_take_focus=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
windows->im_protocols=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
windows->im_remote_command=
XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
windows->im_update_widget=XInternAtom(display,"IM_UPDATE_WIDGET",MagickFalse);
windows->im_update_colormap=
XInternAtom(display,"IM_UPDATE_COLORMAP",MagickFalse);
windows->im_former_image=XInternAtom(display,"IM_FORMER_IMAGE",MagickFalse);
windows->im_next_image=XInternAtom(display,"IM_NEXT_IMAGE",MagickFalse);
windows->im_retain_colors=XInternAtom(display,"IM_RETAIN_COLORS",MagickFalse);
windows->im_exit=XInternAtom(display,"IM_EXIT",MagickFalse);
windows->dnd_protocols=XInternAtom(display,"DndProtocol",MagickFalse);
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
(void) XSynchronize(display,IsWindows95());
#endif
if (IsEventLogging())
{
(void) XSynchronize(display,MagickTrue);
(void) LogMagickEvent(X11Event,GetMagickModule(),"Version: %s",
GetMagickVersion((size_t *) NULL));
(void) LogMagickEvent(X11Event,GetMagickModule(),"Protocols:");
(void) LogMagickEvent(X11Event,GetMagickModule(),
" Window Manager: 0x%lx",windows->wm_protocols);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" delete window: 0x%lx",windows->wm_delete_window);
(void) LogMagickEvent(X11Event,GetMagickModule()," take focus: 0x%lx",
windows->wm_take_focus);
(void) LogMagickEvent(X11Event,GetMagickModule()," ImageMagick: 0x%lx",
windows->im_protocols);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" remote command: 0x%lx",windows->im_remote_command);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" update widget: 0x%lx",windows->im_update_widget);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" update colormap: 0x%lx",windows->im_update_colormap);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" former image: 0x%lx",windows->im_former_image);
(void) LogMagickEvent(X11Event,GetMagickModule()," next image: 0x%lx",
windows->im_next_image);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" retain colors: 0x%lx",windows->im_retain_colors);
(void) LogMagickEvent(X11Event,GetMagickModule()," exit: 0x%lx",
windows->im_exit);
(void) LogMagickEvent(X11Event,GetMagickModule()," Drag and Drop: 0x%lx",
windows->dnd_protocols);
}
/*
Allocate standard colormap.
*/
windows->map_info=XAllocStandardColormap();
windows->icon_map=XAllocStandardColormap();
if ((windows->map_info == (XStandardColormap *) NULL) ||
(windows->icon_map == (XStandardColormap *) NULL))
ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
"...");
windows->map_info->colormap=(Colormap) NULL;
windows->icon_map->colormap=(Colormap) NULL;
windows->pixel_info->pixels=(unsigned long *) NULL;
windows->pixel_info->annotate_context=(GC) NULL;
windows->pixel_info->highlight_context=(GC) NULL;
windows->pixel_info->widget_context=(GC) NULL;
windows->font_info=(XFontStruct *) NULL;
windows->icon_pixel->annotate_context=(GC) NULL;
windows->icon_pixel->pixels=(unsigned long *) NULL;
/*
Allocate visual.
*/
*windows->icon_resources=(*resource_info);
windows->icon_resources->visual_type=(char *) "default";
windows->icon_resources->colormap=SharedColormap;
windows->visual_info=
XBestVisualInfo(display,windows->map_info,resource_info);
windows->icon_visual=
XBestVisualInfo(display,windows->icon_map,windows->icon_resources);
if ((windows->visual_info == (XVisualInfo *) NULL) ||
(windows->icon_visual == (XVisualInfo *) NULL))
ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
resource_info->visual_type);
if (IsEventLogging())
{
(void) LogMagickEvent(X11Event,GetMagickModule(),"Visual:");
(void) LogMagickEvent(X11Event,GetMagickModule()," visual id: 0x%lx",
windows->visual_info->visualid);
(void) LogMagickEvent(X11Event,GetMagickModule()," class: %s",
XVisualClassName(windows->visual_info->klass));
(void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d planes",
windows->visual_info->depth);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" size of colormap: %d entries",windows->visual_info->colormap_size);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" red, green, blue masks: 0x%lx 0x%lx 0x%lx",
windows->visual_info->red_mask,windows->visual_info->green_mask,
windows->visual_info->blue_mask);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" significant bits in color: %d bits",
windows->visual_info->bits_per_rgb);
}
/*
Allocate class and manager hints.
*/
windows->class_hints=XAllocClassHint();
windows->manager_hints=XAllocWMHints();
if ((windows->class_hints == (XClassHint *) NULL) ||
(windows->manager_hints == (XWMHints *) NULL))
ThrowXWindowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
"...");
/*
Determine group leader if we have one.
*/
root_window=XRootWindow(display,windows->visual_info->screen);
windows->group_leader.id=(Window) NULL;
if (resource_info->window_group != (char *) NULL)
{
if (isdigit((int) ((unsigned char) *resource_info->window_group)) != 0)
windows->group_leader.id=XWindowByID(display,root_window,(Window)
strtol((char *) resource_info->window_group,(char **) NULL,0));
if (windows->group_leader.id == (Window) NULL)
windows->group_leader.id=
XWindowByName(display,root_window,resource_info->window_group);
}
return(windows);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X M a k e C u r s o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XMakeCursor() creates a crosshairs X11 cursor.
%
% The format of the XMakeCursor method is:
%
% Cursor XMakeCursor(Display *display,Window window,Colormap colormap,
% char *background_color,char *foreground_color)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o window: Specifies the ID of the window for which the cursor is
% assigned.
%
% o colormap: Specifies the ID of the colormap from which the background
% and foreground color will be retrieved.
%
% o background_color: Specifies the color to use for the cursor background.
%
% o foreground_color: Specifies the color to use for the cursor foreground.
%
*/
MagickPrivate Cursor XMakeCursor(Display *display,Window window,
Colormap colormap,char *background_color,char *foreground_color)
{
#define scope_height 17
#define scope_x_hot 8
#define scope_y_hot 8
#define scope_width 17
static const unsigned char
scope_bits[] =
{
0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x7f,
0xfc, 0x01, 0x01, 0x00, 0x01, 0x7f, 0xfc, 0x01, 0x80, 0x02, 0x00,
0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02, 0x00, 0x80, 0x02,
0x00, 0x80, 0x02, 0x00, 0x80, 0x03, 0x00
},
scope_mask_bits[] =
{
0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xff, 0xfe, 0x01, 0x7f,
0xfc, 0x01, 0x03, 0x80, 0x01, 0x7f, 0xfc, 0x01, 0xff, 0xfe, 0x01,
0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x06,
0x00, 0xc0, 0x07, 0x00, 0xc0, 0x07, 0x00
};
Cursor
cursor;
Pixmap
mask,
source;
XColor
background,
foreground;
assert(display != (Display *) NULL);
assert(window != (Window) NULL);
assert(colormap != (Colormap) NULL);
assert(background_color != (char *) NULL);
assert(foreground_color != (char *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",background_color);
source=XCreateBitmapFromData(display,window,(char *) scope_bits,scope_width,
scope_height);
mask=XCreateBitmapFromData(display,window,(char *) scope_mask_bits,
scope_width,scope_height);
if ((source == (Pixmap) NULL) || (mask == (Pixmap) NULL))
{
ThrowXWindowException(XServerError,"UnableToCreatePixmap","...");
return((Cursor) NULL);
}
(void) XParseColor(display,colormap,background_color,&background);
(void) XParseColor(display,colormap,foreground_color,&foreground);
cursor=XCreatePixmapCursor(display,source,mask,&foreground,&background,
scope_x_hot,scope_y_hot);
(void) XFreePixmap(display,source);
(void) XFreePixmap(display,mask);
return(cursor);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X M a k e I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XMakeImage() creates an X11 image. If the image size differs from the X11
% image size, the image is first resized.
%
% The format of the XMakeImage method is:
%
% MagickBooleanType XMakeImage(Display *display,
% const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
% unsigned int width,unsigned int height,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 window: Specifies a pointer to a XWindowInfo structure.
%
% o image: the image.
%
% o width: Specifies the width in pixels of the rectangular area to
% display.
%
% o height: Specifies the height in pixels of the rectangular area to
% display.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickPrivate MagickBooleanType XMakeImage(Display *display,
const XResourceInfo *resource_info,XWindowInfo *window,Image *image,
unsigned int width,unsigned int height,ExceptionInfo *exception)
{
#define CheckOverflowException(length,width,height) \
(((height) != 0) && ((length)/((size_t) height) != ((size_t) width)))
int
depth,
format;
size_t
length;
XImage
*matte_image,
*ximage;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(resource_info != (XResourceInfo *) NULL);
assert(window != (XWindowInfo *) NULL);
assert(width != 0);
assert(height != 0);
if ((window->width == 0) || (window->height == 0))
return(MagickFalse);
/*
Apply user transforms to the image.
*/
(void) XCheckDefineCursor(display,window->id,window->busy_cursor);
(void) XFlush(display);
depth=(int) window->depth;
if (window->destroy)
window->image=DestroyImage(window->image);
window->image=image;
window->destroy=MagickFalse;
if (window->image != (Image *) NULL)
{
if (window->crop_geometry != (char *) NULL)
{
Image
*crop_image;
RectangleInfo
crop_info;
/*
Crop image.
*/
window->image->page.x=0;
window->image->page.y=0;
(void) ParsePageGeometry(window->image,window->crop_geometry,
&crop_info,exception);
crop_image=CropImage(window->image,&crop_info,exception);
if (crop_image != (Image *) NULL)
{
if (window->image != image)
window->image=DestroyImage(window->image);
window->image=crop_image;
window->destroy=MagickTrue;
}
}
if ((width != (unsigned int) window->image->columns) ||
(height != (unsigned int) window->image->rows))
{
Image
*resize_image;
/*
Resize image.
*/
resize_image=NewImageList();
if ((window->pixel_info->colors == 0) &&
(window->image->rows > (unsigned long) XDisplayHeight(display,window->screen)) &&
(window->image->columns > (unsigned long) XDisplayWidth(display,window->screen)))
resize_image=ResizeImage(window->image,width,height,
image->filter,exception);
else
{
if (window->image->storage_class == PseudoClass)
resize_image=SampleImage(window->image,width,height,
exception);
else
resize_image=ThumbnailImage(window->image,width,height,
exception);
}
if (resize_image != (Image *) NULL)
{
if (window->image != image)
window->image=DestroyImage(window->image);
window->image=resize_image;
window->destroy=MagickTrue;
}
}
width=(unsigned int) window->image->columns;
assert((size_t) width == window->image->columns);
height=(unsigned int) window->image->rows;
assert((size_t) height == window->image->rows);
}
/*
Create X image.
*/
ximage=(XImage *) NULL;
format=(depth == 1) ? XYBitmap : ZPixmap;
#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
if (window->shared_memory != MagickFalse)
{
XShmSegmentInfo
*segment_info;
segment_info=(XShmSegmentInfo *) window->segment_info;
segment_info[1].shmid=(-1);
segment_info[1].shmaddr=(char *) NULL;
ximage=XShmCreateImage(display,window->visual,(unsigned int) depth,format,
(char *) NULL,&segment_info[1],width,height);
if (ximage == (XImage *) NULL)
window->shared_memory=MagickFalse;
else
{
length=(size_t) ximage->bytes_per_line*ximage->height;
if (CheckOverflowException(length,ximage->bytes_per_line,ximage->height))
window->shared_memory=MagickFalse;
}
if (window->shared_memory != MagickFalse)
segment_info[1].shmid=shmget(IPC_PRIVATE,length,IPC_CREAT | 0777);
if (window->shared_memory != MagickFalse)
segment_info[1].shmaddr=(char *) shmat(segment_info[1].shmid,0,0);
if (segment_info[1].shmid < 0)
window->shared_memory=MagickFalse;
if (window->shared_memory != MagickFalse)
(void) shmctl(segment_info[1].shmid,IPC_RMID,0);
else
{
if (ximage != (XImage *) NULL)
XDestroyImage(ximage);
ximage=(XImage *) NULL;
if (segment_info[1].shmaddr)
{
(void) shmdt(segment_info[1].shmaddr);
segment_info[1].shmaddr=(char *) NULL;
}
if (segment_info[1].shmid >= 0)
{
(void) shmctl(segment_info[1].shmid,IPC_RMID,0);
segment_info[1].shmid=(-1);
}
}
}
#endif
/*
Allocate X image pixel data.
*/
#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
if (window->shared_memory)
{
Status
status;
XShmSegmentInfo
*segment_info;
(void) XSync(display,MagickFalse);
xerror_alert=MagickFalse;
segment_info=(XShmSegmentInfo *) window->segment_info;
ximage->data=segment_info[1].shmaddr;
segment_info[1].readOnly=MagickFalse;
status=XShmAttach(display,&segment_info[1]);
if (status != False)
(void) XSync(display,MagickFalse);
if ((status == False) || (xerror_alert != MagickFalse))
{
window->shared_memory=MagickFalse;
if (status != False)
XShmDetach(display,&segment_info[1]);
ximage->data=NULL;
XDestroyImage(ximage);
ximage=(XImage *) NULL;
if (segment_info[1].shmid >= 0)
{
if (segment_info[1].shmaddr != NULL)
(void) shmdt(segment_info[1].shmaddr);
(void) shmctl(segment_info[1].shmid,IPC_RMID,0);
segment_info[1].shmid=(-1);
segment_info[1].shmaddr=(char *) NULL;
}
}
}
#endif
if (window->shared_memory == MagickFalse)
ximage=XCreateImage(display,window->visual,(unsigned int) depth,format,0,
(char *) NULL,width,height,XBitmapPad(display),0);
if (ximage == (XImage *) NULL)
{
/*
Unable to create X image.
*/
(void) XCheckDefineCursor(display,window->id,window->cursor);
return(MagickFalse);
}
length=(size_t) ximage->bytes_per_line*ximage->height;
if (IsEventLogging())
{
(void) LogMagickEvent(X11Event,GetMagickModule(),"XImage:");
(void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %dx%d",
ximage->width,ximage->height);
(void) LogMagickEvent(X11Event,GetMagickModule()," format: %d",
ximage->format);
(void) LogMagickEvent(X11Event,GetMagickModule()," byte order: %d",
ximage->byte_order);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" bitmap unit, bit order, pad: %d %d %d",ximage->bitmap_unit,
ximage->bitmap_bit_order,ximage->bitmap_pad);
(void) LogMagickEvent(X11Event,GetMagickModule()," depth: %d",
ximage->depth);
(void) LogMagickEvent(X11Event,GetMagickModule()," bytes per line: %d",
ximage->bytes_per_line);
(void) LogMagickEvent(X11Event,GetMagickModule()," bits per pixel: %d",
ximage->bits_per_pixel);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" red, green, blue masks: 0x%lx 0x%lx 0x%lx",ximage->red_mask,
ximage->green_mask,ximage->blue_mask);
}
if (window->shared_memory == MagickFalse)
{
if (ximage->format == XYBitmap)
{
ximage->data=(char *) AcquireQuantumMemory((size_t)
ximage->bytes_per_line,(size_t) ximage->depth*ximage->height);
if (ximage->data != (char *) NULL)
(void) memset(ximage->data,0,(size_t)
ximage->bytes_per_line*ximage->depth*ximage->height);
}
else
{
ximage->data=(char *) AcquireQuantumMemory((size_t)
ximage->bytes_per_line,(size_t) ximage->height);
if (ximage->data != (char *) NULL)
(void) memset(ximage->data,0,(size_t)
ximage->bytes_per_line*ximage->height);
}
}
if (ximage->data == (char *) NULL)
{
/*
Unable to allocate pixel data.
*/
XDestroyImage(ximage);
ximage=(XImage *) NULL;
(void) XCheckDefineCursor(display,window->id,window->cursor);
return(MagickFalse);
}
if (window->ximage != (XImage *) NULL)
{
/*
Destroy previous X image.
*/
length=(size_t) window->ximage->bytes_per_line*window->ximage->height;
#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
if (window->segment_info != (XShmSegmentInfo *) NULL)
{
XShmSegmentInfo
*segment_info;
segment_info=(XShmSegmentInfo *) window->segment_info;
if (segment_info[0].shmid >= 0)
{
(void) XSync(display,MagickFalse);
(void) XShmDetach(display,&segment_info[0]);
(void) XSync(display,MagickFalse);
if (segment_info[0].shmaddr != (char *) NULL)
(void) shmdt(segment_info[0].shmaddr);
(void) shmctl(segment_info[0].shmid,IPC_RMID,0);
segment_info[0].shmid=(-1);
segment_info[0].shmaddr=(char *) NULL;
window->ximage->data=(char *) NULL;
}
}
#endif
if (window->ximage->data != (char *) NULL)
free(window->ximage->data);
window->ximage->data=(char *) NULL;
XDestroyImage(window->ximage);
window->ximage=(XImage *) NULL;
}
#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
if (window->segment_info != (XShmSegmentInfo *) NULL)
{
XShmSegmentInfo
*segment_info;
segment_info=(XShmSegmentInfo *) window->segment_info;
segment_info[0]=segment_info[1];
}
#endif
window->ximage=ximage;
matte_image=(XImage *) NULL;
if ((window->shape != MagickFalse) && (window->image != (Image *) NULL))
if ((window->image->alpha_trait != UndefinedPixelTrait) &&
((int) width <= XDisplayWidth(display,window->screen)) &&
((int) height <= XDisplayHeight(display,window->screen)))
{
/*
Create matte image.
*/
matte_image=XCreateImage(display,window->visual,1,XYBitmap,0,
(char *) NULL,width,height,XBitmapPad(display),0);
if (IsEventLogging())
{
(void) LogMagickEvent(X11Event,GetMagickModule(),"Matte Image:");
(void) LogMagickEvent(X11Event,GetMagickModule(),
" width, height: %dx%d",matte_image->width,matte_image->height);
}
if (matte_image != (XImage *) NULL)
{
/*
Allocate matte image pixel data.
*/
matte_image->data=(char *) malloc((size_t)
matte_image->bytes_per_line*matte_image->depth*
matte_image->height);
if (matte_image->data == (char *) NULL)
{
XDestroyImage(matte_image);
matte_image=(XImage *) NULL;
}
}
}
if (window->matte_image != (XImage *) NULL)
{
/*
Free matte image.
*/
if (window->matte_image->data != (char *) NULL)
free(window->matte_image->data);
window->matte_image->data=(char *) NULL;
XDestroyImage(window->matte_image);
window->matte_image=(XImage *) NULL;
}
window->matte_image=matte_image;
if (window->matte_pixmap != (Pixmap) NULL)
{
(void) XFreePixmap(display,window->matte_pixmap);
window->matte_pixmap=(Pixmap) NULL;
#if defined(MAGICKCORE_HAVE_SHAPE)
if (window->shape != MagickFalse)
XShapeCombineMask(display,window->id,ShapeBounding,0,0,None,ShapeSet);
#endif
}
window->stasis=MagickFalse;
/*
Convert pixels to X image data.
*/
if (window->image != (Image *) NULL)
{
if ((ximage->byte_order == LSBFirst) || ((ximage->format == XYBitmap) &&
(ximage->bitmap_bit_order == LSBFirst)))
XMakeImageLSBFirst(resource_info,window,window->image,ximage,
matte_image,exception);
else
XMakeImageMSBFirst(resource_info,window,window->image,ximage,
matte_image,exception);
}
if (window->matte_image != (XImage *) NULL)
{
/*
Create matte pixmap.
*/
window->matte_pixmap=XCreatePixmap(display,window->id,width,height,1);
if (window->matte_pixmap != (Pixmap) NULL)
{
GC
graphics_context;
XGCValues
context_values;
/*
Copy matte image to matte pixmap.
*/
context_values.background=0;
context_values.foreground=1;
graphics_context=XCreateGC(display,window->matte_pixmap,
(size_t) (GCBackground | GCForeground),&context_values);
(void) XPutImage(display,window->matte_pixmap,graphics_context,
window->matte_image,0,0,0,0,width,height);
(void) XFreeGC(display,graphics_context);
#if defined(MAGICKCORE_HAVE_SHAPE)
if (window->shape != MagickFalse)
XShapeCombineMask(display,window->id,ShapeBounding,0,0,
window->matte_pixmap,ShapeSet);
#endif
}
}
(void) XMakePixmap(display,resource_info,window);
/*
Restore cursor.
*/
(void) XCheckDefineCursor(display,window->id,window->cursor);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X M a k e I m a g e L S B F i r s t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XMakeImageLSBFirst() initializes the pixel data of an X11 Image. The X image
% pixels are copied in least-significant bit and byte first order. The
% server's scanline pad is respected. Rather than using one or two general
% cases, many special cases are found here to help speed up the image
% conversion.
%
% The format of the XMakeImageLSBFirst method is:
%
% void XMakeImageLSBFirst(Display *display,XWindows *windows,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
% o window: Specifies a pointer to a XWindowInfo structure.
%
% o image: the image.
%
% o ximage: Specifies a pointer to a XImage structure; returned from
% XCreateImage.
%
% o matte_image: Specifies a pointer to a XImage structure; returned from
% XCreateImage.
%
% o exception: return any errors or warnings in this structure.
%
*/
static void XMakeImageLSBFirst(const XResourceInfo *resource_info,
const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
ExceptionInfo *exception)
{
CacheView
*canvas_view;
Image
*canvas;
int
y;
register const Quantum
*p;
register int
x;
register unsigned char
*q;
unsigned char
bit,
byte;
unsigned int
scanline_pad;
unsigned long
pixel,
*pixels;
XStandardColormap
*map_info;
assert(resource_info != (XResourceInfo *) NULL);
assert(window != (XWindowInfo *) NULL);
assert(image != (Image *) NULL);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
canvas=image;
if ((window->immutable == MagickFalse) &&
(image->storage_class == DirectClass) && (image->alpha_trait != UndefinedPixelTrait))
{
char
size[MagickPathExtent];
Image
*pattern;
ImageInfo
*image_info;
image_info=AcquireImageInfo();
(void) CopyMagickString(image_info->filename,
resource_info->image_info->texture != (char *) NULL ?
resource_info->image_info->texture : "pattern:checkerboard",
MagickPathExtent);
(void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
image->columns,(double) image->rows);
image_info->size=ConstantString(size);
pattern=ReadImage(image_info,exception);
image_info=DestroyImageInfo(image_info);
if (pattern != (Image *) NULL)
{
canvas=CloneImage(image,0,0,MagickTrue,exception);
if (canvas != (Image *) NULL)
(void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickTrue,
0,0,exception);
pattern=DestroyImage(pattern);
}
}
scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
ximage->bits_per_pixel) >> 3));
map_info=window->map_info;
pixels=window->pixel_info->pixels;
q=(unsigned char *) ximage->data;
x=0;
canvas_view=AcquireVirtualCacheView(canvas,exception);
if (ximage->format == XYBitmap)
{
register unsigned short
polarity;
unsigned char
background,
foreground;
/*
Convert canvas to big-endian bitmap.
*/
background=(unsigned char)
(XPixelIntensity(&window->pixel_info->foreground_color) <
XPixelIntensity(&window->pixel_info->background_color) ? 0x80 : 0x00);
foreground=(unsigned char)
(XPixelIntensity(&window->pixel_info->background_color) <
XPixelIntensity(&window->pixel_info->foreground_color) ? 0x80 : 0x00);
polarity=(unsigned short) ((GetPixelInfoIntensity(image,
&canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
if (canvas->colors == 2)
polarity=GetPixelInfoIntensity(image,&canvas->colormap[0]) <
GetPixelInfoIntensity(image,&canvas->colormap[1]);
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
exception);
if (p == (const Quantum *) NULL)
break;
bit=0;
byte=0;
for (x=0; x < (int) canvas->columns; x++)
{
byte>>=1;
if (GetPixelIndex(canvas,p) == (Quantum) polarity)
byte|=foreground;
else
byte|=background;
bit++;
if (bit == 8)
{
*q++=byte;
bit=0;
byte=0;
}
p+=GetPixelChannels(canvas);
}
if (bit != 0)
*q=byte >> (8-bit);
q+=scanline_pad;
}
}
else
if (window->pixel_info->colors != 0)
switch (ximage->bits_per_pixel)
{
case 2:
{
register unsigned int
nibble;
/*
Convert to 2 bit color-mapped X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
nibble=0;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0x0f;
switch (nibble)
{
case 0:
{
*q=(unsigned char) pixel;
nibble++;
break;
}
case 1:
{
*q|=(unsigned char) (pixel << 2);
nibble++;
break;
}
case 2:
{
*q|=(unsigned char) (pixel << 4);
nibble++;
break;
}
case 3:
{
*q|=(unsigned char) (pixel << 6);
q++;
nibble=0;
break;
}
}
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
case 4:
{
register unsigned int
nibble;
/*
Convert to 4 bit color-mapped X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
nibble=0;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)] & 0xf;
switch (nibble)
{
case 0:
{
*q=(unsigned char) pixel;
nibble++;
break;
}
case 1:
{
*q|=(unsigned char) (pixel << 4);
q++;
nibble=0;
break;
}
}
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
case 6:
case 8:
{
/*
Convert to 8 bit color-mapped X canvas.
*/
if (resource_info->color_recovery &&
resource_info->quantize_info->dither_method != NoDitherMethod)
{
XDitherImage(canvas,ximage,exception);
break;
}
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
*q++=(unsigned char) pixel;
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
default:
{
register int
k;
register unsigned int
bytes_per_pixel;
/*
Convert to multi-byte color-mapped X canvas.
*/
bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
for (k=0; k < (int) bytes_per_pixel; k++)
{
*q++=(unsigned char) (pixel & 0xff);
pixel>>=8;
}
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
}
else
switch (ximage->bits_per_pixel)
{
case 2:
{
register unsigned int
nibble;
/*
Convert to contiguous 2 bit continuous-tone X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
nibble=0;
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=XGammaPixel(canvas,map_info,p);
pixel&=0xf;
switch (nibble)
{
case 0:
{
*q=(unsigned char) pixel;
nibble++;
break;
}
case 1:
{
*q|=(unsigned char) (pixel << 2);
nibble++;
break;
}
case 2:
{
*q|=(unsigned char) (pixel << 4);
nibble++;
break;
}
case 3:
{
*q|=(unsigned char) (pixel << 6);
q++;
nibble=0;
break;
}
}
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
case 4:
{
register unsigned int
nibble;
/*
Convert to contiguous 4 bit continuous-tone X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
nibble=0;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=XGammaPixel(canvas,map_info,p);
pixel&=0xf;
switch (nibble)
{
case 0:
{
*q=(unsigned char) pixel;
nibble++;
break;
}
case 1:
{
*q|=(unsigned char) (pixel << 4);
q++;
nibble=0;
break;
}
}
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
case 6:
case 8:
{
/*
Convert to contiguous 8 bit continuous-tone X canvas.
*/
if (resource_info->color_recovery &&
resource_info->quantize_info->dither_method != NoDitherMethod)
{
XDitherImage(canvas,ximage,exception);
break;
}
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=XGammaPixel(canvas,map_info,p);
*q++=(unsigned char) pixel;
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
default:
{
if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
(map_info->green_max == 255) && (map_info->blue_max == 255) &&
(map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
(map_info->blue_mult == 1))
{
/*
Convert to 32 bit continuous-tone X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
(blue_gamma != 1.0))
{
/*
Gamma correct canvas.
*/
for (x=(int) canvas->columns-1; x >= 0; x--)
{
*q++=ScaleQuantumToChar(XBlueGamma(
GetPixelBlue(canvas,p)));
*q++=ScaleQuantumToChar(XGreenGamma(
GetPixelGreen(canvas,p)));
*q++=ScaleQuantumToChar(XRedGamma(
GetPixelRed(canvas,p)));
*q++=0;
p+=GetPixelChannels(canvas);
}
continue;
}
for (x=(int) canvas->columns-1; x >= 0; x--)
{
*q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
*q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
*q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
*q++=0;
p+=GetPixelChannels(canvas);
}
}
}
else
if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
(map_info->green_max == 255) && (map_info->blue_max == 255) &&
(map_info->red_mult == 1) && (map_info->green_mult == 256) &&
(map_info->blue_mult == 65536L))
{
/*
Convert to 32 bit continuous-tone X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
(blue_gamma != 1.0))
{
/*
Gamma correct canvas.
*/
for (x=(int) canvas->columns-1; x >= 0; x--)
{
*q++=ScaleQuantumToChar(XRedGamma(
GetPixelRed(canvas,p)));
*q++=ScaleQuantumToChar(XGreenGamma(
GetPixelGreen(canvas,p)));
*q++=ScaleQuantumToChar(XBlueGamma(
GetPixelBlue(canvas,p)));
*q++=0;
p+=GetPixelChannels(canvas);
}
continue;
}
for (x=(int) canvas->columns-1; x >= 0; x--)
{
*q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
*q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
*q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
*q++=0;
p+=GetPixelChannels(canvas);
}
}
}
else
{
register int
k;
register unsigned int
bytes_per_pixel;
/*
Convert to multi-byte continuous-tone X canvas.
*/
bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=XGammaPixel(canvas,map_info,p);
for (k=0; k < (int) bytes_per_pixel; k++)
{
*q++=(unsigned char) (pixel & 0xff);
pixel>>=8;
}
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
}
break;
}
}
if (matte_image != (XImage *) NULL)
{
/*
Initialize matte canvas.
*/
scanline_pad=(unsigned int) (matte_image->bytes_per_line-
((matte_image->width*matte_image->bits_per_pixel) >> 3));
q=(unsigned char *) matte_image->data;
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
exception);
if (p == (const Quantum *) NULL)
break;
bit=0;
byte=0;
for (x=(int) canvas->columns-1; x >= 0; x--)
{
byte>>=1;
if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
byte|=0x80;
bit++;
if (bit == 8)
{
*q++=byte;
bit=0;
byte=0;
}
p+=GetPixelChannels(canvas);
}
if (bit != 0)
*q=byte >> (8-bit);
q+=scanline_pad;
}
}
canvas_view=DestroyCacheView(canvas_view);
if (canvas != image)
canvas=DestroyImage(canvas);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X M a k e I m a g e M S B F i r s t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XMakeImageMSBFirst() initializes the pixel data of an X11 Image. The X
% image pixels are copied in most-significant bit and byte first order. The
% server's scanline pad is also respected. Rather than using one or two
% general cases, many special cases are found here to help speed up the image
% conversion.
%
% The format of the XMakeImageMSBFirst method is:
%
% XMakeImageMSBFirst(resource_info,window,image,ximage,matte_image,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
% o window: Specifies a pointer to a XWindowInfo structure.
%
% o image: the image.
%
% o ximage: Specifies a pointer to a XImage structure; returned from
% XCreateImage.
%
% o matte_image: Specifies a pointer to a XImage structure; returned from
% XCreateImage.
%
% o exception: return any errors or warnings in this structure.
%
*/
static void XMakeImageMSBFirst(const XResourceInfo *resource_info,
const XWindowInfo *window,Image *image,XImage *ximage,XImage *matte_image,
ExceptionInfo *exception)
{
CacheView
*canvas_view;
Image
*canvas;
int
y;
register int
x;
register const Quantum
*p;
register unsigned char
*q;
unsigned char
bit,
byte;
unsigned int
scanline_pad;
unsigned long
pixel,
*pixels;
XStandardColormap
*map_info;
assert(resource_info != (XResourceInfo *) NULL);
assert(window != (XWindowInfo *) NULL);
assert(image != (Image *) NULL);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
canvas=image;
if ((window->immutable != MagickFalse) &&
(image->storage_class == DirectClass) &&
(image->alpha_trait != UndefinedPixelTrait))
{
char
size[MagickPathExtent];
Image
*pattern;
ImageInfo
*image_info;
image_info=AcquireImageInfo();
(void) CopyMagickString(image_info->filename,
resource_info->image_info->texture != (char *) NULL ?
resource_info->image_info->texture : "pattern:checkerboard",
MagickPathExtent);
(void) FormatLocaleString(size,MagickPathExtent,"%.20gx%.20g",(double)
image->columns,(double) image->rows);
image_info->size=ConstantString(size);
pattern=ReadImage(image_info,exception);
image_info=DestroyImageInfo(image_info);
if (pattern != (Image *) NULL)
{
canvas=CloneImage(image,0,0,MagickTrue,exception);
if (canvas != (Image *) NULL)
(void) CompositeImage(canvas,pattern,DstOverCompositeOp,MagickFalse,
0,0,exception);
pattern=DestroyImage(pattern);
}
}
scanline_pad=(unsigned int) (ximage->bytes_per_line-((ximage->width*
ximage->bits_per_pixel) >> 3));
map_info=window->map_info;
pixels=window->pixel_info->pixels;
q=(unsigned char *) ximage->data;
x=0;
canvas_view=AcquireVirtualCacheView(canvas,exception);
if (ximage->format == XYBitmap)
{
register unsigned short
polarity;
unsigned char
background,
foreground;
/*
Convert canvas to big-endian bitmap.
*/
background=(unsigned char)
(XPixelIntensity(&window->pixel_info->foreground_color) <
XPixelIntensity(&window->pixel_info->background_color) ? 0x01 : 0x00);
foreground=(unsigned char)
(XPixelIntensity(&window->pixel_info->background_color) <
XPixelIntensity(&window->pixel_info->foreground_color) ? 0x01 : 0x00);
polarity=(unsigned short) ((GetPixelInfoIntensity(image,
&canvas->colormap[0])) < (QuantumRange/2.0) ? 1 : 0);
if (canvas->colors == 2)
polarity=GetPixelInfoIntensity(image,&canvas->colormap[0]) <
GetPixelInfoIntensity(image,&canvas->colormap[1]);
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
exception);
if (p == (const Quantum *) NULL)
break;
bit=0;
byte=0;
for (x=(int) canvas->columns-1; x >= 0; x--)
{
byte<<=1;
if (GetPixelIndex(canvas,p) == (Quantum) polarity)
byte|=foreground;
else
byte|=background;
bit++;
if (bit == 8)
{
*q++=byte;
bit=0;
byte=0;
}
p+=GetPixelChannels(canvas);
}
if (bit != 0)
*q=byte << (8-bit);
q+=scanline_pad;
}
}
else
if (window->pixel_info->colors != 0)
switch (ximage->bits_per_pixel)
{
case 2:
{
register unsigned int
nibble;
/*
Convert to 2 bit color-mapped X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
nibble=0;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=pixels[(ssize_t)
GetPixelIndex(canvas,p)] & 0xf;
switch (nibble)
{
case 0:
{
*q=(unsigned char) (pixel << 6);
nibble++;
break;
}
case 1:
{
*q|=(unsigned char) (pixel << 4);
nibble++;
break;
}
case 2:
{
*q|=(unsigned char) (pixel << 2);
nibble++;
break;
}
case 3:
{
*q|=(unsigned char) pixel;
q++;
nibble=0;
break;
}
}
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
case 4:
{
register unsigned int
nibble;
/*
Convert to 4 bit color-mapped X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
nibble=0;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=pixels[(ssize_t)
GetPixelIndex(canvas,p)] & 0xf;
switch (nibble)
{
case 0:
{
*q=(unsigned char) (pixel << 4);
nibble++;
break;
}
case 1:
{
*q|=(unsigned char) pixel;
q++;
nibble=0;
break;
}
}
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
case 6:
case 8:
{
/*
Convert to 8 bit color-mapped X canvas.
*/
if (resource_info->color_recovery &&
resource_info->quantize_info->dither_method != NoDitherMethod)
{
XDitherImage(canvas,ximage,exception);
break;
}
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=pixels[(ssize_t) GetPixelIndex(canvas,p)];
*q++=(unsigned char) pixel;
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
default:
{
register int
k;
register unsigned int
bytes_per_pixel;
unsigned char
channel[sizeof(size_t)];
/*
Convert to 8 bit color-mapped X canvas.
*/
bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (int) canvas->columns; x++)
{
pixel=pixels[(ssize_t)
GetPixelIndex(canvas,p)];
for (k=(int) bytes_per_pixel-1; k >= 0; k--)
{
channel[k]=(unsigned char) pixel;
pixel>>=8;
}
for (k=0; k < (int) bytes_per_pixel; k++)
*q++=channel[k];
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
}
else
switch (ximage->bits_per_pixel)
{
case 2:
{
register unsigned int
nibble;
/*
Convert to 4 bit continuous-tone X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
nibble=0;
for (x=(int) canvas->columns-1; x >= 0; x--)
{
pixel=XGammaPixel(canvas,map_info,p);
pixel&=0xf;
switch (nibble)
{
case 0:
{
*q=(unsigned char) (pixel << 6);
nibble++;
break;
}
case 1:
{
*q|=(unsigned char) (pixel << 4);
nibble++;
break;
}
case 2:
{
*q|=(unsigned char) (pixel << 2);
nibble++;
break;
}
case 3:
{
*q|=(unsigned char) pixel;
q++;
nibble=0;
break;
}
}
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
case 4:
{
register unsigned int
nibble;
/*
Convert to 4 bit continuous-tone X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
nibble=0;
for (x=(int) canvas->columns-1; x >= 0; x--)
{
pixel=XGammaPixel(canvas,map_info,p);
pixel&=0xf;
switch (nibble)
{
case 0:
{
*q=(unsigned char) (pixel << 4);
nibble++;
break;
}
case 1:
{
*q|=(unsigned char) pixel;
q++;
nibble=0;
break;
}
}
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
case 6:
case 8:
{
/*
Convert to 8 bit continuous-tone X canvas.
*/
if (resource_info->color_recovery &&
resource_info->quantize_info->dither_method != NoDitherMethod)
{
XDitherImage(canvas,ximage,exception);
break;
}
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=(int) canvas->columns-1; x >= 0; x--)
{
pixel=XGammaPixel(canvas,map_info,p);
*q++=(unsigned char) pixel;
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
break;
}
default:
{
if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
(map_info->green_max == 255) && (map_info->blue_max == 255) &&
(map_info->red_mult == 65536L) && (map_info->green_mult == 256) &&
(map_info->blue_mult == 1))
{
/*
Convert to 32 bit continuous-tone X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
(blue_gamma != 1.0))
{
/*
Gamma correct canvas.
*/
for (x=(int) canvas->columns-1; x >= 0; x--)
{
*q++=0;
*q++=ScaleQuantumToChar(XRedGamma(
GetPixelRed(canvas,p)));
*q++=ScaleQuantumToChar(XGreenGamma(
GetPixelGreen(canvas,p)));
*q++=ScaleQuantumToChar(XBlueGamma(
GetPixelBlue(canvas,p)));
p+=GetPixelChannels(canvas);
}
continue;
}
for (x=(int) canvas->columns-1; x >= 0; x--)
{
*q++=0;
*q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
*q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
*q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
p+=GetPixelChannels(canvas);
}
}
}
else
if ((ximage->bits_per_pixel == 32) && (map_info->red_max == 255) &&
(map_info->green_max == 255) && (map_info->blue_max == 255) &&
(map_info->red_mult == 1) && (map_info->green_mult == 256) &&
(map_info->blue_mult == 65536L))
{
/*
Convert to 32 bit continuous-tone X canvas.
*/
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
if ((red_gamma != 1.0) || (green_gamma != 1.0) ||
(blue_gamma != 1.0))
{
/*
Gamma correct canvas.
*/
for (x=(int) canvas->columns-1; x >= 0; x--)
{
*q++=0;
*q++=ScaleQuantumToChar(XBlueGamma(
GetPixelBlue(canvas,p)));
*q++=ScaleQuantumToChar(XGreenGamma(
GetPixelGreen(canvas,p)));
*q++=ScaleQuantumToChar(XRedGamma(
GetPixelRed(canvas,p)));
p+=GetPixelChannels(canvas);
}
continue;
}
for (x=(int) canvas->columns-1; x >= 0; x--)
{
*q++=0;
*q++=ScaleQuantumToChar((Quantum) GetPixelBlue(canvas,p));
*q++=ScaleQuantumToChar((Quantum) GetPixelGreen(canvas,p));
*q++=ScaleQuantumToChar((Quantum) GetPixelRed(canvas,p));
p+=GetPixelChannels(canvas);
}
}
}
else
{
register int
k;
register unsigned int
bytes_per_pixel;
unsigned char
channel[sizeof(size_t)];
/*
Convert to multi-byte continuous-tone X canvas.
*/
bytes_per_pixel=(unsigned int) (ximage->bits_per_pixel >> 3);
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,
canvas->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=(int) canvas->columns-1; x >= 0; x--)
{
pixel=XGammaPixel(canvas,map_info,p);
for (k=(int) bytes_per_pixel-1; k >= 0; k--)
{
channel[k]=(unsigned char) pixel;
pixel>>=8;
}
for (k=0; k < (int) bytes_per_pixel; k++)
*q++=channel[k];
p+=GetPixelChannels(canvas);
}
q+=scanline_pad;
}
}
break;
}
}
if (matte_image != (XImage *) NULL)
{
/*
Initialize matte canvas.
*/
scanline_pad=(unsigned int) (matte_image->bytes_per_line-
((matte_image->width*matte_image->bits_per_pixel) >> 3));
q=(unsigned char *) matte_image->data;
for (y=0; y < (int) canvas->rows; y++)
{
p=GetCacheViewVirtualPixels(canvas_view,0,(ssize_t) y,canvas->columns,1,
exception);
if (p == (const Quantum *) NULL)
break;
bit=0;
byte=0;
for (x=(int) canvas->columns-1; x >= 0; x--)
{
byte<<=1;
if (GetPixelAlpha(canvas,p) > (QuantumRange/2))
byte|=0x01;
bit++;
if (bit == 8)
{
*q++=byte;
bit=0;
byte=0;
}
p+=GetPixelChannels(canvas);
}
if (bit != 0)
*q=byte << (8-bit);
q+=scanline_pad;
}
}
canvas_view=DestroyCacheView(canvas_view);
if (canvas != image)
canvas=DestroyImage(canvas);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X M a k e M a g n i f y I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XMakeMagnifyImage() magnifies a region of an X image and displays it.
%
% The format of the XMakeMagnifyImage method is:
%
% void XMakeMagnifyImage(Display *display,XWindows *windows,
% ExceptionInfo *exception)
%
% 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.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickPrivate void XMakeMagnifyImage(Display *display,XWindows *windows,
ExceptionInfo *exception)
{
char
tuple[MagickPathExtent];
int
y;
PixelInfo
pixel;
register int
x;
register ssize_t
i;
register unsigned char
*p,
*q;
ssize_t
n;
static unsigned int
previous_magnify = 0;
static XWindowInfo
magnify_window;
unsigned int
height,
j,
k,
l,
magnify,
scanline_pad,
width;
XImage
*ximage;
/*
Check boundary conditions.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(windows != (XWindows *) NULL);
magnify=1;
for (n=1; n < (ssize_t) windows->magnify.data; n++)
magnify<<=1;
while ((magnify*windows->image.ximage->width) < windows->magnify.width)
magnify<<=1;
while ((magnify*windows->image.ximage->height) < windows->magnify.height)
magnify<<=1;
while (magnify > windows->magnify.width)
magnify>>=1;
while (magnify > windows->magnify.height)
magnify>>=1;
if (magnify == 0)
magnify=1;
if (magnify != previous_magnify)
{
Status
status;
XTextProperty
window_name;
/*
New magnify factor: update magnify window name.
*/
i=0;
while ((1 << i) <= (int) magnify)
i++;
(void) FormatLocaleString(windows->magnify.name,MagickPathExtent,
"Magnify %.20gX",(double) i);
status=XStringListToTextProperty(&windows->magnify.name,1,&window_name);
if (status != False)
{
XSetWMName(display,windows->magnify.id,&window_name);
XSetWMIconName(display,windows->magnify.id,&window_name);
(void) XFree((void *) window_name.value);
}
}
previous_magnify=magnify;
ximage=windows->image.ximage;
width=(unsigned int) windows->magnify.ximage->width;
height=(unsigned int) windows->magnify.ximage->height;
if ((windows->magnify.x < 0) ||
(windows->magnify.x >= windows->image.ximage->width))
windows->magnify.x=windows->image.ximage->width >> 1;
x=windows->magnify.x-((width/magnify) >> 1);
if (x < 0)
x=0;
else
if (x > (int) (ximage->width-(width/magnify)))
x=ximage->width-width/magnify;
if ((windows->magnify.y < 0) ||
(windows->magnify.y >= windows->image.ximage->height))
windows->magnify.y=windows->image.ximage->height >> 1;
y=windows->magnify.y-((height/magnify) >> 1);
if (y < 0)
y=0;
else
if (y > (int) (ximage->height-(height/magnify)))
y=ximage->height-height/magnify;
q=(unsigned char *) windows->magnify.ximage->data;
scanline_pad=(unsigned int) (windows->magnify.ximage->bytes_per_line-
((width*windows->magnify.ximage->bits_per_pixel) >> 3));
if (ximage->bits_per_pixel < 8)
{
register unsigned char
background,
byte,
foreground,
p_bit,
q_bit;
register unsigned int
plane;
XPixelInfo
*pixel_info;
pixel_info=windows->magnify.pixel_info;
switch (ximage->bitmap_bit_order)
{
case LSBFirst:
{
/*
Magnify little-endian bitmap.
*/
background=0x00;
foreground=0x80;
if (ximage->format == XYBitmap)
{
background=(unsigned char)
(XPixelIntensity(&pixel_info->foreground_color) <
XPixelIntensity(&pixel_info->background_color) ? 0x80 : 0x00);
foreground=(unsigned char)
(XPixelIntensity(&pixel_info->background_color) <
XPixelIntensity(&pixel_info->foreground_color) ? 0x80 : 0x00);
if (windows->magnify.depth > 1)
Swap(background,foreground);
}
for (i=0; i < (ssize_t) height; i+=magnify)
{
/*
Propogate pixel magnify rows.
*/
for (j=0; j < magnify; j++)
{
p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
((x*ximage->bits_per_pixel) >> 3);
p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
q_bit=0;
byte=0;
for (k=0; k < width; k+=magnify)
{
/*
Propogate pixel magnify columns.
*/
for (l=0; l < magnify; l++)
{
/*
Propogate each bit plane.
*/
for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
{
byte>>=1;
if (*p & (0x01 << (p_bit+plane)))
byte|=foreground;
else
byte|=background;
q_bit++;
if (q_bit == 8)
{
*q++=byte;
q_bit=0;
byte=0;
}
}
}
p_bit+=ximage->bits_per_pixel;
if (p_bit == 8)
{
p++;
p_bit=0;
}
if (q_bit != 0)
*q=byte >> (8-q_bit);
q+=scanline_pad;
}
}
y++;
}
break;
}
case MSBFirst:
default:
{
/*
Magnify big-endian bitmap.
*/
background=0x00;
foreground=0x01;
if (ximage->format == XYBitmap)
{
background=(unsigned char)
(XPixelIntensity(&pixel_info->foreground_color) <
XPixelIntensity(&pixel_info->background_color) ? 0x01 : 0x00);
foreground=(unsigned char)
(XPixelIntensity(&pixel_info->background_color) <
XPixelIntensity(&pixel_info->foreground_color) ? 0x01 : 0x00);
if (windows->magnify.depth > 1)
Swap(background,foreground);
}
for (i=0; i < (ssize_t) height; i+=magnify)
{
/*
Propogate pixel magnify rows.
*/
for (j=0; j < magnify; j++)
{
p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
((x*ximage->bits_per_pixel) >> 3);
p_bit=(unsigned char) (x*ximage->bits_per_pixel) & 0x07;
q_bit=0;
byte=0;
for (k=0; k < width; k+=magnify)
{
/*
Propogate pixel magnify columns.
*/
for (l=0; l < magnify; l++)
{
/*
Propogate each bit plane.
*/
for (plane=0; (int) plane < ximage->bits_per_pixel; plane++)
{
byte<<=1;
if (*p & (0x80 >> (p_bit+plane)))
byte|=foreground;
else
byte|=background;
q_bit++;
if (q_bit == 8)
{
*q++=byte;
q_bit=0;
byte=0;
}
}
}
p_bit+=ximage->bits_per_pixel;
if (p_bit == 8)
{
p++;
p_bit=0;
}
if (q_bit != 0)
*q=byte << (8-q_bit);
q+=scanline_pad;
}
}
y++;
}
break;
}
}
}
else
switch (ximage->bits_per_pixel)
{
case 6:
case 8:
{
/*
Magnify 8 bit X image.
*/
for (i=0; i < (ssize_t) height; i+=magnify)
{
/*
Propogate pixel magnify rows.
*/
for (j=0; j < magnify; j++)
{
p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
((x*ximage->bits_per_pixel) >> 3);
for (k=0; k < width; k+=magnify)
{
/*
Propogate pixel magnify columns.
*/
for (l=0; l < magnify; l++)
*q++=(*p);
p++;
}
q+=scanline_pad;
}
y++;
}
break;
}
default:
{
register unsigned int
bytes_per_pixel,
m;
/*
Magnify multi-byte X image.
*/
bytes_per_pixel=(unsigned int) ximage->bits_per_pixel >> 3;
for (i=0; i < (ssize_t) height; i+=magnify)
{
/*
Propogate pixel magnify rows.
*/
for (j=0; j < magnify; j++)
{
p=(unsigned char *) ximage->data+y*ximage->bytes_per_line+
((x*ximage->bits_per_pixel) >> 3);
for (k=0; k < width; k+=magnify)
{
/*
Propogate pixel magnify columns.
*/
for (l=0; l < magnify; l++)
for (m=0; m < bytes_per_pixel; m++)
*q++=(*(p+m));
p+=bytes_per_pixel;
}
q+=scanline_pad;
}
y++;
}
break;
}
}
/*
Copy X image to magnify pixmap.
*/
x=windows->magnify.x-((width/magnify) >> 1);
if (x < 0)
x=(int) ((width >> 1)-windows->magnify.x*magnify);
else
if (x > (int) (ximage->width-(width/magnify)))
x=(int) ((ximage->width-windows->magnify.x)*magnify-(width >> 1));
else
x=0;
y=windows->magnify.y-((height/magnify) >> 1);
if (y < 0)
y=(int) ((height >> 1)-windows->magnify.y*magnify);
else
if (y > (int) (ximage->height-(height/magnify)))
y=(int) ((ximage->height-windows->magnify.y)*magnify-(height >> 1));
else
y=0;
if ((x != 0) || (y != 0))
(void) XFillRectangle(display,windows->magnify.pixmap,
windows->magnify.annotate_context,0,0,width,height);
(void) XPutImage(display,windows->magnify.pixmap,
windows->magnify.annotate_context,windows->magnify.ximage,0,0,x,y,width-x,
height-y);
if ((magnify > 1) && ((magnify <= (width >> 1)) &&
(magnify <= (height >> 1))))
{
RectangleInfo
highlight_info;
/*
Highlight center pixel.
*/
highlight_info.x=(ssize_t) windows->magnify.width >> 1;
highlight_info.y=(ssize_t) windows->magnify.height >> 1;
highlight_info.width=magnify;
highlight_info.height=magnify;
(void) XDrawRectangle(display,windows->magnify.pixmap,
windows->magnify.highlight_context,(int) highlight_info.x,
(int) highlight_info.y,(unsigned int) highlight_info.width-1,
(unsigned int) highlight_info.height-1);
if (magnify > 2)
(void) XDrawRectangle(display,windows->magnify.pixmap,
windows->magnify.annotate_context,(int) highlight_info.x+1,
(int) highlight_info.y+1,(unsigned int) highlight_info.width-3,
(unsigned int) highlight_info.height-3);
}
/*
Show center pixel color.
*/
(void) GetOneVirtualPixelInfo(windows->image.image,TileVirtualPixelMethod,
(ssize_t) windows->magnify.x,(ssize_t) windows->magnify.y,&pixel,exception);
(void) FormatLocaleString(tuple,MagickPathExtent,"%d,%d: ",
windows->magnify.x,windows->magnify.y);
(void) ConcatenateMagickString(tuple,"(",MagickPathExtent);
ConcatenateColorComponent(&pixel,RedPixelChannel,X11Compliance,tuple);
(void) ConcatenateMagickString(tuple,",",MagickPathExtent);
ConcatenateColorComponent(&pixel,GreenPixelChannel,X11Compliance,tuple);
(void) ConcatenateMagickString(tuple,",",MagickPathExtent);
ConcatenateColorComponent(&pixel,BluePixelChannel,X11Compliance,tuple);
if (pixel.colorspace == CMYKColorspace)
{
(void) ConcatenateMagickString(tuple,",",MagickPathExtent);
ConcatenateColorComponent(&pixel,BlackPixelChannel,X11Compliance,tuple);
}
if (pixel.alpha_trait != UndefinedPixelTrait)
{
(void) ConcatenateMagickString(tuple,",",MagickPathExtent);
ConcatenateColorComponent(&pixel,AlphaPixelChannel,X11Compliance,tuple);
}
(void) ConcatenateMagickString(tuple,")",MagickPathExtent);
height=(unsigned int) windows->magnify.font_info->ascent+
windows->magnify.font_info->descent;
x=windows->magnify.font_info->max_bounds.width >> 1;
y=windows->magnify.font_info->ascent+(height >> 2);
(void) XDrawImageString(display,windows->magnify.pixmap,
windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
GetColorTuple(&pixel,MagickTrue,tuple);
y+=height;
(void) XDrawImageString(display,windows->magnify.pixmap,
windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
(void) QueryColorname(windows->image.image,&pixel,SVGCompliance,tuple,
exception);
y+=height;
(void) XDrawImageString(display,windows->magnify.pixmap,
windows->magnify.annotate_context,x,y,tuple,(int) strlen(tuple));
/*
Refresh magnify window.
*/
magnify_window=windows->magnify;
magnify_window.x=0;
magnify_window.y=0;
XRefreshWindow(display,&magnify_window,(XEvent *) NULL);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X M a k e P i x m a p %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XMakePixmap() creates an X11 pixmap.
%
% The format of the XMakePixmap method is:
%
% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
% XPixelInfo *pixel)
%
% A description of each parameter follows:
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o window: Specifies a pointer to a XWindowInfo structure.
%
*/
static MagickBooleanType XMakePixmap(Display *display,
const XResourceInfo *resource_info,XWindowInfo *window)
{
unsigned int
height,
width;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(resource_info != (XResourceInfo *) NULL);
assert(window != (XWindowInfo *) NULL);
if (window->pixmap != (Pixmap) NULL)
{
/*
Destroy previous X pixmap.
*/
(void) XFreePixmap(display,window->pixmap);
window->pixmap=(Pixmap) NULL;
}
if (window->use_pixmap == MagickFalse)
return(MagickFalse);
if (window->ximage == (XImage *) NULL)
return(MagickFalse);
/*
Display busy cursor.
*/
(void) XCheckDefineCursor(display,window->id,window->busy_cursor);
(void) XFlush(display);
/*
Create pixmap.
*/
width=(unsigned int) window->ximage->width;
height=(unsigned int) window->ximage->height;
window->pixmap=XCreatePixmap(display,window->id,width,height,window->depth);
if (window->pixmap == (Pixmap) NULL)
{
/*
Unable to allocate pixmap.
*/
(void) XCheckDefineCursor(display,window->id,window->cursor);
return(MagickFalse);
}
/*
Copy X image to pixmap.
*/
#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
if (window->shared_memory)
(void) XShmPutImage(display,window->pixmap,window->annotate_context,
window->ximage,0,0,0,0,width,height,MagickTrue);
#endif
if (window->shared_memory == MagickFalse)
(void) XPutImage(display,window->pixmap,window->annotate_context,
window->ximage,0,0,0,0,width,height);
if (IsEventLogging())
{
(void) LogMagickEvent(X11Event,GetMagickModule(),"Pixmap:");
(void) LogMagickEvent(X11Event,GetMagickModule()," width, height: %ux%u",
width,height);
}
/*
Restore cursor.
*/
(void) XCheckDefineCursor(display,window->id,window->cursor);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X M a k e S t a n d a r d C o l o r m a p %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XMakeStandardColormap() creates an X11 Standard Colormap.
%
% The format of the XMakeStandardColormap method is:
%
% void XMakeStandardColormap(Display *display,XVisualInfo *visual_info,
% XResourceInfo *resource_info,Image *image,XStandardColormap *map_info,
% XPixelInfo *pixel,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o visual_info: Specifies a pointer to a X11 XVisualInfo structure;
% returned from XGetVisualInfo.
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
% o image: the image.
%
% o map_info: If a Standard Colormap type is specified, this structure is
% initialized with info from the Standard Colormap.
%
% o pixel: Specifies a pointer to a XPixelInfo structure.
%
% o exception: return any errors or warnings in this structure.
%
*/
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
static inline double DiversityPixelIntensity(
const DiversityPacket *pixel)
{
double
intensity;
intensity=0.212656*pixel->red+0.715158*pixel->green+0.072186*pixel->blue;
return(intensity);
}
static int IntensityCompare(const void *x,const void *y)
{
DiversityPacket
*color_1,
*color_2;
int
diversity;
color_1=(DiversityPacket *) x;
color_2=(DiversityPacket *) y;
diversity=(int) (DiversityPixelIntensity(color_2)-
DiversityPixelIntensity(color_1));
return(diversity);
}
static int PopularityCompare(const void *x,const void *y)
{
DiversityPacket
*color_1,
*color_2;
color_1=(DiversityPacket *) x;
color_2=(DiversityPacket *) y;
return((int) color_2->count-(int) color_1->count);
}
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
static inline Quantum ScaleXToQuantum(const size_t x,
const size_t scale)
{
return((Quantum) (((double) QuantumRange*x)/scale+0.5));
}
MagickPrivate void XMakeStandardColormap(Display *display,
XVisualInfo *visual_info,XResourceInfo *resource_info,Image *image,
XStandardColormap *map_info,XPixelInfo *pixel,ExceptionInfo *exception)
{
Colormap
colormap;
register ssize_t
i;
Status
status;
size_t
number_colors,
retain_colors;
unsigned short
gray_value;
XColor
color,
*colors,
*p;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(visual_info != (XVisualInfo *) NULL);
assert(map_info != (XStandardColormap *) NULL);
assert(resource_info != (XResourceInfo *) NULL);
assert(pixel != (XPixelInfo *) NULL);
if (resource_info->map_type != (char *) NULL)
{
/*
Standard Colormap is already defined (i.e. xstdcmap).
*/
XGetPixelInfo(display,visual_info,map_info,resource_info,image,
pixel);
number_colors=(unsigned int) (map_info->base_pixel+
(map_info->red_max+1)*(map_info->green_max+1)*(map_info->blue_max+1));
if ((map_info->red_max*map_info->green_max*map_info->blue_max) != 0)
if ((image->alpha_trait == UndefinedPixelTrait) &&
(resource_info->color_recovery == MagickFalse) &&
(resource_info->quantize_info->dither_method != NoDitherMethod) &&
(number_colors < MaxColormapSize))
{
Image
*affinity_image;
register Quantum
*magick_restrict q;
/*
Improve image appearance with error diffusion.
*/
affinity_image=AcquireImage((ImageInfo *) NULL,exception);
if (affinity_image == (Image *) NULL)
ThrowXWindowFatalException(ResourceLimitFatalError,
"UnableToDitherImage",image->filename);
affinity_image->columns=number_colors;
affinity_image->rows=1;
/*
Initialize colormap image.
*/
q=QueueAuthenticPixels(affinity_image,0,0,affinity_image->columns,
1,exception);
if (q != (Quantum *) NULL)
{
for (i=0; i < (ssize_t) number_colors; i++)
{
SetPixelRed(affinity_image,0,q);
if (map_info->red_max != 0)
SetPixelRed(affinity_image,ScaleXToQuantum((size_t)
(i/map_info->red_mult),map_info->red_max),q);
SetPixelGreen(affinity_image,0,q);
if (map_info->green_max != 0)
SetPixelGreen(affinity_image,ScaleXToQuantum((size_t)
((i/map_info->green_mult) % (map_info->green_max+1)),
map_info->green_max),q);
SetPixelBlue(affinity_image,0,q);
if (map_info->blue_max != 0)
SetPixelBlue(affinity_image,ScaleXToQuantum((size_t)
(i % map_info->green_mult),map_info->blue_max),q);
SetPixelAlpha(affinity_image,
TransparentAlpha,q);
q+=GetPixelChannels(affinity_image);
}
(void) SyncAuthenticPixels(affinity_image,exception);
(void) RemapImage(resource_info->quantize_info,image,
affinity_image,exception);
}
XGetPixelInfo(display,visual_info,map_info,resource_info,image,
pixel);
(void) SetImageStorageClass(image,DirectClass,exception);
affinity_image=DestroyImage(affinity_image);
}
if (IsEventLogging())
{
(void) LogMagickEvent(X11Event,GetMagickModule(),
"Standard Colormap:");
(void) LogMagickEvent(X11Event,GetMagickModule(),
" colormap id: 0x%lx",map_info->colormap);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" red, green, blue max: %lu %lu %lu",map_info->red_max,
map_info->green_max,map_info->blue_max);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" red, green, blue mult: %lu %lu %lu",map_info->red_mult,
map_info->green_mult,map_info->blue_mult);
}
return;
}
if ((visual_info->klass != DirectColor) &&
(visual_info->klass != TrueColor))
if ((image->storage_class == DirectClass) ||
((int) image->colors > visual_info->colormap_size))
{
QuantizeInfo
quantize_info;
/*
Image has more colors than the visual supports.
*/
quantize_info=(*resource_info->quantize_info);
quantize_info.number_colors=(size_t) visual_info->colormap_size;
(void) QuantizeImage(&quantize_info,image,exception);
}
/*
Free previous and create new colormap.
*/
(void) XFreeStandardColormap(display,visual_info,map_info,pixel);
colormap=XDefaultColormap(display,visual_info->screen);
if (visual_info->visual != XDefaultVisual(display,visual_info->screen))
colormap=XCreateColormap(display,XRootWindow(display,visual_info->screen),
visual_info->visual,visual_info->klass == DirectColor ?
AllocAll : AllocNone);
if (colormap == (Colormap) NULL)
ThrowXWindowFatalException(ResourceLimitFatalError,"UnableToCreateColormap",
image->filename);
/*
Initialize the map and pixel info structures.
*/
XGetMapInfo(visual_info,colormap,map_info);
XGetPixelInfo(display,visual_info,map_info,resource_info,image,pixel);
/*
Allocating colors in server colormap is based on visual class.
*/
switch (visual_info->klass)
{
case StaticGray:
case StaticColor:
{
/*
Define Standard Colormap for StaticGray or StaticColor visual.
*/
number_colors=image->colors;
colors=(XColor *) AcquireQuantumMemory((size_t)
visual_info->colormap_size,sizeof(*colors));
if (colors == (XColor *) NULL)
ThrowXWindowFatalException(ResourceLimitFatalError,
"UnableToCreateColormap",image->filename);
p=colors;
color.flags=(char) (DoRed | DoGreen | DoBlue);
for (i=0; i < (ssize_t) image->colors; i++)
{
color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
if (visual_info->klass != StaticColor)
{
gray_value=(unsigned short) XPixelIntensity(&color);
color.red=gray_value;
color.green=gray_value;
color.blue=gray_value;
}
status=XAllocColor(display,colormap,&color);
if (status == False)
{
colormap=XCopyColormapAndFree(display,colormap);
(void) XAllocColor(display,colormap,&color);
}
pixel->pixels[i]=color.pixel;
*p++=color;
}
break;
}
case GrayScale:
case PseudoColor:
{
unsigned int
colormap_type;
/*
Define Standard Colormap for GrayScale or PseudoColor visual.
*/
number_colors=image->colors;
colors=(XColor *) AcquireQuantumMemory((size_t)
visual_info->colormap_size,sizeof(*colors));
if (colors == (XColor *) NULL)
ThrowXWindowFatalException(ResourceLimitFatalError,
"UnableToCreateColormap",image->filename);
/*
Preallocate our GUI colors.
*/
(void) XAllocColor(display,colormap,&pixel->foreground_color);
(void) XAllocColor(display,colormap,&pixel->background_color);
(void) XAllocColor(display,colormap,&pixel->border_color);
(void) XAllocColor(display,colormap,&pixel->matte_color);
(void) XAllocColor(display,colormap,&pixel->highlight_color);
(void) XAllocColor(display,colormap,&pixel->shadow_color);
(void) XAllocColor(display,colormap,&pixel->depth_color);
(void) XAllocColor(display,colormap,&pixel->trough_color);
for (i=0; i < MaxNumberPens; i++)
(void) XAllocColor(display,colormap,&pixel->pen_colors[i]);
/*
Determine if image colors will "fit" into X server colormap.
*/
colormap_type=resource_info->colormap;
status=XAllocColorCells(display,colormap,MagickFalse,(unsigned long *)
NULL,0,pixel->pixels,(unsigned int) image->colors);
if (status != False)
colormap_type=PrivateColormap;
if (colormap_type == SharedColormap)
{
CacheView
*image_view;
DiversityPacket
*diversity;
int
y;
register int
x;
unsigned short
index;
XColor
*server_colors;
/*
Define Standard colormap for shared GrayScale or PseudoColor visual.
*/
diversity=(DiversityPacket *) AcquireQuantumMemory(image->colors,
sizeof(*diversity));
if (diversity == (DiversityPacket *) NULL)
ThrowXWindowFatalException(ResourceLimitFatalError,
"UnableToCreateColormap",image->filename);
for (i=0; i < (ssize_t) image->colors; i++)
{
diversity[i].red=ClampToQuantum(image->colormap[i].red);
diversity[i].green=ClampToQuantum(image->colormap[i].green);
diversity[i].blue=ClampToQuantum(image->colormap[i].blue);
diversity[i].index=(unsigned short) i;
diversity[i].count=0;
}
image_view=AcquireAuthenticCacheView(image,exception);
for (y=0; y < (int) image->rows; y++)
{
register int
x;
register const Quantum
*magick_restrict p;
p=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
image->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=(int) image->columns-1; x >= 0; x--)
{
diversity[(ssize_t) GetPixelIndex(image,p)].count++;
p+=GetPixelChannels(image);
}
}
image_view=DestroyCacheView(image_view);
/*
Sort colors by decreasing intensity.
*/
qsort((void *) diversity,image->colors,sizeof(*diversity),
IntensityCompare);
for (i=0; i < (ssize_t) image->colors; )
{
diversity[i].count<<=4; /* increase this colors popularity */
i+=MagickMax((int) (image->colors >> 4),2);
}
diversity[image->colors-1].count<<=4;
qsort((void *) diversity,image->colors,sizeof(*diversity),
PopularityCompare);
/*
Allocate colors.
*/
p=colors;
color.flags=(char) (DoRed | DoGreen | DoBlue);
for (i=0; i < (ssize_t) image->colors; i++)
{
index=diversity[i].index;
color.red=
ScaleQuantumToShort(XRedGamma(image->colormap[index].red));
color.green=
ScaleQuantumToShort(XGreenGamma(image->colormap[index].green));
color.blue=
ScaleQuantumToShort(XBlueGamma(image->colormap[index].blue));
if (visual_info->klass != PseudoColor)
{
gray_value=(unsigned short) XPixelIntensity(&color);
color.red=gray_value;
color.green=gray_value;
color.blue=gray_value;
}
status=XAllocColor(display,colormap,&color);
if (status == False)
break;
pixel->pixels[index]=color.pixel;
*p++=color;
}
/*
Read X server colormap.
*/
server_colors=(XColor *) AcquireQuantumMemory((size_t)
visual_info->colormap_size,sizeof(*server_colors));
if (server_colors == (XColor *) NULL)
ThrowXWindowFatalException(ResourceLimitFatalError,
"UnableToCreateColormap",image->filename);
for (x=visual_info->colormap_size-1; x >= 0; x--)
server_colors[x].pixel=(size_t) x;
(void) XQueryColors(display,colormap,server_colors,
(int) MagickMin((unsigned int) visual_info->colormap_size,256));
/*
Select remaining colors from X server colormap.
*/
for (; i < (ssize_t) image->colors; i++)
{
index=diversity[i].index;
color.red=ScaleQuantumToShort(
XRedGamma(image->colormap[index].red));
color.green=ScaleQuantumToShort(
XGreenGamma(image->colormap[index].green));
color.blue=ScaleQuantumToShort(
XBlueGamma(image->colormap[index].blue));
if (visual_info->klass != PseudoColor)
{
gray_value=(unsigned short) XPixelIntensity(&color);
color.red=gray_value;
color.green=gray_value;
color.blue=gray_value;
}
XBestPixel(display,colormap,server_colors,(unsigned int)
visual_info->colormap_size,&color);
pixel->pixels[index]=color.pixel;
*p++=color;
}
if ((int) image->colors < visual_info->colormap_size)
{
/*
Fill up colors array-- more choices for pen colors.
*/
retain_colors=MagickMin((unsigned int)
(visual_info->colormap_size-image->colors),256);
for (i=0; i < (ssize_t) retain_colors; i++)
*p++=server_colors[i];
number_colors+=retain_colors;
}
server_colors=(XColor *) RelinquishMagickMemory(server_colors);
diversity=(DiversityPacket *) RelinquishMagickMemory(diversity);
break;
}
/*
Define Standard colormap for private GrayScale or PseudoColor visual.
*/
if (status == False)
{
/*
Not enough colormap entries in the colormap-- Create a new colormap.
*/
colormap=XCreateColormap(display,
XRootWindow(display,visual_info->screen),visual_info->visual,
AllocNone);
if (colormap == (Colormap) NULL)
ThrowXWindowFatalException(ResourceLimitFatalError,
"UnableToCreateColormap",image->filename);
map_info->colormap=colormap;
if ((int) image->colors < visual_info->colormap_size)
{
/*
Retain colors from the default colormap to help lessens the
effects of colormap flashing.
*/
retain_colors=MagickMin((unsigned int)
(visual_info->colormap_size-image->colors),256);
p=colors+image->colors;
for (i=0; i < (ssize_t) retain_colors; i++)
{
p->pixel=(unsigned long) i;
p++;
}
(void) XQueryColors(display,
XDefaultColormap(display,visual_info->screen),
colors+image->colors,(int) retain_colors);
/*
Transfer colors from default to private colormap.
*/
(void) XAllocColorCells(display,colormap,MagickFalse,
(unsigned long *) NULL,0,pixel->pixels,(unsigned int)
retain_colors);
p=colors+image->colors;
for (i=0; i < (ssize_t) retain_colors; i++)
{
p->pixel=pixel->pixels[i];
p++;
}
(void) XStoreColors(display,colormap,colors+image->colors,
(int) retain_colors);
number_colors+=retain_colors;
}
(void) XAllocColorCells(display,colormap,MagickFalse,
(unsigned long *) NULL,0,pixel->pixels,(unsigned int)
image->colors);
}
/*
Store the image colormap.
*/
p=colors;
color.flags=(char) (DoRed | DoGreen | DoBlue);
for (i=0; i < (ssize_t) image->colors; i++)
{
color.red=ScaleQuantumToShort(XRedGamma(image->colormap[i].red));
color.green=ScaleQuantumToShort(XGreenGamma(image->colormap[i].green));
color.blue=ScaleQuantumToShort(XBlueGamma(image->colormap[i].blue));
if (visual_info->klass != PseudoColor)
{
gray_value=(unsigned short) XPixelIntensity(&color);
color.red=gray_value;
color.green=gray_value;
color.blue=gray_value;
}
color.pixel=pixel->pixels[i];
*p++=color;
}
(void) XStoreColors(display,colormap,colors,(int) image->colors);
break;
}
case TrueColor:
case DirectColor:
default:
{
MagickBooleanType
linear_colormap;
/*
Define Standard Colormap for TrueColor or DirectColor visual.
*/
number_colors=(unsigned int) ((map_info->red_max*map_info->red_mult)+
(map_info->green_max*map_info->green_mult)+
(map_info->blue_max*map_info->blue_mult)+1);
linear_colormap=(number_colors > 4096) ||
(((int) (map_info->red_max+1) == visual_info->colormap_size) &&
((int) (map_info->green_max+1) == visual_info->colormap_size) &&
((int) (map_info->blue_max+1) == visual_info->colormap_size)) ?
MagickTrue : MagickFalse;
if (linear_colormap != MagickFalse)
number_colors=(size_t) visual_info->colormap_size;
/*
Allocate color array.
*/
colors=(XColor *) AcquireQuantumMemory(number_colors,sizeof(*colors));
if (colors == (XColor *) NULL)
ThrowXWindowFatalException(ResourceLimitFatalError,
"UnableToCreateColormap",image->filename);
/*
Initialize linear color ramp.
*/
p=colors;
color.flags=(char) (DoRed | DoGreen | DoBlue);
if (linear_colormap != MagickFalse)
for (i=0; i < (ssize_t) number_colors; i++)
{
color.blue=(unsigned short) 0;
if (map_info->blue_max != 0)
color.blue=(unsigned short) ((size_t)
((65535L*(i % map_info->green_mult))/map_info->blue_max));
color.green=color.blue;
color.red=color.blue;
color.pixel=XStandardPixel(map_info,&color);
*p++=color;
}
else
for (i=0; i < (ssize_t) number_colors; i++)
{
color.red=(unsigned short) 0;
if (map_info->red_max != 0)
color.red=(unsigned short) ((size_t)
((65535L*(i/map_info->red_mult))/map_info->red_max));
color.green=(unsigned int) 0;
if (map_info->green_max != 0)
color.green=(unsigned short) ((size_t)
((65535L*((i/map_info->green_mult) % (map_info->green_max+1)))/
map_info->green_max));
color.blue=(unsigned short) 0;
if (map_info->blue_max != 0)
color.blue=(unsigned short) ((size_t)
((65535L*(i % map_info->green_mult))/map_info->blue_max));
color.pixel=XStandardPixel(map_info,&color);
*p++=color;
}
if ((visual_info->klass == DirectColor) &&
(colormap != XDefaultColormap(display,visual_info->screen)))
(void) XStoreColors(display,colormap,colors,(int) number_colors);
else
for (i=0; i < (ssize_t) number_colors; i++)
(void) XAllocColor(display,colormap,&colors[i]);
break;
}
}
if ((visual_info->klass != DirectColor) &&
(visual_info->klass != TrueColor))
{
/*
Set foreground, background, border, etc. pixels.
*/
XBestPixel(display,colormap,colors,(unsigned int) number_colors,
&pixel->foreground_color);
XBestPixel(display,colormap,colors,(unsigned int) number_colors,
&pixel->background_color);
if (pixel->background_color.pixel == pixel->foreground_color.pixel)
{
/*
Foreground and background colors must differ.
*/
pixel->background_color.red=(~pixel->foreground_color.red);
pixel->background_color.green=
(~pixel->foreground_color.green);
pixel->background_color.blue=
(~pixel->foreground_color.blue);
XBestPixel(display,colormap,colors,(unsigned int) number_colors,
&pixel->background_color);
}
XBestPixel(display,colormap,colors,(unsigned int) number_colors,
&pixel->border_color);
XBestPixel(display,colormap,colors,(unsigned int) number_colors,
&pixel->matte_color);
XBestPixel(display,colormap,colors,(unsigned int) number_colors,
&pixel->highlight_color);
XBestPixel(display,colormap,colors,(unsigned int) number_colors,
&pixel->shadow_color);
XBestPixel(display,colormap,colors,(unsigned int) number_colors,
&pixel->depth_color);
XBestPixel(display,colormap,colors,(unsigned int) number_colors,
&pixel->trough_color);
for (i=0; i < MaxNumberPens; i++)
{
XBestPixel(display,colormap,colors,(unsigned int) number_colors,
&pixel->pen_colors[i]);
pixel->pixels[image->colors+i]=pixel->pen_colors[i].pixel;
}
pixel->colors=(ssize_t) (image->colors+MaxNumberPens);
}
colors=(XColor *) RelinquishMagickMemory(colors);
if (IsEventLogging())
{
(void) LogMagickEvent(X11Event,GetMagickModule(),"Standard Colormap:");
(void) LogMagickEvent(X11Event,GetMagickModule()," colormap id: 0x%lx",
map_info->colormap);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" red, green, blue max: %lu %lu %lu",map_info->red_max,
map_info->green_max,map_info->blue_max);
(void) LogMagickEvent(X11Event,GetMagickModule(),
" red, green, blue mult: %lu %lu %lu",map_info->red_mult,
map_info->green_mult,map_info->blue_mult);
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X M a k e W i n d o w %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XMakeWindow() creates an X11 window.
%
% The format of the XMakeWindow method is:
%
% void XMakeWindow(Display *display,Window parent,char **argv,int argc,
% XClassHint *class_hint,XWMHints *manager_hints,
% XWindowInfo *window_info)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o parent: Specifies the parent window_info.
%
% o argv: Specifies the application's argument list.
%
% o argc: Specifies the number of arguments.
%
% o class_hint: Specifies a pointer to a X11 XClassHint structure.
%
% o manager_hints: Specifies a pointer to a X11 XWMHints structure.
%
% o window_info: Specifies a pointer to a X11 XWindowInfo structure.
%
*/
MagickPrivate void XMakeWindow(Display *display,Window parent,char **argv,
int argc,XClassHint *class_hint,XWMHints *manager_hints,
XWindowInfo *window_info)
{
#define MinWindowSize 64
Atom
atom_list[2];
int
gravity;
static XTextProperty
icon_name,
window_name;
Status
status;
XSizeHints
*size_hints;
/*
Set window info hints.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(window_info != (XWindowInfo *) NULL);
size_hints=XAllocSizeHints();
if (size_hints == (XSizeHints *) NULL)
ThrowXWindowFatalException(XServerFatalError,"UnableToMakeXWindow",argv[0]);
size_hints->flags=(int) window_info->flags;
size_hints->x=window_info->x;
size_hints->y=window_info->y;
size_hints->width=(int) window_info->width;
size_hints->height=(int) window_info->height;
if (window_info->immutable != MagickFalse)
{
/*
Window size cannot be changed.
*/
size_hints->min_width=size_hints->width;
size_hints->min_height=size_hints->height;
size_hints->max_width=size_hints->width;
size_hints->max_height=size_hints->height;
size_hints->flags|=PMinSize;
size_hints->flags|=PMaxSize;
}
else
{
/*
Window size can be changed.
*/
size_hints->min_width=(int) window_info->min_width;
size_hints->min_height=(int) window_info->min_height;
size_hints->flags|=PResizeInc;
size_hints->width_inc=(int) window_info->width_inc;
size_hints->height_inc=(int) window_info->height_inc;
#if !defined(PRE_R4_ICCCM)
size_hints->flags|=PBaseSize;
size_hints->base_width=size_hints->width_inc;
size_hints->base_height=size_hints->height_inc;
#endif
}
gravity=NorthWestGravity;
if (window_info->geometry != (char *) NULL)
{
char
default_geometry[MagickPathExtent],
geometry[MagickPathExtent];
int
flags;
register char
*p;
/*
User specified geometry.
*/
(void) FormatLocaleString(default_geometry,MagickPathExtent,"%dx%d",
size_hints->width,size_hints->height);
(void) CopyMagickString(geometry,window_info->geometry,MagickPathExtent);
p=geometry;
while (strlen(p) != 0)
{
if ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '%'))
p++;
else
(void) memmove(p,p+1,MagickPathExtent-(p-geometry));
}
flags=XWMGeometry(display,window_info->screen,geometry,default_geometry,
window_info->border_width,size_hints,&size_hints->x,&size_hints->y,
&size_hints->width,&size_hints->height,&gravity);
if ((flags & WidthValue) && (flags & HeightValue))
size_hints->flags|=USSize;
if ((flags & XValue) && (flags & YValue))
{
size_hints->flags|=USPosition;
window_info->x=size_hints->x;
window_info->y=size_hints->y;
}
}
#if !defined(PRE_R4_ICCCM)
size_hints->win_gravity=gravity;
size_hints->flags|=PWinGravity;
#endif
if (window_info->id == (Window) NULL)
window_info->id=XCreateWindow(display,parent,window_info->x,window_info->y,
(unsigned int) size_hints->width,(unsigned int) size_hints->height,
window_info->border_width,(int) window_info->depth,InputOutput,
window_info->visual,(unsigned long) window_info->mask,
&window_info->attributes);
else
{
MagickStatusType
mask;
XEvent
sans_event;
XWindowChanges
window_changes;
/*
Window already exists; change relevant attributes.
*/
(void) XChangeWindowAttributes(display,window_info->id,(unsigned long)
window_info->mask,&window_info->attributes);
mask=ConfigureNotify;
while (XCheckTypedWindowEvent(display,window_info->id,(int) mask,&sans_event)) ;
window_changes.x=window_info->x;
window_changes.y=window_info->y;
window_changes.width=(int) window_info->width;
window_changes.height=(int) window_info->height;
mask=(MagickStatusType) (CWWidth | CWHeight);
if (window_info->flags & USPosition)
mask|=CWX | CWY;
(void) XReconfigureWMWindow(display,window_info->id,window_info->screen,
mask,&window_changes);
}
if (window_info->id == (Window) NULL)
ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
window_info->name);
status=XStringListToTextProperty(&window_info->name,1,&window_name);
if (status == False)
ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
window_info->name);
status=XStringListToTextProperty(&window_info->icon_name,1,&icon_name);
if (status == False)
ThrowXWindowFatalException(XServerFatalError,"UnableToCreateTextProperty",
window_info->icon_name);
if (window_info->icon_geometry != (char *) NULL)
{
int
flags,
height,
width;
/*
User specified icon geometry.
*/
size_hints->flags|=USPosition;
flags=XWMGeometry(display,window_info->screen,window_info->icon_geometry,
(char *) NULL,0,size_hints,&manager_hints->icon_x,
&manager_hints->icon_y,&width,&height,&gravity);
if ((flags & XValue) && (flags & YValue))
manager_hints->flags|=IconPositionHint;
}
XSetWMProperties(display,window_info->id,&window_name,&icon_name,argv,argc,
size_hints,manager_hints,class_hint);
if (window_name.value != (void *) NULL)
{
(void) XFree((void *) window_name.value);
window_name.value=(unsigned char *) NULL;
window_name.nitems=0;
}
if (icon_name.value != (void *) NULL)
{
(void) XFree((void *) icon_name.value);
icon_name.value=(unsigned char *) NULL;
icon_name.nitems=0;
}
atom_list[0]=XInternAtom(display,"WM_DELETE_WINDOW",MagickFalse);
atom_list[1]=XInternAtom(display,"WM_TAKE_FOCUS",MagickFalse);
(void) XSetWMProtocols(display,window_info->id,atom_list,2);
(void) XFree((void *) size_hints);
if (window_info->shape != MagickFalse)
{
#if defined(MAGICKCORE_HAVE_SHAPE)
int
error_base,
event_base;
/*
Can we apply a non-rectangular shaping mask?
*/
error_base=0;
event_base=0;
if (XShapeQueryExtension(display,&error_base,&event_base) == 0)
window_info->shape=MagickFalse;
#else
window_info->shape=MagickFalse;
#endif
}
if (window_info->shared_memory)
{
#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
/*
Can we use shared memory with this window?
*/
if (XShmQueryExtension(display) == 0)
window_info->shared_memory=MagickFalse;
#else
window_info->shared_memory=MagickFalse;
#endif
}
window_info->image=NewImageList();
window_info->destroy=MagickFalse;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X M a g i c k P r o g r e s s M o n i t o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XMagickProgressMonitor() displays the progress a task is making in
% completing a task.
%
% The format of the XMagickProgressMonitor method is:
%
% void XMagickProgressMonitor(const char *task,
% const MagickOffsetType quantum,const MagickSizeType span,
% void *client_data)
%
% A description of each parameter follows:
%
% o task: Identifies the task in progress.
%
% o quantum: Specifies the quantum position within the span which represents
% how much progress has been made in completing a task.
%
% o span: Specifies the span relative to completing a task.
%
% o client_data: Pointer to any client data.
%
*/
static const char *GetLocaleMonitorMessage(const char *text)
{
char
message[MagickPathExtent],
tag[MagickPathExtent];
const char
*locale_message;
register char
*p;
(void) CopyMagickString(tag,text,MagickPathExtent);
p=strrchr(tag,'/');
if (p != (char *) NULL)
*p='\0';
(void) FormatLocaleString(message,MagickPathExtent,"Monitor/%s",tag);
locale_message=GetLocaleMessage(message);
if (locale_message == message)
return(text);
return(locale_message);
}
MagickPrivate MagickBooleanType XMagickProgressMonitor(const char *tag,
const MagickOffsetType quantum,const MagickSizeType span,
void *magick_unused(client_data))
{
XWindows
*windows;
windows=XSetWindows((XWindows *) ~0);
if (windows == (XWindows *) NULL)
return(MagickTrue);
if (windows->info.mapped != MagickFalse)
XProgressMonitorWidget(windows->display,windows,
GetLocaleMonitorMessage(tag),quantum,span);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X Q u e r y C o l o r D a t a b a s e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XQueryColorCompliance() looks up a RGB values for a color given in the target
% string.
%
% The format of the XQueryColorDatabase method is:
%
% MagickBooleanType XQueryColorCompliance(const char *target,XColor *color)
%
% A description of each parameter follows:
%
% o target: Specifies the color to lookup in the X color database.
%
% o color: A pointer to an PixelInfo structure. The RGB value of the target
% color is returned as this value.
%
*/
MagickPrivate MagickBooleanType XQueryColorCompliance(const char *target,
XColor *color)
{
Colormap
colormap;
static Display
*display = (Display *) NULL;
Status
status;
XColor
xcolor;
/*
Initialize color return value.
*/
assert(color != (XColor *) NULL);
color->red=0;
color->green=0;
color->blue=0;
color->flags=(char) (DoRed | DoGreen | DoBlue);
if ((target == (char *) NULL) || (*target == '\0'))
target="#ffffffffffff";
/*
Let the X server define the color for us.
*/
if (display == (Display *) NULL)
display=XOpenDisplay((char *) NULL);
if (display == (Display *) NULL)
{
ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target);
return(MagickFalse);
}
colormap=XDefaultColormap(display,XDefaultScreen(display));
status=XParseColor(display,colormap,(char *) target,&xcolor);
if (status == False)
ThrowXWindowException(XServerError,"ColorIsNotKnownToServer",target)
else
{
color->red=xcolor.red;
color->green=xcolor.green;
color->blue=xcolor.blue;
color->flags=xcolor.flags;
}
return(status != False ? MagickTrue : MagickFalse);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X Q u e r y P o s i t i o n %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XQueryPosition() gets the pointer coordinates relative to a window.
%
% The format of the XQueryPosition method is:
%
% void XQueryPosition(Display *display,const Window window,int *x,int *y)
%
% 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.
%
% o x: Return the x coordinate of the pointer relative to the origin of the
% window.
%
% o y: Return the y coordinate of the pointer relative to the origin of the
% window.
%
*/
MagickPrivate void XQueryPosition(Display *display,const Window window,int *x,
int *y)
{
int
x_root,
y_root;
unsigned int
mask;
Window
root_window;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(window != (Window) NULL);
assert(x != (int *) NULL);
assert(y != (int *) NULL);
(void) XQueryPointer(display,window,&root_window,&root_window,&x_root,&y_root,
x,y,&mask);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X R e f r e s h W i n d o w %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XRefreshWindow() refreshes an image in a X window.
%
% The format of the XRefreshWindow method is:
%
% void XRefreshWindow(Display *display,const XWindowInfo *window,
% const XEvent *event)
%
% 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 XWindowInfo structure.
%
% o event: Specifies a pointer to a XEvent structure. If it is NULL,
% the entire image is refreshed.
%
*/
MagickPrivate void XRefreshWindow(Display *display,const XWindowInfo *window,
const XEvent *event)
{
int
x,
y;
unsigned int
height,
width;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(window != (XWindowInfo *) NULL);
if (window->ximage == (XImage *) NULL)
return;
if (event != (XEvent *) NULL)
{
/*
Determine geometry from expose event.
*/
x=event->xexpose.x;
y=event->xexpose.y;
width=(unsigned int) event->xexpose.width;
height=(unsigned int) event->xexpose.height;
}
else
{
XEvent
sans_event;
/*
Refresh entire window; discard outstanding expose events.
*/
x=0;
y=0;
width=window->width;
height=window->height;
while (XCheckTypedWindowEvent(display,window->id,Expose,&sans_event)) ;
if (window->matte_pixmap != (Pixmap) NULL)
{
#if defined(MAGICKCORE_HAVE_SHAPE)
if (window->shape != MagickFalse)
XShapeCombineMask(display,window->id,ShapeBounding,0,0,
window->matte_pixmap,ShapeSet);
#endif
}
}
/*
Check boundary conditions.
*/
if ((window->ximage->width-(x+window->x)) < (int) width)
width=(unsigned int) (window->ximage->width-(x+window->x));
if ((window->ximage->height-(y+window->y)) < (int) height)
height=(unsigned int) (window->ximage->height-(y+window->y));
/*
Refresh image.
*/
if (window->matte_pixmap != (Pixmap) NULL)
(void) XSetClipMask(display,window->annotate_context,window->matte_pixmap);
if (window->pixmap != (Pixmap) NULL)
{
if (window->depth > 1)
(void) XCopyArea(display,window->pixmap,window->id,
window->annotate_context,x+window->x,y+window->y,width,height,x,y);
else
(void) XCopyPlane(display,window->pixmap,window->id,
window->highlight_context,x+window->x,y+window->y,width,height,x,y,
1L);
}
else
{
#if defined(MAGICKCORE_HAVE_SHARED_MEMORY)
if (window->shared_memory)
(void) XShmPutImage(display,window->id,window->annotate_context,
window->ximage,x+window->x,y+window->y,x,y,width,height,MagickTrue);
#endif
if (window->shared_memory == MagickFalse)
(void) XPutImage(display,window->id,window->annotate_context,
window->ximage,x+window->x,y+window->y,x,y,width,height);
}
if (window->matte_pixmap != (Pixmap) NULL)
(void) XSetClipMask(display,window->annotate_context,None);
(void) XFlush(display);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X R e m o t e C o m m a n d %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XRemoteCommand() forces a remote display(1) to display the specified
% image filename.
%
% The format of the XRemoteCommand method is:
%
% MagickBooleanType XRemoteCommand(Display *display,const char *window,
% const char *filename)
%
% A description of each parameter follows:
%
% o display: Specifies a connection to an X server; returned from
% XOpenDisplay.
%
% o window: Specifies the name or id of an X window.
%
% o filename: the name of the image filename to display.
%
*/
MagickExport MagickBooleanType XRemoteCommand(Display *display,
const char *window,const char *filename)
{
Atom
remote_atom;
Window
remote_window,
root_window;
assert(filename != (char *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
if (display == (Display *) NULL)
display=XOpenDisplay((char *) NULL);
if (display == (Display *) NULL)
{
ThrowXWindowException(XServerError,"UnableToOpenXServer",filename);
return(MagickFalse);
}
remote_atom=XInternAtom(display,"IM_PROTOCOLS",MagickFalse);
remote_window=(Window) NULL;
root_window=XRootWindow(display,XDefaultScreen(display));
if (window != (char *) NULL)
{
/*
Search window hierarchy and identify any clients by name or ID.
*/
if (isdigit((int) ((unsigned char) *window)) != 0)
remote_window=XWindowByID(display,root_window,(Window)
strtol((char *) window,(char **) NULL,0));
if (remote_window == (Window) NULL)
remote_window=XWindowByName(display,root_window,window);
}
if (remote_window == (Window) NULL)
remote_window=XWindowByProperty(display,root_window,remote_atom);
if (remote_window == (Window) NULL)
{
ThrowXWindowException(XServerError,"UnableToConnectToRemoteDisplay",
filename);
return(MagickFalse);
}
/*
Send remote command.
*/
remote_atom=XInternAtom(display,"IM_REMOTE_COMMAND",MagickFalse);
(void) XChangeProperty(display,remote_window,remote_atom,XA_STRING,8,
PropModeReplace,(unsigned char *) filename,(int) strlen(filename));
(void) XSync(display,MagickFalse);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X R e n d e r I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XRenderImage() renders text on the image with an X11 font. It also returns
% the bounding box of the text relative to the image.
%
% The format of the XRenderImage method is:
%
% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o draw_info: the draw info.
%
% o offset: (x,y) location of text relative to image.
%
% o metrics: bounding box of text.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickPrivate MagickBooleanType XRenderImage(Image *image,
const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
ExceptionInfo *exception)
{
const char
*client_name;
DrawInfo
cache_info;
Display
*display;
ImageInfo
*image_info;
MagickBooleanType
status;
size_t
height,
width;
XAnnotateInfo
annotate_info;
XFontStruct
*font_info;
XPixelInfo
pixel;
XResourceInfo
resource_info;
XrmDatabase
resource_database;
XStandardColormap
*map_info;
XVisualInfo
*visual_info;
/*
Open X server connection.
*/
display=XOpenDisplay(draw_info->server_name);
if (display == (Display *) NULL)
{
ThrowXWindowException(XServerError,"UnableToOpenXServer",
draw_info->server_name);
return(MagickFalse);
}
/*
Get user defaults from X resource database.
*/
(void) XSetErrorHandler(XError);
image_info=AcquireImageInfo();
client_name=GetClientName();
resource_database=XGetResourceDatabase(display,client_name);
XGetResourceInfo(image_info,resource_database,client_name,&resource_info);
resource_info.close_server=MagickFalse;
resource_info.colormap=PrivateColormap;
resource_info.font=AcquireString(draw_info->font);
resource_info.background_color=AcquireString("#ffffffffffff");
resource_info.foreground_color=AcquireString("#000000000000");
map_info=XAllocStandardColormap();
visual_info=(XVisualInfo *) NULL;
font_info=(XFontStruct *) NULL;
pixel.pixels=(unsigned long *) NULL;
if (map_info == (XStandardColormap *) NULL)
{
ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
return(MagickFalse);
}
/*
Initialize visual info.
*/
visual_info=XBestVisualInfo(display,map_info,&resource_info);
if (visual_info == (XVisualInfo *) NULL)
{
XFreeResources(display,visual_info,map_info,&pixel,font_info,
&resource_info,(XWindowInfo *) NULL);
ThrowXWindowException(XServerError,"UnableToGetVisual",image->filename);
return(MagickFalse);
}
map_info->colormap=(Colormap) NULL;
/*
Initialize Standard Colormap info.
*/
XGetMapInfo(visual_info,XDefaultColormap(display,visual_info->screen),
map_info);
XGetPixelInfo(display,visual_info,map_info,&resource_info,(Image *) NULL,
&pixel);
pixel.annotate_context=XDefaultGC(display,visual_info->screen);
/*
Initialize font info.
*/
font_info=XBestFont(display,&resource_info,MagickFalse);
if (font_info == (XFontStruct *) NULL)
{
XFreeResources(display,visual_info,map_info,&pixel,font_info,
&resource_info,(XWindowInfo *) NULL);
ThrowXWindowException(XServerError,"UnableToLoadFont",draw_info->font);
return(MagickFalse);
}
cache_info=(*draw_info);
/*
Initialize annotate info.
*/
XGetAnnotateInfo(&annotate_info);
annotate_info.stencil=ForegroundStencil;
if (cache_info.font != draw_info->font)
{
/*
Type name has changed.
*/
(void) XFreeFont(display,font_info);
(void) CloneString(&resource_info.font,draw_info->font);
font_info=XBestFont(display,&resource_info,MagickFalse);
if (font_info == (XFontStruct *) NULL)
{
ThrowXWindowException(XServerError,"UnableToLoadFont",
draw_info->font);
return(MagickFalse);
}
}
if (image->debug != MagickFalse)
(void) LogMagickEvent(AnnotateEvent,GetMagickModule(),
"Font %s; pointsize %g",draw_info->font != (char *) NULL ?
draw_info->font : "none",draw_info->pointsize);
cache_info=(*draw_info);
annotate_info.font_info=font_info;
annotate_info.text=(char *) draw_info->text;
annotate_info.width=(unsigned int) XTextWidth(font_info,draw_info->text,(int)
strlen(draw_info->text));
annotate_info.height=(unsigned int) font_info->ascent+font_info->descent;
metrics->pixels_per_em.x=(double) font_info->max_bounds.width;
metrics->pixels_per_em.y=(double) font_info->ascent+font_info->descent;
metrics->ascent=(double) font_info->ascent+4;
metrics->descent=(double) (-font_info->descent);
metrics->width=annotate_info.width/ExpandAffine(&draw_info->affine);
metrics->height=(double) font_info->ascent+font_info->descent;
metrics->max_advance=(double) font_info->max_bounds.width;
metrics->bounds.x1=0.0;
metrics->bounds.y1=metrics->descent;
metrics->bounds.x2=metrics->ascent+metrics->descent;
metrics->bounds.y2=metrics->ascent+metrics->descent;
metrics->underline_position=(-2.0);
metrics->underline_thickness=1.0;
if (draw_info->render == MagickFalse)
return(MagickTrue);
if (draw_info->fill.alpha == TransparentAlpha)
return(MagickTrue);
/*
Render fill color.
*/
width=annotate_info.width;
height=annotate_info.height;
if ((fabs(draw_info->affine.rx) >= MagickEpsilon) ||
(fabs(draw_info->affine.ry) >= MagickEpsilon))
{
if ((fabs(draw_info->affine.sx-draw_info->affine.sy) < MagickEpsilon) &&
(fabs(draw_info->affine.rx+draw_info->affine.ry) < MagickEpsilon))
annotate_info.degrees=(double) (180.0/MagickPI)*
atan2(draw_info->affine.rx,draw_info->affine.sx);
}
(void) FormatLocaleString(annotate_info.geometry,MagickPathExtent,
"%.20gx%.20g%+.20g%+.20g",(double) width,(double) height,
ceil(offset->x-0.5),ceil(offset->y-metrics->ascent-metrics->descent+
draw_info->interline_spacing-0.5));
pixel.pen_color.red=ScaleQuantumToShort(
ClampToQuantum(draw_info->fill.red));
pixel.pen_color.green=ScaleQuantumToShort(
ClampToQuantum(draw_info->fill.green));
pixel.pen_color.blue=ScaleQuantumToShort(
ClampToQuantum(draw_info->fill.blue));
status=XAnnotateImage(display,&pixel,&annotate_info,image,exception);
if (status == 0)
{
ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
return(MagickFalse);
}
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X R e t a i n W i n d o w C o l o r s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XRetainWindowColors() sets X11 color resources on a window. This preserves
% the colors associated with an image displayed on the window.
%
% The format of the XRetainWindowColors method is:
%
% void XRetainWindowColors(Display *display,const 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 XWindowInfo structure.
%
*/
MagickExport void XRetainWindowColors(Display *display,const Window window)
{
Atom
property;
Pixmap
pixmap;
/*
Put property on the window.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(window != (Window) NULL);
property=XInternAtom(display,"_XSETROOT_ID",MagickFalse);
if (property == (Atom) NULL)
{
ThrowXWindowException(XServerError,"UnableToCreateProperty",
"_XSETROOT_ID");
return;
}
pixmap=XCreatePixmap(display,window,1,1,1);
if (pixmap == (Pixmap) NULL)
{
ThrowXWindowException(XServerError,"UnableToCreateBitmap","");
return;
}
(void) XChangeProperty(display,window,property,XA_PIXMAP,32,PropModeReplace,
(unsigned char *) &pixmap,1);
(void) XSetCloseDownMode(display,RetainPermanent);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X S e l e c t W i n d o w %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XSelectWindow() allows a user to select a window using the mouse. If the
% mouse moves, a cropping rectangle is drawn and the extents of the rectangle
% is returned in the crop_info structure.
%
% The format of the XSelectWindow function is:
%
% target_window=XSelectWindow(display,crop_info)
%
% A description of each parameter follows:
%
% o window: XSelectWindow returns the window id.
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o crop_info: Specifies a pointer to a RectangleInfo structure. It
% contains the extents of any cropping rectangle.
%
*/
static Window XSelectWindow(Display *display,RectangleInfo *crop_info)
{
#define MinimumCropArea (unsigned int) 9
Cursor
target_cursor;
GC
annotate_context;
int
presses,
x_offset,
y_offset;
Status
status;
Window
root_window,
target_window;
XEvent
event;
XGCValues
context_values;
/*
Initialize graphic context.
*/
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(crop_info != (RectangleInfo *) NULL);
root_window=XRootWindow(display,XDefaultScreen(display));
context_values.background=XBlackPixel(display,XDefaultScreen(display));
context_values.foreground=XWhitePixel(display,XDefaultScreen(display));
context_values.function=GXinvert;
context_values.plane_mask=
context_values.background ^ context_values.foreground;
context_values.subwindow_mode=IncludeInferiors;
annotate_context=XCreateGC(display,root_window,(size_t) (GCBackground |
GCForeground | GCFunction | GCSubwindowMode),&context_values);
if (annotate_context == (GC) NULL)
return(MagickFalse);
/*
Grab the pointer using target cursor.
*/
target_cursor=XMakeCursor(display,root_window,XDefaultColormap(display,
XDefaultScreen(display)),(char * ) "white",(char * ) "black");
status=XGrabPointer(display,root_window,MagickFalse,(unsigned int)
(ButtonPressMask | ButtonReleaseMask | ButtonMotionMask),GrabModeSync,
GrabModeAsync,root_window,target_cursor,CurrentTime);
if (status != GrabSuccess)
{
ThrowXWindowException(XServerError,"UnableToGrabMouse","");
return((Window) NULL);
}
/*
Select a window.
*/
crop_info->width=0;
crop_info->height=0;
presses=0;
target_window=(Window) NULL;
x_offset=0;
y_offset=0;
do
{
if ((crop_info->width*crop_info->height) >= MinimumCropArea)
(void) XDrawRectangle(display,root_window,annotate_context,
(int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
(unsigned int) crop_info->height-1);
/*
Allow another event.
*/
(void) XAllowEvents(display,SyncPointer,CurrentTime);
(void) XWindowEvent(display,root_window,ButtonPressMask |
ButtonReleaseMask | ButtonMotionMask,&event);
if ((crop_info->width*crop_info->height) >= MinimumCropArea)
(void) XDrawRectangle(display,root_window,annotate_context,
(int) crop_info->x,(int) crop_info->y,(unsigned int) crop_info->width-1,
(unsigned int) crop_info->height-1);
switch (event.type)
{
case ButtonPress:
{
target_window=XGetSubwindow(display,event.xbutton.subwindow,
event.xbutton.x,event.xbutton.y);
if (target_window == (Window) NULL)
target_window=root_window;
x_offset=event.xbutton.x_root;
y_offset=event.xbutton.y_root;
crop_info->x=(ssize_t) x_offset;
crop_info->y=(ssize_t) y_offset;
crop_info->width=0;
crop_info->height=0;
presses++;
break;
}
case ButtonRelease:
{
presses--;
break;
}
case MotionNotify:
{
/*
Discard pending button motion events.
*/
while (XCheckMaskEvent(display,ButtonMotionMask,&event)) ;
crop_info->x=(ssize_t) event.xmotion.x;
crop_info->y=(ssize_t) event.xmotion.y;
/*
Check boundary conditions.
*/
if ((int) crop_info->x < x_offset)
crop_info->width=(size_t) (x_offset-crop_info->x);
else
{
crop_info->width=(size_t) (crop_info->x-x_offset);
crop_info->x=(ssize_t) x_offset;
}
if ((int) crop_info->y < y_offset)
crop_info->height=(size_t) (y_offset-crop_info->y);
else
{
crop_info->height=(size_t) (crop_info->y-y_offset);
crop_info->y=(ssize_t) y_offset;
}
}
default:
break;
}
} while ((target_window == (Window) NULL) || (presses > 0));
(void) XUngrabPointer(display,CurrentTime);
(void) XFreeCursor(display,target_cursor);
(void) XFreeGC(display,annotate_context);
if ((crop_info->width*crop_info->height) < MinimumCropArea)
{
crop_info->width=0;
crop_info->height=0;
}
if ((crop_info->width != 0) && (crop_info->height != 0))
target_window=root_window;
return(target_window);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X S e t C u r s o r S t a t e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XSetCursorState() sets the cursor state to busy, otherwise the cursor are
% reset to their default.
%
% The format of the XXSetCursorState method is:
%
% XSetCursorState(display,windows,const MagickStatusType state)
%
% 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.
%
% o state: An unsigned integer greater than 0 sets the cursor state
% to busy, otherwise the cursor are reset to their default.
%
*/
MagickPrivate void XSetCursorState(Display *display,XWindows *windows,
const MagickStatusType state)
{
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(windows != (XWindows *) NULL);
if (state)
{
(void) XCheckDefineCursor(display,windows->image.id,
windows->image.busy_cursor);
(void) XCheckDefineCursor(display,windows->pan.id,
windows->pan.busy_cursor);
(void) XCheckDefineCursor(display,windows->magnify.id,
windows->magnify.busy_cursor);
(void) XCheckDefineCursor(display,windows->command.id,
windows->command.busy_cursor);
}
else
{
(void) XCheckDefineCursor(display,windows->image.id,
windows->image.cursor);
(void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
(void) XCheckDefineCursor(display,windows->magnify.id,
windows->magnify.cursor);
(void) XCheckDefineCursor(display,windows->command.id,
windows->command.cursor);
(void) XCheckDefineCursor(display,windows->command.id,
windows->widget.cursor);
(void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
}
windows->info.mapped=MagickFalse;
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X S e t W i n d o w s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XSetWindows() sets the X windows structure if the windows info is specified.
% Otherwise the current windows structure is returned.
%
% The format of the XSetWindows method is:
%
% XWindows *XSetWindows(XWindows *windows_info)
%
% A description of each parameter follows:
%
% o windows_info: Initialize the Windows structure with this information.
%
*/
MagickPrivate XWindows *XSetWindows(XWindows *windows_info)
{
static XWindows
*windows = (XWindows *) NULL;
if (windows_info != (XWindows *) ~0)
{
windows=(XWindows *) RelinquishMagickMemory(windows);
windows=windows_info;
}
return(windows);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X U s e r P r e f e r e n c e s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XUserPreferences() saves the preferences in a configuration file in the
% users' home directory.
%
% The format of the XUserPreferences method is:
%
% void XUserPreferences(XResourceInfo *resource_info)
%
% A description of each parameter follows:
%
% o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
%
*/
MagickPrivate void XUserPreferences(XResourceInfo *resource_info)
{
#if defined(X11_PREFERENCES_PATH)
char
cache[MagickPathExtent],
filename[MagickPathExtent],
specifier[MagickPathExtent];
const char
*client_name,
*value;
XrmDatabase
preferences_database;
/*
Save user preferences to the client configuration file.
*/
assert(resource_info != (XResourceInfo *) NULL);
client_name=GetClientName();
preferences_database=XrmGetStringDatabase("");
(void) FormatLocaleString(specifier,MagickPathExtent,"%s.backdrop",client_name);
value=resource_info->backdrop ? "True" : "False";
XrmPutStringResource(&preferences_database,specifier,(char *) value);
(void) FormatLocaleString(specifier,MagickPathExtent,"%s.colormap",client_name);
value=resource_info->colormap == SharedColormap ? "Shared" : "Private";
XrmPutStringResource(&preferences_database,specifier,(char *) value);
(void) FormatLocaleString(specifier,MagickPathExtent,"%s.confirmExit",
client_name);
value=resource_info->confirm_exit ? "True" : "False";
XrmPutStringResource(&preferences_database,specifier,(char *) value);
(void) FormatLocaleString(specifier,MagickPathExtent,"%s.confirmEdit",
client_name);
value=resource_info->confirm_edit ? "True" : "False";
XrmPutStringResource(&preferences_database,specifier,(char *) value);
(void) FormatLocaleString(specifier,MagickPathExtent,"%s.displayWarnings",
client_name);
value=resource_info->display_warnings ? "True" : "False";
XrmPutStringResource(&preferences_database,specifier,(char *) value);
(void) FormatLocaleString(specifier,MagickPathExtent,"%s.dither",client_name);
value=resource_info->quantize_info->dither_method != NoDitherMethod ?
"True" : "False";
XrmPutStringResource(&preferences_database,specifier,(char *) value);
(void) FormatLocaleString(specifier,MagickPathExtent,"%s.gammaCorrect",
client_name);
value=resource_info->gamma_correct ? "True" : "False";
XrmPutStringResource(&preferences_database,specifier,(char *) value);
(void) FormatLocaleString(specifier,MagickPathExtent,"%s.undoCache",client_name);
(void) FormatLocaleString(cache,MagickPathExtent,"%.20g",(double)
resource_info->undo_cache);
XrmPutStringResource(&preferences_database,specifier,cache);
(void) FormatLocaleString(specifier,MagickPathExtent,"%s.usePixmap",client_name);
value=resource_info->use_pixmap ? "True" : "False";
XrmPutStringResource(&preferences_database,specifier,(char *) value);
(void) FormatLocaleString(filename,MagickPathExtent,"%s%src",
X11_PREFERENCES_PATH,client_name);
ExpandFilename(filename);
XrmPutFileDatabase(preferences_database,filename);
#endif
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X V i s u a l C l a s s N a m e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XVisualClassName() returns the visual class name as a character string.
%
% The format of the XVisualClassName method is:
%
% char *XVisualClassName(const int visual_class)
%
% A description of each parameter follows:
%
% o visual_type: XVisualClassName returns the visual class as a character
% string.
%
% o class: Specifies the visual class.
%
*/
static const char *XVisualClassName(const int visual_class)
{
switch (visual_class)
{
case StaticGray: return("StaticGray");
case GrayScale: return("GrayScale");
case StaticColor: return("StaticColor");
case PseudoColor: return("PseudoColor");
case TrueColor: return("TrueColor");
case DirectColor: return("DirectColor");
}
return("unknown visual class");
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X W a r n i n g %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XWarning() displays a warning reason in a Notice widget.
%
% The format of the XWarning method is:
%
% void XWarning(const unsigned int warning,const char *reason,
% const char *description)
%
% A description of each parameter follows:
%
% o warning: Specifies the numeric warning category.
%
% o reason: Specifies the reason to display before terminating the
% program.
%
% o description: Specifies any description to the reason.
%
*/
MagickPrivate void XWarning(const ExceptionType magick_unused(warning),
const char *reason,const char *description)
{
char
text[MagickPathExtent];
XWindows
*windows;
if (reason == (char *) NULL)
return;
(void) CopyMagickString(text,reason,MagickPathExtent);
(void) ConcatenateMagickString(text,":",MagickPathExtent);
windows=XSetWindows((XWindows *) ~0);
XNoticeWidget(windows->display,windows,text,(char *) description);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X W i n d o w B y I D %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XWindowByID() locates a child window with a given ID. If not window with
% the given name is found, 0 is returned. Only the window specified and its
% subwindows are searched.
%
% The format of the XWindowByID function is:
%
% child=XWindowByID(display,window,id)
%
% A description of each parameter follows:
%
% o child: XWindowByID returns the window with the specified
% id. If no windows are found, XWindowByID returns 0.
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o id: Specifies the id of the window to locate.
%
*/
MagickPrivate Window XWindowByID(Display *display,const Window root_window,
const size_t id)
{
RectangleInfo
rectangle_info;
register int
i;
Status
status;
unsigned int
number_children;
Window
child,
*children,
window;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(root_window != (Window) NULL);
if (id == 0)
return(XSelectWindow(display,&rectangle_info));
if (root_window == id)
return(root_window);
status=XQueryTree(display,root_window,&child,&child,&children,
&number_children);
if (status == False)
return((Window) NULL);
window=(Window) NULL;
for (i=0; i < (int) number_children; i++)
{
/*
Search each child and their children.
*/
window=XWindowByID(display,children[i],id);
if (window != (Window) NULL)
break;
}
if (children != (Window *) NULL)
(void) XFree((void *) children);
return(window);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X W i n d o w B y N a m e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XWindowByName() locates a window with a given name on a display. If no
% window with the given name is found, 0 is returned. If more than one window
% has the given name, the first one is returned. Only root and its children
% are searched.
%
% The format of the XWindowByName function is:
%
% window=XWindowByName(display,root_window,name)
%
% A description of each parameter follows:
%
% o window: XWindowByName returns the window id.
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o root_window: Specifies the id of the root window.
%
% o name: Specifies the name of the window to locate.
%
*/
MagickPrivate Window XWindowByName(Display *display,const Window root_window,
const char *name)
{
register int
i;
Status
status;
unsigned int
number_children;
Window
*children,
child,
window;
XTextProperty
window_name;
assert(display != (Display *) NULL);
assert(root_window != (Window) NULL);
assert(name != (char *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
if (XGetWMName(display,root_window,&window_name) != 0)
if (LocaleCompare((char *) window_name.value,name) == 0)
return(root_window);
status=XQueryTree(display,root_window,&child,&child,&children,
&number_children);
if (status == False)
return((Window) NULL);
window=(Window) NULL;
for (i=0; i < (int) number_children; i++)
{
/*
Search each child and their children.
*/
window=XWindowByName(display,children[i],name);
if (window != (Window) NULL)
break;
}
if (children != (Window *) NULL)
(void) XFree((void *) children);
return(window);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X W i n d o w B y P r o p e r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XWindowByProperty() locates a child window with a given property. If not
% window with the given name is found, 0 is returned. If more than one window
% has the given property, the first one is returned. Only the window
% specified and its subwindows are searched.
%
% The format of the XWindowByProperty function is:
%
% child=XWindowByProperty(display,window,property)
%
% A description of each parameter follows:
%
% o child: XWindowByProperty returns the window id with the specified
% property. If no windows are found, XWindowByProperty returns 0.
%
% o display: Specifies a pointer to the Display structure; returned from
% XOpenDisplay.
%
% o property: Specifies the property of the window to locate.
%
*/
MagickPrivate Window XWindowByProperty(Display *display,const Window window,
const Atom property)
{
Atom
type;
int
format;
Status
status;
unsigned char
*data;
unsigned int
i,
number_children;
unsigned long
after,
number_items;
Window
child,
*children,
parent,
root;
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
assert(display != (Display *) NULL);
assert(window != (Window) NULL);
assert(property != (Atom) NULL);
status=XQueryTree(display,window,&root,&parent,&children,&number_children);
if (status == False)
return((Window) NULL);
type=(Atom) NULL;
child=(Window) NULL;
for (i=0; (i < number_children) && (child == (Window) NULL); i++)
{
status=XGetWindowProperty(display,children[i],property,0L,0L,MagickFalse,
(Atom) AnyPropertyType,&type,&format,&number_items,&after,&data);
if (data != NULL)
(void) XFree((void *) data);
if ((status == Success) && (type != (Atom) NULL))
child=children[i];
}
for (i=0; (i < number_children) && (child == (Window) NULL); i++)
child=XWindowByProperty(display,children[i],property);
if (children != (Window *) NULL)
(void) XFree((void *) children);
return(child);
}
#else
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X I m p o r t I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XImportImage() reads an image from an X window.
%
% The format of the XImportImage method is:
%
% Image *XImportImage(const ImageInfo *image_info,XImportInfo *ximage_info,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info..
%
% o ximage_info: Specifies a pointer to an XImportInfo structure.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport Image *XImportImage(const ImageInfo *image_info,
XImportInfo *ximage_info,ExceptionInfo *exception)
{
assert(image_info != (const ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(ximage_info != (XImportInfo *) NULL);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickCoreSignature);
(void) exception;
return((Image *) NULL);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X R e n d e r X 1 1 %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XRenderImage() renders text on the image with an X11 font. It also returns
% the bounding box of the text relative to the image.
%
% The format of the XRenderImage method is:
%
% MagickBooleanType XRenderImage(Image *image,DrawInfo *draw_info,
% const PointInfo *offset,TypeMetric *metrics,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o draw_info: the draw info.
%
% o offset: (x,y) location of text relative to image.
%
% o metrics: bounding box of text.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickPrivate MagickBooleanType XRenderImage(Image *image,
const DrawInfo *draw_info,const PointInfo *offset,TypeMetric *metrics,
ExceptionInfo *exception)
{
(void) draw_info;
(void) offset;
(void) metrics;
(void) ThrowMagickException(exception,GetMagickModule(),
MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","'%s' (X11)",
image->filename);
return(MagickFalse);
}
#endif
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ X C o m p o n e n t G e n e s i s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XComponentGenesis() instantiates the X component.
%
% The format of the XComponentGenesis method is:
%
% MagickBooleanType XComponentGenesis(void)
%
*/
MagickPrivate MagickBooleanType XComponentGenesis(void)
{
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% X G e t I m p o r t I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% XGetImportInfo() initializes the XImportInfo structure.
%
% The format of the XGetImportInfo method is:
%
% void XGetImportInfo(XImportInfo *ximage_info)
%
% A description of each parameter follows:
%
% o ximage_info: Specifies a pointer to an ImageInfo structure.
%
*/
MagickExport void XGetImportInfo(XImportInfo *ximage_info)
{
assert(ximage_info != (XImportInfo *) NULL);
ximage_info->frame=MagickFalse;
ximage_info->borders=MagickFalse;
ximage_info->screen=MagickFalse;
ximage_info->descend=MagickTrue;
ximage_info->silent=MagickFalse;
}