// // CPDFImageViewController.m // PDFViewer // // Created by kdan on 2022/11/19. // #import "PDFImageWatermarkController.h" #import "PDFWatermarkImageView.h" #import "PDFWatermarkImagePreview.h" #import "PDFWatermarkDataModel.h" #import "PDFWatermarkDrawView.h" #import "PDFWatermarkClipView.h" #import "PDFWatermarkControllerHeader.h" #import "Masonry.h" @interface PDFImageWatermarkController () @property (nonatomic,assign) CGRect watermarkFrame; @property (nonatomic,strong) PDFWatermarkDrawView *drawView; @property (nonatomic,strong) PDFWatermarkClipView *cliView; @property (nonatomic,assign) CGAffineTransform transform1; @property (nonatomic,assign) CGAffineTransform transform2; @property (nonatomic,assign) CGRect normalWatermarkRect; @property (nonatomic,strong) UILabel *shadowWaterLabel; @end @implementation PDFImageWatermarkController #pragma mark - UIViewController Methods - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. _imagePreview = [[PDFWatermarkImagePreview alloc] init]; _imageView = [[PDFWatermarkImageView alloc] init]; _imageView.verticalField.delegate = self; _imageView.horizontalField.delegate = self; [self.view addSubview:_imagePreview]; [self.view addSubview:_imageView]; [self.view setBackgroundColor:UIColor.grayColor]; [self initWatermarkView]; [self addConstraint]; [self addTargets]; [self createGestureRecognizer]; _shadowWaterLabel = [[UILabel alloc] init]; } #pragma mark - Orientation - (void)initDataModel { self.dataModel.textColor = UIColor.blackColor; self.dataModel.watermarkOpacity = 1; self.dataModel.watermarkScale = 17.0 / 24.0; self.dataModel.isTile = NO; self.dataModel.watermarkRotation = 0; self.dataModel.verticalSpacing = 100; self.dataModel.horizontalSpacing = 100; self.dataModel.imagePath = @"btn_selected"; self.dataModel.image = [UIImage imageNamed:self.dataModel.imagePath]; } - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight || [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft) { [self addSideConstraints]; } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationPortrait) { [self addNormalConstraints]; } if ([_drawView isDescendantOfView:self.view]) { _imageView.tileSwitch.on = NO; [_cliView removeFromSuperview]; [_drawView removeFromSuperview]; } } - (void)addSideConstraints { [_imageView mas_remakeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(self.view.mas_right).offset(-38); make.left.equalTo(_imagePreview.mas_right).offset(0); make.height.equalTo(@205); make.width.equalTo(@(self.view.bounds.size.width)); make.bottom.equalTo(self.view.mas_bottom).offset(-40); }]; [_imagePreview mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view.mas_top).offset(0); make.right.equalTo(_imageView.mas_left).offset(-5); make.left.equalTo(self.view.mas_left).offset(0); make.bottom.equalTo(self.view.mas_bottom).offset(0); }]; if ([_drawView isDescendantOfView:self.view]) { [_drawView mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view.mas_top).offset(0); make.right.equalTo(_imageView.mas_left).offset(-5); make.left.equalTo(self.view.mas_left).offset(0); make.bottom.equalTo(self.view.mas_bottom).offset(0); }]; [_cliView mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view.mas_top).offset(0); make.right.equalTo(_imageView.mas_left).offset(-5); make.left.equalTo(self.view.mas_left).offset(0); make.bottom.equalTo(self.view.mas_bottom).offset(0); }]; } } - (void)addNormalConstraints { [_imagePreview mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view.mas_top).offset(0); make.width.equalTo(self.view.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(-205); }]; [_imageView mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_imagePreview.mas_bottom).offset(0); make.width.equalTo(_imagePreview.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(0); }]; if ([_drawView isDescendantOfView:self.view]) { [_drawView mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view.mas_top).offset(0); make.width.equalTo(self.view.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(-205); }]; [_cliView mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view.mas_top).offset(0); make.width.equalTo(self.view.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(-205); }]; } } #pragma mark - Initializers - (void)initWatermarkView { _imageView.horizontalField.text = 0; _imageView.verticalField.text = 0; _imageView.horizontalField.enabled = NO; _imageView.verticalField.enabled = NO; _imageView.imageScaleSlider.enabled = YES; _imagePreview.preImageView.image = [UIImage imageNamed:self.dataModel.imagePath]; } - (void)addConstraint { [_imagePreview mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view.mas_top).offset(0); make.width.equalTo(self.view.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(-205); }]; [_imageView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_imagePreview.mas_bottom).offset(0); make.width.equalTo(_imagePreview.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(0); }]; } - (void)addTargets { [_imageView.selectBtn addTarget:self action:@selector(onSelectBtnClicked:) forControlEvents:UIControlEventTouchDown]; [_imageView.opacitySlider addTarget:self action:@selector(onOpacityChanged:) forControlEvents:UIControlEventValueChanged]; [_imageView.imageScaleSlider addTarget:self action:@selector(onImageScaleChanged:) forControlEvents:UIControlEventValueChanged]; [_imageView.tileSwitch addTarget:self action:@selector(onTileSwitchChanged:) forControlEvents:UIControlEventValueChanged]; [_imageView.pageBtn addTarget:self action:@selector(onSelectPageRange:) forControlEvents:UIControlEventTouchDown]; [_imageView.horizontalField addTarget:self action:@selector(horizontalChange:) forControlEvents:UIControlEventEditingDidEnd]; [_imageView.verticalField addTarget:self action:@selector(verticalChage:) forControlEvents:UIControlEventEditingDidEnd]; } #pragma mark - Gesture - (void)createGestureRecognizer { [_imagePreview.documentImageView setUserInteractionEnabled:YES]; [_imagePreview.preImageView setMultipleTouchEnabled:YES]; [_imagePreview.preImageView setUserInteractionEnabled:YES]; [_imagePreview.rotationBtn setUserInteractionEnabled:YES]; UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panWatermarkView:)]; [_imagePreview.preImageView addGestureRecognizer:panRecognizer]; UIPanGestureRecognizer *panRotationBtnRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(rotateWatermarkView:)]; [_imagePreview.rotationBtn addGestureRecognizer:panRotationBtnRecognizer]; } - (void)rotateWatermarkView:(UIPanGestureRecognizer *)recognizer { CGPoint point = [recognizer translationInView:_imagePreview]; CGFloat radian = atan2(point.x + _imagePreview.center.x - _imagePreview.preImageView.center.x,point.y + _imagePreview.center.y - _imagePreview.preImageView.center.y); if (self.dataModel.watermarkScale == (17.0 / 24.0)) { _imagePreview.preImageView.transform = CGAffineTransformMakeRotation(-radian); } else { _imagePreview.preImageView.transform = CGAffineTransformRotate(self.transform2, -radian); } _transform1 = CGAffineTransformMakeRotation(-radian); self.dataModel.watermarkRotation = (-radian) * 180 / M_PI; } - (void)panWatermarkView:(UIPanGestureRecognizer *)recognizer { CGPoint point = [recognizer translationInView:_imagePreview.documentImageView]; CGRect documentFrame = _imagePreview.documentImageView.frame; documentFrame.origin.x -= _imagePreview.documentImageView.frame.origin.x; documentFrame.origin.y -= _imagePreview.documentImageView.frame.origin.y; [_imagePreview.preImageView setCenter:CGPointMake(_imagePreview.preImageView.center.x + point.x, _imagePreview.preImageView.center.y + point.y)]; [_imagePreview.rotationBtn setCenter:CGPointMake(_imagePreview.rotationBtn.center.x + point.x, _imagePreview.rotationBtn.center.y + point.y)]; if (!CGRectContainsRect(documentFrame,_imagePreview.preImageView.frame)) { [_imagePreview.preImageView setCenter:CGPointMake(_imagePreview.preImageView.center.x - point.x, _imagePreview.preImageView.center.y - point.y)]; [_imagePreview.rotationBtn setCenter:CGPointMake(_imagePreview.rotationBtn.center.x - point.x, _imagePreview.rotationBtn.center.y - point.y)]; } self.dataModel.tx = _imagePreview.preImageView.center.x - (_imagePreview.documentImageView.center.x - _imagePreview.documentImageView.frame.origin.x); self.dataModel.ty = _imagePreview.documentImageView.center.y - _imagePreview.documentImageView.frame.origin.y - _imagePreview.preImageView.center.y; _shadowWaterLabel.center = _imagePreview.preImageView.center; [recognizer setTranslation:CGPointZero inView:_imagePreview.documentImageView]; _normalWatermarkRect = _shadowWaterLabel.frame; } #pragma mark - UI Functions - (void)onSelectBtnClicked:(UIButton *)sender { UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; imagePicker.delegate = self; imagePicker.allowsEditing = YES; [self presentViewController:imagePicker animated:YES completion:nil]; } - (void)onOpacityChanged:(UISlider *)sender { _imagePreview.preImageView.alpha = 1 - sender.value; [self.dataModel setWatermarkOpacity:1 - sender.value]; } /* this had core was deleted: // _watermarkFrame.size.width = sender.value * [UIImage imageNamed:_dataModel.imagePath].size.width; // _watermarkFrame.size.height = sender.value * [UIImage imageNamed:_dataModel.imagePath].size.height; // _watermarkFrame.size.width = sender.value * 33; // _watermarkFrame.size.height = sender.value * 33; // // _watermarkFrame.origin.x = _imagePreview.watermarkView.frame.origin.x; // _watermarkFrame.origin.y = _imagePreview.watermarkView.frame.origin.y; // _imagePreview.watermarkView.frame = _watermarkFrame; // _imagePreview.watermarkFrame = _watermarkFrame; */ - (void)onImageScaleChanged:(UISlider *)sender { sender.minimumValue = 0.5; sender.maximumValue = 2; if (self.dataModel.watermarkRotation) { _imagePreview.preImageView.transform = CGAffineTransformScale(self.transform1, sender.value, sender.value); } else { _imagePreview.preImageView.transform = CGAffineTransformMakeScale(sender.value, sender.value); } _transform2 = CGAffineTransformMakeScale(sender.value, sender.value); _shadowWaterLabel.transform = CGAffineTransformMakeScale(sender.value, sender.value); [_imagePreview.rotationBtn mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_imagePreview.preImageView.mas_bottom).offset(-10); make.width.equalTo(@20); make.height.equalTo(@20); make.left.equalTo(_imagePreview.preImageView.mas_right).offset(-10); }]; [self.dataModel setWatermarkScale:sender.value]; _normalWatermarkRect = _shadowWaterLabel.frame; } - (void)onTileSwitchChanged:(UISwitch *) sender { if ([sender isOn]) { self.dataModel.isTile = YES; _imageView.horizontalField.enabled = YES; _imageView.verticalField.enabled = YES; _imageView.imageScaleSlider.enabled = NO; _drawView = [[PDFWatermarkDrawView alloc] initWithFrame:self.imagePreview.bounds]; if (_shadowWaterLabel.frame.size.height == 0) { _shadowWaterLabel.frame = _imagePreview.preImageView.frame; _normalWatermarkRect = _shadowWaterLabel.frame; } [_drawView setDataModel:self.dataModel]; [_drawView setWaterLabelRect:self.normalWatermarkRect]; [_drawView setDocumentViewRect:self.imagePreview.documentImageView.frame]; [self.view addSubview:_drawView]; [self.imagePreview bringSubviewToFront:_drawView]; _cliView = [[PDFWatermarkClipView alloc] initWithFrame:self.imagePreview.bounds]; [_cliView setDocumentRect:self.imagePreview.documentImageView.frame]; [self.view addSubview:_cliView]; [self.drawView bringSubviewToFront:_cliView]; } else { self.dataModel.isTile = NO; _imageView.horizontalField.enabled = NO; _imageView.verticalField.enabled = NO; _imageView.imageScaleSlider.enabled = YES; [self.drawView removeFromSuperview]; [self.cliView removeFromSuperview]; } } - (void)horizontalChange:(UITextField *)text { [_drawView setHorizontal:[text.text floatValue]]; self.dataModel.horizontalSpacing = [text.text floatValue]; [_drawView setNeedsDisplay]; } - (void)verticalChage:(UITextField *)text { [_drawView setVertical:[text.text floatValue]]; self.dataModel.verticalSpacing = [text.text floatValue]; [_drawView setNeedsDisplay]; } #pragma mark - UIImagePickerControllerDelegate - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *image = info[UIImagePickerControllerOriginalImage]; CGSize size; size.width = image.size.width / 30; size.height = image.size.height / 30; _imagePreview.preImageView.image = [self imageWithImageSimple:image scaledToSize:size]; self.dataModel.image = [self imageWithImageSimple:image scaledToSize:size]; [_imagePreview.preImageView sizeToFit]; _shadowWaterLabel.frame = _imagePreview.preImageView.frame; [picker dismissViewControllerAnimated:YES completion:nil]; _normalWatermarkRect = _shadowWaterLabel.frame; } - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [picker dismissViewControllerAnimated:YES completion:nil]; } - (UIImage *)imageWithImageSimple:(UIImage *)image scaledToSize:(CGSize)newSize { UIGraphicsBeginImageContext(newSize); [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } #pragma mark - UITextFieldDelegate - (void)textFieldDidBeginEditing:(UITextField *)textField { self.cliView.hidden = YES; self.drawView.hidden = YES; if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight || [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft || [UIDevice currentDevice].orientation == UIDeviceOrientationPortraitUpsideDown) { } else { if (_imageView.frame.origin.y > (self.view.frame.size.height - 300)) { [_imageView mas_remakeConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(205); make.width.equalTo(_imagePreview.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(-300); }]; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^ { self.imageView.center = CGPointMake(self.imageView.center.x, self.imageView.center.y - 300); } completion:nil]; } } } - (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; self.cliView.hidden = NO; self.drawView.hidden = NO; if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight || [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft || [UIDevice currentDevice].orientation == UIDeviceOrientationPortraitUpsideDown) { } else { if(_imageView.frame.origin.y < self.view.frame.size.height) { [_imageView mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_imagePreview.mas_bottom).offset(0); make.width.equalTo(_imagePreview.mas_width); make.bottom.equalTo(self.view.mas_bottom).offset(0); make.height.mas_equalTo(205); }]; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^ { self.imageView.center = CGPointMake(self.imageView.center.x, self.imageView.center.y + 300); } completion:nil]; } } return YES; } - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (_imageView.horizontalField == textField || _imageView.verticalField == textField) { return [self validateValue:string]; } return YES; } @end