- KGImage bitmapinfo fixes, added BGRX/8, resampling optimizations

- Moved -[KGFont fetchSharedGlyphRangeTable] to KGFont_gdi
This commit is contained in:
Christopher Lloyd 2008-08-02 23:37:29 +00:00
parent 2c4036da3b
commit 220f7613ac
17 changed files with 294 additions and 188 deletions

View File

@ -7,10 +7,9 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#import <Foundation/NSObject.h>
#import <Foundation/NSGeometry.h>
#import <ApplicationServices/ApplicationServices.h>
@class KGColor,KGColorSpace,KGShading,KGImage,KGGraphicsState,KGMutablePath,KGPath,KGPattern,KGLayer,KGPDFPage,NSMutableArray,CGWindow,KGFont,KGSurface;
@class KGColor,KGColorSpace,KGShading,KGImage,KGGraphicsState,KGMutablePath,KGPath,KGPattern,KGLayer,KGPDFPage,NSMutableArray,CGWindow,KGFont,KGSurface,NSDictionary,NSData;
@interface KGContext : NSObject {
CGAffineTransform _userToDeviceTransform;

View File

@ -672,36 +672,43 @@ static void KGBlendSpanNormal_8888_coverage(KGRGBA8888 *src,KGRGBA8888 *dst,int
static void KGBlendSpanCopy_8888_coverage(KGRGBA8888 *src,KGRGBA8888 *dst,int coverage,int length){
// Passes Visual Test
int i;
int oneMinusCoverage=256-coverage;
for(i=0;i<length;i++,src++,dst++){
KGRGBA8888 d=*dst;
KGRGBA8888 r=*src;
if(coverage==256){
for(i=0;i<length;i++,src++,dst++)
*dst=*src;
}
else {
int oneMinusCoverage=256-coverage;
for(i=0;i<length;i++,src++,dst++){
KGRGBA8888 d=*dst;
KGRGBA8888 r=*src;
r.r=multiplyByCoverage(r.r,coverage);
d.r=(d.r*oneMinusCoverage)/256;
r.r=RI_INT_MIN((int)r.r+(int)d.r,255);
r.r=multiplyByCoverage(r.r,coverage);
d.r=(d.r*oneMinusCoverage)/256;
r.r=RI_INT_MIN((int)r.r+(int)d.r,255);
r.g=multiplyByCoverage(r.g,coverage);
d.g=(d.g*oneMinusCoverage)/256;
r.g=RI_INT_MIN((int)r.g+(int)d.g,255);
r.g=multiplyByCoverage(r.g,coverage);
d.g=(d.g*oneMinusCoverage)/256;
r.g=RI_INT_MIN((int)r.g+(int)d.g,255);
r.b=multiplyByCoverage(r.b,coverage);
d.b=(d.b*oneMinusCoverage)/256;
r.b=RI_INT_MIN((int)r.b+(int)d.b,255);
r.b=multiplyByCoverage(r.b,coverage);
d.b=(d.b*oneMinusCoverage)/256;
r.b=RI_INT_MIN((int)r.b+(int)d.b,255);
r.a=multiplyByCoverage(r.a,coverage);
d.a=(d.a*oneMinusCoverage)/256;
r.a=RI_INT_MIN((int)r.a+(int)d.a,255);
*dst=r;
r.a=multiplyByCoverage(r.a,coverage);
d.a=(d.a*oneMinusCoverage)/256;
r.a=RI_INT_MIN((int)r.a+(int)d.a,255);
*dst=r;
}
}
}
static inline void KGRasterizeWriteCoverageSpan(KGRasterizer *self,int x, int y,int coverage,int length) {
if(self->_useRGBA8888){
KGRGBA8888 *dst=__builtin_alloca(length*sizeof(KGRGBA8888));
KGRGBA8888 *direct=KGImageReadSpan_lRGBA8888_PRE(self->_surface,x,y,dst,length);
KGRGBA8888 *direct=self->_surface->_read_lRGBA8888_PRE(self->_surface,x,y,dst,length);
if(direct!=NULL)
dst=direct;

View File

@ -1,5 +1,4 @@
#import <Foundation/NSString.h>
#import <Foundation/NSGeometry.h>
#import <ApplicationServices/ApplicationServices.h>
@class KGMutablePath;
@ -58,7 +57,7 @@ typedef struct CGGlyphMetricsSet {
NSString *_name;
float _size;
CGFontMetrics _metrics;
BOOL _glyphRangeTableLoaded;
// subclasses are responsible for alloc/dealloc of _glyphRangeTable
struct CGGlyphRangeTable *_glyphRangeTable;
struct CGGlyphMetricsSet *_glyphInfoSet;
}

View File

@ -1,7 +1,6 @@
#import "KGFont.h"
#import "KGExceptions.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSMapTable.h>
@implementation KGFont
@ -30,29 +29,8 @@ static inline CGGlyphMetrics *glyphInfoForGlyph(KGFont *self,CGGlyph glyph){
return NULL;
}
#define MAXUNICHAR 0xFFFF
-(void)fetchSharedGlyphRangeTable {
static NSMapTable *nameToGlyphRanges=NULL;
CGGlyphRangeTable *result;
if(nameToGlyphRanges==NULL)
nameToGlyphRanges=NSCreateMapTable(NSObjectMapKeyCallBacks,NSNonOwnedPointerMapValueCallBacks,0);
result=NSMapGet(nameToGlyphRanges,_name);
if(result==NULL){
result=NSZoneCalloc(NULL,sizeof(CGGlyphRangeTable),1);
NSMapInsert(nameToGlyphRanges,_name,result);
}
_glyphRangeTable=result;
}
-(void)fetchGlyphRanges {
[self loadGlyphRangeTable];
_glyphRangeTableLoaded=YES;
_glyphInfoSet->numberOfGlyphs=_glyphRangeTable->numberOfGlyphs;
}
@ -63,7 +41,7 @@ static inline CGGlyphMetrics *glyphInfoForGlyph(KGFont *self,CGGlyph glyph){
}
static inline void fetchAllGlyphRangesIfNeeded(KGFont *self){
if(!self->_glyphRangeTableLoaded)
if(self->_glyphRangeTable==NULL)
[self fetchGlyphRanges];
}
@ -93,7 +71,6 @@ static inline CGGlyphMetrics *fetchGlyphAdvancementIfNeeded(KGFont *self,CGGlyph
_size=size;
[self fetchMetrics];
_glyphRangeTable=NULL;
[self fetchSharedGlyphRangeTable];
_glyphInfoSet=NSZoneMalloc([self zone],sizeof(CGGlyphMetricsSet));
_glyphInfoSet->numberOfGlyphs=0;
_glyphInfoSet->info=NULL;

View File

@ -7,7 +7,6 @@ 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 <Foundation/NSObject.h>
#import <Foundation/NSGeometry.h>
#import <ApplicationServices/ApplicationServices.h>
@class KGImage,KGColorSpace,KGColor,KGPattern,KGMutablePath,KGPath,NSArray,NSMutableArray,KGFont;

View File

@ -282,15 +282,16 @@ typedef CGFloat *(*KGImageReadSpan_Af)(KGImage *self,int x,int y,CGFloat *spa
BOOL _clampExternalPixels;
VGColorInternalFormat _colorFormat;
KGImageReadSpan_RGBA8888 _readRGBA8888;
KGImageReadSpan_RGBAffff _readRGBAffff;
KGImageReadSpan_A8 _readA8;
KGImageReadSpan_Af _readAf;
BOOL m_mipmapsValid;
int _mipmapsCount;
int _mipmapsCapacity;
struct KGSurface **_mipmaps;
@public
KGImageReadSpan_RGBA8888 _read_lRGBA8888_PRE;
KGImageReadSpan_RGBAffff _read_lRGBAffff_PRE;
KGImageReadSpan_A8 _readA8;
KGImageReadSpan_Af _readAf;
}
-initWithWidth:(size_t)width height:(size_t)height bitsPerComponent:(size_t)bitsPerComponent bitsPerPixel:(size_t)bitsPerPixel bytesPerRow:(size_t)bytesPerRow colorSpace:(KGColorSpace *)colorSpace bitmapInfo:(CGBitmapInfo)bitmapInfo provider:(KGDataProvider *)provider decode:(const CGFloat *)decode interpolate:(BOOL)interpolate renderingIntent:(CGColorRenderingIntent)renderingIntent;
@ -335,7 +336,7 @@ const char *KGImageNameWithIntent(CGColorRenderingIntent intent);
size_t KGImageGetWidth(KGImage *self);
size_t KGImageGetHeight(KGImage *self);
/* KGImage and KGSurface can read and write any image format provided functions are provided to translate to/from either KGRGBA8888 or KGRGBAffff spans.
/* KGImage and KGSurface can read and write any image format provided functions are provided to translate to/from either KGRGBA8888 or KGRGBAffff spans.
The return value will be either NULL or a pointer to the image data if direct access is available for the given format. You must use the return value if it is not NULL. If the value is not NULL you don't do a write back. This is a big boost for native ARGB format as it avoids a copy out and a copy in.
@ -351,6 +352,7 @@ KGRGBA8888 *KGImageRead_GA88_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *s
KGRGBA8888 *KGImageRead_RGBA8888_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
KGRGBA8888 *KGImageRead_ABGR8888_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
KGRGBA8888 *KGImageRead_BGRA8888_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
KGRGBA8888 *KGImageRead_BGRX8888_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
KGRGBA8888 *KGImageRead_XRGB8888_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
KGRGBA8888 *KGImageRead_G3B5X1R5G2_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
KGRGBA8888 *KGImageRead_RGBA4444_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
@ -364,7 +366,6 @@ KGRGBAffff *KGImageRead_ANY_to_RGBA8888_to_RGBAffff(KGImage *self,int x,int y,KG
KGRGBAffff *KGImageRead_RGBAffffLittle_to_RGBAffff(KGImage *self,int x,int y,KGRGBAffff *span,int length);
KGRGBAffff *KGImageRead_RGBAffffBig_to_RGBAffff(KGImage *self,int x,int y,KGRGBAffff *span,int length);
KGRGBA8888 *KGImageReadSpan_lRGBA8888_PRE(KGImage *self,int x,int y,KGRGBA8888 *span,int length);
KGRGBAffff *KGImageReadSpan_lRGBAffff_PRE(KGImage *self,int x,int y,KGRGBAffff *span,int length);
uint8_t *KGImageReadSpan_A8_MASK(KGImage *self,int x,int y,uint8_t *coverage,int length);
CGFloat *KGImageReadSpan_Af_MASK(KGImage *self,int x,int y,CGFloat *coverage,int length);

View File

@ -116,6 +116,7 @@ VGPixelDecode KGImageParametersToPixelLayout(KGImageFormat format,size_t *bitsPe
}
static BOOL initFunctionsForRGBColorSpace(KGImage *self,size_t bitsPerComponent,size_t bitsPerPixel,CGBitmapInfo bitmapInfo){
switch(bitsPerComponent){
case 32:
@ -124,15 +125,14 @@ static BOOL initFunctionsForRGBColorSpace(KGImage *self,size_t bitsPerComponent,
break;
case 128:
switch(bitmapInfo&kCGBitmapByteOrderMask){
case kCGBitmapByteOrderDefault:
case kCGBitmapByteOrder16Little:
case kCGBitmapByteOrder32Little:
self->_readRGBAffff=KGImageRead_RGBAffffLittle_to_RGBAffff;
self->_read_lRGBAffff_PRE=KGImageRead_RGBAffffLittle_to_RGBAffff;
return YES;
case kCGBitmapByteOrder16Big:
case kCGBitmapByteOrder32Big:
self->_readRGBAffff=KGImageRead_RGBAffffBig_to_RGBAffff;
self->_read_lRGBAffff_PRE=KGImageRead_RGBAffffBig_to_RGBAffff;
return YES;
}
}
@ -143,11 +143,11 @@ static BOOL initFunctionsForRGBColorSpace(KGImage *self,size_t bitsPerComponent,
case 8:
self->_readA8=KGImageRead_G8_to_A8;
self->_readRGBA8888=KGImageRead_G8_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_G8_to_RGBA8888;
return YES;
case 16:
self->_readRGBA8888=KGImageRead_GA88_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_GA88_to_RGBA8888;
return YES;
case 24:
@ -161,26 +161,23 @@ static BOOL initFunctionsForRGBColorSpace(KGImage *self,size_t bitsPerComponent,
case kCGImageAlphaLast:
case kCGImageAlphaPremultipliedLast:
switch(bitmapInfo&kCGBitmapByteOrderMask){
case kCGBitmapByteOrderDefault:
case kCGBitmapByteOrder16Little:
case kCGBitmapByteOrder32Little:
self->_readRGBA8888=KGImageRead_ABGR8888_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_ABGR8888_to_RGBA8888;
return YES;
case kCGBitmapByteOrder16Big:
case kCGBitmapByteOrder32Big:
self->_readRGBA8888=KGImageRead_RGBA8888_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_RGBA8888_to_RGBA8888;
return YES;
}
break;
case kCGImageAlphaPremultipliedFirst:
switch(bitmapInfo&kCGBitmapByteOrderMask){
case kCGBitmapByteOrderDefault:
case kCGBitmapByteOrder16Little:
case kCGBitmapByteOrder32Little:
self->_readRGBA8888=KGImageRead_BGRA8888_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_BGRA8888_to_RGBA8888;
return YES;
}
break;
@ -189,33 +186,36 @@ static BOOL initFunctionsForRGBColorSpace(KGImage *self,size_t bitsPerComponent,
break;
case kCGImageAlphaNoneSkipLast:
switch(bitmapInfo&kCGBitmapByteOrderMask){
case kCGBitmapByteOrder16Little:
case kCGBitmapByteOrder32Little:
self->_read_lRGBA8888_PRE=KGImageRead_ABGR8888_to_RGBA8888;
return YES;
case kCGBitmapByteOrder16Big:
case kCGBitmapByteOrder32Big:
self->_read_lRGBA8888_PRE=KGImageRead_RGBA8888_to_RGBA8888;
return YES;
}
break;
case kCGImageAlphaNoneSkipFirst:
switch(bitmapInfo&kCGBitmapByteOrderMask){
case kCGBitmapByteOrderDefault:
case kCGBitmapByteOrder16Little:
case kCGBitmapByteOrder32Little:
self->_read_lRGBA8888_PRE=KGImageRead_BGRX8888_to_RGBA8888;
return YES;
case kCGBitmapByteOrder16Big:
case kCGBitmapByteOrder32Big:
self->_readRGBA8888=KGImageRead_XRGB8888_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_XRGB8888_to_RGBA8888;
return YES;
}
break;
}
switch(bitmapInfo&kCGBitmapByteOrderMask){
case kCGBitmapByteOrderDefault:
case kCGBitmapByteOrder16Little:
case kCGBitmapByteOrder32Little:
self->_readRGBA8888=KGImageRead_ABGR8888_to_RGBA8888;
return YES;
case kCGBitmapByteOrder16Big:
case kCGBitmapByteOrder32Big:
self->_readRGBA8888=KGImageRead_RGBA8888_to_RGBA8888;
return YES;
}
break;
break;
}
break;
@ -224,7 +224,7 @@ static BOOL initFunctionsForRGBColorSpace(KGImage *self,size_t bitsPerComponent,
case 16:
if(bitmapInfo==(kCGBitmapByteOrder16Little|kCGImageAlphaNoneSkipFirst)){
self->_readRGBA8888=KGImageRead_G3B5X1R5G2_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_G3B5X1R5G2_to_RGBA8888;
return YES;
}
break;
@ -239,15 +239,14 @@ static BOOL initFunctionsForRGBColorSpace(KGImage *self,size_t bitsPerComponent,
break;
case 16:
switch(bitmapInfo&kCGBitmapByteOrderMask){
case kCGBitmapByteOrderDefault:
case kCGBitmapByteOrder16Little:
case kCGBitmapByteOrder32Little:
self->_readRGBA8888=KGImageRead_BARG4444_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_BARG4444_to_RGBA8888;
return YES;
case kCGBitmapByteOrder16Big:
case kCGBitmapByteOrder32Big:
self->_readRGBA8888=KGImageRead_RGBA4444_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_RGBA4444_to_RGBA8888;
return YES;
}
@ -262,7 +261,7 @@ static BOOL initFunctionsForRGBColorSpace(KGImage *self,size_t bitsPerComponent,
case 6:
break;
case 8:
self->_readRGBA8888=KGImageRead_RGBA2222_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_RGBA2222_to_RGBA8888;
return YES;
}
break;
@ -270,7 +269,7 @@ static BOOL initFunctionsForRGBColorSpace(KGImage *self,size_t bitsPerComponent,
case 1:
switch(bitsPerPixel){
case 1:
// self->_readRGBAffff=KGImageReadPixelSpan_01;
// self->_read_lRGBAffff_PRE=KGImageReadPixelSpan_01;
// return YES;
case 3:
@ -292,7 +291,7 @@ static BOOL initFunctionsForCMYKColorSpace(KGImage *self,size_t bitsPerComponent
switch(bitmapInfo&kCGBitmapByteOrderMask){
case kCGBitmapByteOrder16Big:
case kCGBitmapByteOrder32Big:
self->_readRGBA8888=KGImageRead_CMYK8888_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_CMYK8888_to_RGBA8888;
return YES;
}
break;
@ -306,7 +305,7 @@ static BOOL initFunctionsForIndexedColorSpace(KGImage *self,size_t bitsPerCompon
switch([[(KGColorSpace_indexed *)colorSpace baseColorSpace] type]){
case KGColorSpaceDeviceRGB:
self->_readRGBA8888=KGImageRead_I8_to_RGBA8888;
self->_read_lRGBA8888_PRE=KGImageRead_I8_to_RGBA8888;
return YES;
}
@ -317,8 +316,11 @@ static BOOL initFunctionsForParameters(KGImage *self,size_t bitsPerComponent,siz
self->_readA8=KGImageRead_ANY_to_RGBA8888_to_A8;
self->_readAf=KGImageRead_ANY_to_A8_to_Af;
self->_readRGBAffff=KGImageRead_ANY_to_RGBA8888_to_RGBAffff;
self->_read_lRGBAffff_PRE=KGImageRead_ANY_to_RGBA8888_to_RGBAffff;
if((bitmapInfo&kCGBitmapByteOrderMask)==kCGBitmapByteOrderDefault)
bitmapInfo|=kCGBitmapByteOrder32Big;
switch([colorSpace type]){
case KGColorSpaceDeviceGray:
break;
@ -351,7 +353,7 @@ static BOOL initFunctionsForParameters(KGImage *self,size_t bitsPerComponent,siz
_directBytes=NULL;
_directLength=0;
_clampExternalPixels=NO; // only do this if premultiplied format
if(!initFunctionsForParameters(self,bitsPerComponent,bitsPerPixel,colorSpace,bitmapInfo)){
NSLog(@"KGImage failed to init with bpc=%d, bpp=%d,colorSpace=%@,bitmapInfo=%0X",bitsPerComponent,bitsPerPixel,colorSpace,bitmapInfo);
@ -377,9 +379,10 @@ static BOOL initFunctionsForParameters(KGImage *self,size_t bitsPerComponent,siz
size_t checkBPP;
KGImageParametersToPixelLayout(imageFormat,&checkBPP,&(self->_colorFormat));
RI_ASSERT(checkBPP==bitsPerPixel);
m_mipmapsValid=NO;
_mipmapsCount=0;
_mipmapsCapacity=2;
_mipmaps=(KGSurface **)NSZoneMalloc(NULL,self->_mipmapsCapacity*sizeof(KGSurface *));
_mipmapsCapacity=0;
_mipmaps=NULL;
return self;
}
@ -413,6 +416,12 @@ static BOOL initFunctionsForParameters(KGImage *self,size_t bitsPerComponent,siz
-(void)dealloc {
[_colorSpace release];
[_provider release];
if(_decode!=NULL)
NSZoneFree(NULL,_decode);
[_mask release];
[_directData release];
if(_mipmaps!=NULL)
NSZoneFree(NULL,_mipmaps);
[super dealloc];
}
@ -553,7 +562,7 @@ size_t KGImageGetHeight(KGImage *self) {
KGRGBAffff *KGImageRead_ANY_to_RGBA8888_to_RGBAffff(KGImage *self,int x,int y,KGRGBAffff *span,int length){
KGRGBA8888 *span8888=__builtin_alloca(length*sizeof(KGRGBA8888));
KGRGBA8888 *direct=self->_readRGBA8888(self,x,y,span8888,length);
KGRGBA8888 *direct=self->_read_lRGBA8888_PRE(self,x,y,span8888,length);
if(direct!=NULL)
span8888=direct;
@ -681,7 +690,7 @@ uint8_t *KGImageRead_ANY_to_RGBA8888_to_A8(KGImage *self,int x,int y,uint8_t *al
KGRGBA8888 *span=__builtin_alloca(length*sizeof(KGRGBA8888));
int i;
KGRGBA8888 *direct=self->_readRGBA8888(self,x,y,span,length);
KGRGBA8888 *direct=self->_read_lRGBA8888_PRE(self,x,y,span,length);
if(direct!=NULL)
span=direct;
@ -807,6 +816,28 @@ KGRGBA8888 *KGImageRead_BGRA8888_to_RGBA8888(KGImage *self,int x,int y,KGRGBA888
return NULL;
}
KGRGBA8888 *KGImageRead_BGRX8888_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length) {
const RIuint8 *scanline = scanlineAtY(self,y);
int i;
if(scanline==NULL)
return NULL;
scanline+=x*4;
for(i=0;i<length;i++){
KGRGBA8888 result;
result.b = *scanline++;
result.g = *scanline++;
result.r = *scanline++;
result.a = 255; scanline++;
*span++=result;
}
return NULL;
}
KGRGBA8888 *KGImageRead_XRGB8888_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *span,int length) {
const RIuint8 *scanline = scanlineAtY(self,y);
int i;
@ -985,7 +1016,9 @@ KGRGBA8888 *KGImageRead_I8_to_RGBA8888(KGImage *self,int x,int y,KGRGBA8888 *spa
/* KGImageReadTileSpanExtendEdge__ is used by the image resampling functions to read
translated spans. When a coordinate is outside the image it uses the edge
value. This works better than say, zero, with averaging algorithms (bilinear,bicubic, etc)
as you get good values at the edges. */
as you get good values at the edges.
Ideally the averaging algorithms would only use the available pixels on the edges */
void KGImageReadTileSpanExtendEdge_lRGBA8888_PRE(KGImage *self,int u, int v, KGRGBA8888 *span,int length){
int i;
@ -993,14 +1026,14 @@ void KGImageReadTileSpanExtendEdge_lRGBA8888_PRE(KGImage *self,int u, int v, KGR
v = RI_INT_CLAMP(v,0,self->_height-1);
for(i=0;i<length && u<0;u++,i++){
direct=KGImageReadSpan_lRGBA8888_PRE(self,0,v,span+i,1);
direct=self->_read_lRGBA8888_PRE(self,0,v,span+i,1);
if(direct!=NULL)
span[i]=direct[0];
}
int chunk=RI_MIN(length-i,self->_width-u);
direct=KGImageReadSpan_lRGBA8888_PRE(self,u,v,span+i,chunk);
direct=self->_read_lRGBA8888_PRE(self,u,v,span+i,chunk);
if(direct!=NULL) {
int k;
@ -1012,7 +1045,7 @@ void KGImageReadTileSpanExtendEdge_lRGBA8888_PRE(KGImage *self,int u, int v, KGR
u+=chunk;
for(;i<length;i++){
direct=KGImageReadSpan_lRGBA8888_PRE(self,self->_width-1,v,span+i,1);
direct=self->_read_lRGBA8888_PRE(self,self->_width-1,v,span+i,1);
if(direct!=NULL)
span[i]=direct[0];
@ -1067,9 +1100,7 @@ void KGImageMakeMipMaps(KGImage *self) {
//delete existing mipmaps
int i;
for(i=0;i<self->_mipmapsCount;i++)
{
[self->_mipmaps[i] release];
}
[self->_mipmaps[i] release];
self->_mipmapsCount=0;
// try
@ -1087,7 +1118,11 @@ void KGImageMakeMipMaps(KGImage *self) {
RI_ASSERT(nextw < prev->_width || nexth < prev->_height);
if(self->_mipmapsCount+1>self->_mipmapsCapacity){
self->_mipmapsCapacity*=2;
if(self->_mipmapsCapacity==0)
self->_mipmapsCapacity=self->_mipmapsCount+1;
else
self->_mipmapsCapacity*=2;
self->_mipmaps=(KGSurface **)NSZoneRealloc(NULL,self->_mipmaps,sizeof(KGSurface *)*self->_mipmapsCapacity);
}
self->_mipmapsCount++;
@ -1269,7 +1304,7 @@ void KGImageEWAOnMipmaps_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *sp
C *= ooF;
for(i=0;i<length;i++,x++){
uv=CGPointMake(x+0.5,y+0.5);
uv=CGPointMake(x+0.5f,y+0.5f);
uv=CGAffineTransformTransformVector2(surfaceToImage ,uv);
CGFloat U0 = uv.x;
@ -1346,11 +1381,12 @@ static inline KGRGBA8888 bicubic_lRGBA8888_PRE(KGRGBA8888 a,KGRGBA8888 b,KGRGBA8
}
void KGImageBicubic_lRGBA8888_PRE(KGImage *self,int x, int y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage){
double du=(x+0.5) * surfaceToImage.a+(y+0.5)* surfaceToImage.c+surfaceToImage.tx;
double dv=(x+0.5) * surfaceToImage.b+(y+0.5)* surfaceToImage.d+surfaceToImage.ty;
int i;
for(i=0;i<length;i++,x++){
CGPoint uv=CGPointMake(x+0.5,y+0.5);
uv = CGAffineTransformTransformVector2(surfaceToImage ,uv);
CGPoint uv=CGPointMake(du,dv);
uv.x -= 0.5f;
uv.y -= 0.5f;
@ -1376,6 +1412,9 @@ void KGImageBicubic_lRGBA8888_PRE(KGImage *self,int x, int y,KGRGBA8888 *span,in
t3 = bicubic_lRGBA8888_PRE(cspan[0],cspan[1],cspan[2],cspan[3],ufrac);
span[i]=bicubic_lRGBA8888_PRE(t0,t1,t2,t3, vfrac);
du+=surfaceToImage.a;
dv+=surfaceToImage.b;
}
}
@ -1395,11 +1434,12 @@ KGRGBAffff bicubic_lRGBAffff_PRE(KGRGBAffff a,KGRGBAffff b,KGRGBAffff c,KGRGBAff
}
void KGImageBicubic_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
double du=(x+0.5) * surfaceToImage.a+(y+0.5)* surfaceToImage.c+surfaceToImage.tx;
double dv=(x+0.5) * surfaceToImage.b+(y+0.5)* surfaceToImage.d+surfaceToImage.ty;
int i;
for(i=0;i<length;i++,x++){
CGPoint uv=CGPointMake(x+0.5,y+0.5);
uv = CGAffineTransformTransformVector2(surfaceToImage ,uv);
CGPoint uv=CGPointMake(du,dv);
uv.x -= 0.5f;
uv.y -= 0.5f;
@ -1425,18 +1465,21 @@ void KGImageBicubic_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,in
t3 = bicubic_lRGBAffff_PRE(cspan[0],cspan[1],cspan[2],cspan[3],ufrac);
span[i]=bicubic_lRGBAffff_PRE(t0,t1,t2,t3, vfrac);
du+=surfaceToImage.a;
dv+=surfaceToImage.b;
}
}
void KGImageBilinear_lRGBA8888_PRE(KGImage *self,int x, int y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage){
double du=(x+0.5) * surfaceToImage.a+(y+0.5)* surfaceToImage.c+surfaceToImage.tx;
double dv=(x+0.5) * surfaceToImage.b+(y+0.5)* surfaceToImage.d+surfaceToImage.ty;
int i;
for(i=0;i<length;i++,x++){
CGPoint uv=CGPointMake(x+0.5,y+0.5);
uv = CGAffineTransformTransformVector2(surfaceToImage,uv);
uv.x -= 0.5f;
uv.y -= 0.5f;
CGPoint uv=CGPointMake(du,dv);
uv.x-=0.5f;
uv.y-=0.5f;
int u = RI_FLOOR_TO_INT(uv.x);
int v = RI_FLOOR_TO_INT(uv.y);
KGRGBA8888 c00c01[2];
@ -1452,16 +1495,20 @@ void KGImageBilinear_lRGBA8888_PRE(KGImage *self,int x, int y,KGRGBA8888 *span,i
KGRGBA8888 c0 = KGRGBA8888Add(KGRGBA8888MultiplyByCoverage(c00c01[0],oneMinusFu),KGRGBA8888MultiplyByCoverage(c00c01[1],fu));
KGRGBA8888 c1 = KGRGBA8888Add(KGRGBA8888MultiplyByCoverage(c01c11[0],oneMinusFu),KGRGBA8888MultiplyByCoverage(c01c11[1],fu));
span[i]=KGRGBA8888Add(KGRGBA8888MultiplyByCoverage(c0,oneMinusFv),KGRGBA8888MultiplyByCoverage(c1, fv));
du+=surfaceToImage.a;
dv+=surfaceToImage.b;
}
}
void KGImageBilinear_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
double du=(x+0.5) * surfaceToImage.a+(y+0.5)* surfaceToImage.c+surfaceToImage.tx;
double dv=(x+0.5) * surfaceToImage.b+(y+0.5)* surfaceToImage.d+surfaceToImage.ty;
int i;
for(i=0;i<length;i++,x++){
CGPoint uv=CGPointMake(x+0.5,y+0.5);
uv = CGAffineTransformTransformVector2(surfaceToImage,uv);
CGPoint uv=CGPointMake(du,dv);
uv.x -= 0.5f;
uv.y -= 0.5f;
@ -1478,46 +1525,40 @@ void KGImageBilinear_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,i
KGRGBAffff c0 = KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(c00c01[0],(1.0f - fu)),KGRGBAffffMultiplyByFloat(c00c01[1],fu));
KGRGBAffff c1 = KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(c01c11[0],(1.0f - fu)),KGRGBAffffMultiplyByFloat(c01c11[1],fu));
span[i]=KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(c0,(1.0f - fv)),KGRGBAffffMultiplyByFloat(c1, fv));
du+=surfaceToImage.a;
dv+=surfaceToImage.b;
}
}
void KGImagePointSampling_lRGBA8888_PRE(KGImage *self,int x, int y,KGRGBA8888 *span,int length, CGAffineTransform surfaceToImage){
double du=(x+0.5) * surfaceToImage.a+(y+0.5)* surfaceToImage.c+surfaceToImage.tx;
double dv=(x+0.5) * surfaceToImage.b+(y+0.5)* surfaceToImage.d+surfaceToImage.ty;
int i;
for(i=0;i<length;i++,x++){
CGPoint uv=CGPointMake(x+0.5,y+0.5);
uv = CGAffineTransformTransformVector2(surfaceToImage ,uv);
CGPoint uv=CGPointMake(du,dv);
KGImageReadTileSpanExtendEdge_lRGBA8888_PRE(self,RI_FLOOR_TO_INT(uv.x), RI_FLOOR_TO_INT(uv.y),span+i,1);
du+=surfaceToImage.a;
dv+=surfaceToImage.b;
}
}
void KGImagePointSampling_lRGBAffff_PRE(KGImage *self,int x, int y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
double du=(x+0.5) * surfaceToImage.a+(y+0.5)* surfaceToImage.c+surfaceToImage.tx;
double dv=(x+0.5) * surfaceToImage.b+(y+0.5)* surfaceToImage.d+surfaceToImage.ty;
int i;
for(i=0;i<length;i++,x++){
CGPoint uv=CGPointMake(x+0.5,y+0.5);
uv = CGAffineTransformTransformVector2(surfaceToImage ,uv);
CGPoint uv=CGPointMake(du,dv);
KGImageReadTileSpanExtendEdge__lRGBAffff_PRE(self,RI_FLOOR_TO_INT(uv.x), RI_FLOOR_TO_INT(uv.y),span+i,1);
}
}
KGRGBA8888 *KGImageReadSpan_lRGBA8888_PRE(KGImage *self,int x,int y,KGRGBA8888 *span,int length) {
return self->_readRGBA8888(self,x,y,span,length);
#if 0
if(format&VGColorNONLINEAR){
KGRGBAffffConvertSpan(span,length,format,VGColor_lRGBA_PRE);
du+=surfaceToImage.a;
dv+=surfaceToImage.b;
}
if(!(format&VGColorPREMULTIPLIED)){
KGRGBPremultiplySpan(span,length);
format|=VGColorPREMULTIPLIED;
}
else {
if(self->_clampExternalPixels)
clampSpan_lRGBAffff_PRE(span,length); // We don't need to do this for internally generated images (context)
}
#endif
}
//clamp premultiplied color to alpha to enforce consistency
@ -1534,7 +1575,7 @@ static void clampSpan_lRGBAffff_PRE(KGRGBAffff *span,int length){
KGRGBAffff *KGImageReadSpan_lRGBAffff_PRE(KGImage *self,int x,int y,KGRGBAffff *span,int length) {
VGColorInternalFormat format=self->_colorFormat;
KGRGBAffff *direct=self->_readRGBAffff(self,x,y,span,length);
KGRGBAffff *direct=self->_read_lRGBAffff_PRE(self,x,y,span,length);
if(direct!=NULL)
span=direct;
@ -1592,11 +1633,12 @@ void KGImageReadTexelTileRepeat(KGImage *self,int u, int v, KGRGBAffff *span,int
}
void KGImagePattern_Bilinear(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){
double du=(x+0.5) * surfaceToImage.a+(y+0.5)* surfaceToImage.c+surfaceToImage.tx;
double dv=(x+0.5) * surfaceToImage.b+(y+0.5)* surfaceToImage.d+surfaceToImage.ty;
int i;
for(i=0;i<length;i++,x++){
CGPoint uv=CGPointMake(x+0.5,y+0.5);
uv = CGAffineTransformTransformVector2(surfaceToImage ,uv);
CGPoint uv=CGPointMake(du,dv);
uv.x -= 0.5f;
uv.y -= 0.5f;
@ -1613,17 +1655,24 @@ void KGImagePattern_Bilinear(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff *span
KGRGBAffff c0 = KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(c00c01[0],(1.0f - fu)),KGRGBAffffMultiplyByFloat(c00c01[1],fu));
KGRGBAffff c1 = KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(c01c11[0],(1.0f - fu)),KGRGBAffffMultiplyByFloat(c01c11[1],fu));
span[i]=KGRGBAffffAdd(KGRGBAffffMultiplyByFloat(c0,(1.0f - fv)),KGRGBAffffMultiplyByFloat(c1, fv));
du+=surfaceToImage.a;
dv+=surfaceToImage.b;
}
}
void KGImagePattern_PointSampling(KGImage *self,CGFloat x, CGFloat y,KGRGBAffff *span,int length, CGAffineTransform surfaceToImage){ //point sampling
double du=(x+0.5) * surfaceToImage.a+(y+0.5)* surfaceToImage.c+surfaceToImage.tx;
double dv=(x+0.5) * surfaceToImage.b+(y+0.5)* surfaceToImage.d+surfaceToImage.ty;
int i;
for(i=0;i<length;i++,x++){
CGPoint uv=CGPointMake(x+0.5,y+0.5);
uv = CGAffineTransformTransformVector2(surfaceToImage ,uv);
CGPoint uv=CGPointMake(du,dv);
KGImageReadTexelTileRepeat(self,RI_FLOOR_TO_INT(uv.x), RI_FLOOR_TO_INT(uv.y),span+i,1);
du+=surfaceToImage.a;
dv+=surfaceToImage.b;
}
}

View File

@ -439,7 +439,7 @@ stbi_uc *stbi_bmp_load_from_memory (const stbi_uc *buffer, int len, int *x, int
KGDataProvider *provider=[[KGDataProvider alloc] initWithData:bitmap];
KGColorSpace *colorSpace=[[KGColorSpace alloc] initWithDeviceRGB];
KGImage *image=[[KGImage alloc] initWithWidth:width height:height bitsPerComponent:8 bitsPerPixel:bitsPerPixel bytesPerRow:bytesPerRow
colorSpace:colorSpace bitmapInfo:kCGBitmapByteOrder32Big/*kCGImageAlphaLast|kCGBitmapByteOrder32Little*/ provider:provider decode:NULL interpolate:NO renderingIntent:kCGRenderingIntentDefault];
colorSpace:colorSpace bitmapInfo:kCGBitmapByteOrder32Big|kCGImageAlphaNoneSkipLast provider:provider decode:NULL interpolate:NO renderingIntent:kCGRenderingIntentDefault];
[colorSpace release];
[provider release];

View File

@ -1097,7 +1097,7 @@ static unsigned char *stbi_jpeg_load_from_memory(jpeg *j,stbi_uc const *buffer,
KGDataProvider *provider=[[KGDataProvider alloc] initWithData:bitmap];
KGColorSpace *colorSpace=[[KGColorSpace alloc] initWithDeviceRGB];
KGImage *image=[[KGImage alloc] initWithWidth:width height:height bitsPerComponent:8 bitsPerPixel:bitsPerPixel bytesPerRow:bytesPerRow
colorSpace:colorSpace bitmapInfo:kCGBitmapByteOrder32Big provider:provider decode:NULL interpolate:NO renderingIntent:kCGRenderingIntentDefault];
colorSpace:colorSpace bitmapInfo:kCGBitmapByteOrder32Big|kCGImageAlphaPremultipliedLast provider:provider decode:NULL interpolate:NO renderingIntent:kCGRenderingIntentDefault];
[colorSpace release];
[provider release];

View File

@ -548,7 +548,7 @@ unsigned char *stbi_png_load_from_memory(const unsigned char *buffer, int len, i
KGDataProvider *provider=[[KGDataProvider alloc] initWithData:bitmap];
KGColorSpace *colorSpace=[[KGColorSpace alloc] initWithDeviceRGB];
KGImage *image=[[KGImage alloc] initWithWidth:width height:height bitsPerComponent:8 bitsPerPixel:bitsPerPixel bytesPerRow:bytesPerRow
colorSpace:colorSpace bitmapInfo:kCGBitmapByteOrder32Big provider:provider decode:NULL interpolate:NO renderingIntent:kCGRenderingIntentDefault];
colorSpace:colorSpace bitmapInfo:kCGBitmapByteOrder32Big||kCGImageAlphaPremultipliedLast provider:provider decode:NULL interpolate:NO renderingIntent:kCGRenderingIntentDefault];
[colorSpace release];
[provider release];

View File

@ -80,7 +80,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
KGDataProvider *provider=[[KGDataProvider alloc] initWithData:bitmap];
KGColorSpace *colorSpace=[[KGColorSpace alloc] initWithDeviceRGB];
KGImage *image=[[KGImage alloc] initWithWidth:width height:height bitsPerComponent:8 bitsPerPixel:bitsPerPixel bytesPerRow:bytesPerRow
colorSpace:colorSpace bitmapInfo:kCGBitmapByteOrder32Big/*kCGImageAlphaLast*/ provider:provider decode:NULL interpolate:NO renderingIntent:kCGRenderingIntentDefault];
colorSpace:colorSpace bitmapInfo:kCGBitmapByteOrder32Big|kCGImageAlphaPremultipliedLast provider:provider decode:NULL interpolate:NO renderingIntent:kCGRenderingIntentDefault];
[colorSpace release];
[provider release];

View File

@ -9,6 +9,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
#import "KGMutablePath.h"
#import "KGPath.h"
#import "KGExceptions.h"
#import <math.h>
// ellipse to 4 spline bezier, http://www.tinaja.com/glib/ellipse4.pdf
void KGMutablePathEllipseToBezier(CGPoint *cp,float x,float y,float xrad,float yrad){

View File

@ -7,7 +7,6 @@ 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 <Foundation/NSObject.h>
#import <Foundation/NSGeometry.h>
#import <ApplicationServices/ApplicationServices.h>
@class KGPDFDocument,KGPDFDictionary,KGContext;

View File

@ -29,29 +29,42 @@
@implementation KGPaint_image
static void KGPaintReadResampledSpan_lRGBAffff_PRE(KGPaint *selfX,int x,int y,KGRGBAffff *span,int length){
static void KGPaintReadResampledHighSpan_lRGBAffff_PRE(KGPaint *selfX,int x,int y,KGRGBAffff *span,int length){
KGPaint_image *self=(KGPaint_image *)selfX;
if(self->_interpolationQuality==kCGInterpolationHigh){
// KGImageEWAOnMipmaps_lRGBAffff_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
KGImageBicubic_lRGBAffff_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
}
else if(self->_interpolationQuality==kCGInterpolationLow)
KGImageBilinear_lRGBAffff_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
else
KGImagePointSampling_lRGBAffff_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
KGImageBicubic_lRGBAffff_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
}
static void KGPaintReadResampledSpan_lRGBA8888_PRE(KGPaint *selfX,int x,int y,KGRGBA8888 *span,int length){
static void KGPaintReadResampledLowSpan_lRGBAffff_PRE(KGPaint *selfX,int x,int y,KGRGBAffff *span,int length){
KGPaint_image *self=(KGPaint_image *)selfX;
if(self->_interpolationQuality==kCGInterpolationHigh){
// KGImageEWAOnMipmaps_lRGBA8888_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
KGImageBicubic_lRGBA8888_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
}
else if(self->_interpolationQuality==kCGInterpolationLow)
KGImageBilinear_lRGBA8888_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
else
KGImagePointSampling_lRGBA8888_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
KGImageBilinear_lRGBAffff_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
}
static void KGPaintReadResampledNoneSpan_lRGBAffff_PRE(KGPaint *selfX,int x,int y,KGRGBAffff *span,int length){
KGPaint_image *self=(KGPaint_image *)selfX;
KGImagePointSampling_lRGBAffff_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
}
//
static void KGPaintReadResampledHighSpan_lRGBA8888_PRE(KGPaint *selfX,int x,int y,KGRGBA8888 *span,int length){
KGPaint_image *self=(KGPaint_image *)selfX;
KGImageBicubic_lRGBA8888_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
}
static void KGPaintReadResampledLowSpan_lRGBA8888_PRE(KGPaint *selfX,int x,int y,KGRGBA8888 *span,int length){
KGPaint_image *self=(KGPaint_image *)selfX;
KGImageBilinear_lRGBA8888_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
}
static void KGPaintReadResampledNoneSpan_lRGBA8888_PRE(KGPaint *selfX,int x,int y,KGRGBA8888 *span,int length){
KGPaint_image *self=(KGPaint_image *)selfX;
KGImagePointSampling_lRGBA8888_PRE(self->_image,x,y,span,length,self->m_surfaceToPaintMatrix);
}
static void multiply(KGPaint *selfX,int x,int y,KGRGBAffff *span,int length){
@ -60,7 +73,9 @@ static void multiply(KGPaint *selfX,int x,int y,KGRGBAffff *span,int length){
KGPaintReadSpan_lRGBAffff_PRE(self->_paint,x,y,span,length);
KGRGBAffff imageSpan[length];
KGPaintReadResampledSpan_lRGBAffff_PRE(self,x,y,imageSpan,length);
// FIXME: Should this take into account the interpolation quality? (depends on how it is used)
KGPaintReadResampledNoneSpan_lRGBAffff_PRE(self,x,y,imageSpan,length);
int i;
@ -87,7 +102,8 @@ static void stencil(KGPaint *selfX,int x,int y,KGRGBAffff *span,int length){
self->_paint->_read_lRGBAffff_PRE(self->_paint,x,y,span,length);
KGRGBAffff imageSpan[length];
KGPaintReadResampledSpan_lRGBAffff_PRE(self,x,y,imageSpan,length);
// FIXME: Should this take into account the interpolation quality? (depends on how it is used)
KGPaintReadResampledNoneSpan_lRGBAffff_PRE(self,x,y,imageSpan,length);
int i;
@ -135,15 +151,35 @@ static void stencil(KGPaint *selfX,int x,int y,KGRGBAffff *span,int length){
-initWithImage:(KGImage *)image mode:(KGSurfaceMode)mode paint:(KGPaint *)paint interpolationQuality:(CGInterpolationQuality)interpolationQuality {
[super init];
switch(mode){
case VG_DRAW_IMAGE_MULTIPLY:
_read_lRGBAffff_PRE=multiply;
break;
case VG_DRAW_IMAGE_STENCIL:
_read_lRGBAffff_PRE=stencil;
break;
default:
_read_lRGBA8888_PRE=KGPaintReadResampledSpan_lRGBA8888_PRE;
_read_lRGBAffff_PRE=KGPaintReadResampledSpan_lRGBAffff_PRE;
switch(interpolationQuality){
case kCGInterpolationHigh:
_read_lRGBA8888_PRE=KGPaintReadResampledHighSpan_lRGBA8888_PRE;
_read_lRGBAffff_PRE=KGPaintReadResampledHighSpan_lRGBAffff_PRE;
break;
case kCGInterpolationLow:
_read_lRGBA8888_PRE=KGPaintReadResampledLowSpan_lRGBA8888_PRE;
_read_lRGBAffff_PRE=KGPaintReadResampledLowSpan_lRGBAffff_PRE;
break;
case kCGInterpolationNone:
default:
_read_lRGBA8888_PRE=KGPaintReadResampledNoneSpan_lRGBA8888_PRE;
_read_lRGBAffff_PRE=KGPaintReadResampledNoneSpan_lRGBAffff_PRE;
break;
}
break;
}

View File

@ -7,7 +7,6 @@ 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 <Foundation/NSObject.h>
#import <Foundation/NSGeometry.h>
#import <ApplicationServices/ApplicationServices.h>
@interface KGPath : NSObject <NSCopying,NSMutableCopying> {

View File

@ -274,6 +274,36 @@ static void KGSurfaceWrite_RGBA8888_to_RGBA8888(KGSurface *self,int x,int y,KGRG
}
}
static void KGSurfaceWrite_RGBAffff_to_ABGR8888(KGSurface *self,int x,int y,KGRGBAffff *span,int length){
RIuint8* scanline = self->_pixelBytes + y * self->_bytesPerRow;
int i;
scanline+=x*4;
for(i=0;i<length;i++){
KGRGBAffff rgba=*span++;
*scanline++=CGByteFromFloat(rgba.a);
*scanline++=CGByteFromFloat(rgba.b);
*scanline++=CGByteFromFloat(rgba.g);
*scanline++=CGByteFromFloat(rgba.r);
}
}
static void KGSurfaceWrite_RGBA8888_to_ABGR8888(KGSurface *self,int x,int y,KGRGBA8888 *span,int length){
RIuint8* scanline = self->_pixelBytes + y * self->_bytesPerRow;
int i;
scanline+=x*4;
for(i=0;i<length;i++){
KGRGBA8888 rgba=*span++;
*scanline++=rgba.a;
*scanline++=rgba.b;
*scanline++=rgba.g;
*scanline++=rgba.r;
}
}
static void KGSurfaceWrite_RGBA8888_to_BGRA8888(KGSurface *self,int x,int y,KGRGBA8888 *span,int length){
RIuint8* scanline = self->_pixelBytes + y * self->_bytesPerRow;
int i;
@ -289,21 +319,6 @@ static void KGSurfaceWrite_RGBA8888_to_BGRA8888(KGSurface *self,int x,int y,KGRG
}
}
static void KGImageWrite_RGBAffff_to_ABGR8888(KGSurface *self,int x,int y,KGRGBAffff *span,int length){
RIuint8* scanline = self->_pixelBytes + y * self->_bytesPerRow;
int i;
scanline+=x*4;
for(i=0;i<length;i++){
KGRGBAffff rgba=*span++;
*scanline++=CGByteFromFloat(rgba.a);
*scanline++=CGByteFromFloat(rgba.b);
*scanline++=CGByteFromFloat(rgba.g);
*scanline++=CGByteFromFloat(rgba.r);
}
}
static void KGSurfaceWrite_RGBAffff_to_RGBA4444(KGSurface *self,int x,int y,KGRGBAffff *span,int length){
RIuint8* scanline = self->_pixelBytes + y * self->_bytesPerRow;
int i;
@ -424,7 +439,8 @@ static BOOL initFunctionsForParameters(KGSurface *self,size_t bitsPerComponent,s
case kCGBitmapByteOrderDefault:
case kCGBitmapByteOrder16Little:
case kCGBitmapByteOrder32Little:
self->_writeRGBAffff=KGImageWrite_RGBAffff_to_ABGR8888;
self->_writeRGBAffff=KGSurfaceWrite_RGBAffff_to_ABGR8888;
self->_writeRGBA8888=KGSurfaceWrite_RGBA8888_to_ABGR8888;
return YES;
case kCGBitmapByteOrder16Big:

View File

@ -156,7 +156,31 @@ static inline CGGlyphMetrics *glyphInfoForGlyph(CGGlyphMetricsSet *infoSet,NSGly
_metrics.underlinePosition=ttMetrics->otmsUnderscorePosition;
}
-(BOOL)fetchSharedGlyphRangeTable {
static NSMapTable *nameToGlyphRanges=NULL;
CGGlyphRangeTable *shared;
BOOL result=YES;
if(nameToGlyphRanges==NULL)
nameToGlyphRanges=NSCreateMapTable(NSObjectMapKeyCallBacks,NSNonOwnedPointerMapValueCallBacks,0);
shared=NSMapGet(nameToGlyphRanges,_name);
if(shared==NULL){
result=NO;
shared=NSZoneCalloc(NULL,sizeof(CGGlyphRangeTable),1);
NSMapInsert(nameToGlyphRanges,_name,shared);
}
_glyphRangeTable=shared;
return result;
}
-(void)loadGlyphRangeTable {
if([self fetchSharedGlyphRangeTable])
return;
HDC dc=[self deviceContextSelfSelected];
NSRange range=NSMakeRange(0,MAXUNICHAR);
unichar characters[range.length];
@ -187,7 +211,7 @@ static inline CGGlyphMetrics *glyphInfoForGlyph(CGGlyphMetricsSet *infoSet,NSGly
if(GetCharacterPlacementW(dc,characters,range.length,0,&results,0)==0)
NSLog(@"GetCharacterPlacementW failed");
}
_glyphRangeTable->numberOfGlyphs=0;
for(i=0;i<range.length;i++){
unsigned short glyph=glyphs[i];