// // PDFObject.m // PDFKit // // Created by Dr. H. Nikolaus Schaller on Fri Nov 9 2005. // Copyright (c) 2005 DSITRI. All rights reserved. // #import "PDFKitPrivate.h" @implementation NSObject (PDFKit) - (BOOL) isPDFAtom; { return NO; } - (BOOL) isPDFIndirect; { return NO; } - (BOOL) isPDFKeyword; { return NO; } - (BOOL) isPDFKeyword:(NSString *) str; { return NO; } - (NSData *) _PDFDataRepresentation; { NIMP; return nil; } // generic object has no representation @end @implementation NSDictionary (PDFKit) - (id) _objectAtIndexInNameTree:(NSString *) str; { return nil; } - (id) _objectAtIndexInNumberTree:(int) num; { id kid, numObj; NSEnumerator *e; NSArray *nums; #if 0 NSLog(@"_objectAtIndexInNumberTree:%d in %@", num, self); #endif nums=[[self objectForKey:@"Nums"] self]; if(nums) { // this is a leaf tree node #if 0 NSLog(@"Nums=%@", nums); #endif e=[nums objectEnumerator]; // go through all entries while((numObj=[e nextObject])) { #if 0 NSLog(@"numObj=%@", numObj); #endif if([numObj intValue] == num) return [e nextObject]; // value found [e nextObject]; // skip value } return nil; // not found } e=[[[self objectForKey:@"Kids"] self] objectEnumerator]; // go through kids-array while((kid=[[e nextObject] self])) { // find the one where index is within limits NSArray *limits; limits=[[kid objectForKey:@"Limits"] self]; #if 1 NSLog(@"limits=%@", limits); #endif if(num >= [[limits objectAtIndex:0] intValue] && num <= [[limits objectAtIndex:1] intValue]) return [kid _objectAtIndexInNumberTree:num]; // must be in that subnode or its descendants } return nil; // out of range } - (id) _objectAtIndexInPageTree:(unsigned) num ofDocument:(PDFDocument *) doc parentIndex:(unsigned *) idx; { // we must be a tree node id kidRef, kid; unsigned dummy; NSEnumerator *e=[[[self objectForKey:@"Kids"] self] objectEnumerator]; // go through kids-array if(!idx) idx=&dummy; for(*idx=0; (kidRef=[e nextObject]); (*idx)++) { unsigned cnt; kid=[kidRef self]; // fetch and cache if required if([kid isKindOfClass:[PDFPage class]]) { // cached page wrapper if(num == 0) return kid; // yes! num--; // skip continue; } if([[kid objectForKey:@"Type"] isEqualToString:@"Page"]) { // page node if(num == 0) { // wrap NSDictionary in PDFPage object and store in catalog so that we always get this wrapper - even if pages are moved around kid=[[[PDFPage alloc] _initWithDocument:doc andPageDictionary:kid] autorelease]; [kidRef setObject:kid]; return kid; // new wrapper } num--; continue; // try next one } cnt=[[kid objectForKey:@"Count"] unsignedIntValue]; // is a pages node; get total number of leafs if(num < cnt) return [kid _objectAtIndexInPageTree:num ofDocument:doc parentIndex:idx]; // must be in that subnode num-=cnt; // skip cnt entries and try next one } return nil; // out of range } - (unsigned) _treeCount; { // recursively count number of entries in page/number/name tree if([self isKindOfClass:[NSDictionary class]]) { // sum up subnodes unsigned sum=0; NSEnumerator *e; id obj; e=[[[self objectForKey:@"Kids"] self] objectEnumerator]; // enumerates objects/references while((obj=[e nextObject])) sum+=[[obj self] _treeCount]; return sum; } return 1; } - (NSData *) _PDFDataRepresentation; { // glue together return nil; } @end @implementation PDFAtom - (NSString *) description; { return [NSString stringWithFormat:@"/%@", _string]; } - (NSData *) _PDFDataRepresentation; { // glue together return nil; } - (BOOL) isPDFAtom; { return YES; } - (id) initWithString:(NSString *) str; { if((self=[super init])) _string=[str retain]; return self; } - (void) dealloc; { [_string release]; [super dealloc]; } - (NSString *) value; { return _string; } - (BOOL) isEqualToString:(NSString *) str; { return [_string isEqualToString:str]; } @end @implementation PDFKeyword - (NSString *) description; { return [NSString stringWithFormat:@"%@", _string]; } - (BOOL) isPDFAtom; { return NO; } - (BOOL) isPDFKeyword; { return YES; } - (BOOL) isPDFKeyword:(NSString *) str; { return [_string isEqualToString:str]; } @end @implementation PDFReference - (NSData *) _PDFDataRepresentation; { // glue together return nil; } - (NSString *) description; { return [NSString stringWithFormat:@"%u %u R -> %@", ref1, ref2, ref?[ref object]:@"?"]; } + (id) keyForNumber:(unsigned) r1 andGeneration:(unsigned) r2; { // make dictionary hash key return [NSNumber numberWithLong:100000*r1+r2]; } - (BOOL) isPDFIndirect; { return YES; } - (id) initWithNumber:(unsigned) r1 andGeneration:(unsigned) r2 forDocument:(PDFDocument *) doc; // create reference { if((self=[super init])) { // hier gleich den Key generieren und speichern ref1=r1; ref2=r2; data=doc; } return self; } - (void) dealloc; { [ref release]; [super dealloc]; } - (id) self; { // load indirect object (if possible) if(!ref) ref=[[data _catalogEntryForObject:ref1 generation:ref2] retain]; // search in catalog return [ref object]; // get object } - (void) setObject:(id) obj; { // replace referenced object in catalog [ref setObject:obj]; } @end @implementation PDFCrossReference - (id) initWithData:(NSData *) data pos:(unsigned) pos number:(unsigned) num generation:(unsigned) gen isFree:(BOOL) flag; { if((self=[super init])) { // we don't save the number? _data=data; _position=pos; _generation=gen; // why do we save the generation? _isFree=flag; #if 0 NSLog(@"%u(%u): %u%@", num, gen, pos, flag?@" free":@""); #endif } return self; } - (void) dealloc; { [_object release]; [super dealloc]; } - (NSString *) description; { return [NSString stringWithFormat:@"%@: %u %u%@ obj: %u -> %@", NSStringFromClass([self class]), 0/* num */, _generation, _isFree?@" free":@"", _position, _object]; } - (NSData *) data; { return _data; } - (unsigned) position; { return _position; } - (id) object; { return _object; } - (void) setObject:(id) obj; { [_object autorelease]; _object=[obj retain]; } @end