Revision: 2880
http://skim-app.svn.sourceforge.net/skim-app/?rev=2880&view=rev
Author: hofman
Date: 2007-09-10 10:10:16 -0700 (Mon, 10 Sep 2007)
Log Message:
-----------
Rewrite FDF parser. Use CGPDFDocument to parse the document after fooling it
that the data is PDF.
Modified Paths:
--------------
trunk/SKDocument.m
trunk/SKFDFParser.h
trunk/SKFDFParser.m
Modified: trunk/SKDocument.m
===================================================================
--- trunk/SKDocument.m 2007-09-10 17:09:31 UTC (rev 2879)
+++ trunk/SKDocument.m 2007-09-10 17:10:16 UTC (rev 2880)
@@ -671,9 +671,9 @@
if ([extension caseInsensitiveCompare:@"skim"] == NSOrderedSame) {
array = [NSKeyedUnarchiver unarchiveObjectWithFile:[notesURL
path]];
} else {
- NSString *fdfString = [NSString stringWithContentsOfURL:notesURL
encoding:NSISOLatin1StringEncoding error:NULL];
- if (fdfString)
- array = [SKFDFParser noteDictionariesFromFDFString:fdfString];
+ NSData *fdfData = [NSData dataWithContentsOfURL:notesURL];
+ if (fdfData)
+ array = [SKFDFParser noteDictionariesFromFDFData:fdfData];
}
if (array) {
Modified: trunk/SKFDFParser.h
===================================================================
--- trunk/SKFDFParser.h 2007-09-10 17:09:31 UTC (rev 2879)
+++ trunk/SKFDFParser.h 2007-09-10 17:10:16 UTC (rev 2880)
@@ -37,11 +37,9 @@
*/
#import <Cocoa/Cocoa.h>
+#import <ApplicationServices/ApplicationServices.h>
[EMAIL PROTECTED] SKFDFParser : NSObject {
- NSDictionary *fdfDictionary;
- NSString *fdfString;
-}
-+ (NSArray *)noteDictionariesFromFDFString:(NSString *)string;
[EMAIL PROTECTED] SKFDFParser : NSObject
++ (NSArray *)noteDictionariesFromFDFData:(NSData *)data;
@end
Modified: trunk/SKFDFParser.m
===================================================================
--- trunk/SKFDFParser.m 2007-09-10 17:09:31 UTC (rev 2879)
+++ trunk/SKFDFParser.m 2007-09-10 17:10:16 UTC (rev 2880)
@@ -44,767 +44,285 @@
@interface SKFDFParser (SKPrivate)
-- (id)initWithString:(NSString *)aString;
-- (BOOL)parseFDFString;
-- (NSArray *)noteDictionaries;
-- (NSDictionary *)noteDictionary:(NSDictionary *)dict;
-- (id)value:(id)value ofClass:(Class)aClass;
-- (NSString *)stringValue:(id)value;
-- (NSNumber *)numberValue:(id)value;
-- (NSArray *)arrayValue:(id)value;
-- (NSDictionary *)dictionaryValue:(id)value;
++ (NSDictionary *)noteDictionaryFromPDFDictionary:(CGPDFDictionaryRef)annot;
@end
[EMAIL PROTECTED] NSScanner (SKFDFParserExtensions)
-- (BOOL)scanFDFObject:(id *)object;
-- (BOOL)scanFDFArray:(NSArray **)array;
-- (BOOL)scanFDFDictionary:(NSDictionary **)dictionary;
-- (BOOL)scanFDFString:(NSString **)string;
-- (BOOL)scanFDFHexString:(NSString **)string;
-- (BOOL)scanFDFName:(NSString **)string;
-- (BOOL)scanFDFNumber:(NSNumber **)number;
-- (BOOL)scanFDFBoolean:(id *)boolNumber;
-- (BOOL)scanFDFIndirectObject:(id *)object;
-- (BOOL)scanFDFComment:(NSString **)comment;
[EMAIL PROTECTED]
[EMAIL PROTECTED] SKFDFParser
-#pragma mark -
+static const void *getCFDataBytePointer(void *info) { return
CFDataGetBytePtr((CFDataRef)info); }
+static void releaseCFData(void *info) { CFRelease((CFDataRef)info); }
[EMAIL PROTECTED] SKIndirectObject : NSObject <NSCopying> {
- unsigned int objectNumber;
- unsigned int generationNumber;
-}
-+ (id)indirectObjectWithNumber:(unsigned int)objNumber generation:(unsigned
int)genNumber;
-- (id)initWithNumber:(unsigned int)objNumber generation:(unsigned
int)genNumber;
-- (unsigned int)objectNumber;
-- (unsigned int)generationNumber;
[EMAIL PROTECTED]
++ (NSArray *)noteDictionariesFromFDFData:(NSData *)data {
+ const char *pdfHeader = "%PDF";
+ unsigned pdfHeaderLength = strlen(pdfHeader);
+
+ if ([data length] < pdfHeaderLength)
+ return NO;
+
+ NSMutableData *pdfData = [data mutableCopy];
+
+ [pdfData replaceBytesInRange:NSMakeRange(0, pdfHeaderLength)
withBytes:pdfHeader length:pdfHeaderLength];
-#pragma mark -
-
[EMAIL PROTECTED] SKFDFParser
-
-+ (NSArray *)noteDictionariesFromFDFString:(NSString *)string {
- NSArray *notes = nil;
- SKFDFParser *parser = [[self alloc] initWithString:string];
+ static const CGDataProviderDirectAccessCallbacks callbacks =
{&getCFDataBytePointer, NULL, NULL, &releaseCFData };
+ void *info = (void *)pdfData;
+ CGDataProviderRef provider = CGDataProviderCreateDirectAccess(info,
[pdfData length], &callbacks);
+ CGPDFDocumentRef document = CGPDFDocumentCreateWithProvider(provider);
+ NSMutableArray *notes = nil;
- if ([parser parseFDFString])
- notes = [parser noteDictionaries];
- [parser release];
+ if (document) {
+ CGPDFDictionaryRef catalog = CGPDFDocumentGetCatalog(document);
+ CGPDFDictionaryRef fdfDict;
+ CGPDFArrayRef annots;
+
+ if (catalog &&
+ CGPDFDictionaryGetDictionary(catalog, "FDF", &fdfDict) &&
+ CGPDFDictionaryGetArray(fdfDict, "Annots", &annots)) {
+
+ size_t i, count = CGPDFArrayGetCount(annots);
+ notes = [NSMutableArray arrayWithCapacity:count];
+ for (i = 0; i < count; i++) {
+ CGPDFDictionaryRef annot;
+ NSDictionary *note;
+ if (CGPDFArrayGetDictionary(annots, i, &annot) &&
+ (note = [self noteDictionaryFromPDFDictionary:annot])) {
+ [notes addObject:note];
+ }
+ }
+ }
+
+ CGPDFDocumentRelease(document);
+ }
+ CGDataProviderRelease(provider);
+ [pdfData release];
+
return notes;
}
-- (id)initWithString:(NSString *)string {
- if (self = [super init]) {
- fdfString = [string retain];
- fdfDictionary = nil;
- }
- return self;
-}
-
-- (void)dealloc {
- [fdfString release];
- [fdfDictionary release];
- [super dealloc];
-}
-
-- (BOOL)parseFDFString {
- NSMutableDictionary *fdfDict = [[NSMutableDictionary alloc] init];
++ (NSDictionary *)noteDictionaryFromPDFDictionary:(CGPDFDictionaryRef)annot {
+ if (annot == NULL)
+ return nil;
- NSDictionary *dictionary;
- int objNumber, genNumber;
- id object;
+ NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+ CGPDFDictionaryRef dict;
+ CGPDFArrayRef array;
+ CGPDFStringRef string;
+ const char *name;
+ CGPDFReal real;
+ CGPDFInteger integer;
BOOL success = YES;
- NSScanner *scanner = [[NSScanner alloc] initWithString:fdfString];
+ if (CGPDFDictionaryGetName(annot, "Type", &name) == NO || strcmp(name,
"Annot") != 0) {
+ success = NO;
+ }
- // Scan the FDF header
- [scanner scanString:@"%FDF-1.2" intoString:NULL];
- while ([scanner scanFDFComment:NULL]);
+ if (CGPDFDictionaryGetName(annot, "Subtype", &name)) {
+ [dictionary setObject:[NSString stringWithFormat:@"%s", name]
forKey:@"type"];
+ } else {
+ success = NO;
+ }
- // Scan the FDF body
- while (success && [scanner scanInt:&objNumber]) {
- while ([scanner scanFDFComment:NULL]);
- if (success = [scanner scanInt:&genNumber]) {
- while ([scanner scanFDFComment:NULL]);
- if (success = [scanner scanString:@"obj" intoString:NULL] &&
[scanner scanFDFObject:&object]) {
- while ([scanner scanFDFComment:NULL]);
- if ([object isKindOfClass:[NSDictionary class]] && [scanner
scanString:@"stream" intoString:NULL]) {
- object = @"";
- if ([scanner scanUpToString:@"endstream"
intoString:&object] && [scanner scanString:@"endstream" intoString:NULL]) {
- int end = [object length];
- unichar ch = end ? [object characterAtIndex:end - 1] :
0;
- if ([[NSCharacterSet newlineCharacterSet]
characterIsMember:ch]) {
- end--;
- if (end && ch == '\n' && [object
characterAtIndex:end - 1] == '\r')
- end--;
- object = [object substringToIndex:end];
- }
- }
- }
- if (success) {
- success = [scanner scanString:@"endobj" intoString:NULL];
- while ([scanner scanFDFComment:NULL]);
- [fdfDict setObject:object forKey:[SKIndirectObject
indirectObjectWithNumber:objNumber generation:genNumber]];
- }
- }
+ if (CGPDFDictionaryGetArray(annot, "Rect", &array)) {
+ CGPDFReal l, b, r, t;
+ if (CGPDFArrayGetCount(array) == 4 && CGPDFArrayGetNumber(array, 0,
&l) && CGPDFArrayGetNumber(array, 1, &b) && CGPDFArrayGetNumber(array, 2, &r)
&& CGPDFArrayGetNumber(array, 3, &t)) {
+ [dictionary setObject:NSStringFromRect(NSMakeRect(l, b, r - l, t -
b)) forKey:@"bounds"];
}
+ } else {
+ success = NO;
}
- // Scan the FDF cross reference table, if present
- if (success) {
- while ([scanner scanString:@"xref" intoString:NULL]) {
- while ([scanner scanFDFComment:NULL]);
- while ([scanner scanInt:NULL] && [scanner scanInt:NULL]) {
- [scanner scanString:@"n" intoString:NULL] || [scanner
scanString:@"f" intoString:NULL];
- while ([scanner scanFDFComment:NULL]);
- }
- }
+ if (CGPDFDictionaryGetInteger(annot, "Page", &integer)) {
+ [dictionary setObject:[NSNumber numberWithInt:integer]
forKey:@"pageIndex"];
+ } else {
+ success = NO;
}
- // Scan the FDF trailer
- if (success = success && [scanner scanString:@"trailer" intoString:NULL]) {
- while ([scanner scanFDFComment:NULL]);
- if (success = [scanner scanFDFDictionary:&dictionary]) {
- while ([scanner scanFDFComment:NULL]);
- [fdfDict setObject:dictionary forKey:@"trailer"];
- [scanner scanString:@"%%EOF" intoString:NULL];
+ if (CGPDFDictionaryGetString(annot, "Contents", &string)) {
+ NSString *contents = (NSString *)CGPDFStringCopyTextString(string);
+ if (contents)
+ [dictionary setObject:contents forKey:@"contents"];
+ [contents release];
+ }
+
+ if (CGPDFDictionaryGetArray(annot, "C", &array)) {
+ CGPDFReal r, g, b;
+ if (CGPDFArrayGetCount(array) == 3 && CGPDFArrayGetNumber(array, 0,
&r) && CGPDFArrayGetNumber(array, 1, &g) && CGPDFArrayGetNumber(array, 2, &b)) {
+ [dictionary setObject:[NSColor colorWithCalibratedRed:r green:g
blue:b alpha:1.0] forKey:@"color"];
}
}
- [scanner release];
-
- if (success)
- fdfDictionary = fdfDict;
- else
- [fdfDict release];
-
- return success;
-}
-
-- (NSArray *)noteDictionaries {
- NSMutableArray *array = nil;
- NSDictionary *trailer;
- NSDictionary *root;
- NSDictionary *fdfDict;
- NSArray *annots;
-
- if ((trailer = [self dictionaryValue:[fdfDictionary
objectForKey:@"trailer"]]) &&
- (root = [self dictionaryValue:[trailer objectForKey:@"Root"]]) &&
- (fdfDict = [self dictionaryValue:[root objectForKey:@"FDF"]]) &&
- (annots = [self arrayValue:[fdfDict objectForKey:@"Annots"]])) {
-
- NSEnumerator *annotEnum = [annots objectEnumerator];
- NSDictionary *dict;
-
- array = [NSMutableArray arrayWithCapacity:[annots count]];
- while (dict = [annotEnum nextObject]) {
- if (dict = [self noteDictionary:[self dictionaryValue:dict]])
- [array addObject:dict];
+ if (CGPDFDictionaryGetArray(annot, "IC", &array)) {
+ CGPDFReal r, g, b;
+ if (CGPDFArrayGetCount(array) == 3 && CGPDFArrayGetNumber(array, 0,
&r) && CGPDFArrayGetNumber(array, 1, &g) && CGPDFArrayGetNumber(array, 2, &b)) {
+ [dictionary setObject:[NSColor colorWithCalibratedRed:r green:g
blue:b alpha:1.0] forKey:@"interiorColor"];
}
}
- return array;
-}
-
-- (id)value:(id)value ofClass:(Class)aClass {
- while ([value isKindOfClass:[SKIndirectObject class]])
- value = [fdfDictionary objectForKey:value];
- return (aClass == Nil || [value isKindOfClass:aClass]) ? value : nil;
-}
-
-- (NSString *)stringValue:(id)value {
- return [self value:value ofClass:[NSString class]];
-}
-
-- (NSNumber *)numberValue:(id)value {
- return [self value:value ofClass:[NSNumber class]];
-}
-
-- (NSArray *)arrayValue:(id)value {
- return [self value:value ofClass:[NSArray class]];
-}
-
-- (NSDictionary *)dictionaryValue:(id)value {
- return [self value:value ofClass:[NSDictionary class]];
-}
-
-- (NSDictionary *)noteDictionary:(NSDictionary *)dict {
- NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
- NSSet *validTypes = [NSSet setWithObjects:@"FreeText", @"Note", @"Circle",
@"Square", @"Highlight", @"Underline", @"StrikeOut", @"Line", nil];
- NSEnumerator *keyEnum = [dict keyEnumerator];
- NSString *key;
- BOOL success = dict != nil;
-
- while (success && (key = [keyEnum nextObject])) {
- id value = [dict valueForKey:key];
-
- if ([key isEqualToString:@"Type"]) {
- if (value = [self stringValue:value]) {
- if ([value isEqualToString:@"Annot"] == NO) {
- success = NO;
+ if (CGPDFDictionaryGetDictionary(annot, "BS", &dict)) {
+ if (CGPDFDictionaryGetNumber(dict, "W", &real)) {
+ if (real > 0.0) {
+ [dictionary setObject:[NSNumber numberWithFloat:real]
forKey:@"lineWidth"];
+ if (CGPDFDictionaryGetName(dict, "S", &name)) {
+ int style = kPDFBorderStyleSolid;
+ if (strcmp(name, "S") == 0)
+ style = kPDFBorderStyleSolid;
+ else if (strcmp(name, "D") == 0)
+ style = kPDFBorderStyleDashed;
+ else if (strcmp(name, "B") == 0)
+ style = kPDFBorderStyleBeveled;
+ else if (strcmp(name, "I") == 0)
+ style = kPDFBorderStyleInset;
+ else if (strcmp(name, "U") == 0)
+ style = kPDFBorderStyleUnderline;
+ [dictionary setObject:[NSNumber numberWithInt:style]
forKey:@"borderStyle"];
}
- } else {
- success = NO;
- }
- } else if ([key isEqualToString:@"Subtype"]) {
- if (value = [self stringValue:value]) {
- if ([value isEqualToString:@"Text"])
- value = @"Note";
- if ([validTypes containsObject:value]) {
- [dictionary setObject:value forKey:@"type"];
- } else {
- success = NO;
+ if (CGPDFDictionaryGetArray(annot, "D", &array)) {
+ size_t i, count = CGPDFArrayGetCount(array);
+ NSMutableArray *dp = [NSMutableArray array];
+ for (i = 0; i < count; i++) {
+ if (CGPDFArrayGetNumber(array, i, &real))
+ [dp addObject:[NSNumber numberWithFloat:real]];
+ }
+ [dictionary setObject:dp forKey:@"dashPattern"];
}
- } else {
- success = NO;
}
- } else if ([key isEqualToString:@"Contents"]) {
- if (value = [self stringValue:value]) {
- [dictionary setObject:value forKey:@"contents"];
- } else {
- success = NO;
- }
- } else if ([key isEqualToString:@"Rect"]) {
- if ((value = [self arrayValue:value]) && [value count] == 4) {
- NSNumber *l = [self numberValue:[value objectAtIndex:0]];
- NSNumber *b = [self numberValue:[value objectAtIndex:1]];
- NSNumber *r = [self numberValue:[value objectAtIndex:2]];
- NSNumber *t = [self numberValue:[value objectAtIndex:3]];
- if (l && b && r && t) {
- NSRect rect;
- rect.origin.x = [l floatValue];
- rect.origin.y = [b floatValue];
- rect.size.width = [r floatValue] - NSMinX(rect);
- rect.size.height = [t floatValue] - NSMinY(rect);
- [dictionary setObject:NSStringFromRect(rect)
forKey:@"bounds"];
- } else {
- success = NO;
+ }
+ } else if (CGPDFDictionaryGetArray(annot, "Border", &array)) {
+ size_t i, count = CGPDFArrayGetCount(array);
+ if (count > 2 && CGPDFArrayGetNumber(array, 2, &real) && real > 0.0) {
+ [dictionary setObject:[NSNumber numberWithFloat:real]
forKey:@"lineWidth"];
+ CGPDFArrayRef dp;
+ if (count > 3 && CGPDFArrayGetArray(array, 3, &dp)) {
+ count = CGPDFArrayGetCount(dp);
+ NSMutableArray *dashPattern = [NSMutableArray
arrayWithCapacity:count];
+ for (i = 0; i < count; i++) {
+ if (CGPDFArrayGetNumber(dp, i, &real))
+ [dashPattern addObject:[NSNumber
numberWithFloat:real]];
}
+ [dictionary setObject:dashPattern forKey:@"dashPattern"];
+ [dictionary setObject:[NSNumber
numberWithInt:kPDFBorderStyleDashed] forKey:@"borderStyle"];
} else {
- success = NO;
+ [dictionary setObject:[NSNumber
numberWithInt:kPDFBorderStyleSolid] forKey:@"borderStyle"];
}
- } else if ([key isEqualToString:@"Page"]) {
- if (value = [self numberValue:value]) {
- [dictionary setObject:value forKey:@"pageIndex"];
- } else {
- success = NO;
- }
- } else if ([key isEqualToString:@"C"]) {
- if ((value = [self arrayValue:value]) && [value count] == 3) {
- NSNumber *r = [self numberValue:[value objectAtIndex:0]];
- NSNumber *g = [self numberValue:[value objectAtIndex:1]];
- NSNumber *b = [self numberValue:[value objectAtIndex:2]];
- if (r && g && b) {
- [dictionary setObject:[NSColor colorWithCalibratedRed:[r
floatValue] green:[g floatValue] blue:[b floatValue] alpha:1.0]
forKey:@"color"];
- } else {
- success = NO;
- }
- } else {
- success = NO;
- }
- } else if ([key isEqualToString:@"BS"]) {
- if (value = [self dictionaryValue:value]) {
- NSNumber *width = [self numberValue:[value objectForKey:@"W"]];
- NSString *s = [self stringValue:[value objectForKey:@"S"]];
- NSArray *dashPattern = [self arrayValue:[value
objectForKey:@"D"]];
- int style = kPDFBorderStyleSolid;
- if ([s isEqualToString:@"S"])
- style = kPDFBorderStyleSolid;
- else if ([s isEqualToString:@"D"])
- style = kPDFBorderStyleDashed;
- else if ([s isEqualToString:@"B"])
- style = kPDFBorderStyleBeveled;
- else if ([s isEqualToString:@"I"])
- style = kPDFBorderStyleInset;
- else if ([s isEqualToString:@"U"])
- style = kPDFBorderStyleUnderline;
- if (width && [width floatValue] > 0.0) {
- [dictionary setObject:width forKey:@"lineWidth"];
- [dictionary setObject:[NSNumber numberWithInt:style]
forKey:@"borderStyle"];
- if (dashPattern)
- [dictionary setObject:dashPattern
forKey:@"dashPattern"];
- }
- } else {
- success = NO;
- }
- } else if ([key isEqualToString:@"Border"]) {
- if ([value isKindOfClass:[NSArray class]] == NO) {
- success = NO;
- break;
- }
- NSNumber *width = [value count] > 2 ? [self numberValue:[value
objectAtIndex:2]] : nil;
- NSArray *dashPattern = [value count] > 3 ? [self arrayValue:[value
objectAtIndex:2]] : nil;
- if (width && [width floatValue] > 0.0) {
- [dictionary setObject:width forKey:@"lineWidth"];
- [dictionary setObject:[NSNumber numberWithInt:dashPattern ?
kPDFBorderStyleDashed : kPDFBorderStyleSolid] forKey:@"borderStyle"];
- if (dashPattern)
- [dictionary setObject:dashPattern forKey:@"dashPattern"];
- }
- } else if ([key isEqualToString:@"Name"]) {
- if (value = [self stringValue:value]) {
- int icon = kPDFTextAnnotationIconNote;
- if ([value isEqualToString:@"Comment"])
- icon = kPDFTextAnnotationIconComment;
- else if ([value isEqualToString:@"Key"])
- icon = kPDFTextAnnotationIconKey;
- else if ([value isEqualToString:@"Note"])
- icon = kPDFTextAnnotationIconNote;
- else if ([value isEqualToString:@"NewParagraph"])
- icon = kPDFTextAnnotationIconNewParagraph;
- else if ([value isEqualToString:@"Paragraph"])
- icon = kPDFTextAnnotationIconParagraph;
- else if ([value isEqualToString:@"Insert"])
- icon = kPDFTextAnnotationIconInsert;
- [dictionary setObject:[NSNumber numberWithInt:icon]
forKey:@"iconType"];
- } else {
- success = NO;
- }
- } else if ([key isEqualToString:@"IC"]) {
- if ((value = [self arrayValue:value]) && [value count] == 3) {
- NSNumber *r = [self numberValue:[value objectAtIndex:0]];
- NSNumber *g = [self numberValue:[value objectAtIndex:1]];
- NSNumber *b = [self numberValue:[value objectAtIndex:2]];
- if (r && g && b) {
- [dictionary setObject:[NSColor colorWithCalibratedRed:[r
floatValue] green:[g floatValue] blue:[b floatValue] alpha:1.0]
forKey:@"interiorColor"];
- } else {
- success = NO;
- }
- } else {
- success = NO;
- }
- } else if ([key isEqualToString:@"LE"]) {
- if ((value = [self arrayValue:value]) && [value count] == 2) {
- NSString *start = [self stringValue:[value objectAtIndex:0]];
- NSString *end = [self stringValue:[value objectAtIndex:1]];
- int startStyle = kPDFLineStyleNone;
- int endStyle = kPDFLineStyleNone;
- if ([start isEqualToString:@"None"])
+ }
+ }
+
+ if (CGPDFDictionaryGetName(annot, "Name", &name)) {
+ int icon = kPDFTextAnnotationIconNote;
+ if (strcmp(name, "Comment") == 0)
+ icon = kPDFTextAnnotationIconComment;
+ else if (strcmp(name, "Key") == 0)
+ icon = kPDFTextAnnotationIconKey;
+ else if (strcmp(name, "Note") == 0)
+ icon = kPDFTextAnnotationIconNote;
+ else if (strcmp(name, "NewParagraph") == 0)
+ icon = kPDFTextAnnotationIconNewParagraph;
+ else if (strcmp(name, "Paragraph") == 0)
+ icon = kPDFTextAnnotationIconParagraph;
+ else if (strcmp(name, "Insert") == 0)
+ icon = kPDFTextAnnotationIconInsert;
+ [dictionary setObject:[NSNumber numberWithInt:icon]
forKey:@"iconType"];
+ }
+
+ if (CGPDFDictionaryGetArray(annot, "LE", &array)) {
+ int startStyle = kPDFLineStyleNone;
+ int endStyle = kPDFLineStyleNone;
+ if (CGPDFArrayGetCount(array) == 2) {
+ if (CGPDFArrayGetName(array, 0, &name)) {
+ if (strcmp(name, "None") == 0)
startStyle = kPDFLineStyleNone;
- else if ([start isEqualToString:@"Square"])
+ else if (strcmp(name, "Square") == 0)
startStyle = kPDFLineStyleSquare;
- else if ([start isEqualToString:@"Circle"])
+ else if (strcmp(name, "Circle") == 0)
startStyle = kPDFLineStyleCircle;
- else if ([start isEqualToString:@"Diamond"])
+ else if (strcmp(name, "Diamond") == 0)
startStyle = kPDFLineStyleDiamond;
- else if ([start isEqualToString:@"OpenArrow"])
+ else if (strcmp(name, "OpenArrow") == 0)
startStyle = kPDFLineStyleOpenArrow;
- else if ([start isEqualToString:@"ClosedArrow"])
+ else if (strcmp(name, "ClosedArrow") == 0)
startStyle = kPDFLineStyleClosedArrow;
- if ([end isEqualToString:@"None"])
+ }
+ if (CGPDFArrayGetName(array, 1, &name)) {
+ if (strcmp(name, "None") == 0)
startStyle = kPDFLineStyleNone;
- else if ([end isEqualToString:@"Square"])
+ else if (strcmp(name, "Square") == 0)
endStyle = kPDFLineStyleSquare;
- else if ([end isEqualToString:@"Circle"])
+ else if (strcmp(name, "Circle") == 0)
endStyle = kPDFLineStyleCircle;
- else if ([end isEqualToString:@"Diamond"])
+ else if (strcmp(name, "Diamond") == 0)
endStyle = kPDFLineStyleDiamond;
- else if ([end isEqualToString:@"OpenArrow"])
+ else if (strcmp(name, "OpenArrow") == 0)
endStyle = kPDFLineStyleOpenArrow;
- else if ([end isEqualToString:@"ClosedArrow"])
+ else if (strcmp(name, "ClosedArrow") == 0)
endStyle = kPDFLineStyleClosedArrow;
- [dictionary setObject:[NSNumber numberWithInt:startStyle]
forKey:@"startLineStyle"];
- [dictionary setObject:[NSNumber numberWithInt:endStyle]
forKey:@"endLineStyle"];
- } else {
- success = NO;
}
- } else if ([key isEqualToString:@"QuadPoints"]) {
- if ((value = [self arrayValue:value]) && [value count] % 8 == 0) {
- NSMutableArray *quadPoints = [NSMutableArray array];
- int i, count = [value count];
- for (i = 0; i < count; i++) {
- NSPoint point;
- point.x = [[value objectAtIndex:i] floatValue];
- point.y = [[value objectAtIndex:++i] floatValue];
+ }
+ [dictionary setObject:[NSNumber numberWithInt:endStyle]
forKey:@"endLineStyle"];
+ [dictionary setObject:[NSNumber numberWithInt:startStyle]
forKey:@"startLineStyle"];
+ }
+
+ if (CGPDFDictionaryGetArray(annot, "QuadPoints", &array)) {
+ size_t i, count = CGPDFArrayGetCount(array);
+ if (i % 8 == 0) {
+ NSMutableArray *quadPoints = [NSMutableArray
arrayWithCapacity:count / 2];
+ for (i = 0; i < count; i++) {
+ NSPoint point;
+ if (CGPDFArrayGetNumber(array, i, &point.x) &&
CGPDFArrayGetNumber(array, i, &point.y))
[quadPoints addObject:NSStringFromPoint(point)];
- }
- [dictionary setObject:quadPoints
forKey:@"quadrilateralPoints"];
- } else {
- success = NO;
}
- } else if ([key isEqualToString:@"DA"]) {
- if (value = [self stringValue:value]) {
- NSScanner *scanner = [NSScanner scannerWithString:value];
- NSString *fontName;
- float fontSize;
- if ([scanner scanUpToString:@"Tf" intoString:NULL] && [scanner
isAtEnd] == NO) {
- unsigned location = [scanner scanLocation];
- NSRange r = [value rangeOfString:@"/"
options:NSBackwardsSearch range:NSMakeRange(0, location)];
- if (r.location != NSNotFound) {
- [scanner setScanLocation:NSMaxRange(r)];
- if ([scanner scanCharactersFromSet:[NSCharacterSet
nonWhitespaceAndNewlineCharacterSet] intoString:&fontName] &&
- [scanner scanFloat:&fontSize] &&
- [scanner scanString:@"Tf" intoString:NULL] &&
- [scanner scanLocation] == location + 2) {
- NSFont *font = [NSFont fontWithName:fontName
size:fontSize];
- if (font == nil) {
- fontName = [[NSUserDefaults
standardUserDefaults] stringForKey:SKTextNoteFontNameKey];
- font = [NSFont fontWithName:fontName
size:fontSize];
- }
- if (font)
- [dictionary setObject:font forKey:@"font"];
- }
- }
- }
- }
+ [dictionary setObject:quadPoints forKey:@"quadrilateralPoints"];
}
}
+ if (CGPDFDictionaryGetString(annot, "DA", &string)) {
+ NSString *da = (NSString *)CGPDFStringCopyTextString(string);
+ if (da) {
+ NSScanner *scanner = [NSScanner scannerWithString:da];
+ NSString *fontName;
+ float fontSize;
+ if ([scanner scanUpToString:@"Tf" intoString:NULL] && [scanner
isAtEnd] == NO) {
+ unsigned location = [scanner scanLocation];
+ NSRange r = [da rangeOfString:@"/" options:NSBackwardsSearch
range:NSMakeRange(0, location)];
+ if (r.location != NSNotFound) {
+ [scanner setScanLocation:NSMaxRange(r)];
+ if ([scanner scanCharactersFromSet:[NSCharacterSet
nonWhitespaceAndNewlineCharacterSet] intoString:&fontName] &&
+ [scanner scanFloat:&fontSize] &&
+ [scanner scanString:@"Tf" intoString:NULL] &&
+ [scanner scanLocation] == location + 2) {
+ NSFont *font = [NSFont fontWithName:fontName
size:fontSize];
+ if (font == nil) {
+ fontName = [[NSUserDefaults standardUserDefaults]
stringForKey:SKTextNoteFontNameKey];
+ font = [NSFont fontWithName:fontName
size:fontSize];
+ }
+ if (font)
+ [dictionary setObject:font forKey:@"font"];
+ }
+ }
+ }
+ [da release];
+ }
+ }
+
+ NSSet *validTypes = [NSSet setWithObjects:@"FreeText", @"Note", @"Circle",
@"Square", @"Highlight", @"Underline", @"StrikeOut", @"Line", nil];
NSString *type = [dictionary objectForKey:@"type"];
NSString *contents;
- if ([type isEqualToString:@"Note"]) {
+ if ([type isEqualToString:@"Text"]) {
+ [dictionary setObject:@"Note" forKey:@"type"];
if (contents = [dictionary objectForKey:@"contents"]) {
unsigned contentsEnd, end;
[contents getLineStart:NULL end:&end contentsEnd:&contentsEnd
forRange:NSMakeRange(0, 0)];
- if (end < [contents length]) {
+ if (contentsEnd < end) {
[dictionary setObject:[contents substringToIndex:contentsEnd]
forKey:@"contents"];
- [dictionary setObject:[[[NSAttributedString alloc]
initWithString:[contents substringFromIndex:end]] autorelease] forKey:@"text"];
+ if (end < [contents length])
+ [dictionary setObject:[[[NSAttributedString alloc]
initWithString:[contents substringFromIndex:end]] autorelease] forKey:@"text"];
}
}
+ } else if ([validTypes containsObject:type] == NO) {
+ success = NO;
}
return success ? dictionary : nil;
}
@end
-
-#pragma mark -
-
[EMAIL PROTECTED] NSScanner (SKFDFParserExtensions)
-
-- (BOOL)scanFDFObject:(id *)object {
- id tmpObject = nil;
- BOOL success;
-
- while ([self scanFDFComment:NULL]);
-
- success = [self scanFDFName:&tmpObject] ||
- [self scanFDFArray:&tmpObject] ||
- [self scanFDFDictionary:&tmpObject] ||
- [self scanFDFString:&tmpObject] ||
- [self scanFDFHexString:&tmpObject] ||
- [self scanFDFIndirectObject:&tmpObject] ||
- [self scanFDFNumber:&tmpObject] ||
- [self scanFDFBoolean:&tmpObject] ||
- [self scanString:@"null" intoString:NULL];
-
- if (success && object)
- *object = tmpObject;
-
- return success;
-}
-
-- (BOOL)scanFDFArray:(NSArray **)array {
- NSMutableArray *tmpArray = [NSMutableArray array];
- id object;
- BOOL success = [self scanString:@"[" intoString:NULL];
-
- while (success) {
- while ([self scanFDFComment:NULL]);
- if ([self scanString:@"]" intoString:NULL]) {
- break;
- } else if (success = [self scanFDFObject:&object]) {
- if (object)
- [tmpArray addObject:object];
- }
- }
-
- if (success && array)
- *array = tmpArray;
-
- return success;
-}
-
-- (BOOL)scanFDFDictionary:(NSDictionary **)dictionary {
- NSMutableDictionary *tmpDict = [NSMutableDictionary dictionary];
- NSString *key;
- id object;
- BOOL success = [self scanString:@"<<" intoString:NULL];
-
- while (success) {
- while ([self scanFDFComment:NULL]);
- if ([self scanString:@">>" intoString:NULL]) {
- break;
- } else if (success = ([self scanFDFName:&key] && [self
scanFDFObject:&object])) {
- if (object)
- [tmpDict setObject:object forKey:key];
- }
- }
-
- if (success && dictionary)
- *dictionary = tmpDict;
-
- return success;
-}
-
-- (BOOL)scanFDFString:(NSString **)string {
- static NSCharacterSet *specialCharSet = nil;
- if (specialCharSet == nil)
- specialCharSet = [[NSCharacterSet
characterSetWithCharactersInString:@"\\)"] retain];
-
- static NSCharacterSet *octalCharSet = nil;
- if (octalCharSet == nil)
- octalCharSet = [[NSCharacterSet
characterSetWithCharactersInString:@"01234567"] retain];
-
- NSMutableString *tmpString = [NSMutableString string];
- NSString *s;
- unichar ch;
- BOOL success;
-
- if (success = [self scanString:@"(" intoString:NULL]) {
- NSCharacterSet *skipChars = [[self charactersToBeSkipped] retain];
- [self setCharactersToBeSkipped:nil];
-
- while (success) {
- if ([self scanUpToCharactersFromSet:specialCharSet intoString:&s])
- [tmpString appendString:s];
- if ([self scanCharacter:&ch]) {
- if (ch == ')') {
- break;
- } else if (ch == '\\') {
- if ([self scanCharacter:&ch]) {
- if (ch == 'n') {
- [tmpString appendString:@"\n"];
- } else if (ch == 'r') {
- [tmpString appendString:@"\r"];
- } else if (ch == 't') {
- [tmpString appendString:@"\r"];
- } else if (ch == 'b') {
- [tmpString appendString:@"\b"];
- } else if (ch == 'f') {
- [tmpString appendString:@"\f"];
- } else if (ch == '(') {
- [tmpString appendString:@"("];
- } else if (ch == ')') {
- [tmpString appendString:@")"];
- } else if (ch == '\\') {
- [tmpString appendString:@"\\"];
- } else if ([octalCharSet characterIsMember:ch]) {
- char octal = ch;
- if ([self peekCharacter:&ch] && [octalCharSet
characterIsMember:ch]) {
- [self scanCharacter:NULL];
- octal = 8 * octal + ch;
- if ([self peekCharacter:&ch] && [octalCharSet
characterIsMember:ch]) {
- [self scanCharacter:NULL];
- octal = 8 * octal + ch;
- }
- }
- NSString *s = [[NSString alloc]
initWithBytes:&octal length:1 encoding:NSISOLatin1StringEncoding];
- if (success = s != nil)
- [tmpString appendString:s];
- [s release];
- } else if ([[NSCharacterSet newlineCharacterSet]
characterIsMember:ch]) {
- if (ch == '\r')
- [self scanString:@"\n" intoString:NULL];
- } else {
- [self setScanLocation:[self scanLocation] - 1];
- }
- } else {
- success = NO;
- }
- }
- } else {
- success = NO;
- }
- }
-
- [self setCharactersToBeSkipped:skipChars];
- [skipChars release];
- }
-
- if (success && string)
- *string = tmpString;
-
- return success;
-}
-
-static inline int hexCharacterNumber(unichar ch) {
- if (ch >= '0' && ch <= '9')
- return ch - '0';
- if (ch >= 'A' && ch <= 'F')
- return ch - 'A' + 10;
- if (ch >= 'a' && ch <= 'f')
- return ch - 'a' + 10;
- return 0;
-}
-
-- (BOOL)scanFDFHexString:(NSString **)string {
- static NSCharacterSet *hexCharSet = nil;
- if (hexCharSet == nil)
- hexCharSet = [[NSCharacterSet
characterSetWithCharactersInString:@"0123456789abcdefABCDEF"] retain];
-
- int rewindLoc = [self scanLocation];
- NSString *hexString = nil;
- unichar ch;
- char hexChar;
- char *bytes = NULL;
- int length = 0;
- BOOL isFirst = YES;
- BOOL done = NO;
- BOOL success = [self scanString:@"<" intoString:NULL];
-
- while (done == NO && success && (success = [self scanCharacter:&ch])) {
- hexChar = 0;
- if ([hexCharSet characterIsMember:ch]) {
- hexChar += hexCharacterNumber(ch);
- } else if (ch == '>') {
- done = YES;
- } else {
- success = NO;
- }
- if (isFirst) {
- hexChar *= 16;
- } else {
- length++;
- bytes = NSZoneRealloc([self zone], bytes, length * sizeof(char));
- bytes[length - 1] = hexChar;
- hexChar = 0;
- }
- isFirst = !isFirst;
- }
-
- if (success) {
- hexString = length == 0 ? @"" : [[[NSString alloc] initWithBytes:bytes
length:length encoding:NSISOLatin1StringEncoding] autorelease];
- success = hexString != nil;
- }
-
- if (bytes)
- NSZoneFree([self zone], bytes);
-
- if (success == NO)
- [self setScanLocation:rewindLoc];
-
- if (success && string)
- *string = hexString;
-
- return success;
-}
-
-- (BOOL)scanFDFName:(NSString **)string {
- static NSCharacterSet *whitespaceOrDelimiterCharSet = nil;
- if (whitespaceOrDelimiterCharSet == nil) {
- NSMutableCharacterSet *tmpSet = [[NSCharacterSet
whitespaceAndNewlineCharacterSet] mutableCopy];
- [tmpSet addCharactersInString:@"()<>[]{}/%"];
- whitespaceOrDelimiterCharSet = [tmpSet copy];
- [tmpSet release];
- }
-
- BOOL success;
-
- if (success = [self scanString:@"/" intoString:NULL]) {
- NSCharacterSet *skipChars = [[self charactersToBeSkipped] retain];
- [self setCharactersToBeSkipped:nil];
- success = [self
scanUpToCharactersFromSet:whitespaceOrDelimiterCharSet intoString:string];
- [self setCharactersToBeSkipped:skipChars];
- [skipChars release];
- }
-
- return success;
-}
-
-- (BOOL)scanFDFNumber:(NSNumber **)number {
- float f;
- BOOL success = [self scanFloat:&f];
-
- if (success && number)
- *number = [NSNumber numberWithFloat:f];
-
- return success;
-}
-
-- (BOOL)scanFDFBoolean:(id *)boolNumber {
- NSNumber *tmpBoolNumber = nil;
- BOOL success;
-
- if (success = [self scanString:@"true" intoString:NULL])
- tmpBoolNumber = [NSNumber numberWithBool:YES];
- else if (success = [self scanString:@"false" intoString:NULL])
- tmpBoolNumber = [NSNumber numberWithBool:NO];
-
- if (success && boolNumber)
- *boolNumber = tmpBoolNumber;
-
- return success;
-}
-
-- (BOOL)scanFDFIndirectObject:(id *)object {
- int rewindLoc = [self scanLocation];
- id tmpObject;
- int objNumber, genNumber;
- BOOL success;
-
- if (success = [self scanInt:&objNumber] && [self scanInt:&genNumber] &&
[self scanString:@"R" intoString:NULL]) {
- tmpObject = [SKIndirectObject indirectObjectWithNumber:objNumber
generation:genNumber];
- } else {
- [self setScanLocation:rewindLoc];
- }
-
- if (success && object)
- *object = tmpObject;
-
- return success;
-}
-
-- (BOOL)scanFDFComment:(NSString **)comment {
- NSString *tmpComment = @"";
- BOOL success;
-
- if (success = [self scanString:@"%" intoString:NULL]) {
- NSCharacterSet *skipChars = [[self charactersToBeSkipped] retain];
- [self setCharactersToBeSkipped:[NSCharacterSet
whitespaceCharacterSet]];
- [self scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet]
intoString:&tmpComment];
- [self setCharactersToBeSkipped:skipChars];
- [skipChars release];
- }
-
- if (success && comment)
- *comment = tmpComment;
-
- return success;
-}
-
[EMAIL PROTECTED]
-
-#pragma mark -
-
[EMAIL PROTECTED] SKIndirectObject : NSObject
-
-+ (id)indirectObjectWithNumber:(unsigned int)objNumber generation:(unsigned
int)genNumber {
- return [[[self alloc] initWithNumber:objNumber generation:genNumber]
autorelease];
-}
-
-- (id)initWithNumber:(unsigned int)objNumber generation:(unsigned
int)genNumber {
- if (self = [super init]) {
- objectNumber = objNumber;
- generationNumber = genNumber;
- }
- return self;
-}
-
-- (id)copyWithZone:(NSZone *)aZone {
- return [self retain];
-}
-
-- (NSString *)description {
- return [NSString stringWithFormat:@"<%@: %i %i>",[self class],
objectNumber, generationNumber];
-}
-
-- (BOOL)isEqual:(id)other {
- return [self isMemberOfClass:[other class]] && [self objectNumber] ==
[other objectNumber] && [self generationNumber] == [other generationNumber];
-}
-
-- (unsigned int)hash {
- return (objectNumber << 16) | generationNumber;
-}
-
-- (unsigned int)objectNumber {
- return objectNumber;
-}
-
-- (unsigned int)generationNumber {
- return generationNumber;
-}
-
[EMAIL PROTECTED]
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Skim-app-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/skim-app-commit