Add XIM Input Method, UPdate to wraster 0.80.2

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@17286 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
fedor 2003-07-22 04:28:43 +00:00
parent 123b8ffd38
commit eb1cd51d37
14 changed files with 1097 additions and 278 deletions

View file

@ -1,3 +1,23 @@
2003-07-21 Adam Fedor <fedor@gnu.org>
* Documentation/Back/DefaultsSummary.gsdoc: Add new
GSXIMInputMethodStyle deafult (Adam Fedor).
* Source/x11/context.c, StdCmp.c, convert.c, raster.c, scale.c:
Updated to 0.80.2 version
2003-07-13 Kazunobu Kuriyama <kazunobu.kuriyama@nifty.com>
* Header/x11/XGInputServer.h: Add the new category InputMethod.
* Header/x11/XGServer.h: Add the new category InputMethod.
* Source/x11/XIMInputServer.m:
([XIMInputServer (XIMPrivate) -ximStyleInit]): Cover the input
method styles RootWindow, OffTheSpot, OverTheSpot, and OnTheSpot.
([XIMInputServer (XIMPrivate) -ximCreateIC:]): Implement OffTheSpot
and OverTheSpot. Implement the category InputMethod.
* Source/x11/XGServer.m: Implement the category InputMethod. Add
overriding methods to NSTextView (NSView (InputMethod)).
2003-07-27 Richard Frith-Macdonald <rfm@gnu.org>
* Tools/gpbs.m: Use protocols

View file

@ -83,6 +83,14 @@
problem with the X-Server.
</p>
</desc>
<term>GSXIMInputMethodStyle</term>
<desc>
<p> A string value used to specify the XIM input method for
entering characters. Valid values are
<code>RootWindow</code>, <code>OffTheSpot</code>, or
<code>OverTheSpot</code>.
</p>
</desc>
<term>GraphicCompositing</term>
<desc>
<p> [Xlib backend only]
@ -90,7 +98,7 @@
<code>YES</code>, then the application uses various tricks
to get alpha colors to work when compositing images. This
may slow down drawing of images, but it is generally
recommended anyway, particularly on fast systems
recommended anyway, particularly on fast systems.
</p>
</desc>
<term>Keyboard Modifiers</term>

View file

@ -59,6 +59,22 @@
name: (NSString *)name;
- (void) ximFocusICWindow: (gswindow_device_t *)windev;
- (void) ximCloseIC: (XIC)xic;
@end
// Public interface for the input methods
@interface XIMInputServer (InputMethod)
- (NSString *) inputMethodStyle;
- (NSString *) fontSize: (int *)size;
- (BOOL) clientWindowRect: (NSRect *)rect;
- (BOOL) statusArea: (NSRect *)rect;
- (BOOL) preeditArea: (NSRect *)rect;
- (BOOL) preeditSpot: (NSPoint *)p;
- (BOOL) setStatusArea: (NSRect *)rect;
- (BOOL) setPreeditArea: (NSRect *)rect;
- (BOOL) setPreeditSpot: (NSPoint *)p;
@end // XIMInputServer (InputMethod)
#endif

View file

@ -81,4 +81,19 @@ typedef enum {
- (NSRect) _XFrameToOSFrame: (NSRect)x for: (void*)window;
@end
// Public interface for the input methods.
@interface XGServer (InputMethod)
- (NSString *) inputMethodStyle;
- (NSString *) fontSize: (int *)size;
- (BOOL) clientWindowRect: (NSRect *)rect;
- (BOOL) statusArea: (NSRect *)rect;
- (BOOL) preeditArea: (NSRect *)rect;
- (BOOL) preeditSpot: (NSPoint *)p;
- (BOOL) setStatusArea: (NSRect *)rect;
- (BOOL) setPreeditArea: (NSRect *)rect;
- (BOOL) setPreeditSpot: (NSPoint *)p;
@end
#endif /* _XGServer_h_INCLUDE */

View file

@ -1,7 +1,7 @@
/*
* Raster graphics library
*
* Copyright (c) 1997 ~ 2000 Alfredo K. Kojima
* 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
@ -39,8 +39,8 @@
#define RLRASTER_H_
/* version of the header for the library: 0.20 */
#define WRASTER_HEADER_VERSION 20
/* version of the header for the library: 0.21 */
#define WRASTER_HEADER_VERSION 21
#include <X11/Xlib.h>
@ -148,6 +148,8 @@ typedef struct RContext {
unsigned int use_shared_pixmap:1;
unsigned int optimize_for_speed:1;
} flags;
struct RHermesData *hermes_data; /* handle for Hermes stuff */
} RContext;
@ -189,10 +191,11 @@ enum RImageFormat {
* internal 24bit+alpha image representation
*/
typedef struct RImage {
unsigned char *data; /* image data RGBA or RGB */
unsigned width, height; /* size of the image */
unsigned char *data; /* image data RGBA or RGB */
int width, height; /* size of the image */
enum RImageFormat format;
RColor background; /* background color */
RColor background; /* background color */
int refCount;
} RImage;
@ -320,7 +323,18 @@ RImage *RCreateImageFromDrawable(RContext *context, Drawable drawable,
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);
@ -418,6 +432,10 @@ 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

View file

@ -35,7 +35,7 @@ in this Software without prior written authorization from the X Consortium.
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/Xmu/StdCmap.h>
#include "x11/StdCmap.h"
#define lowbit(x) ((x) & (~(x) + 1))

View file

@ -575,3 +575,187 @@ _parse_display_name(NSString *name, int *dn, int *sn)
@end
@implementation XGServer (InputMethod)
- (NSString *) inputMethodStyle
{
return inputServer ? [(XIMInputServer *)inputServer inputMethodStyle] : nil;
}
- (NSString *) fontSize: (int *)size
{
return inputServer ? [(XIMInputServer *)inputServer fontSize: size] : nil;
}
- (BOOL) clientWindowRect: (NSRect *)rect
{
return inputServer
? [(XIMInputServer *)inputServer clientWindowRect: rect] : NO;
}
- (BOOL) statusArea: (NSRect *)rect
{
return inputServer ? [(XIMInputServer *)inputServer statusArea: rect] : NO;
}
- (BOOL) preeditArea: (NSRect *)rect
{
return inputServer ? [(XIMInputServer *)inputServer preeditArea: rect] : NO;
}
- (BOOL) preeditSpot: (NSPoint *)p
{
return inputServer ? [(XIMInputServer *)inputServer preeditSpot: p] : NO;
}
- (BOOL) setStatusArea: (NSRect *)rect
{
return inputServer
? [(XIMInputServer *)inputServer setStatusArea: rect] : NO;
}
- (BOOL) setPreeditArea: (NSRect *)rect
{
return inputServer
? [(XIMInputServer *)inputServer setPreeditArea: rect] : NO;
}
- (BOOL) setPreeditSpot: (NSPoint *)p
{
return inputServer
? [(XIMInputServer *)inputServer setPreeditSpot: p] : NO;
}
@end // XGServer (InputMethod)
//==== Additional code for NSTextView =========================================
//
// WARNING This section is not genuine part of the XGServer implementation.
// -------
//
// The methods implemented in this section override some of the internal
// methods defined in NSTextView so that the class can support input methods
// (XIM) in cooperation with XGServer.
//
// Note that the orverriding is done by defining the methods in a category,
// the name of which is not explicitly mentioned in NSTextView.h; the
// category is called 'InputMethod'.
//
#include <AppKit/NSClipView.h>
#include <AppKit/NSTextView.h>
@implementation NSTextView (InputMethod)
- (void) _updateInputMethodState
{
NSRect frame;
int font_size;
NSRect status_area;
NSRect preedit_area;
id displayServer = (XGServer *)GSCurrentServer();
if (![displayServer respondsToSelector: @selector(inputMethodStyle)])
return;
if (![displayServer fontSize: &font_size])
return;
if ([[self superview] isKindOfClass: [NSClipView class]])
frame = [[self superview] frame];
else
frame = [self frame];
status_area.size.width = 2 * font_size;
status_area.size.height = font_size + 2;
status_area.origin.x = 0;
status_area.origin.y = frame.size.height - status_area.size.height;
if ([[displayServer inputMethodStyle] isEqual: @"OverTheSpot"])
{
preedit_area.origin.x = 0;
preedit_area.origin.y = 0;
preedit_area.size.width = frame.size.width;
preedit_area.size.height = status_area.size.height;
[displayServer setStatusArea: &status_area];
[displayServer setPreeditArea: &preedit_area];
}
else if ([[displayServer inputMethodStyle] isEqual: @"OffTheSpot"])
{
preedit_area.origin.x = status_area.size.width + 2;
preedit_area.origin.y = status_area.origin.y;
preedit_area.size.width = frame.origin.x + frame.size.width
- preedit_area.origin.x;
preedit_area.size.height = status_area.size.height;
[displayServer setStatusArea: &status_area];
[displayServer setPreeditArea: &preedit_area];
}
else
{
// Do nothing for the RootWindow style.
}
}
- (void) _updateInputMethodWithInsertionPoint: (NSPoint)insertionPoint
{
id displayServer = (XGServer *)GSCurrentServer();
if (![displayServer respondsToSelector: @selector(inputMethodStyle)])
return;
if ([[displayServer inputMethodStyle] isEqual: @"OverTheSpot"])
{
id view;
NSRect frame;
NSPoint p;
NSRect client_win_rect;
NSPoint screenXY_of_frame;
double x_offset;
double y_offset;
int font_size;
NSRect doc_rect;
NSRect doc_visible_rect;
BOOL cond;
float x = insertionPoint.x;
float y = insertionPoint.y;
[displayServer clientWindowRect: &client_win_rect];
[displayServer fontSize: &font_size];
cond = [[self superview] isKindOfClass: [NSClipView class]];
if (cond)
view = [self superview];
else
view = self;
frame = [view frame];
screenXY_of_frame = [[view window] convertBaseToScreen: frame.origin];
// N.B. The window of NSTextView isn't necessarily the same as the input
// method's client window.
x_offset = screenXY_of_frame.x - client_win_rect.origin.x;
y_offset = (client_win_rect.origin.y + client_win_rect.size.height)
- (screenXY_of_frame.y + frame.size.height) + font_size;
x += x_offset;
y += y_offset;
if (cond) // If 'view' is of NSClipView, then
{
// N.B. Remember, (x, y) are the values with respect to NSTextView.
// We need to know the corresponding insertion position with respect
// to NSClipView.
doc_rect = [(NSClipView *)view documentRect];
doc_visible_rect = [view documentVisibleRect];
y -= doc_visible_rect.origin.y - doc_rect.origin.y;
}
p = NSMakePoint(x, y);
[displayServer setPreeditSpot: &p];
}
}
@end // NSTextView
//==== End: Additional Code for NSTextView ====================================

View file

@ -27,6 +27,7 @@
#include "config.h"
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSData.h>
#include <Foundation/NSDebug.h>
#include <Foundation/NSException.h>
@ -37,6 +38,11 @@
#include "x11/XGInputServer.h"
#include <X11/Xlocale.h>
#define RootWindowStyle (XIMPreeditNothing | XIMStatusNothing)
#define OffTheSpotStyle (XIMPreeditArea | XIMStatusArea)
#define OverTheSpotStyle (XIMPreeditPosition | XIMStatusArea)
#define OnTheSpotStyle (XIMPreeditCallbacks| XIMStatusCallbacks)
@interface XIMInputServer (XIMPrivate)
- (BOOL) ximInit: (Display *)dpy;
@ -240,31 +246,59 @@
- (int) ximStyleInit
{
/* FIXME: Right now we only support this style *but*
this is only temporary */
XIMStyle xim_supported_style=XIMPreeditNothing|XIMStatusNothing;
XIMStyles *styles;
char *failed_arg;
int i;
NSUserDefaults *uds;
NSString *request;
XIMStyle xim_requested_style;
XIMStyles *styles;
char *failed_arg;
int i;
uds = [NSUserDefaults standardUserDefaults];
if ((request = [uds stringForKey: @"GSXIMInputMethodStyle"]) == nil)
{
xim_requested_style = RootWindowStyle;
}
else if ([request isEqual: @"RootWindow"])
{
xim_requested_style = RootWindowStyle;
}
else if ([request isEqual: @"OffTheSpot"])
{
xim_requested_style = OffTheSpotStyle;
}
else if ([request isEqual: @"OverTheSpot"])
{
xim_requested_style = OverTheSpotStyle;
}
else if ([request isEqual: @"OnTheSpot"])
{
xim_requested_style = OnTheSpotStyle;
}
else
{
NSLog(@"XIM: Unknown style '%s'.\n"
@"Fallback to RootWindow style.", [request cString]);
xim_requested_style = RootWindowStyle;
}
failed_arg = XGetIMValues(xim,XNQueryInputStyle,&styles,NULL);
if (failed_arg!=NULL)
failed_arg = XGetIMValues(xim, XNQueryInputStyle, &styles, NULL);
if (failed_arg != NULL)
{
NSDebugLLog(@"XIM", @"Can't getting the following IM value :%s",
failed_arg);
return 0;
}
for (i=0;i<styles->count_styles;i++)
for (i = 0; i < styles->count_styles; i++)
{
if (styles->supported_styles[i]==xim_supported_style)
if (styles->supported_styles[i] == xim_requested_style)
{
xim_style=xim_supported_style;
xim_style = xim_requested_style;
XFree(styles);
return 1;
}
}
NSLog(@"XIM: '%s' is not supported", request);
XFree(styles);
return 0;
}
@ -315,10 +349,111 @@
- (XIC) ximCreateIC: (Window)w
{
XIC xic;
xic = XCreateIC(xim, XNClientWindow, w, XNInputStyle,
xim_style, NULL);
if (xic==NULL)
XIC xic = NULL;
if (xim_style == RootWindowStyle)
{
xic = XCreateIC(xim,
XNInputStyle, xim_style,
XNClientWindow, w,
NULL);
}
else if (xim_style == OffTheSpotStyle || xim_style == OverTheSpotStyle)
{
Display *dpy = [XGServer currentXDisplay];
XFontSet font_set;
char **missing_charset;
int num_missing_charset;
int dummy = 0;
XVaNestedList preedit_args = NULL;
XVaNestedList status_args = NULL;
XRectangle status_area;
XRectangle preedit_area;
XPoint preedit_spot;
NSString *ns_font_size;
int font_size;
char base_font_name[64];
//
// Create a FontSet
//
// N.B. Because some input methods fail to provide a default font set,
// we have to do it by ourselves.
ns_font_size = [self fontSize: &font_size];
sprintf(base_font_name, "*medium-r-normal--%s*", [ns_font_size cString]);
font_set = XCreateFontSet(dpy,
base_font_name,
&missing_charset,
&num_missing_charset,
NULL);
if (!font_set)
{
goto finish;
}
if (missing_charset)
{
int i;
NSLog(@"XIM: missing charset: ");
for (i = 0; i < num_missing_charset; ++i)
NSLog(@"%s", missing_charset[i]);
XFreeStringList(missing_charset);
}
//
// Create XIC.
//
// At least, XNFontSet and XNPreeditSpotLocation must be specified
// at initialization time.
//
status_area.width = font_size * 2;
status_area.height = font_size + 2;
status_area.x = 0;
status_area.y = 0;
status_args = XVaCreateNestedList(dummy,
XNArea, &status_area,
XNFontSet, font_set,
NULL);
preedit_area.width = 120;
preedit_area.height = status_area.height;
preedit_area.x = 0;
preedit_area.y = 0;
preedit_spot.x = 0;
preedit_spot.y = 0;
preedit_args = XVaCreateNestedList(dummy,
XNArea, &preedit_area,
XNSpotLocation, &preedit_spot,
XNFontSet, font_set,
NULL);
xic = XCreateIC(xim,
XNInputStyle, xim_style,
XNClientWindow, w,
XNPreeditAttributes, preedit_args,
XNStatusAttributes, status_args,
NULL);
if (preedit_args) { XFree(preedit_args); preedit_args = NULL; }
if (status_args) { XFree(status_args); status_args = NULL; }
if (font_set) XFreeFontSet(dpy, font_set);
}
else if (xim_style == OnTheSpotStyle)
{
NSLog(@"XIM: GNUstep doesn't support 'OnTheSpot'.\n"
@"Fallback to RootWindow style.");
xim_style = RootWindowStyle;
xic = XCreateIC(xim,
XNInputStyle, xim_style,
XNClientWindow, w,
NULL);
}
finish:
if (xic == NULL)
NSDebugLLog(@"XIM", @"Can't create the input context.\n");
xics = realloc(xics, sizeof(XIC) * (num_xics + 1));
@ -356,3 +491,218 @@
}
@end
@implementation XIMInputServer (InputMethod)
- (NSString *) inputMethodStyle
{
if (num_xics > 0)
{
if (xim_style == RootWindowStyle)
return @"RootWindow";
else if (xim_style == OffTheSpotStyle)
return @"OffTheSpot";
else if (xim_style == OverTheSpotStyle)
return @"OverTheSpot";
else if (xim_style == OnTheSpotStyle)
return @"OnTheSpot";
}
return nil;
}
- (NSString *) fontSize: (int *)size
{
NSString *str;
str = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSFontSize"];
if (!str)
str = @"12";
*size = (int)strtol([str cString], NULL, 10);
return str;
}
- (BOOL) clientWindowRect: (NSRect *)rect
{
Window win;
Window dummy;
Display *dpy;
int abs_x, abs_y;
int x, y;
unsigned int w, h;
unsigned int bw, d;
if (num_xics <= 0 || !rect) return NO;
*rect = NSMakeRect(0, 0, 0, 0);
if (XGetICValues(xics[num_xics - 1], XNClientWindow, &win, NULL))
return NO;
dpy = [XGServer currentXDisplay];
if (XTranslateCoordinates(dpy, win, DefaultRootWindow(dpy), 0, 0,
&abs_x, &abs_y, &dummy) == 0)
return NO;
XGetGeometry(dpy, win, &dummy, &x, &y, &w, &h, &bw, &d);
// X Window Coordinates to GNUstep Coordinates
x = abs_x;
y = XDisplayHeight(dpy, 0) - (abs_y + h);
*rect = NSMakeRect((float)x, (float)y, (float)w, (float)h);
return YES;
}
- (BOOL) statusArea: (NSRect *)rect
{
if (num_xics > 0 && (xim_style & XIMStatusArea))
{
XRectangle area;
int dummy = 0;
XVaNestedList arglist = NULL;
if (!(arglist = XVaCreateNestedList(dummy, XNArea, &area, NULL)))
{
return NO;
}
XGetICValues(xics[num_xics - 1], XNStatusAttributes, arglist, NULL);
rect->origin.x = area.x;
rect->origin.y = area.y;
rect->size.width = area.width;
rect->size.height = area.height;
if (arglist) { XFree(arglist); arglist = NULL; }
return YES;
}
return NO;
}
- (BOOL) preeditArea: (NSRect *)rect
{
if (num_xics > 0
&& ((xim_style & XIMPreeditArea) || (xim_style & XIMPreeditPosition)))
{
XRectangle area;
int dummy = 0;
XVaNestedList arglist = NULL;
if (!(arglist = XVaCreateNestedList(dummy, XNArea, &area, NULL)))
{
return NO;
}
XGetICValues(xics[num_xics - 1], XNPreeditAttributes, arglist, NULL);
rect->origin.x = area.x;
rect->origin.y = area.y;
rect->size.width = area.width;
rect->size.height = area.height;
if (arglist) { XFree(arglist); arglist = NULL; }
return YES;
}
return NO;
}
- (BOOL) preeditSpot: (NSPoint *)p
{
if (num_xics > 0 && (xim_style & XIMPreeditPosition))
{
XPoint spot;
int dummy = 0;
XVaNestedList arglist = NULL;
if (!(arglist = XVaCreateNestedList(dummy, XNSpotLocation, &spot, NULL)))
{
return NO;
}
XGetICValues(xics[num_xics - 1], XNPreeditAttributes, arglist, NULL);
p->x = spot.x;
p->y = spot.y;
if (arglist) { XFree(arglist); arglist = NULL; }
return YES;
}
return NO;
}
- (BOOL) setStatusArea: (NSRect *)rect
{
if (num_xics > 0 && (xim_style & XIMStatusArea))
{
XRectangle area;
int dummy = 0;
XVaNestedList arglist = NULL;
area.x = rect->origin.x;
area.y = rect->origin.y;
area.width = rect->size.width;
area.height = rect->size.height;
if (!(arglist = XVaCreateNestedList(dummy, XNArea, &area, NULL)))
{
return NO;
}
XSetICValues(xics[num_xics - 1], XNStatusAttributes, arglist, NULL);
if (arglist) { XFree(arglist); arglist = NULL; }
return YES;
}
return NO;
}
- (BOOL) setPreeditArea: (NSRect *)rect
{
if (num_xics > 0
&& ((xim_style & XIMPreeditArea) || (xim_style & XIMPreeditPosition)))
{
XRectangle area;
int dummy = 0;
XVaNestedList arglist = NULL;
area.x = rect->origin.x;
area.y = rect->origin.y;
area.width = rect->size.width;
area.height = rect->size.height;
if (!(arglist = XVaCreateNestedList(dummy, XNArea, &area, NULL)))
{
return NO;
}
XSetICValues(xics[num_xics - 1], XNPreeditAttributes, arglist, NULL);
if (arglist) { XFree(arglist); arglist = NULL; }
return YES;
}
return NO;
}
- (BOOL) setPreeditSpot: (NSPoint *)p
{
if (num_xics > 0 && (xim_style & XIMPreeditPosition))
{
XPoint spot;
int dummy = 0;
XVaNestedList arglist = NULL;
spot.x = p->x;
spot.y = p->y;
if (!(arglist = XVaCreateNestedList(dummy, XNSpotLocation, &spot, NULL)))
{
return NO;
}
XSetICValues(xics[num_xics - 1], XNPreeditAttributes, arglist, NULL);
if (arglist) { XFree(arglist); arglist = NULL; }
return YES;
}
return NO;
}
@end // XIMInputServer (InputMethod)

View file

@ -2,7 +2,7 @@
*
* Raster graphics library
*
* Copyright (c) 1997, 1998, 1999 Alfredo K. Kojima
* 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
@ -32,9 +32,17 @@
#include <math.h>
#include "x11/wraster.h"
#include "wrasterP.h"
#ifdef HAVE_HERMES
#include <Hermes/Hermes.h>
#endif
#include "x11/StdCmap.h"
#include "x11/wraster.h"
extern void _wraster_change_filter(int type);
@ -53,7 +61,13 @@ static RContextAttributes DEFAULT_CONTEXT_ATTRIBS = {
RUseStdColormap
};
char**
RSupportedFileFormats(void)
{
static char *tmp[2];
tmp[0] = NULL;
return tmp;
}
/*
*
@ -558,7 +572,6 @@ getColormap(RContext *context, int screen_number)
&cmaps, &ncmaps, XA_RGB_DEFAULT_MAP)) {
for (i=0; i<ncmaps; ++i) {
if (cmaps[i].visualid == context->visual->visualid) {
puts("ACHOU");
cmap = cmaps[i].colormap;
break;
}
@ -632,6 +645,11 @@ RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs)
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
@ -694,17 +712,66 @@ RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs)
context->copy_gc = XCreateGC(dpy, context->drawable, GCFunction
|GCGraphicsExposures, &gcv);
if (context->vclass == PseudoColor || context->vclass == StaticColor) {
#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);
@ -714,6 +781,10 @@ RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs)
if (context->depth >= 24)
context->attribs->render_mode = RBestMatchRendering;
}
#ifdef HAVE_HERMES
#endif
/* check avaiability of MIT-SHM */
#ifdef XSHM

View file

@ -2,7 +2,7 @@
*
* Raster graphics library
*
* Copyright (c) 1997-2000 Alfredo K. Kojima
* 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
@ -18,6 +18,12 @@
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Problems:
* 1. Using Grayscale visual with Dithering crashes wmaker
* 2. Ghost dock/appicon is wrong in Pseudocolor, Staticgray, Grayscale
*/
#include <config.h>
@ -29,11 +35,12 @@
#include <assert.h>
#ifdef BENCH
#include "bench.h"
#endif
#include "x11/wraster.h"
#include "wrasterP.h"
#ifdef XSHM
extern Pixmap R_CreateXImageMappedPixmap(RContext *context, RXImage *ximage);
@ -41,39 +48,7 @@ extern Pixmap R_CreateXImageMappedPixmap(RContext *context, RXImage *ximage);
#endif
#ifdef ASM_X86
extern void x86_PseudoColor_32_to_8(unsigned char *image,
unsigned char *ximage,
char *err, char *nerr,
short *ctable,
int dr, int dg, int db,
unsigned long *pixels,
int cpc,
int width, int height,
int bytesPerPixel,
int line_offset);
#endif /* ASM_X86 */
#ifdef ASM_X86_MMX
extern int x86_check_mmx();
extern void x86_mmx_TrueColor_32_to_16(unsigned char *image,
unsigned short *ximage,
short *err, short *nerr,
short *rtable, short *gtable,
short *btable,
int dr, int dg, int db,
unsigned int roffs,
unsigned int goffs,
unsigned int boffs,
int width, int height,
int line_offset);
#endif /* ASM_X86_MMX */
#define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
typedef struct RConversionTable {
@ -164,7 +139,7 @@ computeStdTable(unsigned int mult, unsigned int max)
static void
convertTrueColor_generic(RXImage *ximg, RImage *image,
char *err, char *nerr,
signed char *err, signed char *nerr,
const short *rtable,
const short *gtable,
const short *btable,
@ -173,13 +148,13 @@ convertTrueColor_generic(RXImage *ximg, RImage *image,
const unsigned short goffs,
const unsigned short boffs)
{
char *terr;
signed char *terr;
int x, y, r, g, b;
int pixel;
int rer, ger, ber;
unsigned char *ptr = image->data;
int channels = image->format == RRGBAFormat ? 4 : 3;
int channels = (image->format == RRGBAFormat ? 4 : 3);
/* convert and dither the image to XImage */
for (y=0; y<image->height; y++) {
nerr[0] = 0;
@ -234,6 +209,57 @@ convertTrueColor_generic(RXImage *ximg, RImage *image,
err = nerr;
nerr = terr;
}
/* redither the 1st line to distribute error better */
ptr=image->data;
y=0;
nerr[0] = 0;
nerr[1] = 0;
nerr[2] = 0;
for (x=0; x<image->width; x++, ptr+=channels) {
/* reduce pixel */
pixel = *ptr + err[x];
if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
r = rtable[pixel];
/* calc error */
rer = pixel - r*dr;
/* reduce pixel */
pixel = *(ptr+1) + err[x+1];
if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
g = gtable[pixel];
/* calc error */
ger = pixel - g*dg;
/* reduce pixel */
pixel = *(ptr+2) + err[x+2];
if (pixel<0) pixel=0; else if (pixel>0xff) pixel=0xff;
b = btable[pixel];
/* calc error */
ber = pixel - b*db;
pixel = (r<<roffs) | (g<<goffs) | (b<<boffs);
XPutPixel(ximg->image, x, y, pixel);
/* distribute error */
r = (rer*3)/8;
g = (ger*3)/8;
b = (ber*3)/8;
/* x+1, y */
err[x+3*1]+=r;
err[x+1+3*1]+=g;
err[x+2+3*1]+=b;
/* x, y+1 */
nerr[x]+=r;
nerr[x+1]+=g;
nerr[x+2]+=b;
/* x+1, y+1 */
nerr[x+3*1]=rer-2*r;
nerr[x+1+3*1]=ger-2*g;
nerr[x+2+3*1]=ber-2*b;
}
}
@ -283,64 +309,42 @@ image2TrueColor(RContext *ctx, RImage *image)
unsigned char *ptr = image->data;
/* fake match */
#ifdef DEBUG
#ifdef WR_DEBUG
puts("true color match");
#endif
for (y=0, ofs=0; y < image->height; y++) {
for (x=0; x < image->width; x++, ofs+=channels-3) {
/* reduce pixel */
r = rtable[ptr[ofs++]];
g = gtable[ptr[ofs++]];
b = btable[ptr[ofs++]];
pixel = (r<<roffs) | (g<<goffs) | (b<<boffs);
XPutPixel(ximg->image, x, y, pixel);
}
}
if (rmask==0xff && gmask==0xff && bmask==0xff) {
for (y=0; y < image->height; y++) {
for (x=0; x < image->width; x++, ptr+=channels) {
/* reduce pixel */
pixel = (*(ptr)<<roffs) | (*(ptr+1)<<goffs) | (*(ptr+2)<<boffs);
XPutPixel(ximg->image, x, y, pixel);
}
}
} else {
for (y=0, ofs=0; y < image->height; y++) {
for (x=0; x < image->width; x++, ofs+=channels-3) {
/* reduce pixel */
r = rtable[ptr[ofs++]];
g = gtable[ptr[ofs++]];
b = btable[ptr[ofs++]];
pixel = (r<<roffs) | (g<<goffs) | (b<<boffs);
XPutPixel(ximg->image, x, y, pixel);
}
}
}
} else {
/* dither */
const int dr=0xff/rmask;
const int dg=0xff/gmask;
const int db=0xff/bmask;
#ifdef DEBUG
#ifdef WR_DEBUG
puts("true color dither");
#endif
#ifdef ASM_X86_MMX
if (ctx->depth == 16 && image->format == RRGBAFormat
&& x86_check_mmx()) {
short *err;
short *nerr;
err = malloc(8*(image->width+3));
nerr = malloc(8*(image->width+3));
if (!err || !nerr) {
if (nerr)
free(nerr);
RErrorCode = RERR_NOMEMORY;
RDestroyXImage(ctx, ximg);
return NULL;
}
memset(err, 0, 8*(image->width+3));
memset(nerr, 0, 8*(image->width+3));
x86_mmx_TrueColor_32_to_16(image->data,
(unsigned short*)ximg->image->data,
err+8, nerr+8,
rtable, gtable, btable,
dr, dg, db,
roffs, goffs, boffs,
image->width, image->height,
ximg->image->bytes_per_line - 2*image->width);
free(err);
free(nerr);
} else
#endif /* ASM_X86_MMX */
#endif
{
char *err;
char *nerr;
int ch = image->format == RRGBAFormat ? 4 : 3;
int ch = (image->format == RRGBAFormat ? 4 : 3);
err = malloc(ch*(image->width+2));
nerr = malloc(ch*(image->width+2));
@ -376,7 +380,7 @@ image2TrueColor(RContext *ctx, RImage *image)
static void
convertPseudoColor_to_8(RXImage *ximg, RImage *image,
char *err, char *nerr,
signed char *err, signed char *nerr,
const short *rtable,
const short *gtable,
const short *btable,
@ -384,13 +388,13 @@ convertPseudoColor_to_8(RXImage *ximg, RImage *image,
unsigned long *pixels,
int cpc)
{
char *terr;
signed char *terr;
int x, y, r, g, b;
int pixel;
int rer, ger, ber;
unsigned char *ptr = image->data;
unsigned char *optr = ximg->image->data;
int channels = image->format == RRGBAFormat ? 4 : 3;
int channels = (image->format == RRGBAFormat ? 4 : 3);
int cpcpc = cpc*cpc;
/* convert and dither the image to XImage */
@ -465,7 +469,7 @@ image2PseudoColor(RContext *ctx, RImage *image)
const unsigned short bmask = rmask;
unsigned short *rtable, *gtable, *btable;
const int cpccpc = cpc*cpc;
int channels = image->format == RRGBAFormat ? 4 : 3;
int channels = (image->format == RRGBAFormat ? 4 : 3);
ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
if (!ximg) {
@ -487,11 +491,11 @@ image2PseudoColor(RContext *ctx, RImage *image)
if (ctx->attribs->render_mode == RBestMatchRendering) {
/* fake match */
#ifdef DEBUG
#ifdef WR_DEBUG
printf("pseudo color match with %d colors per channel\n", cpc);
#endif
for (y=0; y<image->height; y++) {
for (x=0; x<image->width; x++, ptr+=channels-1) {
for (x=0; x<image->width; x++, ptr+=channels-3) {
/* reduce pixel */
r = rtable[*ptr++];
g = gtable[*ptr++];
@ -510,7 +514,7 @@ image2PseudoColor(RContext *ctx, RImage *image)
const int db=0xff/bmask;
#ifdef DEBUG
#ifdef WR_DEBUG
printf("pseudo color dithering with %d colors per channel\n", cpc);
#endif
err = malloc(4*(image->width+3));
@ -525,19 +529,9 @@ image2PseudoColor(RContext *ctx, RImage *image)
memset(err, 0, 4*(image->width+3));
memset(nerr, 0, 4*(image->width+3));
#ifdef ASM_X86
x86_PseudoColor_32_to_8(image->data, ximg->image->data,
err+4, nerr+4,
rtable,
dr, dg, db, ctx->pixels, cpc,
image->width, image->height,
channels,
ximg->image->bytes_per_line - image->width);
#else
convertPseudoColor_to_8(ximg, image, err+4, nerr+4,
rtable, gtable, btable,
dr, dg, db, ctx->pixels, cpc);
#endif
free(err);
free(nerr);
@ -560,8 +554,8 @@ image2StandardPseudoColor(RContext *ctx, RImage *image)
unsigned char *data;
unsigned int *rtable, *gtable, *btable;
unsigned int base_pixel = ctx->std_rgb_map->base_pixel;
int channels = image->format == RRGBAFormat ? 4 : 3;
/*register unsigned char maxrgb = 0xff;*/
int channels = (image->format == RRGBAFormat ? 4 : 3);
ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
if (!ximg) {
@ -591,24 +585,29 @@ image2StandardPseudoColor(RContext *ctx, RImage *image)
if (ctx->attribs->render_mode == RBestMatchRendering) {
for (y=0; y<image->height; y++) {
for (x=0; x<image->width; x++, ptr+=channels-3) {
for (x=0; x<image->width; x++, ptr+=channels) {
/* reduce pixel */
pixel = (rtable[*ptr++] + gtable[*ptr++]
+ btable[*ptr++] + base_pixel) & 0xffffffff;
pixel = (rtable[*ptr] + gtable[*(ptr+1)]
+ btable[*(ptr+2)] + base_pixel) & 0xffffffff;
XPutPixel(ximg->image, x, y, pixel);
}
}
} else {
/* dither */
short *err, *nerr;
short *terr;
signed short *err, *nerr;
signed short *terr;
int rer, ger, ber;
int x1, ofs;
#ifdef WR_DEBUG
printf("pseudo color dithering with %d colors per channel\n", channels);
#endif
err = (short*)malloc(3*(image->width+2)*sizeof(short));
nerr = (short*)malloc(3*(image->width+2)*sizeof(short));
if (!err || !nerr) {
if (err)
free(err);
if (nerr)
free(nerr);
RErrorCode = RERR_NOMEMORY;
@ -620,7 +619,7 @@ image2StandardPseudoColor(RContext *ctx, RImage *image)
err[x++] = ptr[x1++];
err[x++] = ptr[x1++];
}
err[x++] = err[x++] = err[x++] = 0;
err[x] = err[x+1] = err[x+2] = 0;
/* convert and dither the image to XImage */
for (y=0, ofs=0; y<image->height; y++) {
if (y<image->height-1) {
@ -703,9 +702,8 @@ image2GrayScale(RContext *ctx, RImage *image)
unsigned short gmask;
unsigned short *table;
unsigned char *data;
int channels = image->format == RRGBAFormat ? 4 : 3;
int channels = (image->format == RRGBAFormat ? 4 : 3);
/*register unsigned char maxrgb = 0xff;*/
ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
if (!ximg) {
@ -731,14 +729,14 @@ image2GrayScale(RContext *ctx, RImage *image)
if (ctx->attribs->render_mode == RBestMatchRendering) {
/* fake match */
#ifdef DEBUG
#ifdef WR_DEBUG
printf("grayscale match with %d colors per channel\n", cpc);
#endif
for (y=0; y<image->height; y++) {
for (x=0; x<image->width; x++) {
/* reduce pixel */
g = table[(*ptr++ * 30 + *ptr++ * 59 + *ptr++ * 11)/100];
g = table[(*ptr * 30 + *(ptr+1) * 59 + *(ptr+2) * 11)/100];
ptr += channels;
/*data[ofs] = ctx->colors[g].pixel;*/
XPutPixel(ximg->image, x, y, ctx->colors[g].pixel);
}
@ -751,7 +749,7 @@ image2GrayScale(RContext *ctx, RImage *image)
int ger;
const int dg=0xff/gmask;
#ifdef DEBUG
#ifdef WR_DEBUG
printf("grayscale dither with %d colors per channel\n", cpc);
#endif
gerr = (short*)malloc((image->width+2)*sizeof(short));
@ -763,22 +761,20 @@ image2GrayScale(RContext *ctx, RImage *image)
RDestroyXImage(ctx, ximg);
return NULL;
}
for (x=0; x<image->width; x++) {
gerr[x] = (ptr[x*3]*30 + ptr[x*3+1]*59 + ptr[x*3+2]*11)/100;
for (x=0, y=0; x<image->width; x++, y+=channels) {
gerr[x] = (ptr[y]*30 + ptr[y+1]*59 + ptr[y+2]*11)/100;
}
gerr[x] = 0;
/* convert and dither the image to XImage */
for (y=0; y<image->height; y++) {
if (y<image->height-1) {
int x1;
for (x=0, x1=(y+1)*image->width*3;
x<image->width;
x1+=channels-3) {
ngerr[x] = (ptr[x1++]*30 + ptr[x1++]*59 + ptr[x1++]*11)/100;
for (x=0, x1=(y+1)*image->width*channels; x<image->width; x++, x1+=channels) {
ngerr[x] = (ptr[x1]*30 + ptr[x1+1]*59 + ptr[x1+2]*11)/100;
}
/* last column */
x1-=channels;
ngerr[x] = (ptr[x1++]*30 + ptr[x1++]*59 + ptr[x1++]*11)/100;
ngerr[x] = (ptr[x1]*30 + ptr[x1+1]*59 + ptr[x1+2]*11)/100;
}
for (x=0; x<image->width; x++) {
/* reduce pixel */
@ -838,6 +834,88 @@ image2Bitmap(RContext *ctx, RImage *image, int threshold)
}
#ifdef HAVE_HERMES
static RXImage*
hermesConvert(RContext *context, RImage *image)
{
HermesFormat source;
HermesFormat dest;
RXImage *ximage;
ximage = RCreateXImage(context, context->depth,
image->width, image->height);
if (!ximage) {
return NULL;
}
/* The masks look weird for images with alpha. but they work this way.
* wth does hermes do internally?
*/
source.bits = (HAS_ALPHA(image) ? 32 : 24);
if (ximage->image->byte_order==LSBFirst) {
source.r = 0xff0000;
source.g = 0x00ff00;
source.b = 0x0000ff;
} else {
if (source.bits == 32) {
source.r = 0xff000000;
source.g = 0x00ff0000;
source.b = 0x0000ff00;
} else {
source.r = 0xff0000;
source.g = 0x00ff00;
source.b = 0x0000ff;
}
}
source.a = 0; /* Don't care about alpha */
source.indexed = 0;
source.has_colorkey = 0;
/* This is a hack and certainly looks weird, but it works :P
* it assumes though that green is inbetween red and blue (the mask) */
if (ximage->image->byte_order==LSBFirst) {
dest.r = context->visual->blue_mask;
dest.g = context->visual->green_mask;
dest.b = context->visual->red_mask;
} else {
dest.r = context->visual->red_mask;
dest.g = context->visual->green_mask;
dest.b = context->visual->blue_mask;
}
dest.a = 0;
dest.bits = ximage->image->bits_per_pixel;
if (context->vclass == TrueColor)
dest.indexed = 0;
else
dest.indexed = 1;
dest.has_colorkey = 0;
/*printf("source r=0x%x, g=0x%x, b=0x%x, a=0x%x, b=%d, i=%d, c=%d\n",
source.r, source.g, source.b, source.a,
source.bits, source.indexed, source.has_colorkey);
printf("dest r=0x%x, g=0x%x, b=0x%x, a=0x%x, b=%d, i=%d, c=%d\n",
dest.r, dest.g, dest.b, dest.a,
dest.bits, dest.indexed, dest.has_colorkey);
*/
Hermes_ConverterRequest(context->hermes_data->converter, &source, &dest);
Hermes_ConverterPalette(context->hermes_data->converter,
context->hermes_data->palette, 0);
Hermes_ConverterCopy(context->hermes_data->converter,
image->data, 0, 0, image->width, image->height,
image->width * (image->format == RRGBFormat ? 3 : 4),
ximage->image->data, 0, 0,
image->width, image->height,
ximage->image->bytes_per_line);
return ximage;
}
#endif /* HAVE_HERMES */
int
RConvertImage(RContext *context, RImage *image, Pixmap *pixmap)
@ -851,14 +929,22 @@ RConvertImage(RContext *context, RImage *image, Pixmap *pixmap)
assert(image!=NULL);
assert(pixmap!=NULL);
/* clear error message */
if (context->vclass == TrueColor) {
ximg = image2TrueColor(context, image);
} else if (context->vclass == PseudoColor
|| context->vclass == StaticColor) {
switch (context->vclass) {
case TrueColor:
#ifdef HAVE_HERMES
if (context->attribs->render_mode == RBestMatchRendering) {
ximg = hermesConvert(context, image);
} else {
ximg = image2TrueColor(context, image);
}
#else /* !HAVE_HERMES */
ximg = image2TrueColor(context, image);
#endif
break;
case PseudoColor:
case StaticColor:
/* For StaticColor we can also use hermes, but it doesn't dither */
#ifdef BENCH
cycle_bench(1);
#endif
@ -869,16 +955,19 @@ RConvertImage(RContext *context, RImage *image, Pixmap *pixmap)
#ifdef BENCH
cycle_bench(0);
#endif
} else if (context->vclass == GrayScale || context->vclass == StaticGray) {
break;
case GrayScale:
case StaticGray:
ximg = image2GrayScale(context, image);
break;
}
if (!ximg) {
return False;
}
*pixmap = XCreatePixmap(context->dpy, context->drawable, image->width,
image->height, context->depth);
@ -952,6 +1041,7 @@ RConvertImageMask(RContext *context, RImage *image, Pixmap *pixmap,
RPutXImage(context, *mask, gc, ximg, 0, 0, 0, 0,
image->width, image->height);
RDestroyXImage(context, ximg);
XFreeGC(context->dpy, gc);
return True;
}

View file

@ -2,7 +2,7 @@
*
* Raster graphics library
*
* Copyright (c) 1997-2000 Alfredo K. Kojima
* 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
@ -24,6 +24,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <X11/Xlib.h>
#include "x11/wraster.h"
@ -37,14 +38,26 @@ 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;
unsigned bla1, bla2;
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;
@ -54,11 +67,9 @@ RCreateImage(unsigned width, unsigned height, int alpha)
memset(image, 0, sizeof(RImage));
image->width = width;
image->height = height;
if (alpha) {
image->format = RRGBAFormat;
} else {
image->format = RRGBFormat;
}
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
*/
@ -73,6 +84,44 @@ RCreateImage(unsigned width, unsigned height, int alpha)
}
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)
@ -129,16 +178,6 @@ RGetSubImage(RImage *image, int x, int y, unsigned width, unsigned height)
}
void
RDestroyImage(RImage *image)
{
assert(image!=NULL);
free(image->data);
free(image);
}
/*
*----------------------------------------------------------------------
* RCombineImages-
@ -183,24 +222,18 @@ RCombineImages(RImage *image, RImage *src)
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 = (((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 = (((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++;
}
}
@ -225,53 +258,74 @@ RCombineImagesWithOpaqueness(RImage *image, RImage *src, int opaqueness)
s = src->data;
c_opaqueness = 255 - opaqueness;
#define OP opaqueness
#define COP c_opaqueness
if (!HAS_ALPHA(src)) {
int dalpha = HAS_ALPHA(image);
#define COP c_opaqueness
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++;
*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++;
}
}
#undef COP
} 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++;
*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 = (((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,
int *swidth, int *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,
@ -282,18 +336,8 @@ RCombineArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
unsigned char *s;
int alpha, calpha;
assert(dy < image->height);
assert(dx < image->width);
assert(sy + height <= src->height);
assert(sx + width <= src->width);
if (width > image->width - dx)
width = image->width - dx;
if (height > image->height - dy)
height = image->height - dy;
if(!calculateCombineArea(image, src, &sx, &sy, &width, &height, &dx, &dy))
return;
if (!HAS_ALPHA(src)) {
if (!HAS_ALPHA(image)) {
@ -343,12 +387,9 @@ RCombineArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
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++;
*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++;
@ -367,65 +408,48 @@ RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
{
int x, y, dwi, swi;
int c_opaqueness;
unsigned char *d;
unsigned char *s;
unsigned char *s, *d;
int dalpha = HAS_ALPHA(image);
int dch = (dalpha ? 4 : 3);
assert(dy <= image->height);
assert(dx <= image->width);
if(!calculateCombineArea(image, src, &sx, &sy, &width, &height, &dx, &dy))
return;
assert(sy <= height);
assert(sx <= width);
/* clip */
width -= sx;
height -= sy;
if (height > image->height - dy)
height = image->height - dy;
d = image->data + dy*image->width*dch + dx;
d = image->data + (dy*image->width + dx) * dch;
dwi = (image->width - width)*dch;
c_opaqueness = 255 - opaqueness;
#define OP opaqueness
if (!HAS_ALPHA(src)) {
#define COP c_opaqueness
s = src->data + sy*src->width*3;
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++;
*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;
}
#undef COP
} else {
int tmp;
s = src->data + sy*src->width*4;
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 *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
d++; s++;
*d = (((int)*d *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
d++; s++;
*d = (((int)*d *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
d++; s++;
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++;
@ -434,6 +458,7 @@ RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
}
}
#undef OP
#undef COP
}
@ -460,12 +485,9 @@ RCombineImageWithColor(RImage *image, RColor *color)
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 = (((int)*d * alpha) + (r * nalpha))/256; d++;
*d = (((int)*d * alpha) + (g * nalpha))/256; d++;
*d = (((int)*d * alpha) + (b * nalpha))/256; d++;
d++;
}
}

View file

@ -2,7 +2,7 @@
*
* Raster graphics library
*
* Copyright (c) 1997, 1988, 1999 Alfredo K. Kojima
* 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
@ -29,7 +29,7 @@
#include <math.h>
#ifndef PI
#define PI 3.141592
#define PI 3.14159265358979323846
#endif
#include <assert.h>
@ -412,6 +412,7 @@ CLIST *contrib; /* array of contribution lists */
#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)
{
@ -616,7 +617,7 @@ RSmoothScaleImage(RImage *src, unsigned new_width, unsigned new_height)
}
free(contrib);
RDestroyImage(tmp);
RReleaseImage(tmp);
return dst;
}

24
Source/x11/wrasterP.h Normal file
View file

@ -0,0 +1,24 @@
#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

View file

@ -2,7 +2,7 @@
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
* 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
@ -120,7 +120,7 @@ RCreateXImage(RContext *context, int depth, unsigned width, unsigned height)
IPC_CREAT|0777);
if (rximg->info.shmid < 0) {
context->attribs->use_shared_memory = 0;
perror("wrlib:could not allocate shared memory segment");
perror("wrlib: could not allocate shared memory segment");
XDestroyImage(rximg->image);
goto retry_without_shm;
}
@ -129,8 +129,8 @@ RCreateXImage(RContext *context, int depth, unsigned width, unsigned height)
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");
perror("wrlib: shmctl");
perror("wrlib: could not allocate shared memory");
XDestroyImage(rximg->image);
goto retry_without_shm;
}
@ -149,9 +149,9 @@ RCreateXImage(RContext *context, int depth, unsigned width, unsigned height)
context->attribs->use_shared_memory = 0;
XDestroyImage(rximg->image);
if (shmdt(rximg->info.shmaddr) < 0)
perror("wrlib:shmdt");
perror("wrlib: shmdt");
if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
perror("wrlib:shmctl");
perror("wrlib: shmctl");
/* printf("wrlib:error attaching shared memory segment to XImage\n");
*/
goto retry_without_shm;
@ -174,9 +174,9 @@ RDestroyXImage(RContext *context, RXImage *rximage)
XShmDetach(context->dpy, &rximage->info);
XDestroyImage(rximage->image);
if (shmdt(rximage->info.shmaddr) < 0)
perror("wrlib:shmdt");
perror("wrlib: shmdt");
if (shmctl(rximage->info.shmid, IPC_RMID, 0) < 0)
perror("wrlib:shmctl");
perror("wrlib: shmctl");
} else {
XDestroyImage(rximage->image);
}