mirror of
https://github.com/gnustep/libs-back.git
synced 2025-05-30 17:00:52 +00:00
Fixes for doublebuffering. (Nearly?) correct implementation of -compositeGState: and -drawGState:. Temporarily fixed image drawing issues by lying about drawing to screen.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@37142 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
ff80e49fb1
commit
595cc19471
6 changed files with 500 additions and 67 deletions
66
ChangeLog
66
ChangeLog
|
@ -1,3 +1,69 @@
|
||||||
|
2013-09-23 Ivan Vucica <ivan@vucica.net>
|
||||||
|
|
||||||
|
* Source/opal/OpalContext.m:
|
||||||
|
Once again pretending we're not drawing on screen. This is a temporary
|
||||||
|
fix for -DPSimage:.
|
||||||
|
|
||||||
|
-DPSgsave is now passed on to current gstate before GSContext is given
|
||||||
|
chance to replace it.
|
||||||
|
|
||||||
|
Changes relating to rename of OpalSurface and OpalGState methods
|
||||||
|
-cgContext to -CGContext.
|
||||||
|
|
||||||
|
* Source/opal/OpalGState.m:
|
||||||
|
Apparently mostly functional -compositeGState:. Includes disabled
|
||||||
|
modification of code from CairoGState.
|
||||||
|
|
||||||
|
Apparently functional -drawGState.
|
||||||
|
|
||||||
|
-DPSsetlinecap: stub (need to match linecap constants.)
|
||||||
|
-DPSsetmiterlimit:.
|
||||||
|
|
||||||
|
Extended -copyWithZone: to assign a 'default' OpalGStateRef to the
|
||||||
|
newly copied gstate in case we currently have no context. This is
|
||||||
|
done by creating a context and copying whatever's in that context
|
||||||
|
onto the new OpalGState.
|
||||||
|
|
||||||
|
Improved -DPSinitgraphics by setting the device offset that was
|
||||||
|
set here and calling CGContextSaveGState() as many times as it
|
||||||
|
was supposed to be called while CGContext did not exist. Noted
|
||||||
|
that we should, instead of recreating contexts, just reset the
|
||||||
|
internal GState of Opal.
|
||||||
|
|
||||||
|
Added -GSSetCTM:.
|
||||||
|
|
||||||
|
-flushGraphics no longer 'flushes' rect 0,0,1024,1024. Now it instead
|
||||||
|
queries surface for its size.
|
||||||
|
|
||||||
|
In case surface exists but not the CGContext, -DPSgsave creates it.
|
||||||
|
Otherwise, it records that gsave should be run upon context
|
||||||
|
creation.
|
||||||
|
|
||||||
|
Added -DPSsetlinewidth:.
|
||||||
|
|
||||||
|
Changes relating to rename of OpalSurface and OpalGState methods
|
||||||
|
-cgContext to -CGContext.
|
||||||
|
|
||||||
|
* Source/opal/OpalSurface.m:
|
||||||
|
Added reminder of how we should handle recreation of CGContexts.
|
||||||
|
|
||||||
|
Disabled non-doublebuffered windows. (We always need a backing
|
||||||
|
CGBitmapContext so we can implement -compositeGState: and -drawGState:.
|
||||||
|
|
||||||
|
Added accessors -x11CGContext and -backingCGContext.
|
||||||
|
|
||||||
|
Fixed bug where sometimes we'd get incorrect expose values and would
|
||||||
|
try to incorrectly copy the backing image, stretching the resulting
|
||||||
|
on-screen image.
|
||||||
|
|
||||||
|
Added -size accessor.
|
||||||
|
|
||||||
|
* Headers/opal/OpalGState.h:
|
||||||
|
Some accessors. _CGContextSaveGStatesOnContextCreation ivar.
|
||||||
|
|
||||||
|
* Headers/opal/OpalSurface.h:
|
||||||
|
New and renamed accessors.
|
||||||
|
|
||||||
2013-09-19 Ivan Vucica <ivan@vucica.net>
|
2013-09-19 Ivan Vucica <ivan@vucica.net>
|
||||||
|
|
||||||
* Source/opal/OpalContext.m:
|
* Source/opal/OpalContext.m:
|
||||||
|
|
|
@ -57,6 +57,15 @@
|
||||||
have a different cairo_t with the same surface.
|
have a different cairo_t with the same surface.
|
||||||
**/
|
**/
|
||||||
OPGStateRef _opGState;
|
OPGStateRef _opGState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sometimes, -DPSgsave may get called before context has
|
||||||
|
been created.
|
||||||
|
|
||||||
|
We need a counter for how many times CGContextSaveGState()
|
||||||
|
needs to be called in first -DPSinitgraphics that gets called.
|
||||||
|
**/
|
||||||
|
int _CGContextSaveGStatesOnContextCreation;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) DPSinitclip;
|
- (void) DPSinitclip;
|
||||||
|
@ -84,10 +93,13 @@
|
||||||
- (void) GSSetSurface: (OpalSurface *)opalSurface
|
- (void) GSSetSurface: (OpalSurface *)opalSurface
|
||||||
: (int)x
|
: (int)x
|
||||||
: (int)y;
|
: (int)y;
|
||||||
|
|
||||||
|
- (void) DPSgsave;
|
||||||
|
- (void) DPSgrestore;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface OpalGState (Accessors)
|
@interface OpalGState (Accessors)
|
||||||
- (CGContextRef) cgContext;
|
- (CGContextRef) CGContext;
|
||||||
- (OPGStateRef) OPGState;
|
- (OPGStateRef) OPGState;
|
||||||
- (void) setOPGState: (OPGStateRef) opGState;
|
- (void) setOPGState: (OPGStateRef) opGState;
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -37,8 +37,12 @@
|
||||||
|
|
||||||
- (id) initWithDevice: (void *)device;
|
- (id) initWithDevice: (void *)device;
|
||||||
- (struct _gswindow_device_t *) device;
|
- (struct _gswindow_device_t *) device;
|
||||||
- (CGContextRef) cgContext;
|
- (CGContextRef) CGContext;
|
||||||
- (void) createCGContexts;
|
- (void) createCGContexts;
|
||||||
|
- (NSSize) size;
|
||||||
|
|
||||||
|
- (CGContextRef) backingCGContext;
|
||||||
|
- (CGContextRef) x11CGContext;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface OpalSurface (DebugExtensions)
|
@interface OpalSurface (DebugExtensions)
|
||||||
|
|
|
@ -65,6 +65,9 @@
|
||||||
|
|
||||||
- (BOOL) isDrawingToScreen
|
- (BOOL) isDrawingToScreen
|
||||||
{
|
{
|
||||||
|
#warning isDrawingToScreen returning NO to fix DPSimage
|
||||||
|
return NO;
|
||||||
|
|
||||||
// NOTE: This was returning NO because it was not looking at the
|
// NOTE: This was returning NO because it was not looking at the
|
||||||
// return value of GSCurrentSurface. Now it returns YES, which
|
// return value of GSCurrentSurface. Now it returns YES, which
|
||||||
// seems to have broken image drawing (yellow rectangles are drawn instead)
|
// seems to have broken image drawing (yellow rectangles are drawn instead)
|
||||||
|
@ -75,8 +78,8 @@
|
||||||
|
|
||||||
- (void) DPSgsave
|
- (void) DPSgsave
|
||||||
{
|
{
|
||||||
[super DPSgsave];
|
|
||||||
[OGSTATE DPSgsave];
|
[OGSTATE DPSgsave];
|
||||||
|
[super DPSgsave];
|
||||||
}
|
}
|
||||||
- (void) DPSgrestore
|
- (void) DPSgrestore
|
||||||
{
|
{
|
||||||
|
@ -90,7 +93,7 @@
|
||||||
- (void) DPSsetgstate: (int)gstateID
|
- (void) DPSsetgstate: (int)gstateID
|
||||||
{
|
{
|
||||||
|
|
||||||
OPGStateRef previousGState = OPContextCopyGState([OGSTATE cgContext]);
|
OPGStateRef previousGState = OPContextCopyGState([OGSTATE CGContext]);
|
||||||
[OGSTATE setOPGState: previousGState];
|
[OGSTATE setOPGState: previousGState];
|
||||||
[previousGState release]; // FIXME
|
[previousGState release]; // FIXME
|
||||||
|
|
||||||
|
@ -99,17 +102,15 @@
|
||||||
OPGStateRef newGState = [OGSTATE OPGState];
|
OPGStateRef newGState = [OGSTATE OPGState];
|
||||||
if (newGState)
|
if (newGState)
|
||||||
{
|
{
|
||||||
OPContextSetGState([OGSTATE cgContext], newGState);
|
OPContextSetGState([OGSTATE CGContext], newGState);
|
||||||
[OGSTATE setOPGState: nil];
|
[OGSTATE setOPGState: nil];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
// FIXME: we should add this as soon as we implement -drawGState:...
|
|
||||||
- (BOOL) supportsDrawGState
|
- (BOOL) supportsDrawGState
|
||||||
{
|
{
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This handles 'expose' event notifications that arrive from
|
This handles 'expose' event notifications that arrive from
|
||||||
|
@ -127,7 +128,7 @@
|
||||||
{
|
{
|
||||||
OpalSurface * surface;
|
OpalSurface * surface;
|
||||||
[OGSTATE GSCurrentSurface: &surface : NULL : NULL];
|
[OGSTATE GSCurrentSurface: &surface : NULL : NULL];
|
||||||
return [surface cgContext];
|
return [surface CGContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BUILD_SERVER == SERVER_x11
|
#if BUILD_SERVER == SERVER_x11
|
||||||
|
|
|
@ -33,8 +33,19 @@
|
||||||
#import "opal/OpalFontInfo.h"
|
#import "opal/OpalFontInfo.h"
|
||||||
#import "x11/XGServerWindow.h"
|
#import "x11/XGServerWindow.h"
|
||||||
|
|
||||||
#define CGCTX [self cgContext]
|
#define CGCTX [self CGContext]
|
||||||
|
|
||||||
|
static inline NSString * _CGRectRepr(CGRect rect)
|
||||||
|
{
|
||||||
|
return [NSString stringWithFormat: @"(%g,%g,%g,%g)",
|
||||||
|
rect.origin.x, rect.origin.y,
|
||||||
|
rect.size.width, rect.size.height];
|
||||||
|
}
|
||||||
|
static inline CGRect _CGRectFromNSRect(NSRect nsrect)
|
||||||
|
{
|
||||||
|
return CGRectMake(nsrect.origin.x, nsrect.origin.y,
|
||||||
|
nsrect.size.width, nsrect.size.height);
|
||||||
|
}
|
||||||
|
|
||||||
@implementation OpalGState
|
@implementation OpalGState
|
||||||
|
|
||||||
|
@ -75,7 +86,7 @@
|
||||||
: (const unsigned char *const[5])data
|
: (const unsigned char *const[5])data
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
|
NSDebugLLog(@"OpalGState", @" %s - %@ - cgctx %@", __PRETTY_FUNCTION__, _opalSurface, [self CGContext]);
|
||||||
// This depends on CGAffineTransform and NSAffineTransformStruct having
|
// This depends on CGAffineTransform and NSAffineTransformStruct having
|
||||||
// the same in-memory layout.
|
// the same in-memory layout.
|
||||||
// Here's an elementary check if that is true.
|
// Here's an elementary check if that is true.
|
||||||
|
@ -84,10 +95,18 @@
|
||||||
NSAffineTransformStruct nsAT = [matrix transformStruct];
|
NSAffineTransformStruct nsAT = [matrix transformStruct];
|
||||||
CGAffineTransform cgAT = *(CGAffineTransform *)&nsAT;
|
CGAffineTransform cgAT = *(CGAffineTransform *)&nsAT;
|
||||||
|
|
||||||
|
NSDebugLLog(@"OpalGState", @"tf: %@ x %@", matrix, [self GSCurrentCTM]);
|
||||||
CGContextSaveGState(CGCTX);
|
CGContextSaveGState(CGCTX);
|
||||||
// CGContextSetRGBFillColor(CGCTX, 1, 0, 0, 1);
|
//OPContextSetIdentityCTM(CGCTX);
|
||||||
CGContextConcatCTM(CGCTX, cgAT);
|
CGContextConcatCTM(CGCTX, cgAT);
|
||||||
// CGContextFillRect(CGCTX, CGRectMake(0, 0, pixelsWide, pixelsHigh));
|
//OPContextSetCairoDeviceOffset(CGCTX, 0, 0);
|
||||||
|
//CGContextMoveToPoint(CGCTX, 0, 0);
|
||||||
|
#if 0
|
||||||
|
CGContextSetRGBFillColor(CGCTX, 1, 0, 0, 1);
|
||||||
|
CGContextFillRect(CGCTX, CGRectMake(-512, -512, 1024, 1024 /*pixelsWide, pixelsHigh*/ ));
|
||||||
|
#endif
|
||||||
|
// CGContextRestoreGState(CGCTX);
|
||||||
|
// return;
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// We may want to normalize colorspace names between Opal and -gui,
|
// We may want to normalize colorspace names between Opal and -gui,
|
||||||
|
@ -141,6 +160,8 @@ NSLog(@" : samplesperpixel = %d", samplesPerPixel);
|
||||||
false, /* shouldInterpolate? */
|
false, /* shouldInterpolate? */
|
||||||
kCGRenderingIntentDefault );
|
kCGRenderingIntentDefault );
|
||||||
CGContextDrawImage(CGCTX, CGRectMake(0, 0, pixelsWide, pixelsHigh), img);
|
CGContextDrawImage(CGCTX, CGRectMake(0, 0, pixelsWide, pixelsHigh), img);
|
||||||
|
//[_opalSurface _saveImage: img withPrefix:@"/tmp/opalback-dpsimage-" size: NSZeroSize];
|
||||||
|
|
||||||
CGDataProviderRelease(dataProvider);
|
CGDataProviderRelease(dataProvider);
|
||||||
CGImageRelease(img);
|
CGImageRelease(img);
|
||||||
CGContextRestoreGState(CGCTX);
|
CGContextRestoreGState(CGCTX);
|
||||||
|
@ -153,22 +174,257 @@ NSLog(@" : samplesperpixel = %d", samplesPerPixel);
|
||||||
fraction: (CGFloat)delta
|
fraction: (CGFloat)delta
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
#if 0
|
CGContextRef destContexts[2] = { [_opalSurface backingCGContext], [_opalSurface x11CGContext] };
|
||||||
CGContextSaveGState(CGCTX);
|
|
||||||
CGContextSetRGBFillColor(CGCTX, 1, 1, 0, 1);
|
|
||||||
CGContextFillRect(CGCTX, CGRectMake(destPoint.x, destPoint.y, srcRect.size.width, srcRect.size.height));
|
|
||||||
CGContextRestoreGState(CGCTX);
|
|
||||||
#else
|
|
||||||
CGRect srcCGRect = CGRectMake(srcRect.origin.x, srcRect.origin.y,
|
|
||||||
srcRect.size.width, srcRect.size.height);
|
|
||||||
|
|
||||||
// FIXME: this presumes that the backing cgContext of 'source' is
|
/* x11 context needs to have correct ctm applied */
|
||||||
|
CGContextSaveGState([_opalSurface x11CGContext]);
|
||||||
|
OPContextSetIdentityCTM([_opalSurface x11CGContext]);
|
||||||
|
CGContextConcatCTM([_opalSurface x11CGContext], CGContextGetCTM([_opalSurface backingCGContext]));
|
||||||
|
|
||||||
|
for (int i = 0; i < 1; i++) // not drawing into x11cgctx after all.
|
||||||
|
{
|
||||||
|
CGContextRef ctx = destContexts[i];
|
||||||
|
|
||||||
|
[self compositeGState: source
|
||||||
|
fromRect: srcRect
|
||||||
|
toPoint: destPoint
|
||||||
|
op: op
|
||||||
|
fraction: delta
|
||||||
|
destCGContext: ctx];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore x11 context's previous state */
|
||||||
|
CGContextRestoreGState([_opalSurface x11CGContext]);
|
||||||
|
}
|
||||||
|
- (void) drawGState: (OpalGState *)source
|
||||||
|
fromRect: (NSRect)srcRect
|
||||||
|
toPoint: (NSPoint)destPoint
|
||||||
|
op: (NSCompositingOperation)op
|
||||||
|
fraction: (CGFloat)delta
|
||||||
|
{
|
||||||
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
|
CGContextRef destContexts[2] = { [_opalSurface backingCGContext], [_opalSurface x11CGContext] };
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
CGContextRef ctx = destContexts[i];
|
||||||
|
|
||||||
|
[self drawGState: source
|
||||||
|
fromRect: srcRect
|
||||||
|
toPoint: destPoint
|
||||||
|
op: op
|
||||||
|
fraction: delta
|
||||||
|
destCGContext: ctx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- (void) compositeGState: (OpalGState *)source
|
||||||
|
fromRect: (NSRect)srcRect
|
||||||
|
toPoint: (NSPoint)destPoint
|
||||||
|
op: (NSCompositingOperation)op
|
||||||
|
fraction: (CGFloat)delta
|
||||||
|
destCGContext: (CGContextRef) destCGContext
|
||||||
|
{
|
||||||
|
// NOTE: This method seems to need to paint to X11 context, too.
|
||||||
|
|
||||||
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s - from %@ of gstate %p (cgctx %p) to %@ of %p (cgctx %p)", self, [self class], __PRETTY_FUNCTION__, NSStringFromRect(srcRect), source, [source CGContext], NSStringFromPoint(destPoint), self, [self CGContext]);
|
||||||
|
#if 0
|
||||||
|
CGContextSaveGState(destCGContext);
|
||||||
|
CGContextSetRGBFillColor(destCGContext, 1, 1, 0, 1);
|
||||||
|
CGContextFillRect(destCGContext, CGRectMake(destPoint.x, destPoint.y, srcRect.size.width, srcRect.size.height));
|
||||||
|
CGContextRestoreGState(destCGContext);
|
||||||
|
#else
|
||||||
|
#if 1
|
||||||
|
NSSize ssize = [source->_opalSurface size];
|
||||||
|
srcRect = [[source GSCurrentCTM] rectInMatrixSpace: srcRect];
|
||||||
|
destPoint = [[self GSCurrentCTM] pointInMatrixSpace: destPoint];
|
||||||
|
|
||||||
|
srcRect.origin.y = ssize.height-srcRect.origin.y-srcRect.size.height;
|
||||||
|
|
||||||
|
CGRect srcCGRect = _CGRectFromNSRect(srcRect);
|
||||||
|
CGRect destCGRect = CGRectMake(destPoint.x, destPoint.y,
|
||||||
|
srcRect.size.width, srcRect.size.height);
|
||||||
|
NSLog(@"Source cgctx: %p, self: %p - from %@ to %@ with ctm %@", [source CGContext], self, _CGRectRepr(srcCGRect), _CGRectRepr(destCGRect), [self GSCurrentCTM]);
|
||||||
|
// FIXME: this presumes that the backing CGContext of 'source' is
|
||||||
// an OpalSurface with a backing CGBitmapContext
|
// an OpalSurface with a backing CGBitmapContext
|
||||||
CGImageRef backingImage = CGBitmapContextCreateImage([source cgContext]);
|
CGImageRef backingImage = CGBitmapContextCreateImage([source CGContext]);
|
||||||
CGContextMoveToPoint(CGCTX, destPoint.x, destPoint.y);
|
CGImageRef subImage = CGImageCreateWithImageInRect(backingImage, srcCGRect);
|
||||||
|
|
||||||
|
CGContextSaveGState(destCGContext);
|
||||||
|
OPContextSetIdentityCTM(destCGContext);
|
||||||
|
OPContextSetCairoDeviceOffset(destCGContext, 0, 0);
|
||||||
|
|
||||||
// TODO: this ignores op
|
// TODO: this ignores op
|
||||||
// TODO: this ignores delta
|
// TODO: this ignores delta
|
||||||
CGContextDrawImage(CGCTX, srcCGRect, backingImage);
|
CGContextDrawImage(destCGContext, destCGRect, subImage);
|
||||||
|
|
||||||
|
OPContextSetCairoDeviceOffset(CGCTX, -offset.x,
|
||||||
|
offset.y - [_opalSurface device]->buffer_height);
|
||||||
|
|
||||||
|
CGContextRestoreGState(destCGContext);
|
||||||
|
|
||||||
|
CGImageRelease(subImage);
|
||||||
|
CGImageRelease(backingImage);
|
||||||
|
#else
|
||||||
|
CGImageRef src;
|
||||||
|
NSSize ssize = NSZeroSize;
|
||||||
|
BOOL copyOnSelf;
|
||||||
|
/* The source rect in the source base coordinate space.
|
||||||
|
This rect is the minimum bounding rect of srcRect. */
|
||||||
|
NSRect srcRectInBase = NSZeroRect;
|
||||||
|
/* The destination point in the target base coordinate space */
|
||||||
|
NSPoint destPointInBase = NSZeroPoint;
|
||||||
|
/* The origin of srcRectInBase */
|
||||||
|
double minx, miny;
|
||||||
|
/* The composited content size */
|
||||||
|
double width, height;
|
||||||
|
/* The adjusted destination point in the target base coordinate space */
|
||||||
|
double x, y;
|
||||||
|
/* Alternative source rect origin in the source current CTM */
|
||||||
|
NSPoint srcRectAltOrigin;
|
||||||
|
/* Alternative source rect origin in the source base coordinate space */
|
||||||
|
NSPoint srcRectAltOriginInBase;
|
||||||
|
/* The source rect origin in the source base coordinate space */
|
||||||
|
NSPoint srcRectOriginInBase;
|
||||||
|
BOOL originFlippedBetweenBaseAndSource = NO;
|
||||||
|
/* The delta between the origins of srcRect and srcRectInBase */
|
||||||
|
double dx, dy;
|
||||||
|
|
||||||
|
if (![source CGContext] || !destCGContext)
|
||||||
|
return;
|
||||||
|
|
||||||
|
src = CGBitmapContextCreateImage([source CGContext]);
|
||||||
|
copyOnSelf = ([source CGContext] == destCGContext);
|
||||||
|
srcRectAltOrigin = NSMakePoint(srcRect.origin.x, srcRect.origin.y + srcRect.size.height);
|
||||||
|
srcRectAltOriginInBase = [[source GSCurrentCTM] transformPoint: srcRectAltOrigin];
|
||||||
|
srcRectOriginInBase = [[source GSCurrentCTM] transformPoint: srcRect.origin];
|
||||||
|
|
||||||
|
CGContextSaveGState(destCGContext);
|
||||||
|
|
||||||
|
/* When the target and source are the same surface, we use the group tricks */
|
||||||
|
/* // ?
|
||||||
|
if (copyOnSelf) cairo_push_group(_ct);
|
||||||
|
|
||||||
|
cairo_new_path(_ct);
|
||||||
|
_set_op(_ct, op);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Scales and/or rotates the local destination point with the current AppKit CTM */
|
||||||
|
destPointInBase = [ctm transformPoint: destPoint];
|
||||||
|
|
||||||
|
/* Scales and/or rotates the source rect and retrieves the minimum bounding
|
||||||
|
rectangle that encloses it and makes it our source area */
|
||||||
|
[[source GSCurrentCTM] boundingRectFor: srcRect result: &srcRectInBase];
|
||||||
|
|
||||||
|
/* Find whether the source rect origin in the base is the same than in the
|
||||||
|
source current CTM.
|
||||||
|
We need to know the origin in the base to compute how much the source
|
||||||
|
bounding rect origin is shifted relatively to the closest source rect corner.
|
||||||
|
We use this delta (dx, dy) to correctly composite from a rotated source. */
|
||||||
|
originFlippedBetweenBaseAndSource =
|
||||||
|
((srcRect.origin.y < srcRectAltOrigin.y && srcRectOriginInBase.y > srcRectAltOriginInBase.y)
|
||||||
|
|| (srcRect.origin.y > srcRectAltOrigin.y && srcRectOriginInBase.y < srcRectAltOriginInBase.y));
|
||||||
|
if (originFlippedBetweenBaseAndSource)
|
||||||
|
{
|
||||||
|
srcRectOriginInBase = srcRectAltOriginInBase;
|
||||||
|
}
|
||||||
|
dx = srcRectOriginInBase.x - srcRectInBase.origin.x;
|
||||||
|
dy = srcRectOriginInBase.y - srcRectInBase.origin.y;
|
||||||
|
|
||||||
|
if (source->_opalSurface != nil)
|
||||||
|
{
|
||||||
|
ssize = [source->_opalSurface size];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// ?
|
||||||
|
if (cairo_version() >= CAIRO_VERSION_ENCODE(1, 8, 0))
|
||||||
|
{
|
||||||
|
// For cairo > 1.8 we seem to need this adjustment
|
||||||
|
srcRectInBase.origin.y -= 2 * (source->offset.y - ssize.height);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
x = destPointInBase.x;
|
||||||
|
y = destPointInBase.y;
|
||||||
|
minx = NSMinX(srcRectInBase);
|
||||||
|
miny = NSMinY(srcRectInBase);
|
||||||
|
width = NSWidth(srcRectInBase);
|
||||||
|
height = NSHeight(srcRectInBase);
|
||||||
|
|
||||||
|
|
||||||
|
/* Comment from cairo backend:
|
||||||
|
-----8<---- */
|
||||||
|
/* We respect the AppKit CTM effect on the origin 'aPoint' (see
|
||||||
|
-[ctm transformPoint:]), but we ignore the scaling and rotation effect on
|
||||||
|
the composited content and size. Which means we never rotate or scale the
|
||||||
|
content we composite.
|
||||||
|
We use a pattern as a trick to simulate a target CTM change, this way we
|
||||||
|
don't touch the source CTM even when both source and target are identical
|
||||||
|
(e.g. scrolling case).
|
||||||
|
We must use a pattern matrix that matches the AppKit base CTM set up in
|
||||||
|
-DPSinitgraphics to ensure no transform is applied to the source content,
|
||||||
|
translation adjustements related to destination point and source rect put
|
||||||
|
aside. */
|
||||||
|
/* -----8<----
|
||||||
|
We don't have patterns with their own matrices at our disposal, so the
|
||||||
|
relevant code is NOT here. Instead we directly use srcRectInBase
|
||||||
|
*/
|
||||||
|
|
||||||
|
NSLog(@"dy: %d", (int)dy);
|
||||||
|
CGRect srcCGRect = CGRectMake(srcRect.origin.x, srcRect.origin.y, srcRect.size.width, srcRect.size.height);
|
||||||
|
srcCGRect = CGRectMake(minx, miny, width, height);
|
||||||
|
CGImageRef srcSubImage = CGImageCreateWithImageInRect(src, srcCGRect);
|
||||||
|
//OPContextSetIdentityCTM(destCGContext);
|
||||||
|
//CGContextScaleCTM(destCGContext, 1, -1);
|
||||||
|
//CGContextTranslateCTM(destCGContext, -(minx - x + dx), miny - y + dy - ssize.height);
|
||||||
|
//OPContextResetClip(destCGContext);
|
||||||
|
//CGContextAddRect(destCGContext, CGRectMake(x, y, width, height));
|
||||||
|
//CGContextClip(destCGContext);
|
||||||
|
// TODO: this ignores op
|
||||||
|
// TODO: this ignores delta
|
||||||
|
// (delta == opacity, in cairo backend)
|
||||||
|
CGRect destCGRect = CGRectMake(x, y, width, height);
|
||||||
|
CGContextDrawImage(destCGContext, destCGRect, srcSubImage);
|
||||||
|
CGContextSetRGBFillColor(destCGContext, 0.6, 1.0, 0.2, 0.2);
|
||||||
|
CGContextFillRect(destCGContext, destCGRect);
|
||||||
|
// NSLog(@" --> compsoiting subimage %@", srcSubImage);
|
||||||
|
//[source->_opalSurface _saveImage: srcSubImage withPrefix:[NSString stringWithFormat: @"/tmp/opalback-compositing-subimage-%p-", [source CGContext]] size: srcCGRect.size ];
|
||||||
|
//[source->_opalSurface _saveImage: src withPrefix:[NSString stringWithFormat: @"/tmp/opalback-compositing-image-%p-", [source CGContext]] size: NSZeroSize ];
|
||||||
|
CGImageRelease(src);
|
||||||
|
|
||||||
|
CGContextRestoreGState(destCGContext);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unlike -compositeGState, -drawGSstate fully respects the AppKit CTM but
|
||||||
|
doesn't support to use the receiver cairo target as the source. */
|
||||||
|
/* This method is required if -[OpalContext supportsDrawGState] returns YES */
|
||||||
|
- (void) drawGState: (OpalGState *)source
|
||||||
|
fromRect: (NSRect)srcRect
|
||||||
|
toPoint: (NSPoint)destPoint
|
||||||
|
op: (NSCompositingOperation)op
|
||||||
|
fraction: (CGFloat)delta
|
||||||
|
destCGContext: (CGContextRef)destCGContext
|
||||||
|
{
|
||||||
|
// TODO: CairoGState has a lot more complex implementation.
|
||||||
|
// For now, we'll just call compositeGState and live
|
||||||
|
// with the fact that CTM is not respected.
|
||||||
|
|
||||||
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
|
#if 0
|
||||||
|
[self compositeGState: source fromRect: srcRect toPoint: destPoint op: op fraction: delta destCGContext: destCGContext];
|
||||||
|
#else
|
||||||
|
CGRect srcCGRect = CGRectMake(srcRect.origin.x, srcRect.origin.y,
|
||||||
|
srcRect.size.width, srcRect.size.height);
|
||||||
|
CGRect destCGRect = CGRectMake(destPoint.x, destPoint.y,
|
||||||
|
srcRect.size.width, srcRect.size.height);
|
||||||
|
CGImageRef backingImage = CGBitmapContextCreateImage([source CGContext]);
|
||||||
|
CGImageRef subImage = CGImageCreateWithImageInRect(backingImage, srcCGRect);
|
||||||
|
// TODO: this ignores op
|
||||||
|
// TODO: this ignores delta
|
||||||
|
CGContextDrawImage(destCGContext, destCGRect, subImage);
|
||||||
|
CGImageRelease(subImage);
|
||||||
CGImageRelease(backingImage);
|
CGImageRelease(backingImage);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -204,19 +460,20 @@ NSLog(@" : samplesperpixel = %d", samplesPerPixel);
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// TODO: stub
|
CGContextSetLineJoin(CGCTX, linejoin);
|
||||||
}
|
}
|
||||||
- (void) DPSsetlinecap: (int)linecap
|
- (void) DPSsetlinecap: (int)linecap
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// TODO: stub
|
// TODO: ensure match of linecap constants between Opal and DPS
|
||||||
|
CGContextSetLineCap(CGCTX, linecap);
|
||||||
}
|
}
|
||||||
- (void) DPSsetmiterlimit: (CGFloat)miterlimit
|
- (void) DPSsetmiterlimit: (CGFloat)miterlimit
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// TODO: stub
|
CGContextSetMiterLimit(CGCTX, miterlimit);
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -227,10 +484,25 @@ NSLog(@" : samplesperpixel = %d", samplesPerPixel);
|
||||||
|
|
||||||
- (id)copyWithZone: (NSZone *)zone
|
- (id)copyWithZone: (NSZone *)zone
|
||||||
{
|
{
|
||||||
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
OpalGState * theCopy = (OpalGState *) [super copyWithZone: zone];
|
OpalGState * theCopy = (OpalGState *) [super copyWithZone: zone];
|
||||||
|
|
||||||
[_opalSurface retain];
|
[_opalSurface retain];
|
||||||
theCopy->_opGState = OPContextCopyGState(CGCTX);
|
if (CGCTX)
|
||||||
|
{
|
||||||
|
theCopy->_opGState = OPContextCopyGState(CGCTX);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// FIXME: perhaps Opal could provide an API for getting the default
|
||||||
|
// gstate?
|
||||||
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
|
||||||
|
CGContextRef ctx = CGBitmapContextCreate(NULL, 1, 1, 8, 32, colorSpace, kCGImageAlphaPremultipliedFirst);
|
||||||
|
CGColorSpaceRelease(colorSpace);
|
||||||
|
theCopy->_opGState = OPContextCopyGState(ctx);
|
||||||
|
CGContextRelease(ctx);
|
||||||
|
NSLog(@"Included default gstate %p", theCopy->_opGState);
|
||||||
|
}
|
||||||
|
|
||||||
return theCopy;
|
return theCopy;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +530,7 @@ NSLog(@" : samplesperpixel = %d", samplesPerPixel);
|
||||||
: (int)x
|
: (int)x
|
||||||
: (int)y
|
: (int)y
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s - %@ %d %d", self, [self class], __PRETTY_FUNCTION__, opalSurface, x, y);
|
||||||
|
|
||||||
if(_opalSurface != opalSurface)
|
if(_opalSurface != opalSurface)
|
||||||
{
|
{
|
||||||
|
@ -287,7 +559,29 @@ NSLog(@" : samplesperpixel = %d", samplesPerPixel);
|
||||||
|
|
||||||
[super DPSinitgraphics];
|
[super DPSinitgraphics];
|
||||||
|
|
||||||
|
if (!_opalSurface)
|
||||||
|
{
|
||||||
|
NSLog(@"%s: called before GSSetSurface:::", __PRETTY_FUNCTION__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: instead of recreating contexts, we should only reset
|
||||||
|
// the gstate portion of the contexts. Add OPContextResetGState() which
|
||||||
|
// recreates _ct and resets _ctadditions. See DPSinitgraphics in
|
||||||
|
// CairoGState.
|
||||||
|
|
||||||
[_opalSurface createCGContexts];
|
[_opalSurface createCGContexts];
|
||||||
|
|
||||||
|
OPContextSetCairoDeviceOffset(CGCTX, -offset.x,
|
||||||
|
offset.y - [_opalSurface device]->buffer_height);
|
||||||
|
|
||||||
|
while (_CGContextSaveGStatesOnContextCreation > 0)
|
||||||
|
{
|
||||||
|
NSLog(@"%d more times", _CGContextSaveGStatesOnContextCreation);
|
||||||
|
CGContextSaveGState(CGCTX);
|
||||||
|
_CGContextSaveGStatesOnContextCreation--;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if ([_opalSurface device])
|
if ([_opalSurface device])
|
||||||
{
|
{
|
||||||
|
@ -304,13 +598,13 @@ NSLog(@" : samplesperpixel = %d", samplesPerPixel);
|
||||||
|
|
||||||
@implementation OpalGState (Accessors)
|
@implementation OpalGState (Accessors)
|
||||||
|
|
||||||
- (CGContextRef) cgContext
|
- (CGContextRef) CGContext
|
||||||
{
|
{
|
||||||
if (!_opalSurface)
|
if (!_opalSurface)
|
||||||
NSDebugMLLog(@"OpalGState", @"No OpalSurface");
|
NSDebugMLLog(@"OpalGState", @"No OpalSurface");
|
||||||
else if (![_opalSurface cgContext])
|
else if (![_opalSurface CGContext])
|
||||||
NSDebugMLLog(@"OpalGState", @"No OpalSurface CGContext");
|
NSDebugMLLog(@"OpalGState", @"No OpalSurface CGContext");
|
||||||
return [_opalSurface cgContext];
|
return [_opalSurface CGContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (OPGStateRef) OPGState
|
- (OPGStateRef) OPGState
|
||||||
|
@ -473,7 +767,9 @@ static CGFloat theAlpha = 1.; // TODO: removeme
|
||||||
- (NSAffineTransform *) GSCurrentCTM
|
- (NSAffineTransform *) GSCurrentCTM
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
|
return ctm;
|
||||||
|
|
||||||
CGAffineTransform cgCTM = CGContextGetCTM(CGCTX);
|
CGAffineTransform cgCTM = CGContextGetCTM(CGCTX);
|
||||||
NSAffineTransform * affineTransform = [NSAffineTransform transform];
|
NSAffineTransform * affineTransform = [NSAffineTransform transform];
|
||||||
|
|
||||||
|
@ -488,25 +784,54 @@ static CGFloat theAlpha = 1.; // TODO: removeme
|
||||||
|
|
||||||
return affineTransform;
|
return affineTransform;
|
||||||
}
|
}
|
||||||
|
- (void) GSSetCTM: (NSAffineTransform *)newCTM
|
||||||
|
{
|
||||||
|
// This depends on CGAffineTransform and NSAffineTransformStruct having
|
||||||
|
// the same in-memory layout.
|
||||||
|
// Here's an elementary check if that is true.
|
||||||
|
// We should probably check this in -back's "configure" script.
|
||||||
|
assert(sizeof(CGAffineTransform) == sizeof(NSAffineTransformStruct));
|
||||||
|
NSAffineTransformStruct nsAT = [newCTM transformStruct];
|
||||||
|
CGAffineTransform cgAT = *(CGAffineTransform *)&nsAT;
|
||||||
|
|
||||||
|
OPContextSetIdentityCTM(CGCTX);
|
||||||
|
CGContextConcatCTM(CGCTX, cgAT);
|
||||||
|
|
||||||
|
[super GSSetCTM: newCTM];
|
||||||
|
}
|
||||||
- (void) flushGraphics
|
- (void) flushGraphics
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
CGContextFlush(CGCTX);
|
CGContextFlush(CGCTX);
|
||||||
[_opalSurface handleExpose:CGRectMake(0, 0, 1024, 1024)]; // FIXME
|
[_opalSurface handleExpose: [_opalSurface size]];
|
||||||
}
|
}
|
||||||
- (void) DPSgsave
|
- (void) DPSgsave
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
#warning Opal bug: nil ctx should 'only' print a warning instead of crashing
|
if (!CGCTX)
|
||||||
if (CGCTX)
|
{
|
||||||
CGContextSaveGState(CGCTX);
|
if (_opalSurface)
|
||||||
|
{
|
||||||
|
[_opalSurface createCGContexts];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSLog(@"%s: called before CGContext was created; possible -gui bug?", __PRETTY_FUNCTION__);
|
||||||
|
_CGContextSaveGStatesOnContextCreation++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CGContextSaveGState(CGCTX);
|
||||||
}
|
}
|
||||||
- (void) DPSgrestore
|
- (void) DPSgrestore
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
#warning Opal bug: nil ctx should 'only' print a warning instead of crashing
|
if (!CGCTX)
|
||||||
if (CGCTX)
|
{
|
||||||
CGContextRestoreGState(CGCTX);
|
NSLog(@"%s: called before CGContext was created; possible -gui bug?", __PRETTY_FUNCTION__);
|
||||||
|
_CGContextSaveGStatesOnContextCreation--;
|
||||||
|
}
|
||||||
|
CGContextRestoreGState(CGCTX);
|
||||||
}
|
}
|
||||||
- (void *) saveClip
|
- (void *) saveClip
|
||||||
{
|
{
|
||||||
|
@ -626,6 +951,13 @@ static CGFloat theAlpha = 1.; // TODO: removeme
|
||||||
*y = currentPoint.y;
|
*y = currentPoint.y;
|
||||||
NSDebugLLog(@"OpalGState", @" %p (%@): %s (returning: %f %f)", self, [self class], __PRETTY_FUNCTION__, *x, *y);
|
NSDebugLLog(@"OpalGState", @" %p (%@): %s (returning: %f %f)", self, [self class], __PRETTY_FUNCTION__, *x, *y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) DPSsetlinewidth: (CGFloat) width
|
||||||
|
{
|
||||||
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
|
CGContextSetLineWidth(CGCTX, width);
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
// MARK: Non-required unimplemented methods
|
// MARK: Non-required unimplemented methods
|
||||||
|
@ -643,10 +975,6 @@ static CGFloat theAlpha = 1.; // TODO: removeme
|
||||||
empty NSWindow.
|
empty NSWindow.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
- (void) DPSsetlinewidth: (CGFloat) width
|
|
||||||
{
|
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
|
||||||
}
|
|
||||||
- (void) DPSsetgstate: (NSInteger) gst
|
- (void) DPSsetgstate: (NSInteger) gst
|
||||||
{
|
{
|
||||||
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
NSDebugLLog(@"OpalGState", @"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
|
||||||
|
|
|
@ -114,18 +114,29 @@ static CGContextRef createCGBitmapContext (int pixelsWide,
|
||||||
|
|
||||||
// FIXME: this method and class presumes we are being passed
|
// FIXME: this method and class presumes we are being passed
|
||||||
// a window device.
|
// a window device.
|
||||||
|
// FIXME: this method does not destroy existing contexts if
|
||||||
|
// needed, nor transfer Opal GState.
|
||||||
|
|
||||||
|
if (_x11CGContext || _backingCGContext)
|
||||||
|
{
|
||||||
|
NSLog(@"FIXME: Replacement of OpalSurface %p's CGContexts (x11=%p,backing=%p) without transfer of gstate", self, _x11CGContext, _backingCGContext);
|
||||||
|
}
|
||||||
|
|
||||||
Display * display = _gsWindowDevice->display;
|
Display * display = _gsWindowDevice->display;
|
||||||
Window window = _gsWindowDevice->ident;
|
Window window = _gsWindowDevice->ident;
|
||||||
|
|
||||||
_x11CGContext = OPX11ContextCreate(display, window);
|
_x11CGContext = OPX11ContextCreate(display, window);
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (_gsWindowDevice->type == NSBackingStoreNonretained)
|
if (_gsWindowDevice->type == NSBackingStoreNonretained)
|
||||||
{
|
{
|
||||||
// Don't double-buffer:
|
// Don't double-buffer:
|
||||||
// use the window surface as the drawing destination.
|
// use the window surface as the drawing destination.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#else
|
||||||
|
#warning All windows have to be doublebuffered
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// Do double-buffer:
|
// Do double-buffer:
|
||||||
// Create a similar surface to the window which supports alpha
|
// Create a similar surface to the window which supports alpha
|
||||||
|
@ -143,9 +154,15 @@ static CGContextRef createCGBitmapContext (int pixelsWide,
|
||||||
#warning NOTE! Doublebuffering disabled.
|
#warning NOTE! Doublebuffering disabled.
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
CGContextSaveGState(_backingCGContext);
|
||||||
|
CGContextSetRGBFillColor(_backingCGContext, (rand() % 255) / 255., (rand() % 255) / 255., (rand() % 255) / 255., 1);
|
||||||
|
CGContextFillRect(_backingCGContext, CGRectMake(-512, -512, 1024, 1024 /*pixelsWide, pixelsHigh*/ ));
|
||||||
|
CGContextRestoreGState(_backingCGContext);
|
||||||
|
#endif
|
||||||
|
NSDebugLLog(@"OpalSurface", @"Created CGContexts: X11=%p, backing=%p", _x11CGContext, _backingCGContext);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (gswindow_device_t *) device
|
- (gswindow_device_t *) device
|
||||||
|
@ -153,10 +170,19 @@ static CGContextRef createCGBitmapContext (int pixelsWide,
|
||||||
return _gsWindowDevice;
|
return _gsWindowDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGContextRef) cgContext
|
- (CGContextRef) CGContext
|
||||||
{
|
{
|
||||||
return _backingCGContext ? _backingCGContext : _x11CGContext;
|
return _backingCGContext ? _backingCGContext : _x11CGContext;
|
||||||
}
|
}
|
||||||
|
- (CGContextRef) backingCGContext
|
||||||
|
{
|
||||||
|
return _backingCGContext;
|
||||||
|
}
|
||||||
|
- (CGContextRef) x11CGContext
|
||||||
|
{
|
||||||
|
return _x11CGContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void) handleExposeRect: (NSRect)rect
|
- (void) handleExposeRect: (NSRect)rect
|
||||||
{
|
{
|
||||||
|
@ -169,12 +195,13 @@ static CGContextRef createCGBitmapContext (int pixelsWide,
|
||||||
#if 1
|
#if 1
|
||||||
CGRect cgRect = CGRectMake(rect.origin.x, rect.origin.y,
|
CGRect cgRect = CGRectMake(rect.origin.x, rect.origin.y,
|
||||||
rect.size.width, rect.size.height);
|
rect.size.width, rect.size.height);
|
||||||
|
|
||||||
|
NSDebugLLog(@"OpalSurface", @"Exposing %@", NSStringFromRect(*(NSRect *)&cgRect));
|
||||||
|
|
||||||
|
cgRect = CGRectIntegral(cgRect);
|
||||||
|
cgRect = CGRectIntersection(cgRect, CGRectMake(0, 0, CGImageGetWidth(backingImage), CGImageGetHeight(backingImage)));
|
||||||
|
|
||||||
CGRect subimageCGRect = cgRect;
|
CGRect subimageCGRect = cgRect;
|
||||||
//subimageCGRect.origin.y = CGImageGetHeight(backingImage) - cgRect.origin.y - cgRect.size.height;
|
|
||||||
|
|
||||||
// TODO: opal might be able to provide a variant of DrawImage that does
|
|
||||||
// not require creating a subimage
|
|
||||||
CGImageRef subImage = CGImageCreateWithImageInRect(backingImage, subimageCGRect);
|
CGImageRef subImage = CGImageCreateWithImageInRect(backingImage, subimageCGRect);
|
||||||
|
|
||||||
CGContextSaveGState(_x11CGContext);
|
CGContextSaveGState(_x11CGContext);
|
||||||
|
@ -182,7 +209,8 @@ static CGContextRef createCGBitmapContext (int pixelsWide,
|
||||||
OPContextSetIdentityCTM(_x11CGContext);
|
OPContextSetIdentityCTM(_x11CGContext);
|
||||||
|
|
||||||
cgRect.origin.y = [self device]->buffer_height - cgRect.origin.y - cgRect.size.height;
|
cgRect.origin.y = [self device]->buffer_height - cgRect.origin.y - cgRect.size.height;
|
||||||
NSDebugLLog(@"OpalSurface", @"Painting from %@ to %@", NSStringFromRect(*(NSRect *)&subimageCGRect), NSStringFromRect(*(NSRect *)&cgRect));
|
NSDebugLLog(@"OpalSurface", @" ... actually from %@ to %@", NSStringFromRect(*(NSRect *)&subimageCGRect), NSStringFromRect(*(NSRect *)&cgRect));
|
||||||
|
|
||||||
|
|
||||||
CGContextDrawImage(_x11CGContext, cgRect, subImage);
|
CGContextDrawImage(_x11CGContext, cgRect, subImage);
|
||||||
|
|
||||||
|
@ -200,8 +228,11 @@ static CGContextRef createCGBitmapContext (int pixelsWide,
|
||||||
CGContextDrawImage(_x11CGContext, CGRectMake(0, 0, [self device]->buffer_width, [self device]->buffer_height), backingImage);
|
CGContextDrawImage(_x11CGContext, CGRectMake(0, 0, [self device]->buffer_width, [self device]->buffer_height), backingImage);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
[self _saveImage: backingImage withPrefix:@"/tmp/opalback-backing-" size: CGSizeZero];
|
[self _saveImage: backingImage withPrefix:@"/tmp/opalback-backing-" size: CGSizeZero];
|
||||||
[self _saveImage: subImage withPrefix:@"/tmp/opalback-subimage-" size: subimageCGRect.size ];
|
[self _saveImage: subImage withPrefix:@"/tmp/opalback-subimage-" size: subimageCGRect.size ];
|
||||||
|
#endif
|
||||||
|
|
||||||
CGImageRelease(backingImage);
|
CGImageRelease(backingImage);
|
||||||
CGImageRelease(subImage);
|
CGImageRelease(subImage);
|
||||||
|
@ -212,7 +243,7 @@ static CGContextRef createCGBitmapContext (int pixelsWide,
|
||||||
|
|
||||||
- (void) _saveImage: (CGImageRef) img withPrefix: (NSString *) prefix size: (CGSize) size
|
- (void) _saveImage: (CGImageRef) img withPrefix: (NSString *) prefix size: (CGSize) size
|
||||||
{
|
{
|
||||||
#if 0
|
#if 1
|
||||||
|
|
||||||
#warning Saving debug images
|
#warning Saving debug images
|
||||||
#if 1
|
#if 1
|
||||||
|
@ -247,19 +278,10 @@ static CGContextRef createCGBitmapContext (int pixelsWide,
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dummyDraw
|
- (NSSize) size
|
||||||
{
|
{
|
||||||
|
return NSMakeSize(_gsWindowDevice->buffer_width,
|
||||||
NSDebugLLog(@"OpalSurface", @"performing dummy draw");
|
_gsWindowDevice->buffer_height);
|
||||||
|
|
||||||
CGContextSaveGState([self cgContext]);
|
|
||||||
|
|
||||||
CGRect r = CGRectMake(0, 0, 1024, 1024);
|
|
||||||
CGContextSetRGBFillColor([self cgContext], 1, 0, 0, 1);
|
|
||||||
CGContextFillRect([self cgContext], r);
|
|
||||||
|
|
||||||
CGContextRestoreGState([self cgContext]);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue