How to get pdf annotations when I touch ipad screen

I developed an application that displays PDF on ipad using CATiled Layer. So far, so good, But there is a problem that really makes me cut my last hair. I have a PDF with embedded annotations. Each annotation contains a URL. I can find the coordinates of the touch area, but the question is, how can I find if there is an annotation under my finger and how to extract the URL to open it in the browser?

If anyone can share thoughts on how to do this, I will really appreciate your help!

Thanks in advance

+5
source share
1 answer

CGPDF, .

//Get the current page ref 
CGPDFPageRef currentPdfPage = CGPDFDocumentGetPage(pdfDocumentRef, page);

//Get the page dictionary
CGPDFDictionaryRef pageDictionary = CGPDFPageGetDictionary(currentPdfPage);
CGPDFArrayRef annotsArray;

//Get the Annots array
if(!CGPDFDictionaryGetArray(pageDictionary, "Annots", &annotsArray)) {
    //DLog(@"No Annots found for page %d", page);
    [self updateProgress];
    return;
}

int annotsArrayCount = CGPDFArrayGetCount(annotsArray);
//DLog(@"%d annots found for page %d in file %@", annotsArrayCount, page, _fileName);
NSMutableArray* touchRectsArray = [[NSMutableArray alloc] initWithCapacity:annotsArrayCount];
for (int j=annotsArrayCount; j >= 0; j--) {
    int destPageNumber = 0;
    NSString* uri = nil;

    //DLog(@"%d/%d", j+1, annotsArrayCount);

    CGPDFObjectRef aDictObj;
    if(!CGPDFArrayGetObject(annotsArray, j, &aDictObj)) {
        //DLog(@"%@", @"can't get dictionary object");
        continue;
    }

    CGPDFDictionaryRef annotDict;
    if(!CGPDFObjectGetValue(aDictObj, kCGPDFObjectTypeDictionary, &annotDict)) {
        //DLog(@"%@", @"can't get annotDict");
        continue;
    }

    //------------
    CGPDFDictionaryRef aDict;
    CGPDFArrayRef destArray;
    if(CGPDFDictionaryGetDictionary(annotDict, "A", &aDict)) {
        CGPDFStringRef uriStringRef;
        if(CGPDFDictionaryGetString(aDict, "URI", &uriStringRef)) {
            char* uriString = (char *)CGPDFStringGetBytePtr(uriStringRef);
            uri = [NSString stringWithCString:uriString encoding:NSUTF8StringEncoding];
        }
    } else {
        continue;
    }

URL-. :

CGPDFArrayRef rectArray;
    if(!CGPDFDictionaryGetArray(annotDict, "Rect", &rectArray)) {
        DLog(@"%@", @"can't get Rect");
    }

    int arrayCount = CGPDFArrayGetCount(rectArray);
    CGPDFReal coords[4];
    for (int k = 0; k < arrayCount; k++) {
        CGPDFObjectRef rectObj;
        if(!CGPDFArrayGetObject(rectArray, k, &rectObj)) {
            DLog(@"%@", @"can't get rect data");
        }

        CGPDFReal coord;
        if(!CGPDFObjectGetValue(rectObj, kCGPDFObjectTypeReal, &coord)) {
            DLog(@"%@", @"can't get coords");
        }

        coords[k] = coord;
    }

    CGRect drawRect = [[SharedConfig valueForKey:@"screenSize"] CGRectValue];
    BOOL drawBoxIsLandscape = NO;
    if (1 < drawRect.size.width/drawRect.size.height) {
        drawBoxIsLandscape = YES;
    }

    CGRect pageRect = CGRectIntegral(CGPDFPageGetBoxRect(currentPdfPage, kCGPDFMediaBox));
    landscape = NO;
    if (1 < pageRect.size.width/pageRect.size.height) {
        landscape = YES;
    }

    float ratio = 0.0;

    //Get the rect of the clickable area
    //CGRect coordsRect = CGRectMake(coords[0], coords[1], coords[2], coords[3]);
    //Transform to new coordinate system
    CGRect originalRect = CGRectMake(coords[0], (pageRect.size.height-(coords[3]-coords[1]))-coords[1], coords[2]-coords[0], coords[3]-coords[1]);

    CGPDFInteger pageRotate = 0;
    CGPDFDictionaryGetInteger(pageDictionary, "Rotate", &pageRotate);

    if (pageRotate == 90 || pageRotate == 270) {
        CGFloat temp = pageRect.size.width;
        pageRect.size.width = pageRect.size.height;
        pageRect.size.height = temp;
        ratio = drawRect.size.height / pageRect.size.height;
    }       

    if (drawBoxIsLandscape) {
        ratio = landscape ? (drawRect.size.height/pageRect.size.height) : (drawRect.size.height/pageRect.size.width);

        if (landscape && drawRect.size.width < pageRect.size.width*ratio) {
            ratio = drawRect.size.width/pageRect.size.width;
        } else if (!landscape && drawRect.size.height < pageRect.size.width*ratio) {
            ratio = drawRect.size.height/pageRect.size.width;
        }
    } else {
        ratio = landscape ? (drawRect.size.height/pageRect.size.width) : (drawRect.size.height/pageRect.size.height);

        if (landscape && drawRect.size.width < pageRect.size.height*ratio) {
            ratio = drawRect.size.width/pageRect.size.height;
        } else if (!landscape && drawRect.size.height < pageRect.size.height*ratio) {
            ratio = drawRect.size.height/pageRect.size.height;
        }
    }

    CGRect calculatedRect = CGRectMake(originalRect.origin.x*ratio, originalRect.origin.y*ratio, originalRect.size.width*ratio, originalRect.size.height*ratio);

    if ((landscape && !drawBoxIsLandscape) || (!landscape && drawBoxIsLandscape)) {
        CGFloat width = calculatedRect.size.width;
        calculatedRect.size.width = calculatedRect.size.height;
        calculatedRect.size.height = width;

        CGFloat yModifier = drawRect.size.height-(pageRect.size.width*ratio);

        CGFloat x = calculatedRect.origin.x;
        calculatedRect.origin.x = calculatedRect.origin.y;
        calculatedRect.origin.y = drawRect.size.height-(x+calculatedRect.size.height)-yModifier;

    }

    if (nil != uri) {
        [touchRectsArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithCGRect:calculatedRect], @"rect", uri, @"targetUrl", nil]];
    }

, , , , , .. end, . :

- (void) tapGesture:(UIGestureRecognizer*)sender
{
if (UIGestureRecognizerStateEnded == sender.state) {
    CGPoint touchPoint = [sender locationInView:self.view];

    if (nil != self.touchRects) for (int i=0; i<[self.touchRects count]; i++) {
        if (CGRectContainsPoint([[[self.touchRects objectAtIndex:i] objectForKey:@"rect"] CGRectValue], touchPoint)) {
            if ([[self.touchRects objectAtIndex:i] objectForKey:@"targetUrl"]) {
                NSString* targetUrl = [[self.touchRects objectAtIndex:i] objectForKey:@"targetUrl"];
                DLog(@"Hit found for target url: %@", targetUrl);
                NSURL* url = [NSURL URLWithString:targetUrl];
                [[UIApplication sharedApplication] openURL:url];
            }               return;
        }       
    }
    DLog(@"No hit found for touch at %@", NSStringFromCGPoint(touchPoint));
}
} 
+6

All Articles