[英]How to get PDF annotations when i touch on ipad screen
I have developed an application which displays PDF on ipad using CATiled Layer. 我开发了一个应用程序,它使用CATiled Layer在ipad上显示PDF。 So far, so good& But there is a problem which really makes me cut my last hairs. 到目前为止,这么好&但有一个问题真的让我削减了我的最后一根头发。 I have a PDF with embedded annotations. 我有一个嵌入了注释的PDF。 Each annotation has an URL. 每个注释都有一个URL。 I can find the coordinates of touch area but the question is how I can find if there is an annotation under my finger and how to extract URL to open it in browser? 我可以找到触摸区域的坐标,但问题是如果我的手指下有注释以及如何提取URL以在浏览器中打开它,我怎么能找到?
If anyone can share any thoughts about how this can be done, I will really appreciate your help! 如果有人可以分享有关如何做到这一点的任何想法,我将非常感谢您的帮助!
Thanks in advance 提前致谢
Getting the annotations isn't very difficult with CGPDF although it required a little fiddling around for me at first. 使用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;
}
This will get you the URLs. 这将为您提供URL。 Getting the rects: 获得rects:
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]];
}
As you can see this bit of code first gets the rectangle of the annotation, transforms it to the device coordinate system, then does some recalculation, sizing and repositioning, based on page to screen ratio, rotation factor, etc. At the end you will have an array of the touch-active areas for that page. 正如您所看到的,这段代码首先获取注释的矩形,将其转换为设备坐标系,然后根据页面到屏幕的比例,旋转因子等进行一些重新计算,调整大小和重新定位。最后,您将有一个该页面的触摸活动区域的数组。 For handling the touches the following simple solution can be used: 为了处理触摸,可以使用以下简单的解决方案:
- (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));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.