// // 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