Brought art backend closer to the GNUstep coding style.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@24923 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2007-03-22 16:54:47 +00:00
parent 3ab2c8bd91
commit 680ea7befd
8 changed files with 1250 additions and 1288 deletions

View file

@ -1,3 +1,13 @@
2007-03-22 Fred Kiefer <FredKiefer@gmx.de>
* Source/art/ARTGState.h: Declare internal methods.
* Source/art/ARTGState.m: New file split out from ARTContext.m.
* Source/art/ARTConext.m: Removed ARTContext bits.
* Source/art/blit-main.m: New file split out from blit.m.
* Source/art/blit.m: Removed self include stuff.
* Source/GNUmakefile: Add new source files.
* Source/art/composite.m: Adopt to GNUstep coding style.
2007-03-22 Fred Kiefer <FredKiefer@gmx.de>
* Source/cairo/CairoGState.m (-compositeGState:...fraction:):

View file

@ -20,717 +20,23 @@
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <math.h>
#include <AppKit/NSAffineTransform.h>
#include <AppKit/NSBezierPath.h>
#include <AppKit/NSColor.h>
#include <Foundation/NSDebug.h>
#include "ARTGState.h"
#include "blit.h"
#include "ftfont.h"
#ifndef RDS
#include "x11/XWindowBuffer.h"
#endif
#include "blit.h"
#include "ftfont.h"
#include <libart_lgpl/libart.h>
#ifndef PI
#define PI 3.14159265358979323846264338327950288
#endif
/*
** subclassResponsibility **
Note that these aren't actually subclassResponsibility anymore; instead
of crashing, they just print a warning.
- (void) dissolveGState: (GSGState *)source
fromRect: (NSRect)aRect
toPoint: (NSPoint)aPoint
delta: (float)delta
** Other unimplemented stuff **
FontInfo:
-(void) set
Context:
- (NSColor *) NSReadPixel: (NSPoint) location
*/
/* Portions based on gnustep-back code, eg.: */
/* GSGState - Generic graphic state
Copyright (C) 1998 Free Software Foundation, Inc.
Written by: Adam Fedor <fedor@gnu.org>
Date: Mar 2002
This file is part of the GNU Objective C User Interface Library.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
*/
draw_info_t ART_DI;
@implementation ARTGState
/* TODO:
optimize all this. passing device_color_t structures around by value is
very expensive
*/
-(void) setColor: (device_color_t *)color state: (color_state_t)cState
{
device_color_t c;
unsigned char r,g,b;
[super setColor: color state: cState];
if (cState&(COLOR_FILL|COLOR_STROKE))
{
c=fillColor;
gsColorToRGB(&c); /* TODO: check this */
if (c.field[0]>1.0) c.field[0]=1.0;
if (c.field[0]<0.0) c.field[0]=0.0;
r=c.field[0]*255;
if (c.field[1]>1.0) c.field[1]=1.0;
if (c.field[1]<0.0) c.field[1]=0.0;
g=c.field[1]*255;
if (c.field[2]>1.0) c.field[2]=1.0;
if (c.field[2]<0.0) c.field[2]=0.0;
b=c.field[2]*255;
if (cState&COLOR_FILL)
{
fill_color[0]=r;
fill_color[1]=g;
fill_color[2]=b;
fill_color[3]=fillColor.field[AINDEX]*255;
}
if (cState&COLOR_STROKE)
{
stroke_color[0]=r;
stroke_color[1]=g;
stroke_color[2]=b;
stroke_color[3]=strokeColor.field[AINDEX]*255;
}
}
}
/* specially optimized versions (since these are common and simple) */
-(void) DPSsetgray: (float)gray
{
if (gray < 0.0) gray = 0.0;
if (gray > 1.0) gray = 1.0;
fillColor.space = strokeColor.space = gray_colorspace;
fillColor.field[0] = strokeColor.field[0] = gray;
cstate = COLOR_FILL | COLOR_STROKE;
stroke_color[0] = stroke_color[1] = stroke_color[2] =
fill_color[0] = fill_color[1] = fill_color[2] = gray * 255;
}
-(void) DPSsetalpha: (float)a
{
if (a < 0.0) a = 0.0;
if (a > 1.0) a = 1.0;
fillColor.field[AINDEX] = strokeColor.field[AINDEX] = a;
stroke_color[3] = fill_color[3] = a * 255;
}
- (void) DPSsetrgbcolor: (float)r : (float)g : (float)b
{
if (r < 0.0) r = 0.0; if (r > 1.0) r = 1.0;
if (g < 0.0) g = 0.0; if (g > 1.0) g = 1.0;
if (b < 0.0) b = 0.0; if (b > 1.0) b = 1.0;
fillColor.space = strokeColor.space = rgb_colorspace;
fillColor.field[0] = strokeColor.field[0] = r;
fillColor.field[1] = strokeColor.field[1] = g;
fillColor.field[2] = strokeColor.field[2] = b;
cstate = COLOR_FILL | COLOR_STROKE;
stroke_color[0] = fill_color[0] = r * 255;
stroke_color[1] = fill_color[1] = g * 255;
stroke_color[2] = fill_color[2] = b * 255;
}
/* ----------------------------------------------------------------------- */
/* Text operations */
/* ----------------------------------------------------------------------- */
- (void) DPSashow: (float)ax : (float)ay : (const char*)s
{ /* adds (x,y) in user space to each glyph's x/y advancement */
NSPoint p;
int x, y;
float numarray[2];
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
numarray[0] = ax; numarray[1] = ay;
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
deltas: numarray : 1 : 4
widthChar: 0
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPSawidthshow: (float)cx : (float)cy : (int)c : (float)ax : (float)ay
: (const char*)s
{ /* adds (ax,ay) in user space to every glyph's advancement and (cx,cy)
to character c's x/y advancement */
NSPoint p;
int x, y;
float numarray[4];
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
numarray[0] = ax; numarray[1] = ay;
numarray[2] = cx; numarray[3] = cy;
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
deltas: numarray : 1 : 12
widthChar: c
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPScharpath: (const char*)s : (int)b
{ /* TODO: handle b? will freetype ever give us a stroke-only font? */
NSPoint p;
if ([path isEmpty]) return;
p=[self currentPoint];
[(id<FTFontInfo>)font
outlineString: s
at: p.x:p.y
gstate: self];
[self DPSclosepath];
}
- (void) DPSshow: (const char*)s
{
NSPoint p;
int x, y;
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
deltas: NULL : 0 : 0
widthChar: 0
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPSwidthshow: (float)cx : (float)cy : (int)c : (const char*)s
{ /* adds (x,y) in user space to character c's x/y advancement */
NSPoint p;
int x, y;
float numarray[2];
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
numarray[0] = cx; numarray[1] = cy;
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
deltas: numarray : 1 : 8
widthChar: c
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPSxshow: (const char*)s : (const float*)numarray : (int)size
{
NSPoint p;
int x, y;
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
deltas: numarray : size : 1
widthChar: 0
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPSxyshow: (const char*)s : (const float*)numarray : (int)size
{
NSPoint p;
int x, y;
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
deltas: numarray : size : 3
widthChar: 0
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPSyshow: (const char*)s : (const float*)numarray : (int)size
{
NSPoint p;
int x, y;
if (!wi || !wi->data) return;
if (all_clipped)
return;
if (!path || [path isEmpty]) return;
p = [path currentPoint];
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
deltas: numarray : size : 2
widthChar: 0
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) GSShowGlyphs: (const NSGlyph *)glyphs : (size_t) length
{
NSPoint p;
int x, y;
if (!wi || !wi->data) return;
if (all_clipped)
return;
if (!path || [path isEmpty]) return;
p = [path currentPoint];
x = p.x - offset.x;
y = offset.y - p.y;
if (wi->has_alpha)
{
[(id<FTFontInfo>)font
drawGlyphs: glyphs : length
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
alpha: wi->alpha + clip_x0 + clip_y0 * wi->sx : wi->sx
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
drawinfo: &DI];
}
else
{
[(id<FTFontInfo>)font
drawGlyphs: glyphs : length
at: x:y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
drawinfo: &DI];
}
UPDATE_UNBUFFERED
}
/* ----------------------------------------------------------------------- */
/* Gstate operations */
/* ----------------------------------------------------------------------- */
- (void) DPSinitgraphics
{
[super DPSinitgraphics];
line_width=1.0;
linecapstyle=ART_PATH_STROKE_CAP_BUTT;
linejoinstyle=ART_PATH_STROKE_JOIN_MITER;
miter_limit=10.0;
if (dash.n_dash)
{
free(dash.dash);
dash.dash=NULL;
dash.n_dash=0;
do_dash=0;
}
}
- (void) DPScurrentlinecap: (int*)linecap
{
switch (linecapstyle)
{
default:
case ART_PATH_STROKE_CAP_BUTT:
*linecap=NSButtLineCapStyle;
break;
case ART_PATH_STROKE_CAP_ROUND:
*linecap=NSRoundLineCapStyle;
break;
case ART_PATH_STROKE_CAP_SQUARE:
*linecap=NSSquareLineCapStyle;
break;
}
}
- (void) DPScurrentlinejoin: (int*)linejoin
{
switch (linejoinstyle)
{
default:
case ART_PATH_STROKE_JOIN_MITER:
*linejoin=NSMiterLineJoinStyle;
break;
case ART_PATH_STROKE_JOIN_ROUND:
*linejoin=NSRoundLineJoinStyle;
break;
case ART_PATH_STROKE_JOIN_BEVEL:
*linejoin=NSBevelLineJoinStyle;
break;
}
}
- (void) DPScurrentlinewidth: (float*)width
{
*width=line_width;
}
- (void) DPScurrentmiterlimit: (float*)limit
{
*limit=miter_limit;
}
- (void) DPSsetdash: (const float*)pat : (int)size : (float)offs
{
int i;
if (dash.n_dash)
{
free(dash.dash);
dash.dash=NULL;
dash.n_dash=0;
do_dash=0;
}
if (size>0)
{
dash.offset=offs;
dash.n_dash=size;
dash.dash=malloc(sizeof(double)*size);
if (!dash.dash)
{
/* Revert to no dash. Better than crashing. */
dash.n_dash=0;
dash.offset=0;
do_dash=0;
}
else
{
for (i=0;i<size;i++)
dash.dash[i]=pat[i];
do_dash=1;
}
}
}
- (void) DPSsetlinecap: (int)linecap
{
switch (linecap)
{
default:
case NSButtLineCapStyle:
linecapstyle=ART_PATH_STROKE_CAP_BUTT;
break;
case NSRoundLineCapStyle:
linecapstyle=ART_PATH_STROKE_CAP_ROUND;
break;
case NSSquareLineCapStyle:
linecapstyle=ART_PATH_STROKE_CAP_SQUARE;
break;
}
}
- (void) DPSsetlinejoin: (int)linejoin
{
switch (linejoin)
{
default:
case NSMiterLineJoinStyle:
linejoinstyle=ART_PATH_STROKE_JOIN_MITER;
break;
case NSRoundLineJoinStyle:
linejoinstyle=ART_PATH_STROKE_JOIN_ROUND;
break;
case NSBevelLineJoinStyle:
linejoinstyle=ART_PATH_STROKE_JOIN_BEVEL;
break;
}
}
- (void) DPSsetlinewidth: (float)width
{
line_width=width;
/* TODO? handle line_width=0 properly */
if (line_width<=0) line_width=1;
}
- (void) DPSsetmiterlimit: (float)limit
{
miter_limit=limit;
}
- (void) DPScurrentstrokeadjust: (int*)b
{
*b = strokeadjust;
}
- (void) DPSsetstrokeadjust: (int)b
{
strokeadjust = b;
}
@end
@interface ARTGState (internal_stuff)
-(void) _setup_stuff: (gswindow_device_t *)win : (int)x : (int)y;
-(void) GSCurrentDevice: (void **)device : (int *)x : (int *)y;
@end
@implementation ARTGState (internal_stuff)
- (void) dealloc
{
if (dash.dash)
free(dash.dash);
if (clip_span)
free(clip_span);
if (clip_index)
free(clip_index);
DESTROY(wi);
[super dealloc];
}
-(id) deepen
{
[super deepen];
if (dash.dash)
{
double *tmp=malloc(sizeof(double)*dash.n_dash);
if (tmp)
{
memcpy(tmp,dash.dash,sizeof(double)*dash.n_dash);
dash.dash=tmp;
}
else
{
dash.dash=NULL;
dash.n_dash=0;
do_dash=0;
}
}
if (clip_span)
{
unsigned int *n;
n=malloc(sizeof(unsigned int)*clip_num_span);
if (n)
{
memcpy(n,clip_span,sizeof(unsigned int)*clip_num_span);
clip_span=n;
n=malloc(sizeof(unsigned int *)*(clip_sy+1));
if (n)
{
memcpy(n,clip_index,sizeof(unsigned int *)*(clip_sy+1));
clip_index = n;
}
else
{
free(clip_span);
clip_span=clip_index=NULL;
clip_num_span=0;
}
}
else
{
clip_span=clip_index=NULL;
clip_num_span=0;
}
}
wi=RETAIN(wi);
return self;
}
-(void) _setup_stuff: (gswindow_device_t *)window : (int)x : (int)y
{
struct XWindowBuffer_depth_info_s di;
XWindowBuffer *new_wi;
[self setOffset: NSMakePoint(x, y)];
#ifndef RDS
di.drawing_depth = DI.drawing_depth;
#endif
di.bytes_per_pixel = DI.bytes_per_pixel;
di.inline_alpha = DI.inline_alpha;
di.inline_alpha_ofs = DI.inline_alpha_ofs;
new_wi=[XWindowBuffer windowBufferForWindow: window depthInfo: &di];
if (new_wi != wi)
{
DESTROY(wi);
wi=new_wi;
}
else
{
DESTROY(new_wi);
}
}
-(void) GSCurrentDevice: (void **)device : (int *)x : (int *)y
{
if (x)
*x = 0;
if (y)
*y = 0;
if (device)
{
if (wi)
*device = wi->window;
else
*device = NULL;
}
}
@end
@implementation ARTContext
+ (void)initializeBackend
{
NSDebugLLog(@"back-art",@"Initializing libart/freetype backend");
[NSGraphicsContext setDefaultContextClass: [ARTContext class]];
[FTFontInfo initializeBackend];
}
// Could use NSSwapInt() instead
static unsigned int flip_bytes(unsigned int i)
{
return ((i>>24)&0xff)
|((i>> 8)&0xff00)
|((i<< 8)&0xff0000)
|((i<<24)&0xff000000);
return ((i >> 24) & 0xff)
|((i >> 8) & 0xff00)
|((i << 8) & 0xff0000)
|((i << 24) & 0xff000000);
}
static int byte_order(void)
@ -744,6 +50,15 @@ static int byte_order(void)
return foo.c != 1;
}
@implementation ARTContext
+ (void)initializeBackend
{
NSDebugLLog(@"back-art",@"Initializing libart/freetype backend");
[NSGraphicsContext setDefaultContextClass: [ARTContext class]];
[FTFontInfo initializeBackend];
}
- (id) initWithContextInfo: (NSDictionary *)info
{
@ -756,22 +71,19 @@ static int byte_order(void)
{
/* Most likely this is a PS or PDF context, so just return what
super gave us
TODO: figure out if this comment still applies
*/
return self;
}
/* Create a default gstate */
gstate = [[ARTGState allocWithZone: [self zone]] initWithDrawContext: self];
[gstate DPSsetalpha: 1.0];
[gstate DPSsetlinewidth: 1.0];
[gstate DPSsetstrokeadjust: 1];
#ifdef RDS
{
RDSServer *s=(RDSServer *)server;
RDSServer *s = (RDSServer *)server;
int bpp;
int red_mask, green_mask, blue_mask;
[s getPixelFormat: &bpp masks: &red_mask : &green_mask : &blue_mask];
artcontext_setup_draw_info(&DI, red_mask, green_mask, blue_mask, bpp);
}
@ -790,12 +102,12 @@ static int byte_order(void)
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(d, VisualClassMask, &template, &numMatches);
template.class = DirectColor;
visualInfo = XGetVisualInfo(d, VisualClassMask, &template, &numMatches);
if (!visualInfo)
{
template.class=TrueColor;
visualInfo=XGetVisualInfo(d, VisualClassMask, &template, &numMatches);
template.class = TrueColor;
visualInfo = XGetVisualInfo(d, VisualClassMask, &template, &numMatches);
}
if (visualInfo)
{
@ -836,42 +148,28 @@ static int byte_order(void)
return self;
}
- (void) flushGraphics
{ /* TODO: _really_ flush? (ie. force updates and wait for shm completion?) */
{
/* TODO: _really_ flush? (ie. force updates and wait for shm completion?) */
#ifndef RDS
XFlush([(XGServer *)server xDisplay]);
XFlush([(XGServer *)server xDisplay]);
#endif
}
+(void) waitAllContexts
{
}
#ifndef RDS
+(void) _gotShmCompletion: (Drawable)d
+ (void) _gotShmCompletion: (Drawable)d
{
[XWindowBuffer _gotShmCompletion: d];
[XWindowBuffer _gotShmCompletion: d];
}
-(void) gotShmCompletion: (Drawable)d
- (void) gotShmCompletion: (Drawable)d
{
[XWindowBuffer _gotShmCompletion: d];
[XWindowBuffer _gotShmCompletion: d];
}
#endif
//
// Read the Color at a Screen Position
//
- (NSColor *) NSReadPixel: (NSPoint) location
{
NSLog(@"ignoring NSReadPixel: (%g %g)",location.x,location.y);
return nil;
}
/* Private backend methods */
+(void) handleExposeRect: (NSRect)rect forDriver: (void *)driver
+ (void) handleExposeRect: (NSRect)rect forDriver: (void *)driver
{
[(XWindowBuffer *)driver _exposeRect: rect];
}
@ -881,12 +179,11 @@ static int byte_order(void)
@implementation ARTContext (ops)
- (void) GSSetDevice: (void*)device : (int)x : (int)y
{
[(ARTGState *)gstate _setup_stuff: device : x : y];
[(ARTGState *)gstate GSSetDevice: device : x : y];
}
-(void) GSCurrentDevice: (void **)device : (int *)x : (int *)y
- (void) GSCurrentDevice: (void **)device : (int *)x : (int *)y
{
[(ARTGState *)gstate GSCurrentDevice: device : x : y];
[(ARTGState *)gstate GSCurrentDevice: device : x : y];
}
@end

View file

@ -91,14 +91,17 @@
@end
@interface ARTGState (internal_stuff)
-(void) GSSetDevice: (gswindow_device_t *)win : (int)x : (int)y;
-(void) GSCurrentDevice: (void **)device : (int *)x : (int *)y;
@end
#define UPDATE_UNBUFFERED \
if (wi->window->type==NSBackingStoreNonretained) \
{ \
[wi _exposeRect: NSMakeRect(clip_x0,clip_y0,clip_sx,clip_sy)]; \
}
extern struct draw_info_s ART_DI;
#define DI ART_DI

659
Source/art/ARTGState.m Normal file
View file

@ -0,0 +1,659 @@
/*
Copyright (C) 2002, 2003, 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 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 <math.h>
#include <AppKit/NSAffineTransform.h>
#include <AppKit/NSBezierPath.h>
#include <AppKit/NSColor.h>
#include "ARTGState.h"
#include "blit.h"
#include "ftfont.h"
#ifndef RDS
#include "x11/XWindowBuffer.h"
#endif
#include <libart_lgpl/libart.h>
draw_info_t ART_DI;
@implementation ARTGState
/* TODO:
optimize all this. passing device_color_t structures around by value is
very expensive
*/
-(void) setColor: (device_color_t *)color state: (color_state_t)cState
{
device_color_t c;
unsigned char r,g,b;
[super setColor: color state: cState];
if (cState&(COLOR_FILL|COLOR_STROKE))
{
c = fillColor;
gsColorToRGB(&c); /* TODO: check this */
if (c.field[0] > 1.0) c.field[0] = 1.0;
if (c.field[0] < 0.0) c.field[0] = 0.0;
r = c.field[0] * 255;
if (c.field[1] > 1.0) c.field[1] = 1.0;
if (c.field[1] < 0.0) c.field[1] = 0.0;
g = c.field[1] * 255;
if (c.field[2] > 1.0) c.field[2] = 1.0;
if (c.field[2] < 0.0) c.field[2] = 0.0;
b = c.field[2] * 255;
if (cState & COLOR_FILL)
{
fill_color[0] = r;
fill_color[1] = g;
fill_color[2] = b;
fill_color[3] = fillColor.field[AINDEX] * 255;
}
if (cState & COLOR_STROKE)
{
stroke_color[0] = r;
stroke_color[1] = g;
stroke_color[2] = b;
stroke_color[3] = strokeColor.field[AINDEX] * 255;
}
}
}
/* specially optimized versions (since these are common and simple) */
-(void) DPSsetgray: (float)gray
{
if (gray < 0.0) gray = 0.0;
if (gray > 1.0) gray = 1.0;
fillColor.space = strokeColor.space = gray_colorspace;
fillColor.field[0] = strokeColor.field[0] = gray;
cstate = COLOR_FILL | COLOR_STROKE;
stroke_color[0] = stroke_color[1] = stroke_color[2] =
fill_color[0] = fill_color[1] = fill_color[2] = gray * 255;
}
-(void) DPSsetalpha: (float)a
{
if (a < 0.0) a = 0.0;
if (a > 1.0) a = 1.0;
fillColor.field[AINDEX] = strokeColor.field[AINDEX] = a;
stroke_color[3] = fill_color[3] = a * 255;
}
- (void) DPSsetrgbcolor: (float)r : (float)g : (float)b
{
if (r < 0.0) r = 0.0; if (r > 1.0) r = 1.0;
if (g < 0.0) g = 0.0; if (g > 1.0) g = 1.0;
if (b < 0.0) b = 0.0; if (b > 1.0) b = 1.0;
fillColor.space = strokeColor.space = rgb_colorspace;
fillColor.field[0] = strokeColor.field[0] = r;
fillColor.field[1] = strokeColor.field[1] = g;
fillColor.field[2] = strokeColor.field[2] = b;
cstate = COLOR_FILL | COLOR_STROKE;
stroke_color[0] = fill_color[0] = r * 255;
stroke_color[1] = fill_color[1] = g * 255;
stroke_color[2] = fill_color[2] = b * 255;
}
/* ----------------------------------------------------------------------- */
/* Text operations */
/* ----------------------------------------------------------------------- */
- (void) DPSashow: (float)ax : (float)ay : (const char*)s
{ /* adds (ax,ay) in user space to each glyph's x/y advancement */
NSPoint p;
int x, y;
float numarray[2];
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
numarray[0] = ax;
numarray[1] = ay;
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x : y
to: clip_x0 : clip_y0 : clip_x1 : clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0] : fill_color[1] : fill_color[2] : fill_color[3]
transform: ctm
deltas: numarray : 1 : 4
widthChar: 0
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPSawidthshow: (float)cx : (float)cy : (int)c : (float)ax : (float)ay
: (const char*)s
{ /* adds (ax,ay) in user space to every glyph's advancement and (cx,cy)
to character c's x/y advancement */
NSPoint p;
int x, y;
float numarray[4];
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
numarray[0] = ax;
numarray[1] = ay;
numarray[2] = cx;
numarray[3] = cy;
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x : y
to: clip_x0 : clip_y0 : clip_x1 : clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0] : fill_color[1] : fill_color[2] : fill_color[3]
transform: ctm
deltas: numarray : 1 : 12
widthChar: c
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPScharpath: (const char*)s : (int)b
{ /* TODO: handle b? will freetype ever give us a stroke-only font? */
NSPoint p;
if ([path isEmpty]) return;
p=[self currentPoint];
[(id<FTFontInfo>)font
outlineString: s
at: p.x : p.y
gstate: self];
[self DPSclosepath];
}
- (void) DPSshow: (const char*)s
{
NSPoint p;
int x, y;
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x : y
to: clip_x0 : clip_y0 : clip_x1 : clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0] : fill_color[1] : fill_color[2] : fill_color[3]
transform: ctm
deltas: NULL : 0 : 0
widthChar: 0
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPSwidthshow: (float)cx : (float)cy : (int)c : (const char*)s
{ /* adds (x,y) in user space to character c's x/y advancement */
NSPoint p;
int x, y;
float numarray[2];
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
numarray[0] = cx; numarray[1] = cy;
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x : y
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
transform: ctm
deltas: numarray : 1 : 8
widthChar: c
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPSxshow: (const char*)s : (const float*)numarray : (int)size
{
NSPoint p;
int x, y;
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x : y
to: clip_x0 : clip_y0 : clip_x1 : clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0] : fill_color[1] : fill_color[2] : fill_color[3]
transform: ctm
deltas: numarray : size : 1
widthChar: 0
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPSxyshow: (const char*)s : (const float*)numarray : (int)size
{
NSPoint p;
int x, y;
if (!wi || !wi->data) return;
if (all_clipped)
return;
if ([path isEmpty]) return;
p = [path currentPoint];
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x : y
to: clip_x0 : clip_y0 : clip_x1 : clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0] : fill_color[1] : fill_color[2] : fill_color[3]
transform: ctm
deltas: numarray : size : 3
widthChar: 0
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) DPSyshow: (const char*)s : (const float*)numarray : (int)size
{
NSPoint p;
int x, y;
if (!wi || !wi->data) return;
if (all_clipped)
return;
if (!path || [path isEmpty]) return;
p = [path currentPoint];
x = p.x - offset.x;
y = offset.y - p.y;
[(id<FTFontInfo>)font
drawString: s
at: x : y
to: clip_x0 : clip_y0 : clip_x1 : clip_y1 : CLIP_DATA : wi->bytes_per_line
: (wi->has_alpha? wi->alpha + clip_x0 + clip_y0 * wi->sx : NULL) : wi->sx
color: fill_color[0] : fill_color[1] : fill_color[2] : fill_color[3]
transform: ctm
deltas: numarray : size : 2
widthChar: 0
drawinfo: &DI];
UPDATE_UNBUFFERED
}
- (void) GSShowGlyphs: (const NSGlyph *)glyphs : (size_t) length
{
NSPoint p;
int x, y;
if (!wi || !wi->data) return;
if (all_clipped)
return;
if (!path || [path isEmpty]) return;
p = [path currentPoint];
x = p.x - offset.x;
y = offset.y - p.y;
if (wi->has_alpha)
{
[(id<FTFontInfo>)font
drawGlyphs: glyphs : length
at: x : y
to: clip_x0 : clip_y0 : clip_x1 : clip_y1 : CLIP_DATA : wi->bytes_per_line
alpha: wi->alpha + clip_x0 + clip_y0 * wi->sx : wi->sx
color: fill_color[0] : fill_color[1] : fill_color[2] : fill_color[3]
transform: ctm
drawinfo: &DI];
}
else
{
[(id<FTFontInfo>)font
drawGlyphs: glyphs : length
at: x : y
to: clip_x0 : clip_y0 : clip_x1 : clip_y1 : CLIP_DATA : wi->bytes_per_line
color: fill_color[0] : fill_color[1] : fill_color[2] : fill_color[3]
transform: ctm
drawinfo: &DI];
}
UPDATE_UNBUFFERED
}
/* ----------------------------------------------------------------------- */
/* Gstate operations */
/* ----------------------------------------------------------------------- */
- (void) DPSinitgraphics
{
[super DPSinitgraphics];
line_width = 1.0;
linecapstyle = ART_PATH_STROKE_CAP_BUTT;
linejoinstyle = ART_PATH_STROKE_JOIN_MITER;
strokeadjust = 1;
miter_limit = 10.0;
[self DPSsetalpha: 1.0];
if (dash.n_dash)
{
free(dash.dash);
dash.dash = NULL;
dash.n_dash = 0;
do_dash = 0;
}
}
- (void) DPScurrentlinecap: (int*)linecap
{
switch (linecapstyle)
{
default:
case ART_PATH_STROKE_CAP_BUTT:
*linecap = NSButtLineCapStyle;
break;
case ART_PATH_STROKE_CAP_ROUND:
*linecap = NSRoundLineCapStyle;
break;
case ART_PATH_STROKE_CAP_SQUARE:
*linecap = NSSquareLineCapStyle;
break;
}
}
- (void) DPScurrentlinejoin: (int*)linejoin
{
switch (linejoinstyle)
{
default:
case ART_PATH_STROKE_JOIN_MITER:
*linejoin = NSMiterLineJoinStyle;
break;
case ART_PATH_STROKE_JOIN_ROUND:
*linejoin = NSRoundLineJoinStyle;
break;
case ART_PATH_STROKE_JOIN_BEVEL:
*linejoin = NSBevelLineJoinStyle;
break;
}
}
- (void) DPScurrentlinewidth: (float*)width
{
*width = line_width;
}
- (void) DPScurrentmiterlimit: (float*)limit
{
*limit = miter_limit;
}
- (void) DPSsetdash: (const float*)pat : (int)size : (float)offs
{
int i;
if (dash.n_dash)
{
free(dash.dash);
dash.dash = NULL;
dash.n_dash = 0;
do_dash = 0;
}
if (size>0)
{
dash.offset = offs;
dash.n_dash = size;
dash.dash = malloc(sizeof(double)*size);
if (!dash.dash)
{
/* Revert to no dash. Better than crashing. */
dash.n_dash = 0;
dash.offset = 0;
do_dash = 0;
}
else
{
for (i = 0; i < size; i++)
dash.dash[i] = pat[i];
do_dash = 1;
}
}
}
- (void) DPSsetlinecap: (int)linecap
{
switch (linecap)
{
default:
case NSButtLineCapStyle:
linecapstyle = ART_PATH_STROKE_CAP_BUTT;
break;
case NSRoundLineCapStyle:
linecapstyle = ART_PATH_STROKE_CAP_ROUND;
break;
case NSSquareLineCapStyle:
linecapstyle = ART_PATH_STROKE_CAP_SQUARE;
break;
}
}
- (void) DPSsetlinejoin: (int)linejoin
{
switch (linejoin)
{
default:
case NSMiterLineJoinStyle:
linejoinstyle = ART_PATH_STROKE_JOIN_MITER;
break;
case NSRoundLineJoinStyle:
linejoinstyle = ART_PATH_STROKE_JOIN_ROUND;
break;
case NSBevelLineJoinStyle:
linejoinstyle = ART_PATH_STROKE_JOIN_BEVEL;
break;
}
}
- (void) DPSsetlinewidth: (float)width
{
line_width = width;
/* TODO? handle line_width=0 properly */
if (line_width <= 0) line_width = 1;
}
- (void) DPSsetmiterlimit: (float)limit
{
miter_limit=limit;
}
- (void) DPScurrentstrokeadjust: (int*)b
{
*b = strokeadjust;
}
- (void) DPSsetstrokeadjust: (int)b
{
strokeadjust = b;
}
@end
@implementation ARTGState (internal_stuff)
- (void) dealloc
{
if (dash.dash)
free(dash.dash);
if (clip_span)
free(clip_span);
if (clip_index)
free(clip_index);
DESTROY(wi);
[super dealloc];
}
-(id) deepen
{
[super deepen];
if (dash.dash)
{
double *tmp = malloc(sizeof(double) * dash.n_dash);
if (tmp)
{
memcpy(tmp, dash.dash, sizeof(double) * dash.n_dash);
dash.dash = tmp;
}
else
{
dash.dash = NULL;
dash.n_dash = 0;
do_dash = 0;
}
}
if (clip_span)
{
unsigned int *n;
n = malloc(sizeof(unsigned int) * clip_num_span);
if (n)
{
memcpy(n, clip_span, sizeof(unsigned int) * clip_num_span);
clip_span = n;
n = malloc(sizeof(unsigned int *) * (clip_sy+1));
if (n)
{
memcpy(n, clip_index, sizeof(unsigned int *) * (clip_sy + 1));
clip_index = n;
}
else
{
free(clip_span);
clip_span=clip_index = NULL;
clip_num_span = 0;
}
}
else
{
clip_span = clip_index = NULL;
clip_num_span = 0;
}
}
wi = RETAIN(wi);
return self;
}
-(void) GSSetDevice: (gswindow_device_t *)window : (int)x : (int)y
{
struct XWindowBuffer_depth_info_s di;
XWindowBuffer *new_wi;
[self setOffset: NSMakePoint(x, y)];
#ifndef RDS
di.drawing_depth = DI.drawing_depth;
#endif
di.bytes_per_pixel = DI.bytes_per_pixel;
di.inline_alpha = DI.inline_alpha;
di.inline_alpha_ofs = DI.inline_alpha_ofs;
new_wi = [XWindowBuffer windowBufferForWindow: window depthInfo: &di];
if (new_wi != wi)
{
DESTROY(wi);
wi = new_wi;
}
else
{
DESTROY(new_wi);
}
}
-(void) GSCurrentDevice: (void **)device : (int *)x : (int *)y
{
NSPoint theOffset = [self offset];
if (x)
*x = theOffset.x;
if (y)
*y = theOffset.y;
if (device)
{
if (wi)
*device = wi->window;
else
*device = NULL;
}
}
@end

View file

@ -35,7 +35,8 @@ SUBPROJECT_NAME=art
# The Objective-C source files to be compiled
art_OBJC_FILES = \
ARTContext.m \
blit.m \
ARTGState.m \
blit-main.m \
ftfont.m \
image.m \
composite.m \

523
Source/art/blit-main.m Normal file
View file

@ -0,0 +1,523 @@
/*
Copyright (C) 2002, 2003, 2004 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 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 <math.h>
#include <string.h>
#include <Foundation/NSDebug.h>
#include "blit.h"
/*
First attempt at gamma correction. Only used in text rendering (blit_*),
but that's where it's needed the most. The gamma adjustment is a large
hack, but the results are good.
*/
static unsigned char gamma_table[256],inv_gamma_table[256];
#define NPRE(r, pre) pre##_##r
#define M2PRE(a, b) NPRE(a, b)
#define MPRE(r) M2PRE(r, FORMAT_INSTANCE)
/*
For each supported pixel format we define a bunch of macros and include
ourself.
*/
/* 24-bit red green blue */
#define FORMAT_INSTANCE rgb
#define FORMAT_HOW DI_24_RGB
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nr=p[0]; ng=p[1]; nb=p[2];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nr=p[0]; ng=p[1]; nb=p[2]; na=pa[0];
#define BLEND_WRITE(p,nr,ng,nb) p[0]=nr; p[1]=ng; p[2]=nb;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=nr; p[1]=ng; p[2]=nb; pa[0]=na;
#define BLEND_INC(p) p+=3;
#define ALPHA_READ(s,sa,d) d=sa[0];
#define ALPHA_INC(s,sa) s+=3; sa++;
#define COPY_TYPE unsigned char
#define COPY_TYPE_PIXEL(a) unsigned char a[3];
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v[0]=r; v[1]=g; v[2]=b;
#define COPY_WRITE(dst,v) dst[0]=v[0]; dst[1]=v[1]; dst[2]=v[2];
#define COPY_INC(dst) dst+=3;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 24-bit blue green red */
#define FORMAT_INSTANCE bgr
#define FORMAT_HOW DI_24_BGR
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nb=p[0]; ng=p[1]; nr=p[2];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nb=p[0]; ng=p[1]; nr=p[2]; na=pa[0];
#define BLEND_WRITE(p,nr,ng,nb) p[0]=nb; p[1]=ng; p[2]=nr;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=nb; p[1]=ng; p[2]=nr; pa[0]=na;
#define BLEND_INC(p) p+=3;
#define ALPHA_READ(s,sa,d) d=sa[0];
#define ALPHA_INC(s,sa) s+=3; sa++;
#define COPY_TYPE unsigned char
#define COPY_TYPE_PIXEL(a) unsigned char a[3];
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v[0]=b; v[1]=g; v[2]=r;
#define COPY_WRITE(dst,v) dst[0]=v[0]; dst[1]=v[1]; dst[2]=v[2];
#define COPY_INC(dst) dst+=3;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 32-bit red green blue alpha */
#define FORMAT_INSTANCE rgba
#define FORMAT_HOW DI_32_RGBA
#define INLINE_ALPHA
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nr=p[0]; ng=p[1]; nb=p[2];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nr=p[0]; ng=p[1]; nb=p[2]; na=p[3];
#define BLEND_WRITE(p,nr,ng,nb) p[0]=nr; p[1]=ng; p[2]=nb;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=nr; p[1]=ng; p[2]=nb; p[3]=na;
#define BLEND_INC(p) p+=4;
#define ALPHA_READ(s,sa,d) d=s[3];
#define ALPHA_INC(s,sa) s+=4;
#define COPY_TYPE unsigned int
#define COPY_TYPE_PIXEL(a) unsigned int a;
#if GS_WORDS_BIGENDIAN
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(r<<24)|(g<<16)|(b<<8);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(r<<24)|(g<<16)|(b<<8)|(a);
#else
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(b<<16)|(g<<8)|(r<<0);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(b<<16)|(g<<8)|(r<<0)|(a<<24);
#endif
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 32-bit blue green red alpha */
#define FORMAT_INSTANCE bgra
#define FORMAT_HOW DI_32_BGRA
#define INLINE_ALPHA
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nb=p[0]; ng=p[1]; nr=p[2];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nb=p[0]; ng=p[1]; nr=p[2]; na=p[3];
#define BLEND_WRITE(p,nr,ng,nb) p[0]=nb; p[1]=ng; p[2]=nr;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=nb; p[1]=ng; p[2]=nr; p[3]=na;
#define BLEND_INC(p) p+=4;
#define ALPHA_READ(s,sa,d) d=s[3];
#define ALPHA_INC(s,sa) s+=4;
#define COPY_TYPE unsigned int
#define COPY_TYPE_PIXEL(a) unsigned int a;
#if GS_WORDS_BIGENDIAN
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(b<<24)|(g<<16)|(r<<8);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(b<<24)|(g<<16)|(r<<8)|(a);
#else
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(r<<16)|(g<<8)|(b<<0);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(r<<16)|(g<<8)|(b<<0)|(a<<24);
#endif
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 32-bit alpha red green blue */
#define FORMAT_INSTANCE argb
#define FORMAT_HOW DI_32_ARGB
#define INLINE_ALPHA
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nr=p[1]; ng=p[2]; nb=p[3];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nr=p[1]; ng=p[2]; nb=p[3]; na=p[0];
#define BLEND_WRITE(p,nr,ng,nb) p[1]=nr; p[2]=ng; p[3]=nb;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[1]=nr; p[2]=ng; p[3]=nb; p[0]=na;
#define BLEND_INC(p) p+=4;
#define ALPHA_READ(s,sa,d) d=s[0];
#define ALPHA_INC(s,sa) s+=4;
#define COPY_TYPE unsigned int
#define COPY_TYPE_PIXEL(a) unsigned int a;
#if GS_WORDS_BIGENDIAN
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(r<<16)|(g<<8)|(b<<0);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(r<<16)|(g<<8)|(b<<0)|(a<<24);
#else
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(b<<24)|(g<<16)|(r<<8);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(b<<24)|(g<<16)|(r<<8)|(a);
#endif
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 32-bit alpha blue green red */
#define FORMAT_INSTANCE abgr
#define FORMAT_HOW DI_32_ABGR
#define INLINE_ALPHA
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nb=p[1]; ng=p[2]; nr=p[3];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nb=p[1]; ng=p[2]; nr=p[3]; na=p[0];
#define BLEND_WRITE(p,nr,ng,nb) p[1]=nb; p[2]=ng; p[3]=nr;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[1]=nb; p[2]=ng; p[3]=nr; p[0]=na;
#define BLEND_INC(p) p+=4;
#define ALPHA_READ(s,sa,d) d=s[0];
#define ALPHA_INC(s,sa) s+=4;
#define COPY_TYPE unsigned int
#define COPY_TYPE_PIXEL(a) unsigned int a;
#if GS_WORDS_BIGENDIAN
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(b<<16)|(g<<8)|(r<<0);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(b<<16)|(g<<8)|(r<<0)|(a<<24);
#else
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(r<<24)|(g<<16)|(b<<8);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(r<<24)|(g<<16)|(b<<8)|(a);
#endif
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 16-bit 5 bits blue, 6 bits green, 5 bits red */
#define FORMAT_INSTANCE b5g6r5
#define FORMAT_HOW DI_16_B5_G6_R5
#define BLEND_TYPE unsigned short
#define BLEND_READ(p,nr,ng,nb) \
{ \
unsigned short _s=p[0]; \
nr=(_s>>11)<<3; \
ng=((_s>>5)<<2)&0xff; \
nb=(_s<<3)&0xff; \
}
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) \
{ \
unsigned short _s=p[0]; \
nr=(_s>>11)<<3; \
ng=((_s>>5)<<2)&0xff; \
nb=(_s<<3)&0xff; \
na=pa[0]; \
}
#define BLEND_WRITE(p,nr,ng,nb) p[0]=((nr>>3)<<11)|((ng>>2)<<5)|(nb>>3);
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=((nr>>3)<<11)|((ng>>2)<<5)|(nb>>3); pa[0]=na;
#define BLEND_INC(p) p++;
#define ALPHA_READ(s,sa,d) d=sa[0];
#define ALPHA_INC(s,sa) s++; sa++;
#define COPY_TYPE unsigned short
#define COPY_TYPE_PIXEL(a) unsigned short a;
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=((r>>3)<<11)|((g>>2)<<5)|(b>>3);
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 16-bit 5 bits blue, 5 bits green, 5 bits red */
#define FORMAT_INSTANCE b5g5r5a1
#define FORMAT_HOW DI_16_B5_G5_R5_A1
#define BLEND_TYPE unsigned short
#define BLEND_READ(p,nr,ng,nb) \
{ \
unsigned short _s=p[0]; \
nr=(_s>>10)<<3; \
ng=((_s>>5)<<3)&0xff; \
nb=(_s<<3)&0xff; \
}
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) \
{ \
unsigned short _s=p[0]; \
nr=(_s>>10)<<3; \
ng=((_s>>5)<<3)&0xff; \
nb=(_s<<3)&0xff; \
na=pa[0]; \
}
#define BLEND_WRITE(p,nr,ng,nb) p[0]=((nr>>3)<<10)+((ng>>3)<<5)+(nb>>3);
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=((nr>>3)<<10)+((ng>>3)<<5)+(nb>>3); pa[0]=na;
#define BLEND_INC(p) p++;
#define ALPHA_READ(s,sa,d) d=sa[0];
#define ALPHA_INC(s,sa) s++; sa++;
#define COPY_TYPE unsigned short
#define COPY_TYPE_PIXEL(a) unsigned short a;
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=((r>>3)<<10)|((g>>3)<<5)|(b>>3);
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* end of pixel formats */
static draw_info_t draw_infos[DI_NUM] = {
#define C(x) \
NPRE(run_alpha,x), \
NPRE(run_opaque,x), \
NPRE(run_alpha_a,x), \
NPRE(run_opaque_a,x), \
NPRE(blit_alpha_opaque,x), \
NPRE(blit_mono_opaque,x), \
NPRE(blit_alpha,x), \
NPRE(blit_mono,x), \
NPRE(blit_alpha_a,x), \
NPRE(blit_mono_a,x), \
\
NPRE(blit_subpixel,x), \
\
NPRE(read_pixels_o,x), \
NPRE(read_pixels_a,x), \
\
NPRE(sover_aa,x), \
NPRE(sover_ao,x), \
NPRE(sin_aa,x), \
NPRE(sin_oa,x), \
NPRE(sout_aa,x), \
NPRE(sout_oa,x), \
NPRE(satop_aa,x), \
NPRE(dover_aa,x), \
NPRE(dover_oa,x), \
NPRE(din_aa,x), \
NPRE(dout_aa,x), \
NPRE(datop_aa,x), \
NPRE(xor_aa,x), \
NPRE(plusl_aa,x), \
NPRE(plusl_oa,x), \
NPRE(plusl_ao_oo,x), \
NPRE(plusl_ao_oo,x), \
NPRE(plusd_aa,x), \
NPRE(plusd_oa,x), \
NPRE(plusd_ao_oo,x), \
NPRE(plusd_ao_oo,x), \
NPRE(dissolve_aa,x), \
NPRE(dissolve_oa,x), \
NPRE(dissolve_ao,x), \
NPRE(dissolve_oo,x),
/* TODO: try to implement fallback versions? possible? */
{DI_FALLBACK ,0, 0,0,-1,/*C(fallback)*/},
{DI_16_B5_G5_R5_A1 ,2,15,0,-1,C(b5g5r5a1)},
{DI_16_B5_G6_R5 ,2,16,0,-1,C(b5g6r5)},
{DI_24_RGB ,3,24,0,-1,C(rgb)},
{DI_24_BGR ,3,24,0,-1,C(bgr)},
/* ARTContext.m assumes that only 32-bit modes have inline alpha. this
might eventually need to be fixed */
{DI_32_RGBA ,4,24,1, 3,C(rgba)},
{DI_32_BGRA ,4,24,1, 3,C(bgra)},
{DI_32_ARGB ,4,24,1, 0,C(argb)},
{DI_32_ABGR ,4,24,1, 0,C(abgr)},
};
static int byte_ofs_of_mask(unsigned int m)
{
union
{
unsigned char b[4];
unsigned int m;
} tmp;
tmp.m = m;
if (tmp.b[0] == 0xff && !tmp.b[1] && !tmp.b[2] && !tmp.b[3])
return 0;
else if (tmp.b[1] == 0xff && !tmp.b[0] && !tmp.b[2] && !tmp.b[3])
return 1;
else if (tmp.b[2] == 0xff && !tmp.b[0] && !tmp.b[1] && !tmp.b[3])
return 2;
else if (tmp.b[3] == 0xff && !tmp.b[0] && !tmp.b[1] && !tmp.b[2])
return 3;
else
return -1;
}
#include <Foundation/NSUserDefaults.h>
void artcontext_setup_draw_info(draw_info_t *di,
unsigned int red_mask, unsigned int green_mask, unsigned int blue_mask,
int bpp)
{
int t = DI_FALLBACK;
NSDebugLLog(@"back-art", @"%s masks=(%08x %08x %08x) bpp=%i",
__PRETTY_FUNCTION__, red_mask, green_mask, blue_mask, bpp);
if (bpp == 16 && red_mask == 0xf800 && green_mask == 0x7e0 &&
blue_mask == 0x1f)
{
t = DI_16_B5_G6_R5;
}
else if (bpp == 16 && red_mask == 0x7c00 && green_mask == 0x3e0 &&
blue_mask == 0x1f)
{
t = DI_16_B5_G5_R5_A1;
}
else if (bpp == 24 || bpp == 32)
{
int r, g, b;
r = byte_ofs_of_mask(red_mask);
g = byte_ofs_of_mask(green_mask);
b = byte_ofs_of_mask(blue_mask);
if (bpp == 24)
{
if (r == 0 && g == 1 && b == 2)
t = DI_24_RGB;
else if (r == 2 && g == 1 && b == 0)
t = DI_24_BGR;
}
else if (bpp == 32)
{
if (r == 0 && g == 1 && b == 2)
t = DI_32_RGBA;
else if (r == 2 && g == 1 && b == 0)
t = DI_32_BGRA;
else if (r == 1 && g == 2 && b == 3)
t = DI_32_ARGB;
else if (r == 3 && g == 2 && b == 1)
t = DI_32_ABGR;
}
}
NSDebugLLog(@"back-art", @"got t=%i", t);
*di = draw_infos[t];
if (!di->render_run_alpha)
*di = draw_infos[DI_FALLBACK];
if (di->how == DI_FALLBACK)
{
NSLog(@"gnustep-back(art): Unrecognized color masks: %08x:%08x:%08x %i",
red_mask, green_mask, blue_mask, bpp);
NSLog(@"Please report this along with details on your pixel format "
@"(ie. the four numbers above) to bug-gnustep@gnu.org."
@"Better: implement it and send a patch.)");
exit(1);
}
{
float gamma = [[NSUserDefaults standardUserDefaults]
floatForKey: @"back-art-text-gamma"];
int i;
if (!gamma)
gamma = 1.4;
NSDebugLLog(@"back-art",@"gamma=%g",gamma);
gamma = 1.0 / gamma;
for (i = 0; i < 256; i++)
{
gamma_table[i] = pow(i / 255.0, gamma) * 255 + .5;
inv_gamma_table[i] = pow(i / 255.0, 1.0 / gamma) * 255 + .5;
}
}
}
/*
compositing: source opaque/dest. opaque
00 01 10 11
Clear 0 0 +ab, clear
Copy 1 0 copy all +ab, copy copy copy
Sover 1 1 - srcA impl impl copy copy
Sin dstA 0 impl +ab, copy impl copy
Sout 1 - dstA 0 impl clear impl clear
Satop dstA 1 - srcA impl Sover 01 Sin 10 copy
Dover 1 - dstA 1 impl noop impl noop
Din 0 srcA impl +ab, 00 noop noop
Dout 0 1 - srcA impl +ab, 00 clear clear
Datop 1 - dstA srcA impl +ab, 00 Dover 10 noop
Xor 1 - dstA 1 - srcA impl +ab, 00 Sout 10 clear
PlusL impl impl impl impl
dst=dst+src, dsta=dsta+srca
PlusD impl impl impl impl
dst=dst+src-1, dsta=dsta+srca
compositing (source transparent) dest. opaque
0 1
Clear 0 0 clear clear
Copy 1 0 clear clear
Sover 1 1 - srcA noop noop
Sin dstA 0 clear clear
Sout 1 - dstA 0 clear clear
Satop dstA 1 - srcA noop noop
Dover 1 - dstA 1 noop noop
Din 0 srcA clear clear
Dout 0 1 - srcA noop noop
Datop 1 - dstA srcA clear clear
Xor 1 - dstA 1 - srcA noop noop
PlusL dst=src+dst , clamp to 1.0; dsta=srca+dsta, clamp to 1.0
PlusD dst=src+dst-1, clamp to 0.0; dsta=srca+dsta, clamp to 1.0
*/

View file

@ -20,22 +20,6 @@
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
This file includes itself. Many times. You have been warned.
*/
#ifndef FORMAT_INSTANCE
#include <math.h>
#include <string.h>
#include <Foundation/NSDebug.h>
#include "blit.h"
#endif
/*
TODO: rounding of alpha is wrong in many places, ie. an alpha of 255 is
treated as an alpha of 255/256 instead of 255/255. The
@ -62,29 +46,12 @@ TODO: more cpp magic to reduce the amount of code?
/*
First attempt at gamma correction. Only used in text rendering (blit_*),
but that's where it's needed the most. The gamma adjustment is a large
hack, but the results are good.
*/
static unsigned char gamma_table[256],inv_gamma_table[256];
#define NPRE(r, pre) pre##_##r
#ifdef FORMAT_INSTANCE
/*
Define the different blitting functions. This is the important part when
the file includes itself. Each blitter is defined once for each format
Define the different blitting functions.
Each blitter is defined once for each format
using the different helper macros (or specially optimized functions in
some cases).
*/
#define M2PRE(a, b) NPRE(a, b)
#define MPRE(r) M2PRE(r, FORMAT_INSTANCE)
static void MPRE(blit_alpha_opaque) (unsigned char *adst,
const unsigned char *asrc,
@ -1517,502 +1484,4 @@ static void MPRE(dissolve_oo) (composite_run_t *c, int num)
#undef FORMAT_HOW
#undef INLINE_ALPHA
#else
/*
For each supported pixel format we define a bunch of macros and include
ourself.
*/
/* 24-bit red green blue */
#define FORMAT_INSTANCE rgb
#define FORMAT_HOW DI_24_RGB
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nr=p[0]; ng=p[1]; nb=p[2];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nr=p[0]; ng=p[1]; nb=p[2]; na=pa[0];
#define BLEND_WRITE(p,nr,ng,nb) p[0]=nr; p[1]=ng; p[2]=nb;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=nr; p[1]=ng; p[2]=nb; pa[0]=na;
#define BLEND_INC(p) p+=3;
#define ALPHA_READ(s,sa,d) d=sa[0];
#define ALPHA_INC(s,sa) s+=3; sa++;
#define COPY_TYPE unsigned char
#define COPY_TYPE_PIXEL(a) unsigned char a[3];
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v[0]=r; v[1]=g; v[2]=b;
#define COPY_WRITE(dst,v) dst[0]=v[0]; dst[1]=v[1]; dst[2]=v[2];
#define COPY_INC(dst) dst+=3;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 24-bit blue green red */
#define FORMAT_INSTANCE bgr
#define FORMAT_HOW DI_24_BGR
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nb=p[0]; ng=p[1]; nr=p[2];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nb=p[0]; ng=p[1]; nr=p[2]; na=pa[0];
#define BLEND_WRITE(p,nr,ng,nb) p[0]=nb; p[1]=ng; p[2]=nr;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=nb; p[1]=ng; p[2]=nr; pa[0]=na;
#define BLEND_INC(p) p+=3;
#define ALPHA_READ(s,sa,d) d=sa[0];
#define ALPHA_INC(s,sa) s+=3; sa++;
#define COPY_TYPE unsigned char
#define COPY_TYPE_PIXEL(a) unsigned char a[3];
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v[0]=b; v[1]=g; v[2]=r;
#define COPY_WRITE(dst,v) dst[0]=v[0]; dst[1]=v[1]; dst[2]=v[2];
#define COPY_INC(dst) dst+=3;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 32-bit red green blue alpha */
#define FORMAT_INSTANCE rgba
#define FORMAT_HOW DI_32_RGBA
#define INLINE_ALPHA
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nr=p[0]; ng=p[1]; nb=p[2];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nr=p[0]; ng=p[1]; nb=p[2]; na=p[3];
#define BLEND_WRITE(p,nr,ng,nb) p[0]=nr; p[1]=ng; p[2]=nb;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=nr; p[1]=ng; p[2]=nb; p[3]=na;
#define BLEND_INC(p) p+=4;
#define ALPHA_READ(s,sa,d) d=s[3];
#define ALPHA_INC(s,sa) s+=4;
#define COPY_TYPE unsigned int
#define COPY_TYPE_PIXEL(a) unsigned int a;
#if GS_WORDS_BIGENDIAN
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(r<<24)|(g<<16)|(b<<8);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(r<<24)|(g<<16)|(b<<8)|(a);
#else
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(b<<16)|(g<<8)|(r<<0);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(b<<16)|(g<<8)|(r<<0)|(a<<24);
#endif
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 32-bit blue green red alpha */
#define FORMAT_INSTANCE bgra
#define FORMAT_HOW DI_32_BGRA
#define INLINE_ALPHA
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nb=p[0]; ng=p[1]; nr=p[2];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nb=p[0]; ng=p[1]; nr=p[2]; na=p[3];
#define BLEND_WRITE(p,nr,ng,nb) p[0]=nb; p[1]=ng; p[2]=nr;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=nb; p[1]=ng; p[2]=nr; p[3]=na;
#define BLEND_INC(p) p+=4;
#define ALPHA_READ(s,sa,d) d=s[3];
#define ALPHA_INC(s,sa) s+=4;
#define COPY_TYPE unsigned int
#define COPY_TYPE_PIXEL(a) unsigned int a;
#if GS_WORDS_BIGENDIAN
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(b<<24)|(g<<16)|(r<<8);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(b<<24)|(g<<16)|(r<<8)|(a);
#else
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(r<<16)|(g<<8)|(b<<0);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(r<<16)|(g<<8)|(b<<0)|(a<<24);
#endif
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 32-bit alpha red green blue */
#define FORMAT_INSTANCE argb
#define FORMAT_HOW DI_32_ARGB
#define INLINE_ALPHA
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nr=p[1]; ng=p[2]; nb=p[3];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nr=p[1]; ng=p[2]; nb=p[3]; na=p[0];
#define BLEND_WRITE(p,nr,ng,nb) p[1]=nr; p[2]=ng; p[3]=nb;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[1]=nr; p[2]=ng; p[3]=nb; p[0]=na;
#define BLEND_INC(p) p+=4;
#define ALPHA_READ(s,sa,d) d=s[0];
#define ALPHA_INC(s,sa) s+=4;
#define COPY_TYPE unsigned int
#define COPY_TYPE_PIXEL(a) unsigned int a;
#if GS_WORDS_BIGENDIAN
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(r<<16)|(g<<8)|(b<<0);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(r<<16)|(g<<8)|(b<<0)|(a<<24);
#else
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(b<<24)|(g<<16)|(r<<8);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(b<<24)|(g<<16)|(r<<8)|(a);
#endif
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 32-bit alpha blue green red */
#define FORMAT_INSTANCE abgr
#define FORMAT_HOW DI_32_ABGR
#define INLINE_ALPHA
#define BLEND_TYPE unsigned char
#define BLEND_READ(p,nr,ng,nb) nb=p[1]; ng=p[2]; nr=p[3];
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) nb=p[1]; ng=p[2]; nr=p[3]; na=p[0];
#define BLEND_WRITE(p,nr,ng,nb) p[1]=nb; p[2]=ng; p[3]=nr;
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[1]=nb; p[2]=ng; p[3]=nr; p[0]=na;
#define BLEND_INC(p) p+=4;
#define ALPHA_READ(s,sa,d) d=s[0];
#define ALPHA_INC(s,sa) s+=4;
#define COPY_TYPE unsigned int
#define COPY_TYPE_PIXEL(a) unsigned int a;
#if GS_WORDS_BIGENDIAN
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(b<<16)|(g<<8)|(r<<0);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(b<<16)|(g<<8)|(r<<0)|(a<<24);
#else
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=(r<<24)|(g<<16)|(b<<8);
#define COPY_ASSEMBLE_PIXEL_ALPHA(v,r,g,b,a) v=(r<<24)|(g<<16)|(b<<8)|(a);
#endif
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 16-bit 5 bits blue, 6 bits green, 5 bits red */
#define FORMAT_INSTANCE b5g6r5
#define FORMAT_HOW DI_16_B5_G6_R5
#define BLEND_TYPE unsigned short
#define BLEND_READ(p,nr,ng,nb) \
{ \
unsigned short _s=p[0]; \
nr=(_s>>11)<<3; \
ng=((_s>>5)<<2)&0xff; \
nb=(_s<<3)&0xff; \
}
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) \
{ \
unsigned short _s=p[0]; \
nr=(_s>>11)<<3; \
ng=((_s>>5)<<2)&0xff; \
nb=(_s<<3)&0xff; \
na=pa[0]; \
}
#define BLEND_WRITE(p,nr,ng,nb) p[0]=((nr>>3)<<11)|((ng>>2)<<5)|(nb>>3);
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=((nr>>3)<<11)|((ng>>2)<<5)|(nb>>3); pa[0]=na;
#define BLEND_INC(p) p++;
#define ALPHA_READ(s,sa,d) d=sa[0];
#define ALPHA_INC(s,sa) s++; sa++;
#define COPY_TYPE unsigned short
#define COPY_TYPE_PIXEL(a) unsigned short a;
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=((r>>3)<<11)|((g>>2)<<5)|(b>>3);
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* 16-bit 5 bits blue, 5 bits green, 5 bits red */
#define FORMAT_INSTANCE b5g5r5a1
#define FORMAT_HOW DI_16_B5_G5_R5_A1
#define BLEND_TYPE unsigned short
#define BLEND_READ(p,nr,ng,nb) \
{ \
unsigned short _s=p[0]; \
nr=(_s>>10)<<3; \
ng=((_s>>5)<<3)&0xff; \
nb=(_s<<3)&0xff; \
}
#define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) \
{ \
unsigned short _s=p[0]; \
nr=(_s>>10)<<3; \
ng=((_s>>5)<<3)&0xff; \
nb=(_s<<3)&0xff; \
na=pa[0]; \
}
#define BLEND_WRITE(p,nr,ng,nb) p[0]=((nr>>3)<<10)+((ng>>3)<<5)+(nb>>3);
#define BLEND_WRITE_ALPHA(p,pa,nr,ng,nb,na) p[0]=((nr>>3)<<10)+((ng>>3)<<5)+(nb>>3); pa[0]=na;
#define BLEND_INC(p) p++;
#define ALPHA_READ(s,sa,d) d=sa[0];
#define ALPHA_INC(s,sa) s++; sa++;
#define COPY_TYPE unsigned short
#define COPY_TYPE_PIXEL(a) unsigned short a;
#define COPY_ASSEMBLE_PIXEL(v,r,g,b) v=((r>>3)<<10)|((g>>3)<<5)|(b>>3);
#define COPY_WRITE(dst,v) dst[0]=v;
#define COPY_INC(dst) dst++;
#include "blit.m"
#undef FORMAT_INSTANCE
/* end of pixel formats */
static draw_info_t draw_infos[DI_NUM] = {
#define C(x) \
NPRE(run_alpha,x), \
NPRE(run_opaque,x), \
NPRE(run_alpha_a,x), \
NPRE(run_opaque_a,x), \
NPRE(blit_alpha_opaque,x), \
NPRE(blit_mono_opaque,x), \
NPRE(blit_alpha,x), \
NPRE(blit_mono,x), \
NPRE(blit_alpha_a,x), \
NPRE(blit_mono_a,x), \
\
NPRE(blit_subpixel,x), \
\
NPRE(read_pixels_o,x), \
NPRE(read_pixels_a,x), \
\
NPRE(sover_aa,x), \
NPRE(sover_ao,x), \
NPRE(sin_aa,x), \
NPRE(sin_oa,x), \
NPRE(sout_aa,x), \
NPRE(sout_oa,x), \
NPRE(satop_aa,x), \
NPRE(dover_aa,x), \
NPRE(dover_oa,x), \
NPRE(din_aa,x), \
NPRE(dout_aa,x), \
NPRE(datop_aa,x), \
NPRE(xor_aa,x), \
NPRE(plusl_aa,x), \
NPRE(plusl_oa,x), \
NPRE(plusl_ao_oo,x), \
NPRE(plusl_ao_oo,x), \
NPRE(plusd_aa,x), \
NPRE(plusd_oa,x), \
NPRE(plusd_ao_oo,x), \
NPRE(plusd_ao_oo,x), \
NPRE(dissolve_aa,x), \
NPRE(dissolve_oa,x), \
NPRE(dissolve_ao,x), \
NPRE(dissolve_oo,x),
/* TODO: try to implement fallback versions? possible? */
{DI_FALLBACK ,0, 0,0,-1,/*C(fallback)*/},
{DI_16_B5_G5_R5_A1 ,2,15,0,-1,C(b5g5r5a1)},
{DI_16_B5_G6_R5 ,2,16,0,-1,C(b5g6r5)},
{DI_24_RGB ,3,24,0,-1,C(rgb)},
{DI_24_BGR ,3,24,0,-1,C(bgr)},
/* ARTContext.m assumes that only 32-bit modes have inline alpha. this
might eventually need to be fixed */
{DI_32_RGBA ,4,24,1, 3,C(rgba)},
{DI_32_BGRA ,4,24,1, 3,C(bgra)},
{DI_32_ARGB ,4,24,1, 0,C(argb)},
{DI_32_ABGR ,4,24,1, 0,C(abgr)},
};
static int byte_ofs_of_mask(unsigned int m)
{
union
{
unsigned char b[4];
unsigned int m;
} tmp;
tmp.m = m;
if (tmp.b[0] == 0xff && !tmp.b[1] && !tmp.b[2] && !tmp.b[3])
return 0;
else if (tmp.b[1] == 0xff && !tmp.b[0] && !tmp.b[2] && !tmp.b[3])
return 1;
else if (tmp.b[2] == 0xff && !tmp.b[0] && !tmp.b[1] && !tmp.b[3])
return 2;
else if (tmp.b[3] == 0xff && !tmp.b[0] && !tmp.b[1] && !tmp.b[2])
return 3;
else
return -1;
}
#include <Foundation/NSUserDefaults.h>
void artcontext_setup_draw_info(draw_info_t *di,
unsigned int red_mask, unsigned int green_mask, unsigned int blue_mask,
int bpp)
{
int t = DI_FALLBACK;
NSDebugLLog(@"back-art", @"%s masks=(%08x %08x %08x) bpp=%i",
__PRETTY_FUNCTION__, red_mask, green_mask, blue_mask, bpp);
if (bpp == 16 && red_mask == 0xf800 && green_mask == 0x7e0 &&
blue_mask == 0x1f)
{
t = DI_16_B5_G6_R5;
}
else if (bpp == 16 && red_mask == 0x7c00 && green_mask == 0x3e0 &&
blue_mask == 0x1f)
{
t = DI_16_B5_G5_R5_A1;
}
else if (bpp == 24 || bpp == 32)
{
int r, g, b;
r = byte_ofs_of_mask(red_mask);
g = byte_ofs_of_mask(green_mask);
b = byte_ofs_of_mask(blue_mask);
if (bpp == 24)
{
if (r == 0 && g == 1 && b == 2)
t = DI_24_RGB;
else if (r == 2 && g == 1 && b == 0)
t = DI_24_BGR;
}
else if (bpp == 32)
{
if (r == 0 && g == 1 && b == 2)
t = DI_32_RGBA;
else if (r == 2 && g == 1 && b == 0)
t = DI_32_BGRA;
else if (r == 1 && g == 2 && b == 3)
t = DI_32_ARGB;
else if (r == 3 && g == 2 && b == 1)
t = DI_32_ABGR;
}
}
NSDebugLLog(@"back-art", @"got t=%i", t);
*di = draw_infos[t];
if (!di->render_run_alpha)
*di = draw_infos[DI_FALLBACK];
if (di->how == DI_FALLBACK)
{
NSLog(@"gnustep-back(art): Unrecognized color masks: %08x:%08x:%08x %i",
red_mask, green_mask, blue_mask, bpp);
NSLog(@"Please report this along with details on your pixel format "
@"(ie. the four numbers above) to bug-gnustep@gnu.org."
@"Better: implement it and send a patch.)");
exit(1);
}
{
float gamma = [[NSUserDefaults standardUserDefaults]
floatForKey: @"back-art-text-gamma"];
int i;
if (!gamma)
gamma = 1.4;
NSDebugLLog(@"back-art",@"gamma=%g",gamma);
gamma = 1.0 / gamma;
for (i = 0; i < 256; i++)
{
gamma_table[i] = pow(i / 255.0, gamma) * 255 + .5;
inv_gamma_table[i] = pow(i / 255.0, 1.0 / gamma) * 255 + .5;
}
}
}
#endif
#if 0
/* potentially interesting old implementations of stuff */
static void r5g6b5_blit_mono_opaque(
/* ... */
/* TODO: could optimize with a two-bit check and a four-way branch
that writes two pixels in one go */
/* ... */
}
#endif
/*
compositing: source opaque/dest. opaque
00 01 10 11
Clear 0 0 +ab, clear
Copy 1 0 copy all +ab, copy copy copy
Sover 1 1 - srcA impl impl copy copy
Sin dstA 0 impl +ab, copy impl copy
Sout 1 - dstA 0 impl clear impl clear
Satop dstA 1 - srcA impl Sover 01 Sin 10 copy
Dover 1 - dstA 1 impl noop impl noop
Din 0 srcA impl +ab, 00 noop noop
Dout 0 1 - srcA impl +ab, 00 clear clear
Datop 1 - dstA srcA impl +ab, 00 Dover 10 noop
Xor 1 - dstA 1 - srcA impl +ab, 00 Sout 10 clear
PlusL impl impl impl impl
dst=dst+src, dsta=dsta+srca
PlusD impl impl impl impl
dst=dst+src-1, dsta=dsta+srca
compositing (source transparent) dest. opaque
0 1
Clear 0 0 clear clear
Copy 1 0 clear clear
Sover 1 1 - srcA noop noop
Sin dstA 0 clear clear
Sout 1 - dstA 0 clear clear
Satop dstA 1 - srcA noop noop
Dover 1 - dstA 1 noop noop
Din 0 srcA clear clear
Dout 0 1 - srcA noop noop
Datop 1 - dstA srcA clear clear
Xor 1 - dstA 1 - srcA noop noop
PlusL dst=src+dst , clamp to 1.0; dsta=srca+dsta, clamp to 1.0
PlusD dst=src+dst-1, clamp to 0.0; dsta=srca+dsta, clamp to 1.0
*/

View file

@ -39,7 +39,7 @@
windows are known to be totally opaque, we can optimize in many ways
(see big table at the end of blit.m). Will set dst_need_alpha and blit_func
if necessary. Returns new operation, or -1 it it's a noop. */
-(int) _composite_func: (BOOL)src_opaque : (BOOL)src_transparent
- (int) _composite_func: (BOOL)src_opaque : (BOOL)src_transparent
: (BOOL)dst_opaque : (BOOL *)dst_needs_alpha
: (int)op : (void (**)(composite_run_t *c, int num))blit_func_r
{
@ -217,27 +217,28 @@ if necessary. Returns new operation, or -1 it it's a noop. */
static void copy_oo(composite_run_t *c, int num)
{
memcpy(c->dst,c->src,num*DI.bytes_per_pixel);
memcpy(c->dst, c->src, num * DI.bytes_per_pixel);
}
static void copy_oa(composite_run_t *c, int num)
{
memcpy(c->dst,c->src,num*DI.bytes_per_pixel);
if (DI.inline_alpha)
{
unsigned char *dsta=c->dst+DI.inline_alpha_ofs;
for (;num;num--,dsta+=4)
*dsta=0xff;
}
else
memset(c->dsta,0xff,num);
memcpy(c->dst, c->src, num * DI.bytes_per_pixel);
if (DI.inline_alpha)
{
unsigned char *dsta = c->dst + DI.inline_alpha_ofs;
for (; num; num--, dsta += 4)
*dsta = 0xff;
}
else
memset(c->dsta, 0xff, num);
}
static void copy_aa(composite_run_t *c, int num)
{
memcpy(c->dst,c->src,num*DI.bytes_per_pixel);
if (!DI.inline_alpha)
memcpy(c->dsta,c->srca,num);
memcpy(c->dst,c->src,num*DI.bytes_per_pixel);
if (!DI.inline_alpha)
memcpy(c->dsta, c->srca, num);
}
@ -453,7 +454,6 @@ static BOOL _rect_advance(rect_trace_t *t, int *x0, int *x1)
if (!wi || !wi->data || !ags->wi || !ags->wi->data) return;
if (all_clipped) return;
{
BOOL dst_needs_alpha;
op = [self _composite_func: !ags->wi->has_alpha : NO