diff --git a/Cocoa/Document.xib b/Cocoa/Document.xib index 49b14d6..1f78d4a 100644 --- a/Cocoa/Document.xib +++ b/Cocoa/Document.xib @@ -323,19 +323,19 @@ - - + + - + - - + + - + diff --git a/Cocoa/GBCPUView.m b/Cocoa/GBCPUView.m index f927fc9..0b87fde 100644 --- a/Cocoa/GBCPUView.m +++ b/Cocoa/GBCPUView.m @@ -10,41 +10,108 @@ - (void)drawRect:(NSRect)dirtyRect { - NSSize size = self.bounds.size; + CGRect bounds = self.bounds; + NSSize size = bounds.size; + unsigned factor = [[self.window screen] backingScaleFactor]; - NSBezierPath *line = [NSBezierPath bezierPath]; - { - double sample = _samples[_position % SAMPLE_COUNT]; - [line moveToPoint:NSMakePoint(size.width * 0.5 / SAMPLE_COUNT, - sample * size.height)]; - } + NSBitmapImageRep *maskBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:(unsigned)size.width * factor + pixelsHigh:(unsigned)size.height * factor + bitsPerSample:8 + samplesPerPixel:2 + hasAlpha:true + isPlanar:false + colorSpaceName:NSDeviceWhiteColorSpace + bytesPerRow:size.width * 2 * factor + bitsPerPixel:16]; - for (unsigned i = 1; i < SAMPLE_COUNT; i++) { - double sample = _samples[(i + _position) % SAMPLE_COUNT]; - [line lineToPoint:NSMakePoint(size.width * (i + 0.5) / SAMPLE_COUNT, - sample * size.height)]; - } + - NSBezierPath *fill = [line copy]; - [fill lineToPoint:NSMakePoint(size.width + 0.5, 0)]; - [fill lineToPoint:NSMakePoint(0.5, 0)]; + NSGraphicsContext *mainContext = [NSGraphicsContext currentContext]; - NSColor *strokeColor; + + NSColor *greenColor, *redColor; if (@available(macOS 10.10, *)) { - strokeColor = [NSColor systemGreenColor]; + greenColor = [NSColor systemGreenColor]; + redColor = [NSColor systemRedColor]; } else { - strokeColor = [NSColor colorWithRed:3.0 / 16 green:0.5 blue:5.0 / 16 alpha:1.0]; + greenColor = [NSColor colorWithRed:3.0 / 16 green:0.5 blue:5.0 / 16 alpha:1.0]; + redColor = [NSColor colorWithRed:13.0 / 16 green:0.25 blue:0.25 alpha:1.0]; } + + + NSBitmapImageRep *colorBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:SAMPLE_COUNT + pixelsHigh:1 + bitsPerSample:8 + samplesPerPixel:3 + hasAlpha:false + isPlanar:false + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:SAMPLE_COUNT * 4 + bitsPerPixel:32]; + + unsigned lastFill = 0; + NSBezierPath *line = [NSBezierPath bezierPath]; + bool isRed = false; + { + double sample = _samples[_position % SAMPLE_COUNT]; + [line moveToPoint:NSMakePoint(0, + (sample * (size.height - 1) + 0.5) * factor)]; + isRed = sample == 1; + } + + + [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:colorBitmap]]; + for (unsigned i = 1; i < SAMPLE_COUNT; i++) { + double sample = _samples[(i + _position) % SAMPLE_COUNT]; + [line lineToPoint:NSMakePoint(size.width * i * factor / (SAMPLE_COUNT - 1), + (sample * (size.height - 1) + 0.5) * factor)]; + + if (isRed != (sample == 1)) { + // Color changed + [(isRed? redColor : greenColor) setFill]; + NSRectFill(CGRectMake(lastFill, 0, i - lastFill, 1)); + lastFill = i; + + isRed ^= true; + } + } + [(isRed? redColor : greenColor) setFill]; + NSRectFill(CGRectMake(lastFill, 0, SAMPLE_COUNT - lastFill, 1)); + + NSBezierPath *fill = [line copy]; + [fill lineToPoint:NSMakePoint(size.width * factor, 0)]; + [fill lineToPoint:NSMakePoint(0, 0)]; + + NSColor *strokeColor = [NSColor whiteColor]; NSColor *fillColor = [strokeColor colorWithAlphaComponent:1 / 3.0]; + [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:maskBitmap]]; [fillColor setFill]; [fill fill]; - [strokeColor setStroke]; + [line setLineWidth:factor]; [line stroke]; - + + CGContextRef maskContext = CGContextRetain([NSGraphicsContext currentContext].graphicsPort); + [NSGraphicsContext setCurrentContext:mainContext]; + CGContextSaveGState(mainContext.graphicsPort); + + CGImageRef maskImage = CGBitmapContextCreateImage(maskContext); + CGContextClipToMask(mainContext.graphicsPort, bounds, maskImage); + CGImageRelease(maskImage); + + NSImage *colors = [[NSImage alloc] initWithSize:NSMakeSize(SAMPLE_COUNT, 1)]; + [colors addRepresentation:colorBitmap]; + [colors drawInRect:bounds]; + + CGContextRestoreGState(mainContext.graphicsPort); + CGContextRelease(maskContext); + + [super drawRect:dirtyRect]; }