- added NSColor private method to generate a CGColorRef

- NSShadow set now does the proper CG calls instead of raise exception, but the underlying CG to draw shadows is not present
- added CGColorSpaceCreateDeviceGray(), CGColorSpaceCreateDeviceCMYK() functions
- Gaussian blur work for shadows
This commit is contained in:
Christopher Lloyd 2008-09-05 19:17:18 +00:00
parent 9567075ce6
commit b8ef1a6601
26 changed files with 355 additions and 165 deletions

View File

@ -722,6 +722,7 @@
FEDF95200CAF43E7009DC96F /* KGPDFContext.m in Sources */ = {isa = PBXBuildFile; fileRef = FEDF951C0CAF43E7009DC96F /* KGPDFContext.m */; };
FEF2EC350C891E7C001FC5A8 /* NSOpenGLDrawable_gdiView.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF2EC330C891E7C001FC5A8 /* NSOpenGLDrawable_gdiView.h */; settings = {ATTRIBUTES = (Private, ); }; };
FEF2EC7B0C8A03CC001FC5A8 /* NSOpenGLDrawable_gdiView.m in Sources */ = {isa = PBXBuildFile; fileRef = FEF2EC790C8A03CC001FC5A8 /* NSOpenGLDrawable_gdiView.m */; };
FEF35E270E6DC186000BD639 /* NSColor-Private.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF35E260E6DC186000BD639 /* NSColor-Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
FEF9CAE90E133FF2003502ED /* KGSurface_DIBSection.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF9CAE70E133FF2003502ED /* KGSurface_DIBSection.h */; };
FEF9CAEA0E133FF2003502ED /* KGSurface_DIBSection.m in Sources */ = {isa = PBXBuildFile; fileRef = FEF9CAE80E133FF2003502ED /* KGSurface_DIBSection.m */; };
FEF9CB9F0E13EB8E003502ED /* KGColorSpace+PDF.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF9CB780E13EB8E003502ED /* KGColorSpace+PDF.h */; };
@ -1529,6 +1530,7 @@
FEF2EC790C8A03CC001FC5A8 /* NSOpenGLDrawable_gdiView.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = NSOpenGLDrawable_gdiView.m; sourceTree = "<group>"; };
FEF33BFF0B93543C00DC0B6F /* KGMutablePath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGMutablePath.h; sourceTree = "<group>"; };
FEF33C000B93543C00DC0B6F /* KGMutablePath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGMutablePath.m; sourceTree = "<group>"; };
FEF35E260E6DC186000BD639 /* NSColor-Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSColor-Private.h"; sourceTree = "<group>"; };
FEF9CAE70E133FF2003502ED /* KGSurface_DIBSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGSurface_DIBSection.h; sourceTree = "<group>"; };
FEF9CAE80E133FF2003502ED /* KGSurface_DIBSection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGSurface_DIBSection.m; sourceTree = "<group>"; };
FEF9CB780E13EB8E003502ED /* KGColorSpace+PDF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KGColorSpace+PDF.h"; sourceTree = "<group>"; };
@ -1956,6 +1958,7 @@
6E2B55430976075300DA0954 /* NSColor */ = {
isa = PBXGroup;
children = (
FEF35E260E6DC186000BD639 /* NSColor-Private.h */,
FE08C3210DDF299800B3169A /* NSColor_CGColor.h */,
FE08C3220DDF299800B3169A /* NSColor_CGColor.m */,
6E2B55620976075300DA0954 /* conversions.h */,
@ -2950,6 +2953,7 @@
FEF9CBC20E13EB8E003502ED /* KGImage+PDF.h in Headers */,
FEF9CBC40E13EB8E003502ED /* KGShading+PDF.h in Headers */,
FEF9CCC30E1416C4003502ED /* KGContext_builtin_gdi.h in Headers */,
FEF35E270E6DC186000BD639 /* NSColor-Private.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -16,3 +16,11 @@ void CGColorSpaceRelease(CGColorSpaceRef colorSpace) {
CGColorSpaceRef CGColorSpaceCreateDeviceRGB() {
return [[KGColorSpace alloc] initWithDeviceRGB];
}
CGColorSpaceRef CGColorSpaceCreateDeviceGray() {
return [[KGColorSpace alloc] initWithDeviceGray];
}
CGColorSpaceRef CGColorSpaceCreateDeviceCMYK() {
return [[KGColorSpace alloc] initWithDeviceCMYK];
}

View File

@ -59,20 +59,23 @@ typedef struct Edge {
typedef void (*KGBlendSpan_RGBA8888)(KGRGBA8888 *src,KGRGBA8888 *dst,int length);
typedef void (*KGBlendSpan_RGBAffff)(KGRGBAffff *src,KGRGBAffff *dst,int length);
typedef void (*KGWriteCoverage_RGBA8888)(KGSurface *surface,KGSurface *mask,KGPaint *paint,int x, int y,int coverage,int length,KGBlendSpan_RGBA8888 blendFunction);
@class KGSurface,KGContext_builtin;
#define KGRasterizer KGContext_builtin
@interface KGContext_builtin : KGBitmapContext {
KGSurface *m_mask;
KGPaint *m_paint;
BOOL _useRGBA8888;
CGBlendMode _blendMode;
KGBlendSpan_RGBA8888 _blend_lRGBA8888_PRE;
KGBlendSpan_RGBAffff _blend_lRGBAffff_PRE;
KGBlendSpan_RGBA8888 _blend_lRGBA8888_PRE;
KGBlendSpan_RGBAffff _blend_lRGBAffff_PRE;
KGWriteCoverage_RGBA8888 _writeCoverage_lRGBA8888_PRE;
void (*_blendFunction)();
void (*_writeCoverageFunction)();
int _vpx,_vpy,_vpwidth,_vpheight;
int _edgeCount;
@ -98,7 +101,7 @@ void KGRasterizerSetViewport(KGRasterizer *self,int x,int y,int vpwidth,int vphe
void KGRasterizerClear(KGRasterizer *self);
void KGRasterizerAddEdge(KGRasterizer *self,const CGPoint v0, const CGPoint v1);
void KGRasterizerSetShouldAntialias(KGRasterizer *self,BOOL antialias,int quality);
void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRule);
void KGRasterizerFill(KGRasterizer *self,int fillRule);
void KGRasterizeSetBlendMode(KGRasterizer *self,CGBlendMode blendMode);
void KGRasterizeSetMask(KGRasterizer *self,KGSurface* mask);

View File

@ -623,17 +623,25 @@ static void KGApplyCoverageAndMaskToSpan_lRGBA8888_PRE(KGRGBA8888 *dst,int icove
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;
if(coverage==256){
for(i=0;i<length;i++,src++,dst++){
*dst=*src;
}
}
else {
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));
*dst=KGRGBA8888Add(KGRGBA8888MultiplyByCoverage(r , coverage) , KGRGBA8888MultiplyByCoverage(d , oneMinusCoverage));
}
}
}
static void KGBlendSpanNormal_8888_coverage(KGRGBA8888 *src,KGRGBA8888 *dst,int coverage,int length){
static inline void KGBlendSpanNormal_8888_coverage(KGRGBA8888 *src,KGRGBA8888 *dst,int coverage,int length){
// Passes Visual Test
int i;
@ -646,10 +654,12 @@ static void KGBlendSpanNormal_8888_coverage(KGRGBA8888 *src,KGRGBA8888 *dst,int
if(s.a==255)
r=*src;
else {
r.r=RI_INT_MIN((int)s.r+((int)d.r*(255-s.a))/255,255);
r.g=RI_INT_MIN((int)s.g+((int)d.g*(255-s.a))/255,255);
r.b=RI_INT_MIN((int)s.b+((int)d.b*(255-s.a))/255,255);
r.a=RI_INT_MIN((int)s.a+((int)d.a*(255-s.a))/255,255);
int sa=255-s.a;
r.r=RI_INT_MIN((int)s.r+((int)d.r*sa)/255,255);
r.g=RI_INT_MIN((int)s.g+((int)d.g*sa)/255,255);
r.b=RI_INT_MIN((int)s.b+((int)d.b*sa)/255,255);
r.a=RI_INT_MIN((int)s.a+((int)d.a*sa)/255,255);
}
*dst=r;
}
@ -692,8 +702,8 @@ static void KGBlendSpanCopy_8888_coverage(KGRGBA8888 *src,KGRGBA8888 *dst,int co
int i;
if(coverage==256){
for(i=0;i<length;i++,src++,dst++)
*dst=*src;
for(i=0;i<length;i++)
*dst++=*src++;
}
else {
int oneMinusCoverage=256-coverage;
@ -723,77 +733,102 @@ static void KGBlendSpanCopy_8888_coverage(KGRGBA8888 *src,KGRGBA8888 *dst,int co
}
}
static inline void KGRasterizeWriteCoverageSpan(KGRasterizer *self,int x, int y,int coverage,int length) {
if(self->_useRGBA8888){
static inline void KGRasterizeWriteCoverageSpan8888_Normal(KGSurface *surface,KGSurface *mask,KGPaint *paint,int x, int y,int coverage,int length,KGBlendSpan_RGBA8888 blendFunction) {
KGRGBA8888 *dst=__builtin_alloca(length*sizeof(KGRGBA8888));
KGRGBA8888 *direct=self->_surface->_read_lRGBA8888_PRE(self->_surface,x,y,dst,length);
KGRGBA8888 *direct=surface->_read_lRGBA8888_PRE(surface,x,y,dst,length);
if(direct!=NULL)
dst=direct;
KGRGBA8888 src[length];
KGPaintReadSpan_lRGBA8888_PRE(self->m_paint,x,y,src,length);
KGPaintReadSpan_lRGBA8888_PRE(paint,x,y,src,length);
switch(self->_blendMode){
case kCGBlendModeNormal:
KGBlendSpanNormal_8888_coverage(src,dst,coverage,length);
break;
KGBlendSpanNormal_8888_coverage(src,dst,coverage,length);
// FIXME: doesnt handle mask if present
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;
}
if(direct==NULL){
//write result to the destination surface
KGSurfaceWriteSpan_lRGBA8888_PRE(self->_surface,x,y,dst,length);
KGSurfaceWriteSpan_lRGBA8888_PRE(surface,x,y,dst,length);
}
}
}
static inline void KGRasterizeWriteCoverageSpan8888_Copy(KGSurface *surface,KGSurface *mask,KGPaint *paint,int x, int y,int coverage,int length,KGBlendSpan_RGBA8888 blendFunction) {
KGRGBA8888 *dst=__builtin_alloca(length*sizeof(KGRGBA8888));
KGRGBA8888 *direct=surface->_read_lRGBA8888_PRE(surface,x,y,dst,length);
if(direct!=NULL)
dst=direct;
KGRGBA8888 src[length];
KGPaintReadSpan_lRGBA8888_PRE(paint,x,y,src,length);
KGBlendSpanCopy_8888_coverage(src,dst,coverage,length);
// FIXME: doesnt handle mask if present
if(direct==NULL){
//write result to the destination surface
KGSurfaceWriteSpan_lRGBA8888_PRE(surface,x,y,dst,length);
}
}
static inline void KGRasterizeWriteCoverageSpan8888(KGSurface *surface,KGSurface *mask,KGPaint *paint,int x, int y,int coverage,int length,KGBlendSpan_RGBA8888 blendFunction) {
KGRGBA8888 *dst=__builtin_alloca(length*sizeof(KGRGBA8888));
KGRGBA8888 *direct=surface->_read_lRGBA8888_PRE(surface,x,y,dst,length);
if(direct!=NULL)
dst=direct;
KGRGBA8888 src[length];
KGPaintReadSpan_lRGBA8888_PRE(paint,x,y,src,length);
blendFunction(src,dst,length);
//apply masking
if(mask==NULL)
KGApplyCoverageToSpan_lRGBA8888_PRE(dst,coverage,src,length);
else {
uint8_t maskSpan[length];
KGImageReadSpan_A8_MASK(mask,x,y,maskSpan,length);
KGApplyCoverageAndMaskToSpan_lRGBA8888_PRE(dst,coverage,maskSpan,src,length);
}
if(direct==NULL){
//write result to the destination surface
KGSurfaceWriteSpan_lRGBA8888_PRE(surface,x,y,dst,length);
}
}
static inline void KGRasterizeWriteCoverageSpanffff(KGSurface *surface,KGSurface *mask,KGPaint *paint,int x, int y,int coverage,int length,KGBlendSpan_RGBAffff blendFunction) {
KGRGBAffff *dst=__builtin_alloca(length*sizeof(KGRGBAffff));
KGRGBAffff *direct=KGImageReadSpan_lRGBAffff_PRE(self->_surface,x,y,dst,length);
KGRGBAffff *direct=KGImageReadSpan_lRGBAffff_PRE(surface,x,y,dst,length);
if(direct!=NULL)
dst=direct;
KGRGBAffff src[length];
KGPaintReadSpan_lRGBAffff_PRE(self->m_paint,x,y,src,length);
KGPaintReadSpan_lRGBAffff_PRE(paint,x,y,src,length);
self->_blend_lRGBAffff_PRE(src,dst,length);
blendFunction(src,dst,length);
//apply masking
if(!self->m_mask)
if(mask==NULL)
KGApplyCoverageToSpan_lRGBAffff_PRE(dst,coverage,src,length);
else {
CGFloat maskSpan[length];
KGImageReadSpan_Af_MASK(self->m_mask,x,y,maskSpan,length);
KGImageReadSpan_Af_MASK(mask,x,y,maskSpan,length);
KGApplyCoverageAndMaskToSpan_lRGBAffff_PRE(dst,coverage,maskSpan,src,length);
}
if(direct==NULL){
//write result to the destination surface
KGSurfaceWriteSpan_lRGBAffff_PRE(self->_surface,x,y,dst,length);
KGSurfaceWriteSpan_lRGBAffff_PRE(surface,x,y,dst,length);
}
}
}
void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
void KGRasterizerFill(KGRasterizer *self,int fillRuleMask) {
int edgeCount=self->_edgeCount;
Edge **edges=self->_edges;
@ -812,7 +847,7 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
int *increase=self->_increase;
int numberOfSamples=self->numSamples;
int shiftNumberOfSamples=self->sampleSizeShift;
CGFloat sidePre[numberOfSamples];
CGFloat sidePre[numberOfSamples];
for(scany=self->_vpy;scany<ylimit;scany++){
Edge *edge,*previous=NULL;
@ -851,7 +886,7 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
CGFloat normalY=edge->normal.y;
int belowY=0;
int aboveY;
for(;sampleY<v0y && pre<preEnd;sampleY+=sampleDeltaY,samplesX++){
pre++;
belowY++;
@ -902,8 +937,8 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
if(pcxnormal<=*pre++)
*windptr+++=direction;
else {
leftOfEdge++;
windptr++;
leftOfEdge++;
}
}
@ -951,7 +986,10 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
for(;windptr<windend;) {
// using ? with 0 is faster than not
coverage +=((*windptr+++accum) & fillRuleMask)?weight:0;
coverage +=(((*windptr+accum) & fillRuleMask)?weight:0);
windptr++;
}
accum+=increase[scanx];
@ -964,7 +1002,7 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
}
if(coverage>0){
KGRasterizeWriteCoverageSpan(self,scanx,scany,coverage,(advance-scanx));
self->_writeCoverageFunction(self->_surface,self->m_mask,self->m_paint,scanx,scany,coverage,(advance-scanx),self->_blendFunction);
coverage=0;
}
@ -976,15 +1014,15 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRuleMask fillRuleMask) {
void KGRasterizeSetBlendMode(KGRasterizer *self,CGBlendMode blendMode) {
RI_ASSERT(blendMode >= kCGBlendModeNormal && blendMode <= kCGBlendModePlusLighter);
self->_blendMode=blendMode;
self->_useRGBA8888=NO;
self->_blend_lRGBA8888_PRE=NULL;
self->_writeCoverage_lRGBA8888_PRE=NULL;
switch(blendMode){
case kCGBlendModeNormal:
self->_useRGBA8888=YES;
self->_blend_lRGBA8888_PRE=KGBlendSpanNormal_8888;
self->_blend_lRGBAffff_PRE=KGBlendSpanNormal_ffff;
self->_writeCoverage_lRGBA8888_PRE=KGRasterizeWriteCoverageSpan8888_Normal;
break;
case kCGBlendModeMultiply:
@ -1048,19 +1086,17 @@ void KGRasterizeSetBlendMode(KGRasterizer *self,CGBlendMode blendMode) {
break;
case kCGBlendModeClear:
self->_useRGBA8888=YES;
self->_blend_lRGBA8888_PRE=KGBlendSpanClear_8888;
self->_blend_lRGBAffff_PRE=KGBlendSpanClear_ffff;
break;
case kCGBlendModeCopy:
self->_useRGBA8888=YES;
self->_blend_lRGBA8888_PRE=KGBlendSpanCopy_8888;
self->_blend_lRGBAffff_PRE=KGBlendSpanCopy_ffff;
self->_writeCoverage_lRGBA8888_PRE=KGRasterizeWriteCoverageSpan8888_Copy;
break;
case kCGBlendModeSourceIn:
self->_useRGBA8888=YES;
self->_blend_lRGBA8888_PRE=KGBlendSpanSourceIn_8888;
self->_blend_lRGBAffff_PRE=KGBlendSpanSourceIn_ffff;
break;
@ -1090,7 +1126,6 @@ void KGRasterizeSetBlendMode(KGRasterizer *self,CGBlendMode blendMode) {
break;
case kCGBlendModeXOR:
self->_useRGBA8888=YES;
self->_blend_lRGBA8888_PRE=KGBlendSpanXOR_8888;
self->_blend_lRGBAffff_PRE=KGBlendSpanXOR_ffff;
break;
@ -1100,11 +1135,25 @@ void KGRasterizeSetBlendMode(KGRasterizer *self,CGBlendMode blendMode) {
break;
case kCGBlendModePlusLighter:
self->_useRGBA8888=YES;
self->_blend_lRGBA8888_PRE=KGBlendSpanPlusLighter_8888;
self->_blend_lRGBAffff_PRE=KGBlendSpanPlusLighter_ffff;
break;
}
if(self->_writeCoverage_lRGBA8888_PRE!=NULL){
self->_blendFunction=NULL;
self->_writeCoverageFunction=self->_writeCoverage_lRGBA8888_PRE;
}
else {
if(self->_blend_lRGBA8888_PRE!=NULL){
self->_blendFunction=self->_blend_lRGBA8888_PRE;
self->_writeCoverageFunction=KGRasterizeWriteCoverageSpan8888;
}
else {
self->_blendFunction=self->_blend_lRGBAffff_PRE;
self->_writeCoverageFunction=KGRasterizeWriteCoverageSpanffff;
}
}
}
void KGRasterizeSetMask(KGRasterizer *self,KGSurface* mask) {

View File

@ -39,6 +39,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
CGSize _shadowOffset;
float _shadowBlur;
KGColor *_shadowColor;
void *_shadowKernel;
BOOL _shouldAntialias;
int _antialiasingQuality;

View File

@ -16,6 +16,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#import "KGClipPhase.h"
#import <Foundation/NSArray.h>
#import "KGExceptions.h"
#import "KGSurface.h"
@implementation KGGraphicsState
@ -49,6 +50,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
if(_dashLengths!=NULL)
NSZoneFree(NULL,_dashLengths);
[_shadowColor release];
KGGaussianKernelRelease(_shadowKernel);
[super dealloc];
}
@ -69,6 +71,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
copy->_shadowColor=[_shadowColor copyWithZone:zone];
copy->_shadowKernel=KGGaussianKernelRetain(_shadowKernel);
return copy;
}
@ -283,16 +287,17 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
[color retain];
[_shadowColor release];
_shadowColor=color;
KGGaussianKernelRelease(_shadowKernel);
_shadowKernel=(_shadowColor==nil)?NULL:KGCreateGaussianKernelWithDeviation(blur);
}
-(void)setShadowOffset:(CGSize)offset blur:(float)blur {
KGColorSpace *colorSpace=[[KGColorSpace alloc] initWithDeviceRGB];
float components[4]={0,0,0,1.0/3.0};
KGColor *color=[[KGColor alloc] initWithColorSpace:colorSpace components:components];
_shadowOffset=offset;
_shadowBlur=blur;
[_shadowColor release];
_shadowColor=[[KGColor alloc] initWithColorSpace:colorSpace components:components];
[self setShadowOffset:offset blur:blur color:color];
[color release];
[colorSpace release];
}

View File

@ -253,11 +253,17 @@ void KGSurfaceWriteFilteredPixel(KGSurface *self,int x, int y, VGColor c, VGbitf
void KGSurfaceWriteMaskPixel(KGSurface *self,int x, int y, CGFloat m); //can write only to VG_A_8
typedef struct KGGaussianKernel *KGGaussianKernelRef;
KGGaussianKernelRef KGCreateGaussianKernelWithDeviation(CGFloat stdDeviation);
KGGaussianKernelRef KGGaussianKernelRetain(KGGaussianKernelRef kernel);
void KGGaussianKernelRelease(KGGaussianKernelRef kernel);
void KGSurfaceColorMatrix(KGSurface *self,KGSurface * src, const CGFloat* matrix, BOOL filterFormatLinear, BOOL filterFormatPremultiplied, VGbitfield channelMask);
void KGSurfaceConvolve(KGSurface *self,KGSurface * src, int kernelWidth, int kernelHeight, int shiftX, int shiftY, const RIint16* kernel, CGFloat scale, CGFloat bias, VGTilingMode tilingMode, VGColor edgeFillColor, BOOL filterFormatLinear, BOOL filterFormatPremultiplied, VGbitfield channelMask);
void KGSurfaceSeparableConvolve(KGSurface *self,KGSurface * src, int kernelWidth, int kernelHeight, int shiftX, int shiftY, const RIint16* kernelX, const RIint16* kernelY, CGFloat scale, CGFloat bias, VGTilingMode tilingMode, VGColor edgeFillColor, BOOL filterFormatLinear, BOOL filterFormatPremultiplied, VGbitfield channelMask);
void KGSurfaceGaussianBlur(KGSurface *self,KGSurface * src, CGFloat stdDeviationX, CGFloat stdDeviationY, VGTilingMode tilingMode, VGColor edgeFillColor, BOOL filterFormatLinear, BOOL filterFormatPremultiplied, VGbitfield channelMask);
void KGSurfaceGaussianBlur(KGSurface *self,KGImage * src, KGGaussianKernelRef kernel);
void KGSurfaceLookup(KGSurface *self,KGSurface * src, const RIuint8 * redLUT, const RIuint8 * greenLUT, const RIuint8 * blueLUT, const RIuint8 * alphaLUT, BOOL outputLinear, BOOL outputPremultiplied, BOOL filterFormatLinear, BOOL filterFormatPremultiplied, VGbitfield channelMask);
void KGSurfaceLookupSingle(KGSurface *self,KGSurface * src, const RIuint32 * lookupTable, KGSurfaceChannel sourceChannel, BOOL outputLinear, BOOL outputPremultiplied, BOOL filterFormatLinear, BOOL filterFormatPremultiplied, VGbitfield channelMask);

View File

@ -1310,39 +1310,42 @@ void KGSurfaceSeparableConvolve(KGSurface *self,KGSurface * src, int kernelWidth
* \note
*//*-------------------------------------------------------------------*/
void KGSurfaceGaussianBlur(KGSurface *self,KGSurface * src, CGFloat stdDeviationX, CGFloat stdDeviationY, VGTilingMode tilingMode, VGColor edgeFillColor, BOOL filterFormatLinear, BOOL filterFormatPremultiplied, VGbitfield channelMask){
RI_ASSERT(src->_pixelBytes); //source exists
RI_ASSERT(self->_pixelBytes); //destination exists
static KGRGBAffff gaussianReadPixel(int x, int y, int w, int h,KGRGBAffff *image)
{
if(x < 0 || x >= w || y < 0 || y >= h) { //apply tiling mode
return KGRGBAffffInit(0,0,0,0);
}
else
{
RI_ASSERT(x >= 0 && x < w && y >= 0 && y < h);
return image[y*w+x];
}
}
typedef struct KGGaussianKernel {
int refCount;
int xSize;
int xShift;
CGFloat xScale;
CGFloat *xValues;
int ySize;
int yShift;
CGFloat yScale;
CGFloat *yValues;
} KGGaussianKernel;
KGGaussianKernel *KGCreateGaussianKernelWithDeviation(CGFloat stdDeviation){
KGGaussianKernel *kernel=NSZoneMalloc(NULL,sizeof(KGGaussianKernel));
kernel->refCount=1;
CGFloat stdDeviationX=stdDeviation;
CGFloat stdDeviationY=stdDeviation;
RI_ASSERT(stdDeviationX > 0.0f && stdDeviationY > 0.0f);
RI_ASSERT(stdDeviationX <= RI_MAX_GAUSSIAN_STD_DEVIATION && stdDeviationY <= RI_MAX_GAUSSIAN_STD_DEVIATION);
//the area to be written is an intersection of source and destination image areas.
//lower-left corners of the images are aligned.
int w = RI_INT_MIN(self->_width, src->_width);
int h = RI_INT_MIN(self->_height, src->_height);
RI_ASSERT(w > 0 && h > 0);
VGColorInternalFormat procFormat = getProcessingFormat(src->_colorFormat, filterFormatLinear, filterFormatPremultiplied);
VGColor edge = edgeFillColor;
edge=VGColorClamp(edge);
edge=VGColorConvert(edge,procFormat);
VGColor *tmp=(VGColor *)NSZoneMalloc(NULL,src->_width*src->_height*sizeof(VGColor));
//copy source region to tmp and do conversion
int j;
for(j=0;j<src->_height;j++)
{
int i;
for(i=0;i<src->_width;i++)
{
VGColor s = KGSurfaceReadPixel(src,i, j);
s=VGColorConvert(s,procFormat);
tmp[j*src->_width+i] = s;
}
}
//find a size for the kernel
CGFloat totalWeightX = stdDeviationX*(CGFloat)sqrt(2.0f*M_PI);
CGFloat totalWeightY = stdDeviationY*(CGFloat)sqrt(2.0f*M_PI);
@ -1354,81 +1357,117 @@ void KGSurfaceGaussianBlur(KGSurface *self,KGSurface * src, CGFloat stdDeviation
int kernelWidth = 0;
CGFloat e = 0.0f;
CGFloat sumX = 1.0f; //the weight of the middle entry counted already
do
{
do{
kernelWidth++;
e = (CGFloat)exp((CGFloat)(kernelWidth * kernelWidth) * expScaleX);
sumX += e*2.0f; //count left&right lobes
}
while(sumX < tolerance*totalWeightX);
}while(sumX < tolerance*totalWeightX);
int kernelHeight = 0;
e = 0.0f;
CGFloat sumY = 1.0f; //the weight of the middle entry counted already
do
{
do{
kernelHeight++;
e = (CGFloat)exp((CGFloat)(kernelHeight * kernelHeight) * expScaleY);
sumY += e*2.0f; //count left&right lobes
}
while(sumY < tolerance*totalWeightY);
}while(sumY < tolerance*totalWeightY);
//make a separable kernel
int kernelXSize=kernelWidth*2+1;
CGFloat kernelX[kernelXSize];
int shiftX = kernelWidth;
CGFloat scaleX = 0.0f;
kernel->xSize=kernelWidth*2+1;
kernel->xValues=NSZoneMalloc(NULL,sizeof(CGFloat)*kernel->xSize);
kernel->xShift = kernelWidth;
kernel->xScale = 0.0f;
int i;
for(i=0;i<kernelXSize;i++)
{
int x = i-shiftX;
kernelX[i] = (CGFloat)exp((CGFloat)x*(CGFloat)x * expScaleX);
scaleX += kernelX[i];
for(i=0;i<kernel->xSize;i++){
int x = i-kernel->xShift;
kernel->xValues[i] = (CGFloat)exp((CGFloat)x*(CGFloat)x * expScaleX);
kernel->xScale += kernel->xValues[i];
}
scaleX = 1.0f / scaleX; //NOTE: using the mathematical definition of the scaling term doesn't work since we cut the filter support early for performance
kernel->xScale = 1.0f / kernel->xScale; //NOTE: using the mathematical definition of the scaling term doesn't work since we cut the filter support early for performance
int kernelYSize=kernelHeight*2+1;
CGFloat kernelY[kernelYSize];
int shiftY = kernelHeight;
CGFloat scaleY = 0.0f;
for(i=0;i<kernelYSize;i++)
kernel->ySize=kernelHeight*2+1;
kernel->yValues=NSZoneMalloc(NULL,sizeof(CGFloat)*kernel->ySize);
kernel->yShift = kernelHeight;
kernel->yScale = 0.0f;
for(i=0;i<kernel->ySize;i++)
{
int y = i-shiftY;
kernelY[i] = (CGFloat)exp((CGFloat)y*(CGFloat)y * expScaleY);
scaleY += kernelY[i];
int y = i-kernel->yShift;
kernel->yValues[i] = (CGFloat)exp((CGFloat)y*(CGFloat)y * expScaleY);
kernel->yScale += kernel->yValues[i];
}
scaleY = 1.0f / scaleY; //NOTE: using the mathematical definition of the scaling term doesn't work since we cut the filter support early for performance
kernel->yScale = 1.0f / kernel->yScale; //NOTE: using the mathematical definition of the scaling term doesn't work since we cut the filter support early for performance
return kernel;
}
VGColor *tmp2=(VGColor *)NSZoneMalloc(NULL,w*src->_height*sizeof(VGColor));
KGGaussianKernelRef KGGaussianKernelRetain(KGGaussianKernelRef kernel) {
if(kernel!=NULL)
kernel->refCount++;
return kernel;
}
void KGGaussianKernelRelease(KGGaussianKernelRef kernel) {
if(kernel!=NULL){
kernel->refCount--;
if(kernel->refCount<=0){
NSZoneFree(NULL,kernel->xValues);
NSZoneFree(NULL,kernel->yValues);
NSZoneFree(NULL,kernel);
}
}
}
void KGSurfaceGaussianBlur(KGSurface *self,KGImage * src, KGGaussianKernel *kernel){
RI_ASSERT(src->_pixelBytes); //source exists
RI_ASSERT(self->_pixelBytes); //destination exists
//the area to be written is an intersection of source and destination image areas.
//lower-left corners of the images are aligned.
int w = RI_INT_MIN(self->_width, src->_width);
int h = RI_INT_MIN(self->_height, src->_height);
RI_ASSERT(w > 0 && h > 0);
KGRGBAffff *tmp=NSZoneMalloc(NULL,src->_width*src->_height*sizeof(KGRGBAffff));
//copy source region to tmp and do conversion
int i,j;
for(j=0;j<src->_height;j++){
KGRGBAffff *tmpRow=tmp+j*src->_width;
int i,width=src->_width;
KGRGBAffff *direct=KGImageReadSpan_lRGBAffff_PRE(src,0,j,tmpRow,width);
if(direct!=NULL){
for(i=0;i<width;i++)
tmpRow[i]=direct[i];
}
}
KGRGBAffff *tmp2=NSZoneMalloc(NULL,w*src->_height*sizeof(KGRGBAffff));
//horizontal pass
for(j=0;j<src->_height;j++)
{
for(i=0;i<w;i++)
{
VGColor sum=VGColorRGBA(0,0,0,0,procFormat);
for(j=0;j<src->_height;j++){
for(i=0;i<w;i++){
KGRGBAffff sum=KGRGBAffffInit(0,0,0,0);
int ki;
for(ki=0;ki<kernelXSize;ki++)
{
int x = i+ki-shiftX;
sum=VGColorAdd(sum, VGColorMultiplyByFloat(readTiledPixel(x, j, src->_width, src->_height, tilingMode, tmp, edge),kernelX[ki]));
for(ki=0;ki<kernel->xSize;ki++){
int x = i+ki-kernel->xShift;
sum=KGRGBAffffAdd(sum, KGRGBAffffMultiplyByFloat(gaussianReadPixel(x, j, src->_width, src->_height, tmp),kernel->xValues[ki]));
}
tmp2[j*w+i] = VGColorMultiplyByFloat(sum, scaleX);
tmp2[j*w+i] = KGRGBAffffMultiplyByFloat(sum, kernel->xScale);
}
}
//vertical pass
for(j=0;j<h;j++)
{
for(i=0;i<w;i++)
{
VGColor sum=VGColorRGBA(0,0,0,0,procFormat);
for(j=0;j<h;j++){
for(i=0;i<w;i++){
KGRGBAffff sum=KGRGBAffffInit(0,0,0,0);
int kj;
for(kj=0;kj<kernelYSize;kj++)
{
int y = j+kj-shiftY;
sum=VGColorAdd(sum, VGColorMultiplyByFloat(readTiledPixel(i, y, w, src->_height, tilingMode, tmp2, edge), kernelY[kj]));
for(kj=0;kj<kernel->ySize;kj++){
int y = j+kj-kernel->yShift;
sum=KGRGBAffffAdd(sum, KGRGBAffffMultiplyByFloat(gaussianReadPixel(i, y, w, src->_height, tmp2), kernel->yValues[kj]));
}
KGSurfaceWriteFilteredPixel(self,i, j, VGColorMultiplyByFloat(sum, scaleY), channelMask);
sum=KGRGBAffffMultiplyByFloat(sum, kernel->yScale);
KGSurfaceWriteSpan_lRGBAffff_PRE(self,i, j, &sum,1);
}
}
NSZoneFree(NULL,tmp);

View File

@ -9,7 +9,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#import "NSTIFFImageFileDirectory.h"
#import "NSTIFFReader.h"
#import "KGPDFFilter.h"
#import <ApplicationServices/CoreGraphics.h>
#import <ApplicationServices/ApplicationServices.h>
@implementation NSTIFFImageFileDirectory

View File

@ -0,0 +1,6 @@
#import <AppKit/NSColor.h>
#import <ApplicationServices/ApplicationServices.h>
@interface NSColor(NSAppKitPrivate)
-(CGColorRef)createCGColorRef;
@end

View File

@ -67,6 +67,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
return nil;
}
-(CGColorRef)createCGColorRef {
return CGColorRetain(_colorRef);
}
-(void)setStroke {
CGContextSetStrokeColorWithColor(NSCurrentGraphicsPort(),_colorRef);
}

View File

@ -9,6 +9,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#import <AppKit/NSColor_catalog.h>
#import <AppKit/NSGraphics.h>
#import <AppKit/NSDisplay.h>
#import <AppKit/NSColor-Private.h>
@implementation NSColor_catalog
@ -71,6 +72,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
return result;
}
-(CGColorRef)createCGColorRef {
return [[[NSDisplay currentDisplay] colorWithName:_colorName] createCGColorRef];
}
-(void)setFill {
NSColor *color=[[NSDisplay currentDisplay] colorWithName:_colorName];

View File

@ -97,6 +97,16 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
return [super colorUsingColorSpaceName:colorSpace device:device];
}
-(CGColorRef)createCGColorRef {
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceCMYK();
float components[5]={_cyan,_magenta,_yellow,_black,_alpha};
KGColor *color=CGColorCreate(colorSpace,components);
CGColorSpaceRelease(colorSpace);
return color;
}
-(void)setFill {
CGContextSetCMYKFillColor(NSCurrentGraphicsPort(),_cyan,_magenta,_yellow,_black, _alpha);
}

View File

@ -105,6 +105,15 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
return [super colorUsingColorSpaceName:colorSpace device:device];
}
-(CGColorRef)createCGColorRef {
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();
float components[4]={_red,_green,_blue,_alpha};
KGColor *color=CGColorCreate(colorSpace,components);
CGColorSpaceRelease(colorSpace);
return color;
}
-(void)setFill {
CGContextSetRGBFillColor(NSCurrentGraphicsPort(),_red,_green,_blue,_alpha);
}

View File

@ -111,6 +111,15 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
return NSDeviceRGBColorSpace;
}
-(CGColorRef)createCGColorRef {
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();
float components[4]={_red,_green,_blue,_alpha};
KGColor *color=CGColorCreate(colorSpace,components);
CGColorSpaceRelease(colorSpace);
return color;
}
-(void)setStroke {
CGContextSetRGBStrokeColor(NSCurrentGraphicsPort(),_red,_green,_blue,_alpha);
}

View File

@ -124,6 +124,15 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
return [super colorUsingColorSpaceName:colorSpace device:device];
}
-(CGColorRef)createCGColorRef {
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceGray();
float components[2]={_white,_alpha};
KGColor *color=CGColorCreate(colorSpace,components);
CGColorSpaceRelease(colorSpace);
return color;
}
-(void)setStroke {
CGContextSetGrayStrokeColor(NSCurrentGraphicsPort(),_white,_alpha);
}

View File

@ -66,6 +66,15 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
return [[[[self class] alloc] initWithGray:_white alpha:alpha] autorelease];
}
-(CGColorRef)createCGColorRef {
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceGray();
float components[2]={_white,_alpha};
KGColor *color=CGColorCreate(colorSpace,components);
CGColorSpaceRelease(colorSpace);
return color;
}
-(void)setStroke {
CGContextSetGrayStrokeColor(NSCurrentGraphicsPort(),_white,_alpha);
}

View File

@ -130,9 +130,10 @@ void evaluate(void *info,const float *in, float *output) {
function=CGFunctionCreate(self,1,domain,4,range,&callbacks);
float radius=[self bounds].size.width/2;
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();
shading=CGShadingCreateRadial(CGColorSpaceCreateDeviceRGB(),CGPointMake(0,0),1,
CGPointMake(radius *2,radius*2),radius,function,YES,NO);
CGColorSpaceRelease(colorSpace);
CGContextDrawShading(graphicsPort,shading);
CGContextRotateCTM(graphicsPort,M_PI*(120)/180.0);
CGContextDrawShading(graphicsPort,shading);

View File

@ -7,9 +7,9 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#import <AppKit/NSShadow.h>
#import <AppKit/NSColor.h>
#import <AppKit/NSColor-Private.h>
#import <AppKit/NSGraphicsContext.h>
#import <ApplicationServices/CGContext.h>
#import <ApplicationServices/ApplicationServices.h>
#import <Foundation/NSRaise.h>
@implementation NSShadow
@ -71,10 +71,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
-(void)set {
CGContextRef context=[[NSGraphicsContext currentContext] graphicsPort];
CGColorRef color=[_color createCGColorRef];
CGContextSetShadowWithColor(context,_offset,_blurRadius,color);
// need NSColor->CGColor
// CGContextSetShadowWithColor(context,_offset,_blurRadius,[color _cgColor]);
NSUnimplementedMethod();
CGColorRelease(color);
}
@end

View File

@ -25,3 +25,5 @@ typedef enum {
COREGRAPHICS_EXPORT void CGColorSpaceRelease(CGColorSpaceRef colorSpace);
COREGRAPHICS_EXPORT CGColorSpaceRef CGColorSpaceCreateDeviceRGB();
COREGRAPHICS_EXPORT CGColorSpaceRef CGColorSpaceCreateDeviceGray();
COREGRAPHICS_EXPORT CGColorSpaceRef CGColorSpaceCreateDeviceCMYK();

View File

@ -180,8 +180,8 @@
[context setFlatness:flatness]
#define CGContextSetInterpolationQuality(context,quality) \
[context setInterpolationQuality:quality]
#define CGContextSetShadowWithColor(context,offset,blur,color) \
[context setShadowOffset:offset blur:blur color:color]
#define CGContextSetShadowWithColor(context,o,b,c) \
[context setShadowOffset:o blur:b color:c]
#define CGContextSetShadow(context,offset,blur) \
[context setShadowOffset:offset blur:blur]
#define CGContextSetShouldAntialias(context,yesOrNo) \

View File

@ -79,7 +79,7 @@ static CGColorRef cgColorFromColor(NSColor *color){
_dashLengthsCount=0;
_dashLengths=NSZoneMalloc([self zone],sizeof(float)*4);
NSString *path=[[NSBundle bundleForClass:[self class]] pathForResource:@"overlay" ofType:@"jpg"];
NSString *path=[[NSBundle bundleForClass:[self class]] pathForResource:@"overlay" ofType:@"png"];
NSData *data=[NSData dataWithContentsOfFile:path];
CGImageSourceRef source=CGImageSourceCreateWithData((CFDataRef)data,nil);
_resamplingImage=CGImageSourceCreateImageAtIndex(source,0,nil);
@ -282,6 +282,16 @@ static void addSliceToPath(CGMutablePathRef path,float innerRadius,float outerRa
[self establishContextState];
#if 0
CGColorRef color=CGColorCreateGenericRGB(1,0,0,1);
CGContextSetShadowWithColor(_context,CGSizeMake(-5,-5),5,color);
CGColorRelease(color);
#endif
#if 0
CGContextAddEllipseInRect(_context,CGRectMake(0,0,CGImageGetWidth(_resamplingImage),CGImageGetHeight(_resamplingImage)));
CGContextClip(_context);
#endif
CGContextDrawImage(_context,CGRectMake(0,0,CGImageGetWidth(_resamplingImage),CGImageGetHeight(_resamplingImage)),_resamplingImage);
CGContextRestoreGState(_context);

View File

@ -10,11 +10,11 @@
<integer>5</integer>
<key>IBOpenObjects</key>
<array>
<integer>2</integer>
<integer>29</integer>
<integer>2</integer>
</array>
<key>IBSystem Version</key>
<string>9D34</string>
<string>9E17</string>
<key>targetFramework</key>
<string>IBCocoaFramework</string>
</dict>

View File

@ -649,7 +649,7 @@
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO;
GCC_MODEL_TUNING = "";
GCC_OPTIMIZATION_LEVEL = 3;
GCC_UNROLL_LOOPS = YES;
GCC_UNROLL_LOOPS = NO;
GCC_VERSION = 4.2;
GCC_WARN_64_TO_32_BIT_CONVERSION = NO;
GCC_WARN_SHADOW = NO;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 36 KiB