opal: Implementation of a lot of drawing and matrix methods. Work on getting backing store support to work.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@36893 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
ivucica 2013-07-15 15:24:04 +00:00
parent 333059a5d8
commit a73c2e0fc5
8 changed files with 470 additions and 60 deletions

View file

@ -1,3 +1,18 @@
2013-07-15 Ivan Vucica <ivan@vucica.net>
* Source/opal/OpalFontEnumerator.m:
* Source/opal/OpalFontInfo.m:
More dummy font code, trying to get wider menu items et al.
* Source/opal/OpalSurface.m:
* Source/opal/OpalContext.m:
* Headers/opal/OpalSurface.h:
Work on getting backing store support to work.
* Source/opal/OpalGState.m:
* Headers/opal/OpalGState.h:
Implementation of a lot of drawing and matrix methods.
2013-07-11 Ivan Vucica <ivan@vucica.net>
* Source/opal/OpalContext.m:

View file

@ -60,3 +60,7 @@
: (int)x
: (int)y;
@end
@interface OpalGState (Accessors)
- (CGContextRef) cgContext;
@end

View file

@ -31,10 +31,18 @@
@interface OpalSurface : NSObject
{
struct _gswindow_device_t * _gsWindowDevice;
CGContextRef _cgContext;
CGContextRef _backingCGContext;
CGContextRef _x11CGContext;
}
- (id) initWithDevice: (void *)device;
- (struct _gswindow_device_t *) device;
- (CGContextRef) cgContext;
@end
@interface OpalSurface (DebugExtensions)
- (void) dummyDraw;
@end

View file

@ -62,5 +62,40 @@
[surface release];
}
- (BOOL) isDrawingToScreen
{
OpalSurface *surface = nil;
[OGSTATE GSCurrentSurface: &surface : NULL : NULL];
return [surface isDrawingToScreen];
}
/**
This handles 'expose' event notifications that arrive from
X11.
*/
+ (void) handleExposeRect: (NSRect)rect forDriver: (void *)driver
{
if ([(id)driver isKindOfClass: [OpalSurface class]])
{
[(OpalSurface *)driver handleExposeRect: rect];
}
}
#if BUILD_SERVER == SERVER_x11
#ifdef XSHM
+ (void) _gotShmCompletion: (Drawable)d
{
[XWindowBuffer _gotShmCompletion: d];
}
- (void) gotShmCompletion: (Drawable)d
{
[XWindowBuffer _gotShmCompletion: d];
}
#endif // XSHM
#endif // BUILD_SERVER = SERVER_x11
@end

View file

@ -27,11 +27,88 @@
#import "opal/OpalFontEnumerator.h"
#import <Foundation/Foundation.h>
@interface OpalFaceInfo : NSObject
/* DUMMY interface */
{
NSString * _familyName;
int _weight;
unsigned int _traits;
}
- (id) initWithFamilyName: (NSString *)familyName
weight: (int)weight
traits: (unsigned int)traits;
- (unsigned int) cacheSize;
- (int) weight;
- (void) setWeight: (int)weight;
- (unsigned int) traits;
- (void) setTraits: (unsigned int)traits;
- (NSString *) familyName;
- (void) setFamilyName: (NSString *)name;
- (NSCharacterSet*)characterSet;
@end
@implementation OpalFaceInfo
/* DUMMY implementation */
- (id) initWithFamilyName: (NSString *)familyName
weight: (int)weight
traits: (unsigned int)traits
{
self = [super init];
if (!self)
return nil;
_familyName = [familyName retain];
_weight = weight;
_traits = traits;
return self;
}
- (int) weight { return _weight; }
- (void) setWeight: (int)weight { _weight = weight; }
- (unsigned int) traits { return _traits; }
- (void) setTraits: (unsigned int)traits { _traits = traits; }
- (NSString *)familyName { return _familyName; }
- (void) setFamilyName: (NSString *)name { [_familyName release]; _familyName = [name retain]; }
- (NSCharacterSet *) characterSet { return nil; }
@end
@implementation OpalFontEnumerator
+ (OpalFaceInfo *) fontWithName: (NSString *) name
{
return [[[OpalFaceInfo alloc] initWithFamilyName:name weight:1 traits:0] autorelease];
}
- (void) enumerateFontsAndFamilies
{
allFontNames = [[NSArray arrayWithObjects: @"FreeSans",
@"FreeSans-Bold", @"FreeMono", nil] retain];
allFontFamilies = [[NSDictionary dictionaryWithObjectsAndKeys:
@"FreeSans", @"FreeSans",
@"FreeMono", @"FreeMono",
nil] retain];
}
- (NSString *) defaultSystemFontName
{
return @"FreeSans";
}
- (NSString *) defaultBoldSystemFontName
{
return @"FreeSans-Bold";
}
- (NSString *) defaultFixedPitchFontName
{
return @"FreeMono";
}
@end

View file

@ -35,5 +35,13 @@
{
return [super init];
}
- (NSRect) boundingRectForGlyph: (NSGlyph)glyph
{
return NSMakeRect(0, 0, 10, 10);
}
- (CGFloat) widthOfString: (NSString *)string
{
NSLog(@"WIDTH OF %@", string);
return [string length] * 10;
}
@end

View file

@ -31,6 +31,8 @@
#import "opal/OpalSurface.h"
#import "x11/XGServerWindow.h"
#define CGCTX [self cgContext]
@implementation OpalGState
// MARK: Minimum required methods
@ -38,20 +40,23 @@
- (void) DPSinitclip
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
OPContextResetClip(CGCTX);
}
- (void) DPSclip
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
CGContextClip(CGCTX);
}
- (void) DPSfill
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
[_opalSurface dummyDraw];
//CGContextFillPath(CGCTX);
}
- (void) DPSimage: (NSAffineTransform *)matrix
@ -76,15 +81,33 @@
op: (NSCompositingOperation)op
fraction: (CGFloat)delta
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
- (void) compositerect: (NSRect)aRect
op: (NSCompositingOperation)op
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
CGContextSaveGState(CGCTX);
CGContextFillRect(CGCTX, CGRectMake(aRect.origin.x, aRect.origin.y,
aRect.size.width, aRect.size.height));
CGContextRestoreGState(CGCTX);
}
- (void) DPSsetdash: (const CGFloat*)pat
: (NSInteger)size
: (CGFloat)offset
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
// TODO: stub
}
- (void) DPSstroke
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
CGContextStrokePath(CGCTX);
}
@end
@ -126,11 +149,15 @@
_opalSurface = [opalSurface retain];
// TODO: apply offset using [self setOffset:]
[_opalSurface dummyDraw];
}
- (id) GSCurrentSurface: (OpalSurface **)surface
: (int *)x
: (int *)y
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
return _opalSurface;
}
/**
Sets up a new CG*Context() for drawing content.
@ -148,6 +175,124 @@
@end
// MARK: Accessors
// MARK: -
@implementation OpalGState (Accessors)
- (CGContextRef) cgContext
{
return [_opalSurface cgContext];
}
@end
// MARK: Non-required methods
// MARK: -
static CGFloat theAlpha = 1.; // TODO: removeme
@implementation OpalGState (NonrequiredMethods)
- (void) DPSsetrgbcolor: (CGFloat)r : (CGFloat)g : (CGFloat)b
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
const CGFloat alpha = 1; // TODO: is this correct?
CGContextSetRGBFillColor(CGCTX, r, g, b, alpha);
}
- (void) DPSrectfill: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h
{
NSLog(@"%p (%@): %s - rect %g %g %g %g", self, [self class], __PRETTY_FUNCTION__, x, y, w, h);
if (theAlpha == 0)
return;
CGContextFillRect(CGCTX, CGRectMake(x, y, w, h));
}
- (void) DPSrectclip: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
CGContextClipToRect(CGCTX, CGRectMake(x, y, w, h));
}
- (void) DPSsetgray: (CGFloat)gray
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
const CGFloat alpha = 1; // TODO: is this correct?
CGContextSetGrayFillColor(CGCTX, gray, alpha);
}
- (void) DPSsetalpha: (CGFloat)a
{
NSLog(@"%p (%@): %s - alpha %g", self, [self class], __PRETTY_FUNCTION__, a);
CGContextSetAlpha(CGCTX, a);
theAlpha = a;
}
- (void)DPSinitmatrix
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
OPContextSetIdentityCTM(CGCTX);
}
- (void)DPSconcat: (const CGFloat *)m
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
CGContextConcatCTM(CGCTX, CGAffineTransformMake(
m[0], m[1], m[2],
m[3], m[4], m[5]));
}
- (void)DPSscale: (CGFloat)x
: (CGFloat)y
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
CGContextScaleCTM(CGCTX, x, y);
}
- (void)DPStranslate: (CGFloat)x
: (CGFloat)y
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
CGContextTranslateCTM(CGCTX, x, y);
}
- (void) DPSmoveto: (CGFloat) x
: (CGFloat) y
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
CGContextMoveToPoint(CGCTX, x, y);
}
- (void) DPSlineto: (CGFloat) x
: (CGFloat) y
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
CGContextAddLineToPoint(CGCTX, x, y);
}
/*
- (void) setColor: (device_color_t *)color state: (color_state_t)cState
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
[super setColor: color
state: cState];
switch (color->space)
{
case rgb_colorspace:
if (cState & COLOR_STROKE)
CGContextSetRGBStrokeColor(CGCTX, color->field[0],
color->field[1], color->field[2], color->field[3]);
if (cState & COLOR_FILL)
CGContextSetRGBFillColor(CGCTX, color->field[0],
color->field[1], color->field[2], color->field[3]);
break;
}
}
*/
@end
// MARK: Non-required unimplemented methods
// MARK: -
@ -167,43 +312,6 @@
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
- (void) setColor: (device_color_t *)color state: (color_state_t)cState
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
- (void)DPSinitmatrix
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
- (void)DPSconcat: (const CGFloat *)m
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
- (void) DPSsetalpha: (CGFloat)a
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
- (void) DPSrectfill: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
[_opalSurface dummyDraw];
}
- (void) DPSrectclip: (CGFloat)x : (CGFloat)y : (CGFloat)w : (CGFloat)h
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
- (void) DPSsetrgbcolor: (CGFloat)r : (CGFloat)g : (CGFloat)b
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
- (void) GSSetCTM: (NSAffineTransform *)newctm
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
- (void) DPSsetgray: (CGFloat)gray
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
/*
- (NSAffineTransform *) GSCurrentCTM
{
@ -211,13 +319,50 @@
return nil;
}
*/
- (void)DPSscale: (CGFloat)x : (CGFloat)y
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
- (void)DPStranslate: (CGFloat)x : (CGFloat)y
{
NSLog(@"%p (%@): %s", self, [self class], __PRETTY_FUNCTION__);
}
@end
@implementation OpalGState (Unused)
- (void) _setPath
{
#if 0
NSInteger count = [path elementCount];
NSInteger i;
SEL elmsel = @selector(elementAtIndex:associatedPoints:);
NSBezierPathElement (*elmidx)(id, SEL, NSInteger, NSPoint*) =
(NSBezierPathElement (*)(id, SEL, NSInteger, NSPoint*))[path methodForSelector: elmsel];
// reset current cairo path
cairo_new_path(_ct);
for (i = 0; i < count; i++)
{
NSBezierPathElement type;
NSPoint points[3];
type = (NSBezierPathElement)(*elmidx)(path, elmsel, i, points);
switch(type)
{
case NSMoveToBezierPathElement:
cairo_move_to(_ct, points[0].x, points[0].y);
break;
case NSLineToBezierPathElement:
cairo_line_to(_ct, points[0].x, points[0].y);
break;
case NSCurveToBezierPathElement:
cairo_curve_to(_ct, points[0].x, points[0].y,
points[1].x, points[1].y,
points[2].x, points[2].y);
break;
case NSClosePathBezierPathElement:
cairo_close_path(_ct);
break;
default:
break;
}
}
#endif
}
@end

View file

@ -32,6 +32,66 @@
extern CGContextRef OPX11ContextCreate(Display *display, Drawable drawable);
extern void OPContextSetSize(CGContextRef ctx, CGSize s);
/* Taken from GSQuartzCore's CABackingStore */
static CGContextRef createCGBitmapContext (int pixelsWide,
int pixelsHigh)
{
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
void * bitmapData;
int bitmapByteCount;
int bitmapBytesPerRow;
bitmapBytesPerRow = (pixelsWide * 4);
bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);// 2
// Let CGBitmapContextCreate() allocate the memory.
// This should be good under Cocoa too.
bitmapData = NULL;
context = CGBitmapContextCreate (bitmapData,
pixelsWide,
pixelsHigh,
8, // bits per component
bitmapBytesPerRow,
colorSpace,
#if !GNUSTEP
kCGImageAlphaPremultipliedLast);
#else
// Opal only supports kCGImageAlphaPremultipliedFirst.
// However, this is incorrect since it implies ARGB.
kCGImageAlphaPremultipliedFirst);
#endif
// Note: our use of premultiplied alpha means that we need to
// do alpha blending using:
// GL_SRC_ALPHA, GL_ONE
CGColorSpaceRelease(colorSpace);
if (context== NULL)
{
free (bitmapData);// 5
fprintf (stderr, "Context not created!");
return NULL;
}
#if GNUSTEP
#warning Opal bug: context should be cleared automatically
#if 0
CGContextClearRect (context, CGRectInfinite);
#else
#warning Opal bug: CGContextClearRect() permanently whacks the context
memset (CGBitmapContextGetData (context),
0, bitmapBytesPerRow * pixelsHigh);
#endif
#endif
return context;
}
@implementation OpalSurface
- (id) initWithDevice: (void *)device
@ -46,8 +106,31 @@ extern void OPContextSetSize(CGContextRef ctx, CGSize s);
Display * display = _gsWindowDevice->display;
Window window = _gsWindowDevice->ident;
_x11CGContext = OPX11ContextCreate(display, window);
if (_gsWindowDevice->type == NSBackingStoreNonretained)
{
// Don't double-buffer:
// use the window surface as the drawing destination.
}
else
{
// Do double-buffer:
// Create a similar surface to the window which supports alpha
_cgContext = OPX11ContextCreate(display, window);
// Ask XGServerWindow to call +[OpalContext handleExposeRect:forDriver:]
// to let us handle the back buffer -> front buffer copy using Opal.
_gsWindowDevice->gdriverProtocol |= GDriverHandlesExpose | GDriverHandlesBacking;
_gsWindowDevice->gdriver = self;
#if 0
// Disabled because when the content is blitted onto the screen,
// we get just yellow blots instead of actual content.
_backingCGContext = createCGBitmapContext(
_gsWindowDevice->buffer_width,
_gsWindowDevice->buffer_height);
#endif
}
return self;
}
@ -57,18 +140,53 @@ extern void OPContextSetSize(CGContextRef ctx, CGSize s);
return _gsWindowDevice;
}
- (CGContextRef) cgContext
{
return _backingCGContext ? _backingCGContext : _x11CGContext;
}
- (void) handleExposeRect: (NSRect)rect
{
CGRect cgRect = CGRectMake(rect.origin.x, rect.origin.y,
rect.size.width, rect.size.height);
CGImageRef backingImage = CGBitmapContextCreateImage(_backingCGContext);
if (!backingImage) // FIXME: writing a nil image fails with Opal
return;
CGContextDrawImage(_x11CGContext, cgRect, backingImage);
// FIXME: Opal tries to access -path from CFURLRef
//CFURLRef fileUrl = CFURLCreateWithFileSystemPath(NULL, @"/tmp/opalback.jpg", kCFURLPOSIXPathStyle, NO);
CFURLRef fileUrl = (CFURLRef)[[NSURL fileURLWithPath: @"/tmp/opalback.jpg"] retain];
CGImageDestinationRef outfile = CGImageDestinationCreateWithURL(fileUrl, @"public.jpeg"/*kUTTypeJPEG*/, 1, NULL);
CGImageDestinationAddImage(outfile, backingImage, NULL);
CGImageDestinationFinalize(outfile);
CFRelease(fileUrl);
CFRelease(outfile);
CGImageRelease(backingImage);
}
- (BOOL) isDrawingToScreen
{
// TODO: stub
return YES;
}
- (void) dummyDraw
{
NSLog(@"performing dummy draw");
CGContextSaveGState(_cgContext);
CGContextSaveGState([self cgContext]);
CGRect r = CGRectMake(0, 0, 1024, 1024);
CGContextSetRGBFillColor(_cgContext, 1, 0, 0, 1);
CGContextFillRect(_cgContext, r);
CGContextSetRGBFillColor([self cgContext], 1, 0, 0, 1);
CGContextFillRect([self cgContext], r);
CGContextRestoreGState(_cgContext);
CGContextRestoreGState([self cgContext]);
}