- SWRender, Split KGPaint into specific subclasses, changed image drawing into KGPaint_image, merged KGRasterizer and KGPixelPipe int KGRasterizer, got rid of stray static variable in KGImageSource_JPEG.

This commit is contained in:
Christopher Lloyd 2008-05-04 01:25:46 +00:00
parent 51add64d47
commit e698157b7a
28 changed files with 1547 additions and 1032 deletions

View File

@ -682,8 +682,6 @@
FE6EE27F0DB91EA8005503A1 /* VGmath.m in Sources */ = {isa = PBXBuildFile; fileRef = FE6EE27D0DB91EA8005503A1 /* VGmath.m */; };
FE6EE28E0DB91FDF005503A1 /* KGSurface.h in Headers */ = {isa = PBXBuildFile; fileRef = FE6EE28C0DB91FDF005503A1 /* KGSurface.h */; };
FE6EE28F0DB91FDF005503A1 /* KGSurface.m in Sources */ = {isa = PBXBuildFile; fileRef = FE6EE28D0DB91FDF005503A1 /* KGSurface.m */; };
FE6EE2DF0DB92B05005503A1 /* KGPixelPipe.h in Headers */ = {isa = PBXBuildFile; fileRef = FE6EE2DB0DB92B05005503A1 /* KGPixelPipe.h */; };
FE6EE2E00DB92B05005503A1 /* KGPixelPipe.m in Sources */ = {isa = PBXBuildFile; fileRef = FE6EE2DC0DB92B05005503A1 /* KGPixelPipe.m */; };
FE6EE2E10DB92B05005503A1 /* KGRasterizer.h in Headers */ = {isa = PBXBuildFile; fileRef = FE6EE2DD0DB92B05005503A1 /* KGRasterizer.h */; };
FE6EE2E20DB92B05005503A1 /* KGRasterizer.m in Sources */ = {isa = PBXBuildFile; fileRef = FE6EE2DE0DB92B05005503A1 /* KGRasterizer.m */; };
FE6EE2E50DB92B11005503A1 /* VGPath.h in Headers */ = {isa = PBXBuildFile; fileRef = FE6EE2E30DB92B11005503A1 /* VGPath.h */; };
@ -704,6 +702,21 @@
FEABD5ED0CB9CEE40035F828 /* KGLayer_gdi.m in Sources */ = {isa = PBXBuildFile; fileRef = FEABD5E90CB9CEE40035F828 /* KGLayer_gdi.m */; };
FEABD6070CB9D0C90035F828 /* KGContext_gdi.h in Headers */ = {isa = PBXBuildFile; fileRef = FEABD6030CB9D0C90035F828 /* KGContext_gdi.h */; settings = {ATTRIBUTES = (Private, ); }; };
FEABD6080CB9D0C90035F828 /* KGContext_gdi.m in Sources */ = {isa = PBXBuildFile; fileRef = FEABD6040CB9D0C90035F828 /* KGContext_gdi.m */; };
FEBF55E50DCA112900CE5A1C /* KGImageSource_JPEG.h in Headers */ = {isa = PBXBuildFile; fileRef = FEBF55E20DCA112900CE5A1C /* KGImageSource_JPEG.h */; };
FEBF55E60DCA112900CE5A1C /* KGPaint.h in Headers */ = {isa = PBXBuildFile; fileRef = FEBF55E30DCA112900CE5A1C /* KGPaint.h */; };
FEBF55E70DCA112900CE5A1C /* KGPaint.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF55E40DCA112900CE5A1C /* KGPaint.m */; };
FEBF5A0D0DCD450700CE5A1C /* KGPaint_axialGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = FEBF5A010DCD450700CE5A1C /* KGPaint_axialGradient.h */; };
FEBF5A0E0DCD450700CE5A1C /* KGPaint_axialGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF5A020DCD450700CE5A1C /* KGPaint_axialGradient.m */; };
FEBF5A0F0DCD450700CE5A1C /* KGPaint_color.h in Headers */ = {isa = PBXBuildFile; fileRef = FEBF5A030DCD450700CE5A1C /* KGPaint_color.h */; };
FEBF5A100DCD450700CE5A1C /* KGPaint_color.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF5A040DCD450700CE5A1C /* KGPaint_color.m */; };
FEBF5A110DCD450700CE5A1C /* KGPaint_image.h in Headers */ = {isa = PBXBuildFile; fileRef = FEBF5A050DCD450700CE5A1C /* KGPaint_image.h */; };
FEBF5A120DCD450700CE5A1C /* KGPaint_image.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF5A060DCD450700CE5A1C /* KGPaint_image.m */; };
FEBF5A130DCD450700CE5A1C /* KGPaint_pattern.h in Headers */ = {isa = PBXBuildFile; fileRef = FEBF5A070DCD450700CE5A1C /* KGPaint_pattern.h */; };
FEBF5A140DCD450700CE5A1C /* KGPaint_pattern.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF5A080DCD450700CE5A1C /* KGPaint_pattern.m */; };
FEBF5A150DCD450700CE5A1C /* KGPaint_radialGradient.h in Headers */ = {isa = PBXBuildFile; fileRef = FEBF5A090DCD450700CE5A1C /* KGPaint_radialGradient.h */; };
FEBF5A160DCD450700CE5A1C /* KGPaint_radialGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF5A0A0DCD450700CE5A1C /* KGPaint_radialGradient.m */; };
FEBF5A170DCD450700CE5A1C /* KGPaint_ramp.h in Headers */ = {isa = PBXBuildFile; fileRef = FEBF5A0B0DCD450700CE5A1C /* KGPaint_ramp.h */; };
FEBF5A180DCD450700CE5A1C /* KGPaint_ramp.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF5A0C0DCD450700CE5A1C /* KGPaint_ramp.m */; };
FEDF951F0CAF43E7009DC96F /* KGPDFContext.h in Headers */ = {isa = PBXBuildFile; fileRef = FEDF951B0CAF43E7009DC96F /* KGPDFContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
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, ); }; };
@ -1426,8 +1439,6 @@
FE6EE27D0DB91EA8005503A1 /* VGmath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VGmath.m; sourceTree = "<group>"; };
FE6EE28C0DB91FDF005503A1 /* KGSurface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGSurface.h; sourceTree = "<group>"; };
FE6EE28D0DB91FDF005503A1 /* KGSurface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGSurface.m; sourceTree = "<group>"; };
FE6EE2DB0DB92B05005503A1 /* KGPixelPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGPixelPipe.h; sourceTree = "<group>"; };
FE6EE2DC0DB92B05005503A1 /* KGPixelPipe.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGPixelPipe.m; sourceTree = "<group>"; };
FE6EE2DD0DB92B05005503A1 /* KGRasterizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGRasterizer.h; sourceTree = "<group>"; };
FE6EE2DE0DB92B05005503A1 /* KGRasterizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGRasterizer.m; sourceTree = "<group>"; };
FE6EE2E30DB92B11005503A1 /* VGPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VGPath.h; sourceTree = "<group>"; };
@ -1467,6 +1478,21 @@
FEABD5E90CB9CEE40035F828 /* KGLayer_gdi.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = KGLayer_gdi.m; sourceTree = "<group>"; };
FEABD6030CB9D0C90035F828 /* KGContext_gdi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KGContext_gdi.h; sourceTree = "<group>"; };
FEABD6040CB9D0C90035F828 /* KGContext_gdi.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = KGContext_gdi.m; sourceTree = "<group>"; };
FEBF55E20DCA112900CE5A1C /* KGImageSource_JPEG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGImageSource_JPEG.h; sourceTree = "<group>"; };
FEBF55E30DCA112900CE5A1C /* KGPaint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGPaint.h; sourceTree = "<group>"; };
FEBF55E40DCA112900CE5A1C /* KGPaint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGPaint.m; sourceTree = "<group>"; };
FEBF5A010DCD450700CE5A1C /* KGPaint_axialGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGPaint_axialGradient.h; sourceTree = "<group>"; };
FEBF5A020DCD450700CE5A1C /* KGPaint_axialGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGPaint_axialGradient.m; sourceTree = "<group>"; };
FEBF5A030DCD450700CE5A1C /* KGPaint_color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGPaint_color.h; sourceTree = "<group>"; };
FEBF5A040DCD450700CE5A1C /* KGPaint_color.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGPaint_color.m; sourceTree = "<group>"; };
FEBF5A050DCD450700CE5A1C /* KGPaint_image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGPaint_image.h; sourceTree = "<group>"; };
FEBF5A060DCD450700CE5A1C /* KGPaint_image.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGPaint_image.m; sourceTree = "<group>"; };
FEBF5A070DCD450700CE5A1C /* KGPaint_pattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGPaint_pattern.h; sourceTree = "<group>"; };
FEBF5A080DCD450700CE5A1C /* KGPaint_pattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGPaint_pattern.m; sourceTree = "<group>"; };
FEBF5A090DCD450700CE5A1C /* KGPaint_radialGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGPaint_radialGradient.h; sourceTree = "<group>"; };
FEBF5A0A0DCD450700CE5A1C /* KGPaint_radialGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGPaint_radialGradient.m; sourceTree = "<group>"; };
FEBF5A0B0DCD450700CE5A1C /* KGPaint_ramp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KGPaint_ramp.h; sourceTree = "<group>"; };
FEBF5A0C0DCD450700CE5A1C /* KGPaint_ramp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KGPaint_ramp.m; sourceTree = "<group>"; };
FECAF4C80DB710EE00BA2A8E /* ApplicationServices.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ApplicationServices.xcodeproj; path = ../ApplicationServices/ApplicationServices.xcodeproj; sourceTree = SOURCE_ROOT; };
FED166D40BE502AD00BF9889 /* NSSegment.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NSSegment.h; sourceTree = "<group>"; };
FED166D50BE502AD00BF9889 /* NSSegment.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = NSSegment.m; sourceTree = "<group>"; };
@ -1974,6 +2000,21 @@
6E2B55B20976075300DA0954 /* CoreGraphics */ = {
isa = PBXGroup;
children = (
FEBF5A010DCD450700CE5A1C /* KGPaint_axialGradient.h */,
FEBF5A020DCD450700CE5A1C /* KGPaint_axialGradient.m */,
FEBF5A030DCD450700CE5A1C /* KGPaint_color.h */,
FEBF5A040DCD450700CE5A1C /* KGPaint_color.m */,
FEBF5A050DCD450700CE5A1C /* KGPaint_image.h */,
FEBF5A060DCD450700CE5A1C /* KGPaint_image.m */,
FEBF5A070DCD450700CE5A1C /* KGPaint_pattern.h */,
FEBF5A080DCD450700CE5A1C /* KGPaint_pattern.m */,
FEBF5A090DCD450700CE5A1C /* KGPaint_radialGradient.h */,
FEBF5A0A0DCD450700CE5A1C /* KGPaint_radialGradient.m */,
FEBF5A0B0DCD450700CE5A1C /* KGPaint_ramp.h */,
FEBF5A0C0DCD450700CE5A1C /* KGPaint_ramp.m */,
FEBF55E20DCA112900CE5A1C /* KGImageSource_JPEG.h */,
FEBF55E30DCA112900CE5A1C /* KGPaint.h */,
FEBF55E40DCA112900CE5A1C /* KGPaint.m */,
FE7ABEBD0DC2C9BA0060D15B /* CGPDFDocument.m */,
FE45EDCB0DC2407E00F49290 /* CGImageSource.m */,
FE3395570DB930F4009AB3E0 /* KGContext_builtin.h */,
@ -1981,8 +2022,6 @@
FE33952C0DB92D25009AB3E0 /* KGBlending.h */,
FE6EE2E30DB92B11005503A1 /* VGPath.h */,
FE6EE2E40DB92B11005503A1 /* VGPath.m */,
FE6EE2DB0DB92B05005503A1 /* KGPixelPipe.h */,
FE6EE2DC0DB92B05005503A1 /* KGPixelPipe.m */,
FE6EE2DD0DB92B05005503A1 /* KGRasterizer.h */,
FE6EE2DE0DB92B05005503A1 /* KGRasterizer.m */,
FE6EE28C0DB91FDF005503A1 /* KGSurface.h */,
@ -2847,11 +2886,18 @@
FE6EDE340DB797D9005503A1 /* KGExceptions.h in Headers */,
FE6EE27E0DB91EA8005503A1 /* VGmath.h in Headers */,
FE6EE28E0DB91FDF005503A1 /* KGSurface.h in Headers */,
FE6EE2DF0DB92B05005503A1 /* KGPixelPipe.h in Headers */,
FE6EE2E10DB92B05005503A1 /* KGRasterizer.h in Headers */,
FE6EE2E50DB92B11005503A1 /* VGPath.h in Headers */,
FE33952D0DB92D25009AB3E0 /* KGBlending.h in Headers */,
FE3395590DB930F4009AB3E0 /* KGContext_builtin.h in Headers */,
FEBF55E50DCA112900CE5A1C /* KGImageSource_JPEG.h in Headers */,
FEBF55E60DCA112900CE5A1C /* KGPaint.h in Headers */,
FEBF5A0D0DCD450700CE5A1C /* KGPaint_axialGradient.h in Headers */,
FEBF5A0F0DCD450700CE5A1C /* KGPaint_color.h in Headers */,
FEBF5A110DCD450700CE5A1C /* KGPaint_image.h in Headers */,
FEBF5A130DCD450700CE5A1C /* KGPaint_pattern.h in Headers */,
FEBF5A150DCD450700CE5A1C /* KGPaint_radialGradient.h in Headers */,
FEBF5A170DCD450700CE5A1C /* KGPaint_ramp.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -3347,12 +3393,18 @@
FE5C69A20D76039F00098551 /* KGDeviceContext_gdiDIBSection.m in Sources */,
FE6EE27F0DB91EA8005503A1 /* VGmath.m in Sources */,
FE6EE28F0DB91FDF005503A1 /* KGSurface.m in Sources */,
FE6EE2E00DB92B05005503A1 /* KGPixelPipe.m in Sources */,
FE6EE2E20DB92B05005503A1 /* KGRasterizer.m in Sources */,
FE6EE2E60DB92B11005503A1 /* VGPath.m in Sources */,
FE33955A0DB930F4009AB3E0 /* KGContext_builtin.m in Sources */,
FE45EDCC0DC2407E00F49290 /* CGImageSource.m in Sources */,
FE7ABEBE0DC2C9BA0060D15B /* CGPDFDocument.m in Sources */,
FEBF55E70DCA112900CE5A1C /* KGPaint.m in Sources */,
FEBF5A0E0DCD450700CE5A1C /* KGPaint_axialGradient.m in Sources */,
FEBF5A100DCD450700CE5A1C /* KGPaint_color.m in Sources */,
FEBF5A120DCD450700CE5A1C /* KGPaint_image.m in Sources */,
FEBF5A140DCD450700CE5A1C /* KGPaint_pattern.m in Sources */,
FEBF5A160DCD450700CE5A1C /* KGPaint_radialGradient.m in Sources */,
FEBF5A180DCD450700CE5A1C /* KGPaint_ramp.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -7,12 +7,11 @@ 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 "KGBitmapContext.h"
@class KGSurface,KGRasterizer,KGPixelPipe;
@class KGSurface,KGRasterizer;
@interface KGContext_builtin : KGBitmapContext {
KGSurface *_surface;
KGRasterizer *_rasterizer;
KGPixelPipe *_pixelPipe;
}

View File

@ -27,9 +27,10 @@
#import "KGSurface.h"
#import "KGExceptions.h"
#import "KGRasterizer.h"
#import "KGPixelPipe.h"
#import "KGGraphicsState.h"
#import "VGPath.h"
#import "KGPaint_image.h"
#import "KGPaint_color.h"
@implementation KGContext_builtin
@ -81,9 +82,8 @@ BOOL _isAvailable=NO;
}
_surface=KGSurfaceInitWithBytes(KGSurfaceAlloc(),_width,_height,bitsPerComponent,bitsPerPixel,bytesPerRow,colorSpace,bitmapInfo,VG_lRGBA_8888_PRE,_bytes);
_rasterizer=KGRasterizerInit(KGRasterizerAlloc());
_pixelPipe=KGPixelPipeInit(KGPixelPipeAlloc());
KGPixelPipeSetRenderingSurface(_pixelPipe,_surface);
_rasterizer=KGRasterizerInit(KGRasterizerAlloc(),_surface);
KGRasterizerSetViewport(_rasterizer,0,0,KGImageGetWidth(_surface),KGImageGetHeight(_surface));
return self;
}
@ -142,32 +142,25 @@ static void applyPath(void *info,const CGPathElement *element) {
}
static KGPaint *paintFromColor(KGColor *color){
KGPaint *result=KGPaintInit(KGPaintAlloc());
int count=[color numberOfComponents];
const float *components=[color components];
if(count==2)
result->m_inputPaintColor=VGColorRGBA(components[0],components[0],components[0],components[1],VGColor_lRGBA);
return [[KGPaint_color alloc] initWithGray:components[0] alpha:components[1]];
if(count==4)
result->m_inputPaintColor=VGColorRGBA(components[0],components[1],components[2],components[3],VGColor_lRGBA);
result->m_paintColor = result->m_inputPaintColor;
result->m_paintColor=VGColorClamp(result->m_paintColor);
result->m_paintColor=VGColorPremultiply(result->m_paintColor);
return result;
return [[KGPaint_color alloc] initWithRed:components[0] green:components[1] blue:components[2] alpha:components[3]];
return [[KGPaint_color alloc] initWithGray:0 alpha:1];
}
-(void)drawPath:(CGPathDrawingMode)drawingMode {
VGPath *vgPath=[self buildDeviceSpacePath:_path];
KGGraphicsState *gState=[self currentState];
// KGPixelPipeSetMask(context->m_masking ? context->getMask() : NULL);
KGPixelPipeSetBlendMode(_pixelPipe,gState->_blendMode);
// KGPixelPipeSetTileFillColor(context->m_tileFillColor);
if(gState->_interpolationQuality==kCGInterpolationDefault)
KGPixelPipeSetImageQuality(_pixelPipe,kCGInterpolationHigh);
else
KGPixelPipeSetImageQuality(_pixelPipe,gState->_interpolationQuality);
// KGRasterizeSetMask(context->m_masking ? context->getMask() : NULL);
KGRasterizeSetBlendMode(_rasterizer,gState->_blendMode);
// KGRasterizeSetTileFillColor(context->m_tileFillColor);
KGRasterizerSetShouldAntialias(_rasterizer,gState->_shouldAntialias);
@ -183,37 +176,39 @@ xform=CGAffineTransformConcat(xform,u2d);
if(drawingMode!=kCGPathStroke)
{
KGPixelPipeSetPaint(_pixelPipe,paintFromColor(gState->_fillColor));
KGPaint *paint=paintFromColor(gState->_fillColor);
KGRasterizeSetPaint(_rasterizer,paint);
Matrix3x3 surfaceToPaintMatrix =Matrix3x3WithCGAffineTransform(xform);//context->m_pathUserToSurface * context->m_fillPaintToUser;
if(Matrix3x3InplaceInvert(&surfaceToPaintMatrix))
{
Matrix3x3ForceAffinity(&surfaceToPaintMatrix);
KGPixelPipeSetSurfaceToPaintMatrix(_pixelPipe,surfaceToPaintMatrix);
KGPaintSetSurfaceToPaintMatrix(paint,surfaceToPaintMatrix);
VGPathFill(vgPath,userToSurfaceMatrix,_rasterizer);
VGFillRule fillRule=(drawingMode==kCGPathFill || drawingMode==kCGPathFillStroke)?VG_NON_ZERO:VG_EVEN_ODD;
KGRasterizerFill(_rasterizer,fillRule, _pixelPipe);
KGRasterizerFill(_rasterizer,fillRule);
}
}
if(drawingMode>=kCGPathStroke){
if(gState->_lineWidth > 0.0f){
KGPixelPipeSetPaint(_pixelPipe,paintFromColor(gState->_strokeColor));
KGPaint *paint=paintFromColor(gState->_strokeColor);
KGRasterizeSetPaint(_rasterizer,paint);
Matrix3x3 surfaceToPaintMatrix=Matrix3x3WithCGAffineTransform(xform);// = context->m_pathUserToSurface * context->m_strokePaintToUser;
if(Matrix3x3InplaceInvert(&surfaceToPaintMatrix))
{
Matrix3x3ForceAffinity(&surfaceToPaintMatrix);
KGPixelPipeSetSurfaceToPaintMatrix(_pixelPipe,surfaceToPaintMatrix);
KGPaintSetSurfaceToPaintMatrix(paint,surfaceToPaintMatrix);
KGRasterizerClear(_rasterizer);
VGPathStroke(vgPath,userToSurfaceMatrix, _rasterizer, gState->_dashLengths,gState->_dashLengthsCount, gState->_dashPhase, YES /* context->m_strokeDashPhaseReset ? YES : NO*/,
gState->_lineWidth, gState->_lineCap, gState->_lineJoin, RI_MAX(gState->_miterLimit, 1.0f));
KGRasterizerFill(_rasterizer,VG_NON_ZERO,_pixelPipe);
KGRasterizerFill(_rasterizer,VG_NON_ZERO);
}
}
}
@ -270,16 +265,21 @@ xform=CGAffineTransformConcat(xform,u2d);
KGRasterizerSetShouldAntialias(_rasterizer,gState->_shouldAntialias);
// KGPixelPipeSetTileFillColor(context->m_tileFillColor);
KGPixelPipeSetPaint(_pixelPipe,paintFromColor(gState->_fillColor));
// KGRasterizeSetTileFillColor(context->m_tileFillColor);
KGPaint *paint=paintFromColor(gState->_fillColor);
CGInterpolationQuality iq;
if(gState->_interpolationQuality==kCGInterpolationDefault)
KGPixelPipeSetImageQuality(_pixelPipe,kCGInterpolationHigh);
iq=kCGInterpolationHigh;
else
KGPixelPipeSetImageQuality(_pixelPipe,gState->_interpolationQuality);
iq=gState->_interpolationQuality;
KGPixelPipeSetBlendMode(_pixelPipe,gState->_blendMode);
KGPaint *imagePaint=[[KGPaint_image alloc] initWithImage:image mode:VG_DRAW_IMAGE_NORMAL paint:paint interpolationQuality:iq];
KGRasterizeSetPaint(_rasterizer,imagePaint);
// KGPixelPipeSetMask(context->m_masking ? context->getMask() : NULL);
KGRasterizeSetBlendMode(_rasterizer,gState->_blendMode);
// KGRasterizeSetMask(context->m_masking ? context->getMask() : NULL);
Matrix3x3 surfaceToImageMatrix = imageUserToSurface;
Matrix3x3 surfaceToPaintMatrix = Matrix3x3Multiply(imageUserToSurface,fillPaintToUser);
@ -288,16 +288,16 @@ xform=CGAffineTransformConcat(xform,u2d);
KGSurfaceMode imode = VG_DRAW_IMAGE_NORMAL;
if(!Matrix3x3IsAffine(surfaceToPaintMatrix))
imode = VG_DRAW_IMAGE_NORMAL; //if paint matrix is not affine, always use normal image mode
KGPixelPipeSetImage(_pixelPipe,image, imode);
KGPixelPipeSetSurfaceToPaintMatrix(_pixelPipe,surfaceToPaintMatrix);
KGPixelPipeSetSurfaceToImageMatrix(_pixelPipe,surfaceToImageMatrix);
KGPaintSetSurfaceToPaintMatrix(paint,surfaceToPaintMatrix);
KGPaintSetSurfaceToPaintMatrix(imagePaint,surfaceToImageMatrix);
KGRasterizerAddEdge(_rasterizer,Vector2Make(p0.x,p0.y), Vector2Make(p1.x,p1.y));
KGRasterizerAddEdge(_rasterizer,Vector2Make(p1.x,p1.y), Vector2Make(p2.x,p2.y));
KGRasterizerAddEdge(_rasterizer,Vector2Make(p2.x,p2.y), Vector2Make(p3.x,p3.y));
KGRasterizerAddEdge(_rasterizer,Vector2Make(p3.x,p3.y), Vector2Make(p0.x,p0.y));
KGRasterizerFill(_rasterizer,VG_EVEN_ODD, _pixelPipe);
KGPixelPipeSetImage(_pixelPipe,nil, imode);
KGRasterizerFill(_rasterizer,VG_EVEN_ODD);
KGRasterizeSetPaint(_rasterizer,nil);
}
KGRasterizerClear(_rasterizer);

View File

@ -525,14 +525,6 @@ static RIfloat byteToColor(unsigned char i){
return (RIfloat)(i) / (RIfloat)0xFF;
}
static RIfloat nibbleToColor(unsigned char i){
return (RIfloat)(i) / (RIfloat)0x0F;
}
static RIfloat twoBitsToColor(unsigned char i){
return (RIfloat)(i) / (RIfloat)0x03;
}
void KGImageRead_ANY_to_RGBA8888_to_RGBAffff(KGImage *self,int x,int y,KGRGBAffff *span,int length){
KGRGBA8888 span8888[length];
@ -800,7 +792,6 @@ KGImage *KGSurfaceMipMapForLevel(KGImage *self,int level){
VGColorInternalFormat KGImageResample_EWAOnMipmaps(KGImage *self,RIfloat x, RIfloat y,KGRGBAffff *span,int length, Matrix3x3 surfaceToImage){
// Visual test indicates this is very close to what Apple is using
int i;
RIfloat m_pixelFilterRadius = 1.25f;
RIfloat m_resamplingFilterRadius = 1.25f;

View File

@ -28,17 +28,6 @@ typedef struct {
} huffman;
// definition of jpeg image component
static struct
{
int id;
int h,v;
int tq;
int hd,ha;
int dc_pred;
int x,y,w2,h2;
uint8_t *data;
} img_comp[4];
@interface KGImageSource_JPEG : KGImageSource {
NSData *_jpg;
@ -52,6 +41,18 @@ static struct
huffman huff_ac[4];
uint8_t dequant[4][64];
struct
{
int id;
int h,v;
int tq;
int hd,ha;
int dc_pred;
int x,y,w2,h2;
uint8_t *data;
} img_comp[4];
// sizes for components, interleaved MCUs
int img_h_max, img_v_max;
int img_mcu_x, img_mcu_y;

View File

@ -280,8 +280,8 @@ static int decode_block(KGImageSource_JPEG *self,short data[64], huffman *hdc, h
memset(data,0,64*sizeof(data[0]));
diff = t ? extend_receive(self,t) : 0;
dc = img_comp[b].dc_pred + diff;
img_comp[b].dc_pred = dc;
dc = self->img_comp[b].dc_pred + diff;
self->img_comp[b].dc_pred = dc;
data[0] = (short) dc;
// decode AC components, see JPEG spec
@ -442,7 +442,7 @@ static void reset(KGImageSource_JPEG *self)
self->code_bits = 0;
self->code_buffer = 0;
self->nomore = 0;
img_comp[0].dc_pred = img_comp[1].dc_pred = img_comp[2].dc_pred = 0;
self->img_comp[0].dc_pred = self->img_comp[1].dc_pred = self->img_comp[2].dc_pred = 0;
self->marker = MARKER_none;
self->todo = self->restart_interval ? self->restart_interval : 0x7fffffff;
// no more than 1<<31 MCUs if no restart_interal? that's plenty safe,
@ -460,12 +460,12 @@ static int parse_entropy_coded_data(KGImageSource_JPEG *self)
// in trivial scanline order
// number of blocks to do just depends on how many actual "pixels" this
// component has, independent of interleaved MCU blocking and such
int w = (img_comp[n].x+7) >> 3;
int h = (img_comp[n].y+7) >> 3;
int w = (self->img_comp[n].x+7) >> 3;
int h = (self->img_comp[n].y+7) >> 3;
for (j=0; j < h; ++j) {
for (i=0; i < w; ++i) {
if (!decode_block(self,data, self->huff_dc+img_comp[n].hd, self->huff_ac+img_comp[n].ha, n)) return 0;
idct_block(self,img_comp[n].data+img_comp[n].w2*j*8+i*8, img_comp[n].w2, data, self->dequant[img_comp[n].tq]);
if (!decode_block(self,data, self->huff_dc+self->img_comp[n].hd, self->huff_ac+self->img_comp[n].ha, n)) return 0;
idct_block(self,self->img_comp[n].data+self->img_comp[n].w2*j*8+i*8, self->img_comp[n].w2, data, self->dequant[self->img_comp[n].tq]);
// every data block is an MCU, so countdown the restart interval
if (--self->todo <= 0) {
if (self->code_bits < 24) grow_buffer_unsafe(self);
@ -486,12 +486,12 @@ static int parse_entropy_coded_data(KGImageSource_JPEG *self)
int n = self->order[k];
// scan out an mcu's worth of this component; that's just determined
// by the basic H and V specified for the component
for (y=0; y < img_comp[n].v; ++y) {
for (x=0; x < img_comp[n].h; ++x) {
int x2 = (i*img_comp[n].h + x)*8;
int y2 = (j*img_comp[n].v + y)*8;
if (!decode_block(self,data, self->huff_dc+img_comp[n].hd, self->huff_ac+img_comp[n].ha, n)) return 0;
idct_block(self,img_comp[n].data+img_comp[n].w2*y2+x2, img_comp[n].w2, data, self->dequant[img_comp[n].tq]);
for (y=0; y < self->img_comp[n].v; ++y) {
for (x=0; x < self->img_comp[n].h; ++x) {
int x2 = (i*self->img_comp[n].h + x)*8;
int y2 = (j*self->img_comp[n].v + y)*8;
if (!decode_block(self,data, self->huff_dc+self->img_comp[n].hd, self->huff_ac+self->img_comp[n].ha, n)) return 0;
idct_block(self,self->img_comp[n].data+self->img_comp[n].w2*y2+x2, self->img_comp[n].w2, data, self->dequant[self->img_comp[n].tq]);
}
}
}
@ -586,11 +586,11 @@ static int process_scan_header(KGImageSource_JPEG *self)
int id = get8(self), which;
int z = get8(self);
for (which = 0; which < self->img_n; ++which)
if (img_comp[which].id == id)
if (self->img_comp[which].id == id)
break;
if (which == self->img_n) return 0;
img_comp[which].hd = z >> 4; if (img_comp[which].hd > 3) return e(self,"bad DC huff","Corrupt JPEG");
img_comp[which].ha = z & 15; if (img_comp[which].ha > 3) return e(self,"bad AC huff","Corrupt JPEG");
self->img_comp[which].hd = z >> 4; if (self->img_comp[which].hd > 3) return e(self,"bad DC huff","Corrupt JPEG");
self->img_comp[which].ha = z & 15; if (self->img_comp[which].ha > 3) return e(self,"bad AC huff","Corrupt JPEG");
self->order[i] = which;
}
if (get8(self) != 0) return e(self,"bad SOS","Corrupt JPEG");
@ -613,14 +613,14 @@ static int process_frame_header(KGImageSource_JPEG *self,int scan)
if (Lf != 8+3*self->img_n) return e(self,"bad SOF len","Corrupt JPEG");
for (i=0; i < self->img_n; ++i) {
img_comp[i].id = get8(self);
if (img_comp[i].id != i+1) // JFIF requires
if (img_comp[i].id != i) // jpegtran outputs non-JFIF-compliant files!
self->img_comp[i].id = get8(self);
if (self->img_comp[i].id != i+1) // JFIF requires
if (self->img_comp[i].id != i) // jpegtran outputs non-JFIF-compliant files!
return e(self,"bad component ID","Corrupt JPEG");
z = get8(self);
img_comp[i].h = (z >> 4); if (!img_comp[i].h || img_comp[i].h > 4) return e(self,"bad H","Corrupt JPEG");
img_comp[i].v = z & 15; if (!img_comp[i].v || img_comp[i].v > 4) return e(self,"bad V","Corrupt JPEG");
img_comp[i].tq = get8(self); if (img_comp[i].tq > 3) return e(self,"bad TQ","Corrupt JPEG");
self->img_comp[i].h = (z >> 4); if (!self->img_comp[i].h || self->img_comp[i].h > 4) return e(self,"bad H","Corrupt JPEG");
self->img_comp[i].v = z & 15; if (!self->img_comp[i].v || self->img_comp[i].v > 4) return e(self,"bad V","Corrupt JPEG");
self->img_comp[i].tq = get8(self); if (self->img_comp[i].tq > 3) return e(self,"bad TQ","Corrupt JPEG");
}
if (scan != SCAN_load) return 1;
@ -628,8 +628,8 @@ static int process_frame_header(KGImageSource_JPEG *self,int scan)
if ((1 << 30) / self->img_x / self->img_n < self->img_y) return e(self,"too large", "Image too large to decode");
for (i=0; i < self->img_n; ++i) {
if (img_comp[i].h > h_max) h_max = img_comp[i].h;
if (img_comp[i].v > v_max) v_max = img_comp[i].v;
if (self->img_comp[i].h > h_max) h_max = self->img_comp[i].h;
if (self->img_comp[i].v > v_max) v_max = self->img_comp[i].v;
}
// compute interleaved mcu info
@ -642,18 +642,18 @@ static int process_frame_header(KGImageSource_JPEG *self,int scan)
for (i=0; i < self->img_n; ++i) {
// number of effective pixels (e.g. for non-interleaved MCU)
img_comp[i].x = (self->img_x * img_comp[i].h + h_max-1) / h_max;
img_comp[i].y = (self->img_y * img_comp[i].v + v_max-1) / v_max;
self->img_comp[i].x = (self->img_x * self->img_comp[i].h + h_max-1) / h_max;
self->img_comp[i].y = (self->img_y * self->img_comp[i].v + v_max-1) / v_max;
// to simplify generation, we'll allocate enough memory to decode
// the bogus oversized data from using interleaved MCUs and their
// big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
// discard the extra data until colorspace conversion
img_comp[i].w2 = self->img_mcu_x * img_comp[i].h * 8;
img_comp[i].h2 = self->img_mcu_y * img_comp[i].v * 8;
img_comp[i].data = (uint8 *) NSZoneMalloc(NULL,img_comp[i].w2 * img_comp[i].h2);
if (img_comp[i].data == NULL) {
self->img_comp[i].w2 = self->img_mcu_x * self->img_comp[i].h * 8;
self->img_comp[i].h2 = self->img_mcu_y * self->img_comp[i].v * 8;
self->img_comp[i].data = (uint8 *) NSZoneMalloc(NULL,self->img_comp[i].w2 * self->img_comp[i].h2);
if (self->img_comp[i].data == NULL) {
for(--i; i >= 0; --i)
NSZoneFree(NULL,img_comp[i].data);
NSZoneFree(NULL,self->img_comp[i].data);
return e(self,"outofmem", "Out of memory");
}
}
@ -856,9 +856,9 @@ static void cleanup_jpeg(KGImageSource_JPEG *self)
{
int i;
for (i=0; i < self->img_n; ++i) {
if (img_comp[i].data) {
NSZoneFree(NULL,img_comp[i].data);
img_comp[i].data = NULL;
if (self->img_comp[i].data) {
NSZoneFree(NULL,self->img_comp[i].data);
self->img_comp[i].data = NULL;
}
}
}
@ -886,7 +886,7 @@ static void load_jpeg_image(KGImageSource_JPEG *self,int *out_x, int *out_y, int
if (n < 3 && i) continue;
// check if the component scale is less than max; if so it needs upsampling
if (img_comp[i].h != self->img_h_max || img_comp[i].v != self->img_v_max) {
if (self->img_comp[i].h != self->img_h_max || self->img_comp[i].v != self->img_v_max) {
int stride = self->img_x;
// allocate final size; make sure it's big enough for upsampling off
// the edges with upsample up to 4x4 (although we only support 2x2
@ -897,15 +897,15 @@ static void load_jpeg_image(KGImageSource_JPEG *self,int *out_x, int *out_y, int
ep("outofmem", "Out of memory (image too large?)");
return;
}
if (img_comp[i].h*2 == self->img_h_max && img_comp[i].v*2 == self->img_v_max) {
if (self->img_comp[i].h*2 == self->img_h_max && self->img_comp[i].v*2 == self->img_v_max) {
int tx = (self->img_x+1)>>1;
resample_hv_2(new_data, img_comp[i].data, tx,(self->img_y+1)>>1, img_comp[i].w2);
resample_hv_2(new_data, self->img_comp[i].data, tx,(self->img_y+1)>>1, self->img_comp[i].w2);
stride = tx*2;
} else if (img_comp[i].h == self->img_h_max && img_comp[i].v*2 == self->img_v_max) {
resample_v_2(new_data, img_comp[i].data, self->img_x,(self->img_y+1)>>1, img_comp[i].w2);
} else if (img_comp[i].h*2 == self->img_h_max && img_comp[i].v == self->img_v_max) {
} else if (self->img_comp[i].h == self->img_h_max && self->img_comp[i].v*2 == self->img_v_max) {
resample_v_2(new_data, self->img_comp[i].data, self->img_x,(self->img_y+1)>>1, self->img_comp[i].w2);
} else if (self->img_comp[i].h*2 == self->img_h_max && self->img_comp[i].v == self->img_v_max) {
int tx = (self->img_x+1)>>1;
resample_h_2(new_data, img_comp[i].data, tx,self->img_y, img_comp[i].w2);
resample_h_2(new_data, self->img_comp[i].data, tx,self->img_y, self->img_comp[i].w2);
stride = tx*2;
} else {
// @TODO resample uncommon sampling pattern with nearest neighbor
@ -914,9 +914,9 @@ static void load_jpeg_image(KGImageSource_JPEG *self,int *out_x, int *out_y, int
ep("uncommon H or V", "JPEG not supported: atypical downsampling mode");
return;
}
img_comp[i].w2 = stride;
NSZoneFree(NULL,img_comp[i].data);
img_comp[i].data = new_data;
self->img_comp[i].w2 = stride;
NSZoneFree(NULL,self->img_comp[i].data);
self->img_comp[i].data = new_data;
}
}
@ -927,11 +927,11 @@ static void load_jpeg_image(KGImageSource_JPEG *self,int *out_x, int *out_y, int
if (n >= 3) { // output STBI_rgb_*
for (j=0; j < self->img_y; ++j) {
uint8 *y = img_comp[0].data + j*img_comp[0].w2;
uint8 *y = self->img_comp[0].data + j*self->img_comp[0].w2;
uint8 *out = self->_bitmap + n * self->img_x * j;
if (self->img_n == 3) {
uint8 *cb = img_comp[1].data + j*img_comp[1].w2;
uint8 *cr = img_comp[2].data + j*img_comp[2].w2;
uint8 *cb = self->img_comp[1].data + j*self->img_comp[1].w2;
uint8 *cr = self->img_comp[2].data + j*self->img_comp[2].w2;
YCbCr_to_RGB_row(out, y, cb, cr, self->img_x, n);
} else {
for (i=0; i < self->img_x; ++i) {
@ -943,7 +943,7 @@ static void load_jpeg_image(KGImageSource_JPEG *self,int *out_x, int *out_y, int
}
} else { // output STBI_grey_*
for (j=0; j < self->img_y; ++j) {
uint8 *y = img_comp[0].data + j*img_comp[0].w2;
uint8 *y = self->img_comp[0].data + j*self->img_comp[0].w2;
uint8 *out = self->_bitmap + n * self->img_x * j;
if (n == 1)
for (i=0; i < self->img_x; ++i) *out++ = *y++;

View File

@ -0,0 +1,56 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGSurface.h"
typedef enum {
VG_PAINT_TYPE_COLOR,
VG_PAINT_TYPE_LINEAR_GRADIENT,
VG_PAINT_TYPE_RADIAL_GRADIENT,
VG_PAINT_TYPE_PATTERN
} VGPaintType;
@class KGPaint;
typedef VGColorInternalFormat (*KGPaintReadSpan_RGBAffff)(KGPaint *self,int x,int y,KGRGBAffff *span,int length);
@interface KGPaint : NSObject {
@public
KGPaintReadSpan_RGBAffff _readRGBAffff;
@protected
VGPaintType m_paintType;
Matrix3x3 m_surfaceToPaintMatrix;
}
KGPaint *KGPaintAlloc();
KGPaint *KGPaintInit(KGPaint *self);
void KGPaintSetSurfaceToPaintMatrix(KGPaint *self,Matrix3x3 surfaceToPaintMatrix);
void KGPaintDealloc(KGPaint *self);
@end

View File

@ -0,0 +1,57 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint.h"
@implementation KGPaint
KGPaint *KGPaintAlloc() {
return [KGPaint alloc];
}
KGPaint *KGPaintInit(KGPaint *self) {
self->m_surfaceToPaintMatrix=Matrix3x3Identity();
return self;
}
void KGPaintSetSurfaceToPaintMatrix(KGPaint *self,Matrix3x3 surfaceToPaintMatrix) {
self->m_surfaceToPaintMatrix = surfaceToPaintMatrix;
}
void KGPaintDealloc(KGPaint *self) {
}
@end

View File

@ -0,0 +1,35 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint_ramp.h"
@interface KGPaint_axialGradient : KGPaint_ramp {
Vector2 m_linearGradientPoint0;
Vector2 m_linearGradientPoint1;
}
@end

View File

@ -0,0 +1,88 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint_axialGradient.h"
@implementation KGPaint_axialGradient
void KGPaintLinearGradient(KGPaint_axialGradient *self,RIfloat *g, RIfloat *rho, RIfloat x, RIfloat y) {
RI_ASSERT(self);
Vector2 u = Vector2Subtract(self->m_linearGradientPoint1 , self->m_linearGradientPoint0);
RIfloat usq = Vector2Dot(u,u);
if( usq <= 0.0f )
{ //points are equal, gradient is always 1.0f
*g = 1.0f;
*rho = 0.0f;
return;
}
RIfloat oou = 1.0f / usq;
Vector2 p=Vector2Make(x, y);
p = Matrix3x3TransformVector2(self->m_surfaceToPaintMatrix, p);
p = Vector2Subtract(p,self->m_linearGradientPoint0);
RI_ASSERT(usq >= 0.0f);
*g = Vector2Dot(p, u) * oou;
RIfloat dgdx = oou * u.x * self->m_surfaceToPaintMatrix.matrix[0][0] + oou * u.y * self->m_surfaceToPaintMatrix.matrix[1][0];
RIfloat dgdy = oou * u.x * self->m_surfaceToPaintMatrix.matrix[0][1] + oou * u.y * self->m_surfaceToPaintMatrix.matrix[1][1];
*rho = (RIfloat)sqrt(dgdx*dgdx + dgdy*dgdy);
RI_ASSERT(*rho >= 0.0f);
}
static inline VGColor linearGradientColorAt(KGPaint_axialGradient *self,int x,int y){
VGColor result;
RIfloat g, rho;
KGPaintLinearGradient(self,&g, &rho, x+0.5f, y+0.5f);
result = KGPaintColorRamp(self,g, rho);
RI_ASSERT((result.m_format == VGColor_sRGBA && !self->m_colorRampPremultiplied) || (result.m_format == VGColor_sRGBA_PRE && self->m_colorRampPremultiplied));
return VGColorPremultiply(result);
}
VGColorInternalFormat KGPaintReadPremultipliedLinearGradientSpan(KGPaint_axialGradient *self,int x,int y,KGRGBAffff *span,int length){
VGColorInternalFormat result=0;
int i;
for(i=0;i<length;i++,x++){
VGColor s=linearGradientColorAt(self,x,y);
result=s.m_format;
span[i]=KGRGBAffffFromColor(s);
}
return result;
}
-init {
[super init];
self->_readRGBAffff=(KGPaintReadSpan_RGBAffff)KGPaintReadPremultipliedLinearGradientSpan;
self->m_linearGradientPoint0=Vector2Make(0,0);
self->m_linearGradientPoint1=Vector2Make(1,0);
return self;
}
@end

View File

@ -0,0 +1,38 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint.h"
@interface KGPaint_color : KGPaint {
VGColor m_paintColor;
}
-initWithGray:(RIfloat)gray alpha:(RIfloat)alpha;
-initWithRed:(RIfloat)red green:(RIfloat)green blue:(RIfloat)blue alpha:(RIfloat)alpha;
@end

View File

@ -0,0 +1,61 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint_color.h"
#import "KGSurface.h"
@implementation KGPaint_color
static VGColorInternalFormat KGPaintReadPremultipliedConstantSourceSpan(KGPaint_color *self,int x,int y,KGRGBAffff *span,int length){
KGRGBAffff rgba=KGRGBAffffFromColor(self->m_paintColor);
int i;
for(i=0;i<length;i++)
span[i]=rgba;
return self->m_paintColor.m_format;
}
-initWithGray:(RIfloat)gray alpha:(RIfloat)alpha {
KGPaintInit(self);
_readRGBAffff=(KGPaintReadSpan_RGBAffff)KGPaintReadPremultipliedConstantSourceSpan;
m_paintColor=VGColorRGBA(gray,gray,gray,alpha,VGColor_lRGBA);
m_paintColor=VGColorClamp(m_paintColor);
m_paintColor=VGColorPremultiply(m_paintColor);
return self;
}
-initWithRed:(RIfloat)red green:(RIfloat)green blue:(RIfloat)blue alpha:(RIfloat)alpha {
KGPaintInit(self);
_readRGBAffff=(KGPaintReadSpan_RGBAffff)KGPaintReadPremultipliedConstantSourceSpan;
m_paintColor=VGColorRGBA(red,green,blue,alpha,VGColor_lRGBA);
m_paintColor=VGColorClamp(m_paintColor);
m_paintColor=VGColorPremultiply(m_paintColor);
return self;
}
@end

View File

@ -0,0 +1,39 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint.h"
@interface KGPaint_image : KGPaint {
KGImage *_image;
KGSurfaceMode _mode;
KGPaint *_paint;
CGInterpolationQuality _interpolationQuality;
}
-initWithImage:(KGImage *)image mode:(KGSurfaceMode)mode paint:(KGPaint *)paint interpolationQuality:(CGInterpolationQuality)interpolationQuality;
@end

View File

@ -0,0 +1,202 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint_image.h"
@implementation KGPaint_image
static VGColorInternalFormat KGPaintReadPremultipliedImageNormalSpan(KGPaint_image *self,int x,int y,KGRGBAffff *span,int length){
VGColorInternalFormat spanFormat;
if(self->_interpolationQuality==kCGInterpolationHigh){
spanFormat=KGImageResample_EWAOnMipmaps(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
// spanFormat=KGImageResample_Bicubic(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
}
else if(self->_interpolationQuality==kCGInterpolationLow)
spanFormat=KGImageResample_Bilinear(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
else
spanFormat=KGImageResample_PointSampling(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
return spanFormat;
}
static VGColorInternalFormat multiply(KGPaint_image *self,int x,int y,KGRGBAffff *span,int length){
VGColorInternalFormat paintFormat;
paintFormat=self->_paint->_readRGBAffff(self->_paint,x,y,span,length);
if(!(paintFormat&VGColorPREMULTIPLIED)){
KGRGBPremultiplySpan(span,length);
paintFormat|=VGColorPREMULTIPLIED;
}
KGRGBAffff imageSpan[length];
VGColorInternalFormat imageFormat=KGPaintReadPremultipliedImageNormalSpan(self,x,y,imageSpan,length);
if(!(imageFormat&VGColorPREMULTIPLIED)){
KGRGBPremultiplySpan(span,length);
imageFormat|=VGColorPREMULTIPLIED;
}
int i;
for(i=0;i<length;i++,x++){
//evaluate paint
VGColor s=VGColorFromKGRGBA_ffff(span[i],paintFormat);
VGColor im=VGColorFromKGRGBA_ffff(imageSpan[i],imageFormat);
//apply image (vgDrawImage only)
//1. paint: convert paint to dst space
//2. image: convert image to dst space
//3. paint MULTIPLY image: convert paint to image number of channels, multiply with image, and convert to dst
//4. paint STENCIL image: convert paint to dst, convert image to dst number of channels, multiply
RI_ASSERT((s.m_format & VGColorLUMINANCE && s.r == s.g && s.r == s.b) || !(s.m_format & VGColorLUMINANCE)); //if luminance, r=g=b
RI_ASSERT((im.m_format & VGColorLUMINANCE && im.r == im.g && im.r == im.b) || !(im.m_format & VGColorLUMINANCE)); //if luminance, r=g=b
//the result will be in image color space. If the number of channels in image and paint
// colors differ, convert to the number of channels in the image color.
//paint == RGB && image == RGB: RGB*RGB
//paint == RGB && image == L : (0.2126 R + 0.7152 G + 0.0722 B)*L
//paint == L && image == RGB: LLL*RGB
//paint == L && image == L : L*L
if(!(s.m_format & VGColorLUMINANCE) && im.m_format & VGColorLUMINANCE)
{
s.r = s.g = s.b = RI_MIN(0.2126f*s.r + 0.7152f*s.g + 0.0722f*s.b, s.a);
}
RI_ASSERT(Matrix3x3IsAffine(self->m_paint->m_surfaceToPaintMatrix));
im.r *= s.r;
im.g *= s.g;
im.b *= s.b;
im.a *= s.a;
s = im;
// s=VGColorConvert(s,format); //convert resulting color to destination color space
span[i]=KGRGBAffffFromColor(s);
}
return imageFormat;
}
static VGColorInternalFormat stencil(KGPaint_image *self,int x,int y,KGRGBAffff *span,int length){
VGColorInternalFormat paintFormat;
paintFormat=self->_paint->_readRGBAffff(self->_paint,x,y,span,length);
if(!(paintFormat&VGColorPREMULTIPLIED)){
KGRGBPremultiplySpan(span,length);
paintFormat|=VGColorPREMULTIPLIED;
}
KGRGBAffff imageSpan[length];
VGColorInternalFormat imageFormat=KGPaintReadPremultipliedImageNormalSpan(self,x,y,imageSpan,length);
if(!(imageFormat&VGColorPREMULTIPLIED)){
KGRGBPremultiplySpan(span,length);
imageFormat|=VGColorPREMULTIPLIED;
}
int i;
for(i=0;i<length;i++,x++){
//evaluate paint
VGColor s=VGColorFromKGRGBA_ffff(span[i],paintFormat);
VGColor im=VGColorFromKGRGBA_ffff(imageSpan[i],imageFormat);
//apply image (vgDrawImage only)
//1. paint: convert paint to dst space
//2. image: convert image to dst space
//3. paint MULTIPLY image: convert paint to image number of channels, multiply with image, and convert to dst
//4. paint STENCIL image: convert paint to dst, convert image to dst number of channels, multiply
RI_ASSERT((s.m_format & VGColorLUMINANCE && s.r == s.g && s.r == s.b) || !(s.m_format & VGColorLUMINANCE)); //if luminance, r=g=b
RI_ASSERT((im.m_format & VGColorLUMINANCE && im.r == im.g && im.r == im.b) || !(im.m_format & VGColorLUMINANCE)); //if luminance, r=g=b
{
// FIX
// This needs to be changed to a nonpremultplied form. This is the only case which used ar, ag, ab premultiplied values for source.
RIfloat ar = s.a, ag = s.a, ab = s.a;
//the result will be in paint color space.
//dst == RGB && image == RGB: RGB*RGB
//dst == RGB && image == L : RGB*LLL
//dst == L && image == RGB: L*(0.2126 R + 0.7152 G + 0.0722 B)
//dst == L && image == L : L*L
RI_ASSERT(self->m_imageMode == VG_DRAW_IMAGE_STENCIL);
#if 0
if(format & VGColorLUMINANCE && !(im.m_format & VGColorLUMINANCE))
{
im.r = im.g = im.b = RI_MIN(0.2126f*im.r + 0.7152f*im.g + 0.0722f*im.b, im.a);
}
RI_ASSERT(Matrix3x3IsAffine(self->m_paint->m_surfaceToPaintMatrix));
//s and im are both in premultiplied format. Each image channel acts as an alpha channel.
s=VGColorConvert(s,format); //convert paint color to destination space already here, since convert cannot deal with per channel alphas used in this mode.
#endif
s.r *= im.r;
s.g *= im.g;
s.b *= im.b;
s.a *= im.a;
ar *= im.r;
ag *= im.g;
ab *= im.b;
//in nonpremultiplied form the result is
// s.rgb = paint.a * paint.rgb * image.a * image.rgb
// s.a = paint.a * image.a
// argb = paint.a * image.a * image.rgb
RI_ASSERT(s.r >= 0.0f && s.r <= s.a && s.r <= ar);
RI_ASSERT(s.g >= 0.0f && s.g <= s.a && s.g <= ag);
RI_ASSERT(s.b >= 0.0f && s.b <= s.a && s.b <= ab);
}
span[i]=KGRGBAffffFromColor(s);
}
return paintFormat;
}
-initWithImage:(KGImage *)image mode:(KGSurfaceMode)mode paint:(KGPaint *)paint interpolationQuality:(CGInterpolationQuality)interpolationQuality {
KGPaintInit(self);
switch(mode){
case VG_DRAW_IMAGE_MULTIPLY:
_readRGBAffff=(KGPaintReadSpan_RGBAffff)multiply;
break;
case VG_DRAW_IMAGE_STENCIL:
_readRGBAffff=(KGPaintReadSpan_RGBAffff)stencil;
break;
default:
_readRGBAffff=(KGPaintReadSpan_RGBAffff)KGPaintReadPremultipliedImageNormalSpan;
break;
}
_image=[image retain];
_mode=mode;
_paint=[paint retain];
_interpolationQuality=interpolationQuality;
return self;
}
-(void)dealloc {
[_image release];
[_paint release];
[super dealloc];
}
@end

View File

@ -0,0 +1,37 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint.h"
@interface KGPaint_pattern : KGPaint {
KGImage *m_pattern;
}
-initWithImage:(KGImage *)image;
@end

View File

@ -0,0 +1,49 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint_pattern.h"
#import "KGSurface.h"
@implementation KGPaint_pattern
static VGColorInternalFormat KGPaintReadPremultipliedPatternSpan(KGPaint_pattern *self,int x,int y,KGRGBAffff *span,int length){
return KGSurfacePatternSpan(self->m_pattern,x, y,span,length, self->m_surfaceToPaintMatrix, kCGPatternTilingConstantSpacing);
}
-initWithImage:(KGImage *)image {
[super init];
_readRGBAffff=(KGPaintReadSpan_RGBAffff)KGPaintReadPremultipliedPatternSpan;
m_pattern=[image retain];
return self;
}
-(void)dealloc {
[m_pattern release];
[super dealloc];
}
@end

View File

@ -0,0 +1,36 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint_ramp.h"
@interface KGPaint_radialGradient : KGPaint_ramp {
Vector2 m_radialGradientCenter;
Vector2 m_radialGradientFocalPoint;
RIfloat m_radialGradientRadius;
}
@end

View File

@ -0,0 +1,104 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint_radialGradient.h"
@implementation KGPaint_radialGradient
void KGPaintRadialGradient(KGPaint_radialGradient *self,RIfloat *g, RIfloat *rho, RIfloat x, RIfloat y) {
RI_ASSERT(self);
if( self->m_radialGradientRadius <= 0.0f )
{
*g = 1.0f;
*rho = 0.0f;
return;
}
RIfloat r = self->m_radialGradientRadius;
Vector2 c = self->m_radialGradientCenter;
Vector2 f = self->m_radialGradientFocalPoint;
Vector2 gx=Vector2Make(self->m_surfaceToPaintMatrix.matrix[0][0], self->m_surfaceToPaintMatrix.matrix[1][0]);
Vector2 gy=Vector2Make(self->m_surfaceToPaintMatrix.matrix[0][1],self->m_surfaceToPaintMatrix.matrix[1][1]);
Vector2 fp = Vector2Subtract(f,c);
//clamp the focal point inside the gradient circle
RIfloat fpLen = Vector2Length(fp);
if( fpLen > 0.999f * r )
fp = Vector2MultiplyByFloat(fp, (0.999f * r / fpLen));
RIfloat D = -1.0f / (Vector2Dot(fp,fp) - r*r);
Vector2 p=Vector2Make(x, y);
p = Vector2Subtract(Matrix3x3TransformVector2(self->m_surfaceToPaintMatrix, p), c);
Vector2 d = Vector2Subtract(p,fp);
RIfloat s = (RIfloat)sqrt(r*r*Vector2Dot(d,d) - RI_SQR(p.x*fp.y - p.y*fp.x));
*g = (Vector2Dot(fp,d) + s) * D;
if(RI_ISNAN(*g))
*g = 0.0f;
RIfloat dgdx = D*Vector2Dot(fp,gx) + (r*r*Vector2Dot(d,gx) - (gx.x*fp.y - gx.y*fp.x)*(p.x*fp.y - p.y*fp.x)) * (D / s);
RIfloat dgdy = D*Vector2Dot(fp,gy) + (r*r*Vector2Dot(d,gy) - (gy.x*fp.y - gy.y*fp.x)*(p.x*fp.y - p.y*fp.x)) * (D / s);
*rho = (RIfloat)sqrt(dgdx*dgdx + dgdy*dgdy);
if(RI_ISNAN(*rho))
*rho = 0.0f;
RI_ASSERT(*rho >= 0.0f);
}
static inline VGColor radialGradientColorAt(KGPaint_radialGradient *self,int x,int y){
VGColor result;
RIfloat g, rho;
KGPaintRadialGradient(self,&g, &rho, x+0.5f, y+0.5f);
result = KGPaintColorRamp(self,g, rho);
RI_ASSERT((result.m_format == VGColor_sRGBA && !self->m_colorRampPremultiplied) || (result.m_format == VGColor_sRGBA_PRE && self->m_colorRampPremultiplied));
return VGColorPremultiply(result);
}
VGColorInternalFormat KGPaintReadPremultipliedRadialGradientSpan(KGPaint_radialGradient *self,int x,int y,KGRGBAffff *span,int length){
VGColorInternalFormat result=0;
int i;
for(i=0;i<length;i++,x++){
VGColor s=radialGradientColorAt(self,x,y);
result=s.m_format;
span[i]=KGRGBAffffFromColor(s);
}
return result;
}
-init {
[super init];
self->_readRGBAffff=(KGPaintReadSpan_RGBAffff)KGPaintReadPremultipliedRadialGradientSpan;
self->m_radialGradientRadius=1.0f;
self->m_radialGradientCenter=Vector2Make(0,0);
self->m_radialGradientFocalPoint=Vector2Make(0,0);
return self;
}
@end

View File

@ -0,0 +1,55 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint.h"
typedef enum {
VG_COLOR_RAMP_SPREAD_PAD,
VG_COLOR_RAMP_SPREAD_REPEAT,
VG_COLOR_RAMP_SPREAD_REFLECT
} VGColorRampSpreadMode;
typedef struct {
RIfloat offset;
VGColor color;
} GradientStop;
@interface KGPaint_ramp : KGPaint {
VGColorRampSpreadMode m_colorRampSpreadMode;
int m_colorRampStopsCount;
int m_colorRampStopsCapacity;
GradientStop *m_colorRampStops;
BOOL m_colorRampPremultiplied;
}
VGColor KGPaintIntegrateColorRamp(KGPaint_ramp *self,RIfloat gmin, RIfloat gmax);
VGColor KGPaintColorRamp(KGPaint_ramp *self,RIfloat gradient, RIfloat rho);
@end

View File

@ -0,0 +1,245 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import "KGPaint_ramp.h"
@implementation KGPaint_ramp
-init {
[super init];
self->m_colorRampSpreadMode=VG_COLOR_RAMP_SPREAD_PAD;
self->m_colorRampStopsCount=2;
self->m_colorRampStopsCapacity=2;
self->m_colorRampStops=(GradientStop *)NSZoneCalloc(NULL,self->m_colorRampStopsCapacity,sizeof(GradientStop));
self->m_colorRampPremultiplied=YES;
GradientStop gs;
gs.offset = 0.0f;
gs.color=VGColorRGBA(0,0,0,1,VGColor_sRGBA);
self->m_colorRampStops[0]=gs;
gs.offset = 1.0f;
gs.color=VGColorRGBA(1,1,1,1,VGColor_sRGBA);
self->m_colorRampStops[1]=gs;
return self;
}
/*-------------------------------------------------------------------*//*!
* \brief Returns the average color within an offset range in the color ramp.
* \param
* \return
* \note
*//*-------------------------------------------------------------------*/
static VGColor readStopColor(GradientStop *colorRampStops,int colorRampStopsCount, int i, BOOL colorRampPremultiplied)
{
RI_ASSERT(i >= 0 && i < colorRampStopsCount);
VGColor c = colorRampStops[i].color;
RI_ASSERT(c.m_format == VGColor_sRGBA);
if(colorRampPremultiplied)
c=VGColorPremultiply(c);
return c;
}
VGColor KGPaintIntegrateColorRamp(KGPaint_ramp *self,RIfloat gmin, RIfloat gmax) {
RI_ASSERT(gmin <= gmax);
RI_ASSERT(gmin >= 0.0f && gmin <= 1.0f);
RI_ASSERT(gmax >= 0.0f && gmax <= 1.0f);
RI_ASSERT(self->m_colorRampStopsCount >= 2); //there are at least two stops
VGColor c=VGColorRGBA(0,0,0,0,self->m_colorRampPremultiplied ? VGColor_sRGBA_PRE : VGColor_sRGBA);
if(gmin == 1.0f || gmax == 0.0f)
return c;
int i=0;
for(;i<self->m_colorRampStopsCount-1;i++)
{
if(gmin >= self->m_colorRampStops[i].offset && gmin < self->m_colorRampStops[i+1].offset)
{
RIfloat s = self->m_colorRampStops[i].offset;
RIfloat e = self->m_colorRampStops[i+1].offset;
RI_ASSERT(s < e);
RIfloat g = (gmin - s) / (e - s);
VGColor sc = readStopColor(self->m_colorRampStops,self->m_colorRampStopsCount, i, self->m_colorRampPremultiplied);
VGColor ec = readStopColor(self->m_colorRampStops,self->m_colorRampStopsCount, i+1, self->m_colorRampPremultiplied);
VGColor rc = VGColorAdd(VGColorMultiplyByFloat(sc, (1.0f-g)),VGColorMultiplyByFloat(ec , g));
//subtract the average color from the start of the stop to gmin
c=VGColorSubtract(c,VGColorMultiplyByFloat(VGColorAdd(sc,rc) , 0.5f*(gmin - s)));
break;
}
}
for(;i<self->m_colorRampStopsCount-1;i++)
{
RIfloat s = self->m_colorRampStops[i].offset;
RIfloat e = self->m_colorRampStops[i+1].offset;
RI_ASSERT(s <= e);
VGColor sc = readStopColor(self->m_colorRampStops,self->m_colorRampStopsCount, i, self->m_colorRampPremultiplied);
VGColor ec = readStopColor(self->m_colorRampStops,self->m_colorRampStopsCount, i+1, self->m_colorRampPremultiplied);
//average of the stop
c=VGColorAdd(c , VGColorMultiplyByFloat(VGColorAdd(sc , ec), 0.5f*(e-s)));
if(gmax >= self->m_colorRampStops[i].offset && gmax < self->m_colorRampStops[i+1].offset)
{
RIfloat g = (gmax - s) / (e - s);
VGColor rc = VGColorAdd(VGColorMultiplyByFloat(sc , (1.0f-g)),VGColorMultiplyByFloat( ec , g));
//subtract the average color from gmax to the end of the stop
c=VGColorSubtract(c,VGColorMultiplyByFloat(VGColorAdd(rc , ec) , 0.5f*(e - gmax)));
break;
}
}
return c;
}
/*-------------------------------------------------------------------*//*!
* \brief Maps a gradient function value to a color.
* \param
* \return
* \note
*//*-------------------------------------------------------------------*/
VGColor KGPaintColorRamp(KGPaint_ramp *self,RIfloat gradient, RIfloat rho)
{
RI_ASSERT(self);
RI_ASSERT(rho >= 0.0f);
VGColor c=VGColorRGBA(0,0,0,0,self->m_colorRampPremultiplied ? VGColor_sRGBA_PRE : VGColor_sRGBA);
VGColor avg=VGColorZero();
if(rho == 0.0f)
{ //filter size is zero or gradient is degenerate
switch(self->m_colorRampSpreadMode)
{
case VG_COLOR_RAMP_SPREAD_PAD:
gradient = RI_CLAMP(gradient, 0.0f, 1.0f);
break;
case VG_COLOR_RAMP_SPREAD_REFLECT:
{
RIfloat g = RI_MOD(gradient, 2.0f);
gradient = (g < 1.0f) ? g : 2.0f - g;
break;
}
default:
RI_ASSERT(self->m_colorRampSpreadMode == VG_COLOR_RAMP_SPREAD_REPEAT);
gradient = gradient - (RIfloat)floor(gradient);
break;
}
RI_ASSERT(gradient >= 0.0f && gradient <= 1.0f);
int i;
for(i=0;i<self->m_colorRampStopsCount-1;i++)
{
if(gradient >= self->m_colorRampStops[i].offset && gradient < self->m_colorRampStops[i+1].offset)
{
RIfloat s = self->m_colorRampStops[i].offset;
RIfloat e = self->m_colorRampStops[i+1].offset;
RI_ASSERT(s < e);
RIfloat g = RI_CLAMP((gradient - s) / (e - s), 0.0f, 1.0f); //clamp needed due to numerical inaccuracies
VGColor sc = readStopColor(self->m_colorRampStops,self->m_colorRampStopsCount, i, self->m_colorRampPremultiplied);
VGColor ec = readStopColor(self->m_colorRampStops,self->m_colorRampStopsCount, i+1, self->m_colorRampPremultiplied);
return VGColorAdd(VGColorMultiplyByFloat(sc , (1.0f-g)) , VGColorMultiplyByFloat(ec , g)); //return interpolated value
}
}
return readStopColor(self->m_colorRampStops,self->m_colorRampStopsCount, self->m_colorRampStopsCount-1, self->m_colorRampPremultiplied);
}
RIfloat gmin = gradient - rho*0.5f; //filter starting from the gradient point (if starts earlier, radial gradient center will be an average of the first and the last stop, which doesn't look good)
RIfloat gmax = gradient + rho*0.5f;
switch(self->m_colorRampSpreadMode)
{
case VG_COLOR_RAMP_SPREAD_PAD:
{
if(gmin < 0.0f)
c=VGColorAdd(c,VGColorMultiplyByFloat(readStopColor(self->m_colorRampStops,self->m_colorRampStopsCount, 0, self->m_colorRampPremultiplied), (RI_MIN(gmax, 0.0f) - gmin)));
if(gmax > 1.0f)
c=VGColorAdd(c,VGColorMultiplyByFloat(readStopColor(self->m_colorRampStops,self->m_colorRampStopsCount, self->m_colorRampStopsCount-1, self->m_colorRampPremultiplied) , (gmax - RI_MAX(gmin, 1.0f))));
gmin = RI_CLAMP(gmin, 0.0f, 1.0f);
gmax = RI_CLAMP(gmax, 0.0f, 1.0f);
c=VGColorAdd(c, KGPaintIntegrateColorRamp(self,gmin, gmax));
c=VGColorMultiplyByFloat(c , 1.0f/rho);
c=VGColorClamp(c); //clamp needed due to numerical inaccuracies
return c;
}
case VG_COLOR_RAMP_SPREAD_REFLECT:
{
avg = KGPaintIntegrateColorRamp(self,0.0f, 1.0f);
RIfloat gmini = (RIfloat)floor(gmin);
RIfloat gmaxi = (RIfloat)floor(gmax);
c = VGColorMultiplyByFloat(avg , (gmaxi + 1.0f - gmini)); //full ramps
//subtract beginning
if(((int)gmini) & 1)
c=VGColorSubtract(c,KGPaintIntegrateColorRamp(self,RI_CLAMP(1.0f - (gmin - gmini), 0.0f, 1.0f), 1.0f));
else
c=VGColorSubtract(c,KGPaintIntegrateColorRamp(self,0.0f, RI_CLAMP(gmin - gmini, 0.0f, 1.0f)));
//subtract end
if(((int)gmaxi) & 1)
c=VGColorSubtract(c,KGPaintIntegrateColorRamp(self,0.0f, RI_CLAMP(1.0f - (gmax - gmaxi), 0.0f, 1.0f)));
else
c=VGColorSubtract(c,KGPaintIntegrateColorRamp(self,RI_CLAMP(gmax - gmaxi, 0.0f, 1.0f), 1.0f));
break;
}
default:
{
RI_ASSERT(self->m_colorRampSpreadMode == VG_COLOR_RAMP_SPREAD_REPEAT);
avg = KGPaintIntegrateColorRamp(self,0.0f, 1.0f);
RIfloat gmini = (RIfloat)floor(gmin);
RIfloat gmaxi = (RIfloat)floor(gmax);
c = VGColorMultiplyByFloat(avg , (gmaxi + 1.0f - gmini)); //full ramps
c=VGColorSubtract(c,KGPaintIntegrateColorRamp(self,0.0f, RI_CLAMP(gmin - gmini, 0.0f, 1.0f))); //subtract beginning
c=VGColorSubtract(c,KGPaintIntegrateColorRamp(self,RI_CLAMP(gmax - gmaxi, 0.0f, 1.0f), 1.0f)); //subtract end
break;
}
}
//divide color by the length of the range
c=VGColorMultiplyByFloat(c, 1.0f / rho);
c=VGColorClamp(c); //clamp needed due to numerical inaccuracies
//hide aliasing by fading to the average color
const RIfloat fadeStart = 0.5f;
const RIfloat fadeMultiplier = 2.0f; //the larger, the earlier fade to average is done
if(rho < fadeStart)
return c;
RIfloat ratio = RI_MIN((rho - fadeStart) * fadeMultiplier, 1.0f);
return VGColorAdd(VGColorMultiplyByFloat(avg , ratio) , VGColorMultiplyByFloat(c , (1.0f - ratio)));
}
@end

View File

@ -1,106 +0,0 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*-------------------------------------------------------------------*/
#import <Foundation/Foundation.h>
#import <ApplicationServices/ApplicationServices.h>
#import "VGmath.h"
#import "KGSurface.h"
typedef enum {
VG_PAINT_TYPE_COLOR,
VG_PAINT_TYPE_LINEAR_GRADIENT,
VG_PAINT_TYPE_RADIAL_GRADIENT,
VG_PAINT_TYPE_PATTERN
} VGPaintType;
typedef enum {
VG_COLOR_RAMP_SPREAD_PAD,
VG_COLOR_RAMP_SPREAD_REPEAT,
VG_COLOR_RAMP_SPREAD_REFLECT
} VGColorRampSpreadMode;
typedef struct {
RIfloat offset;
VGColor color;
} GradientStop;
typedef struct {
VGPaintType m_paintType;
VGColor m_paintColor;
VGColor m_inputPaintColor;
VGColorRampSpreadMode m_colorRampSpreadMode;
int m_colorRampStopsCount;
int m_colorRampStopsCapacity;
GradientStop *m_colorRampStops;
BOOL m_colorRampPremultiplied;
Vector2 m_linearGradientPoint0;
Vector2 m_linearGradientPoint1;
Vector2 m_radialGradientCenter;
Vector2 m_radialGradientFocalPoint;
RIfloat m_radialGradientRadius;
KGSurface* m_pattern;
} KGPaint;
KGPaint *KGPaintAlloc();
KGPaint *KGPaintInit(KGPaint *self);
void KGPaintDealloc(KGPaint *self);
@interface KGPixelPipe : NSObject {
KGSurface* m_renderingSurface;
KGSurface* m_mask;
KGImage* m_image;
KGPaint* m_paint;
KGPaint * m_defaultPaint;
CGBlendMode m_blendMode;
KGSurfaceMode m_imageMode;
CGInterpolationQuality m_imageQuality;
Matrix3x3 m_surfaceToPaintMatrix;
Matrix3x3 m_surfaceToImageMatrix;
}
KGPixelPipe *KGPixelPipeAlloc();
KGPixelPipe *KGPixelPipeInit(KGPixelPipe *self);
void KGPixelPipeDealloc(KGPixelPipe *self);
void KGPixelPipeSetRenderingSurface(KGPixelPipe *self,KGSurface *renderingSurface);
void KGPixelPipeSetBlendMode(KGPixelPipe *self,CGBlendMode blendMode);
void KGPixelPipeSetMask(KGPixelPipe *self,KGSurface* mask);
void KGPixelPipeSetImage(KGPixelPipe *self,KGImage *image, KGSurfaceMode imageMode);
void KGPixelPipeSetSurfaceToPaintMatrix(KGPixelPipe *self,Matrix3x3 surfaceToPaintMatrix);
void KGPixelPipeSetSurfaceToImageMatrix(KGPixelPipe *self,Matrix3x3 surfaceToImageMatrix);
void KGPixelPipeSetImageQuality(KGPixelPipe *self,CGInterpolationQuality imageQuality);
void KGPixelPipeSetPaint(KGPixelPipe *self,KGPaint* paint);
//private
void KGPixelPipeLinearGradient(KGPixelPipe *self,RIfloat *g, RIfloat *rho, RIfloat x, RIfloat y);
void KGPixelPipeRadialGradient(KGPixelPipe *self,RIfloat *g, RIfloat *rho, RIfloat x, RIfloat y);
VGColor KGPixelPipeIntegrateColorRamp(KGPixelPipe *self,RIfloat gmin, RIfloat gmax);
VGColor KGPixelPipeColorRamp(KGPixelPipe *self,RIfloat gradient, RIfloat rho);
void KGPixelPipeWriteCoverage(KGPixelPipe *self,int x, int y,RIfloat *coverage,int length);
@end

View File

@ -1,765 +0,0 @@
/*------------------------------------------------------------------------
*
* Derivative of the OpenVG 1.0.1 Reference Implementation
* -------------------------------------
*
* Copyright (c) 2007 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and /or associated documentation files
* (the "Materials "), to deal in the Materials without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Materials,
* and to permit persons to whom the Materials are furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE 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 MATERIALS OR
* THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*//**
* \file
* \brief Implementation of KGPaint and pixel pipe functionality.
* \note
*//*-------------------------------------------------------------------*/
#import "KGPixelPipe.h"
#import "KGBlending.h"
#import "KGSurface.h"
KGPaint *KGPaintAlloc() {
return (KGPaint *)NSZoneCalloc(NULL,1,sizeof(KGPaint));
}
KGPaint *KGPaintInit(KGPaint *self) {
self->m_paintType=VG_PAINT_TYPE_COLOR;
self->m_paintColor=VGColorRGBA(0,0,0,1,VGColor_lRGBA_PRE);
self->m_inputPaintColor=VGColorRGBA(0,0,0,1,VGColor_lRGBA);
self->m_colorRampSpreadMode=VG_COLOR_RAMP_SPREAD_PAD;
self->m_colorRampStopsCount=2;
self->m_colorRampStopsCapacity=2;
self->m_colorRampStops=(GradientStop *)NSZoneCalloc(NULL,self->m_colorRampStopsCapacity,sizeof(GradientStop));
self->m_colorRampPremultiplied=YES;
self->m_linearGradientPoint0=Vector2Make(0,0);
self->m_linearGradientPoint1=Vector2Make(1,0);
self->m_radialGradientCenter=Vector2Make(0,0);
self->m_radialGradientFocalPoint=Vector2Make(0,0);
self->m_radialGradientRadius=1.0f;
self->m_pattern=NULL;
GradientStop gs;
gs.offset = 0.0f;
gs.color=VGColorRGBA(0,0,0,1,VGColor_sRGBA);
self->m_colorRampStops[0]=gs;
gs.offset = 1.0f;
gs.color=VGColorRGBA(1,1,1,1,VGColor_sRGBA);
self->m_colorRampStops[1]=gs;
return self;
}
void KGPaintDealloc(KGPaint *self) {
if(self->m_pattern)
{
KGSurfaceDealloc(self->m_pattern);
}
}
@implementation KGPixelPipe
KGPixelPipe *KGPixelPipeAlloc() {
return (KGPixelPipe *)NSZoneCalloc(NULL,1,sizeof(KGPixelPipe));
}
KGPixelPipe *KGPixelPipeInit(KGPixelPipe *self) {
self->m_renderingSurface=NULL;
self->m_mask=NULL;
self->m_image=NULL;
self->m_paint=NULL;
self->m_defaultPaint=KGPaintInit(KGPaintAlloc());
self->m_blendMode=kCGBlendModeNormal;
self->m_imageMode=VG_DRAW_IMAGE_NORMAL;
self->m_imageQuality=kCGInterpolationLow;
self->m_surfaceToPaintMatrix=Matrix3x3Identity();
self->m_surfaceToImageMatrix=Matrix3x3Identity();
return self;
}
void KGPixelPipeDealloc(KGPixelPipe *self) {
NSZoneFree(NULL,self);
}
void KGPixelPipeSetRenderingSurface(KGPixelPipe *self,KGSurface *renderingSurface) {
RI_ASSERT(renderingSurface);
self->m_renderingSurface = renderingSurface;
}
void KGPixelPipeSetBlendMode(KGPixelPipe *self,CGBlendMode blendMode) {
RI_ASSERT(blendMode >= kCGBlendModeNormal && blendMode <= kCGBlendModePlusLighter);
self->m_blendMode = blendMode;
}
void KGPixelPipeSetMask(KGPixelPipe *self,KGSurface* mask) {
self->m_mask = mask;
}
void KGPixelPipeSetImage(KGPixelPipe *self,KGImage *image, KGSurfaceMode imageMode) {
RI_ASSERT(imageMode == VG_DRAW_IMAGE_NORMAL || imageMode == VG_DRAW_IMAGE_MULTIPLY || imageMode == VG_DRAW_IMAGE_STENCIL);
self->m_image = image;
self->m_imageMode = imageMode;
}
void KGPixelPipeSetSurfaceToPaintMatrix(KGPixelPipe *self,Matrix3x3 surfaceToPaintMatrix) {
self->m_surfaceToPaintMatrix = surfaceToPaintMatrix;
}
void KGPixelPipeSetSurfaceToImageMatrix(KGPixelPipe *self,Matrix3x3 surfaceToImageMatrix) {
self->m_surfaceToImageMatrix = surfaceToImageMatrix;
}
void KGPixelPipeSetImageQuality(KGPixelPipe *self,CGInterpolationQuality imageQuality) {
RI_ASSERT(imageQuality == kCGInterpolationNone || imageQuality == kCGInterpolationLow || imageQuality == kCGInterpolationHigh);
self->m_imageQuality = imageQuality;
}
void KGPixelPipeSetPaint(KGPixelPipe *self, KGPaint* paint) {
self->m_paint = paint;
if(!self->m_paint)
self->m_paint = self->m_defaultPaint;
}
void KGPixelPipeLinearGradient(KGPixelPipe *self,RIfloat *g, RIfloat *rho, RIfloat x, RIfloat y) {
RI_ASSERT(self->m_paint);
Vector2 u = Vector2Subtract(self->m_paint->m_linearGradientPoint1 , self->m_paint->m_linearGradientPoint0);
RIfloat usq = Vector2Dot(u,u);
if( usq <= 0.0f )
{ //points are equal, gradient is always 1.0f
*g = 1.0f;
*rho = 0.0f;
return;
}
RIfloat oou = 1.0f / usq;
Vector2 p=Vector2Make(x, y);
p = Matrix3x3TransformVector2(self->m_surfaceToPaintMatrix, p);
p = Vector2Subtract(p,self->m_paint->m_linearGradientPoint0);
RI_ASSERT(usq >= 0.0f);
*g = Vector2Dot(p, u) * oou;
RIfloat dgdx = oou * u.x * self->m_surfaceToPaintMatrix.matrix[0][0] + oou * u.y * self->m_surfaceToPaintMatrix.matrix[1][0];
RIfloat dgdy = oou * u.x * self->m_surfaceToPaintMatrix.matrix[0][1] + oou * u.y * self->m_surfaceToPaintMatrix.matrix[1][1];
*rho = (RIfloat)sqrt(dgdx*dgdx + dgdy*dgdy);
RI_ASSERT(*rho >= 0.0f);
}
void KGPixelPipeRadialGradient(KGPixelPipe *self,RIfloat *g, RIfloat *rho, RIfloat x, RIfloat y) {
RI_ASSERT(self->m_paint);
if( self->m_paint->m_radialGradientRadius <= 0.0f )
{
*g = 1.0f;
*rho = 0.0f;
return;
}
RIfloat r = self->m_paint->m_radialGradientRadius;
Vector2 c = self->m_paint->m_radialGradientCenter;
Vector2 f = self->m_paint->m_radialGradientFocalPoint;
Vector2 gx=Vector2Make(self->m_surfaceToPaintMatrix.matrix[0][0], self->m_surfaceToPaintMatrix.matrix[1][0]);
Vector2 gy=Vector2Make(self->m_surfaceToPaintMatrix.matrix[0][1],self->m_surfaceToPaintMatrix.matrix[1][1]);
Vector2 fp = Vector2Subtract(f,c);
//clamp the focal point inside the gradient circle
RIfloat fpLen = Vector2Length(fp);
if( fpLen > 0.999f * r )
fp = Vector2MultiplyByFloat(fp, (0.999f * r / fpLen));
RIfloat D = -1.0f / (Vector2Dot(fp,fp) - r*r);
Vector2 p=Vector2Make(x, y);
p = Vector2Subtract(Matrix3x3TransformVector2(self->m_surfaceToPaintMatrix, p), c);
Vector2 d = Vector2Subtract(p,fp);
RIfloat s = (RIfloat)sqrt(r*r*Vector2Dot(d,d) - RI_SQR(p.x*fp.y - p.y*fp.x));
*g = (Vector2Dot(fp,d) + s) * D;
if(RI_ISNAN(*g))
*g = 0.0f;
RIfloat dgdx = D*Vector2Dot(fp,gx) + (r*r*Vector2Dot(d,gx) - (gx.x*fp.y - gx.y*fp.x)*(p.x*fp.y - p.y*fp.x)) * (D / s);
RIfloat dgdy = D*Vector2Dot(fp,gy) + (r*r*Vector2Dot(d,gy) - (gy.x*fp.y - gy.y*fp.x)*(p.x*fp.y - p.y*fp.x)) * (D / s);
*rho = (RIfloat)sqrt(dgdx*dgdx + dgdy*dgdy);
if(RI_ISNAN(*rho))
*rho = 0.0f;
RI_ASSERT(*rho >= 0.0f);
}
/*-------------------------------------------------------------------*//*!
* \brief Returns the average color within an offset range in the color ramp.
* \param
* \return
* \note
*//*-------------------------------------------------------------------*/
static VGColor readStopColor(GradientStop *colorRampStops,int colorRampStopsCount, int i, BOOL colorRampPremultiplied)
{
RI_ASSERT(i >= 0 && i < colorRampStopsCount);
VGColor c = colorRampStops[i].color;
RI_ASSERT(c.m_format == VGColor_sRGBA);
if(colorRampPremultiplied)
c=VGColorPremultiply(c);
return c;
}
VGColor KGPixelPipeIntegrateColorRamp(KGPixelPipe *self,RIfloat gmin, RIfloat gmax) {
RI_ASSERT(gmin <= gmax);
RI_ASSERT(gmin >= 0.0f && gmin <= 1.0f);
RI_ASSERT(gmax >= 0.0f && gmax <= 1.0f);
RI_ASSERT(self->m_paint->m_colorRampStopsCount >= 2); //there are at least two stops
VGColor c=VGColorRGBA(0,0,0,0,self->m_paint->m_colorRampPremultiplied ? VGColor_sRGBA_PRE : VGColor_sRGBA);
if(gmin == 1.0f || gmax == 0.0f)
return c;
int i=0;
for(;i<self->m_paint->m_colorRampStopsCount-1;i++)
{
if(gmin >= self->m_paint->m_colorRampStops[i].offset && gmin < self->m_paint->m_colorRampStops[i+1].offset)
{
RIfloat s = self->m_paint->m_colorRampStops[i].offset;
RIfloat e = self->m_paint->m_colorRampStops[i+1].offset;
RI_ASSERT(s < e);
RIfloat g = (gmin - s) / (e - s);
VGColor sc = readStopColor(self->m_paint->m_colorRampStops,self->m_paint->m_colorRampStopsCount, i, self->m_paint->m_colorRampPremultiplied);
VGColor ec = readStopColor(self->m_paint->m_colorRampStops,self->m_paint->m_colorRampStopsCount, i+1, self->m_paint->m_colorRampPremultiplied);
VGColor rc = VGColorAdd(VGColorMultiplyByFloat(sc, (1.0f-g)),VGColorMultiplyByFloat(ec , g));
//subtract the average color from the start of the stop to gmin
c=VGColorSubtract(c,VGColorMultiplyByFloat(VGColorAdd(sc,rc) , 0.5f*(gmin - s)));
break;
}
}
for(;i<self->m_paint->m_colorRampStopsCount-1;i++)
{
RIfloat s = self->m_paint->m_colorRampStops[i].offset;
RIfloat e = self->m_paint->m_colorRampStops[i+1].offset;
RI_ASSERT(s <= e);
VGColor sc = readStopColor(self->m_paint->m_colorRampStops,self->m_paint->m_colorRampStopsCount, i, self->m_paint->m_colorRampPremultiplied);
VGColor ec = readStopColor(self->m_paint->m_colorRampStops,self->m_paint->m_colorRampStopsCount, i+1, self->m_paint->m_colorRampPremultiplied);
//average of the stop
c=VGColorAdd(c , VGColorMultiplyByFloat(VGColorAdd(sc , ec), 0.5f*(e-s)));
if(gmax >= self->m_paint->m_colorRampStops[i].offset && gmax < self->m_paint->m_colorRampStops[i+1].offset)
{
RIfloat g = (gmax - s) / (e - s);
VGColor rc = VGColorAdd(VGColorMultiplyByFloat(sc , (1.0f-g)),VGColorMultiplyByFloat( ec , g));
//subtract the average color from gmax to the end of the stop
c=VGColorSubtract(c,VGColorMultiplyByFloat(VGColorAdd(rc , ec) , 0.5f*(e - gmax)));
break;
}
}
return c;
}
/*-------------------------------------------------------------------*//*!
* \brief Maps a gradient function value to a color.
* \param
* \return
* \note
*//*-------------------------------------------------------------------*/
VGColor KGPixelPipeColorRamp(KGPixelPipe *self,RIfloat gradient, RIfloat rho)
{
RI_ASSERT(self->m_paint);
RI_ASSERT(rho >= 0.0f);
VGColor c=VGColorRGBA(0,0,0,0,self->m_paint->m_colorRampPremultiplied ? VGColor_sRGBA_PRE : VGColor_sRGBA);
VGColor avg=VGColorZero();
if(rho == 0.0f)
{ //filter size is zero or gradient is degenerate
switch(self->m_paint->m_colorRampSpreadMode)
{
case VG_COLOR_RAMP_SPREAD_PAD:
gradient = RI_CLAMP(gradient, 0.0f, 1.0f);
break;
case VG_COLOR_RAMP_SPREAD_REFLECT:
{
RIfloat g = RI_MOD(gradient, 2.0f);
gradient = (g < 1.0f) ? g : 2.0f - g;
break;
}
default:
RI_ASSERT(self->m_paint->m_colorRampSpreadMode == VG_COLOR_RAMP_SPREAD_REPEAT);
gradient = gradient - (RIfloat)floor(gradient);
break;
}
RI_ASSERT(gradient >= 0.0f && gradient <= 1.0f);
int i;
for(i=0;i<self->m_paint->m_colorRampStopsCount-1;i++)
{
if(gradient >= self->m_paint->m_colorRampStops[i].offset && gradient < self->m_paint->m_colorRampStops[i+1].offset)
{
RIfloat s = self->m_paint->m_colorRampStops[i].offset;
RIfloat e = self->m_paint->m_colorRampStops[i+1].offset;
RI_ASSERT(s < e);
RIfloat g = RI_CLAMP((gradient - s) / (e - s), 0.0f, 1.0f); //clamp needed due to numerical inaccuracies
VGColor sc = readStopColor(self->m_paint->m_colorRampStops,self->m_paint->m_colorRampStopsCount, i, self->m_paint->m_colorRampPremultiplied);
VGColor ec = readStopColor(self->m_paint->m_colorRampStops,self->m_paint->m_colorRampStopsCount, i+1, self->m_paint->m_colorRampPremultiplied);
return VGColorAdd(VGColorMultiplyByFloat(sc , (1.0f-g)) , VGColorMultiplyByFloat(ec , g)); //return interpolated value
}
}
return readStopColor(self->m_paint->m_colorRampStops,self->m_paint->m_colorRampStopsCount, self->m_paint->m_colorRampStopsCount-1, self->m_paint->m_colorRampPremultiplied);
}
RIfloat gmin = gradient - rho*0.5f; //filter starting from the gradient point (if starts earlier, radial gradient center will be an average of the first and the last stop, which doesn't look good)
RIfloat gmax = gradient + rho*0.5f;
switch(self->m_paint->m_colorRampSpreadMode)
{
case VG_COLOR_RAMP_SPREAD_PAD:
{
if(gmin < 0.0f)
c=VGColorAdd(c,VGColorMultiplyByFloat(readStopColor(self->m_paint->m_colorRampStops,self->m_paint->m_colorRampStopsCount, 0, self->m_paint->m_colorRampPremultiplied), (RI_MIN(gmax, 0.0f) - gmin)));
if(gmax > 1.0f)
c=VGColorAdd(c,VGColorMultiplyByFloat(readStopColor(self->m_paint->m_colorRampStops,self->m_paint->m_colorRampStopsCount, self->m_paint->m_colorRampStopsCount-1, self->m_paint->m_colorRampPremultiplied) , (gmax - RI_MAX(gmin, 1.0f))));
gmin = RI_CLAMP(gmin, 0.0f, 1.0f);
gmax = RI_CLAMP(gmax, 0.0f, 1.0f);
c=VGColorAdd(c, KGPixelPipeIntegrateColorRamp(self,gmin, gmax));
c=VGColorMultiplyByFloat(c , 1.0f/rho);
c=VGColorClamp(c); //clamp needed due to numerical inaccuracies
return c;
}
case VG_COLOR_RAMP_SPREAD_REFLECT:
{
avg = KGPixelPipeIntegrateColorRamp(self,0.0f, 1.0f);
RIfloat gmini = (RIfloat)floor(gmin);
RIfloat gmaxi = (RIfloat)floor(gmax);
c = VGColorMultiplyByFloat(avg , (gmaxi + 1.0f - gmini)); //full ramps
//subtract beginning
if(((int)gmini) & 1)
c=VGColorSubtract(c,KGPixelPipeIntegrateColorRamp(self,RI_CLAMP(1.0f - (gmin - gmini), 0.0f, 1.0f), 1.0f));
else
c=VGColorSubtract(c,KGPixelPipeIntegrateColorRamp(self,0.0f, RI_CLAMP(gmin - gmini, 0.0f, 1.0f)));
//subtract end
if(((int)gmaxi) & 1)
c=VGColorSubtract(c,KGPixelPipeIntegrateColorRamp(self,0.0f, RI_CLAMP(1.0f - (gmax - gmaxi), 0.0f, 1.0f)));
else
c=VGColorSubtract(c,KGPixelPipeIntegrateColorRamp(self,RI_CLAMP(gmax - gmaxi, 0.0f, 1.0f), 1.0f));
break;
}
default:
{
RI_ASSERT(self->m_paint->m_colorRampSpreadMode == VG_COLOR_RAMP_SPREAD_REPEAT);
avg = KGPixelPipeIntegrateColorRamp(self,0.0f, 1.0f);
RIfloat gmini = (RIfloat)floor(gmin);
RIfloat gmaxi = (RIfloat)floor(gmax);
c = VGColorMultiplyByFloat(avg , (gmaxi + 1.0f - gmini)); //full ramps
c=VGColorSubtract(c,KGPixelPipeIntegrateColorRamp(self,0.0f, RI_CLAMP(gmin - gmini, 0.0f, 1.0f))); //subtract beginning
c=VGColorSubtract(c,KGPixelPipeIntegrateColorRamp(self,RI_CLAMP(gmax - gmaxi, 0.0f, 1.0f), 1.0f)); //subtract end
break;
}
}
//divide color by the length of the range
c=VGColorMultiplyByFloat(c, 1.0f / rho);
c=VGColorClamp(c); //clamp needed due to numerical inaccuracies
//hide aliasing by fading to the average color
const RIfloat fadeStart = 0.5f;
const RIfloat fadeMultiplier = 2.0f; //the larger, the earlier fade to average is done
if(rho < fadeStart)
return c;
RIfloat ratio = RI_MIN((rho - fadeStart) * fadeMultiplier, 1.0f);
return VGColorAdd(VGColorMultiplyByFloat(avg , ratio) , VGColorMultiplyByFloat(c , (1.0f - ratio)));
}
static inline VGColor linearGradientColorAt(KGPixelPipe *self,int x,int y){
VGColor result;
RIfloat g, rho;
KGPixelPipeLinearGradient(self,&g, &rho, x+0.5f, y+0.5f);
result = KGPixelPipeColorRamp(self,g, rho);
RI_ASSERT((result.m_format == VGColor_sRGBA && !self->m_paint->m_colorRampPremultiplied) || (result.m_format == VGColor_sRGBA_PRE && self->m_paint->m_colorRampPremultiplied));
return VGColorPremultiply(result);
}
static inline VGColor radialGradientColorAt(KGPixelPipe *self,int x,int y){
VGColor result;
RIfloat g, rho;
KGPixelPipeRadialGradient(self,&g, &rho, x+0.5f, y+0.5f);
result = KGPixelPipeColorRamp(self,g, rho);
RI_ASSERT((result.m_format == VGColor_sRGBA && !self->m_paint->m_colorRampPremultiplied) || (result.m_format == VGColor_sRGBA_PRE && self->m_paint->m_colorRampPremultiplied));
return VGColorPremultiply(result);
}
static void KGPixelPipeReadPremultipliedConstantSourceSpan(KGPixelPipe *self,int x,int y,KGRGBAffff *span,int length,int format){
KGRGBAffff rgba=KGRGBAffffFromColor(VGColorConvert(self->m_paint->m_paintColor,format));
int i;
for(i=0;i<length;i++)
span[i]=rgba;
}
static void KGPixelPipeReadPremultipliedLinearGradientSpan(KGPixelPipe *self,int x,int y,KGRGBAffff *span,int length,int format){
int i;
for(i=0;i<length;i++,x++){
VGColor s=linearGradientColorAt(self,x,y);
span[i]=KGRGBAffffFromColor(VGColorConvert(s,format));
}
}
static void KGPixelPipeReadPremultipliedRadialGradientSpan(KGPixelPipe *self,int x,int y,KGRGBAffff *span,int length,int format){
int i;
for(i=0;i<length;i++,x++){
VGColor s=radialGradientColorAt(self,x,y);
span[i]=KGRGBAffffFromColor(VGColorConvert(s,format));
}
}
static void KGPixelPipeReadPremultipliedPatternSpan(KGPixelPipe *self,int x,int y,KGRGBAffff *span,int length,int format){
if(self->m_paint->m_pattern==NULL)
KGPixelPipeReadPremultipliedConstantSourceSpan(self,x,y,span,length,format);
else {
KGSurfacePatternSpan(self->m_paint->m_pattern,x, y,span,length,format, self->m_surfaceToPaintMatrix, kCGPatternTilingConstantSpacing);
}
}
static void KGPixelPipeReadPremultipliedImageNormalSpan(KGPixelPipe *self,int x,int y,KGRGBAffff *span,int length,VGColorInternalFormat format){
VGColorInternalFormat spanFormat;
if(self->m_imageQuality== kCGInterpolationHigh){
spanFormat=KGImageResample_EWAOnMipmaps(self->m_image,x,y,span,length,self->m_surfaceToImageMatrix);
// spanFormat=KGImageResample_Bicubic(self->m_image,x,y,span,length,self->m_surfaceToImageMatrix);
}
else if(self->m_imageQuality== kCGInterpolationLow)
spanFormat=KGImageResample_Bilinear(self->m_image,x,y,span,length,self->m_surfaceToImageMatrix);
else
spanFormat=KGImageResample_PointSampling(self->m_image,x,y,span,length,self->m_surfaceToImageMatrix);
if(!(spanFormat&VGColorPREMULTIPLIED)){
KGRGBPremultiplySpan(span,length);
spanFormat|=VGColorPREMULTIPLIED;
}
convertSpan(span,length,spanFormat,format);
}
static void KGPixelPipeReadPremultipliedSourceSpan(KGPixelPipe *self,int x,int y,KGRGBAffff *span,int length,int format){
int i;
RI_ASSERT(self->m_paint);
switch(self->m_paint->m_paintType){
case VG_PAINT_TYPE_COLOR:
KGPixelPipeReadPremultipliedConstantSourceSpan(self,x,y,span,length,format);
break;
case VG_PAINT_TYPE_LINEAR_GRADIENT:
KGPixelPipeReadPremultipliedLinearGradientSpan(self,x,y,span,length,format);
break;
case VG_PAINT_TYPE_RADIAL_GRADIENT:
KGPixelPipeReadPremultipliedRadialGradientSpan(self,x,y,span,length,format);
break;
case VG_PAINT_TYPE_PATTERN:
KGPixelPipeReadPremultipliedPatternSpan(self,x,y,span,length,format);
break;
}
if(self->m_image!=NULL){
if(self->m_imageMode==VG_DRAW_IMAGE_NORMAL){
KGPixelPipeReadPremultipliedImageNormalSpan(self,x,y,span,length,format);
}
else {
KGRGBAffff imageSpan[length];
KGPixelPipeReadPremultipliedImageNormalSpan(self,x,y,imageSpan,length,KGImageColorFormat(self->m_image)|VGColorPREMULTIPLIED);
for(i=0;i<length;i++,x++){
//evaluate paint
VGColor s=VGColorFromKGRGBA_ffff(span[i],format);
VGColor im=VGColorFromKGRGBA_ffff(imageSpan[i],KGImageColorFormat(self->m_image));
//apply image (vgDrawImage only)
//1. paint: convert paint to dst space
//2. image: convert image to dst space
//3. paint MULTIPLY image: convert paint to image number of channels, multiply with image, and convert to dst
//4. paint STENCIL image: convert paint to dst, convert image to dst number of channels, multiply
RI_ASSERT((s.m_format & VGColorLUMINANCE && s.r == s.g && s.r == s.b) || !(s.m_format & VGColorLUMINANCE)); //if luminance, r=g=b
RI_ASSERT((im.m_format & VGColorLUMINANCE && im.r == im.g && im.r == im.b) || !(im.m_format & VGColorLUMINANCE)); //if luminance, r=g=b
switch(self->m_imageMode)
{
case VG_DRAW_IMAGE_MULTIPLY:
//the result will be in image color space. If the number of channels in image and paint
// colors differ, convert to the number of channels in the image color.
//paint == RGB && image == RGB: RGB*RGB
//paint == RGB && image == L : (0.2126 R + 0.7152 G + 0.0722 B)*L
//paint == L && image == RGB: LLL*RGB
//paint == L && image == L : L*L
if(!(s.m_format & VGColorLUMINANCE) && im.m_format & VGColorLUMINANCE)
{
s.r = s.g = s.b = RI_MIN(0.2126f*s.r + 0.7152f*s.g + 0.0722f*s.b, s.a);
}
RI_ASSERT(Matrix3x3IsAffine(self->m_surfaceToPaintMatrix));
im.r *= s.r;
im.g *= s.g;
im.b *= s.b;
im.a *= s.a;
s = im;
s=VGColorConvert(s,format); //convert resulting color to destination color space
break;
case VG_DRAW_IMAGE_STENCIL:
{
// FIX
// This needs to be changed to a nonpremultplied form. This is the only case which used ar, ag, ab premultiplied values for source.
RIfloat ar = s.a, ag = s.a, ab = s.a;
//the result will be in paint color space.
//dst == RGB && image == RGB: RGB*RGB
//dst == RGB && image == L : RGB*LLL
//dst == L && image == RGB: L*(0.2126 R + 0.7152 G + 0.0722 B)
//dst == L && image == L : L*L
RI_ASSERT(self->m_imageMode == VG_DRAW_IMAGE_STENCIL);
if(format & VGColorLUMINANCE && !(im.m_format & VGColorLUMINANCE))
{
im.r = im.g = im.b = RI_MIN(0.2126f*im.r + 0.7152f*im.g + 0.0722f*im.b, im.a);
}
RI_ASSERT(Matrix3x3IsAffine(self->m_surfaceToPaintMatrix));
//s and im are both in premultiplied format. Each image channel acts as an alpha channel.
s=VGColorConvert(s,format); //convert paint color to destination space already here, since convert cannot deal with per channel alphas used in this mode.
s.r *= im.r;
s.g *= im.g;
s.b *= im.b;
s.a *= im.a;
ar *= im.r;
ag *= im.g;
ab *= im.b;
//in nonpremultiplied form the result is
// s.rgb = paint.a * paint.rgb * image.a * image.rgb
// s.a = paint.a * image.a
// argb = paint.a * image.a * image.rgb
RI_ASSERT(s.r >= 0.0f && s.r <= s.a && s.r <= ar);
RI_ASSERT(s.g >= 0.0f && s.g <= s.a && s.g <= ag);
RI_ASSERT(s.b >= 0.0f && s.b <= s.a && s.b <= ab);
}
break;
}
span[i]=KGRGBAffffFromColor(s);
}
}
}
}
static void KGBlendSpanWithMode_ffff(KGRGBAffff *src,KGRGBAffff *dst,int length,CGBlendMode blendMode){
switch(blendMode){
case kCGBlendModeNormal:
KGBlendSpanNormal_ffff(src,dst,length);
break;
case kCGBlendModeMultiply:
KGBlendSpanMultiply_ffff(src,dst,length);
break;
case kCGBlendModeScreen:
KGBlendSpanScreen_ffff(src,dst,length);
break;
case kCGBlendModeOverlay:
KGBlendSpanOverlay_ffff(src,dst,length);
break;
case kCGBlendModeDarken:
KGBlendSpanDarken_ffff(src,dst,length);
break;
case kCGBlendModeLighten:
KGBlendSpanLighten_ffff(src,dst,length);
break;
case kCGBlendModeColorDodge:
KGBlendSpanColorDodge_ffff(src,dst,length);
break;
case kCGBlendModeColorBurn:
KGBlendSpanColorBurn_ffff(src,dst,length);
break;
case kCGBlendModeHardLight:
KGBlendSpanHardLight_ffff(src,dst,length);
break;
case kCGBlendModeSoftLight:
KGBlendSpanSoftLight_ffff(src,dst,length);
break;
case kCGBlendModeDifference:
KGBlendSpanDifference_ffff(src,dst,length);
break;
case kCGBlendModeExclusion:
KGBlendSpanExclusion_ffff(src,dst,length);
break;
case kCGBlendModeHue:
KGBlendSpanHue_ffff(src,dst,length);
break;
case kCGBlendModeSaturation:
KGBlendSpanSaturation_ffff(src,dst,length);
break;
case kCGBlendModeColor:
KGBlendSpanColor_ffff(src,dst,length);
break;
case kCGBlendModeLuminosity:
KGBlendSpanLuminosity_ffff(src,dst,length);
break;
case kCGBlendModeClear:
KGBlendSpanClear_ffff(src,dst,length);
break;
case kCGBlendModeCopy:
KGBlendSpanCopy_ffff(src,dst,length);
break;
case kCGBlendModeSourceIn:
KGBlendSpanSourceIn_ffff(src,dst,length);
break;
case kCGBlendModeSourceOut:
KGBlendSpanSourceOut_ffff(src,dst,length);
break;
case kCGBlendModeSourceAtop:
KGBlendSpanSourceAtop_ffff(src,dst,length);
break;
case kCGBlendModeDestinationOver:
KGBlendSpanDestinationOver_ffff(src,dst,length);
break;
case kCGBlendModeDestinationIn:
KGBlendSpanDestinationIn_ffff(src,dst,length);
break;
case kCGBlendModeDestinationOut:
KGBlendSpanDestinationOut_ffff(src,dst,length);
break;
case kCGBlendModeDestinationAtop:
KGBlendSpanDestinationAtop_ffff(src,dst,length);
break;
case kCGBlendModeXOR:
KGBlendSpanXOR_ffff(src,dst,length);
break;
case kCGBlendModePlusDarker:
KGBlendSpanPlusDarker_ffff(src,dst,length);
break;
case kCGBlendModePlusLighter:
KGBlendSpanPlusLighter_ffff(src,dst,length);
break;
}
}
static inline KGRGBAffff KGRGBAffffConvert(KGRGBAffff rgba,int fromFormat,int toFormat){
VGColor color=VGColorFromKGRGBA_ffff(rgba,fromFormat);
color=VGColorConvert(color,toFormat);
return KGRGBAffffFromColor(color);
}
static VGColorInternalFormat KGApplyCoverageToSpan(KGRGBAffff *dst,RIfloat *coverage,KGRGBAffff *result,int length,VGColorInternalFormat dFormat){
//apply antialiasing in linear color space
VGColorInternalFormat aaFormat = (dFormat & VGColorLUMINANCE) ? VGColor_lLA_PRE : VGColor_lRGBA_PRE;
int i;
if(aaFormat!=dFormat){
for(i=0;i<length;i++){
KGRGBAffff r=result[i];
KGRGBAffff d=dst[i];
RIfloat cov=coverage[i];
r=KGRGBAffffConvert(r,dFormat,aaFormat);
d=KGRGBAffffConvert(d,dFormat,aaFormat);
result[i]=KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(r , cov) , KGRGBAffffMultiplyByFloat(d , (1.0f - cov)));
}
return aaFormat;
}
else {
for(i=0;i<length;i++){
KGRGBAffff r=result[i];
KGRGBAffff d=dst[i];
RIfloat cov=coverage[i];
result[i]=KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(r , cov) , KGRGBAffffMultiplyByFloat(d , (1.0f - cov)));
}
return dFormat;
}
}
void KGPixelPipeWriteCoverage(KGPixelPipe *self,int x, int y,RIfloat *coverage,int length) {
RI_ASSERT(self->m_renderingSurface);
//apply masking
if(self->m_mask)
KGSurfaceReadMaskPixelSpanIntoCoverage(self->m_mask,x,y,coverage,length);
// This optimization may not make sense in the bulk computations
// if(coverage[0..length] == 0.0f)
// return;
//read destination color
KGRGBAffff d[length];
VGColorInternalFormat dFormat=KGSurfaceReadPremultipliedSpan_ffff(self->m_renderingSurface,x,y,d,length);
KGRGBAffff src[length];
KGPixelPipeReadPremultipliedSourceSpan(self,x,y,src,length,dFormat);
KGBlendSpanWithMode_ffff(src,d,length,self->m_blendMode);
VGColorInternalFormat resultFormat;
resultFormat=KGApplyCoverageToSpan(d,coverage,src,length,dFormat);
//write result to the destination surface
KGSurfaceWritePixelSpan(self->m_renderingSurface,x,y,src,length,resultFormat);
}
@end

View File

@ -27,8 +27,9 @@
*-------------------------------------------------------------------*/
#import "VGmath.h"
#import "KGSurface.h"
@class KGPixelPipe;
@class KGPaint;
typedef enum {
VG_EVEN_ODD,
@ -63,7 +64,15 @@ typedef struct {
RIfloat weight;
} Sample;
typedef void (*KGRasterizeBlendSpan_RGBAffff)(KGRGBAffff *src,KGRGBAffff *dst,int length);
@interface KGRasterizer : NSObject {
KGSurface *m_renderingSurface;
KGSurface *m_mask;
KGPaint *m_paint;
KGRasterizeBlendSpan_RGBAffff _blendRGBAffff;
int _vpx,_vpy,_vpwidth,_vpheight;
int _edgeCount;
@ -78,12 +87,18 @@ typedef struct {
}
KGRasterizer *KGRasterizerAlloc();
KGRasterizer *KGRasterizerInit(KGRasterizer *self);
KGRasterizer *KGRasterizerInit(KGRasterizer *self,KGSurface *renderingSurface);
void KGRasterizerDealloc(KGRasterizer *self);
void KGRasterizerSetViewport(KGRasterizer *self,int vpx,int vpy,int vpwidth,int vpheight);
void KGRasterizerClear(KGRasterizer *self);
void KGRasterizerAddEdge(KGRasterizer *self,const Vector2 v0, const Vector2 v1);
void KGRasterizerSetShouldAntialias(KGRasterizer *self,BOOL antialias);
void KGRasterizerFill(KGRasterizer *self,VGFillRule fillRule, KGPixelPipe *pixelPipe);
void KGRasterizerFill(KGRasterizer *self,VGFillRule fillRule);
void KGRasterizeSetBlendMode(KGRasterizer *self,CGBlendMode blendMode);
void KGRasterizeSetMask(KGRasterizer *self,KGSurface* mask);
void KGRasterizeSetPaint(KGRasterizer *self,KGPaint* paint);
//private
void KGRasterizeWriteCoverage(KGRasterizer *self,int x, int y,RIfloat *coverage,int length);
@end

View File

@ -27,7 +27,9 @@
*-------------------------------------------------------------------*/
#import "KGRasterizer.h"
#import "KGPixelPipe.h"
#import "KGPaint_color.h"
#import "KGSurface.h"
#import "KGBlending.h"
#define RI_MAX_EDGES 262144
@ -37,7 +39,12 @@ KGRasterizer *KGRasterizerAlloc(){
return (KGRasterizer *)NSZoneCalloc(NULL,1,sizeof(KGRasterizer));
}
KGRasterizer *KGRasterizerInit(KGRasterizer *self) {
KGRasterizer *KGRasterizerInit(KGRasterizer *self,KGSurface *renderingSurface) {
self->m_renderingSurface = renderingSurface;
self->m_mask=NULL;
self->m_paint=NULL;
self->_blendRGBAffff=KGBlendSpanNormal_ffff;
self->_vpx=self->_vpy=self->_vpwidth=self->_vpheight=0;
self->_edgeCount=0;
@ -325,7 +332,7 @@ static void incrementEdgeForAET(Edge *edge,RIfloat cminy,RIfloat cmaxy,RIfloat f
*/
void KGRasterizerFill(KGRasterizer *self,VGFillRule fillRule, KGPixelPipe *pixelPipe) {
void KGRasterizerFill(KGRasterizer *self,VGFillRule fillRule) {
RI_ASSERT(fillRule == VG_EVEN_ODD || fillRule == VG_NON_ZERO);
//proceed scanline by scanline
@ -488,7 +495,7 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRule fillRule, KGPixelPipe *pixel
}
}
int nextx = xlimit;
for(i=nextEdge;i<activeCount;i++){
@ -500,7 +507,6 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRule fillRule, KGPixelPipe *pixel
}
}
RIfloat coverage = 0.0f;
s=self->numSamples;
while(--s>=0)
@ -516,7 +522,7 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRule fillRule, KGPixelPipe *pixel
if(spanCount==0)
spanX=scanx;
else if(scanx!=(spanX+spanCount)){
KGPixelPipeWriteCoverage(pixelPipe,spanX,scany,span,spanCount);
KGRasterizeWriteCoverage(self,spanX,scany,span,spanCount);
spanCount=0;
spanX=scanx;
}
@ -524,7 +530,7 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRule fillRule, KGPixelPipe *pixel
for(i=0;i<(nextx-scanx);i++){
if(spanCount>=spanCapacity){
KGPixelPipeWriteCoverage(pixelPipe,spanX,scany,span,spanCount);
KGRasterizeWriteCoverage(self,spanX,scany,span,spanCount);
spanCount=0;
spanX=scanx+i;
}
@ -536,7 +542,7 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRule fillRule, KGPixelPipe *pixel
}
if(spanCount>0){
KGPixelPipeWriteCoverage(pixelPipe,spanX,scany,span,spanCount);
KGRasterizeWriteCoverage(self,spanX,scany,span,spanCount);
spanCount=0;
}
}
@ -545,4 +551,206 @@ void KGRasterizerFill(KGRasterizer *self,VGFillRule fillRule, KGPixelPipe *pixel
NSZoneFree(NULL,edges);
}
void KGRasterizeSetBlendMode(KGRasterizer *self,CGBlendMode blendMode) {
RI_ASSERT(blendMode >= kCGBlendModeNormal && blendMode <= kCGBlendModePlusLighter);
switch(blendMode){
case kCGBlendModeNormal:
self->_blendRGBAffff=KGBlendSpanNormal_ffff;
break;
case kCGBlendModeMultiply:
self->_blendRGBAffff=KGBlendSpanMultiply_ffff;
break;
case kCGBlendModeScreen:
self->_blendRGBAffff=KGBlendSpanScreen_ffff;
break;
case kCGBlendModeOverlay:
self->_blendRGBAffff=KGBlendSpanOverlay_ffff;
break;
case kCGBlendModeDarken:
self->_blendRGBAffff=KGBlendSpanDarken_ffff;
break;
case kCGBlendModeLighten:
self->_blendRGBAffff=KGBlendSpanLighten_ffff;
break;
case kCGBlendModeColorDodge:
self->_blendRGBAffff=KGBlendSpanColorDodge_ffff;
break;
case kCGBlendModeColorBurn:
self->_blendRGBAffff=KGBlendSpanColorBurn_ffff;
break;
case kCGBlendModeHardLight:
self->_blendRGBAffff=KGBlendSpanHardLight_ffff;
break;
case kCGBlendModeSoftLight:
self->_blendRGBAffff=KGBlendSpanSoftLight_ffff;
break;
case kCGBlendModeDifference:
self->_blendRGBAffff=KGBlendSpanDifference_ffff;
break;
case kCGBlendModeExclusion:
self->_blendRGBAffff=KGBlendSpanExclusion_ffff;
break;
case kCGBlendModeHue:
self->_blendRGBAffff=KGBlendSpanHue_ffff;
break;
case kCGBlendModeSaturation:
self->_blendRGBAffff=KGBlendSpanSaturation_ffff;
break;
case kCGBlendModeColor:
self->_blendRGBAffff=KGBlendSpanColor_ffff;
break;
case kCGBlendModeLuminosity:
self->_blendRGBAffff=KGBlendSpanLuminosity_ffff;
break;
case kCGBlendModeClear:
self->_blendRGBAffff=KGBlendSpanClear_ffff;
break;
case kCGBlendModeCopy:
self->_blendRGBAffff=KGBlendSpanCopy_ffff;
break;
case kCGBlendModeSourceIn:
self->_blendRGBAffff=KGBlendSpanSourceIn_ffff;
break;
case kCGBlendModeSourceOut:
self->_blendRGBAffff=KGBlendSpanSourceOut_ffff;
break;
case kCGBlendModeSourceAtop:
self->_blendRGBAffff=KGBlendSpanSourceAtop_ffff;
break;
case kCGBlendModeDestinationOver:
self->_blendRGBAffff=KGBlendSpanDestinationOver_ffff;
break;
case kCGBlendModeDestinationIn:
self->_blendRGBAffff=KGBlendSpanDestinationIn_ffff;
break;
case kCGBlendModeDestinationOut:
self->_blendRGBAffff=KGBlendSpanDestinationOut_ffff;
break;
case kCGBlendModeDestinationAtop:
self->_blendRGBAffff=KGBlendSpanDestinationAtop_ffff;
break;
case kCGBlendModeXOR:
self->_blendRGBAffff=KGBlendSpanXOR_ffff;
break;
case kCGBlendModePlusDarker:
self->_blendRGBAffff=KGBlendSpanPlusDarker_ffff;
break;
case kCGBlendModePlusLighter:
self->_blendRGBAffff=KGBlendSpanPlusLighter_ffff;
break;
}
}
void KGRasterizeSetMask(KGRasterizer *self,KGSurface* mask) {
self->m_mask = mask;
}
void KGRasterizeSetPaint(KGRasterizer *self, KGPaint* paint) {
self->m_paint = paint;
if(!self->m_paint)
self->m_paint = [[KGPaint_color alloc] initWithGray:0 alpha:1];
}
static inline KGRGBAffff KGRGBAffffConvert(KGRGBAffff rgba,int fromFormat,int toFormat){
VGColor color=VGColorFromKGRGBA_ffff(rgba,fromFormat);
color=VGColorConvert(color,toFormat);
return KGRGBAffffFromColor(color);
}
static VGColorInternalFormat KGApplyCoverageToSpan(KGRGBAffff *dst,RIfloat *coverage,KGRGBAffff *result,int length,VGColorInternalFormat dFormat){
//apply antialiasing in linear color space
VGColorInternalFormat aaFormat = (dFormat & VGColorLUMINANCE) ? VGColor_lLA_PRE : VGColor_lRGBA_PRE;
int i;
if(aaFormat!=dFormat){
for(i=0;i<length;i++){
KGRGBAffff r=result[i];
KGRGBAffff d=dst[i];
RIfloat cov=coverage[i];
r=KGRGBAffffConvert(r,dFormat,aaFormat);
d=KGRGBAffffConvert(d,dFormat,aaFormat);
result[i]=KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(r , cov) , KGRGBAffffMultiplyByFloat(d , (1.0f - cov)));
}
return aaFormat;
}
else {
for(i=0;i<length;i++){
KGRGBAffff r=result[i];
KGRGBAffff d=dst[i];
RIfloat cov=coverage[i];
result[i]=KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(r , cov) , KGRGBAffffMultiplyByFloat(d , (1.0f - cov)));
}
return dFormat;
}
}
void KGRasterizeWriteCoverage(KGRasterizer *self,int x, int y,RIfloat *coverage,int length) {
RI_ASSERT(self->m_renderingSurface);
//apply masking
if(self->m_mask)
KGSurfaceReadMaskPixelSpanIntoCoverage(self->m_mask,x,y,coverage,length);
// This optimization may not make sense in the bulk computations
// if(coverage[0..length] == 0.0f)
// return;
//read destination color
KGRGBAffff d[length];
VGColorInternalFormat dFormat=KGSurfaceReadPremultipliedSpan_ffff(self->m_renderingSurface,x,y,d,length);
KGRGBAffff src[length];
VGColorInternalFormat srcFormat=self->m_paint->_readRGBAffff(self->m_paint,x,y,src,length);
if(!(srcFormat&VGColorPREMULTIPLIED)){
KGRGBPremultiplySpan(src,length);
srcFormat|=VGColorPREMULTIPLIED;
}
convertSpan(src,length,srcFormat,dFormat);
self->_blendRGBAffff(src,d,length);
VGColorInternalFormat resultFormat;
resultFormat=KGApplyCoverageToSpan(d,coverage,src,length,dFormat);
//write result to the destination surface
KGSurfaceWritePixelSpan(self->m_renderingSurface,x,y,src,length,resultFormat);
}
@end

View File

@ -254,7 +254,7 @@ void KGSurfaceReadMaskPixelSpanIntoCoverage(KGSurface *self,int x,int y,RIfloat
void KGSurfaceWriteMaskPixel(KGSurface *self,int x, int y, RIfloat m); //can write only to VG_A_8
void KGSurfacePatternSpan(KGSurface *self,RIfloat x, RIfloat y, KGRGBAffff *span,int length,int colorFormat, Matrix3x3 surfaceToImage, CGPatternTiling distortion);
VGColorInternalFormat KGSurfacePatternSpan(KGImage *self,RIfloat x, RIfloat y, KGRGBAffff *span,int length, Matrix3x3 surfaceToImage, CGPatternTiling distortion);
void KGSurfaceMakeMipMaps(KGImage *self);

View File

@ -39,24 +39,6 @@
#define RI_MAX_GAUSSIAN_STD_DEVIATION 128.0f
BOOL KGSurfaceIsValidFormat(int f)
{
if(f < VG_sRGBX_8888 || f > VG_lABGR_8888_PRE)
return NO;
return YES;
}
/*-------------------------------------------------------------------*//*!
* \brief Converts from numBits into a shifted mask
* \param
* \return
* \note
*//*-------------------------------------------------------------------*/
static unsigned int bitsToMask(unsigned int bits, unsigned int shift)
{
return ((1<<bits)-1) << shift;
}
/*-------------------------------------------------------------------*//*!
* \brief Converts from color (RIfloat) to an int with 1.0f mapped to the
@ -147,10 +129,10 @@ VGColor VGColorConvert(VGColor result,VGColorInternalFormat outputFormat){
//7: sRGB = sL
//Source/Dest lRGB sRGB lL sL
//lRGB 1 3 3,5
//sRGB 2 2,3 2,3,5
//lL 4 4,1 5
//sL 7,2 7 6
//lRGB Ñ 1 3 3,5
//sRGB 2 Ñ 2,3 2,3,5
//lL 4 4,1 Ñ 5
//sL 7,2 7 6 Ñ
const unsigned int shift = 3;
unsigned int conversion = (result.m_format & (VGColorNONLINEAR | VGColorLUMINANCE)) | ((outputFormat & (VGColorNONLINEAR | VGColorLUMINANCE)) << shift);
@ -195,7 +177,6 @@ VGColor VGColorConvert(VGColor result,VGColorInternalFormat outputFormat){
VGPixelDecode KGSurfaceParametersToPixelLayout(KGSurfaceFormat format,size_t *bitsPerPixel,VGColorInternalFormat *colorFormat){
VGPixelDecode desc;
memset(&desc, 0, sizeof(VGPixelDecode));
RI_ASSERT(KGSurfaceIsValidFormat(format));
int baseFormat = (int)format & 15;
RI_ASSERT(baseFormat >= 0 && baseFormat <= 12);
@ -1232,7 +1213,7 @@ void KGSurfaceReadTexelTilePad(KGImage *self,int u, int v, KGRGBAffff *span,int
*//*-------------------------------------------------------------------*/
void KGSurfaceReadTexelTileRepeat(KGSurface *self,int u, int v, KGRGBAffff *span,int length){
void KGSurfaceReadTexelTileRepeat(KGImage *self,int u, int v, KGRGBAffff *span,int length){
int i;
v = RI_INT_MOD(v, self->_height);
@ -1244,7 +1225,7 @@ void KGSurfaceReadTexelTileRepeat(KGSurface *self,int u, int v, KGRGBAffff *span
}
}
void KGSurfacePattern_Bilinear(KGSurface *self,RIfloat x, RIfloat y,KGRGBAffff *span,int length, Matrix3x3 surfaceToImage){
void KGSurfacePattern_Bilinear(KGImage *self,RIfloat x, RIfloat y,KGRGBAffff *span,int length, Matrix3x3 surfaceToImage){
int i;
for(i=0;i<length;i++,x++){
@ -1270,7 +1251,7 @@ void KGSurfacePattern_Bilinear(KGSurface *self,RIfloat x, RIfloat y,KGRGBAffff *
}
}
void KGSurfacePattern_PointSampling(KGSurface *self,RIfloat x, RIfloat y,KGRGBAffff *span,int length, Matrix3x3 surfaceToImage){ //point sampling
void KGSurfacePattern_PointSampling(KGImage *self,RIfloat x, RIfloat y,KGRGBAffff *span,int length, Matrix3x3 surfaceToImage){ //point sampling
int i;
for(i=0;i<length;i++,x++){
@ -1282,7 +1263,7 @@ void KGSurfacePattern_PointSampling(KGSurface *self,RIfloat x, RIfloat y,KGRGBAf
}
}
void KGSurfacePatternSpan(KGSurface *self,RIfloat x, RIfloat y, KGRGBAffff *span,int length,int colorFormat, Matrix3x3 surfaceToImage, CGPatternTiling distortion) {
VGColorInternalFormat KGSurfacePatternSpan(KGImage *self,RIfloat x, RIfloat y, KGRGBAffff *span,int length, Matrix3x3 surfaceToImage, CGPatternTiling distortion) {
switch(distortion){
case kCGPatternTilingNoDistortion:
@ -1295,8 +1276,8 @@ void KGSurfacePatternSpan(KGSurface *self,RIfloat x, RIfloat y, KGRGBAffff *span
KGSurfacePattern_Bilinear(self,x,y,span,length,surfaceToImage);
break;
}
convertSpan(span,length,self->_colorFormat|VGColorPREMULTIPLIED,colorFormat);
return self->_colorFormat|VGColorPREMULTIPLIED;
}
/*-------------------------------------------------------------------*//*!

View File

@ -229,6 +229,7 @@ static CGColorRef cgColorFromColor(NSColor *color){
CGContextSetMiterLimit(_context,_miterLimit);
CGContextSetLineDash(_context,_dashPhase,_dashLengths,_dashLengthsCount);
CGContextSetFlatness(_context,_flatness);
CGContextSetInterpolationQuality(_context,_interpolationQuality);
}
static void addSliceToPath(CGMutablePathRef path,float innerRadius,float outerRadius,float startAngle,float endAngle){

View File

@ -69,8 +69,14 @@
FE9552810D77CA67009B765B /* KGSurface.m in Sources */ = {isa = PBXBuildFile; fileRef = FE9552780D77CA67009B765B /* KGSurface.m */; };
FE9552820D77CA67009B765B /* VGmath.m in Sources */ = {isa = PBXBuildFile; fileRef = FE95527A0D77CA67009B765B /* VGmath.m */; };
FE9552830D77CA67009B765B /* VGPath.m in Sources */ = {isa = PBXBuildFile; fileRef = FE95527C0D77CA67009B765B /* VGPath.m */; };
FE9552840D77CA67009B765B /* KGPixelPipe.m in Sources */ = {isa = PBXBuildFile; fileRef = FE95527E0D77CA67009B765B /* KGPixelPipe.m */; };
FE9552850D77CA67009B765B /* KGRasterizer.m in Sources */ = {isa = PBXBuildFile; fileRef = FE9552800D77CA67009B765B /* KGRasterizer.m */; };
FEBF55B90DCA0DE500CE5A1C /* KGPaint.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF55B80DCA0DE500CE5A1C /* KGPaint.m */; };
FEBF575B0DCA60CD00CE5A1C /* KGPaint_image.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF575A0DCA60CD00CE5A1C /* KGPaint_image.m */; };
FEBF59190DCC063400CE5A1C /* KGPaint_pattern.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF59050DCC063400CE5A1C /* KGPaint_pattern.m */; };
FEBF59350DCC0E2000CE5A1C /* KGPaint_color.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF59340DCC0E2000CE5A1C /* KGPaint_color.m */; };
FEBF596B0DCC1B5C00CE5A1C /* KGPaint_axialGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF59660DCC1B5C00CE5A1C /* KGPaint_axialGradient.m */; };
FEBF596C0DCC1B5C00CE5A1C /* KGPaint_radialGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF59680DCC1B5C00CE5A1C /* KGPaint_radialGradient.m */; };
FEBF596D0DCC1B5C00CE5A1C /* KGPaint_ramp.m in Sources */ = {isa = PBXBuildFile; fileRef = FEBF596A0DCC1B5C00CE5A1C /* KGPaint_ramp.m */; };
/* End PBXBuildFile section */
/* Begin PBXBuildRule section */
@ -212,10 +218,22 @@
FE95527A0D77CA67009B765B /* VGmath.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = VGmath.m; path = ../../AppKit/CoreGraphics.subproj/VGmath.m; sourceTree = "<group>"; };
FE95527B0D77CA67009B765B /* VGPath.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = VGPath.h; path = ../../AppKit/CoreGraphics.subproj/VGPath.h; sourceTree = "<group>"; };
FE95527C0D77CA67009B765B /* VGPath.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = VGPath.m; path = ../../AppKit/CoreGraphics.subproj/VGPath.m; sourceTree = "<group>"; };
FE95527D0D77CA67009B765B /* KGPixelPipe.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = KGPixelPipe.h; path = ../../AppKit/CoreGraphics.subproj/KGPixelPipe.h; sourceTree = "<group>"; };
FE95527E0D77CA67009B765B /* KGPixelPipe.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = KGPixelPipe.m; path = ../../AppKit/CoreGraphics.subproj/KGPixelPipe.m; sourceTree = "<group>"; };
FE95527F0D77CA67009B765B /* KGRasterizer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = KGRasterizer.h; path = ../../AppKit/CoreGraphics.subproj/KGRasterizer.h; sourceTree = "<group>"; };
FE9552800D77CA67009B765B /* KGRasterizer.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = KGRasterizer.m; path = ../../AppKit/CoreGraphics.subproj/KGRasterizer.m; sourceTree = "<group>"; };
FEBF55B70DCA0DE500CE5A1C /* KGPaint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KGPaint.h; path = ../../AppKit/CoreGraphics.subproj/KGPaint.h; sourceTree = "<group>"; };
FEBF55B80DCA0DE500CE5A1C /* KGPaint.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KGPaint.m; path = ../../AppKit/CoreGraphics.subproj/KGPaint.m; sourceTree = "<group>"; };
FEBF57590DCA60CD00CE5A1C /* KGPaint_image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KGPaint_image.h; path = ../../AppKit/CoreGraphics.subproj/KGPaint_image.h; sourceTree = SOURCE_ROOT; };
FEBF575A0DCA60CD00CE5A1C /* KGPaint_image.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KGPaint_image.m; path = ../../AppKit/CoreGraphics.subproj/KGPaint_image.m; sourceTree = SOURCE_ROOT; };
FEBF59040DCC063400CE5A1C /* KGPaint_pattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KGPaint_pattern.h; path = ../../AppKit/CoreGraphics.subproj/KGPaint_pattern.h; sourceTree = SOURCE_ROOT; };
FEBF59050DCC063400CE5A1C /* KGPaint_pattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KGPaint_pattern.m; path = ../../AppKit/CoreGraphics.subproj/KGPaint_pattern.m; sourceTree = SOURCE_ROOT; };
FEBF59330DCC0E2000CE5A1C /* KGPaint_color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KGPaint_color.h; path = ../../AppKit/CoreGraphics.subproj/KGPaint_color.h; sourceTree = SOURCE_ROOT; };
FEBF59340DCC0E2000CE5A1C /* KGPaint_color.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KGPaint_color.m; path = ../../AppKit/CoreGraphics.subproj/KGPaint_color.m; sourceTree = SOURCE_ROOT; };
FEBF59650DCC1B5C00CE5A1C /* KGPaint_axialGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KGPaint_axialGradient.h; path = ../../AppKit/CoreGraphics.subproj/KGPaint_axialGradient.h; sourceTree = SOURCE_ROOT; };
FEBF59660DCC1B5C00CE5A1C /* KGPaint_axialGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KGPaint_axialGradient.m; path = ../../AppKit/CoreGraphics.subproj/KGPaint_axialGradient.m; sourceTree = SOURCE_ROOT; };
FEBF59670DCC1B5C00CE5A1C /* KGPaint_radialGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KGPaint_radialGradient.h; path = ../../AppKit/CoreGraphics.subproj/KGPaint_radialGradient.h; sourceTree = SOURCE_ROOT; };
FEBF59680DCC1B5C00CE5A1C /* KGPaint_radialGradient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KGPaint_radialGradient.m; path = ../../AppKit/CoreGraphics.subproj/KGPaint_radialGradient.m; sourceTree = SOURCE_ROOT; };
FEBF59690DCC1B5C00CE5A1C /* KGPaint_ramp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KGPaint_ramp.h; path = ../../AppKit/CoreGraphics.subproj/KGPaint_ramp.h; sourceTree = SOURCE_ROOT; };
FEBF596A0DCC1B5C00CE5A1C /* KGPaint_ramp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KGPaint_ramp.m; path = ../../AppKit/CoreGraphics.subproj/KGPaint_ramp.m; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -334,13 +352,25 @@
FE6EDCC70DB78E3C005503A1 /* KoreGraphics */ = {
isa = PBXGroup;
children = (
FEBF59650DCC1B5C00CE5A1C /* KGPaint_axialGradient.h */,
FEBF59660DCC1B5C00CE5A1C /* KGPaint_axialGradient.m */,
FEBF59670DCC1B5C00CE5A1C /* KGPaint_radialGradient.h */,
FEBF59680DCC1B5C00CE5A1C /* KGPaint_radialGradient.m */,
FEBF59690DCC1B5C00CE5A1C /* KGPaint_ramp.h */,
FEBF596A0DCC1B5C00CE5A1C /* KGPaint_ramp.m */,
FEBF59330DCC0E2000CE5A1C /* KGPaint_color.h */,
FEBF59340DCC0E2000CE5A1C /* KGPaint_color.m */,
FEBF59040DCC063400CE5A1C /* KGPaint_pattern.h */,
FEBF59050DCC063400CE5A1C /* KGPaint_pattern.m */,
FEBF57590DCA60CD00CE5A1C /* KGPaint_image.h */,
FEBF575A0DCA60CD00CE5A1C /* KGPaint_image.m */,
FEBF55B70DCA0DE500CE5A1C /* KGPaint.h */,
FEBF55B80DCA0DE500CE5A1C /* KGPaint.m */,
FE1474D20DB44967001B5634 /* KGBlending.h */,
FE6EE0090DB7CE0B005503A1 /* KGContext_builtin.h */,
FE6EE00A0DB7CE0B005503A1 /* KGContext_builtin.m */,
FE95527B0D77CA67009B765B /* VGPath.h */,
FE95527C0D77CA67009B765B /* VGPath.m */,
FE95527D0D77CA67009B765B /* KGPixelPipe.h */,
FE95527E0D77CA67009B765B /* KGPixelPipe.m */,
FE95527F0D77CA67009B765B /* KGRasterizer.h */,
FE9552800D77CA67009B765B /* KGRasterizer.m */,
FE9552770D77CA67009B765B /* KGSurface.h */,
@ -494,7 +524,6 @@
FE9552810D77CA67009B765B /* KGSurface.m in Sources */,
FE9552820D77CA67009B765B /* VGmath.m in Sources */,
FE9552830D77CA67009B765B /* VGPath.m in Sources */,
FE9552840D77CA67009B765B /* KGPixelPipe.m in Sources */,
FE9552850D77CA67009B765B /* KGRasterizer.m in Sources */,
FE1F93630D7EF19900969491 /* KGImageView.m in Sources */,
FE1F937A0D7EF1F800969491 /* KGRenderController.m in Sources */,
@ -549,6 +578,13 @@
FE45ED410DC2374E00F49290 /* KGImageSource_TIFF.m in Sources */,
FE45ED460DC2376700F49290 /* NSTIFFImageFileDirectory.m in Sources */,
FE45ED470DC2376700F49290 /* NSTIFFReader.m in Sources */,
FEBF55B90DCA0DE500CE5A1C /* KGPaint.m in Sources */,
FEBF575B0DCA60CD00CE5A1C /* KGPaint_image.m in Sources */,
FEBF59190DCC063400CE5A1C /* KGPaint_pattern.m in Sources */,
FEBF59350DCC0E2000CE5A1C /* KGPaint_color.m in Sources */,
FEBF596B0DCC1B5C00CE5A1C /* KGPaint_axialGradient.m in Sources */,
FEBF596C0DCC1B5C00CE5A1C /* KGPaint_radialGradient.m in Sources */,
FEBF596D0DCC1B5C00CE5A1C /* KGPaint_ramp.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};