Make GBImageView not slow

This commit is contained in:
Lior Halphon 2022-02-19 22:13:07 +02:00
parent 4c6bc91ded
commit 3c6a46830d
2 changed files with 60 additions and 42 deletions

View File

@ -1389,28 +1389,21 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
+ (NSImage *) imageFromData:(NSData *)data width:(NSUInteger) width height:(NSUInteger) height scale:(double) scale + (NSImage *) imageFromData:(NSData *)data width:(NSUInteger) width height:(NSUInteger) height scale:(double) scale
{ {
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef) data);
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaNoneSkipLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef iref = CGImageCreate(width,
height,
8,
32,
4 * width,
colorSpaceRef,
bitmapInfo,
provider,
NULL,
true,
renderingIntent);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpaceRef);
NSImage *ret = [[NSImage alloc] initWithCGImage:iref size:NSMakeSize(width * scale, height * scale)];
CGImageRelease(iref);
NSImage *ret = [[NSImage alloc] initWithSize:NSMakeSize(width * scale, height * scale)];
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:width
pixelsHigh:height
bitsPerSample:8
samplesPerPixel:3
hasAlpha:false
isPlanar:false
colorSpaceName:NSDeviceRGBColorSpace
bitmapFormat:0
bytesPerRow:4 * width
bitsPerPixel:32];
memcpy(rep.bitmapData, data.bytes, data.length);
[ret addRepresentation:rep];
return ret; return ret;
} }

View File

@ -10,18 +10,18 @@
} }
@end @end
@implementation GBImageView @interface GBGridView : NSView
{ @end
NSTrackingArea *trackingArea;
} @implementation GBGridView
- (void)drawRect:(NSRect)dirtyRect - (void)drawRect:(NSRect)dirtyRect
{ {
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; GBImageView *parent = (GBImageView *)self.superview;
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
[super drawRect:dirtyRect]; CGFloat y_ratio = parent.frame.size.height / parent.image.size.height;
CGFloat y_ratio = self.frame.size.height / self.image.size.height; CGFloat x_ratio = parent.frame.size.width / parent.image.size.width;
CGFloat x_ratio = self.frame.size.width / self.image.size.width; for (GBImageViewGridConfiguration *conf in parent.verticalGrids) {
for (GBImageViewGridConfiguration *conf in self.verticalGrids) {
[conf.color set]; [conf.color set];
for (CGFloat y = conf.size * y_ratio; y < self.frame.size.height; y += conf.size * y_ratio) { for (CGFloat y = conf.size * y_ratio; y < self.frame.size.height; y += conf.size * y_ratio) {
NSBezierPath *line = [NSBezierPath bezierPath]; NSBezierPath *line = [NSBezierPath bezierPath];
@ -32,7 +32,7 @@
} }
} }
for (GBImageViewGridConfiguration *conf in self.horizontalGrids) { for (GBImageViewGridConfiguration *conf in parent.horizontalGrids) {
[conf.color set]; [conf.color set];
for (CGFloat x = conf.size * x_ratio; x < self.frame.size.width; x += conf.size * x_ratio) { for (CGFloat x = conf.size * x_ratio; x < self.frame.size.width; x += conf.size * x_ratio) {
NSBezierPath *line = [NSBezierPath bezierPath]; NSBezierPath *line = [NSBezierPath bezierPath];
@ -43,11 +43,11 @@
} }
} }
if (self.displayScrollRect) { if (parent.displayScrollRect) {
NSBezierPath *path = [NSBezierPath bezierPathWithRect:CGRectInfinite]; NSBezierPath *path = [NSBezierPath bezierPathWithRect:CGRectInfinite];
for (unsigned x = 0; x < 2; x++) { for (unsigned x = 0; x < 2; x++) {
for (unsigned y = 0; y < 2; y++) { for (unsigned y = 0; y < 2; y++) {
NSRect rect = self.scrollRect; NSRect rect = parent.scrollRect;
rect.origin.x *= x_ratio; rect.origin.x *= x_ratio;
rect.origin.y *= y_ratio; rect.origin.y *= y_ratio;
rect.size.width *= x_ratio; rect.size.width *= x_ratio;
@ -56,7 +56,7 @@
rect.origin.x -= self.frame.size.width * x; rect.origin.x -= self.frame.size.width * x;
rect.origin.y += self.frame.size.height * y; rect.origin.y += self.frame.size.height * y;
NSBezierPath *subpath = [NSBezierPath bezierPathWithRect:rect]; NSBezierPath *subpath = [NSBezierPath bezierPathWithRect:rect];
[path appendBezierPath:subpath]; [path appendBezierPath:subpath];
@ -72,36 +72,61 @@
[path stroke]; [path stroke];
} }
} }
@end
@implementation GBImageView
{
NSTrackingArea *_trackingArea;
GBGridView *_gridView;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
self.wantsLayer = true;
_gridView = [[GBGridView alloc] initWithFrame:self.bounds];
_gridView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[self addSubview:_gridView];
return self;
}
- (void)setImage:(NSImage *)image
{
[super setImage:image];
for (CALayer *layer in self.layer.sublayers) {
layer.magnificationFilter = kCAFilterNearest;
}
}
- (void)setHorizontalGrids:(NSArray *)horizontalGrids - (void)setHorizontalGrids:(NSArray *)horizontalGrids
{ {
self->_horizontalGrids = horizontalGrids; self->_horizontalGrids = horizontalGrids;
[self setNeedsDisplay]; [_gridView setNeedsDisplay:true];
} }
- (void)setVerticalGrids:(NSArray *)verticalGrids - (void)setVerticalGrids:(NSArray *)verticalGrids
{ {
self->_verticalGrids = verticalGrids; self->_verticalGrids = verticalGrids;
[self setNeedsDisplay]; [_gridView setNeedsDisplay:true];
} }
- (void)setDisplayScrollRect:(bool)displayScrollRect - (void)setDisplayScrollRect:(bool)displayScrollRect
{ {
self->_displayScrollRect = displayScrollRect; self->_displayScrollRect = displayScrollRect;
[self setNeedsDisplay]; [_gridView setNeedsDisplay:true];
} }
- (void)updateTrackingAreas - (void)updateTrackingAreas
{ {
if (trackingArea != nil) { if (_trackingArea != nil) {
[self removeTrackingArea:trackingArea]; [self removeTrackingArea:_trackingArea];
} }
trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds] _trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds]
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingMouseMoved options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingMouseMoved
owner:self owner:self
userInfo:nil]; userInfo:nil];
[self addTrackingArea:trackingArea]; [self addTrackingArea:_trackingArea];
} }
- (void)mouseExited:(NSEvent *)theEvent - (void)mouseExited:(NSEvent *)theEvent