// // CPDFImageViewController.m // PDFViewer // // Created by kdan on 2022/11/19. // #import "CPDFImageViewController.h" #import "CPDFImageView.h" #import "CPDFImagePreview.h" #import "CPDFDataModel.h" #import "CPDFDrawView.h" #import "CPDFClipView.h" #import "Masonry.h" @interface CPDFImageViewController () @property (nonatomic,assign) CGRect watermarkFrame; @property (nonatomic,strong) CPDFDrawView *drawView; @property (nonatomic,strong) CPDFClipView *cliView; @end @implementation CPDFImageViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. _imagePreview = [[CPDFImagePreview alloc] init]; _imageView = [[CPDFImageView alloc] init]; _dataModel = [[CPDFDataModel alloc] init]; [self.view addSubview:_imagePreview]; [self.view addSubview:_imageView]; [self.view setBackgroundColor:UIColor.systemGray5Color]; [self initDataModel]; [self addConstraint]; [self addTargets]; [self createGestureRecognizer]; } - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight) { [_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(10); 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); }]; } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationPortrait) { [_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); }]; } } - (void)initDataModel { _dataModel.watermarkOpacity = 1; _dataModel.imagePath = @"btn_selected"; _dataModel.image = [UIImage imageNamed:_dataModel.imagePath]; _dataModel.watermarkScale = 1; _dataModel.isTile = NO; _dataModel.watermarkRotation = 0; _imageView.horizontalField.text = 0; _imageView.verticalField.text = 0; _imageView.horizontalField.enabled = NO; _imageView.verticalField.enabled = NO; _imageView.imageScaleSlider.enabled = YES; _imagePreview.watermarkView.image = [UIImage imageNamed:_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]; } #pragma mark - Gesture - (void)createGestureRecognizer { [_imagePreview.documentView setUserInteractionEnabled:YES]; [_imagePreview.watermarkView setMultipleTouchEnabled:YES]; [_imagePreview.watermarkView setUserInteractionEnabled:YES]; [_imagePreview.rotationBtn setUserInteractionEnabled:YES]; UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panWatermarkView:)]; [_imagePreview.watermarkView 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.watermarkView.center.x,point.y + _imagePreview.center.y - _imagePreview.watermarkView.center.y); _imagePreview.watermarkView.transform = CGAffineTransformMakeRotation(-radian); _dataModel.watermarkRotation = (-radian) * 180 / M_PI; } - (void)panWatermarkView:(UIPanGestureRecognizer *)recognizer { CGPoint point = [recognizer translationInView:_imagePreview.documentView]; CGRect documentFrame = _imagePreview.documentView.frame; documentFrame.origin.x -= _imagePreview.documentView.frame.origin.x; documentFrame.origin.y -= _imagePreview.documentView.frame.origin.y; [_imagePreview.watermarkView setCenter:CGPointMake(_imagePreview.watermarkView.center.x + point.x, _imagePreview.watermarkView.center.y + point.y)]; [_imagePreview.rotationBtn setCenter:CGPointMake(_imagePreview.rotationBtn.center.x + point.x, _imagePreview.rotationBtn.center.y + point.y)]; if (!CGRectContainsRect(documentFrame,_imagePreview.watermarkView.frame)) { [_imagePreview.watermarkView setCenter:CGPointMake(_imagePreview.watermarkView.center.x - point.x, _imagePreview.watermarkView.center.y - point.y)]; [_imagePreview.rotationBtn setCenter:CGPointMake(_imagePreview.rotationBtn.center.x - point.x, _imagePreview.rotationBtn.center.y - point.y)]; } _dataModel.tx = _imagePreview.watermarkView.center.x - (_imagePreview.documentView.center.x - _imagePreview.documentView.frame.origin.x); _dataModel.ty = _imagePreview.documentView.center.y - _imagePreview.documentView.frame.origin.y - _imagePreview.watermarkView.center.y; [recognizer setTranslation:CGPointZero inView:_imagePreview.documentView]; } #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.watermarkView.alpha = 1 - sender.value; [_dataModel setWatermarkOpacity:1 - sender.value]; } - (void)onImageScaleChanged:(UISlider *)sender { sender.minimumValue = 1; sender.maximumValue = 3; // _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; [_imagePreview.rotationBtn mas_remakeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(_imagePreview.watermarkView.mas_bottom).offset(-10); make.width.equalTo(@20); make.height.equalTo(@20); make.left.equalTo(_imagePreview.watermarkView.mas_right).offset(-10); }]; [_dataModel setWatermarkScale:sender.value]; } - (void)onSelectPageRange:(UIButton *)sender { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; UIAlertAction *defaultRange = [UIAlertAction actionWithTitle:@"All Pages" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { self.imageView.rangeLabel.text = @"Page Range: ALL"; }]; UIAlertAction *customRange = [UIAlertAction actionWithTitle:@"Custom Page Range" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self createCustomRangeAlert]; }]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]; [alertController addAction:defaultRange]; [alertController addAction:customRange]; [alertController addAction:cancelAction]; [self presentViewController:alertController animated:YES completion:nil]; } - (void)createCustomRangeAlert { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Custom Page Range" message:nil preferredStyle:UIAlertControllerStyleAlert]; [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.placeholder = @"such as:1,3-5,10"; }]; [alertController addAction:[UIAlertAction actionWithTitle:@"Done" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { self.dataModel.pageString = alertController.textFields.firstObject.text; self.imageView.rangeLabel.text = @"Page Range:Custom"; }]]; [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { }]]; [self presentViewController:alertController animated:YES completion:nil]; } - (void)onTileSwitchChanged:(UISwitch *) sender { if ([sender isOn]) { _dataModel.isTile = YES; _imageView.horizontalField.enabled = YES; _imageView.verticalField.enabled = YES; _imageView.imageScaleSlider.enabled = NO; _drawView = [[CPDFDrawView alloc] initWithFrame:self.imagePreview.bounds]; _drawView.delegate = self; [self.view addSubview:_drawView]; [self.imagePreview bringSubviewToFront:_drawView]; _cliView = [[CPDFClipView alloc] initWithFrame:self.imagePreview.bounds]; _cliView.delegate = self; [self.view addSubview:_cliView]; [self.drawView bringSubviewToFront:_cliView]; } else { _dataModel.isTile = NO; _imageView.horizontalField.enabled = NO; _imageView.verticalField.enabled = NO; _imageView.imageScaleSlider.enabled = YES; [self.drawView removeFromSuperview]; [self.cliView removeFromSuperview]; } } #pragma mark - UIImagePickerControllerDelegate - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *image = info[UIImagePickerControllerOriginalImage]; CGSize size; size.width = image.size.width/10; size.height = image.size.width/10; _imagePreview.watermarkView.image = [self imageWithImageSimple:image scaledToSize:size]; _dataModel.image = [self imageWithImageSimple:image scaledToSize:size]; [_imagePreview.watermarkView sizeToFit]; [picker dismissViewControllerAnimated:YES completion:nil]; } - (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 - CPDFTextPreviewDelegate - (void)drawText:(CGContextRef)context { CGContextSaveGState(context); UIImage *image = self.imagePreview.watermarkView.image; self.drawView.transform = CGAffineTransformMakeRotation((self.dataModel.watermarkRotation * M_PI) / 180); NSInteger wx,wy,height,width; wx = self.imagePreview.watermarkView.frame.origin.x + self.imagePreview.documentView.frame.origin.x; wy = self.imagePreview.watermarkView.frame.origin.y + self.imagePreview.documentView.frame.origin.y; height = self.imagePreview.watermarkView.frame.size.height + 10; width = self.imagePreview.watermarkView.frame.size.width + 10; NSInteger x,y,a,b; x = wx / width + (self.imagePreview.frame.size.width - (wx + width)) / width + 1; y = wy / height + (self.imagePreview.frame.size.height - (wy + height)) / height + 1; a = wx % width; b = wy % height; for (NSInteger i = 0; i < x; i++) { for (NSInteger j = 0; j < y; j++) { [image drawInRect:CGRectMake(a + i * width, b + j * height, width - 10, height - 10)]; } } } #pragma mark - CPDFClipTextPreviewDelegate - (void)clipText:(CGContextRef)context { CGContextSetFillColorWithColor(context, [UIColor systemGray5Color].CGColor); CGContextFillRect(context, self.imagePreview.bounds); CGContextClearRect(context, self.imagePreview.documentView.frame); } @end