// // RSKImageCropViewController.h // // Copyright (c) 2014-present Ruslan Skorb, http://ruslanskorb.com/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #import NS_ASSUME_NONNULL_BEGIN @protocol RSKImageCropViewControllerDataSource; @protocol RSKImageCropViewControllerDelegate; /** Types of supported crop modes. */ typedef NS_ENUM(NSUInteger, RSKImageCropMode) { RSKImageCropModeCircle, RSKImageCropModeSquare, RSKImageCropModeCustom }; @interface RSKImageCropViewController : UIViewController /** Designated initializer. Initializes and returns a newly allocated view controller object with the specified image. @param originalImage The image for cropping. */ - (instancetype)initWithImage:(UIImage *)originalImage; /** Initializes and returns a newly allocated view controller object with the specified image and the specified crop mode. @param originalImage The image for cropping. @param cropMode The mode for cropping. */ - (instancetype)initWithImage:(UIImage *)originalImage cropMode:(RSKImageCropMode)cropMode; /** Zooms to a specific area of the image so that it is visible. @param rect A rectangle defining an area of the image. @param animated YES if the scrolling should be animated, NO if it should be immediate. */ - (void)zoomToRect:(CGRect)rect animated:(BOOL)animated; ///----------------------------- /// @name Accessing the Delegate ///----------------------------- /** The receiver's delegate. @discussion A `RSKImageCropViewControllerDelegate` delegate responds to messages sent by completing / canceling crop the image in the image crop view controller. */ @property (weak, nonatomic, nullable) id delegate; /** The receiver's data source. @discussion A `RSKImageCropViewControllerDataSource` data source provides a custom rect and a custom path for the mask and a custom movement rect for the image. */ @property (weak, nonatomic, nullable) id dataSource; ///-------------------------- /// @name Accessing the Image ///-------------------------- /** The image for cropping. */ @property (strong, nonatomic) UIImage *originalImage; /// ----------------------------------- /// @name Accessing the Mask Attributes /// ----------------------------------- /** The color of the layer with the mask. Default value is [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.7f]. */ @property (copy, nonatomic) UIColor *maskLayerColor; /** The line width used when stroking the path of the mask layer. Default value is 1.0. */ @property (assign, nonatomic) CGFloat maskLayerLineWidth; /** The color to fill the stroked outline of the path of the mask layer, or nil for no stroking. Default valus is nil. */ @property (copy, nonatomic, nullable) UIColor *maskLayerStrokeColor; /** The rect of the mask. @discussion Updating each time before the crop view lays out its subviews. */ @property (assign, readonly, nonatomic) CGRect maskRect; /** The path of the mask. @discussion Updating each time before the crop view lays out its subviews. */ @property (copy, readonly, nonatomic) UIBezierPath *maskPath; /// ----------------------------------- /// @name Accessing the Crop Attributes /// ----------------------------------- /** The mode for cropping. Default value is `RSKImageCropModeCircle`. */ @property (assign, nonatomic) RSKImageCropMode cropMode; /** The crop rectangle. @discussion The value is calculated at run time. */ @property (readonly, nonatomic) CGRect cropRect; /** A value that specifies the current rotation angle of the image in radians. @discussion The value is calculated at run time. */ @property (readonly, nonatomic) CGFloat rotationAngle; /** A floating-point value that specifies the current scale factor applied to the image. @discussion The value is calculated at run time. */ @property (readonly, nonatomic) CGFloat zoomScale; /** A Boolean value that determines whether the image will always fill the mask space. Default value is `NO`. */ @property (assign, nonatomic) BOOL avoidEmptySpaceAroundImage; /** A Boolean value that determines whether the image will always bounce horizontally. Default value is `NO`. */ @property (assign, nonatomic) BOOL alwaysBounceHorizontal; /** A Boolean value that determines whether the image will always bounce vertically. Default value is `NO`. */ @property (assign, nonatomic) BOOL alwaysBounceVertical; /** A Boolean value that determines whether the mask applies to the image after cropping. Default value is `NO`. */ @property (assign, nonatomic) BOOL applyMaskToCroppedImage; /** A Boolean value that controls whether the rotaion gesture is enabled. Default value is `NO`. @discussion To support the rotation when `cropMode` is `RSKImageCropModeCustom` you must implement the data source method `imageCropViewControllerCustomMovementRect:`. */ @property (assign, getter=isRotationEnabled, nonatomic) BOOL rotationEnabled; /// ------------------------------- /// @name Accessing the UI Elements /// ------------------------------- /** The Title Label. */ @property (strong, nonatomic, readonly) UILabel *moveAndScaleLabel; /** The Cancel Button. */ @property (strong, nonatomic, readonly) UIButton *cancelButton; /** The Choose Button. */ @property (strong, nonatomic, readonly) UIButton *chooseButton; /// ------------------------------------------- /// @name Checking of the Interface Orientation /// ------------------------------------------- /** Returns a Boolean value indicating whether the user interface is currently presented in a portrait orientation. @return YES if the interface orientation is portrait, otherwise returns NO. */ - (BOOL)isPortraitInterfaceOrientation; /// ------------------------------------- /// @name Accessing the Layout Attributes /// ------------------------------------- /** The inset of the circle mask rect's area within the crop view's area in portrait orientation. Default value is `15.0f`. */ @property (assign, nonatomic) CGFloat portraitCircleMaskRectInnerEdgeInset; /** The inset of the square mask rect's area within the crop view's area in portrait orientation. Default value is `20.0f`. */ @property (assign, nonatomic) CGFloat portraitSquareMaskRectInnerEdgeInset; /** The vertical space between the top of the 'Move and Scale' label and the top of the crop view in portrait orientation. Default value is `64.0f`. */ @property (assign, nonatomic) CGFloat portraitMoveAndScaleLabelTopAndCropViewTopVerticalSpace; /** The vertical space between the bottom of the crop view and the bottom of the 'Cancel' button in portrait orientation. Default value is `21.0f`. */ @property (assign, nonatomic) CGFloat portraitCropViewBottomAndCancelButtonBottomVerticalSpace; /** The vertical space between the bottom of the crop view and the bottom of the 'Choose' button in portrait orientation. Default value is `21.0f`. */ @property (assign, nonatomic) CGFloat portraitCropViewBottomAndChooseButtonBottomVerticalSpace; /** The horizontal space between the leading of the 'Cancel' button and the leading of the crop view in portrait orientation. Default value is `13.0f`. */ @property (assign, nonatomic) CGFloat portraitCancelButtonLeadingAndCropViewLeadingHorizontalSpace; /** The horizontal space between the trailing of the crop view and the trailing of the 'Choose' button in portrait orientation. Default value is `13.0f`. */ @property (assign, nonatomic) CGFloat portraitCropViewTrailingAndChooseButtonTrailingHorizontalSpace; /** The inset of the circle mask rect's area within the crop view's area in landscape orientation. Default value is `45.0f`. */ @property (assign, nonatomic) CGFloat landscapeCircleMaskRectInnerEdgeInset; /** The inset of the square mask rect's area within the crop view's area in landscape orientation. Default value is `45.0f`. */ @property (assign, nonatomic) CGFloat landscapeSquareMaskRectInnerEdgeInset; /** The vertical space between the top of the 'Move and Scale' label and the top of the crop view in landscape orientation. Default value is `12.0f`. */ @property (assign, nonatomic) CGFloat landscapeMoveAndScaleLabelTopAndCropViewTopVerticalSpace; /** The vertical space between the bottom of the crop view and the bottom of the 'Cancel' button in landscape orientation. Default value is `12.0f`. */ @property (assign, nonatomic) CGFloat landscapeCropViewBottomAndCancelButtonBottomVerticalSpace; /** The vertical space between the bottom of the crop view and the bottom of the 'Choose' button in landscape orientation. Default value is `12.0f`. */ @property (assign, nonatomic) CGFloat landscapeCropViewBottomAndChooseButtonBottomVerticalSpace; /** The horizontal space between the leading of the 'Cancel' button and the leading of the crop view in landscape orientation. Default value is `13.0f`. */ @property (assign, nonatomic) CGFloat landscapeCancelButtonLeadingAndCropViewLeadingHorizontalSpace; /** The horizontal space between the trailing of the crop view and the trailing of the 'Choose' button in landscape orientation. Default value is `13.0f`. */ @property (assign, nonatomic) CGFloat landscapeCropViewTrailingAndChooseButtonTrailingHorizontalSpace; @end /** The `RSKImageCropViewControllerDataSource` protocol is adopted by an object that provides a custom rect and a custom path for the mask and a custom movement rect for the image. */ @protocol RSKImageCropViewControllerDataSource /** Asks the data source a custom rect for the mask. @param controller The crop view controller object to whom a rect is provided. @return A custom rect for the mask. */ - (CGRect)imageCropViewControllerCustomMaskRect:(RSKImageCropViewController *)controller; /** Asks the data source a custom path for the mask. @param controller The crop view controller object to whom a path is provided. @return A custom path for the mask. */ - (UIBezierPath *)imageCropViewControllerCustomMaskPath:(RSKImageCropViewController *)controller; /** Asks the data source a custom rect in which the image can be moved. @param controller The crop view controller object to whom a rect is provided. @return A custom rect in which the image can be moved. */ - (CGRect)imageCropViewControllerCustomMovementRect:(RSKImageCropViewController *)controller; @end /** The `RSKImageCropViewControllerDelegate` protocol defines messages sent to a image crop view controller delegate when crop image was canceled or the original image was cropped. */ @protocol RSKImageCropViewControllerDelegate /** Tells the delegate that crop image has been canceled. */ - (void)imageCropViewControllerDidCancelCrop:(RSKImageCropViewController *)controller; /** Tells the delegate that the original image has been cropped. Additionally provides a crop rect and a rotation angle used to produce image. */ - (void)imageCropViewController:(RSKImageCropViewController *)controller didCropImage:(UIImage *)croppedImage usingCropRect:(CGRect)cropRect rotationAngle:(CGFloat)rotationAngle; @optional /** Tells the delegate that the image has been displayed. */ - (void)imageCropViewControllerDidDisplayImage:(RSKImageCropViewController *)controller; /** Tells the delegate that the original image will be cropped. */ - (void)imageCropViewController:(RSKImageCropViewController *)controller willCropImage:(UIImage *)originalImage; @end NS_ASSUME_NONNULL_END