292 lines
9.5 KiB
Objective-C

//
// CLSplashTool.m
//
// Created by sho yakushiji on 2014/06/21.
// Copyright (c) 2014年 CALACULU. All rights reserved.
//
#import "CLSplashTool.h"
static NSString* const kCLSplashToolEraserIconName = @"eraserIconAssetsName";
@implementation CLSplashTool
{
UIImageView *_drawingView;
UIImage *_maskImage;
UIImage *_grayImage;
CGSize _originalImageSize;
CGPoint _prevDraggingPosition;
UIView *_menuView;
UISlider *_widthSlider;
UIView *_strokePreview;
UIView *_strokePreviewBackground;
UIImageView *_eraserIcon;
CLToolbarMenuItem *_colorBtn;
}
+ (NSArray*)subtools
{
return nil;
}
+ (NSString*)defaultTitle
{
return [CLImageEditorTheme localizedString:@"CLSplashTool_DefaultTitle" withDefault:@"Splash"];
}
+ (BOOL)isAvailable
{
return YES;
}
+ (CGFloat)defaultDockedNumber
{
return 4.6;
}
#pragma mark- optional info
+ (NSDictionary*)optionalInfo
{
return @{
kCLSplashToolEraserIconName : @"",
};
}
#pragma mark- implementation
- (void)setup
{
_originalImageSize = self.editor.imageView.image.size;
_drawingView = [[UIImageView alloc] initWithFrame:self.editor.imageView.bounds];
_drawingView.contentMode = UIViewContentModeScaleAspectFit;
_grayImage = [[self.editor.imageView.image aspectFit:CGSizeMake(_drawingView.width*2, _drawingView.height*2)] grayScaleImage];
_drawingView.image = _grayImage;
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(drawingViewDidPan:)];
panGesture.maximumNumberOfTouches = 1;
_drawingView.userInteractionEnabled = YES;
[_drawingView addGestureRecognizer:panGesture];
[self.editor.imageView addSubview:_drawingView];
self.editor.imageView.userInteractionEnabled = YES;
self.editor.scrollView.panGestureRecognizer.minimumNumberOfTouches = 2;
self.editor.scrollView.panGestureRecognizer.delaysTouchesBegan = NO;
self.editor.scrollView.pinchGestureRecognizer.delaysTouchesBegan = NO;
_menuView = [[UIView alloc] initWithFrame:self.editor.menuView.frame];
_menuView.backgroundColor = self.editor.menuView.backgroundColor;
[self.editor.view addSubview:_menuView];
[self setMenu];
_menuView.transform = CGAffineTransformMakeTranslation(0, self.editor.view.height-_menuView.top);
[UIView animateWithDuration:kCLImageToolAnimationDuration
animations:^{
self->_menuView.transform = CGAffineTransformIdentity;
}];
}
- (void)cleanup
{
[_drawingView removeFromSuperview];
self.editor.imageView.userInteractionEnabled = NO;
self.editor.scrollView.panGestureRecognizer.minimumNumberOfTouches = 1;
[UIView animateWithDuration:kCLImageToolAnimationDuration
animations:^{
self->_menuView.transform = CGAffineTransformMakeTranslation(0, self.editor.view.height-self->_menuView.top);
}
completion:^(BOOL finished) {
[self->_menuView removeFromSuperview];
}];
}
- (void)executeWithCompletionBlock:(void (^)(UIImage *, NSError *, NSDictionary *))completionBlock
{
UIImage *backgroundImage = self.editor.imageView.image;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *image = [self buildImageWithBackgroundImage:backgroundImage];
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(image, nil, nil);
});
});
}
#pragma mark-
- (UISlider*)defaultSliderWithWidth:(CGFloat)width
{
UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 0, width, 34)];
[slider setMaximumTrackImage:[UIImage new] forState:UIControlStateNormal];
[slider setMinimumTrackImage:[UIImage new] forState:UIControlStateNormal];
[slider setThumbImage:[UIImage new] forState:UIControlStateNormal];
slider.thumbTintColor = [UIColor whiteColor];
return slider;
}
- (UIImage*)widthSliderBackground
{
CGSize size = _widthSlider.frame.size;
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
UIColor *color = [[[CLImageEditorTheme theme] toolbarTextColor] colorWithAlphaComponent:0.5];
CGFloat strRadius = 1;
CGFloat endRadius = size.height/2 * 0.6;
CGPoint strPoint = CGPointMake(strRadius + 5, size.height/2 - 2);
CGPoint endPoint = CGPointMake(size.width-endRadius - 1, strPoint.y);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddArc(path, NULL, strPoint.x, strPoint.y, strRadius, -M_PI/2, M_PI-M_PI/2, YES);
CGPathAddLineToPoint(path, NULL, endPoint.x, endPoint.y + endRadius);
CGPathAddArc(path, NULL, endPoint.x, endPoint.y, endRadius, M_PI/2, M_PI+M_PI/2, YES);
CGPathAddLineToPoint(path, NULL, strPoint.x, strPoint.y - strRadius);
CGPathCloseSubpath(path);
CGContextAddPath(context, path);
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillPath(context);
UIImage *tmp = UIGraphicsGetImageFromCurrentImageContext();
CGPathRelease(path);
UIGraphicsEndImageContext();
return tmp;
}
- (void)setMenu
{
CGFloat W = 70;
_widthSlider = [self defaultSliderWithWidth:_menuView.width - W - 20];
_widthSlider.left = 10;
_widthSlider.top = _menuView.height/2 - _widthSlider.height/2;
[_widthSlider addTarget:self action:@selector(widthSliderDidChange:) forControlEvents:UIControlEventValueChanged];
_widthSlider.value = 0.1;
_widthSlider.backgroundColor = [UIColor colorWithPatternImage:[self widthSliderBackground]];
[_menuView addSubview:_widthSlider];
_strokePreview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, W - 5, W - 5)];
_strokePreview.layer.cornerRadius = _strokePreview.height/2;
_strokePreview.layer.borderWidth = 1;
_strokePreview.layer.borderColor = [[[CLImageEditorTheme theme] toolbarTextColor] CGColor];
_strokePreview.center = CGPointMake(_menuView.width-W/2, _menuView.height/2);
[_menuView addSubview:_strokePreview];
_strokePreviewBackground = [[UIView alloc] initWithFrame:_strokePreview.frame];
_strokePreviewBackground.layer.cornerRadius = _strokePreviewBackground.height/2;
_strokePreviewBackground.alpha = 0.3;
[_strokePreviewBackground addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(strokePreviewDidTap:)]];
[_menuView insertSubview:_strokePreviewBackground aboveSubview:_strokePreview];
_strokePreview.backgroundColor = [[CLImageEditorTheme theme] toolbarTextColor];
_strokePreviewBackground.backgroundColor = _strokePreview.backgroundColor;
_eraserIcon = [[UIImageView alloc] initWithFrame:_strokePreview.frame];
_eraserIcon.image = [self imageForKey:kCLSplashToolEraserIconName defaultImageName:@"btn_eraser.png"];
_eraserIcon.hidden = YES;
[_menuView addSubview:_eraserIcon];
[self widthSliderDidChange:_widthSlider];
_menuView.clipsToBounds = NO;
}
- (void)widthSliderDidChange:(UISlider*)sender
{
CGFloat scale = MAX(0.05, _widthSlider.value);
_strokePreview.transform = CGAffineTransformMakeScale(scale, scale);
_strokePreview.layer.borderWidth = 2/scale;
}
- (void)strokePreviewDidTap:(UITapGestureRecognizer*)sender
{
_eraserIcon.hidden = !_eraserIcon.hidden;
}
- (void)drawingViewDidPan:(UIPanGestureRecognizer*)sender
{
CGPoint currentDraggingPosition = [sender locationInView:_drawingView];
if(sender.state == UIGestureRecognizerStateBegan){
_prevDraggingPosition = currentDraggingPosition;
}
if(sender.state != UIGestureRecognizerStateEnded){
[self drawLine:_prevDraggingPosition to:currentDraggingPosition];
_drawingView.image = [_grayImage maskedImage:_maskImage];
}
_prevDraggingPosition = currentDraggingPosition;
}
-(void)drawLine:(CGPoint)from to:(CGPoint)to
{
CGSize size = _drawingView.frame.size;
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat strokeWidth = MAX(1, _widthSlider.value * 65);
if(_maskImage==nil){
CGContextSetFillColorWithColor(context, [[UIColor blackColor] CGColor]);
CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));
}
else{
[_maskImage drawAtPoint:CGPointZero];
}
CGContextSetLineWidth(context, strokeWidth);
CGContextSetLineCap(context, kCGLineCapRound);
if(!_eraserIcon.hidden){
CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);
}
else{
CGContextSetStrokeColorWithColor(context, [[UIColor whiteColor] CGColor]);
}
CGContextMoveToPoint(context, from.x, from.y);
CGContextAddLineToPoint(context, to.x, to.y);
CGContextStrokePath(context);
_maskImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
- (UIImage*)buildImageWithBackgroundImage:(UIImage*)backgroundImage
{
_grayImage = [backgroundImage grayScaleImage];
UIGraphicsBeginImageContextWithOptions(_originalImageSize, NO, backgroundImage.scale);
[backgroundImage drawAtPoint:CGPointZero];
[[_grayImage maskedImage:_maskImage] drawInRect:CGRectMake(0, 0, _originalImageSize.width, _originalImageSize.height)];
UIImage *tmp = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return tmp;
}
@end