diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 1f30104218e3..236cf96f027a 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.8.1+5 + +* Make sure the `setFocusPoint` and `setExposurePoint` coordinates work correctly in all orientations on iOS (instead of only in portrait mode). + ## 0.8.1+4 * Silenced warnings that may occur during build when using a very diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraExposureTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraExposureTests.m new file mode 100644 index 000000000000..ee43d3f155f4 --- /dev/null +++ b/packages/camera/camera/example/ios/RunnerTests/CameraExposureTests.m @@ -0,0 +1,55 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +@import camera; +@import XCTest; +@import AVFoundation; +#import + +@interface FLTCam : NSObject + +- (void)setExposurePointWithResult:(FlutterResult)result x:(double)x y:(double)y; +@end + +@interface CameraExposureTests : XCTestCase +@property(readonly, nonatomic) FLTCam *camera; +@property(readonly, nonatomic) id mockDevice; +@property(readonly, nonatomic) id mockUIDevice; +@end + +@implementation CameraExposureTests + +- (void)setUp { + _camera = [[FLTCam alloc] init]; + _mockDevice = OCMClassMock([AVCaptureDevice class]); + _mockUIDevice = OCMPartialMock([UIDevice currentDevice]); +} + +- (void)tearDown { + [_mockDevice stopMocking]; + [_mockUIDevice stopMocking]; +} + +- (void)testSetExpsourePointWithResult_SetsExposurePointOfInterest { + // UI is currently in landscape left orientation + OCMStub([(UIDevice *)_mockUIDevice orientation]).andReturn(UIDeviceOrientationLandscapeLeft); + // Exposure point of interest is supported + OCMStub([_mockDevice isExposurePointOfInterestSupported]).andReturn(true); + // Set mock device as the current capture device + [_camera setValue:_mockDevice forKey:@"captureDevice"]; + + // Run test + [_camera + setExposurePointWithResult:^void(id _Nullable result) { + } + x:1 + y:1]; + + // Verify the focus point of interest has been set + OCMVerify([_mockDevice setExposurePointOfInterest:CGPointMake(1, 1)]); +} + +@end diff --git a/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m b/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m index 5d93bdf70332..27537e7ebdac 100644 --- a/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m +++ b/packages/camera/camera/example/ios/RunnerTests/CameraFocusTests.m @@ -19,12 +19,13 @@ @interface FLTCam : NSObject + +@interface FLTCam : NSObject + +- (CGPoint)getCGPointForCoordsWithOrientation:(UIDeviceOrientation)orientation + x:(double)x + y:(double)y; + +@end + +@interface CameraUtilTests : XCTestCase +@property(readonly, nonatomic) FLTCam *camera; + +@end + +@implementation CameraUtilTests + +- (void)setUp { + _camera = [[FLTCam alloc] init]; +} + +- (void)testGetCGPointForCoordsWithOrientation_ShouldRotateCoords { + CGPoint point; + point = [_camera getCGPointForCoordsWithOrientation:UIDeviceOrientationLandscapeLeft x:1 y:1]; + XCTAssertTrue(CGPointEqualToPoint(point, CGPointMake(1, 1)), + @"Resulting coordinates are invalid."); + point = [_camera getCGPointForCoordsWithOrientation:UIDeviceOrientationPortrait x:0 y:1]; + XCTAssertTrue(CGPointEqualToPoint(point, CGPointMake(1, 1)), + @"Resulting coordinates are invalid."); + point = [_camera getCGPointForCoordsWithOrientation:UIDeviceOrientationLandscapeRight x:0 y:0]; + XCTAssertTrue(CGPointEqualToPoint(point, CGPointMake(1, 1)), + @"Resulting coordinates are invalid."); + point = [_camera getCGPointForCoordsWithOrientation:UIDeviceOrientationPortraitUpsideDown + x:1 + y:0]; + XCTAssertTrue(CGPointEqualToPoint(point, CGPointMake(1, 1)), + @"Resulting coordinates are invalid."); +} + +@end diff --git a/packages/camera/camera/ios/Classes/CameraPlugin.m b/packages/camera/camera/ios/Classes/CameraPlugin.m index ebd5366ba78d..d88eb45945fe 100644 --- a/packages/camera/camera/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera/ios/Classes/CameraPlugin.m @@ -1030,6 +1030,31 @@ - (void)applyFocusMode:(FocusMode)focusMode onDevice:(AVCaptureDevice *)captureD [captureDevice unlockForConfiguration]; } +- (CGPoint)getCGPointForCoordsWithOrientation:(UIDeviceOrientation)orientation + x:(double)x + y:(double)y { + double oldX = x, oldY = y; + switch (orientation) { + case UIDeviceOrientationPortrait: // 90 ccw + y = 1 - oldX; + x = oldY; + break; + case UIDeviceOrientationPortraitUpsideDown: // 90 cw + x = 1 - oldY; + y = oldX; + break; + case UIDeviceOrientationLandscapeRight: // 180 + x = 1 - x; + y = 1 - y; + break; + case UIDeviceOrientationLandscapeLeft: + default: + // No rotation required + break; + } + return CGPointMake(x, y); +} + - (void)setExposurePointWithResult:(FlutterResult)result x:(double)x y:(double)y { if (!_captureDevice.isExposurePointOfInterestSupported) { result([FlutterError errorWithCode:@"setExposurePointFailed" @@ -1037,8 +1062,11 @@ - (void)setExposurePointWithResult:(FlutterResult)result x:(double)x y:(double)y details:nil]); return; } + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; [_captureDevice lockForConfiguration:nil]; - [_captureDevice setExposurePointOfInterest:CGPointMake(y, 1 - x)]; + [_captureDevice setExposurePointOfInterest:[self getCGPointForCoordsWithOrientation:orientation + x:x + y:y]]; [_captureDevice unlockForConfiguration]; // Retrigger auto exposure [self applyExposureMode]; @@ -1052,11 +1080,16 @@ - (void)setFocusPointWithResult:(FlutterResult)result x:(double)x y:(double)y { details:nil]); return; } + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; [_captureDevice lockForConfiguration:nil]; - [_captureDevice setFocusPointOfInterest:CGPointMake(y, 1 - x)]; + + [_captureDevice setFocusPointOfInterest:[self getCGPointForCoordsWithOrientation:orientation + x:x + y:y]]; [_captureDevice unlockForConfiguration]; // Retrigger auto focus [self applyFocusMode]; + result(nil); } diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 789910e2c79b..78eb49a999a2 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flutter plugin for getting information about and controlling the and streaming image buffers to dart. repository: https://github.com/flutter/plugins/tree/master/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.8.1+4 +version: 0.8.1+5 environment: sdk: ">=2.12.0 <3.0.0"