From da3f639ef2cb28731a3bc24e8f3db6d3572142fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20A=2E=20A=CC=81lvarez?= Date: Fri, 1 Mar 2024 23:31:06 +0100 Subject: [PATCH] prefer pixel-perfect scaling when filter is set to nearest --- Mini vMac/ScreenView.m | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Mini vMac/ScreenView.m b/Mini vMac/ScreenView.m index 97eee3c..926f265 100644 --- a/Mini vMac/ScreenView.m +++ b/Mini vMac/ScreenView.m @@ -29,7 +29,7 @@ static ScreenView *sharedScreenView = nil; [self updateVideoLayer]; [self.layer addSublayer:videoLayer]; [[AppDelegate sharedInstance] addObserver:self forKeyPath:@"sharedEmulator" options:NSKeyValueObservingOptionNew context:NULL]; - [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"screenFilter" options:NSKeyValueObservingOptionNew context:NULL]; + [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"screenFilter" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL]; } + (instancetype)sharedScreenView { @@ -57,17 +57,25 @@ static ScreenView *sharedScreenView = nil; - (void)layoutSubviews { [super layoutSubviews]; CGRect viewBounds = self.bounds; - CGFloat screenScale = MAX(screenSize.width / viewBounds.size.width, screenSize.height / viewBounds.size.height); - if (screenScale > 0.9 && screenScale <= 1.0) { + CGFloat screenScale = MIN(viewBounds.size.width / screenSize.width, viewBounds.size.height / screenSize.height); + NSString *screenFilter = [[NSUserDefaults standardUserDefaults] stringForKey:@"screenFilter"]; + if ([screenFilter isEqualToString:kCAFilterNearest] && screenScale > 1.0) { + screenScale = floor(screenScale); + } else if (screenScale > 1.0 && screenScale <= 1.1) { screenScale = 1.0; } - screenBounds = CGRectMake(0, 0, screenSize.width / screenScale, screenSize.height / screenScale); + screenBounds = CGRectMake(0, 0, screenSize.width * screenScale, screenSize.height * screenScale); screenBounds.origin.x = (viewBounds.size.width - screenBounds.size.width)/2; screenBounds = CGRectIntegral(screenBounds); + + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && (viewBounds.size.height - screenBounds.size.height) >= 30.0) { + // move under multitasking indicator on iPad + screenBounds.origin.y += 30; + } videoLayer.frame = screenBounds; - screenBounds.origin.y = self.frame.origin.y; + screenBounds.origin.y += self.frame.origin.y; BOOL scaleIsIntegral = (floor(screenScale) == screenScale); - NSString *screenFilter = scaleIsIntegral ? kCAFilterNearest : [[NSUserDefaults standardUserDefaults] stringForKey:@"screenFilter"]; + if (scaleIsIntegral) screenFilter = kCAFilterNearest; videoLayer.magnificationFilter = screenFilter; videoLayer.minificationFilter = screenFilter; } @@ -75,13 +83,19 @@ static ScreenView *sharedScreenView = nil; - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([object isEqual:[NSUserDefaults standardUserDefaults]]) { if ([keyPath isEqualToString:@"screenFilter"]) { + NSString *oldValue = change[NSKeyValueChangeOldKey]; NSString *value = change[NSKeyValueChangeNewKey]; videoLayer.magnificationFilter = value; videoLayer.minificationFilter = value; + if ([value isEqualToString:kCAFilterNearest] || [oldValue isEqualToString:kCAFilterNearest]) { + [self setNeedsLayout]; + [self layoutIfNeeded]; + } } } else if (object == [AppDelegate sharedInstance] && [keyPath isEqualToString:@"sharedEmulator"]) { [self updateVideoLayer]; - [self layoutSubviews]; + [self setNeedsLayout]; + [self layoutIfNeeded]; } }