- SWRender, private AA quality gstate ivar, fill/blend optimizations, bugfix in surface resize

This commit is contained in:
Christopher Lloyd 2008-06-23 18:58:30 +00:00
parent f057bee1b4
commit 9d8e020688
15 changed files with 481 additions and 313 deletions

View File

@ -221,6 +221,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
-(void)resetClip;
-(void)setAntialiasingQuality:(int)value;
-(void)setWordSpacing:(float)spacing;
-(void)setTextLeading:(float)leading;

View File

@ -908,6 +908,10 @@ static inline KGGraphicsState *currentState(KGContext *self){
[self deviceClipReset];
}
-(void)setAntialiasingQuality:(int)value {
[currentState(self) setAntialiasingQuality:value];
}
-(void)setWordSpacing:(float)spacing {
[currentState(self) setWordSpacing:spacing];
}

View File

@ -62,9 +62,6 @@ typedef void (*KGBlendSpan_RGBAffff)(KGRGBAffff *src,KGRGBAffff *dst,int length)
@class KGSurface,KGContext_builtin;
typedef void (*KGWriteCoverageSpans)(KGContext_builtin *self,int *x, int *y,int *coverage,int *lengths,int count);
#define KGRasterizer KGContext_builtin
@interface KGContext_builtin : KGBitmapContext {
@ -73,7 +70,7 @@ typedef void (*KGWriteCoverageSpans)(KGContext_builtin *self,int *x, int *y,int
KGPaint *m_paint;
BOOL _useRGBA8888;
CGBlendMode _blendMode;
KGBlendSpan_RGBA8888 _blend_lRGBA8888_PRE;
KGBlendSpan_RGBAffff _blend_lRGBAffff_PRE;
@ -81,11 +78,12 @@ typedef void (*KGWriteCoverageSpans)(KGContext_builtin *self,int *x, int *y,int
int _edgeCount;
int _edgeCapacity;
Edge *_edgePool;
Edge **_edges;
Edge **_sortCache;
int *_winding;
int *_increase;
int *_xIndexSet;
int sampleSizeShift;
int numSamples;
@ -101,14 +99,11 @@ void KGRasterizerDealloc(KGRasterizer *self);
void KGRasterizerSetViewport(KGRasterizer *self,int vpwidth,int vpheight);
void KGRasterizerClear(KGRasterizer *self);
void KGRasterizerAddEdge(KGRasterizer *self,const CGPoint v0, const CGPoint v1);
void KGRasterizerSetShouldAntialias(KGRasterizer *self,BOOL antialias);
void KGRasterizerSetShouldAntialias(KGRasterizer *self,BOOL antialias,int quality);
void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRule);
void KGRasterizeSetBlendMode(KGRasterizer *self,CGBlendMode blendMode);
void KGRasterizeSetMask(KGRasterizer *self,KGSurface* mask);
void KGRasterizeSetPaint(KGRasterizer *self,KGPaint* paint);
//private
void KGRasterizeWriteCoverageSpan(KGRasterizer *self,int x, int y,int coverage,int lengths);
@end

View File

@ -32,9 +32,7 @@
#import "KGPaint_color.h"
#import "KGBlending.h"
#define SAMPLING_RADIUS 0.5
#define MAX_SAMPLES 128
#define RI_MAX_EDGES 262144
#define MAX_SAMPLES COVERAGE_MULTIPLIER
@implementation KGContext_builtin
@ -93,7 +91,8 @@ BOOL _isAvailable=NO;
}
-(void)setWidth:(size_t)width height:(size_t)height reallocateOnlyIfRequired:(BOOL)roir {
_width=width;
_height=height;
[m_renderingSurface setWidth:width height:height reallocateOnlyIfRequired:roir];
KGRasterizerSetViewport(self,KGImageGetWidth(m_renderingSurface),KGImageGetHeight(m_renderingSurface));
}
@ -181,7 +180,7 @@ static KGPaint *paintFromColor(KGColor *color){
// KGRasterizeSetTileFillColor(context->m_tileFillColor);
KGRasterizerSetShouldAntialias(self,gState->_shouldAntialias);
KGRasterizerSetShouldAntialias(self,gState->_shouldAntialias,gState->_antialiasingQuality);
//CGAffineTransform xform=CGAffineTransformIdentity;//gState->_userSpaceTransform;
CGAffineTransform xform=gState->_userSpaceTransform;
@ -274,7 +273,7 @@ xform=CGAffineTransformConcat(xform,u2d);
p3 = CGAffineTransformTransformVector2(imageUserToSurface , p3);
KGRasterizerSetShouldAntialias(self,gState->_shouldAntialias);
KGRasterizerSetShouldAntialias(self,gState->_shouldAntialias,gState->_antialiasingQuality);
// KGRasterizeSetTileFillColor(context->m_tileFillColor);
KGPaint *paint=paintFromColor(gState->_fillColor);
@ -345,8 +344,9 @@ KGRasterizer *KGRasterizerInit(KGRasterizer *self,KGSurface *renderingSurface) {
self->_edgeCount=0;
self->_edgeCapacity=256;
self->_edgePool=NSZoneMalloc(NULL,self->_edgeCapacity*sizeof(Edge));
self->_edges=NSZoneMalloc(NULL,self->_edgeCapacity*sizeof(Edge *));
self->_sortCache=NSZoneMalloc(NULL,(self->_edgeCapacity/2 + 1)*sizeof(Edge *));
self->samplesX=NSZoneMalloc(NULL,MAX_SAMPLES*sizeof(CGFloat));
self->samplesY=NSZoneMalloc(NULL,MAX_SAMPLES*sizeof(CGFloat));
@ -354,7 +354,12 @@ KGRasterizer *KGRasterizerInit(KGRasterizer *self,KGSurface *renderingSurface) {
}
void KGRasterizerDealloc(KGRasterizer *self) {
NSZoneFree(NULL,self->_edgePool);
int i;
for(i=0;i<self->_edgeCount;i++)
NSZoneFree(NULL,self->_edges[i]);
NSZoneFree(NULL,self->_edges);
NSZoneFree(NULL,self->_sortCache);
NSZoneFree(NULL,self);
}
@ -366,51 +371,58 @@ void KGRasterizerSetViewport(KGRasterizer *self,int vpwidth,int vpheight) {
self->_winding=malloc((vpwidth*MAX_SAMPLES)*sizeof(int));
free(self->_increase);
self->_increase=malloc(vpwidth*sizeof(int));
free(self->_xIndexSet);
self->_xIndexSet=malloc(vpwidth*sizeof(int));
int i;
for(i=0;i<vpwidth;i++)
self->_xIndexSet[i]=-1;
}
void KGRasterizerClear(KGRasterizer *self) {
int i;
for(i=0;i<self->_edgeCount;i++)
NSZoneFree(NULL,self->_edges[i]);
self->_edgeCount=0;
}
void KGRasterizerAddEdge(KGRasterizer *self,const CGPoint v0, const CGPoint v1) {
if(v0.y == v1.y)
return; //skip horizontal edges (they don't affect rasterization since we scan horizontally)
if(v0.y<self->_vpy && v1.y<self->_vpy)
if((v0.y+0.5f)<self->_vpy && (v1.y+0.5f)<self->_vpy) // ignore below miny
return;
int MaxY=self->_vpy+self->_vpheight;
if(v0.y>=MaxY && v1.y>=MaxY)
if((v0.y-0.5f)>=MaxY && (v1.y-0.5f)>=MaxY) // ignore above maxy
return;
if( self->_edgeCount >= RI_MAX_EDGES )
NSLog(@"too many edges");
Edge *edge;
Edge *edge=NSZoneMalloc(NULL,sizeof(Edge));
if(self->_edgeCount+1>=self->_edgeCapacity){
self->_edgeCapacity*=2;
self->_edgePool=NSZoneRealloc(NULL,self->_edgePool,self->_edgeCapacity*sizeof(Edge));
self->_edges=NSZoneRealloc(NULL,self->_edges,self->_edgeCapacity*sizeof(Edge *));
self->_sortCache=NSZoneRealloc(NULL,self->_sortCache,(self->_edgeCapacity/2 + 1)*sizeof(Edge *));
}
edge=self->_edgePool+self->_edgeCount;
self->_edges[self->_edgeCount]=edge;
self->_edgeCount++;
if(v0.y < v1.y)
{ //edge is going upward
if(v0.y < v1.y){ //edge is going upward
edge->v0 = v0;
edge->v1 = v1;
edge->direction = 1;
}
else
{ //edge is going downward
else { //edge is going downward
edge->v0 = v1;
edge->v1 = v0;
edge->direction = -1;
}
edge->normal=CGPointMake(edge->v0.y - edge->v1.y, edge->v1.x - edge->v0.x); //edge normal
edge->normal=CGPointMake(edge->v0.y-edge->v1.y , edge->v1.x - edge->v0.x); //edge normal
edge->cnst = Vector2Dot(edge->v0, edge->normal); //distance of v0 from the origin along the edge normal
edge->minscany=RI_FLOOR_TO_INT(edge->v0.y-SAMPLING_RADIUS);
edge->maxscany=ceil(edge->v1.y+SAMPLING_RADIUS);
edge->normal.y=-edge->normal.y;
edge->minscany=RI_FLOOR_TO_INT(edge->v0.y-0.5f);
edge->maxscany=ceil(edge->v1.y+0.5f);
edge->next=NULL;
}
@ -420,7 +432,7 @@ static double radicalInverseBase2(unsigned int i)
if( i == 0 )
return 0.0;
double p = 0.0;
double f = 0.5;
double f = 0.5f;
double ff = f;
unsigned int j;
for(j=0;j<32;j++)
@ -432,34 +444,44 @@ static double radicalInverseBase2(unsigned int i)
return p;
}
void KGRasterizerSetShouldAntialias(KGRasterizer *self,BOOL antialias) {
void KGRasterizerSetShouldAntialias(KGRasterizer *self,BOOL antialias,int quality) {
/* RULES:
- samplesY must be in ascending order
*/
//make a sampling pattern
if(!antialias){
quality=RI_INT_CLAMP(quality,1,MAX_SAMPLES);
if(!antialias || quality==1){
self->numSamples=1;
self->samplesX[0] = 0;
self->samplesY[0] = 0;
self->samplesWeight = 256;
self->samplesY[0] = 0.5f;
self->samplesWeight = MAX_SAMPLES;
}
else {
int shift;
int numberOfSamples=1;
for(shift=0;numberOfSamples<quality;shift++)
numberOfSamples<<=1;
/*
At this point I am pretty convinced Apple is using a box shaped filter
At this point I am pretty convinced Apple is using a box filter
The sampling pattern is different than this
*/
self->sampleSizeShift=6;
self->numSamples = 1<<self->sampleSizeShift; // 64
self->sampleSizeShift=shift;
self->numSamples = numberOfSamples;
int i;
for(i=0;i<self->numSamples;i++){
self->samplesX[i] = (CGFloat)radicalInverseBase2(i)-0.5;
self->samplesY[i] = ((CGFloat)(i+0.5)) / (CGFloat)self->numSamples-0.5;
self->samplesWeight=256/self->numSamples;
}
for(i=0;i<numberOfSamples;i++){
self->samplesX[i] = (CGFloat)radicalInverseBase2(i)-0.5f;
self->samplesY[i] = ((CGFloat)(i+0.5f)) / (CGFloat)numberOfSamples-0.5f;
self->samplesWeight=MAX_SAMPLES/numberOfSamples;
}
}
}
static void sortEdgesByMinY(Edge **edges,int count,Edge **B){
static inline void sortEdgesByMinY(Edge **edges,int count,Edge **B){
int h, i, j, k, l, m, n = count;
Edge *A;
@ -492,7 +514,7 @@ static void sortEdgesByMinY(Edge **edges,int count,Edge **B){
}
}
static void initEdgeForAET(Edge *edge,CGFloat cminy,CGFloat cmaxy,int xlimit){
static inline void initEdgeForAET(Edge *edge,int scany){
//compute edge min and max x-coordinates for this scanline
CGPoint vd = Vector2Subtract(edge->v1,edge->v0);
@ -502,22 +524,22 @@ static void initEdgeForAET(Edge *edge,CGFloat cminy,CGFloat cmaxy,int xlimit){
edge->bminx = RI_MIN(edge->v0.x, edge->v1.x);
edge->bmaxx = RI_MAX(edge->v0.x, edge->v1.x);
edge->sxPre = (edge->v0.x - edge->v0.y* edge->vdxwl)+ edge->vdxwl*cminy;
edge->exPre = (edge->v0.x - edge->v0.y* edge->vdxwl)+ edge->vdxwl*cmaxy;
edge->sxPre = (edge->v0.x - edge->v0.y* edge->vdxwl)+ edge->vdxwl*(scany-1);
edge->exPre = (edge->v0.x - edge->v0.y* edge->vdxwl)+ edge->vdxwl*(scany+1);
CGFloat autosx = RI_CLAMP(edge->sxPre, edge->bminx, edge->bmaxx);
CGFloat autoex = RI_CLAMP(edge->exPre, edge->bminx, edge->bmaxx);
CGFloat minx=RI_MIN(autosx,autoex);
CGFloat maxx=RI_MAX(autosx,autoex);
minx-=SAMPLING_RADIUS+0.5f;
minx-=0.5f+0.5f;
//0.01 is a safety region to prevent too aggressive optimization due to numerical inaccuracy
maxx+=SAMPLING_RADIUS+0.5f+0.01f;
maxx+=0.5f+0.5f+0.01f;
edge->minx = minx;
edge->maxx = maxx;
}
static void incrementEdgeForAET(Edge *edge,CGFloat cminy,CGFloat cmaxy,int xlimit){
static inline void incrementEdgeForAET(Edge *edge){
edge->sxPre+= edge->vdxwl;
edge->exPre+= edge->vdxwl;
@ -526,63 +548,213 @@ static void incrementEdgeForAET(Edge *edge,CGFloat cminy,CGFloat cmaxy,int xlimi
CGFloat minx=RI_MIN(autosx,autoex);
CGFloat maxx=RI_MAX(autosx,autoex);
minx-=SAMPLING_RADIUS+0.5f;
minx-=0.5f+0.5f;
//0.01 is a safety region to prevent too aggressive optimization due to numerical inaccuracy
maxx+=SAMPLING_RADIUS+0.5f+0.01f;
maxx+=0.5f+0.5f+0.01f;
edge->minx = minx;
edge->maxx = maxx;
}
void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
int edgeCount=self->_edgeCount;
Edge **edges=NSZoneMalloc(NULL,(edgeCount+(edgeCount/2 + 1))*sizeof(Edge *));
Edge **sortTmp=edges+edgeCount;
static void KGApplyCoverageAndMaskToSpan_lRGBAffff_PRE(KGRGBAffff *dst,int icoverage,CGFloat *mask,KGRGBAffff *src,int length){
int i;
for(i=0;i<length;i++){
KGRGBAffff r=src[i];
KGRGBAffff d=dst[i];
CGFloat coverage=zeroToOneFromCoverage(icoverage);
CGFloat cov=mask[i]*coverage;
dst[i]=KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(r , cov) , KGRGBAffffMultiplyByFloat(d , (1.0f - cov)));
}
}
int ylimit=self->_vpheight;
int xlimit=self->_vpwidth;
int nextAvailableEdge=0;
int i;
for(i=0;i<edgeCount;i++)
edges[i]=self->_edgePool+i;
static void KGApplyCoverageToSpan_lRGBAffff_PRE(KGRGBAffff *dst,int icoverage,KGRGBAffff *src,int length){
int i;
CGFloat coverage=zeroToOneFromCoverage(icoverage);
for(i=0;i<length;i++){
KGRGBAffff r=src[i];
KGRGBAffff d=dst[i];
sortEdgesByMinY(edges,edgeCount,sortTmp);
for(;nextAvailableEdge<edgeCount;nextAvailableEdge++){
Edge *check=edges[nextAvailableEdge];
dst[i]=KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(r , coverage) , KGRGBAffffMultiplyByFloat(d , (1.0f - coverage)));
}
}
static void KGApplyCoverageAndMaskToSpan_lRGBA8888_PRE(KGRGBA8888 *dst,int icoverage,uint8_t *mask,KGRGBA8888 *src,int length){
int i;
for(i=0;i<length;i++){
KGRGBA8888 r=src[i];
KGRGBA8888 d=dst[i];
int cov=(mask[i]*icoverage)/255;
int oneMinusCov=inverseCoverage(cov);
if(check->maxscany>=self->_vpy)
dst[i]=KGRGBA8888Add(KGRGBA8888MultiplyByCoverage(r , cov) , KGRGBA8888MultiplyByCoverage(d , oneMinusCov));
}
}
static void KGApplyCoverageToSpan_lRGBA8888_PRE(KGRGBA8888 *dst,int coverage,KGRGBA8888 *src,int length){
int i;
int oneMinusCoverage=inverseCoverage(coverage);
for(i=0;i<length;i++,src++,dst++){
KGRGBA8888 r=*src;
KGRGBA8888 d=*dst;
*dst=KGRGBA8888Add(KGRGBA8888MultiplyByCoverage(r , coverage) , KGRGBA8888MultiplyByCoverage(d , oneMinusCoverage));
}
}
static void KGBlendSpanNormal_8888_coverage(KGRGBA8888 *src,KGRGBA8888 *dst,int coverage,int length){
// Passes Visual Test
int i;
int oneMinusCoverage=inverseCoverage(coverage);
for(i=0;i<length;i++,src++,dst++){
KGRGBA8888 s=*src;
KGRGBA8888 d=*dst;
KGRGBA8888 r;
r.r=RI_INT_MIN((int)s.r+((int)d.r*(255-s.a))/255,255);
r.r=multiplyByCoverage(r.r,coverage);
d.r=(d.r*oneMinusCoverage)/256;
r.r=RI_INT_MIN((int)r.r+(int)d.r,255);
r.g=RI_INT_MIN((int)s.g+((int)d.g*(255-s.a))/255,255);
r.g=multiplyByCoverage(r.g,coverage);
d.g=(d.g*oneMinusCoverage)/256;
r.g=RI_INT_MIN((int)r.g+(int)d.g,255);
r.b=RI_INT_MIN((int)s.b+((int)d.b*(255-s.a))/255,255);
r.b=multiplyByCoverage(r.b,coverage);
d.b=(d.b*oneMinusCoverage)/256;
r.b=RI_INT_MIN((int)r.b+(int)d.b,255);
r.a=RI_INT_MIN((int)s.a+((int)d.a*(255-s.a))/255,255);
r.a=multiplyByCoverage(r.a,coverage);
d.a=(d.a*oneMinusCoverage)/256;
r.a=RI_INT_MIN((int)r.a+(int)d.a,255);
*dst=r;
}
}
static void KGBlendSpanCopy_8888_coverage(KGRGBA8888 *src,KGRGBA8888 *dst,int coverage,int length){
// Passes Visual Test
int i;
int oneMinusCoverage=256-coverage;
for(i=0;i<length;i++,src++,dst++){
KGRGBA8888 d=*dst;
KGRGBA8888 r=*src;
r.r=multiplyByCoverage(r.r,coverage);
d.r=(d.r*oneMinusCoverage)/256;
r.r=RI_INT_MIN((int)r.r+(int)d.r,255);
r.g=multiplyByCoverage(r.g,coverage);
d.g=(d.g*oneMinusCoverage)/256;
r.g=RI_INT_MIN((int)r.g+(int)d.g,255);
r.b=multiplyByCoverage(r.b,coverage);
d.b=(d.b*oneMinusCoverage)/256;
r.b=RI_INT_MIN((int)r.b+(int)d.b,255);
r.a=multiplyByCoverage(r.a,coverage);
d.a=(d.a*oneMinusCoverage)/256;
r.a=RI_INT_MIN((int)r.a+(int)d.a,255);
*dst=r;
}
}
static inline void KGRasterizeWriteCoverageSpan(KGRasterizer *self,int x, int y,int coverage,int length) {
if(self->_useRGBA8888){
KGRGBA8888 dst[length];
KGImageReadSpan_lRGBA8888_PRE(self->m_renderingSurface,x,y,dst,length);
KGRGBA8888 src[length];
KGPaintReadSpan_lRGBA8888_PRE(self->m_paint,x,y,src,length);
switch(self->_blendMode){
case kCGBlendModeNormal:
KGBlendSpanNormal_8888_coverage(src,dst,coverage,length);
break;
case kCGBlendModeCopy:
KGBlendSpanCopy_8888_coverage(src,dst,coverage,length);
break;
default:
self->_blend_lRGBA8888_PRE(src,dst,length);
//apply masking
if(!self->m_mask)
KGApplyCoverageToSpan_lRGBA8888_PRE(dst,coverage,src,length);
else {
uint8_t maskSpan[length];
KGImageReadSpan_A8_MASK(self->m_mask,x,y,maskSpan,length);
KGApplyCoverageAndMaskToSpan_lRGBA8888_PRE(dst,coverage,maskSpan,src,length);
}
break;
}
//write result to the destination surface
KGSurfaceWriteSpan_lRGBA8888_PRE(self->m_renderingSurface,x,y,dst,length);
}
else {
KGRGBAffff dst[length];
KGImageReadSpan_lRGBAffff_PRE(self->m_renderingSurface,x,y,dst,length);
KGRGBAffff src[length];
KGPaintReadSpan_lRGBAffff_PRE(self->m_paint,x,y,src,length);
self->_blend_lRGBAffff_PRE(src,dst,length);
//apply masking
if(!self->m_mask)
KGApplyCoverageToSpan_lRGBAffff_PRE(dst,coverage,src,length);
else {
CGFloat maskSpan[length];
KGImageReadSpan_Af_MASK(self->m_mask,x,y,maskSpan,length);
KGApplyCoverageAndMaskToSpan_lRGBAffff_PRE(dst,coverage,maskSpan,src,length);
}
//write result to the destination surface
KGSurfaceWriteSpan_lRGBAffff_PRE(self->m_renderingSurface,x,y,dst,length);
}
}
void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
int edgeCount=self->_edgeCount;
Edge **edges=self->_edges;
int ylimit=self->_vpy+self->_vpheight;
int xlimit=self->_vpx+self->_vpwidth;
int nextAvailableEdge=0;
sortEdgesByMinY(edges,edgeCount,self->_sortCache);
Edge *activeRoot=NULL;
CGFloat cminy = (CGFloat)0 - SAMPLING_RADIUS + 0.5f;
CGFloat cmaxy = (CGFloat)0 + SAMPLING_RADIUS + 0.5f;
int scany;
int *winding=self->_winding;
int *increase=self->_increase;
for(scany=0;scany<ylimit;scany++,cminy+=1.0,cmaxy+=1.0){
int *winding=self->_winding;
int *increase=self->_increase;
int *xIndexSet=self->_xIndexSet;
int numberOfSamples=self->numSamples;
int shiftNumberOfSamples=self->sampleSizeShift;
CGFloat sidePre[numberOfSamples];
CGFloat *preEnd=sidePre+numberOfSamples;
for(scany=self->_vpy;scany<ylimit;scany++){
Edge *edge,*previous=NULL;
// remove edges out of range
for(edge=activeRoot;edge!=NULL;edge=edge->next){
if(edge->maxscany>=scany){
incrementEdgeForAET(edge,cminy,cmaxy,xlimit);
previous=edge;
}
else {
if(previous==NULL)
activeRoot=edge->next;
else
previous->next=edge->next;
}
}
// load more available edges
for(;nextAvailableEdge<edgeCount;nextAvailableEdge++){
edge=edges[nextAvailableEdge];
@ -592,88 +764,111 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
edge->next=activeRoot;
activeRoot=edge;
initEdgeForAET(edge,cminy,cmaxy,xlimit);
initEdgeForAET(edge,scany);
}
if(activeRoot==NULL)
continue;
int numberOfSamples=self->numSamples;
int accum=0;
int s;
int scanx,minx=xlimit,maxx=0;
int xIndexSet[xlimit];
int nextXIndex=0;
CGFloat sidePre[numberOfSamples];
CGFloat *preEnd=sidePre+numberOfSamples;
CGFloat pcy=scany+0.5f; // pixel center
for(scanx=0;scanx<xlimit;scanx++)
xIndexSet[scanx]=-1;
int accum=0;
int minx=xlimit,maxx=0;
int nextXIndex=0;
int scanx;
for(edge=activeRoot;edge!=NULL;edge=edge->next){
CGFloat *pre=sidePre;
CGFloat *samplesY=self->samplesY;
CGFloat *samplesX=self->samplesX;
CGFloat v0y=edge->v0.y;
CGFloat v1y=edge->v1.y;
CGFloat pcy=scany+0.5f;
CGFloat v0y=edge->v0.y-pcy;
CGFloat v1y=edge->v1.y-pcy;
CGFloat normalX=edge->normal.x;
CGFloat normalY=edge->normal.y;
int deltaStart=0;
int deltaEnd=0;
s=numberOfSamples;
do {
CGFloat spy = pcy+*samplesY++;
if(spy >= v0y && spy < v1y)
*pre++ = -(spy*normalY + *samplesX++*normalX)-0.5f*normalX;
else {
*pre++=-INT_MAX;
}
}while(--s>0);
int direction=edge->direction;
for(;*samplesY<v0y && pre<preEnd;samplesY++,samplesX++){
pre++;
deltaStart++;
}
for(;*samplesY<v1y && pre<preEnd;samplesY++,samplesX++)
*pre++ = (*samplesY*normalY-*samplesX*normalX);
for(;pre<preEnd;){
pre++;
deltaEnd++;
}
int direction=edge->direction;
minx=MIN(minx,edge->minx);
scanx=MAX(0,edge->minx);
CGFloat pcxnormal=scanx*normalX+0.5f*normalX-(pcy*normalY)-edge->cnst;
for(scanx=MAX(0,edge->minx);scanx<xlimit;scanx++){
for(;scanx<xlimit;scanx++,pcxnormal+=normalX){
int xIndex=xIndexSet[scanx];
int *windptr;
int *windptr;
int leftOfEdge=deltaStart+deltaEnd;
if(xIndex==-1){
xIndex=nextXIndex++;
xIndexSet[scanx]=xIndex;
windptr=winding+(xIndex<<self->sampleSizeShift);
s=numberOfSamples;
do {
pre=sidePre;
windptr=winding+(xIndex<<shiftNumberOfSamples);
int k;
for(k=0;k<deltaStart;k++,pre++)
*windptr++=0;
}while(--s>0);
while(pre<(preEnd-deltaEnd)){
if(*pre>=pcxnormal)
*windptr=direction;
else {
*windptr=0;
leftOfEdge++;
}
windptr++;
pre++;
}
for(k=0;k<deltaEnd;k++)
*windptr++=0;
increase[xIndex]=0;
}
pre=sidePre;
windptr=winding+(xIndex<<self->sampleSizeShift);
CGFloat pcxnormal=scanx*edge->normal.x-edge->cnst;
int rightOfEdge=0;
do{
if(pcxnormal<=*pre){
*windptr+=direction;
rightOfEdge++;
else {
pre=sidePre+deltaStart;
windptr=winding+(xIndex<<shiftNumberOfSamples)+deltaStart;
while(pre<(preEnd-deltaEnd)){
if(*pre>=pcxnormal)
*windptr+=direction;
else
leftOfEdge++;
windptr++;
pre++;
}
windptr++;
pre++;
}while(pre<preEnd);
}
if(rightOfEdge==0 && scanx>edge->maxx)
break;
if(rightOfEdge==numberOfSamples){
if(leftOfEdge==0){
increase[xIndex]+=direction;
break;
}
if(leftOfEdge==numberOfSamples && scanx>edge->maxx)
break;
}
maxx=MAX(maxx,scanx);
// increment and remove edges out of range
if(edge->maxscany>=scany){
incrementEdgeForAET(edge);
previous=edge;
}
else {
if(previous==NULL)
activeRoot=edge->next;
else
previous->next=edge->next;
}
}
minx=MAX(0,minx);
maxx=MIN(xlimit,maxx+1);
@ -681,9 +876,11 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
int xIndex=-1;
for(scanx=minx;scanx<maxx;)
if((xIndex=xIndexSet[scanx])!=-1)
if((xIndex=xIndexSet[scanx])!=-1){
xIndexSet[scanx]=-1;
break;
}
if(xIndex==-1)
continue;
@ -691,12 +888,12 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
int coverage=0;
for(scanx=minx;scanx<maxx;){
int *windptr=winding+(xIndex<<self->sampleSizeShift);
for(scanx=minx;scanx<maxx;){
int *windptr=winding+(xIndex<<shiftNumberOfSamples);
s=numberOfSamples;
int s=numberOfSamples;
do {
if((*windptr+++accum) & fillRuleMask )
if((*windptr+++accum) & fillRuleMask)
coverage +=weight;
}while(--s>0);
@ -704,8 +901,10 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
int advance;
for(advance=scanx+1;advance<maxx;advance++)
if((xIndex=xIndexSet[advance])!=-1)
if((xIndex=xIndexSet[advance])!=-1){
xIndexSet[advance]=-1;
break;
}
if(coverage>0){
KGRasterizeWriteCoverageSpan(self,scanx,scany,coverage,(advance-scanx));
@ -715,13 +914,12 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
scanx=advance;
}
}
NSZoneFree(NULL,edges);
}
void KGRasterizeSetBlendMode(KGRasterizer *self,CGBlendMode blendMode) {
RI_ASSERT(blendMode >= kCGBlendModeNormal && blendMode <= kCGBlendModePlusLighter);
self->_blendMode=blendMode;
self->_useRGBA8888=NO;
switch(blendMode){
@ -866,102 +1064,4 @@ void KGRasterizeSetPaint(KGRasterizer *self, KGPaint* paint) {
}
static void KGApplyCoverageAndMaskToSpan_lRGBAffff_PRE(KGRGBAffff *dst,int coverage256,CGFloat *mask,KGRGBAffff *result,int length){
int i;
for(i=0;i<length;i++){
KGRGBAffff r=result[i];
KGRGBAffff d=dst[i];
CGFloat coverage=(CGFloat)coverage256/256.0;
CGFloat cov=mask[i]*coverage;
result[i]=KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(r , cov) , KGRGBAffffMultiplyByFloat(d , (1.0f - cov)));
}
}
static void KGApplyCoverageToSpan_lRGBAffff_PRE(KGRGBAffff *dst,int coverage256,KGRGBAffff *result,int length){
int i;
CGFloat coverage=(CGFloat)coverage256/256.0;
for(i=0;i<length;i++){
KGRGBAffff r=result[i];
KGRGBAffff d=dst[i];
result[i]=KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(r , coverage) , KGRGBAffffMultiplyByFloat(d , (1.0f - coverage)));
}
}
static void KGApplyCoverageAndMaskToSpan_lRGBA8888_PRE(KGRGBA8888 *dst,int coverage256,uint8_t *mask,KGRGBA8888 *result,int length){
int i;
for(i=0;i<length;i++){
KGRGBA8888 r=result[i];
KGRGBA8888 d=dst[i];
int cov=(mask[i]*coverage256)/255;
int oneMinusCov=(256-cov);
result[i]=KGRGBA8888Add(KGRGBA8888MultiplyByCoverage256(r , cov) , KGRGBA8888MultiplyByCoverage256(d , oneMinusCov));
}
}
static void KGApplyCoverageToSpan_lRGBA8888_PRE(KGRGBA8888 *dst,int coverage256,KGRGBA8888 *result,int length){
int i;
int coverage=coverage256;
int oneMinusCoverage=256-coverage256;
for(i=0;i<length;i++){
KGRGBA8888 r=result[i];
KGRGBA8888 d=dst[i];
result[i]=KGRGBA8888Add(KGRGBA8888MultiplyByCoverage256(r , coverage) , KGRGBA8888MultiplyByCoverage256(d , oneMinusCoverage));
}
}
void KGRasterizeWriteCoverageSpan(KGRasterizer *self,int x, int y,int coverage,int length) {
if(self->_useRGBA8888){
KGRGBA8888 dst[length];
KGImageReadSpan_lRGBA8888_PRE(self->m_renderingSurface,x,y,dst,length);
KGRGBA8888 src[length];
KGPaintReadSpan_lRGBA8888_PRE(self->m_paint,x,y,src,length);
self->_blend_lRGBA8888_PRE(src,dst,length);
//apply masking
if(!self->m_mask)
KGApplyCoverageToSpan_lRGBA8888_PRE(dst,coverage,src,length);
else {
uint8_t maskSpan[length];
KGImageReadSpan_A8_MASK(self->m_mask,x,y,maskSpan,length);
KGApplyCoverageAndMaskToSpan_lRGBA8888_PRE(dst,coverage,maskSpan,src,length);
}
//write result to the destination surface
KGSurfaceWriteSpan_lRGBA8888_PRE(self->m_renderingSurface,x,y,src,length);
}
else {
KGRGBAffff dst[length];
KGImageReadSpan_lRGBAffff_PRE(self->m_renderingSurface,x,y,dst,length);
KGRGBAffff src[length];
KGPaintReadSpan_lRGBAffff_PRE(self->m_paint,x,y,src,length);
self->_blend_lRGBAffff_PRE(src,dst,length);
//apply masking
if(!self->m_mask)
KGApplyCoverageToSpan_lRGBAffff_PRE(dst,coverage,src,length);
else {
CGFloat maskSpan[length];
KGImageReadSpan_Af_MASK(self->m_mask,x,y,maskSpan,length);
KGApplyCoverageAndMaskToSpan_lRGBAffff_PRE(dst,coverage,maskSpan,src,length);
}
//write result to the destination surface
KGSurfaceWriteSpan_lRGBAffff_PRE(self->m_renderingSurface,x,y,src,length);
}
}
@end

View File

@ -42,6 +42,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
KGColor *_shadowColor;
BOOL _shouldAntialias;
int _antialiasingQuality;
float _wordSpacing;
float _textLeading;
}
@ -108,7 +109,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
-(void)setShouldAntialias:(BOOL)flag;
// temporary?
-(void)setAntialiasingQuality:(int)value;
-(void)setWordSpacing:(float)spacing;
-(void)setTextLeading:(float)leading;

View File

@ -30,6 +30,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
_blendMode=kCGBlendModeNormal;
_interpolationQuality=kCGInterpolationDefault;
_shouldAntialias=NO;
_antialiasingQuality=64;
return self;
}
@ -298,6 +299,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
// temporary
-(void)setAntialiasingQuality:(int)value {
_antialiasingQuality=value;
}
-(void)setWordSpacing:(float)spacing {
_wordSpacing=spacing;
}

View File

@ -4,7 +4,7 @@
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
* Copyright (c) 2007-2008 Christopher J. W. Lloyd
* Copyright (c) 2008 Christopher J. W. Lloyd
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
@ -187,20 +187,38 @@ static inline KGRGBA8888 KGRGBA8888FromKGRGBAffff(KGRGBAffff rgba){
return result;
}
static inline KGRGBA8888 KGRGBA8888MultiplyByCoverage256(KGRGBA8888 result,int value){
result.r=((int)result.r*value)/256;
result.g=((int)result.g*value)/256;
result.b=((int)result.b*value)/256;
result.a=((int)result.a*value)/256;
#define COVERAGE_MULTIPLIER 256
static inline CGFloat zeroToOneFromCoverage(int coverage){
return (CGFloat)coverage/(CGFloat)COVERAGE_MULTIPLIER;
}
static inline CGFloat coverageFromZeroToOne(CGFloat value){
return value*COVERAGE_MULTIPLIER;
}
static inline int inverseCoverage(int coverage){
return COVERAGE_MULTIPLIER-coverage;
}
static inline int multiplyByCoverage(int value,int coverage){
return (value*coverage)/COVERAGE_MULTIPLIER;
}
static inline KGRGBA8888 KGRGBA8888MultiplyByCoverage(KGRGBA8888 result,int value){
result.r=((int)result.r*value)/COVERAGE_MULTIPLIER;
result.g=((int)result.g*value)/COVERAGE_MULTIPLIER;
result.b=((int)result.b*value)/COVERAGE_MULTIPLIER;
result.a=((int)result.a*value)/COVERAGE_MULTIPLIER;
return result;
}
static inline KGRGBA8888 KGRGBA8888Add(KGRGBA8888 result,KGRGBA8888 other){
result.r=RI_INT_CLAMP((int)result.r+(int)other.r,0,255);
result.g=RI_INT_CLAMP((int)result.g+(int)other.g,0,255);
result.b=RI_INT_CLAMP((int)result.b+(int)other.b,0,255);
result.a=RI_INT_CLAMP((int)result.a+(int)other.a,0,255);
result.r=MIN((int)result.r+(int)other.r,255);
result.g=MIN((int)result.g+(int)other.g,255);
result.b=MIN((int)result.b+(int)other.b,255);
result.a=MIN((int)result.a+(int)other.a,255);
return result;
}
@ -208,6 +226,8 @@ static inline KGRGBA8888 KGRGBA8888Add(KGRGBA8888 result,KGRGBA8888 other){
typedef void (*KGImageReadSpan_RGBA8888)(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
typedef void (*KGImageReadSpan_RGBAffff)(KGImage *self,int x,int y,KGRGBAffff *span,int length);
typedef void (*KGImageReadSpan_A8)(KGImage *self,int x,int y,uint8_t *span,int length);
typedef void (*KGImageReadSpan_Af)(KGImage *self,int x,int y,CGFloat *span,int length);
@interface KGImage : NSObject <NSCopying> {
@public
@ -233,7 +253,9 @@ typedef void (*KGImageReadSpan_RGBAffff)(KGImage *self,int x,int y,KGRGBAffff *s
KGImageReadSpan_RGBA8888 _readRGBA8888;
KGImageReadSpan_RGBAffff _readRGBAffff;
KGImageReadSpan_RGBA8888 _readA8;
KGImageReadSpan_RGBAffff _readAf;
VGPixelDecode m_desc;
BOOL m_ownsData;
BOOL m_mipmapsValid;
@ -242,7 +264,7 @@ typedef void (*KGImageReadSpan_RGBAffff)(KGImage *self,int x,int y,KGRGBAffff *s
struct KGSurface **_mipmaps;
}
-initWithWidth:(size_t)width height:(size_t)height bitsPerComponent:(size_t)bitsPerComponent bitsPerPixel:(size_t)bitsPerPixel bytesPerRow:(size_t)bytesPerRow colorSpace:(KGColorSpace *)colorSpace bitmapInfo:(unsigned)bitmapInfo provider:(KGDataProvider *)provider decode:(const CGFloat *)decode interpolate:(BOOL)interpolate renderingIntent:(CGColorRenderingIntent)renderingIntent;
-initWithWidth:(size_t)width height:(size_t)height bitsPerComponent:(size_t)bitsPerComponent bitsPerPixel:(size_t)bitsPerPixel bytesPerRow:(size_t)bytesPerRow colorSpace:(KGColorSpace *)colorSpace bitmapInfo:(CGBitmapInfo)bitmapInfo provider:(KGDataProvider *)provider decode:(const CGFloat *)decode interpolate:(BOOL)interpolate renderingIntent:(CGColorRenderingIntent)renderingIntent;
-initMaskWithWidth:(size_t)width height:(size_t)height bitsPerComponent:(size_t)bitsPerComponent bitsPerPixel:(size_t)bitsPerPixel bytesPerRow:(size_t)bytesPerRow provider:(KGDataProvider *)provider decode:(const float *)decode interpolate:(BOOL)interpolate ;
@ -291,6 +313,7 @@ void KGImageRead_G8_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int l
void KGImageRead_GA88_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
void KGImageRead_RGBA8888_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
void KGImageRead_ABGR8888_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
void KGImageRead_G3B5X1R5G2_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
void KGImageRead_RGBA4444_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
void KGImageRead_BARG4444_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
void KGImageRead_RGBA2222_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
@ -309,12 +332,12 @@ void KGImageReadSpan_Af_MASK(KGImage *self,int x,int y,CGFloat *coverage,int len
void KGImageReadTileSpanExtendEdge__lRGBA8888_PRE(KGImage *self,int u, int v, KGRGBA8888 *span,int length);
void KGImageReadTileSpanExtendEdge__lRGBAffff_PRE(KGImage *self,int u, int v, KGRGBAffff *span,int length);
void KGImageEWAOnMipmaps_lRGBAffff_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage);
void KGImageBicubic_lRGBA8888_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage);
void KGImageBicubic_lRGBAffff_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage);
void KGImageBilinear_lRGBA8888_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage);
void KGImageBilinear_lRGBAffff_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage);
void KGImagePointSampling_lRGBA8888_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage);
void KGImagePointSampling_lRGBAffff_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage);
void KGImageEWAOnMipmaps_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage);
void KGImageBicubic_lRGBA8888_PRE(KGImage *self,int x, int y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage);
void KGImageBicubic_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage);
void KGImageBilinear_lRGBA8888_PRE(KGImage *self,int x, int y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage);
void KGImageBilinear_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage);
void KGImagePointSampling_lRGBA8888_PRE(KGImage *self,int x, int y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage);
void KGImagePointSampling_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage);
void KGImageReadPatternSpan_lRGBAffff_PRE(KGImage *self,CGFloat x, CGFloat y, KGRGBAffff *span,int length, CGAffineTransform surfaceToImage, CGPatternTiling distortion);

View File

@ -4,7 +4,7 @@
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
* Copyright (c) 2007-2008 Christopher J. W. Lloyd
* Copyright (c) 2008 Christopher J. W. Lloyd
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
@ -194,6 +194,19 @@ static BOOL initFunctionsForParameters(KGImage *self,size_t bitsPerComponent,siz
break;
}
break;
case 5:
switch(bitsPerPixel){
case 16:
if(bitmapInfo==(kCGBitmapByteOrder16Little|kCGImageAlphaNoneSkipFirst)){
self->_readRGBA8888=KGImageRead_G3B5X1R5G2_to_RGBA8888;
self->_readRGBAffff=KGImageRead_ANY_to_RGBA8888_to_RGBAffff;
break;
}
break;
}
break;
case 4:
switch(bitsPerPixel){
@ -781,6 +794,27 @@ void KGImageRead_ABGR8888_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span
}
}
// kCGBitmapByteOrder16Little|kCGImageAlphaNoneSkipFirst
void KGImageRead_G3B5X1R5G2_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length){
RIuint8 *scanline = self->_bytes + y * self->_bytesPerRow;
int i;
scanline+=x*2;
for(i=0;i<length;i++){
unsigned short low=*scanline++;
unsigned short high=*scanline;
unsigned short value=low|(high<<8);
KGRGBA8888 result;
result.r = ((value>>10)&0x1F)<<3;
result.g = ((value>>5)&0x1F)<<3;
result.b = ((value&0x1F)<<3);
result.a = 255;
scanline++;
*span++=result;
}
}
void KGImageRead_RGBA4444_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length){
RIuint8 *scanline = self->_bytes + y * self->_bytesPerRow;
int i;
@ -1038,7 +1072,7 @@ KGImage *KGImageMipMapForLevel(KGImage *self,int level){
}
void KGImageEWAOnMipmaps_lRGBAffff_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
void KGImageEWAOnMipmaps_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
int i;
CGFloat m_pixelFilterRadius = 1.25f;
CGFloat m_resamplingFilterRadius = 1.25f;
@ -1188,7 +1222,7 @@ static inline int cubic_8(int v0,int v1,int v2,int v3,int fraction){
int p = (v3 - v2) - (v0 - v1);
int q = (v0 - v1) - p;
return RI_INT_CLAMP((p * (fraction*fraction*fraction))/(255*255*255) + (q * fraction*fraction)/(255*255) + ((v2 - v0) * fraction)/255 + v1,0,255);
return RI_INT_CLAMP((p * (fraction*fraction*fraction))/(256*256*256) + (q * fraction*fraction)/(256*256) + ((v2 - v0) * fraction)/256 + v1,0,255);
}
KGRGBA8888 bicubic_lRGBA8888_PRE(KGRGBA8888 a,KGRGBA8888 b,KGRGBA8888 c,KGRGBA8888 d,int fraction) {
@ -1199,7 +1233,7 @@ KGRGBA8888 bicubic_lRGBA8888_PRE(KGRGBA8888 a,KGRGBA8888 b,KGRGBA8888 c,KGRGBA88
cubic_8(a.a, b.a, c.a, d.a, fraction));
}
void KGImageBicubic_lRGBA8888_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage){
void KGImageBicubic_lRGBA8888_PRE(KGImage *self,int x, int y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage){
int i;
for(i=0;i<length;i++,x++){
@ -1209,10 +1243,10 @@ void KGImageBicubic_lRGBA8888_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBA8888
uv.x -= 0.5f;
uv.y -= 0.5f;
int u = RI_FLOOR_TO_INT(uv.x);
int ufrac=(uv.x-u)*255;
int ufrac=coverageFromZeroToOne(uv.x-u);
int v = RI_FLOOR_TO_INT(uv.y);
int vfrac=(uv.y-v)*255;
int vfrac=coverageFromZeroToOne(uv.y-v);
KGRGBA8888 t0,t1,t2,t3;
KGRGBA8888 cspan[4];
@ -1248,7 +1282,7 @@ KGRGBAffff bicubic_lRGBAffff_PRE(KGRGBAffff a,KGRGBAffff b,KGRGBAffff c,KGRGBAff
cubic_f(a.a, b.a, c.a, d.a, fraction));
}
void KGImageBicubic_lRGBAffff_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
void KGImageBicubic_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
int i;
for(i=0;i<length;i++,x++){
@ -1282,7 +1316,7 @@ void KGImageBicubic_lRGBAffff_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff
}
}
void KGImageBilinear_lRGBA8888_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage){
void KGImageBilinear_lRGBA8888_PRE(KGImage *self,int x, int y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage){
int i;
for(i=0;i<length;i++,x++){
@ -1299,16 +1333,18 @@ void KGImageBilinear_lRGBA8888_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBA8888
KGRGBA8888 c01c11[2];
KGImageReadTileSpanExtendEdge__lRGBA8888_PRE(self,u,v+1,c01c11,2);
CGFloat fu = uv.x - (CGFloat)u;
CGFloat fv = uv.y - (CGFloat)v;
KGRGBA8888 c0 = KGRGBA8888Add(KGRGBA8888MultiplyByCoverage256(c00c01[0],(1.0f - fu)*256),KGRGBA8888MultiplyByCoverage256(c00c01[1],fu*256));
KGRGBA8888 c1 = KGRGBA8888Add(KGRGBA8888MultiplyByCoverage256(c01c11[0],(1.0f - fu)*256),KGRGBA8888MultiplyByCoverage256(c01c11[1],fu*256));
span[i]=KGRGBA8888Add(KGRGBA8888MultiplyByCoverage256(c0,(1.0f - fv)*256),KGRGBA8888MultiplyByCoverage256(c1, fv*256));
int fu = coverageFromZeroToOne(uv.x - (CGFloat)u);
int oneMinusFu=inverseCoverage(fu);
int fv = coverageFromZeroToOne(uv.y - (CGFloat)v);
int oneMinusFv=inverseCoverage(fv);
KGRGBA8888 c0 = KGRGBA8888Add(KGRGBA8888MultiplyByCoverage(c00c01[0],oneMinusFu),KGRGBA8888MultiplyByCoverage(c00c01[1],fu));
KGRGBA8888 c1 = KGRGBA8888Add(KGRGBA8888MultiplyByCoverage(c01c11[0],oneMinusFu),KGRGBA8888MultiplyByCoverage(c01c11[1],fu));
span[i]=KGRGBA8888Add(KGRGBA8888MultiplyByCoverage(c0,oneMinusFv),KGRGBA8888MultiplyByCoverage(c1, fv));
}
}
void KGImageBilinear_lRGBAffff_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
void KGImageBilinear_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
int i;
for(i=0;i<length;i++,x++){
@ -1333,7 +1369,7 @@ void KGImageBilinear_lRGBAffff_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff
}
}
void KGImagePointSampling_lRGBA8888_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage){
void KGImagePointSampling_lRGBA8888_PRE(KGImage *self,int x, int y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage){
int i;
for(i=0;i<length;i++,x++){
@ -1344,7 +1380,7 @@ void KGImagePointSampling_lRGBA8888_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGB
}
}
void KGImagePointSampling_lRGBAffff_PRE(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
void KGImagePointSampling_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
int i;
for(i=0;i<length;i++,x++){

View File

@ -95,18 +95,18 @@ static void bezier(KGGraphicsState *self,double x1,double y1,double x2, double y
_numberOfPoints=0;
}
static void expandOperatorCapacity(KGMutablePath *self,unsigned delta){
static inline void expandOperatorCapacity(KGMutablePath *self,unsigned delta){
if(self->_numberOfElements+delta>self->_capacityOfElements){
self->_capacityOfElements=self->_numberOfElements+delta;
self->_capacityOfElements=(self->_capacityOfElements/16+1)*16;
self->_capacityOfElements=(self->_capacityOfElements/32+1)*32;
self->_elements=NSZoneRealloc(NULL,self->_elements,self->_capacityOfElements);
}
}
static void expandPointCapacity(KGMutablePath *self,unsigned delta){
static inline void expandPointCapacity(KGMutablePath *self,unsigned delta){
if(self->_numberOfPoints+delta>self->_capacityOfPoints){
self->_capacityOfPoints=self->_numberOfPoints+delta;
self->_capacityOfPoints=(self->_capacityOfPoints/32+1)*32;
self->_capacityOfPoints=(self->_capacityOfPoints/64+1)*64;
self->_points=NSZoneRealloc(NULL,self->_points,self->_capacityOfPoints*sizeof(CGPoint));
}
}

View File

@ -44,7 +44,14 @@ typedef void (*KGPaintReadSpan_lRGBAffff_PRE_function)(KGPaint *self,int x,int y
-init;
void KGPaintSetSurfaceToPaintMatrix(KGPaint *self,CGAffineTransform surfaceToPaintMatrix);
void KGPaintReadSpan_lRGBA8888_PRE(KGPaint *self,int x,int y,KGRGBA8888 *span,int length);
void KGPaintReadSpan_lRGBAffff_PRE(KGPaint *self,int x,int y,KGRGBAffff *span,int length);
@end
static inline void KGPaintReadSpan_lRGBA8888_PRE(KGPaint *self,int x,int y,KGRGBA8888 *span,int length) {
self->_read_lRGBA8888_PRE(self,x,y,span,length);
}
static inline void KGPaintReadSpan_lRGBAffff_PRE(KGPaint *self,int x,int y,KGRGBAffff *span,int length) {
self->_read_lRGBAffff_PRE(self,x,y,span,length);
}

View File

@ -39,14 +39,5 @@ void KGPaintSetSurfaceToPaintMatrix(KGPaint *self,CGAffineTransform surfaceToPai
self->m_surfaceToPaintMatrix = surfaceToPaintMatrix;
}
void KGPaintReadSpan_lRGBA8888_PRE(KGPaint *self,int x,int y,KGRGBA8888 *span,int length) {
self->_read_lRGBA8888_PRE(self,x,y,span,length);
}
void KGPaintReadSpan_lRGBAffff_PRE(KGPaint *self,int x,int y,KGRGBAffff *span,int length) {
self->_read_lRGBAffff_PRE(self,x,y,span,length);
}
@end

View File

@ -10,8 +10,8 @@
<integer>5</integer>
<key>IBOpenObjects</key>
<array>
<integer>2</integer>
<integer>29</integer>
<integer>21</integer>
</array>
<key>IBSystem Version</key>
<string>9D34</string>

View File

@ -78,8 +78,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
unsigned char *kgData=[_kgContext bytes];
char *diff=NSZoneMalloc([self zone],[_kgContext bytesPerRow]*[_kgContext pixelsHigh]);
int i;
for(i=0;i<[_kgContext bytesPerRow]*[_kgContext pixelsHigh];i++){
int i,max=[_kgContext bytesPerRow]*[_kgContext pixelsHigh];
for(i=0;i<max;i++){
int d1=cgData[i];
int d2=kgData[i];

View File

@ -12,6 +12,7 @@
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
FE0997430D87095000033630 /* overlay.png in Resources */ = {isa = PBXBuildFile; fileRef = FE0997420D87095000033630 /* overlay.png */; };
FE11A3C70DFA3DB900356918 /* libSaturn.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FE11A3C60DFA3DB900356918 /* libSaturn.dylib */; };
FE14EC4B0DBD9BF00070928C /* DemoCGContext.m in Sources */ = {isa = PBXBuildFile; fileRef = FE14EC490DBD9BF00070928C /* DemoCGContext.m */; };
FE14EC4C0DBD9BF00070928C /* DemoKGContext.m in Sources */ = {isa = PBXBuildFile; fileRef = FE14EC4A0DBD9BF00070928C /* DemoKGContext.m */; };
FE14EC960DBDA5420070928C /* DemoContext.m in Sources */ = {isa = PBXBuildFile; fileRef = FE14EC950DBDA5420070928C /* DemoContext.m */; };
@ -100,6 +101,7 @@
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
8D1107320486CEB800E47090 /* SWRender.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SWRender.app; sourceTree = BUILT_PRODUCTS_DIR; };
FE0997420D87095000033630 /* overlay.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = overlay.png; sourceTree = "<group>"; };
FE11A3C60DFA3DB900356918 /* libSaturn.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libSaturn.dylib; path = /usr/lib/libSaturn.dylib; sourceTree = "<absolute>"; };
FE1474D20DB44967001B5634 /* KGBlending.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KGBlending.h; path = ../../AppKit/CoreGraphics.subproj/KGBlending.h; sourceTree = "<group>"; };
FE14EC480DBD9BF00070928C /* DemoContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoContext.h; sourceTree = "<group>"; };
FE14EC490DBD9BF00070928C /* DemoCGContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoCGContext.m; sourceTree = "<group>"; };
@ -239,6 +241,7 @@
buildActionMask = 2147483647;
files = (
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
FE11A3C70DFA3DB900356918 /* libSaturn.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -273,6 +276,7 @@
29B97314FDCFA39411CA2CEA /* SWRender */ = {
isa = PBXGroup;
children = (
FE11A3C60DFA3DB900356918 /* libSaturn.dylib */,
FE21384A0DC2303100CEDC65 /* ImageIO */,
FE14EC950DBDA5420070928C /* DemoContext.m */,
FE14EC480DBD9BF00070928C /* DemoContext.h */,
@ -614,11 +618,11 @@
GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_ENABLE_CPP_RTTI = NO;
GCC_ENABLE_SSE3_EXTENSIONS = YES;
GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = NO;
GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO;
GCC_MODEL_TUNING = "";
GCC_OPTIMIZATION_LEVEL = s;
GCC_OPTIMIZATION_LEVEL = 3;
GCC_UNROLL_LOOPS = YES;
GCC_VERSION = 4.2;
GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
@ -630,7 +634,7 @@
GENERATE_PROFILING_CODE = NO;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Applications";
OTHER_LDFLAGS = "";
OTHER_LDFLAGS = "-lgcov";
PRODUCT_NAME = SWRender;
SDKROOT = "";
WRAPPER_EXTENSION = app;