mirror of
https://github.com/gnustep/libs-back.git
synced 2025-04-22 07:21:02 +00:00
back-ericwa-experimental: delete a pile of legacy code
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/branches/ericwa-experimental@34068 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
401132302e
commit
addea6d663
27 changed files with 28 additions and 7283 deletions
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
Win32CairoGlitzSurface.h
|
||||
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
March 2nd, 2008
|
||||
Author: Xavier Glattard <xavier.glattard@free.fr>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef Win32CairoGlitzSurface_h
|
||||
#define Win32CairoGlitzSurface_h
|
||||
|
||||
#include "win32/WIN32Server.h"
|
||||
|
||||
#include "cairo/CairoSurface.h"
|
||||
|
||||
@interface Win32CairoGlitzSurface : CairoSurface
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
Win32CairoSurface.h
|
||||
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
March 2nd, 2008
|
||||
Author: Xavier Glattard <xavier.glattard@free.fr>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef Win32CairoSurface_h
|
||||
#define Win32CairoSurface_h
|
||||
|
||||
#include "win32/WIN32Server.h"
|
||||
|
||||
#include "cairo/CairoSurface.h"
|
||||
|
||||
@interface Win32CairoSurface : CairoSurface
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
Author: Banlu Kemiyatorn <object at gmail dot com>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef XGCairoGlitzSurface_h
|
||||
#define XGCairoGlitzSurface_h
|
||||
|
||||
#include "x11/XGServer.h"
|
||||
#include "x11/XGServerWindow.h"
|
||||
|
||||
#include "cairo/CairoSurface.h"
|
||||
|
||||
@interface XGCairoGlitzSurface : CairoSurface
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
Author: Banlu Kemiyatorn <object at gmail dot com>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef XGCairoSurface_h
|
||||
#define XGCairoSurface_h
|
||||
|
||||
#include "cairo/CairoSurface.h"
|
||||
|
||||
@interface XGCairoSurface : CairoSurface
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
Author: Banlu Kemiyatorn <object at gmail dot com>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef XGCairoXImageSurface_h
|
||||
#define XGCairoXImageSurface_h
|
||||
|
||||
#include "cairo/CairoSurface.h"
|
||||
|
||||
@class XWindowBuffer;
|
||||
|
||||
@interface XGCairoXImageSurface : CairoSurface
|
||||
{
|
||||
@private
|
||||
XWindowBuffer *wi;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
/* $XConsortium: StdCmap.h,v 1.4 94/04/17 20:16:15 converse Exp $ */
|
||||
|
||||
/*
|
||||
|
||||
Copyright (c) 1988 X Consortium
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of the X Consortium shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the X Consortium.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* The interfaces described by this header file are for miscellaneous utilities
|
||||
* and are not part of the Xlib standard.
|
||||
*/
|
||||
|
||||
#ifndef _XMU_STDCMAP_H_
|
||||
#define _XMU_STDCMAP_H_
|
||||
|
||||
#include <X11/Xfuncproto.h>
|
||||
|
||||
_XFUNCPROTOBEGIN
|
||||
|
||||
Status XmuAllStandardColormaps(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* dpy */
|
||||
#endif
|
||||
);
|
||||
|
||||
Status XmuCreateColormap(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* dpy */,
|
||||
XStandardColormap* /* colormap */
|
||||
#endif
|
||||
);
|
||||
|
||||
void XmuDeleteStandardColormap(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* dpy */,
|
||||
int /* screen */,
|
||||
Atom /* property */
|
||||
#endif
|
||||
);
|
||||
|
||||
Status XmuGetColormapAllocation(
|
||||
#if NeedFunctionPrototypes
|
||||
XVisualInfo* /* vinfo */,
|
||||
Atom /* property */,
|
||||
unsigned long* /* red_max_return */,
|
||||
unsigned long* /* green_max_return */,
|
||||
unsigned long* /* blue_max_return */
|
||||
#endif
|
||||
);
|
||||
|
||||
Status XmuLookupStandardColormap(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* dpy */,
|
||||
int /* screen */,
|
||||
VisualID /* visualid */,
|
||||
unsigned int /* depth */,
|
||||
Atom /* property */,
|
||||
Bool /* replace */,
|
||||
Bool /* retain */
|
||||
#endif
|
||||
);
|
||||
|
||||
XStandardColormap *XmuStandardColormap(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* dpy */,
|
||||
int /* screen */,
|
||||
VisualID /* visualid */,
|
||||
unsigned int /* depth */,
|
||||
Atom /* property */,
|
||||
Colormap /* cmap */,
|
||||
unsigned long /* red_max */,
|
||||
unsigned long /* green_max */,
|
||||
unsigned long /* blue_max */
|
||||
#endif
|
||||
);
|
||||
|
||||
Status XmuVisualStandardColormaps(
|
||||
#if NeedFunctionPrototypes
|
||||
Display* /* dpy */,
|
||||
int /* screen */,
|
||||
VisualID /* visualid */,
|
||||
unsigned int /* depth */,
|
||||
Bool /* replace */,
|
||||
Bool /* retain */
|
||||
#endif
|
||||
);
|
||||
|
||||
_XFUNCPROTOEND
|
||||
|
||||
#endif /* _XMU_STDCMAP_H_ */
|
|
@ -86,7 +86,6 @@ typedef struct _gswindow_device_t {
|
|||
Window root; /* Handle of root window */
|
||||
Window parent; /* Handle of parent window */
|
||||
int screen; /* Screeen this window is on */
|
||||
GC gc; /* GC for drawing */
|
||||
long number; /* Globally unique identifier */
|
||||
unsigned int depth; /* Window depth */
|
||||
unsigned int border; /* Border size */
|
||||
|
@ -98,12 +97,8 @@ typedef struct _gswindow_device_t {
|
|||
|
||||
unsigned int buffer_width; /* Size in pixels of the current buffers. */
|
||||
unsigned int buffer_height;
|
||||
Drawable buffer; /* Backing store pixmap */
|
||||
Drawable alpha_buffer; /* Alpha buffer. Managed by gdriver
|
||||
will be freed if HandlesBacking=0 */
|
||||
BOOL is_exposed;
|
||||
NSMutableArray *exposedRects; /* List of exposure event rects */
|
||||
Region region; /* Used between several expose events */
|
||||
XWMHints gen_hints;
|
||||
XSizeHints siz_hints;
|
||||
GNUstepWMAttributes win_attrs;
|
||||
|
@ -124,8 +119,6 @@ typedef struct _gswindow_device_t {
|
|||
#endif
|
||||
} gswindow_device_t;
|
||||
|
||||
#define GET_XDRAWABLE(win) ((win)->buffer ? (win)->buffer: (win)->ident)
|
||||
|
||||
@interface XGServer (DPSWindow)
|
||||
+ (gswindow_device_t *) _windowForXWindow: (Window)xWindow;
|
||||
+ (gswindow_device_t *) _windowForXParent: (Window)xWindow;
|
||||
|
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2002, 2005 Free Software Foundation, Inc.
|
||||
|
||||
Author: Alexander Malmberg <alexander@malmberg.org>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef XWindowBuffer_h
|
||||
#define XWindowBuffer_h
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef XSHM
|
||||
#include <X11/extensions/XShm.h>
|
||||
#else
|
||||
// FIXME
|
||||
#define XShmSegmentInfo int
|
||||
#endif
|
||||
|
||||
struct XWindowBuffer_depth_info_s
|
||||
{
|
||||
/* The drawing depth according to X. Usually the number of bits of color
|
||||
data in each pixel. */
|
||||
int drawing_depth;
|
||||
|
||||
/* The number of bytes used by a pixel. There is generally no
|
||||
relationship between this and drawing_depth, except that
|
||||
bytes_per_pixel*8>=drawing_depth. (Eg. 32-bit modes usually have a
|
||||
drawing depth of 24.) */
|
||||
int bytes_per_pixel;
|
||||
|
||||
/* If alpha is to be stored inside the normal data, this should be YES.
|
||||
Otherwise, a separate buffer will be allocated for the alpha data (which
|
||||
never does any harm, but it wastes memory if there's enough space in a
|
||||
pixel, as in 32-bit modes. There needs to be 8 bits available for alpha
|
||||
data at a byte boundary for this to work, though. (This could be fixed,
|
||||
but in the mean time, just setting inline_alpha to NO is easier.)
|
||||
inline_alpha_ofs should be the offset to the byte in each pixel that
|
||||
holds the alpha value. */
|
||||
BOOL inline_alpha;
|
||||
int inline_alpha_ofs;
|
||||
|
||||
/* The byte order used for the buffer. This must be either MSBFirst or
|
||||
LSBFirst. */
|
||||
int byte_order;
|
||||
};
|
||||
|
||||
/*
|
||||
XWindowBuffer maintains an XImage for a window. Each ARTGState that
|
||||
renders to that window uses the same XWindowBuffer (and thus the same
|
||||
buffer, etc.).
|
||||
|
||||
Many states might render to the same window, so we need to make sure
|
||||
that there's only one XWindowBuffer for each window. */
|
||||
@interface XWindowBuffer : NSObject
|
||||
{
|
||||
@public
|
||||
gswindow_device_t *window;
|
||||
|
||||
@private
|
||||
GC gc;
|
||||
Drawable drawable;
|
||||
XImage *ximage;
|
||||
Display *display;
|
||||
Pixmap pixmap;
|
||||
|
||||
int use_shm;
|
||||
XShmSegmentInfo shminfo;
|
||||
|
||||
|
||||
struct XWindowBuffer_depth_info_s DI;
|
||||
|
||||
|
||||
/* While a XShmPutImage is in progress we don't try to call it
|
||||
again. The pending updates are stored here, and when we get the
|
||||
ShmCompletion event, we handle them. */
|
||||
int pending_put; /* There are pending updates */
|
||||
struct
|
||||
{
|
||||
int x, y, w, h;
|
||||
} pending_rect; /* in this rectangle. */
|
||||
|
||||
int pending_event; /* We're waiting for the ShmCompletion event. */
|
||||
|
||||
|
||||
/* This is for the ugly shape-hack */
|
||||
unsigned char *old_shape;
|
||||
int old_shape_size;
|
||||
|
||||
@public
|
||||
unsigned char *data;
|
||||
int sx, sy;
|
||||
int bytes_per_line, bits_per_pixel, bytes_per_pixel;
|
||||
|
||||
/* If has_alpha is 1 and alpha is NULL, the alpha is stored in data
|
||||
somehow. The drawing mechanism code should know how to deal with
|
||||
it. A separate alpha buffer will always be exactly the right size,
|
||||
so each row is sx bytes long.
|
||||
|
||||
If has_alpha is 0, the window is assumed to be completely opaque.
|
||||
*/
|
||||
unsigned char *alpha;
|
||||
int has_alpha;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns a _retained_ XWindowBuffer for the specified gswindow_device_t.
|
||||
|
||||
The depth info is only used if a new XWindowBuffer needs to be allocated.
|
||||
*/
|
||||
+ windowBufferForWindow: (gswindow_device_t *)awindow
|
||||
depthInfo: (struct XWindowBuffer_depth_info_s *)aDI;
|
||||
|
||||
/*
|
||||
Note that alpha is _not_ guaranteed to exist after this has been called;
|
||||
you still need to check has_alpha. If the call fails, a message will be
|
||||
logged.
|
||||
|
||||
(In ARTGState, I handle failures by simply ignoring the operation that
|
||||
required alpha.)
|
||||
|
||||
The alpha channel is initialized to being completely opaque when first
|
||||
created.
|
||||
*/
|
||||
-(void) needsAlpha;
|
||||
|
||||
-(void) _gotShmCompletion;
|
||||
-(void) _exposeRect: (NSRect)r;
|
||||
+(void) _gotShmCompletion: (Drawable)d;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,477 +0,0 @@
|
|||
/*
|
||||
* Raster graphics library
|
||||
*
|
||||
* Copyright (c) 1997-2002 Alfredo K. Kojima
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Environment variables:
|
||||
*
|
||||
* WRASTER_GAMMA <rgamma>/<ggamma>/<bgamma>
|
||||
* gamma correction value. Must be greater than 0
|
||||
* Only for PseudoColor visuals.
|
||||
*
|
||||
* Default:
|
||||
* WRASTER_GAMMA 1/1/1
|
||||
*
|
||||
*
|
||||
* If you want a specific value for a screen, append the screen number
|
||||
* preceded by a hash to the variable name as in
|
||||
* WRASTER_GAMMA#1
|
||||
* for screen number 1
|
||||
*/
|
||||
|
||||
#ifndef RLRASTER_H_
|
||||
#define RLRASTER_H_
|
||||
|
||||
|
||||
/* version of the header for the library: 0.21 */
|
||||
#define WRASTER_HEADER_VERSION 21
|
||||
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#ifdef XSHM
|
||||
#include <X11/extensions/XShm.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* RBestMatchRendering or RDitheredRendering */
|
||||
#define RC_RenderMode (1<<0)
|
||||
|
||||
/* number of colors per channel for colormap in PseudoColor mode */
|
||||
#define RC_ColorsPerChannel (1<<1)
|
||||
|
||||
/* do gamma correction */
|
||||
#define RC_GammaCorrection (1<<2)
|
||||
|
||||
/* visual id to use */
|
||||
#define RC_VisualID (1<<3)
|
||||
|
||||
/* shared memory usage */
|
||||
#define RC_UseSharedMemory (1<<4)
|
||||
|
||||
/* use default instead of best visual */
|
||||
#define RC_DefaultVisual (1<<5)
|
||||
|
||||
/* filter type for smoothed scaling */
|
||||
#define RC_ScalingFilter (1<<6)
|
||||
|
||||
/* standard colormap usage */
|
||||
#define RC_StandardColormap (1<<7)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* std colormap usage/creation modes */
|
||||
enum {
|
||||
RUseStdColormap, /* default. fallbacks to RIgnore.. if
|
||||
there is none defined */
|
||||
RCreateStdColormap,
|
||||
RIgnoreStdColormap
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef struct RContextAttributes {
|
||||
int flags;
|
||||
int render_mode;
|
||||
int colors_per_channel; /* for PseudoColor */
|
||||
float rgamma; /* gamma correction for red, */
|
||||
float ggamma; /* green, */
|
||||
float bgamma; /* and blue */
|
||||
VisualID visualid; /* visual ID to use */
|
||||
int use_shared_memory; /* True of False */
|
||||
int scaling_filter;
|
||||
int standard_colormap_mode; /* what to do with std cma */
|
||||
} RContextAttributes;
|
||||
|
||||
|
||||
/*
|
||||
* describes a screen in terms of depth, visual, number of colors
|
||||
* we can use, if we should do dithering, and what colors to use for
|
||||
* dithering.
|
||||
*/
|
||||
typedef struct RContext {
|
||||
Display *dpy;
|
||||
int screen_number;
|
||||
Colormap cmap;
|
||||
|
||||
RContextAttributes *attribs;
|
||||
|
||||
GC copy_gc;
|
||||
|
||||
Visual *visual;
|
||||
int depth;
|
||||
Window drawable; /* window to pass for XCreatePixmap().*/
|
||||
/* generally = root */
|
||||
int vclass;
|
||||
|
||||
unsigned long black;
|
||||
unsigned long white;
|
||||
|
||||
int red_offset; /* only used in 24bpp */
|
||||
int green_offset;
|
||||
int blue_offset;
|
||||
|
||||
/* only used for pseudocolor and grayscale */
|
||||
|
||||
XStandardColormap *std_rgb_map; /* standard RGB colormap */
|
||||
XStandardColormap *std_gray_map; /* standard grayscale colormap */
|
||||
|
||||
int ncolors; /* total number of colors we can use */
|
||||
XColor *colors; /* internal colormap */
|
||||
unsigned long *pixels; /* RContext->colors[].pixel */
|
||||
|
||||
struct {
|
||||
unsigned int use_shared_pixmap:1;
|
||||
unsigned int optimize_for_speed:1;
|
||||
} flags;
|
||||
|
||||
struct RHermesData *hermes_data; /* handle for Hermes stuff */
|
||||
} RContext;
|
||||
|
||||
|
||||
typedef struct RColor {
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
unsigned char alpha;
|
||||
} RColor;
|
||||
|
||||
|
||||
typedef struct RHSVColor {
|
||||
unsigned short hue; /* 0-359 */
|
||||
unsigned char saturation; /* 0-255 */
|
||||
unsigned char value; /* 0-255 */
|
||||
} RHSVColor;
|
||||
|
||||
|
||||
|
||||
typedef struct RPoint {
|
||||
int x, y;
|
||||
} RPoint;
|
||||
|
||||
|
||||
typedef struct RSegment {
|
||||
int x1, y1, x2, y2;
|
||||
} RSegment;
|
||||
|
||||
|
||||
|
||||
/* image formats */
|
||||
enum RImageFormat {
|
||||
RRGBFormat,
|
||||
RRGBAFormat
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* internal 24bit+alpha image representation
|
||||
*/
|
||||
typedef struct RImage {
|
||||
unsigned char *data; /* image data RGBA or RGB */
|
||||
int width, height; /* size of the image */
|
||||
enum RImageFormat format;
|
||||
RColor background; /* background color */
|
||||
int refCount;
|
||||
} RImage;
|
||||
|
||||
|
||||
/*
|
||||
* internal wrapper for XImage. Used for shm abstraction
|
||||
*/
|
||||
typedef struct RXImage {
|
||||
XImage *image;
|
||||
|
||||
/* Private data. Do not access */
|
||||
#ifdef XSHM
|
||||
XShmSegmentInfo info;
|
||||
char is_shared;
|
||||
#endif
|
||||
} RXImage;
|
||||
|
||||
|
||||
/* image display modes */
|
||||
enum {
|
||||
RDitheredRendering = 0,
|
||||
RBestMatchRendering = 1
|
||||
};
|
||||
|
||||
|
||||
/* smoothed scaling filter types */
|
||||
enum {
|
||||
RBoxFilter,
|
||||
RTriangleFilter,
|
||||
RBellFilter,
|
||||
RBSplineFilter,
|
||||
RLanczos3Filter,
|
||||
RMitchellFilter
|
||||
};
|
||||
|
||||
|
||||
/* note that not all operations are supported in all functions */
|
||||
enum {
|
||||
RClearOperation, /* clear with 0 */
|
||||
RCopyOperation,
|
||||
RNormalOperation, /* same as combine */
|
||||
RAddOperation,
|
||||
RSubtractOperation
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
RAbsoluteCoordinates = 0,
|
||||
RRelativeCoordinates = 1
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
RSunkenBevel = -1,
|
||||
RNoBevel = 0,
|
||||
RRaisedBevel = 1
|
||||
};
|
||||
/* bw compat */
|
||||
#define RBEV_SUNKEN RSunkenBevel
|
||||
/* 1 pixel wide */
|
||||
#define RBEV_RAISED RRaisedBevel
|
||||
/* 1 pixel wide on top/left 2 on bottom/right */
|
||||
#define RBEV_RAISED2 2
|
||||
/* 2 pixel width */
|
||||
#define RBEV_RAISED3 3
|
||||
|
||||
enum {
|
||||
RHorizontalGradient = 2,
|
||||
RVerticalGradient = 3,
|
||||
RDiagonalGradient = 4
|
||||
};
|
||||
/* for backwards compatibility */
|
||||
#define RGRD_HORIZONTAL RHorizontalGradient
|
||||
#define RGRD_VERTICAL RVerticalGradient
|
||||
#define RGRD_DIAGONAL RDiagonalGradient
|
||||
|
||||
|
||||
|
||||
/* error codes */
|
||||
#define RERR_NONE 0
|
||||
#define RERR_OPEN 1 /* cant open file */
|
||||
#define RERR_READ 2 /* error reading from file */
|
||||
#define RERR_WRITE 3 /* error writing to file */
|
||||
#define RERR_NOMEMORY 4 /* out of memory */
|
||||
#define RERR_NOCOLOR 5 /* out of color cells */
|
||||
#define RERR_BADIMAGEFILE 6 /* image file is corrupted or invalid */
|
||||
#define RERR_BADFORMAT 7 /* image file format is unknown */
|
||||
#define RERR_BADINDEX 8 /* no such image index in file */
|
||||
|
||||
#define RERR_BADVISUALID 16 /* invalid visual ID requested for context */
|
||||
#define RERR_STDCMAPFAIL 17 /* failed to created std colormap */
|
||||
|
||||
#define RERR_XERROR 127 /* internal X error */
|
||||
#define RERR_INTERNAL 128 /* should not happen */
|
||||
|
||||
|
||||
/*
|
||||
* Returns a NULL terminated array of strings containing the
|
||||
* supported formats, such as: TIFF, XPM, PNG, JPEG, PPM, GIF
|
||||
* Do not free the returned data.
|
||||
*/
|
||||
char **RSupportedFileFormats(void);
|
||||
|
||||
|
||||
char *RGetImageFileFormat(char *file);
|
||||
|
||||
/*
|
||||
* Xlib contexts
|
||||
*/
|
||||
RContext *RCreateContext(Display *dpy, int screen_number,
|
||||
RContextAttributes *attribs);
|
||||
|
||||
void RDestroyContext(RContext *context);
|
||||
|
||||
Bool RGetClosestXColor(RContext *context, RColor *color, XColor *retColor);
|
||||
|
||||
/*
|
||||
* RImage creation
|
||||
*/
|
||||
RImage *RCreateImage(unsigned width, unsigned height, int alpha);
|
||||
|
||||
RImage *RCreateImageFromXImage(RContext *context, XImage *image, XImage *mask);
|
||||
|
||||
RImage *RCreateImageFromDrawable(RContext *context, Drawable drawable,
|
||||
Pixmap mask);
|
||||
|
||||
RImage *RLoadImage(RContext *context, char *file, int index);
|
||||
|
||||
RImage* RRetainImage(RImage *image);
|
||||
|
||||
void RReleaseImage(RImage *image);
|
||||
|
||||
/* Obsoleted function. Use RReleaseImage() instead. This was kept only to
|
||||
* allow a smoother transition and to avoid breaking existing programs, but
|
||||
* it will be removed in a future release. Right now is just an alias to
|
||||
* RReleaseImage(). Do _NOT_ use RDestroyImage() anymore in your programs.
|
||||
* Being an alias to RReleaseImage() this function no longer actually
|
||||
* destroys the image, unless the image is no longer retained in some other
|
||||
* place.
|
||||
*/
|
||||
void RDestroyImage(RImage *image);
|
||||
|
||||
RImage *RGetImageFromXPMData(RContext *context, char **xpmData);
|
||||
|
||||
/*
|
||||
* RImage storing
|
||||
*/
|
||||
Bool RSaveImage(RImage *image, char *filename, char *format);
|
||||
|
||||
/*
|
||||
* Area manipulation
|
||||
*/
|
||||
RImage *RCloneImage(RImage *image);
|
||||
|
||||
RImage *RGetSubImage(RImage *image, int x, int y, unsigned width,
|
||||
unsigned height);
|
||||
|
||||
void RCombineImageWithColor(RImage *image, RColor *color);
|
||||
|
||||
void RCombineImages(RImage *image, RImage *src);
|
||||
|
||||
void RCombineArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
|
||||
unsigned height, int dx, int dy);
|
||||
|
||||
void RCombineImagesWithOpaqueness(RImage *image, RImage *src, int opaqueness);
|
||||
|
||||
void RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
|
||||
unsigned width, unsigned height, int dx, int dy,
|
||||
int opaqueness);
|
||||
|
||||
RImage *RScaleImage(RImage *image, unsigned new_width, unsigned new_height);
|
||||
|
||||
RImage *RSmoothScaleImage(RImage *src, unsigned new_width,
|
||||
unsigned new_height);
|
||||
|
||||
RImage *RRotateImage(RImage *image, float angle);
|
||||
|
||||
|
||||
RImage *RMakeTiledImage(RImage *tile, unsigned width, unsigned height);
|
||||
|
||||
RImage* RMakeCenteredImage(RImage *image, unsigned width, unsigned height,
|
||||
RColor *color);
|
||||
|
||||
/*
|
||||
* Drawing
|
||||
*/
|
||||
Bool RGetPixel(RImage *image, int x, int y, RColor *color);
|
||||
|
||||
void RPutPixel(RImage *image, int x, int y, RColor *color);
|
||||
|
||||
void ROperatePixel(RImage *image, int operation, int x, int y, RColor *color);
|
||||
|
||||
void RPutPixels(RImage *image, RPoint *points, int npoints, int mode,
|
||||
RColor *color);
|
||||
|
||||
void ROperatePixels(RImage *image, int operation, RPoint *points,
|
||||
int npoints, int mode, RColor *color);
|
||||
|
||||
int RDrawLine(RImage *image, int x0, int y0, int x1, int y1, RColor *color);
|
||||
|
||||
int ROperateLine(RImage *image, int operation, int x0, int y0, int x1, int y1,
|
||||
RColor *color);
|
||||
|
||||
void RDrawLines(RImage *image, RPoint *points, int npoints, int mode,
|
||||
RColor *color);
|
||||
|
||||
void ROperateLines(RImage *image, int operation, RPoint *points, int npoints,
|
||||
int mode, RColor *color);
|
||||
|
||||
void RDrawSegments(RImage *image, RSegment *segs, int nsegs, RColor *color);
|
||||
|
||||
void ROperateSegments(RImage *image, int operation, RSegment *segs, int nsegs,
|
||||
RColor *color);
|
||||
|
||||
/*
|
||||
* Color convertion
|
||||
*/
|
||||
void RRGBtoHSV(RColor *color, RHSVColor *hsv);
|
||||
void RHSVtoRGB(RHSVColor *hsv, RColor *rgb);
|
||||
|
||||
/*
|
||||
* Painting
|
||||
*/
|
||||
void RClearImage(RImage *image, RColor *color);
|
||||
|
||||
void RFillImage(RImage *image, RColor *color);
|
||||
|
||||
void RBevelImage(RImage *image, int bevel_type);
|
||||
|
||||
RImage *RRenderGradient(unsigned width, unsigned height, RColor *from,
|
||||
RColor *to, int style);
|
||||
|
||||
|
||||
RImage *RRenderMultiGradient(unsigned width, unsigned height, RColor **colors,
|
||||
int style);
|
||||
|
||||
|
||||
RImage *RRenderInterwovenGradient(unsigned width, unsigned height,
|
||||
RColor colors1[2], int thickness1,
|
||||
RColor colors2[2], int thickness2);
|
||||
|
||||
|
||||
/*
|
||||
* Convertion into X Pixmaps
|
||||
*/
|
||||
int RConvertImage(RContext *context, RImage *image, Pixmap *pixmap);
|
||||
|
||||
int RConvertImageMask(RContext *context, RImage *image, Pixmap *pixmap,
|
||||
Pixmap *mask, int threshold);
|
||||
|
||||
|
||||
/*
|
||||
* misc. utilities
|
||||
*/
|
||||
RXImage *RCreateXImage(RContext *context, int depth,
|
||||
unsigned width, unsigned height);
|
||||
|
||||
RXImage *RGetXImage(RContext *context, Drawable d, int x, int y,
|
||||
unsigned width, unsigned height);
|
||||
|
||||
void RDestroyXImage(RContext *context, RXImage *ximage);
|
||||
|
||||
void RPutXImage(RContext *context, Drawable d, GC gc, RXImage *ximage,
|
||||
int src_x, int src_y, int dest_x, int dest_y,
|
||||
unsigned width, unsigned height);
|
||||
|
||||
/* do not free the returned string! */
|
||||
const char *RMessageForError(int errorCode);
|
||||
|
||||
int RBlurImage(RImage *image);
|
||||
|
||||
/****** Global Variables *******/
|
||||
|
||||
extern int RErrorCode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
|
@ -53,7 +53,7 @@
|
|||
# include "cairo/XGCairoModernSurface.h"
|
||||
# endif /* USE_GLITZ */
|
||||
# include "x11/XGServerWindow.h"
|
||||
# include "x11/XWindowBuffer.h"
|
||||
//# include "x11/XWindowBuffer.h"
|
||||
#elif BUILD_SERVER == SERVER_win32
|
||||
# include <windows.h>
|
||||
# ifdef USE_GLITZ
|
||||
|
@ -116,12 +116,13 @@
|
|||
/* Private backend methods */
|
||||
+ (void) handleExposeRect: (NSRect)rect forDriver: (void *)driver
|
||||
{
|
||||
if ([(id)driver isKindOfClass: [XWindowBuffer class]])
|
||||
{
|
||||
// For XGCairoXImageSurface
|
||||
[(XWindowBuffer *)driver _exposeRect: rect];
|
||||
}
|
||||
else if ([(id)driver isKindOfClass: [CairoSurface class]])
|
||||
// if ([(id)driver isKindOfClass: [XWindowBuffer class]])
|
||||
// {
|
||||
// // For XGCairoXImageSurface
|
||||
// [(XWindowBuffer *)driver _exposeRect: rect];
|
||||
// }
|
||||
// else
|
||||
if ([(id)driver isKindOfClass: [CairoSurface class]])
|
||||
{
|
||||
// For XGCairoModernSurface
|
||||
[(CairoSurface *)driver handleExposeRect: rect];
|
||||
|
@ -132,12 +133,12 @@
|
|||
|
||||
+ (void) _gotShmCompletion: (Drawable)d
|
||||
{
|
||||
[XWindowBuffer _gotShmCompletion: d];
|
||||
// [XWindowBuffer _gotShmCompletion: d];
|
||||
}
|
||||
|
||||
- (void) gotShmCompletion: (Drawable)d
|
||||
{
|
||||
[XWindowBuffer _gotShmCompletion: d];
|
||||
// [XWindowBuffer _gotShmCompletion: d];
|
||||
}
|
||||
|
||||
#endif // XSHM
|
||||
|
|
|
@ -39,20 +39,7 @@ cairo_OBJC_FILES = CairoSurface.m \
|
|||
CairoPDFSurface.m \
|
||||
|
||||
ifeq ($(BUILD_SERVER),x11)
|
||||
ifeq ($(WITH_GLITZ),yes)
|
||||
cairo_OBJC_FILES += XGCairoGlitzSurface.m
|
||||
else
|
||||
cairo_OBJC_FILES += XGCairoSurface.m XGCairoXImageSurface.m XGCairoModernSurface.m
|
||||
endif
|
||||
else
|
||||
ifeq ($(BUILD_GRAPHICS),cairo)
|
||||
ifeq ($(WITH_GLITZ),yes)
|
||||
cairo_OBJC_FILES += Win32CairoGlitzSurface.m
|
||||
else
|
||||
cairo_OBJC_FILES += Win32CairoSurface.m
|
||||
# Win32CairoXImageSurface.m
|
||||
endif
|
||||
endif
|
||||
cairo_OBJC_FILES += XGCairoModernSurface.m
|
||||
endif
|
||||
|
||||
cairo_OBJC_FILES +=
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
Win32CairoGlitzSurface.m
|
||||
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
Author: Xavier Glattard <xavier.glattard@online.fr>
|
||||
Based on the work of:
|
||||
Alexander Malmberg <alexander@malmberg.org>
|
||||
Banlu Kemiyatorn <object at gmail dot com>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "cairo/Win32CairoGlitzSurface.h"
|
||||
#include <cairo-glitz.h>
|
||||
#include <glitz-wgl.h>
|
||||
|
||||
#define GSWINDEVICE ((HWND)gsDevice)
|
||||
|
||||
@implementation Win32CairoGlitzSurface
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
NSLog(@"Win32CairoGlitzSurface : %d : glitz_wgl_init", __LINE__);
|
||||
glitz_wgl_init(NULL);
|
||||
}
|
||||
|
||||
- (id) initWithDevice: (void *)device
|
||||
{
|
||||
WIN_INTERN *win;
|
||||
|
||||
unsigned long mask = 0;
|
||||
glitz_drawable_format_t dtempl;
|
||||
|
||||
//static
|
||||
glitz_drawable_format_t *dformat = NULL;
|
||||
glitz_drawable_t *drawable = NULL;
|
||||
glitz_format_t *format = NULL;
|
||||
glitz_surface_t *surface = NULL;
|
||||
RECT sz;
|
||||
|
||||
gsDevice = device;
|
||||
GetClientRect(GSWINDEVICE, &sz);
|
||||
win = (WIN_INTERN *)GetWindowLong(GSWINDEVICE, GWL_USERDATA);
|
||||
if (win && win->useHDC)
|
||||
{
|
||||
HGDIOBJ old;
|
||||
|
||||
old = SelectObject(win->hdc, win->old);
|
||||
DeleteObject(old);
|
||||
DeleteDC(win->hdc);
|
||||
win->hdc = NULL;
|
||||
win->old = NULL;
|
||||
win->useHDC = NO;
|
||||
}
|
||||
|
||||
//NSLog(@"Win32CairoGlitzSurface : init window %d (%d,%d-%d,%d)",GSWINDEVICE,sz.left,sz.top,sz.right,sz.bottom);
|
||||
|
||||
//if(!dformat)
|
||||
{
|
||||
dtempl.samples = 1;
|
||||
mask |= GLITZ_FORMAT_SAMPLES_MASK;
|
||||
dtempl.color.red_size = 8;
|
||||
dtempl.color.green_size = 8;
|
||||
dtempl.color.blue_size = 8;
|
||||
dtempl.color.alpha_size = 8;
|
||||
dtempl.color.fourcc = GLITZ_FOURCC_RGB;
|
||||
mask |= GLITZ_FORMAT_FOURCC_MASK
|
||||
| GLITZ_FORMAT_RED_SIZE_MASK
|
||||
| GLITZ_FORMAT_GREEN_SIZE_MASK
|
||||
| GLITZ_FORMAT_BLUE_SIZE_MASK
|
||||
| GLITZ_FORMAT_ALPHA_SIZE_MASK;
|
||||
|
||||
dtempl.doublebuffer = 0;
|
||||
mask |= GLITZ_FORMAT_DOUBLEBUFFER_MASK;
|
||||
|
||||
dformat = glitz_wgl_find_window_format(mask, &dtempl, 0);
|
||||
if (!dformat)
|
||||
{
|
||||
NSLog(@"Win32CairoGlitzSurface : %d : no format for drawable",__LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* NSLog (@"ID:%d RGBA:%d/%d/%d/%d D:%d St:%d DB:%d S:%d",
|
||||
(int) dformat->id,
|
||||
dformat->color.red_size,
|
||||
dformat->color.green_size,
|
||||
dformat->color.blue_size,
|
||||
dformat->color.alpha_size,
|
||||
dformat->depth_size,
|
||||
dformat->stencil_size,
|
||||
dformat->doublebuffer,
|
||||
dformat->samples
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
drawable = glitz_wgl_create_drawable_for_window(
|
||||
dformat,
|
||||
GSWINDEVICE,
|
||||
sz.right - sz.left,
|
||||
sz.bottom - sz.top);
|
||||
if (!drawable)
|
||||
{
|
||||
NSLog(@"Win32CairoGlitzSurface : %d : no glitz drawable",__LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
format = glitz_find_standard_format(drawable, GLITZ_STANDARD_ARGB32);
|
||||
if (!format)
|
||||
{
|
||||
NSLog(@"Win32CairoGlitzSurface : %d (%d) : couldn't find ARGB32 surface format",__LINE__,GSWINDEVICE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
surface = glitz_surface_create(
|
||||
drawable, format,
|
||||
sz.right - sz.left,
|
||||
sz.bottom - sz.top,
|
||||
0, NULL);
|
||||
if (!surface)
|
||||
{
|
||||
NSLog(@"Win32CairoGlitzSurface : %d : couldn't create glitz surface",__LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glitz_surface_attach(surface, drawable, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
|
||||
_surface = cairo_glitz_surface_create(surface);
|
||||
if (cairo_surface_status(_surface))
|
||||
{
|
||||
DESTROY(self);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSSize) size
|
||||
{
|
||||
RECT sz;
|
||||
|
||||
GetClientRect(GSWINDEVICE, &sz);
|
||||
return NSMakeSize(sz.right - sz.left, sz.bottom - sz.top);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
Win32CairoSurface.m
|
||||
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
Author: Xavier Glattard <xavier.glattard@online.fr>
|
||||
Based on the work of:
|
||||
Banlu Kemiyatorn <object at gmail dot com>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "cairo/Win32CairoSurface.h"
|
||||
#include <cairo-win32.h>
|
||||
|
||||
#define GSWINDEVICE ((HWND)gsDevice)
|
||||
|
||||
@implementation Win32CairoSurface
|
||||
|
||||
- (id) initWithDevice: (void *)device
|
||||
{
|
||||
HDC hDC;
|
||||
WIN_INTERN *win;
|
||||
gsDevice = device;
|
||||
|
||||
win = (WIN_INTERN *)GetWindowLong(GSWINDEVICE, GWL_USERDATA);
|
||||
if (win && win->useHDC)
|
||||
hDC = win->hdc;
|
||||
else
|
||||
hDC = GetDC(GSWINDEVICE);
|
||||
|
||||
if (!hDC)
|
||||
{
|
||||
NSLog(@"Win32CairoSurface : %d : no device context",__LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
_surface = cairo_win32_surface_create(hDC);
|
||||
if (!(win && win->useHDC))
|
||||
ReleaseDC(GSWINDEVICE, hDC);
|
||||
if (cairo_surface_status(_surface))
|
||||
{
|
||||
DESTROY(self);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSSize) size
|
||||
{
|
||||
RECT sz;
|
||||
|
||||
GetClientRect(GSWINDEVICE, &sz);
|
||||
return NSMakeSize(sz.right - sz.left, sz.top - sz.bottom);
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
Author: Alexander Malmberg <alexander@malmberg.org>
|
||||
Author: Banlu Kemiyatorn <object at gmail dot com>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "cairo/XGCairoGlitzSurface.h"
|
||||
#include <cairo-glitz.h>
|
||||
#include <glitz-glx.h>
|
||||
|
||||
#define GSWINDEVICE ((gswindow_device_t *)gsDevice)
|
||||
|
||||
@implementation XGCairoGlitzSurface
|
||||
|
||||
- (id) initWithDevice: (void *)device
|
||||
{
|
||||
glitz_drawable_format_t templ;
|
||||
glitz_drawable_format_t *dformat = NULL;
|
||||
glitz_drawable_t *drawable = NULL;
|
||||
glitz_format_t *format = NULL;
|
||||
glitz_surface_t *surface = NULL;
|
||||
|
||||
gsDevice = device;
|
||||
|
||||
/*
|
||||
if (GSWINDEVICE->type != NSBackingStoreNonretained)
|
||||
{
|
||||
XSetWindowBackgroundPixmap(GSWINDEVICE->display,
|
||||
GSWINDEVICE->ident,
|
||||
GSWINDEVICE->buffer);
|
||||
}
|
||||
*/
|
||||
|
||||
templ.doublebuffer = 0;
|
||||
dformat = glitz_glx_find_drawable_format_for_visual(GSWINDEVICE->display,
|
||||
GSWINDEVICE->screen,
|
||||
XVisualIDFromVisual(DefaultVisual(GSWINDEVICE->display, GSWINDEVICE->screen)));
|
||||
|
||||
if (!dformat)
|
||||
{
|
||||
NSLog(@"XGCairoGlitzSurface : %d : no format",__LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
drawable = glitz_glx_create_drawable_for_window(GSWINDEVICE->display,
|
||||
GSWINDEVICE->screen,
|
||||
dformat,
|
||||
GSWINDEVICE->ident,
|
||||
GSWINDEVICE->xframe.size.width,
|
||||
GSWINDEVICE->xframe.size.height);
|
||||
if (!drawable)
|
||||
{
|
||||
NSLog(@"XGCairoGlitzSurface : %d : no glitz drawable", __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
format = glitz_find_standard_format(drawable, GLITZ_STANDARD_ARGB32);
|
||||
if (!format)
|
||||
{
|
||||
NSLog(@"XGCairoGlitzSurface : %d : couldn't find ARGB32 surface format", __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
surface = glitz_surface_create(drawable, format,
|
||||
GSWINDEVICE->xframe.size.width,
|
||||
GSWINDEVICE->xframe.size.height,
|
||||
0, NULL);
|
||||
if (!surface)
|
||||
{
|
||||
NSLog(@"XGCairoGlitzSurface : %d : couldn't create glitz surface", __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glitz_surface_attach(surface, drawable, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
|
||||
_surface = cairo_glitz_surface_create(surface);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSSize) size
|
||||
{
|
||||
return GSWINDEVICE->xframe.size;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
Author: Banlu Kemiyatorn <object at gmail dot com>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <AppKit/NSImage.h>
|
||||
#include <AppKit/NSGraphics.h>
|
||||
#include "x11/XGServer.h"
|
||||
#include "x11/XGServerWindow.h"
|
||||
#include "cairo/XGCairoSurface.h"
|
||||
#include <cairo-xlib.h>
|
||||
|
||||
#define GSWINDEVICE ((gswindow_device_t *)gsDevice)
|
||||
|
||||
@implementation XGCairoSurface
|
||||
|
||||
- (id) initWithDevice: (void *)device
|
||||
{
|
||||
Display *dpy;
|
||||
Drawable drawable;
|
||||
Visual* visual;
|
||||
XWindowAttributes attributes;
|
||||
|
||||
gsDevice = device;
|
||||
|
||||
dpy = GSWINDEVICE->display;
|
||||
if (GSWINDEVICE->type != NSBackingStoreNonretained)
|
||||
{
|
||||
drawable = GSWINDEVICE->buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawable = GSWINDEVICE->ident;
|
||||
}
|
||||
|
||||
/*
|
||||
if (GSWINDEVICE->type != NSBackingStoreNonretained)
|
||||
{
|
||||
GSWINDEVICE->gdriverProtocol |= GDriverHandlesExpose;
|
||||
XSetWindowBackgroundPixmap(GSWINDEVICE->display,
|
||||
GSWINDEVICE->ident,
|
||||
GSWINDEVICE->buffer);
|
||||
}
|
||||
*/
|
||||
|
||||
if (!XGetWindowAttributes (dpy, GSWINDEVICE->ident, &attributes))
|
||||
{
|
||||
visual = DefaultVisual (dpy, DefaultScreen (dpy));
|
||||
}
|
||||
else
|
||||
{
|
||||
visual = attributes.visual;
|
||||
}
|
||||
|
||||
_surface = cairo_xlib_surface_create(dpy,
|
||||
drawable,
|
||||
visual,
|
||||
GSWINDEVICE->xframe.size.width,
|
||||
GSWINDEVICE->xframe.size.height);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSSize) size
|
||||
{
|
||||
return GSWINDEVICE->xframe.size;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation XGServer (ScreenCapture)
|
||||
|
||||
- (NSImage *) contentsOfScreen: (int)screen inRect: (NSRect)rect
|
||||
{
|
||||
Window win;
|
||||
XWindowAttributes attrs;
|
||||
|
||||
win = [self xDisplayRootWindowForScreen: screen];
|
||||
|
||||
if (XGetWindowAttributes(dpy, win, &attrs))
|
||||
{
|
||||
NSInteger width = rect.size.width;
|
||||
NSInteger height = rect.size.height;
|
||||
NSImage *result;
|
||||
NSBitmapImageRep *bmp;
|
||||
cairo_surface_t *src, *dest;
|
||||
|
||||
// Convert rect to flipped coordinates
|
||||
rect.origin.y = attrs.height - NSMaxY(rect);
|
||||
|
||||
bmp = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
|
||||
pixelsWide: width
|
||||
pixelsHigh: height
|
||||
bitsPerSample: 8
|
||||
samplesPerPixel: 4
|
||||
hasAlpha: YES
|
||||
isPlanar: NO
|
||||
colorSpaceName: NSDeviceRGBColorSpace
|
||||
bitmapFormat: 0
|
||||
bytesPerRow: 0
|
||||
bitsPerPixel: 32] autorelease];
|
||||
|
||||
src = cairo_xlib_surface_create(dpy, win, attrs.visual, attrs.width, attrs.height);
|
||||
dest = cairo_image_surface_create_for_data([bmp bitmapData], CAIRO_FORMAT_ARGB32, width, height, [bmp bytesPerRow]);
|
||||
|
||||
{
|
||||
cairo_t *cr = cairo_create(dest);
|
||||
cairo_set_source_surface(cr, src, -1 * rect.origin.x, -1 * rect.origin.y);
|
||||
cairo_paint(cr);
|
||||
cairo_destroy(cr);
|
||||
}
|
||||
|
||||
cairo_surface_destroy(src);
|
||||
cairo_surface_destroy(dest);
|
||||
|
||||
// Convert BGRA to RGBA
|
||||
{
|
||||
NSInteger stride;
|
||||
NSInteger x, y;
|
||||
unsigned char *cdata;
|
||||
|
||||
stride = [bmp bytesPerRow];
|
||||
cdata = [bmp bitmapData];
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
NSInteger i = (y * stride) + (x * 4);
|
||||
unsigned char d = cdata[i];
|
||||
|
||||
#if GS_WORDS_BIGENDIAN
|
||||
cdata[i] = cdata[i + 1];
|
||||
cdata[i + 1] = cdata[i + 2];
|
||||
cdata[i + 2] = cdata[i + 3];
|
||||
cdata[i + 3] = d;
|
||||
#else
|
||||
cdata[i] = cdata[i + 2];
|
||||
//cdata[i + 1] = cdata[i + 1];
|
||||
cdata[i + 2] = d;
|
||||
//cdata[i + 3] = cdata[i + 3];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = [[[NSImage alloc] initWithSize: NSMakeSize(width, height)] autorelease];
|
||||
[result addRepresentation: bmp];
|
||||
return result;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
Author: Banlu Kemiyatorn <object at gmail dot com>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "x11/XGServer.h"
|
||||
#include "x11/XGServerWindow.h"
|
||||
#include "x11/XWindowBuffer.h"
|
||||
#include "cairo/XGCairoXImageSurface.h"
|
||||
#include "cairo/XGCairoSurface.h"
|
||||
|
||||
#define GSWINDEVICE ((gswindow_device_t *)gsDevice)
|
||||
|
||||
@implementation XGCairoXImageSurface
|
||||
|
||||
- (id) initWithDevice: (void *)device
|
||||
{
|
||||
struct XWindowBuffer_depth_info_s di;
|
||||
|
||||
gsDevice = device;
|
||||
if (GSWINDEVICE->type == NSBackingStoreNonretained)
|
||||
{
|
||||
// FIXME: This is a hack to get non-reatined backing store working.
|
||||
// I see no reason, why it isn't working, as the code is identical
|
||||
// to the one in the art backend.
|
||||
RELEASE(self);
|
||||
return [[XGCairoSurface alloc] initWithDevice: device];
|
||||
}
|
||||
|
||||
di.drawing_depth = GSWINDEVICE->depth;
|
||||
// FIXME: The next lines may be wrong for depth <> 32.
|
||||
// But then art uses a depth of 24 for 32 bit modes. Strange!
|
||||
di.bytes_per_pixel = 4;
|
||||
di.inline_alpha = YES;
|
||||
di.inline_alpha_ofs = 0;
|
||||
/* The cairo image surface uses the client's byte order (cf. bug #28590). */
|
||||
#if GS_WORDS_BIGENDIAN
|
||||
di.byte_order = MSBFirst;
|
||||
#else
|
||||
di.byte_order = LSBFirst;
|
||||
#endif
|
||||
|
||||
ASSIGN(wi, [XWindowBuffer windowBufferForWindow: GSWINDEVICE depthInfo: &di]);
|
||||
|
||||
_surface = cairo_image_surface_create_for_data((unsigned char*)wi->data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
wi->sx, wi->sy,
|
||||
wi->bytes_per_line);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
DESTROY(wi);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSSize) size
|
||||
{
|
||||
return GSWINDEVICE->xframe.size;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -33,18 +33,8 @@ include ../../config.make
|
|||
SUBPROJECT_NAME=x11
|
||||
|
||||
# The C source files to be compiled
|
||||
ifeq ($(WITH_WRASTER),yes)
|
||||
x11_C_FILES = \
|
||||
xdnd.c
|
||||
else
|
||||
x11_C_FILES = \
|
||||
context.c \
|
||||
convert.c \
|
||||
raster.c \
|
||||
scale.c \
|
||||
xdnd.c \
|
||||
xutil.c
|
||||
endif
|
||||
|
||||
# The Objective-C source files to be compiled
|
||||
x11_OBJC_FILES = \
|
||||
|
@ -53,7 +43,6 @@ XGServerEvent.m \
|
|||
XGServerWindow.m \
|
||||
XGDragView.m \
|
||||
XIMInputServer.m \
|
||||
XWindowBuffer.m\
|
||||
XGGLFormat.m\
|
||||
XGGLContext.m
|
||||
|
||||
|
|
|
@ -56,12 +56,6 @@ terminate(int sig)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_WRASTER_H
|
||||
#include "wraster.h"
|
||||
#else
|
||||
#include "x11/wraster.h"
|
||||
#endif
|
||||
|
||||
#include "x11/XGServer.h"
|
||||
#include "x11/XGInputServer.h"
|
||||
#ifdef HAVE_GLX
|
||||
|
@ -130,218 +124,6 @@ _parse_display_name(NSString *name, int *dn, int *sn)
|
|||
- (void) setupRunLoopInputSourcesForMode: (NSString*)mode;
|
||||
@end
|
||||
|
||||
@interface XGScreenContext : NSObject
|
||||
{
|
||||
RContext *rcontext;
|
||||
XGDrawMechanism drawMechanism;
|
||||
}
|
||||
|
||||
- initForDisplay: (Display *)dpy screen: (int)screen_number;
|
||||
- (XGDrawMechanism) drawMechanism;
|
||||
- (RContext *) context;
|
||||
@end
|
||||
|
||||
@implementation XGScreenContext
|
||||
|
||||
- (RContextAttributes *) _getXDefaults
|
||||
{
|
||||
int dummy;
|
||||
RContextAttributes *attribs;
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
attribs = (RContextAttributes *)malloc(sizeof(RContextAttributes));
|
||||
|
||||
attribs->flags = 0;
|
||||
if ([defaults boolForKey: @"NSDefaultVisual"])
|
||||
attribs->flags |= RC_DefaultVisual;
|
||||
if ((dummy = [defaults integerForKey: @"NSDefaultVisual"]))
|
||||
{
|
||||
attribs->flags |= RC_VisualID;
|
||||
attribs->visualid = dummy;
|
||||
}
|
||||
if ((dummy = [defaults integerForKey: @"NSColorsPerChannel"]))
|
||||
{
|
||||
attribs->flags |= RC_ColorsPerChannel;
|
||||
attribs->colors_per_channel = dummy;
|
||||
}
|
||||
|
||||
return attribs;
|
||||
}
|
||||
|
||||
- initForDisplay: (Display *)dpy screen: (int)screen_number
|
||||
{
|
||||
RContextAttributes *attribs;
|
||||
XColor testColor;
|
||||
unsigned char r, g, b;
|
||||
|
||||
/* Get the visual information */
|
||||
attribs = NULL;
|
||||
//attribs = [self _getXDefaults];
|
||||
rcontext = RCreateContext(dpy, screen_number, attribs);
|
||||
|
||||
/*
|
||||
* If we have shared memory available, only use it when the XGPS-Shm
|
||||
* default is set to YES
|
||||
*/
|
||||
if (rcontext->attribs->use_shared_memory == True
|
||||
&& [[NSUserDefaults standardUserDefaults] boolForKey: @"XGPS-Shm"] != YES)
|
||||
rcontext->attribs->use_shared_memory = False;
|
||||
|
||||
/*
|
||||
* Crude tests to see if we can accelerate creation of pixels from
|
||||
* 8-bit red, green and blue color values.
|
||||
*/
|
||||
if (rcontext->depth == 12 || rcontext->depth == 16)
|
||||
{
|
||||
drawMechanism = XGDM_FAST16;
|
||||
r = 8;
|
||||
g = 9;
|
||||
b = 7;
|
||||
testColor.pixel = (((r << 5) + g) << 6) + b;
|
||||
XQueryColor(rcontext->dpy, rcontext->cmap, &testColor);
|
||||
if (((testColor.red >> 11) != r)
|
||||
|| ((testColor.green >> 11) != g)
|
||||
|| ((testColor.blue >> 11) != b))
|
||||
{
|
||||
NSLog(@"WARNING - XGServer is unable to use the "
|
||||
@"fast algorithm for writing to a 16-bit display on "
|
||||
@"this host - perhaps you'd like to adjust the code "
|
||||
@"to work ... and submit a patch.");
|
||||
drawMechanism = XGDM_PORTABLE;
|
||||
}
|
||||
}
|
||||
else if (rcontext->depth == 15)
|
||||
{
|
||||
drawMechanism = XGDM_FAST15;
|
||||
r = 8;
|
||||
g = 9;
|
||||
b = 7;
|
||||
testColor.pixel = (((r << 5) + g) << 5) + b;
|
||||
XQueryColor(rcontext->dpy, rcontext->cmap, &testColor);
|
||||
if (((testColor.red >> 11) != r)
|
||||
|| ((testColor.green >> 11) != g)
|
||||
|| ((testColor.blue >> 11) != b))
|
||||
{
|
||||
NSLog(@"WARNING - XGServer is unable to use the "
|
||||
@"fast algorithm for writing to a 15-bit display on "
|
||||
@"this host - perhaps you'd like to adjust the code "
|
||||
@"to work ... and submit a patch.");
|
||||
drawMechanism = XGDM_PORTABLE;
|
||||
}
|
||||
}
|
||||
else if (rcontext->depth == 24 || rcontext->depth == 32)
|
||||
{
|
||||
drawMechanism = XGDM_FAST32;
|
||||
r = 32;
|
||||
g = 33;
|
||||
b = 31;
|
||||
testColor.pixel = (((r << 8) + g) << 8) + b;
|
||||
XQueryColor(rcontext->dpy, rcontext->cmap, &testColor);
|
||||
if (((testColor.red >> 8) == r)
|
||||
&& ((testColor.green >> 8) == g)
|
||||
&& ((testColor.blue >> 8) == b))
|
||||
{
|
||||
drawMechanism = XGDM_FAST32;
|
||||
}
|
||||
else if (((testColor.red >> 8) == b)
|
||||
&& ((testColor.green >> 8) == g)
|
||||
&& ((testColor.blue >> 8) == r))
|
||||
{
|
||||
drawMechanism = XGDM_FAST32_BGR;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"WARNING - XGServer is unable to use the "
|
||||
@"fast algorithm for writing to a 32-bit display on "
|
||||
@"this host - perhaps you'd like to adjust the code "
|
||||
@"to work ... and submit a patch.");
|
||||
drawMechanism = XGDM_PORTABLE;
|
||||
}
|
||||
}
|
||||
else if (rcontext->depth == 8)
|
||||
{
|
||||
drawMechanism = XGDM_FAST8;
|
||||
r = 2;
|
||||
g = 3;
|
||||
b = 1;
|
||||
testColor.pixel = (((r << 3) + g) << 2) + b;
|
||||
XQueryColor(rcontext->dpy, rcontext->cmap, &testColor);
|
||||
if (((testColor.red >> 13) != r)
|
||||
|| ((testColor.green >> 13) != g)
|
||||
|| ((testColor.blue >> 14) != b))
|
||||
{
|
||||
NSLog(@"WARNING - XGServer is unable to use the "
|
||||
@"fast algorithm for writing to an 8-bit display on "
|
||||
@"this host - the most likely reason being "
|
||||
@"the StandardColormap RGB_BEST_MAP has not been installed.");
|
||||
drawMechanism = XGDM_PORTABLE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"WARNING - XGServer is unable to use a "
|
||||
@"fast algorithm for writing to the display on "
|
||||
@"this host - perhaps you'd like to adjust the code "
|
||||
@"to work ... and submit a patch.");
|
||||
drawMechanism = XGDM_PORTABLE;
|
||||
}
|
||||
NSDebugLLog(@"XGTrace", @"Draw mech %d for screen %d", drawMechanism,
|
||||
screen_number);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
#ifndef HAVE_WRASTER_H
|
||||
// FIXME: context.c does not include a clean up function for Rcontext,
|
||||
// so we try do it here.
|
||||
|
||||
/*
|
||||
Note that this can be done only when we use our own version of wraster.
|
||||
If we're using an external version of wraster, the rcontext structure
|
||||
might be different (different fields, or differently used fields), which
|
||||
breaks this code.
|
||||
*/
|
||||
|
||||
if (rcontext)
|
||||
{
|
||||
XFreeGC(rcontext->dpy, rcontext->copy_gc);
|
||||
if (rcontext->drawable)
|
||||
{
|
||||
XDestroyWindow(rcontext->dpy, rcontext->drawable);
|
||||
}
|
||||
if (rcontext->pixels)
|
||||
{
|
||||
free(rcontext->pixels);
|
||||
}
|
||||
if (rcontext->colors)
|
||||
{
|
||||
free(rcontext->colors);
|
||||
}
|
||||
if (rcontext->hermes_data)
|
||||
{
|
||||
free(rcontext->hermes_data);
|
||||
}
|
||||
free(rcontext->attribs);
|
||||
free(rcontext);
|
||||
}
|
||||
#endif
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (XGDrawMechanism) drawMechanism
|
||||
{
|
||||
return drawMechanism;
|
||||
}
|
||||
|
||||
- (RContext *) context
|
||||
{
|
||||
return rcontext;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
<unit>
|
||||
<heading>XGServer</heading>
|
||||
|
@ -502,164 +284,6 @@ _parse_display_name(NSString *name, int *dn, int *sn)
|
|||
return dpy;
|
||||
}
|
||||
|
||||
- (XGScreenContext *) _screenContextForScreen: (int)screen_number
|
||||
{
|
||||
int count = ScreenCount(dpy);
|
||||
XGScreenContext *screen;
|
||||
|
||||
if (screen_number >= count)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Request for invalid screen"];
|
||||
}
|
||||
|
||||
screen = NSMapGet(screenList, (void *)(uintptr_t)screen_number);
|
||||
if (screen == NULL)
|
||||
{
|
||||
screen = [[XGScreenContext alloc]
|
||||
initForDisplay: dpy screen: screen_number];
|
||||
NSMapInsert(screenList, (void *)(uintptr_t)screen_number, (void *)screen);
|
||||
RELEASE(screen);
|
||||
}
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a pointer to a structure which describes aspects of the
|
||||
X windows display
|
||||
*/
|
||||
- (void *) xrContextForScreen: (int)screen_number
|
||||
{
|
||||
return [[self _screenContextForScreen: screen_number] context];
|
||||
}
|
||||
|
||||
- (Visual *) visualForScreen: (int)screen_number
|
||||
{
|
||||
return [[self _screenContextForScreen: screen_number] context]->visual;
|
||||
}
|
||||
|
||||
- (int) depthForScreen: (int)screen_number
|
||||
{
|
||||
return [[self _screenContextForScreen: screen_number] context]->depth;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the XGDrawMechanism, which roughly describes the depth of
|
||||
the screen and how pixels should be drawn to the screen for maximum
|
||||
speed.
|
||||
*/
|
||||
- (XGDrawMechanism) drawMechanismForScreen: (int)screen_number
|
||||
{
|
||||
return [[self _screenContextForScreen: screen_number] drawMechanism];
|
||||
}
|
||||
|
||||
// Could use NSSwapInt() instead
|
||||
static unsigned int flip_bytes32(unsigned int i)
|
||||
{
|
||||
return ((i >> 24) & 0xff)
|
||||
|((i >> 8) & 0xff00)
|
||||
|((i << 8) & 0xff0000)
|
||||
|((i << 24) & 0xff000000);
|
||||
}
|
||||
|
||||
static unsigned int flip_bytes16(unsigned int i)
|
||||
{
|
||||
return ((i >> 8) & 0xff)
|
||||
|((i << 8) & 0xff00);
|
||||
}
|
||||
|
||||
static int byte_order(void)
|
||||
{
|
||||
union
|
||||
{
|
||||
unsigned int i;
|
||||
char c;
|
||||
} foo;
|
||||
foo.i = 1;
|
||||
return foo.c != 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the art backend to determine the drawing mechanism.
|
||||
*/
|
||||
- (void) getForScreen: (int)screen_number pixelFormat: (int *)bpp_number
|
||||
masks: (int *)red_mask : (int *)green_mask : (int *)blue_mask
|
||||
{
|
||||
Visual *visual;
|
||||
XImage *i;
|
||||
int bpp;
|
||||
#if 0
|
||||
XVisualInfo template;
|
||||
XVisualInfo *visualInfo;
|
||||
int numMatches;
|
||||
|
||||
/*
|
||||
We need a visual that we can generate pixel values for by ourselves.
|
||||
Thus, we try to find a DirectColor or TrueColor visual. If that fails,
|
||||
we use the default visual and hope that it's usable.
|
||||
*/
|
||||
template.class = DirectColor;
|
||||
visualInfo = XGetVisualInfo(dpy, VisualClassMask, &template, &numMatches);
|
||||
if (!visualInfo)
|
||||
{
|
||||
template.class = TrueColor;
|
||||
visualInfo = XGetVisualInfo(dpy, VisualClassMask, &template, &numMatches);
|
||||
}
|
||||
if (visualInfo)
|
||||
{
|
||||
visual = visualInfo->visual;
|
||||
bpp = visualInfo->depth;
|
||||
XFree(visualInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
visual = DefaultVisual(dpy, DefaultScreen(dpy));
|
||||
bpp = DefaultDepth(dpy, DefaultScreen(dpy));
|
||||
}
|
||||
#else
|
||||
RContext *context;
|
||||
|
||||
// Better to get the used visual from the context.
|
||||
context = [self xrContextForScreen: screen_number];
|
||||
visual = context->visual;
|
||||
bpp = context->depth;
|
||||
#endif
|
||||
|
||||
i = XCreateImage(dpy, visual, bpp, ZPixmap, 0, NULL, 8, 8, 8, 0);
|
||||
bpp = i->bits_per_pixel;
|
||||
XDestroyImage(i);
|
||||
|
||||
*red_mask = visual->red_mask;
|
||||
*green_mask = visual->green_mask;
|
||||
*blue_mask = visual->blue_mask;
|
||||
*bpp_number = bpp;
|
||||
|
||||
/* If the server doesn't have the same endianness as we do, we need
|
||||
to flip the masks around (well, at least sometimes; not sure
|
||||
what'll really happen for 15/16bpp modes). */
|
||||
{
|
||||
int us = byte_order(); /* True iff we're big-endian. */
|
||||
int them = ImageByteOrder(dpy); /* True iff the server is big-endian. */
|
||||
|
||||
if (us != them)
|
||||
{
|
||||
if ((bpp == 32) || (bpp == 24))
|
||||
{
|
||||
*red_mask = flip_bytes32(*red_mask);
|
||||
*green_mask = flip_bytes32(*green_mask);
|
||||
*blue_mask = flip_bytes32(*blue_mask);
|
||||
}
|
||||
else if (bpp == 16)
|
||||
{
|
||||
*red_mask = flip_bytes16(*red_mask);
|
||||
*green_mask = flip_bytes16(*green_mask);
|
||||
*blue_mask = flip_bytes16(*blue_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the root window of the display
|
||||
*/
|
||||
|
@ -668,26 +292,6 @@ static int byte_order(void)
|
|||
return RootWindow(dpy, screen_number);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the closest color in the current colormap to the indicated
|
||||
X color
|
||||
*/
|
||||
- (XColor) xColorFromColor: (XColor)color forScreen: (int)screen_number
|
||||
{
|
||||
Status ret;
|
||||
RColor rcolor;
|
||||
RContext *context = [self xrContextForScreen: screen_number];
|
||||
XAllocColor(dpy, context->cmap, &color);
|
||||
rcolor.red = color.red / 256;
|
||||
rcolor.green = color.green / 256;
|
||||
rcolor.blue = color.blue / 256;
|
||||
ret = RGetClosestXColor(context, &rcolor, &color);
|
||||
if (ret == False)
|
||||
NSLog(@"Failed to alloc color (%d,%d,%d)\n",
|
||||
(int)rcolor.red, (int)rcolor.green, (int)rcolor.blue);
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the application root window, which is used for many things
|
||||
such as window hints
|
||||
|
|
|
@ -49,23 +49,10 @@
|
|||
#include "x11/XGGeneric.h"
|
||||
#include "x11/xdnd.h"
|
||||
|
||||
#ifdef HAVE_WRASTER_H
|
||||
#include "wraster.h"
|
||||
#else
|
||||
#include "x11/wraster.h"
|
||||
#endif
|
||||
|
||||
#include "math.h"
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xproto.h>
|
||||
|
||||
#if LIB_FOUNDATION_LIBRARY
|
||||
# include <Foundation/NSPosixFileDescriptor.h>
|
||||
#elif defined(NeXT_PDO)
|
||||
# include <Foundation/NSFileHandle.h>
|
||||
# include <Foundation/NSNotification.h>
|
||||
#endif
|
||||
|
||||
#define cWin ((gswindow_device_t*)generic.cachedWindow)
|
||||
|
||||
// NumLock's mask (it depends on the keyboard mapping)
|
||||
|
@ -95,15 +82,6 @@ void __objc_xgcontextevent_linking (void)
|
|||
{
|
||||
}
|
||||
|
||||
static SEL procSel = 0;
|
||||
static void (*procEvent)(id, SEL, XEvent*) = 0;
|
||||
|
||||
#ifdef XSHM
|
||||
@interface NSGraphicsContext (SharedMemory)
|
||||
-(void) gotShmCompletion: (Drawable)d;
|
||||
@end
|
||||
#endif
|
||||
|
||||
@interface XGServer (Private)
|
||||
- (void) receivedEvent: (void*)data
|
||||
type: (RunLoopEventType)type
|
||||
|
@ -251,12 +229,6 @@ static int check_modifier (XEvent *xEvent, KeySym key_sym)
|
|||
watcher: (id<RunLoopEvents>)self
|
||||
forMode: mode];
|
||||
#endif
|
||||
if (procSel == 0)
|
||||
{
|
||||
procSel = @selector(processEvent:);
|
||||
procEvent = (void (*)(id, SEL, XEvent*))
|
||||
[self methodForSelector: procSel];
|
||||
}
|
||||
}
|
||||
|
||||
#if LIB_FOUNDATION_LIBRARY
|
||||
|
@ -307,7 +279,7 @@ posixFileDescriptor: (NSPosixFileDescriptor*)fileDescriptor
|
|||
}
|
||||
#endif
|
||||
|
||||
(*procEvent)(self, procSel, &xEvent);
|
||||
[self processEvent: &xEvent];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1735,15 +1707,6 @@ posixFileDescriptor: (NSPosixFileDescriptor*)fileDescriptor
|
|||
|
||||
// We shouldn't get here unless we forgot to trap an event above
|
||||
default:
|
||||
#ifdef XSHM
|
||||
if (xEvent.type == XShmGetEventBase(dpy)+ShmCompletion
|
||||
&& [gcontext respondsToSelector: @selector(gotShmCompletion:)])
|
||||
{
|
||||
[gcontext gotShmCompletion:
|
||||
((XShmCompletionEvent *)&xEvent)->drawable];
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
NSLog(@"Received an untrapped event\n");
|
||||
break;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,748 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
Author: Alexander Malmberg <alexander@malmberg.org>
|
||||
|
||||
This file is part of GNUstep.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <Foundation/NSUserDefaults.h>
|
||||
|
||||
#include "x11/XGServer.h"
|
||||
#include "x11/XGServerWindow.h"
|
||||
#include "x11/XWindowBuffer.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
|
||||
#ifdef HAVE_XSHAPE
|
||||
#include <X11/extensions/shape.h>
|
||||
#endif
|
||||
|
||||
static XWindowBuffer **window_buffers;
|
||||
static int num_window_buffers;
|
||||
|
||||
|
||||
static int use_shape_hack = 0; /* this is an ugly hack : ) */
|
||||
|
||||
#ifdef XSHM
|
||||
|
||||
static int did_test_xshm = 0;
|
||||
static int use_xshm = 1;
|
||||
static Bool use_xshm_pixmaps = 0;
|
||||
static int num_xshm_test_errors = 0;
|
||||
|
||||
static int test_xshm_error_handler(Display *d, XErrorEvent *ev)
|
||||
{
|
||||
num_xshm_test_errors++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_xshm(Display *display, Visual *visual, int drawing_depth)
|
||||
{
|
||||
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
did_test_xshm = 1;
|
||||
|
||||
if ([ud objectForKey: @"XWindowBufferUseXShm"])
|
||||
use_xshm = [ud boolForKey: @"XWindowBufferUseXShm"];
|
||||
|
||||
/* If the user doesn't want XShm, there's no point in doing any further
|
||||
testing. */
|
||||
if (!use_xshm)
|
||||
return;
|
||||
|
||||
/* This seems to return success if the X server understands the XShm
|
||||
protocol, regardless of whether XShm can actually be used or not... */
|
||||
{
|
||||
int major, minor;
|
||||
|
||||
if (!XShmQueryExtension(display) ||
|
||||
!XShmQueryVersion(display, &major, &minor, &use_xshm_pixmaps))
|
||||
{
|
||||
NSLog(@"XShm not supported by X server.");
|
||||
NSLog(@"Falling back to normal XImage (will be slower).");
|
||||
use_xshm = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* ... so we check that it actually works here. To do this, we need to
|
||||
set up our own error handler (because the xlib calls never fail, they
|
||||
just cause error events to be sent to us), explicitly synchronize
|
||||
(or we wouldn't get to handle, and thus detect, the errors until much
|
||||
later), and try actually creating a XShm image. Yuck. */
|
||||
{
|
||||
XImage *ximage;
|
||||
XShmSegmentInfo shminfo;
|
||||
int (*old_error_handler)();
|
||||
|
||||
old_error_handler = XSetErrorHandler(test_xshm_error_handler);
|
||||
|
||||
ximage = XShmCreateImage(display, visual,
|
||||
drawing_depth, ZPixmap, NULL, &shminfo,
|
||||
1, 1);
|
||||
XSync(display, False);
|
||||
if (!ximage || num_xshm_test_errors)
|
||||
{
|
||||
NSLog(@"XShm not supported, XShmCreateImage failed.");
|
||||
goto no_xshm;
|
||||
}
|
||||
|
||||
shminfo.shmid = shmget(IPC_PRIVATE,
|
||||
64, /* We don't have exact bytes per row values here, but this
|
||||
should be safe, and we'll probably get a full page anyway.
|
||||
(And if it turns out not to be enough, the X server will notice
|
||||
and give us errors, causing us to think that XShm isn't
|
||||
supported.) */
|
||||
IPC_CREAT | 0700);
|
||||
|
||||
if (shminfo.shmid == -1 || num_xshm_test_errors)
|
||||
{
|
||||
NSLog(@"XShm not supported, shmget() failed: %m.");
|
||||
XDestroyImage(ximage);
|
||||
goto no_xshm;
|
||||
}
|
||||
|
||||
shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
|
||||
if ((intptr_t)shminfo.shmaddr == -1 || num_xshm_test_errors)
|
||||
{
|
||||
NSLog(@"XShm not supported, shmat() failed: %m.");
|
||||
XDestroyImage(ximage);
|
||||
shmctl(shminfo.shmid, IPC_RMID, 0);
|
||||
goto no_xshm;
|
||||
}
|
||||
|
||||
shminfo.readOnly = 0;
|
||||
if (!XShmAttach(display, &shminfo))
|
||||
num_xshm_test_errors++;
|
||||
XSync(display, False);
|
||||
if (num_xshm_test_errors)
|
||||
{
|
||||
NSLog(@"XShm not supported, XShmAttach() failed.");
|
||||
XDestroyImage(ximage);
|
||||
shmdt(shminfo.shmaddr);
|
||||
shmctl(shminfo.shmid, IPC_RMID, 0);
|
||||
goto no_xshm;
|
||||
}
|
||||
|
||||
XShmDetach(display, &shminfo);
|
||||
XDestroyImage(ximage);
|
||||
shmdt(shminfo.shmaddr);
|
||||
|
||||
/* Most of the time, all the above calls will return success despite
|
||||
actually failing. To catch all errors generated by the calls before
|
||||
returning, we synchronize here. */
|
||||
XSync(display, False);
|
||||
|
||||
shmctl(shminfo.shmid, IPC_RMID, 0);
|
||||
|
||||
if (num_xshm_test_errors)
|
||||
{
|
||||
NSLog(@"XShm not supported.");
|
||||
no_xshm:
|
||||
NSLog(@"Falling back to normal XImage (will be slower).");
|
||||
use_xshm = 0;
|
||||
}
|
||||
XSetErrorHandler(old_error_handler);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@implementation XWindowBuffer
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
||||
use_shape_hack = [ud boolForKey: @"XWindowBuffer-shape-hack"];
|
||||
}
|
||||
|
||||
+ windowBufferForWindow: (gswindow_device_t *)awindow
|
||||
depthInfo: (struct XWindowBuffer_depth_info_s *)aDI
|
||||
{
|
||||
int i;
|
||||
XWindowBuffer *wi;
|
||||
int drawing_depth;
|
||||
Visual *visual;
|
||||
|
||||
for (i = 0; i < num_window_buffers; i++)
|
||||
{
|
||||
if (window_buffers[i]->window == awindow)
|
||||
break;
|
||||
}
|
||||
if (i == num_window_buffers)
|
||||
{
|
||||
wi = [[XWindowBuffer alloc] init];
|
||||
wi->window = awindow;
|
||||
window_buffers = realloc(window_buffers,
|
||||
sizeof(XWindowBuffer *) * (num_window_buffers + 1));
|
||||
if (!window_buffers)
|
||||
{
|
||||
NSLog(@"Out of memory (failed to allocate %lu bytes)",
|
||||
(unsigned long)sizeof(XWindowBuffer *) * (num_window_buffers + 1));
|
||||
exit(1);
|
||||
}
|
||||
window_buffers[num_window_buffers++] = wi;
|
||||
}
|
||||
else
|
||||
{
|
||||
wi = window_buffers[i];
|
||||
wi = RETAIN(wi);
|
||||
}
|
||||
|
||||
wi->DI = *aDI;
|
||||
wi->gc = awindow->gc;
|
||||
wi->drawable = awindow->ident;
|
||||
wi->display = awindow->display;
|
||||
|
||||
wi->window->gdriverProtocol = GDriverHandlesExpose | GDriverHandlesBacking;
|
||||
wi->window->gdriver = wi;
|
||||
|
||||
#if 0
|
||||
drawing_depth = aDI->drawing_depth;
|
||||
visual = DefaultVisual(wi->display, DefaultScreen(wi->display));
|
||||
#else
|
||||
// Better to get the used visual from the XGServer.
|
||||
visual = [(XGServer*)GSCurrentServer() visualForScreen: awindow->screen];
|
||||
drawing_depth = [(XGServer*)GSCurrentServer() depthForScreen: awindow->screen];
|
||||
#endif
|
||||
|
||||
/* TODO: resolve properly.
|
||||
-x11 is creating buffers before I have a chance to tell it not to, so
|
||||
I'm freeing them here to reduce memory consumption (and prevent
|
||||
leaks, though that should be fixed now) */
|
||||
if (awindow->buffer)
|
||||
{
|
||||
XFreePixmap (awindow->display, awindow->buffer);
|
||||
awindow->buffer = 0;
|
||||
}
|
||||
if (awindow->alpha_buffer)
|
||||
{
|
||||
XFreePixmap (awindow->display, awindow->alpha_buffer);
|
||||
awindow->alpha_buffer = 0;
|
||||
}
|
||||
|
||||
/* create the image if necessary */
|
||||
if (!wi->ximage ||
|
||||
wi->sx != awindow->xframe.size.width ||
|
||||
wi->sy != awindow->xframe.size.height)
|
||||
{
|
||||
/* printf("%@ updating image for %p (%gx%g)\n", wi, wi->window,
|
||||
wi->window->xframe.size.width, wi->window->xframe.size.height);*/
|
||||
if (wi->ximage)
|
||||
{
|
||||
#ifdef XSHM
|
||||
if (wi->use_shm)
|
||||
{
|
||||
XShmDetach(wi->display, &wi->shminfo);
|
||||
XDestroyImage(wi->ximage);
|
||||
shmdt(wi->shminfo.shmaddr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
XDestroyImage(wi->ximage);
|
||||
}
|
||||
if (wi->pixmap)
|
||||
{
|
||||
XFreePixmap(wi->display,wi->pixmap);
|
||||
XSetWindowBackground(wi->display,wi->window->ident,None);
|
||||
wi->pixmap=0;
|
||||
}
|
||||
|
||||
wi->has_alpha = 0;
|
||||
if (wi->alpha)
|
||||
{
|
||||
free(wi->alpha);
|
||||
wi->alpha = NULL;
|
||||
}
|
||||
|
||||
wi->pending_put = wi->pending_event = 0;
|
||||
|
||||
wi->ximage = NULL;
|
||||
|
||||
/* TODO: only use shared memory for 'real' on-screen windows. how can
|
||||
we tell? don't create shared buffer until first expose? */
|
||||
/* The primary problems seems to be the system limit on the _number_
|
||||
of shared memory segments, not their total size, so we only create
|
||||
shared buffers for reasonably large buffers and assume that the small
|
||||
ones are just caches of images and will never be displayed, anyway
|
||||
(and if they are displayed, it won't cost much, since they're small).
|
||||
*/
|
||||
if (wi->window->xframe.size.width * wi->window->xframe.size.height < 4096)
|
||||
goto no_xshm;
|
||||
|
||||
#ifdef XSHM
|
||||
if (!did_test_xshm)
|
||||
test_xshm(wi->display, visual, drawing_depth);
|
||||
|
||||
if (!use_xshm)
|
||||
goto no_xshm;
|
||||
|
||||
/* Use XShm if possible, else fall back to normal XImage: s */
|
||||
wi->use_shm = 1;
|
||||
wi->ximage = XShmCreateImage(wi->display, visual,
|
||||
drawing_depth, ZPixmap, NULL, &wi->shminfo,
|
||||
wi->window->xframe.size.width,
|
||||
wi->window->xframe.size.height);
|
||||
if (!wi->ximage)
|
||||
{
|
||||
NSLog(@"Warning: XShmCreateImage failed!");
|
||||
NSLog(@"Falling back to normal XImage (will be slower).");
|
||||
goto no_xshm;
|
||||
}
|
||||
wi->shminfo.shmid = shmget(IPC_PRIVATE,
|
||||
wi->ximage->bytes_per_line * wi->ximage->height,
|
||||
IPC_CREAT | 0700);
|
||||
|
||||
if (wi->shminfo.shmid == -1)
|
||||
{
|
||||
NSLog(@"Warning: shmget() failed: %m.");
|
||||
NSLog(@"Falling back to normal XImage (will be slower).");
|
||||
XDestroyImage(wi->ximage);
|
||||
goto no_xshm;
|
||||
}
|
||||
|
||||
wi->shminfo.shmaddr = wi->ximage->data = shmat(wi->shminfo.shmid, 0, 0);
|
||||
if ((intptr_t)wi->shminfo.shmaddr == -1)
|
||||
{
|
||||
NSLog(@"Warning: shmat() failed: %m.");
|
||||
NSLog(@"Falling back to normal XImage (will be slower).");
|
||||
XDestroyImage(wi->ximage);
|
||||
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
|
||||
goto no_xshm;
|
||||
}
|
||||
|
||||
wi->shminfo.readOnly = 0;
|
||||
if (!XShmAttach(wi->display, &wi->shminfo))
|
||||
{
|
||||
NSLog(@"Warning: XShmAttach() failed.");
|
||||
NSLog(@"Falling back to normal XImage (will be slower).");
|
||||
XDestroyImage(wi->ximage);
|
||||
shmdt(wi->shminfo.shmaddr);
|
||||
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
|
||||
goto no_xshm;
|
||||
}
|
||||
|
||||
if (use_xshm_pixmaps)
|
||||
{
|
||||
/* We try to create a shared pixmap using the same buffer, and set
|
||||
it as the background of the window. This allows X to handle expose
|
||||
events all by itself, which avoids white flashing when things are
|
||||
dragged across a window. */
|
||||
/* TODO: we still get and handle expose events, although we don't
|
||||
need to. */
|
||||
wi->pixmap = XShmCreatePixmap(wi->display, wi->drawable,
|
||||
wi->ximage->data, &wi->shminfo,
|
||||
wi->window->xframe.size.width,
|
||||
wi->window->xframe.size.height,
|
||||
drawing_depth);
|
||||
if (wi->pixmap) /* TODO: this doesn't work */
|
||||
{
|
||||
XSetWindowBackgroundPixmap(wi->display, wi->window->ident,
|
||||
wi->pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
/* On some systems (eg. freebsd), X can't attach to the shared segment
|
||||
if it's marked for destruction, so we make sure it's attached before
|
||||
marking it. */
|
||||
XSync(wi->display, False);
|
||||
|
||||
/* Mark the segment as destroyed now. Since we're attached, it won't
|
||||
actually be destroyed, but if we crashed before doing this, it wouldn't
|
||||
be destroyed despite nobody being attached anymore. */
|
||||
shmctl(wi->shminfo.shmid, IPC_RMID, 0);
|
||||
#endif
|
||||
|
||||
if (!wi->ximage)
|
||||
{
|
||||
no_xshm:
|
||||
wi->use_shm = 0;
|
||||
wi->ximage = XCreateImage(wi->display, visual, drawing_depth,
|
||||
ZPixmap, 0, NULL,
|
||||
wi->window->xframe.size.width,
|
||||
wi->window->xframe.size.height,
|
||||
8, 0);
|
||||
|
||||
/* Normally, the data of an XImage is saved with the X server's
|
||||
byte order. However, some backends (notably cairo) use the
|
||||
native byte order of the client for the backend image, hence
|
||||
we must set the image's byte order here. Without this, GNUstep
|
||||
applications would display wrong colors on an X server that
|
||||
is running on a machine with a different byte order than the
|
||||
client (bug #28590). */
|
||||
wi->ximage->byte_order = wi->DI.byte_order;
|
||||
wi->ximage->data = malloc(wi->ximage->height * wi->ximage->bytes_per_line);
|
||||
if (!wi->ximage->data)
|
||||
{
|
||||
XDestroyImage(wi->ximage);
|
||||
wi->ximage = NULL;
|
||||
}
|
||||
/*TODO? wi->ximage = XGetImage(wi->display, wi->drawable,
|
||||
0, 0, wi->window->xframe.size.width, wi->window->xframe.size.height,
|
||||
-1, ZPixmap);*/
|
||||
}
|
||||
}
|
||||
|
||||
if (wi->ximage)
|
||||
{
|
||||
wi->sx = wi->ximage->width;
|
||||
wi->sy = wi->ximage->height;
|
||||
wi->data = (unsigned char *)wi->ximage->data;
|
||||
wi->bytes_per_line = wi->ximage->bytes_per_line;
|
||||
wi->bits_per_pixel = wi->ximage->bits_per_pixel;
|
||||
wi->bytes_per_pixel = wi->bits_per_pixel / 8;
|
||||
// NSLog(@"%@ ximage=%p data=%p\n", wi->ximage, wi->data);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"Warning: failed to create image for window!");
|
||||
wi->data = NULL;
|
||||
}
|
||||
|
||||
return AUTORELEASE(wi);
|
||||
}
|
||||
|
||||
|
||||
extern int XShmGetEventBase(Display *d);
|
||||
|
||||
- (void) _gotShmCompletion
|
||||
{
|
||||
#ifdef XSHM
|
||||
if (!use_shm)
|
||||
return;
|
||||
|
||||
pending_event = 0;
|
||||
if (pending_put)
|
||||
{
|
||||
pending_put = 0;
|
||||
if (pending_rect.x + pending_rect.w > window->xframe.size.width)
|
||||
{
|
||||
pending_rect.w = window->xframe.size.width - pending_rect.x;
|
||||
if (pending_rect.w <= 0)
|
||||
return;
|
||||
}
|
||||
if (pending_rect.y + pending_rect.h > window->xframe.size.height)
|
||||
{
|
||||
pending_rect.h = window->xframe.size.height - pending_rect.y;
|
||||
if (pending_rect.h <= 0)
|
||||
return;
|
||||
}
|
||||
if (!XShmPutImage(display, drawable, gc, ximage,
|
||||
pending_rect.x, pending_rect.y,
|
||||
pending_rect.x, pending_rect.y,
|
||||
pending_rect.w, pending_rect.h,
|
||||
1))
|
||||
{
|
||||
NSLog(@"XShmPutImage failed?");
|
||||
}
|
||||
else
|
||||
{
|
||||
pending_event = 1;
|
||||
}
|
||||
}
|
||||
// XFlush(window->display);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) _exposeRect: (NSRect)rect
|
||||
{
|
||||
/* TODO: Somehow, we can get negative coordinates in the rectangle. So far
|
||||
I've tracked them back to [NSWindow flushWindow]. Should probably figure
|
||||
out where they're coming from originally, and see if they really should be
|
||||
negative. (Seems to happen when a window is created or resized, so possibly
|
||||
something is refreshing while coordinates are still invalid.
|
||||
|
||||
Also, just about every resize of a window causes a few calls here with
|
||||
rects in the new size before we are updated.
|
||||
|
||||
For now, we just intersect with our known size to avoid problems with X.
|
||||
|
||||
And, to avoid problems with clever optimizations and float vs. double
|
||||
accuracy, we do the test using int: s.
|
||||
*/
|
||||
int x, y, w, h;
|
||||
|
||||
x = floor(rect.origin.x);
|
||||
y = floor(rect.origin.y);
|
||||
w = ceil(rect.size.width + rect.origin.x - x);
|
||||
h = ceil(rect.size.height + rect.origin.y - y);
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if (x + w > sx)
|
||||
{
|
||||
w = sx - x;
|
||||
}
|
||||
if (y + h > sy)
|
||||
{
|
||||
h = sy - y;
|
||||
}
|
||||
|
||||
if (w <= 0 || h <= 0)
|
||||
return;
|
||||
|
||||
#ifdef XSHM
|
||||
if (use_shm)
|
||||
{
|
||||
#ifdef HAVE_XSHAPE
|
||||
/* HACK: lets try to use shaped windows to get some use out of
|
||||
destination alpha */
|
||||
if (has_alpha && use_shape_hack)
|
||||
{
|
||||
static int warn = 0;
|
||||
Pixmap p;
|
||||
int dsize = ((sx + 7) / 8) * sy;
|
||||
unsigned char *buf = malloc(dsize);
|
||||
unsigned char *dst;
|
||||
int bofs;
|
||||
unsigned char *a;
|
||||
int as;
|
||||
int i, x;
|
||||
|
||||
if (!warn)
|
||||
NSLog(@"Warning: activating shaped windows");
|
||||
warn = 1;
|
||||
|
||||
memset(buf, 0xff, dsize);
|
||||
|
||||
#define CUTOFF 128
|
||||
|
||||
if (DI.inline_alpha)
|
||||
{
|
||||
a = data + DI.inline_alpha_ofs;
|
||||
as = DI.bytes_per_pixel;
|
||||
}
|
||||
else
|
||||
{
|
||||
a = alpha;
|
||||
as = 1;
|
||||
}
|
||||
|
||||
for (bofs = 0, i = sx * sy, x = sx, dst = buf; i; i--, a += as)
|
||||
{
|
||||
if (*a < CUTOFF)
|
||||
{
|
||||
*dst = *dst & ~(1 << bofs);
|
||||
}
|
||||
bofs++;
|
||||
if (bofs == 8)
|
||||
{
|
||||
dst++;
|
||||
bofs = 0;
|
||||
}
|
||||
x--;
|
||||
if (!x)
|
||||
{
|
||||
if (bofs)
|
||||
{
|
||||
bofs = 0;
|
||||
dst++;
|
||||
}
|
||||
x = sx;
|
||||
}
|
||||
}
|
||||
#undef CUTOFF
|
||||
//NSLog(@"check shape");
|
||||
if (old_shape_size == dsize && !memcmp(old_shape, buf, dsize))
|
||||
{
|
||||
free(buf);
|
||||
// NSLog(@" same shape");
|
||||
}
|
||||
else
|
||||
{
|
||||
// NSLog(@" updating");
|
||||
p = XCreatePixmapFromBitmapData(display, window->ident,
|
||||
(char *)buf, sx, sy, 1, 0, 1);
|
||||
free(old_shape);
|
||||
old_shape = buf;
|
||||
old_shape_size = dsize;
|
||||
XShapeCombineMask(display, window->ident,
|
||||
ShapeBounding, 0, 0, p, ShapeSet);
|
||||
XFreePixmap(display, p);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_XSHAPE
|
||||
|
||||
if (pending_event)
|
||||
{
|
||||
if (!pending_put)
|
||||
{
|
||||
pending_put = 1;
|
||||
pending_rect.x = x;
|
||||
pending_rect.y = y;
|
||||
pending_rect.w = w;
|
||||
pending_rect.h = h;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x < pending_rect.x)
|
||||
{
|
||||
pending_rect.w += pending_rect.x - x;
|
||||
pending_rect.x = x;
|
||||
}
|
||||
if (x + w > pending_rect.x + pending_rect.w)
|
||||
{
|
||||
pending_rect.w = x + w - pending_rect.x;
|
||||
}
|
||||
if (y < pending_rect.y)
|
||||
{
|
||||
pending_rect.h += pending_rect.y - y;
|
||||
pending_rect.y = y;
|
||||
}
|
||||
if (y + h > pending_rect.y + pending_rect.h)
|
||||
{
|
||||
pending_rect.h = y + h - pending_rect.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pending_put = 0;
|
||||
if (!XShmPutImage(display, drawable, gc, ximage,
|
||||
x, y, x, y, w, h, 1))
|
||||
{
|
||||
NSLog(@"XShmPutImage failed?");
|
||||
}
|
||||
else
|
||||
{
|
||||
pending_event = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Performance hack. Check right away for ShmCompletion
|
||||
events. */
|
||||
{
|
||||
XEvent e;
|
||||
|
||||
while (XCheckTypedEvent(window->display,
|
||||
XShmGetEventBase(window->display) + ShmCompletion, &e))
|
||||
{
|
||||
[isa _gotShmCompletion: ((XShmCompletionEvent *)&e)->drawable];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (ximage)
|
||||
{
|
||||
XPutImage(display, drawable, gc, ximage, x, y, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) needsAlpha
|
||||
{
|
||||
if (has_alpha)
|
||||
return;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
// NSLog(@"needs alpha for %p: %ix%i", self, sx, sy);
|
||||
|
||||
if (DI.inline_alpha)
|
||||
{
|
||||
int i;
|
||||
unsigned char *s;
|
||||
alpha = NULL;
|
||||
has_alpha = 1;
|
||||
/* fill the alpha channel */
|
||||
for (i = 0, s = data + DI.inline_alpha_ofs; i < sx * sy;
|
||||
i++, s += DI.bytes_per_pixel)
|
||||
*s = 0xff;
|
||||
return;
|
||||
}
|
||||
|
||||
alpha = malloc(sx * sy);
|
||||
if (!alpha)
|
||||
{
|
||||
NSLog(@"Warning! Failed to allocate alpha buffer for window!");
|
||||
return;
|
||||
}
|
||||
|
||||
// NSLog(@"got buffer at %p", alpha);
|
||||
|
||||
has_alpha = 1;
|
||||
memset(alpha, 0xff, sx * sy);
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_window_buffers; i++)
|
||||
if (window_buffers[i] == self) break;
|
||||
if (i < num_window_buffers)
|
||||
{
|
||||
num_window_buffers--;
|
||||
for (; i < num_window_buffers; i++)
|
||||
window_buffers[i] = window_buffers[i + 1];
|
||||
}
|
||||
|
||||
if (ximage)
|
||||
{
|
||||
if (pixmap)
|
||||
{
|
||||
XFreePixmap(display,pixmap);
|
||||
pixmap=0;
|
||||
}
|
||||
|
||||
#ifdef XSHM
|
||||
if (use_shm)
|
||||
{
|
||||
XShmDetach(display, &shminfo);
|
||||
XDestroyImage(ximage);
|
||||
shmdt(shminfo.shmaddr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
XDestroyImage(ximage);
|
||||
}
|
||||
if (alpha)
|
||||
free(alpha);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
+ (void) _gotShmCompletion: (Drawable)d
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_window_buffers; i++)
|
||||
{
|
||||
if (window_buffers[i]->drawable == d)
|
||||
{
|
||||
[window_buffers[i] _gotShmCompletion];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,899 +0,0 @@
|
|||
/* context.c - X context management
|
||||
*
|
||||
* Raster graphics library
|
||||
*
|
||||
* Copyright (c) 1997-2002 Alfredo K. Kojima
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "wrasterP.h"
|
||||
|
||||
#ifdef HAVE_HERMES
|
||||
#include <Hermes/Hermes.h>
|
||||
#endif
|
||||
|
||||
#include "x11/StdCmap.h"
|
||||
|
||||
#include "x11/wraster.h"
|
||||
|
||||
#ifdef XRENDER
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#endif
|
||||
|
||||
extern void _wraster_change_filter(int type);
|
||||
|
||||
|
||||
static Bool bestContext(Display *dpy, int screen_number, RContext *context);
|
||||
|
||||
static RContextAttributes DEFAULT_CONTEXT_ATTRIBS = {
|
||||
RC_UseSharedMemory|RC_RenderMode|RC_ColorsPerChannel, /* flags */
|
||||
RDitheredRendering, /* render_mode */
|
||||
4, /* colors_per_channel */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
True, /* use_shared_memory */
|
||||
RMitchellFilter,
|
||||
RUseStdColormap
|
||||
};
|
||||
|
||||
char**
|
||||
RSupportedFileFormats(void)
|
||||
{
|
||||
static char *tmp[2];
|
||||
tmp[0] = NULL;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Colormap allocation for PseudoColor visuals:
|
||||
*
|
||||
*
|
||||
* switch standardColormap:
|
||||
* none:
|
||||
* allocate colors according to colors_per_channel
|
||||
*
|
||||
* best/default:
|
||||
* if there's a std colormap defined then use it
|
||||
*
|
||||
* else
|
||||
* create a std colormap and set it
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
* allocateStandardPseudoColor
|
||||
* Creates the internal colormap for PseudoColor, setting the
|
||||
* color values according to the supplied standard colormap.
|
||||
*
|
||||
* Returns: -
|
||||
*
|
||||
* Side effects: -
|
||||
*
|
||||
* Notes: -
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static Bool
|
||||
allocateStandardPseudoColor(RContext *ctx, XStandardColormap *stdcmap)
|
||||
{
|
||||
int i;
|
||||
|
||||
ctx->ncolors = stdcmap->red_max * stdcmap->red_mult
|
||||
+ stdcmap->green_max * stdcmap->green_mult
|
||||
+ stdcmap->blue_max * stdcmap->blue_mult + 1;
|
||||
|
||||
if (ctx->ncolors <= 1) {
|
||||
RErrorCode = RERR_INTERNAL;
|
||||
puts("wraster: bad standard colormap");
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
ctx->colors = malloc(sizeof(XColor)*ctx->ncolors);
|
||||
if (!ctx->colors) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
ctx->pixels = malloc(sizeof(unsigned long)*ctx->ncolors);
|
||||
if (!ctx->pixels) {
|
||||
|
||||
free(ctx->colors);
|
||||
ctx->colors = NULL;
|
||||
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
#define calc(max,mult) (((i / stdcmap->mult) % \
|
||||
(stdcmap->max + 1)) * 65535) / stdcmap->max
|
||||
|
||||
for (i = 0; i < ctx->ncolors; i++) {
|
||||
ctx->colors[i].pixel = i + stdcmap->base_pixel;
|
||||
ctx->colors[i].red = calc(red_max, red_mult);
|
||||
ctx->colors[i].green = calc(green_max, green_mult);
|
||||
ctx->colors[i].blue = calc(blue_max, blue_mult);
|
||||
|
||||
ctx->pixels[i] = ctx->colors[i].pixel;
|
||||
}
|
||||
|
||||
#undef calc
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
static Bool
|
||||
setupStandardColormap(RContext *ctx, Atom property)
|
||||
{
|
||||
if (!XmuLookupStandardColormap(ctx->dpy, ctx->screen_number,
|
||||
ctx->visual->visualid,
|
||||
ctx->depth, property,
|
||||
True, True)) {
|
||||
RErrorCode = RERR_STDCMAPFAIL;
|
||||
|
||||
return False;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static Bool
|
||||
allocatePseudoColor(RContext *ctx)
|
||||
{
|
||||
XColor *colors;
|
||||
XColor avcolors[256];
|
||||
int avncolors;
|
||||
int i, ncolors, r, g, b;
|
||||
int retries;
|
||||
int cpc = ctx->attribs->colors_per_channel;
|
||||
|
||||
ncolors = cpc * cpc * cpc;
|
||||
|
||||
if (ncolors > (1<<ctx->depth)) {
|
||||
/* reduce colormap size */
|
||||
cpc = ctx->attribs->colors_per_channel = 1<<((int)ctx->depth/3);
|
||||
ncolors = cpc * cpc * cpc;
|
||||
}
|
||||
|
||||
assert(cpc >= 2 && ncolors <= (1<<ctx->depth));
|
||||
|
||||
colors = malloc(sizeof(XColor)*ncolors);
|
||||
if (!colors) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return False;
|
||||
}
|
||||
|
||||
ctx->pixels = malloc(sizeof(unsigned long)*ncolors);
|
||||
if (!ctx->pixels) {
|
||||
free(colors);
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return False;
|
||||
}
|
||||
|
||||
i=0;
|
||||
|
||||
if ((ctx->attribs->flags & RC_GammaCorrection) && ctx->attribs->rgamma > 0
|
||||
&& ctx->attribs->ggamma > 0 && ctx->attribs->bgamma > 0) {
|
||||
double rg, gg, bg;
|
||||
double tmp;
|
||||
|
||||
/* do gamma correction */
|
||||
rg = 1.0/ctx->attribs->rgamma;
|
||||
gg = 1.0/ctx->attribs->ggamma;
|
||||
bg = 1.0/ctx->attribs->bgamma;
|
||||
for (r=0; r<cpc; r++) {
|
||||
for (g=0; g<cpc; g++) {
|
||||
for (b=0; b<cpc; b++) {
|
||||
colors[i].red=(r*0xffff) / (cpc-1);
|
||||
colors[i].green=(g*0xffff) / (cpc-1);
|
||||
colors[i].blue=(b*0xffff) / (cpc-1);
|
||||
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||
|
||||
tmp = (double)colors[i].red / 65536.0;
|
||||
colors[i].red = (unsigned short)(65536.0*pow(tmp, rg));
|
||||
|
||||
tmp = (double)colors[i].green / 65536.0;
|
||||
colors[i].green = (unsigned short)(65536.0*pow(tmp, gg));
|
||||
|
||||
tmp = (double)colors[i].blue / 65536.0;
|
||||
colors[i].blue = (unsigned short)(65536.0*pow(tmp, bg));
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (r=0; r<cpc; r++) {
|
||||
for (g=0; g<cpc; g++) {
|
||||
for (b=0; b<cpc; b++) {
|
||||
colors[i].red=(r*0xffff) / (cpc-1);
|
||||
colors[i].green=(g*0xffff) / (cpc-1);
|
||||
colors[i].blue=(b*0xffff) / (cpc-1);
|
||||
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* try to allocate the colors */
|
||||
for (i=0; i<ncolors; i++) {
|
||||
if (!XAllocColor(ctx->dpy, ctx->cmap, &(colors[i]))) {
|
||||
colors[i].flags = 0; /* failed */
|
||||
} else {
|
||||
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||
}
|
||||
}
|
||||
/* try to allocate close values for the colors that couldn't
|
||||
* be allocated before */
|
||||
avncolors = (1<<ctx->depth>256 ? 256 : 1<<ctx->depth);
|
||||
for (i=0; i<avncolors; i++) avcolors[i].pixel = i;
|
||||
|
||||
XQueryColors(ctx->dpy, ctx->cmap, avcolors, avncolors);
|
||||
|
||||
for (i=0; i<ncolors; i++) {
|
||||
if (colors[i].flags==0) {
|
||||
int j;
|
||||
unsigned long cdiff=0xffffffff, diff;
|
||||
unsigned long closest=0;
|
||||
|
||||
retries = 2;
|
||||
|
||||
while (retries--) {
|
||||
/* find closest color */
|
||||
for (j=0; j<avncolors; j++) {
|
||||
r = (colors[i].red - avcolors[i].red)>>8;
|
||||
g = (colors[i].green - avcolors[i].green)>>8;
|
||||
b = (colors[i].blue - avcolors[i].blue)>>8;
|
||||
diff = r*r + g*g + b*b;
|
||||
if (diff<cdiff) {
|
||||
cdiff = diff;
|
||||
closest = j;
|
||||
}
|
||||
}
|
||||
/* allocate closest color found */
|
||||
colors[i].red = avcolors[closest].red;
|
||||
colors[i].green = avcolors[closest].green;
|
||||
colors[i].blue = avcolors[closest].blue;
|
||||
if (XAllocColor(ctx->dpy, ctx->cmap, &colors[i])) {
|
||||
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||
break; /* succeeded, don't need to retry */
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("close color allocation failed. Retrying...\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->colors = colors;
|
||||
ctx->ncolors = ncolors;
|
||||
|
||||
/* fill the pixels shortcut array */
|
||||
for (i = 0; i < ncolors; i++) {
|
||||
ctx->pixels[i] = ctx->colors[i].pixel;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
static XColor*
|
||||
allocateGrayScale(RContext *ctx)
|
||||
{
|
||||
XColor *colors;
|
||||
XColor avcolors[256];
|
||||
int avncolors;
|
||||
int i, ncolors, r, g, b;
|
||||
int retries;
|
||||
int cpc = ctx->attribs->colors_per_channel;
|
||||
|
||||
ncolors = cpc * cpc * cpc;
|
||||
|
||||
if (ctx->vclass == StaticGray) {
|
||||
/* we might as well use all grays */
|
||||
ncolors = 1<<ctx->depth;
|
||||
} else {
|
||||
if ( ncolors > (1<<ctx->depth) ) {
|
||||
/* reduce colormap size */
|
||||
cpc = ctx->attribs->colors_per_channel = 1<<((int)ctx->depth/3);
|
||||
ncolors = cpc * cpc * cpc;
|
||||
}
|
||||
|
||||
assert(cpc >= 2 && ncolors <= (1<<ctx->depth));
|
||||
}
|
||||
|
||||
if (ncolors>=256 && ctx->vclass==StaticGray) {
|
||||
/* don't need dithering for 256 levels of gray in StaticGray visual */
|
||||
ctx->attribs->render_mode = RBestMatchRendering;
|
||||
}
|
||||
|
||||
colors = malloc(sizeof(XColor)*ncolors);
|
||||
if (!colors) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return False;
|
||||
}
|
||||
for (i=0; i<ncolors; i++) {
|
||||
colors[i].red=(i*0xffff) / (ncolors-1);
|
||||
colors[i].green=(i*0xffff) / (ncolors-1);
|
||||
colors[i].blue=(i*0xffff) / (ncolors-1);
|
||||
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||
}
|
||||
/* try to allocate the colors */
|
||||
for (i=0; i<ncolors; i++) {
|
||||
#ifdef DEBUG
|
||||
printf("trying:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
|
||||
#endif
|
||||
if (!XAllocColor(ctx->dpy, ctx->cmap, &(colors[i]))) {
|
||||
colors[i].flags = 0; /* failed */
|
||||
#ifdef DEBUG
|
||||
printf("failed:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
|
||||
#endif
|
||||
} else {
|
||||
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||
#ifdef DEBUG
|
||||
printf("success:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* try to allocate close values for the colors that couldn't
|
||||
* be allocated before */
|
||||
avncolors = (1<<ctx->depth>256 ? 256 : 1<<ctx->depth);
|
||||
for (i=0; i<avncolors; i++) avcolors[i].pixel = i;
|
||||
|
||||
XQueryColors(ctx->dpy, ctx->cmap, avcolors, avncolors);
|
||||
|
||||
for (i=0; i<ncolors; i++) {
|
||||
if (colors[i].flags==0) {
|
||||
int j;
|
||||
unsigned long cdiff=0xffffffff, diff;
|
||||
unsigned long closest=0;
|
||||
|
||||
retries = 2;
|
||||
|
||||
while (retries--) {
|
||||
/* find closest color */
|
||||
for (j=0; j<avncolors; j++) {
|
||||
r = (colors[i].red - avcolors[i].red)>>8;
|
||||
g = (colors[i].green - avcolors[i].green)>>8;
|
||||
b = (colors[i].blue - avcolors[i].blue)>>8;
|
||||
diff = r*r + g*g + b*b;
|
||||
if (diff<cdiff) {
|
||||
cdiff = diff;
|
||||
closest = j;
|
||||
}
|
||||
}
|
||||
/* allocate closest color found */
|
||||
#ifdef DEBUG
|
||||
printf("best match:%x,%x,%x => %x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue,avcolors[closest].red,avcolors[closest].green,avcolors[closest].blue);
|
||||
#endif
|
||||
colors[i].red = avcolors[closest].red;
|
||||
colors[i].green = avcolors[closest].green;
|
||||
colors[i].blue = avcolors[closest].blue;
|
||||
if (XAllocColor(ctx->dpy, ctx->cmap, &colors[i])) {
|
||||
colors[i].flags = DoRed|DoGreen|DoBlue;
|
||||
break; /* succeeded, don't need to retry */
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("close color allocation failed. Retrying...\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
|
||||
static Bool
|
||||
setupPseudoColorColormap(RContext *context)
|
||||
{
|
||||
Atom property = 0;
|
||||
|
||||
if (context->attribs->standard_colormap_mode == RCreateStdColormap) {
|
||||
property = XInternAtom(context->dpy, "RGB_DEFAULT_MAP", False);
|
||||
|
||||
if (!setupStandardColormap(context, property)) {
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
if (context->attribs->standard_colormap_mode != RIgnoreStdColormap) {
|
||||
XStandardColormap *maps;
|
||||
int count, i;
|
||||
|
||||
if (!property) {
|
||||
property = XInternAtom(context->dpy, "RGB_BEST_MAP", False);
|
||||
if (!XGetRGBColormaps(context->dpy,
|
||||
DefaultRootWindow(context->dpy),
|
||||
&maps, &count, property)) {
|
||||
maps = NULL;
|
||||
}
|
||||
|
||||
if (!maps) {
|
||||
property = XInternAtom(context->dpy, "RGB_DEFAULT_MAP", False);
|
||||
if (!XGetRGBColormaps(context->dpy,
|
||||
DefaultRootWindow(context->dpy),
|
||||
&maps, &count, property)) {
|
||||
maps = NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!XGetRGBColormaps(context->dpy,
|
||||
DefaultRootWindow(context->dpy),
|
||||
&maps, &count, property)) {
|
||||
maps = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (maps) {
|
||||
int theMap = -1;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (maps[i].visualid == context->visual->visualid) {
|
||||
theMap = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (theMap < 0) {
|
||||
puts("wrlib: no std cmap found");
|
||||
}
|
||||
|
||||
if (theMap >= 0
|
||||
&& allocateStandardPseudoColor(context, &maps[theMap])) {
|
||||
|
||||
context->std_rgb_map = XAllocStandardColormap();
|
||||
|
||||
*context->std_rgb_map = maps[theMap];
|
||||
|
||||
context->cmap = context->std_rgb_map->colormap;
|
||||
|
||||
XFree(maps);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
XFree(maps);
|
||||
}
|
||||
}
|
||||
|
||||
context->attribs->standard_colormap_mode = RIgnoreStdColormap;
|
||||
|
||||
/* RIgnoreStdColormap and fallback */
|
||||
return allocatePseudoColor(context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static char*
|
||||
mygetenv(char *var, int scr)
|
||||
{
|
||||
char *p;
|
||||
char varname[64];
|
||||
|
||||
sprintf(varname, "%s%i", var, scr);
|
||||
p = getenv(varname);
|
||||
if (!p) {
|
||||
p = getenv(var);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gatherconfig(RContext *context, int screen_n)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = mygetenv("WRASTER_GAMMA", screen_n);
|
||||
if (ptr) {
|
||||
float g1,g2,g3;
|
||||
if (sscanf(ptr, "%f/%f/%f", &g1, &g2, &g3)!=3
|
||||
|| g1<=0.0 || g2<=0.0 || g3<=0.0) {
|
||||
printf("wrlib: invalid value(s) for gamma correction \"%s\"\n",
|
||||
ptr);
|
||||
} else {
|
||||
context->attribs->flags |= RC_GammaCorrection;
|
||||
context->attribs->rgamma = g1;
|
||||
context->attribs->ggamma = g2;
|
||||
context->attribs->bgamma = g3;
|
||||
}
|
||||
}
|
||||
ptr = mygetenv("WRASTER_COLOR_RESOLUTION", screen_n);
|
||||
if (ptr) {
|
||||
int i;
|
||||
if (sscanf(ptr, "%d", &i)!=1 || i<2 || i>6) {
|
||||
printf("wrlib: invalid value for color resolution \"%s\"\n",ptr);
|
||||
} else {
|
||||
context->attribs->flags |= RC_ColorsPerChannel;
|
||||
context->attribs->colors_per_channel = i;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = mygetenv("WRASTER_OPTIMIZE_FOR_SPEED", screen_n);
|
||||
if (ptr) {
|
||||
context->flags.optimize_for_speed = 1;
|
||||
} else {
|
||||
context->flags.optimize_for_speed = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
getColormap(RContext *context, int screen_number)
|
||||
{
|
||||
Colormap cmap = None;
|
||||
XStandardColormap *cmaps;
|
||||
int ncmaps, i;
|
||||
|
||||
if (XGetRGBColormaps(context->dpy,
|
||||
RootWindow(context->dpy, screen_number),
|
||||
&cmaps, &ncmaps, XA_RGB_DEFAULT_MAP)) {
|
||||
for (i=0; i<ncmaps; ++i) {
|
||||
if (cmaps[i].visualid == context->visual->visualid) {
|
||||
cmap = cmaps[i].colormap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
XFree(cmaps);
|
||||
}
|
||||
if (cmap == None) {
|
||||
XColor color;
|
||||
|
||||
cmap = XCreateColormap(context->dpy,
|
||||
RootWindow(context->dpy, screen_number),
|
||||
context->visual, AllocNone);
|
||||
|
||||
color.red = color.green = color.blue = 0;
|
||||
XAllocColor(context->dpy, cmap, &color);
|
||||
context->black = color.pixel;
|
||||
|
||||
color.red = color.green = color.blue = 0xffff;
|
||||
XAllocColor(context->dpy, cmap, &color);
|
||||
context->white = color.pixel;
|
||||
|
||||
}
|
||||
context->cmap = cmap;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
count_offset(unsigned long mask)
|
||||
{
|
||||
int i;
|
||||
|
||||
i=0;
|
||||
while ((mask & 1)==0) {
|
||||
i++;
|
||||
mask = mask >> 1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
RContext*
|
||||
RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs)
|
||||
{
|
||||
RContext *context;
|
||||
XGCValues gcv;
|
||||
|
||||
|
||||
context = malloc(sizeof(RContext));
|
||||
if (!context) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
memset(context, 0, sizeof(RContext));
|
||||
|
||||
context->dpy = dpy;
|
||||
|
||||
context->screen_number = screen_number;
|
||||
|
||||
context->attribs = malloc(sizeof(RContextAttributes));
|
||||
if (!context->attribs) {
|
||||
free(context);
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
if (!attribs)
|
||||
*context->attribs = DEFAULT_CONTEXT_ATTRIBS;
|
||||
else
|
||||
*context->attribs = *attribs;
|
||||
|
||||
if (!(context->attribs->flags & RC_StandardColormap)) {
|
||||
context->attribs->standard_colormap_mode = RUseStdColormap;
|
||||
}
|
||||
|
||||
if (!(context->attribs->flags & RC_ScalingFilter)) {
|
||||
context->attribs->flags |= RC_ScalingFilter;
|
||||
context->attribs->scaling_filter = RMitchellFilter;
|
||||
}
|
||||
|
||||
/* get configuration from environment variables */
|
||||
gatherconfig(context, screen_number);
|
||||
#ifndef BENCH
|
||||
_wraster_change_filter(context->attribs->scaling_filter);
|
||||
#endif
|
||||
if ((context->attribs->flags & RC_VisualID)) {
|
||||
XVisualInfo *vinfo, templ;
|
||||
int nret;
|
||||
|
||||
templ.screen = screen_number;
|
||||
templ.visualid = context->attribs->visualid;
|
||||
vinfo = XGetVisualInfo(context->dpy, VisualIDMask|VisualScreenMask,
|
||||
&templ, &nret);
|
||||
if (!vinfo || nret==0) {
|
||||
free(context);
|
||||
RErrorCode = RERR_BADVISUALID;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (vinfo[0].visual == DefaultVisual(dpy, screen_number)) {
|
||||
context->attribs->flags |= RC_DefaultVisual;
|
||||
} else {
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
|
||||
context->visual = vinfo[0].visual;
|
||||
context->depth = vinfo[0].depth;
|
||||
context->vclass = vinfo[0].class;
|
||||
getColormap(context, screen_number);
|
||||
attr.colormap = context->cmap;
|
||||
attr.override_redirect = True;
|
||||
attr.border_pixel = 0;
|
||||
attr.background_pixel = 0;
|
||||
mask = CWBorderPixel|CWColormap|CWOverrideRedirect|CWBackPixel;
|
||||
context->drawable =
|
||||
XCreateWindow(dpy, RootWindow(dpy, screen_number), 1, 1,
|
||||
1, 1, 0, context->depth, CopyFromParent,
|
||||
context->visual, mask, &attr);
|
||||
/* XSetWindowColormap(dpy, context->drawable, attr.colormap);*/
|
||||
}
|
||||
XFree(vinfo);
|
||||
}
|
||||
|
||||
/* use default */
|
||||
if (!context->visual) {
|
||||
if ((context->attribs->flags & RC_DefaultVisual)
|
||||
|| !bestContext(dpy, screen_number, context)) {
|
||||
context->visual = DefaultVisual(dpy, screen_number);
|
||||
context->depth = DefaultDepth(dpy, screen_number);
|
||||
context->cmap = DefaultColormap(dpy, screen_number);
|
||||
context->drawable = RootWindow(dpy, screen_number);
|
||||
context->black = BlackPixel(dpy, screen_number);
|
||||
context->white = WhitePixel(dpy, screen_number);
|
||||
context->vclass = context->visual->class;
|
||||
}
|
||||
}
|
||||
|
||||
gcv.function = GXcopy;
|
||||
gcv.graphics_exposures = False;
|
||||
context->copy_gc = XCreateGC(dpy, context->drawable, GCFunction
|
||||
|GCGraphicsExposures, &gcv);
|
||||
|
||||
#ifdef HAVE_HERMES
|
||||
context->hermes_data = malloc(sizeof(RHermesData));
|
||||
if (!context->hermes_data) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Hermes_Init();
|
||||
|
||||
context->hermes_data->palette = Hermes_PaletteInstance();
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (context->attribs->render_mode == RDitheredRendering) {
|
||||
flags |= HERMES_CONVERT_DITHER;
|
||||
}
|
||||
context->hermes_data->converter = Hermes_ConverterInstance(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (context->vclass == PseudoColor || context->vclass == StaticColor) {
|
||||
if (!setupPseudoColorColormap(context)) {
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef HAVE_HERMES
|
||||
{
|
||||
int32 palette[256];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < context->ncolors; i++) {
|
||||
palette[i] = ((context->colors[i].red >> 8) << 16) ||
|
||||
((context->colors[i].green >> 8) << 8) ||
|
||||
((context->colors[i].blue >> 8));
|
||||
}
|
||||
|
||||
Hermes_PaletteSet(context->hermes_data->palette, palette);
|
||||
}
|
||||
#endif
|
||||
} else if (context->vclass == GrayScale || context->vclass == StaticGray) {
|
||||
context->colors = allocateGrayScale(context);
|
||||
if (!context->colors) {
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef HAVE_HERMES
|
||||
{
|
||||
int32 palette[256];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < context->ncolors; i++) {
|
||||
palette[i] = ((context->colors[i].red >> 8) << 16) ||
|
||||
((context->colors[i].green >> 8) << 8) ||
|
||||
((context->colors[i].blue >> 8));
|
||||
}
|
||||
|
||||
Hermes_PaletteSet(context->hermes_data->palette, palette);
|
||||
}
|
||||
#endif
|
||||
} else if (context->vclass == TrueColor) {
|
||||
/* calc offsets to create a TrueColor pixel */
|
||||
context->red_offset = count_offset(context->visual->red_mask);
|
||||
context->green_offset = count_offset(context->visual->green_mask);
|
||||
context->blue_offset = count_offset(context->visual->blue_mask);
|
||||
/* disable dithering on 24 bits visuals */
|
||||
if (context->depth >= 24)
|
||||
context->attribs->render_mode = RBestMatchRendering;
|
||||
}
|
||||
|
||||
#ifdef HAVE_HERMES
|
||||
|
||||
#endif
|
||||
|
||||
/* check avaiability of MIT-SHM */
|
||||
#ifdef XSHM
|
||||
if (!(context->attribs->flags & RC_UseSharedMemory)) {
|
||||
context->attribs->flags |= RC_UseSharedMemory;
|
||||
context->attribs->use_shared_memory = True;
|
||||
}
|
||||
|
||||
if (context->attribs->use_shared_memory) {
|
||||
int major, minor;
|
||||
Bool sharedPixmaps;
|
||||
|
||||
context->flags.use_shared_pixmap = 0;
|
||||
|
||||
if (!XShmQueryVersion(context->dpy, &major, &minor, &sharedPixmaps)) {
|
||||
context->attribs->use_shared_memory = False;
|
||||
} else {
|
||||
if (XShmPixmapFormat(context->dpy)==ZPixmap)
|
||||
context->flags.use_shared_pixmap = sharedPixmaps;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
static Bool
|
||||
bestContext(Display *dpy, int screen_number, RContext *context)
|
||||
{
|
||||
XVisualInfo *vinfo=NULL, rvinfo;
|
||||
int best = -1, numvis, i;
|
||||
long flags;
|
||||
XSetWindowAttributes attr;
|
||||
|
||||
rvinfo.class = TrueColor;
|
||||
rvinfo.screen = screen_number;
|
||||
|
||||
#ifdef XRENDER
|
||||
|
||||
rvinfo.depth = 32;
|
||||
flags = VisualClassMask | VisualScreenMask | VisualDepthMask;
|
||||
|
||||
vinfo = XGetVisualInfo(dpy, flags, &rvinfo, &numvis);
|
||||
if (vinfo)
|
||||
{
|
||||
for (i=numvis-1, best = -1; i>=0; i--)
|
||||
{
|
||||
XRenderPictFormat* pictFormat =
|
||||
XRenderFindVisualFormat (dpy, vinfo[i].visual);
|
||||
if ((pictFormat->type == PictTypeDirect)
|
||||
&& (pictFormat->direct.alphaMask))
|
||||
{
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (best == -1)
|
||||
{
|
||||
flags = VisualClassMask | VisualScreenMask;
|
||||
vinfo = XGetVisualInfo(dpy, flags, &rvinfo, &numvis);
|
||||
if (vinfo)
|
||||
{ /* look for a TrueColor, 24-bit or more (pref 24) */
|
||||
for (i=numvis-1, best = -1; i>=0; i--)
|
||||
{
|
||||
if (vinfo[i].depth == 24) best = i;
|
||||
else if (vinfo[i].depth>24 && best<0) best = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (best == -1) { /* look for a DirectColor, 24-bit or more (pref 24) */
|
||||
rvinfo.class = DirectColor;
|
||||
if (vinfo) XFree((char *) vinfo);
|
||||
vinfo = XGetVisualInfo(dpy, flags, &rvinfo, &numvis);
|
||||
if (vinfo) {
|
||||
for (i=0, best = -1; i<numvis; i++) {
|
||||
if (vinfo[i].depth == 24) best = i;
|
||||
else if (vinfo[i].depth>24 && best<0) best = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (best > -1) {
|
||||
context->visual = vinfo[best].visual;
|
||||
context->depth = vinfo[best].depth;
|
||||
context->vclass = vinfo[best].class;
|
||||
getColormap(context, screen_number);
|
||||
attr.colormap = context->cmap;
|
||||
attr.override_redirect = True;
|
||||
attr.border_pixel = 0;
|
||||
context->drawable =
|
||||
XCreateWindow(dpy, RootWindow(dpy, screen_number),
|
||||
1, 1, 1, 1, 0, context->depth,
|
||||
CopyFromParent, context->visual,
|
||||
CWBorderPixel|CWColormap|CWOverrideRedirect, &attr);
|
||||
/* XSetWindowColormap(dpy, context->drawable, context->cmap);*/
|
||||
}
|
||||
if (vinfo) XFree((char *) vinfo);
|
||||
|
||||
if (best < 0)
|
||||
return False;
|
||||
else
|
||||
return True;
|
||||
}
|
1155
Source/x11/convert.c
1155
Source/x11/convert.c
File diff suppressed because it is too large
Load diff
|
@ -1,538 +0,0 @@
|
|||
/* raster.c - main and other misc stuff
|
||||
*
|
||||
* Raster graphics library
|
||||
*
|
||||
* Copyright (c) 1997-2002 Alfredo K. Kojima
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include "x11/wraster.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
char *WRasterLibVersion="0.9";
|
||||
|
||||
int RErrorCode=RERR_NONE;
|
||||
|
||||
|
||||
#define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
|
||||
|
||||
#define MAX_WIDTH 20000
|
||||
#define MAX_HEIGHT 20000
|
||||
/* 20000^2*4 < 2G */
|
||||
|
||||
|
||||
RImage*
|
||||
RCreateImage(unsigned width, unsigned height, int alpha)
|
||||
{
|
||||
RImage *image=NULL;
|
||||
|
||||
assert(width>0 && height>0);
|
||||
|
||||
/* check for bogus image sizes (and avoid overflow as a bonus) */
|
||||
if (width > MAX_WIDTH || height > MAX_HEIGHT) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
image = malloc(sizeof(RImage));
|
||||
if (!image) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(image, 0, sizeof(RImage));
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
image->format = alpha ? RRGBAFormat : RRGBFormat;
|
||||
image->refCount = 1;
|
||||
|
||||
/* the +4 is to give extra bytes at the end of the buffer,
|
||||
* so that we can optimize image conversion for MMX(tm).. see convert.c
|
||||
*/
|
||||
image->data = malloc(width * height * (alpha ? 4 : 3) + 4);
|
||||
if (!image->data) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
free(image);
|
||||
image = NULL;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
RImage*
|
||||
RRetainImage(RImage *image)
|
||||
{
|
||||
if (image)
|
||||
image->refCount++;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RReleaseImage(RImage *image)
|
||||
{
|
||||
assert(image!=NULL);
|
||||
|
||||
image->refCount--;
|
||||
|
||||
if (image->refCount < 1) {
|
||||
free(image->data);
|
||||
free(image);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Obsoleted function. Use RReleaseImage() instead. This was kept only to
|
||||
* allow a smoother transition and to avoid breaking existing programs, but
|
||||
* it will be removed in a future release. Right now is just an alias to
|
||||
* RReleaseImage(). Do _NOT_ use RDestroyImage() anymore in your programs.
|
||||
* Being an alias to RReleaseImage() this function no longer actually
|
||||
* destroys the image, unless the image is no longer retained in some other
|
||||
* place.
|
||||
*/
|
||||
void
|
||||
RDestroyImage(RImage *image)
|
||||
{
|
||||
RReleaseImage(image);
|
||||
}
|
||||
|
||||
|
||||
RImage*
|
||||
RCloneImage(RImage *image)
|
||||
{
|
||||
RImage *new_image;
|
||||
|
||||
assert(image!=NULL);
|
||||
|
||||
new_image = RCreateImage(image->width, image->height, HAS_ALPHA(image));
|
||||
if (!new_image)
|
||||
return NULL;
|
||||
|
||||
new_image->background = image->background;
|
||||
memcpy(new_image->data, image->data,
|
||||
image->width*image->height*(HAS_ALPHA(image) ? 4 : 3));
|
||||
|
||||
return new_image;
|
||||
}
|
||||
|
||||
|
||||
RImage*
|
||||
RGetSubImage(RImage *image, int x, int y, unsigned width, unsigned height)
|
||||
{
|
||||
int i, ofs;
|
||||
RImage *new_image;
|
||||
unsigned total_line_size, line_size;
|
||||
|
||||
assert(image!=NULL);
|
||||
assert(x>=0 && y>=0);
|
||||
assert(x<image->width && y<image->height);
|
||||
assert(width>0 && height>0);
|
||||
|
||||
if (x+width > image->width)
|
||||
width = image->width-x;
|
||||
if (y+height > image->height)
|
||||
height = image->height-y;
|
||||
|
||||
new_image = RCreateImage(width, height, HAS_ALPHA(image));
|
||||
|
||||
if (!new_image)
|
||||
return NULL;
|
||||
new_image->background = image->background;
|
||||
|
||||
total_line_size = image->width * (HAS_ALPHA(image) ? 4 : 3);
|
||||
line_size = width * (HAS_ALPHA(image) ? 4 : 3);
|
||||
|
||||
ofs = x*(HAS_ALPHA(image) ? 4 : 3) + y*total_line_size;;
|
||||
|
||||
for (i=0; i<height; i++) {
|
||||
memcpy(&new_image->data[i*line_size],
|
||||
&image->data[i*total_line_size+ofs], line_size);
|
||||
}
|
||||
return new_image;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
* RCombineImages-
|
||||
* Combines two equal sized images with alpha image. The second
|
||||
* image will be placed on top of the first one.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
RCombineImages(RImage *image, RImage *src)
|
||||
{
|
||||
assert(image->width == src->width);
|
||||
assert(image->height == src->height);
|
||||
|
||||
if (!HAS_ALPHA(src)) {
|
||||
if (!HAS_ALPHA(image)) {
|
||||
memcpy(image->data, src->data, image->height*image->width*3);
|
||||
} else {
|
||||
int x, y;
|
||||
unsigned char *d, *s;
|
||||
|
||||
d = image->data;
|
||||
s = src->data;
|
||||
for (y = 0; y < image->height; y++) {
|
||||
for (x = 0; x < image->width; x++) {
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
d++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
register int i;
|
||||
unsigned char *d;
|
||||
unsigned char *s;
|
||||
int alpha, calpha;
|
||||
|
||||
d = image->data;
|
||||
s = src->data;
|
||||
|
||||
if (!HAS_ALPHA(image)) {
|
||||
for (i=0; i<image->height*image->width; i++) {
|
||||
alpha = *(s+3);
|
||||
calpha = 255 - alpha;
|
||||
*d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
|
||||
*d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
|
||||
*d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
|
||||
s++;
|
||||
}
|
||||
} else {
|
||||
for (i=0; i<image->height*image->width; i++) {
|
||||
alpha = *(s+3);
|
||||
calpha = 255 - alpha;
|
||||
*d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
|
||||
*d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
|
||||
*d = (((int)*d * calpha) + ((int)*s * alpha))/256; d++; s++;
|
||||
*d++ |= *s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
RCombineImagesWithOpaqueness(RImage *image, RImage *src, int opaqueness)
|
||||
{
|
||||
register int i;
|
||||
unsigned char *d;
|
||||
unsigned char *s;
|
||||
int c_opaqueness;
|
||||
|
||||
assert(image->width == src->width);
|
||||
assert(image->height == src->height);
|
||||
|
||||
d = image->data;
|
||||
s = src->data;
|
||||
|
||||
c_opaqueness = 255 - opaqueness;
|
||||
|
||||
#define OP opaqueness
|
||||
#define COP c_opaqueness
|
||||
|
||||
if (!HAS_ALPHA(src)) {
|
||||
int dalpha = HAS_ALPHA(image);
|
||||
for (i=0; i < image->width*image->height; i++) {
|
||||
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; d++; s++;
|
||||
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; d++; s++;
|
||||
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; d++; s++;
|
||||
if (dalpha) {
|
||||
d++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int tmp;
|
||||
|
||||
if (!HAS_ALPHA(image)) {
|
||||
for (i=0; i<image->width*image->height; i++) {
|
||||
tmp = (*(s+3) * opaqueness)/256;
|
||||
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
|
||||
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
|
||||
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
|
||||
s++;
|
||||
}
|
||||
} else {
|
||||
for (i=0; i<image->width*image->height; i++) {
|
||||
tmp = (*(s+3) * opaqueness)/256;
|
||||
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
|
||||
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
|
||||
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
|
||||
*d |= tmp;
|
||||
d++; s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef OP
|
||||
#undef COP
|
||||
}
|
||||
|
||||
int
|
||||
calculateCombineArea(RImage *des, RImage *src, int *sx, int *sy,
|
||||
unsigned *swidth, unsigned *sheight, int *dx, int *dy)
|
||||
{
|
||||
if (*dx < 0) {
|
||||
*sx = -*dx;
|
||||
*swidth = *swidth + *dx;
|
||||
*dx = 0;
|
||||
}
|
||||
|
||||
if (*dx + *swidth > des->width) {
|
||||
*swidth = des->width - *dx;
|
||||
}
|
||||
|
||||
if (*dy < 0) {
|
||||
*sy = -*dy;
|
||||
*sheight = *sheight + *dy;
|
||||
*dy = 0;
|
||||
}
|
||||
|
||||
if (*dy + *sheight > des->height) {
|
||||
*sheight = des->height - *dy;
|
||||
}
|
||||
|
||||
if (*sheight > 0 && *swidth > 0) {
|
||||
return True;
|
||||
} else return False;
|
||||
}
|
||||
|
||||
void
|
||||
RCombineArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
|
||||
unsigned height, int dx, int dy)
|
||||
{
|
||||
int x, y, dwi, swi;
|
||||
unsigned char *d;
|
||||
unsigned char *s;
|
||||
int alpha, calpha;
|
||||
|
||||
if(!calculateCombineArea(image, src, &sx, &sy, &width, &height, &dx, &dy))
|
||||
return;
|
||||
|
||||
if (!HAS_ALPHA(src)) {
|
||||
if (!HAS_ALPHA(image)) {
|
||||
swi = src->width * 3;
|
||||
dwi = image->width * 3;
|
||||
|
||||
s = src->data + (sy*(int)src->width + sx) * 3;
|
||||
d = image->data + (dy*(int)image->width + dx) * 3;
|
||||
|
||||
for (y=0; y < height; y++) {
|
||||
memcpy(d, s, width*3);
|
||||
d += dwi;
|
||||
s += swi;
|
||||
}
|
||||
} else {
|
||||
swi = (src->width - width) * 3;
|
||||
dwi = (image->width - width) * 4;
|
||||
|
||||
s = src->data + (sy*(int)src->width + sx) * 3;
|
||||
d = image->data + (dy*(int)image->width + dx) * 4;
|
||||
|
||||
for (y=0; y < height; y++) {
|
||||
for (x=0; x < width; x++) {
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
*d++ = *s++;
|
||||
d++;
|
||||
}
|
||||
d += dwi;
|
||||
s += swi;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int dalpha = HAS_ALPHA(image);
|
||||
|
||||
swi = (src->width - width) * 4;
|
||||
s = src->data + (sy*(int)src->width + sx) * 4;
|
||||
if (dalpha) {
|
||||
dwi = (image->width - width) * 4;
|
||||
d = image->data + (dy*(int)image->width + dx) * 4;
|
||||
} else {
|
||||
dwi = (image->width - width) * 3;
|
||||
d = image->data + (dy*(int)image->width + dx) * 3;
|
||||
}
|
||||
|
||||
for (y=0; y < height; y++) {
|
||||
for (x=0; x < width; x++) {
|
||||
alpha = *(s+3);
|
||||
calpha = 255 - alpha;
|
||||
*d = (((int)*d * calpha) + ((int)*s * alpha))/256; s++; d++;
|
||||
*d = (((int)*d * calpha) + ((int)*s * alpha))/256; s++; d++;
|
||||
*d = (((int)*d * calpha) + ((int)*s * alpha))/256; s++; d++;
|
||||
s++;
|
||||
if (dalpha)
|
||||
d++;
|
||||
}
|
||||
d += dwi;
|
||||
s += swi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
|
||||
unsigned width, unsigned height, int dx, int dy,
|
||||
int opaqueness)
|
||||
{
|
||||
int x, y, dwi, swi;
|
||||
int c_opaqueness;
|
||||
unsigned char *s, *d;
|
||||
int dalpha = HAS_ALPHA(image);
|
||||
int dch = (dalpha ? 4 : 3);
|
||||
|
||||
if(!calculateCombineArea(image, src, &sx, &sy, &width, &height, &dx, &dy))
|
||||
return;
|
||||
|
||||
d = image->data + (dy*image->width + dx) * dch;
|
||||
dwi = (image->width - width)*dch;
|
||||
|
||||
c_opaqueness = 255 - opaqueness;
|
||||
|
||||
#define OP opaqueness
|
||||
#define COP c_opaqueness
|
||||
|
||||
if (!HAS_ALPHA(src)) {
|
||||
|
||||
s = src->data + (sy*src->width + sx)*3;
|
||||
swi = (src->width - width) * 3;
|
||||
|
||||
for (y=0; y < height; y++) {
|
||||
for (x=0; x < width; x++) {
|
||||
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; s++; d++;
|
||||
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; s++; d++;
|
||||
*d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256; s++; d++;
|
||||
if (dalpha)
|
||||
d++;
|
||||
}
|
||||
d += dwi; s += swi;
|
||||
}
|
||||
} else {
|
||||
int tmp;
|
||||
|
||||
s = src->data + (sy*src->width + sx)*4;
|
||||
swi = (src->width - width) * 4;
|
||||
|
||||
for (y=0; y < height; y++) {
|
||||
for (x=0; x < width; x++) {
|
||||
tmp = (*(s+3) * opaqueness)/256;
|
||||
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
|
||||
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
|
||||
*d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256; d++; s++;
|
||||
s++;
|
||||
if (dalpha)
|
||||
d++;
|
||||
}
|
||||
d += dwi; s += swi;
|
||||
}
|
||||
}
|
||||
#undef OP
|
||||
#undef COP
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
RCombineImageWithColor(RImage *image, RColor *color)
|
||||
{
|
||||
register int i;
|
||||
unsigned char *d;
|
||||
int alpha, nalpha, r, g, b;
|
||||
|
||||
d = image->data;
|
||||
|
||||
if (!HAS_ALPHA(image)) {
|
||||
/* Image has no alpha channel, so we consider it to be all 255.
|
||||
* Thus there are no transparent parts to be filled. */
|
||||
return;
|
||||
}
|
||||
r = color->red;
|
||||
g = color->green;
|
||||
b = color->blue;
|
||||
|
||||
for (i=0; i < image->width*image->height; i++) {
|
||||
alpha = *(d+3);
|
||||
nalpha = 255 - alpha;
|
||||
|
||||
*d = (((int)*d * alpha) + (r * nalpha))/256; d++;
|
||||
*d = (((int)*d * alpha) + (g * nalpha))/256; d++;
|
||||
*d = (((int)*d * alpha) + (b * nalpha))/256; d++;
|
||||
d++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
RImage*
|
||||
RMakeTiledImage(RImage *tile, unsigned width, unsigned height)
|
||||
{
|
||||
int x, y;
|
||||
unsigned w;
|
||||
unsigned long tile_size = tile->width * tile->height;
|
||||
unsigned long tx = 0;
|
||||
RImage *image;
|
||||
unsigned char *s, *d;
|
||||
|
||||
if (width == tile->width && height == tile->height)
|
||||
image = RCloneImage(tile);
|
||||
else if (width <= tile->width && height <= tile->height)
|
||||
image = RGetSubImage(tile, 0, 0, width, height);
|
||||
else {
|
||||
int has_alpha = HAS_ALPHA(tile);
|
||||
|
||||
image = RCreateImage(width, height, has_alpha);
|
||||
|
||||
d = image->data;
|
||||
s = tile->data;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < width; x += tile->width) {
|
||||
|
||||
w = (width - x < tile->width) ? width - x : tile->width;
|
||||
|
||||
if (has_alpha) {
|
||||
w *= 4;
|
||||
memcpy(d, s+tx*4, w);
|
||||
} else {
|
||||
w *= 3;
|
||||
memcpy(d, s+tx*3, w);
|
||||
}
|
||||
d += w;
|
||||
}
|
||||
|
||||
tx = (tx + tile->width) % tile_size;
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
|
@ -1,624 +0,0 @@
|
|||
/* scale.c - image scaling
|
||||
*
|
||||
* Raster graphics library
|
||||
*
|
||||
* Copyright (c) 1997-2002 Alfredo K. Kojima
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "x11/wraster.h"
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
* RScaleImage--
|
||||
* Creates a scaled copy of an image.
|
||||
*
|
||||
* Returns:
|
||||
* The new scaled image.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef broken_code
|
||||
RImage*
|
||||
RScaleImage(RImage *image, unsigned new_width, unsigned new_height)
|
||||
{
|
||||
int ox;
|
||||
int px, py;
|
||||
register int x, y, t;
|
||||
int dx, dy;
|
||||
unsigned char *s;
|
||||
unsigned char *d;
|
||||
RImage *img;
|
||||
|
||||
assert(new_width >= 0 && new_height >= 0);
|
||||
|
||||
if (new_width == image->width && new_height == image->height)
|
||||
return RCloneImage(image);
|
||||
|
||||
img = RCreateImage(new_width, new_height, image->format==RRGBAFormat);
|
||||
|
||||
if (!img)
|
||||
return NULL;
|
||||
|
||||
/* fixed point math idea taken from Imlib by
|
||||
* Carsten Haitzler (Rasterman) */
|
||||
dx = (image->width<<16)/new_width;
|
||||
dy = (image->height<<16)/new_height;
|
||||
|
||||
py = 0;
|
||||
|
||||
d = img->data;
|
||||
|
||||
if (image->format == RRGBAFormat) {
|
||||
for (y=0; y<new_height; y++) {
|
||||
t = image->width*(py>>16);
|
||||
|
||||
s = image->data+(t<<2); /* image->data+t*4 */
|
||||
|
||||
ox = 0;
|
||||
px = 0;
|
||||
for (x=0; x<new_width; x++) {
|
||||
px += dx;
|
||||
|
||||
*(d++) = *(s);
|
||||
*(d++) = *(s+1);
|
||||
*(d++) = *(s+2);
|
||||
*(d++) = *(s+3);
|
||||
|
||||
t = (px - ox)>>16;
|
||||
ox += t<<16;
|
||||
|
||||
s += t<<2; /* t*4 */
|
||||
}
|
||||
py += dy;
|
||||
}
|
||||
} else {
|
||||
for (y=0; y<new_height; y++) {
|
||||
t = image->width*(py>>16);
|
||||
|
||||
s = image->data+(t<<1)+t; /* image->data+t*3 */
|
||||
|
||||
ox = 0;
|
||||
px = 0;
|
||||
for (x=0; x<new_width; x++) {
|
||||
px += dx;
|
||||
|
||||
*(d++) = *(s);
|
||||
*(d++) = *(s+1);
|
||||
*(d++) = *(s+2);
|
||||
|
||||
t = (px - ox)>>16;
|
||||
ox += t<<16;
|
||||
|
||||
s += (t<<1)+t; /* t*3 */
|
||||
}
|
||||
py += dy;
|
||||
}
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
#else
|
||||
RImage*
|
||||
RScaleImage(RImage *src, unsigned new_width, unsigned new_height)
|
||||
{
|
||||
int ddy, ee;
|
||||
int h2;
|
||||
int yd;
|
||||
int xd, xs;
|
||||
RImage *dst;
|
||||
int e, xd2;
|
||||
unsigned char *sr, *sg, *sb, *sa;
|
||||
unsigned char *dr, *dg, *db, *da;
|
||||
int ys = 0;
|
||||
|
||||
|
||||
|
||||
dst = RCreateImage(new_width, new_height, src->data[3]!=NULL);
|
||||
|
||||
ddy = src->height/2;
|
||||
ee = (ddy/2) - dst->height;
|
||||
h2 = new_height/2;
|
||||
|
||||
xd = dst->width;
|
||||
xs = src->width/2;
|
||||
e = (src->width/2)-xd;
|
||||
xd2 = xd/2;
|
||||
|
||||
sr = src->data[0];
|
||||
sg = src->data[1];
|
||||
sb = src->data[2];
|
||||
sa = src->data[3];
|
||||
|
||||
dr = dst->data[0];
|
||||
dg = dst->data[1];
|
||||
db = dst->data[2];
|
||||
da = dst->data[3];
|
||||
|
||||
if (sa == NULL) {
|
||||
for (yd = 0; yd < new_height; yd++) {
|
||||
int x;
|
||||
|
||||
sr = src->data[0] + ys * src->width;
|
||||
sg = src->data[1] + ys * src->width;
|
||||
sb = src->data[2] + ys * src->width;
|
||||
|
||||
for (x = 0; x < xd; x++) {
|
||||
*(dr++) = *sr;
|
||||
*(dg++) = *sg;
|
||||
*(db++) = *sb;
|
||||
|
||||
while (e >= 0) {
|
||||
sr++;
|
||||
sg++;
|
||||
sb++;
|
||||
e -= xd2;
|
||||
}
|
||||
e += xs;
|
||||
}
|
||||
while (ee >= 0) {
|
||||
ys++;
|
||||
ee -= h2;
|
||||
}
|
||||
ee += ddy;
|
||||
}
|
||||
} else {
|
||||
for (yd = 0; yd < new_height; yd++) {
|
||||
int x;
|
||||
|
||||
sr = src->data[0] + ys * src->width;
|
||||
sg = src->data[1] + ys * src->width;
|
||||
sb = src->data[2] + ys * src->width;
|
||||
sa = src->data[3] + ys * src->width;
|
||||
|
||||
for (x = 0; x < xd; x++) {
|
||||
*(dr++) = *sr;
|
||||
*(dg++) = *sg;
|
||||
*(db++) = *sb;
|
||||
*(da++) = *sa;
|
||||
|
||||
while (e >= 0) {
|
||||
sr++;
|
||||
sg++;
|
||||
sb++;
|
||||
sa++;
|
||||
e -= xd2;
|
||||
}
|
||||
e += xs;
|
||||
}
|
||||
while (ee >= 0) {
|
||||
ys++;
|
||||
ee -= h2;
|
||||
}
|
||||
ee += ddy;
|
||||
}
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Filtered Image Rescaling code copy/pasted from
|
||||
* Graphics Gems III
|
||||
* Public Domain 1991 by Dale Schumacher
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* filter function definitions
|
||||
*/
|
||||
#if 0
|
||||
#define filter_support (1.0)
|
||||
|
||||
static double
|
||||
filter(t)
|
||||
double t;
|
||||
{
|
||||
/* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */
|
||||
if(t < 0.0) t = -t;
|
||||
if(t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0);
|
||||
return(0.0);
|
||||
}
|
||||
#endif
|
||||
#define box_support (0.5)
|
||||
|
||||
static double
|
||||
box_filter(t)
|
||||
double t;
|
||||
{
|
||||
if((t > -0.5) && (t <= 0.5)) return(1.0);
|
||||
return(0.0);
|
||||
}
|
||||
|
||||
#define triangle_support (1.0)
|
||||
|
||||
static double
|
||||
triangle_filter(t)
|
||||
double t;
|
||||
{
|
||||
if(t < 0.0) t = -t;
|
||||
if(t < 1.0) return(1.0 - t);
|
||||
return(0.0);
|
||||
}
|
||||
|
||||
#define bell_support (1.5)
|
||||
|
||||
static double
|
||||
bell_filter(t) /* box (*) box (*) box */
|
||||
double t;
|
||||
{
|
||||
if(t < 0) t = -t;
|
||||
if(t < .5) return(.75 - (t * t));
|
||||
if(t < 1.5) {
|
||||
t = (t - 1.5);
|
||||
return(.5 * (t * t));
|
||||
}
|
||||
return(0.0);
|
||||
}
|
||||
|
||||
#define B_spline_support (2.0)
|
||||
|
||||
static double
|
||||
B_spline_filter(t) /* box (*) box (*) box (*) box */
|
||||
double t;
|
||||
{
|
||||
double tt;
|
||||
|
||||
if(t < 0) t = -t;
|
||||
if(t < 1) {
|
||||
tt = t * t;
|
||||
return((.5 * tt * t) - tt + (2.0 / 3.0));
|
||||
} else if(t < 2) {
|
||||
t = 2 - t;
|
||||
return((1.0 / 6.0) * (t * t * t));
|
||||
}
|
||||
return(0.0);
|
||||
}
|
||||
|
||||
static double
|
||||
sinc(x)
|
||||
double x;
|
||||
{
|
||||
x *= PI;
|
||||
if(x != 0) return(sin(x) / x);
|
||||
return(1.0);
|
||||
}
|
||||
|
||||
#define Lanczos3_support (3.0)
|
||||
|
||||
static double
|
||||
Lanczos3_filter(t)
|
||||
double t;
|
||||
{
|
||||
if(t < 0) t = -t;
|
||||
if(t < 3.0) return(sinc(t) * sinc(t/3.0));
|
||||
return(0.0);
|
||||
}
|
||||
|
||||
#define Mitchell_support (2.0)
|
||||
|
||||
#define B (1.0 / 3.0)
|
||||
#define C (1.0 / 3.0)
|
||||
|
||||
static double
|
||||
Mitchell_filter(t)
|
||||
double t;
|
||||
{
|
||||
double tt;
|
||||
|
||||
tt = t * t;
|
||||
if(t < 0) t = -t;
|
||||
if(t < 1.0) {
|
||||
t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt))
|
||||
+ ((-18.0 + 12.0 * B + 6.0 * C) * tt)
|
||||
+ (6.0 - 2 * B));
|
||||
return(t / 6.0);
|
||||
} else if(t < 2.0) {
|
||||
t = (((-1.0 * B - 6.0 * C) * (t * tt))
|
||||
+ ((6.0 * B + 30.0 * C) * tt)
|
||||
+ ((-12.0 * B - 48.0 * C) * t)
|
||||
+ (8.0 * B + 24 * C));
|
||||
return(t / 6.0);
|
||||
}
|
||||
return(0.0);
|
||||
}
|
||||
|
||||
static double (*filterf)() = Mitchell_filter;
|
||||
static double fwidth = Mitchell_support;
|
||||
|
||||
void
|
||||
_wraster_change_filter(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case RBoxFilter:
|
||||
filterf = box_filter;
|
||||
fwidth = box_support;
|
||||
break;
|
||||
case RTriangleFilter:
|
||||
filterf = triangle_filter;
|
||||
fwidth = triangle_support;
|
||||
break;
|
||||
case RBellFilter:
|
||||
filterf = bell_filter;
|
||||
fwidth = bell_support;
|
||||
break;
|
||||
case RBSplineFilter:
|
||||
filterf = B_spline_filter;
|
||||
fwidth = B_spline_support;
|
||||
break;
|
||||
case RLanczos3Filter:
|
||||
filterf = Lanczos3_filter;
|
||||
fwidth = Lanczos3_support;
|
||||
break;
|
||||
default:
|
||||
case RMitchellFilter:
|
||||
filterf = Mitchell_filter;
|
||||
fwidth = Mitchell_support;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* image rescaling routine
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int pixel;
|
||||
double weight;
|
||||
} CONTRIB;
|
||||
|
||||
typedef struct {
|
||||
int n; /* number of contributors */
|
||||
CONTRIB *p; /* pointer to list of contributions */
|
||||
} CLIST;
|
||||
|
||||
CLIST *contrib; /* array of contribution lists */
|
||||
|
||||
/* clamp the input to the specified range */
|
||||
#define CLAMP(v,l,h) ((v)<(l) ? (l) : (v) > (h) ? (h) : v)
|
||||
|
||||
|
||||
/* return of calloc is not checked if NULL in the function below! */
|
||||
RImage*
|
||||
RSmoothScaleImage(RImage *src, unsigned new_width, unsigned new_height)
|
||||
{
|
||||
RImage *tmp; /* intermediate image */
|
||||
double xscale, yscale; /* zoom scale factors */
|
||||
int i, j, k; /* loop variables */
|
||||
int n; /* pixel number */
|
||||
double center, left, right; /* filter calculation variables */
|
||||
double width, fscale; /* filter calculation variables */
|
||||
double rweight, gweight, bweight;
|
||||
RImage *dst;
|
||||
unsigned char *p;
|
||||
unsigned char *sp;
|
||||
int sch = src->format == RRGBAFormat ? 4 : 3;
|
||||
|
||||
|
||||
dst = RCreateImage(new_width, new_height, False);
|
||||
|
||||
/* create intermediate image to hold horizontal zoom */
|
||||
tmp = RCreateImage(dst->width, src->height, False);
|
||||
xscale = (double)new_width / (double)src->width;
|
||||
yscale = (double)new_height / (double)src->height;
|
||||
|
||||
/* pre-calculate filter contributions for a row */
|
||||
contrib = (CLIST *)calloc(new_width, sizeof(CLIST));
|
||||
if (xscale < 1.0) {
|
||||
width = fwidth / xscale;
|
||||
fscale = 1.0 / xscale;
|
||||
for (i = 0; i < new_width; ++i) {
|
||||
contrib[i].n = 0;
|
||||
contrib[i].p = (CONTRIB *)calloc((int)(width * 2 + 1),
|
||||
sizeof(CONTRIB));
|
||||
center = (double) i / xscale;
|
||||
left = ceil(center - width);
|
||||
right = floor(center + width);
|
||||
for(j = left; j <= right; ++j) {
|
||||
rweight = center - (double) j;
|
||||
rweight = (*filterf)(rweight / fscale) / fscale;
|
||||
if(j < 0) {
|
||||
n = -j;
|
||||
} else if(j >= src->width) {
|
||||
n = (src->width - j) + src->width - 1;
|
||||
} else {
|
||||
n = j;
|
||||
}
|
||||
k = contrib[i].n++;
|
||||
contrib[i].p[k].pixel = n*sch;
|
||||
contrib[i].p[k].weight = rweight;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
for(i = 0; i < new_width; ++i) {
|
||||
contrib[i].n = 0;
|
||||
contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),
|
||||
sizeof(CONTRIB));
|
||||
center = (double) i / xscale;
|
||||
left = ceil(center - fwidth);
|
||||
right = floor(center + fwidth);
|
||||
for(j = left; j <= right; ++j) {
|
||||
rweight = center - (double) j;
|
||||
rweight = (*filterf)(rweight);
|
||||
if(j < 0) {
|
||||
n = -j;
|
||||
} else if(j >= src->width) {
|
||||
n = (src->width - j) + src->width - 1;
|
||||
} else {
|
||||
n = j;
|
||||
}
|
||||
k = contrib[i].n++;
|
||||
contrib[i].p[k].pixel = n*sch;
|
||||
contrib[i].p[k].weight = rweight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* apply filter to zoom horizontally from src to tmp */
|
||||
p = tmp->data;
|
||||
|
||||
|
||||
for(k = 0; k < tmp->height; ++k) {
|
||||
CONTRIB *pp;
|
||||
|
||||
sp = src->data + src->width*k*sch;
|
||||
|
||||
for(i = 0; i < tmp->width; ++i) {
|
||||
rweight = gweight = bweight = 0.0;
|
||||
|
||||
pp = contrib[i].p;
|
||||
|
||||
for(j = 0; j < contrib[i].n; ++j) {
|
||||
rweight += sp[pp[j].pixel] * pp[j].weight;
|
||||
gweight += sp[pp[j].pixel+1] * pp[j].weight;
|
||||
bweight += sp[pp[j].pixel+2] * pp[j].weight;
|
||||
}
|
||||
*p++ = CLAMP(rweight, 0, 255);
|
||||
*p++ = CLAMP(gweight, 0, 255);
|
||||
*p++ = CLAMP(bweight, 0, 255);
|
||||
}
|
||||
}
|
||||
|
||||
/* free the memory allocated for horizontal filter weights */
|
||||
for(i = 0; i < tmp->width; ++i) {
|
||||
free(contrib[i].p);
|
||||
}
|
||||
free(contrib);
|
||||
|
||||
/* pre-calculate filter contributions for a column */
|
||||
contrib = (CLIST *)calloc(dst->height, sizeof(CLIST));
|
||||
if(yscale < 1.0) {
|
||||
width = fwidth / yscale;
|
||||
fscale = 1.0 / yscale;
|
||||
for(i = 0; i < dst->height; ++i) {
|
||||
contrib[i].n = 0;
|
||||
contrib[i].p = (CONTRIB *)calloc((int) (width * 2 + 1),
|
||||
sizeof(CONTRIB));
|
||||
center = (double) i / yscale;
|
||||
left = ceil(center - width);
|
||||
right = floor(center + width);
|
||||
for(j = left; j <= right; ++j) {
|
||||
rweight = center - (double) j;
|
||||
rweight = (*filterf)(rweight / fscale) / fscale;
|
||||
if(j < 0) {
|
||||
n = -j;
|
||||
} else if(j >= tmp->height) {
|
||||
n = (tmp->height - j) + tmp->height - 1;
|
||||
} else {
|
||||
n = j;
|
||||
}
|
||||
k = contrib[i].n++;
|
||||
contrib[i].p[k].pixel = n*3;
|
||||
contrib[i].p[k].weight = rweight;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < dst->height; ++i) {
|
||||
contrib[i].n = 0;
|
||||
contrib[i].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1),
|
||||
sizeof(CONTRIB));
|
||||
center = (double) i / yscale;
|
||||
left = ceil(center - fwidth);
|
||||
right = floor(center + fwidth);
|
||||
for(j = left; j <= right; ++j) {
|
||||
rweight = center - (double) j;
|
||||
rweight = (*filterf)(rweight);
|
||||
if(j < 0) {
|
||||
n = -j;
|
||||
} else if(j >= tmp->height) {
|
||||
n = (tmp->height - j) + tmp->height - 1;
|
||||
} else {
|
||||
n = j;
|
||||
}
|
||||
k = contrib[i].n++;
|
||||
contrib[i].p[k].pixel = n*3;
|
||||
contrib[i].p[k].weight = rweight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* apply filter to zoom vertically from tmp to dst */
|
||||
sp = malloc(tmp->height*3);
|
||||
|
||||
for(k = 0; k < new_width; ++k) {
|
||||
CONTRIB *pp;
|
||||
|
||||
p = dst->data + k*3;
|
||||
|
||||
/* copy a column into a row */
|
||||
{
|
||||
int i;
|
||||
unsigned char *p, *d;
|
||||
|
||||
d = sp;
|
||||
for(i = tmp->height, p = tmp->data + k*3; i-- > 0;
|
||||
p += tmp->width*3) {
|
||||
*d++ = *p;
|
||||
*d++ = *(p+1);
|
||||
*d++ = *(p+2);
|
||||
}
|
||||
}
|
||||
for(i = 0; i < new_height; ++i) {
|
||||
rweight = gweight = bweight = 0.0;
|
||||
|
||||
pp = contrib[i].p;
|
||||
|
||||
for(j = 0; j < contrib[i].n; ++j) {
|
||||
rweight += sp[pp[j].pixel] * pp[j].weight;
|
||||
gweight += sp[pp[j].pixel+1] * pp[j].weight;
|
||||
bweight += sp[pp[j].pixel+2] * pp[j].weight;
|
||||
}
|
||||
*p = CLAMP(rweight, 0, 255);
|
||||
*(p+1) = CLAMP(gweight, 0, 255);
|
||||
*(p+2) = CLAMP(bweight, 0, 255);
|
||||
p += new_width*3;
|
||||
}
|
||||
}
|
||||
free(sp);
|
||||
|
||||
/* free the memory allocated for vertical filter weights */
|
||||
for(i = 0; i < dst->height; ++i) {
|
||||
free(contrib[i].p);
|
||||
}
|
||||
free(contrib);
|
||||
|
||||
RReleaseImage(tmp);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Raster graphics library
|
||||
*
|
||||
* Copyright (c) 1997-2002 Alfredo K. Kojima
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef WRASTERP_H_
|
||||
#define WRASTERP_H_
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
#include "x11/wraster.h"
|
||||
|
||||
|
||||
#ifdef HAVE_HERMES
|
||||
|
||||
# include <Hermes/Hermes.h>
|
||||
|
||||
typedef struct RHermesData {
|
||||
HermesHandle palette;
|
||||
HermesHandle converter;
|
||||
} RHermesData;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
|
@ -1,284 +0,0 @@
|
|||
/* xutil.c - utility functions for X
|
||||
*
|
||||
* Raster graphics library
|
||||
*
|
||||
* Copyright (c) 1997-2002 Alfredo K. Kojima
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef XSHM
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#endif /* XSHM */
|
||||
|
||||
#include "x11/wraster.h"
|
||||
|
||||
|
||||
#ifdef XSHM
|
||||
|
||||
static int shmError;
|
||||
|
||||
static int (*oldErrorHandler)();
|
||||
|
||||
static int
|
||||
errorHandler(Display *dpy, XErrorEvent *err)
|
||||
{
|
||||
shmError=1;
|
||||
if(err->error_code!=BadAccess)
|
||||
(*oldErrorHandler)(dpy, err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
RXImage*
|
||||
RCreateXImage(RContext *context, int depth, unsigned width, unsigned height)
|
||||
{
|
||||
RXImage *rximg;
|
||||
Visual *visual = context->visual;
|
||||
|
||||
rximg = malloc(sizeof(RXImage));
|
||||
if (!rximg) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef XSHM
|
||||
rximg->image = XCreateImage(context->dpy, visual, depth,
|
||||
ZPixmap, 0, NULL, width, height, 8, 0);
|
||||
if (!rximg->image) {
|
||||
free(rximg);
|
||||
RErrorCode = RERR_XERROR;
|
||||
return NULL;
|
||||
}
|
||||
rximg->image->data = malloc(rximg->image->bytes_per_line*height);
|
||||
if (!rximg->image->data) {
|
||||
XDestroyImage(rximg->image);
|
||||
free(rximg);
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else /* XSHM */
|
||||
if (!context->attribs->use_shared_memory) {
|
||||
retry_without_shm:
|
||||
|
||||
context->attribs->use_shared_memory = 0;
|
||||
rximg->is_shared = 0;
|
||||
rximg->image = XCreateImage(context->dpy, visual, depth,
|
||||
ZPixmap, 0, NULL, width, height, 8, 0);
|
||||
if (!rximg->image) {
|
||||
free(rximg);
|
||||
RErrorCode = RERR_XERROR;
|
||||
return NULL;
|
||||
}
|
||||
rximg->image->data = malloc(rximg->image->bytes_per_line*height);
|
||||
if (!rximg->image->data) {
|
||||
XDestroyImage(rximg->image);
|
||||
free(rximg);
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
rximg->is_shared = 1;
|
||||
|
||||
rximg->info.readOnly = False;
|
||||
|
||||
rximg->image = XShmCreateImage(context->dpy, visual, depth,
|
||||
ZPixmap, NULL, &rximg->info, width,
|
||||
height);
|
||||
|
||||
rximg->info.shmid = shmget(IPC_PRIVATE,
|
||||
rximg->image->bytes_per_line*height,
|
||||
IPC_CREAT|0777);
|
||||
if (rximg->info.shmid < 0) {
|
||||
context->attribs->use_shared_memory = 0;
|
||||
perror("wrlib: could not allocate shared memory segment");
|
||||
XDestroyImage(rximg->image);
|
||||
goto retry_without_shm;
|
||||
}
|
||||
|
||||
rximg->info.shmaddr = shmat(rximg->info.shmid, 0, 0);
|
||||
if (rximg->info.shmaddr == (void*)-1) {
|
||||
context->attribs->use_shared_memory = 0;
|
||||
if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
|
||||
perror("wrlib: shmctl");
|
||||
perror("wrlib: could not allocate shared memory");
|
||||
XDestroyImage(rximg->image);
|
||||
goto retry_without_shm;
|
||||
}
|
||||
|
||||
shmError = 0;
|
||||
XSync(context->dpy, False);
|
||||
oldErrorHandler = XSetErrorHandler(errorHandler);
|
||||
XShmAttach(context->dpy, &rximg->info);
|
||||
XSync(context->dpy, False);
|
||||
XSetErrorHandler(oldErrorHandler);
|
||||
|
||||
rximg->image->data = rximg->info.shmaddr;
|
||||
/* rximg->image->obdata = &(rximg->info);*/
|
||||
|
||||
if (shmError) {
|
||||
context->attribs->use_shared_memory = 0;
|
||||
XDestroyImage(rximg->image);
|
||||
if (shmdt(rximg->info.shmaddr) < 0)
|
||||
perror("wrlib: shmdt");
|
||||
if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
|
||||
perror("wrlib: shmctl");
|
||||
/* printf("wrlib:error attaching shared memory segment to XImage\n");
|
||||
*/
|
||||
goto retry_without_shm;
|
||||
}
|
||||
}
|
||||
#endif /* XSHM */
|
||||
|
||||
return rximg;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RDestroyXImage(RContext *context, RXImage *rximage)
|
||||
{
|
||||
#ifndef XSHM
|
||||
XDestroyImage(rximage->image);
|
||||
#else /* XSHM */
|
||||
if (rximage->is_shared) {
|
||||
XSync(context->dpy, False);
|
||||
XShmDetach(context->dpy, &rximage->info);
|
||||
XDestroyImage(rximage->image);
|
||||
if (shmdt(rximage->info.shmaddr) < 0)
|
||||
perror("wrlib: shmdt");
|
||||
if (shmctl(rximage->info.shmid, IPC_RMID, 0) < 0)
|
||||
perror("wrlib: shmctl");
|
||||
} else {
|
||||
XDestroyImage(rximage->image);
|
||||
}
|
||||
#endif
|
||||
free(rximage);
|
||||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
getDepth(Display *dpy, Drawable d)
|
||||
{
|
||||
Window w;
|
||||
int foo;
|
||||
unsigned bar;
|
||||
unsigned depth;
|
||||
|
||||
XGetGeometry(dpy, d, &w, &foo, &foo, &bar, &bar, &bar, &depth);
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
|
||||
|
||||
RXImage*
|
||||
RGetXImage(RContext *context, Drawable d, int x, int y,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
RXImage *ximg = NULL;
|
||||
|
||||
#ifdef XSHM
|
||||
if (context->attribs->use_shared_memory && 0) {
|
||||
ximg = RCreateXImage(context, getDepth(context->dpy, d),
|
||||
width, height);
|
||||
|
||||
if (ximg && !ximg->is_shared) {
|
||||
RDestroyXImage(context, ximg);
|
||||
ximg = NULL;
|
||||
}
|
||||
if (ximg) {
|
||||
XShmGetImage(context->dpy, d, ximg->image, x, y, AllPlanes);
|
||||
}
|
||||
}
|
||||
if (!ximg) {
|
||||
ximg = malloc(sizeof(RXImage));
|
||||
if (!ximg) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
ximg->is_shared = 0;
|
||||
ximg->image = XGetImage(context->dpy, d, x, y, width, height,
|
||||
AllPlanes, ZPixmap);
|
||||
}
|
||||
return ximg;
|
||||
#else /* !XSHM */
|
||||
ximg = malloc(sizeof(RXImage));
|
||||
if (!ximg) {
|
||||
RErrorCode = RERR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ximg->image = XGetImage(context->dpy, d, x, y, width, height,
|
||||
AllPlanes, ZPixmap);
|
||||
|
||||
return ximg;
|
||||
#endif /* !XSHM */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RPutXImage(RContext *context, Drawable d, GC gc, RXImage *ximage, int src_x,
|
||||
int src_y, int dest_x, int dest_y,
|
||||
unsigned int width, unsigned int height)
|
||||
{
|
||||
#ifndef XSHM
|
||||
XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x,
|
||||
dest_y, width, height);
|
||||
#else
|
||||
if (ximage->is_shared) {
|
||||
XShmPutImage(context->dpy, d, gc, ximage->image, src_x, src_y,
|
||||
dest_x, dest_y, width, height, False);
|
||||
} else {
|
||||
XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x,
|
||||
dest_y, width, height);
|
||||
}
|
||||
XFlush(context->dpy);
|
||||
#endif /* XSHM */
|
||||
}
|
||||
|
||||
|
||||
#ifdef XSHM
|
||||
Pixmap
|
||||
R_CreateXImageMappedPixmap(RContext *context, RXImage *rximage)
|
||||
{
|
||||
Pixmap pix;
|
||||
|
||||
pix = XShmCreatePixmap(context->dpy, context->drawable,
|
||||
rximage->image->data, &rximage->info,
|
||||
rximage->image->width, rximage->image->height,
|
||||
rximage->image->depth);
|
||||
|
||||
return pix;
|
||||
}
|
||||
|
||||
#endif /* XSHM */
|
||||
|
Loading…
Reference in a new issue