The answer is in the question itself
here is the output:
Question
This is a self-answering question in gratitude to the various help I've gained off both StackOverflow and the Ray Wenderlich tutorial on drawing. I thought I'd put the various snippets together in one package.
My problem was that I wanted to do freehand drawing on a pdf larger than the iphone screen size. I therefore chose UIScrollView to handle the extra size, but as other posts have indicated, you then get into the following issues:
in this question Objective C: Drawing with Fingers on UIScrollView apouche gave me a great pointer to fixing the first issue. He suggested the use of custom UIPanGesturerecognizers to distinguish between drawing and scrolling. I found that the confusion over one vs two-finger scrolling was still a bit clumsy, so I used either the selection of the pencils, or a UISegmentedControl in the navigation bar, to select between pan and draw, and whether pinch would work by setting a BOOL drawActive.
Here's the viewDidLoad code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.tempDrawImage.userInteractionEnabled =YES;
cumTranslation = CGPointMake(0,0);
[panDrawSelect setSelectedSegmentIndex:0];
drawActive = NO;
red = 0.0/255.0;
green = 0.0/255.0;
blue = 0.0/255.0;
brush = 3.0;
opacity = 1.0;
NSURL *pdfUrl = [NSURL fileURLWithPath:loadPath];
document = CGPDFDocumentCreateWithURL((__bridge CFURLRef)pdfUrl);
currentPage = 1;
CGPDFPageRef page = CGPDFDocumentGetPage(document, currentPage);
pageRect = CGPDFPageGetBoxRect(page, kCGPDFTrimBox);
NSLog(@"page width = %f", pageRect.size.width);
NSLog(@"page height = %f", pageRect.size.height);
pdfScale = self.view.frame.size.width/pageRect.size.width;
pageRect.origin = CGPointMake(0,0);
NSLog(@"page width = %f", pageRect.size.width);
NSLog(@"page height = %f", pageRect.size.height);
UIGraphicsBeginImageContext(pageRect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
// White BG
CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0);
CGContextFillRect(context,pageRect);
CGContextSaveGState(context);
CGContextTranslateCTM(context, pageRect.size.width*0.75, pageRect.size.width+44);
CGContextScaleCTM(context, 1, -1);
CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(page, kCGPDFTrimBox, pageRect, 0, true));
CGContextRotateCTM(context, -1.5707);
CGContextDrawPDFPage(context, page);
CGContextRestoreGState(context);
UIImage *image =UIGraphicsGetImageFromCurrentImageContext();
initImage = image;
tempDrawImage =[[UIImageView alloc] initWithImage:image];
//CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
scrollView = [[UIScrollView alloc] initWithFrame:pageRect];
scrollView.delegate = self;
scrollView.minimumZoomScale = 0.3;
scrollView.maximumZoomScale = 3.0;
scrollView.contentSize= pageRect.size;
NSLog(@"page width = %f", pageRect.size.width);
NSLog(@"page height = %f", pageRect.size.height);
[scrollView addSubview:tempDrawImage];
[self.view addSubview:scrollView];
[self.view sendSubviewToBack: scrollView];
UIPanGestureRecognizer *Scrolling = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onScroll:)];
UIPinchGestureRecognizer *Zooming = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(onZoom:)];
[scrollView addGestureRecognizer:Scrolling];
[scrollView addGestureRecognizer:Zooming];
// Do any additional setup after loading the view.
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return tempDrawImage;
}
I then used the following code in the onScroll
method:
- (void)onScroll:(UIPanGestureRecognizer*)sender
{
if (!drawActive) {
CGPoint translation = [sender translationInView:self.view];
sender.view.center = CGPointMake(sender.view.center.x + translation.x,
sender.view.center.y + translation.y);
[sender setTranslation:CGPointMake(0, 0) inView:self.view];
cumTranslation = CGPointMake(cumTranslation.x + translation.x,
cumTranslation.y + translation.y);
}
else {// Processing the drawing by using comparing:
if (sender.state == UIGestureRecognizerStateBegan)
{ /* drawing began */
mouseSwiped = NO;
lastPoint = [sender locationInView:self.tempDrawImage];
scaleLastPoint.x = lastPoint.x*scrollView.zoomScale;
scaleLastPoint.y = lastPoint.y*scrollView.zoomScale;
}
else if (sender.state == UIGestureRecognizerStateChanged)
{ /* drawing occured */
mouseSwiped = YES;
CGPoint currentPoint = [sender locationInView:self.tempDrawImage];
CGPoint scalePoint;
scalePoint.x = currentPoint.x*scrollView.zoomScale;
scalePoint.y = currentPoint.y*scrollView.zoomScale;
UIGraphicsBeginImageContext(self.tempDrawImage.frame.size);
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.tempDrawImage.frame.size.width, self.tempDrawImage.frame.size.height)];
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), scaleLastPoint.x, scaleLastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), scalePoint.x, scalePoint.y);
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush );
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);
CGContextStrokePath(UIGraphicsGetCurrentContext());
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self.tempDrawImage setAlpha:opacity];
UIGraphicsEndImageContext();
scaleLastPoint = scalePoint;
}
else if (sender.state == UIGestureRecognizerStateEnded)
{ /* drawing ended */
if(!mouseSwiped) {
UIGraphicsBeginImageContext(self.tempDrawImage.frame.size);
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.tempDrawImage.frame.size.width, self.tempDrawImage.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, opacity);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), scaleLastPoint.x, scaleLastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), scaleLastPoint.x, scaleLastPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}}
To compensate for zoom, to ensure that the drawing annotation wasn't offset, I used the scaling included above, but highlighted here:
lastPoint = [sender locationInView:self.tempDrawImage];
scaleLastPoint.x = lastPoint.x*scrollView.zoomScale;
scaleLastPoint.y = lastPoint.y*scrollView.zoomScale;
La solution
The answer is in the question itself
here is the output: