in O2PDFContext:

- spool the graphic state before the actual path, because some old Adobe Software, e.g. AR 7 and AI CS2, complain about "Invalid operation inside a path" otherwise.
- deactivate per page spooling because by its present incarnation the generated PDF would contain the Kids object more than once and in addition the PDF structure would be spoiled.
This commit is contained in:
Rolf Jansen 2015-10-06 17:01:03 -03:00 committed by Rolf
parent bbba7c2199
commit bbc801b7d4

View File

@ -110,7 +110,7 @@ const NSString *kO2PDFContextTitle=@"kO2PDFContextTitle";
}
-(unsigned)length {
return _length;
return _length;
}
-(BOOL)isBitmapContext
@ -119,16 +119,16 @@ const NSString *kO2PDFContextTitle=@"kO2PDFContextTitle";
}
-(void)appendBytes:(const void *)ptr length:(unsigned)length {
_length += length;
O2DataConsumerPutBytes(_dataConsumer, ptr, length);
_length += length;
O2DataConsumerPutBytes(_dataConsumer, ptr, length);
}
-(void)appendData:(NSData *)data {
[self appendBytes:[data bytes] length:[data length]];
[self appendBytes:[data bytes] length:[data length]];
}
-(void)appendCString:(const char *)cString {
[self appendBytes:cString length:strlen(cString)];
[self appendBytes:cString length:strlen(cString)];
}
-(void)appendString:(NSString *)string {
@ -292,7 +292,7 @@ const NSString *kO2PDFContextTitle=@"kO2PDFContextTitle";
const char *objectName=[[NSString stringWithFormat:@"%s%d",categoryName,[next intValue]] UTF8String];
[category setObjectForKey:objectName value:pdfObject];
return [O2PDFObject_Name pdfObjectWithCString:objectName];
return [O2PDFObject_Name pdfObjectWithCString:objectName];
}
-(void)emitPath:(O2PathRef)path {
@ -346,11 +346,11 @@ const NSString *kO2PDFContextTitle=@"kO2PDFContextTitle";
- (void)translateCTM:(float)x:(float)y
{
[self contentWithFormat:@"1 0 0 1 %f %f cm ", x, y];
[self contentWithFormat:@"1 0 0 1 %f %f cm ", x, y];
}
- (void)scaleCTM:(float)x:(float)y
{
[self contentWithFormat:@"%f 0 0 %f 0 0 cm ", x, y];
[self contentWithFormat:@"%f 0 0 %f 0 0 cm ", x, y];
}
-(void)emitSaveGState {
@ -449,7 +449,7 @@ const NSString *kO2PDFContextTitle=@"kO2PDFContextTitle";
[self contentWithFormat:@"%g i ",gState->_flatness];
O2AffineTransform matrix=gState->_userSpaceTransform;
[self contentWithFormat:@"%g %g %g %g %g %g cm ",matrix.a,matrix.b,matrix.c,matrix.d,matrix.tx,matrix.ty];
[self contentWithFormat:@"%g %g %g %g %g %g cm ",matrix.a,matrix.b,matrix.c,matrix.d,matrix.tx,matrix.ty];
NSArray *clipPhases=[O2GStateClipState(gState) clipPhases];
@ -470,7 +470,7 @@ const NSString *kO2PDFContextTitle=@"kO2PDFContextTitle";
}
break;
case O2ClipPhaseMask: {
case O2ClipPhaseMask: {
#if 0
O2PDFObject *pdfObject=[image encodeReferenceWithContext:self];
O2PDFObject *name=[self nameForResource:pdfObject inCategory:"XObject"];
@ -481,7 +481,7 @@ const NSString *kO2PDFContextTitle=@"kO2PDFContextTitle";
[self contentWithFormat:@"%@ Do ",name];
[self contentWithString:@"Q "];
#endif
}
}
break;
}
}
@ -490,8 +490,8 @@ const NSString *kO2PDFContextTitle=@"kO2PDFContextTitle";
-(void)drawPath:(O2PathDrawingMode)pathMode {
[self emitSaveGState];
[self emitPath:_path];
[self emitCurrentGState];
[self emitCurrentGState]; // spool the graphic state before the actual path, because some old Adobe Software,
[self emitPath:_path]; // e.g. AR 7 and AI CS2, complain about "Invalid operation inside a path" otherwise.
switch(pathMode){
@ -548,91 +548,91 @@ const NSString *kO2PDFContextTitle=@"kO2PDFContextTitle";
}
-(void)drawShading:(O2Shading *)shading {
[self emitSaveGState];
[self emitCurrentGState];
O2PDFObject *pdfObject=[shading encodeReferenceWithContext:self];
O2PDFObject *name=[self nameForResource:pdfObject inCategory:"Shading"];
[self emitSaveGState];
[self emitCurrentGState];
O2PDFObject *pdfObject=[shading encodeReferenceWithContext:self];
O2PDFObject *name=[self nameForResource:pdfObject inCategory:"Shading"];
[self contentWithFormat:@"%@ sh ",name];
[self emitRestoreGState];
[self contentWithFormat:@"%@ sh ",name];
[self emitRestoreGState];
}
-(void)drawImage:(O2Image *)image inRect:(O2Rect)rect {
[self emitSaveGState];
[self emitSaveGState];
O2PDFObject *pdfObject=[image encodeReferenceWithContext:self];
O2PDFObject *name=[self nameForResource:pdfObject inCategory:"XObject"];
[self emitCurrentGState];
O2PDFObject *pdfObject=[image encodeReferenceWithContext:self];
O2PDFObject *name=[self nameForResource:pdfObject inCategory:"XObject"];
[self emitCurrentGState];
[self emitSaveGState];
[self translateCTM:rect.origin.x:rect.origin.y];
[self scaleCTM:rect.size.width:rect.size.height];
[self contentWithFormat:@"%@ Do ",name];
[self emitRestoreGState];
[self emitSaveGState];
[self translateCTM:rect.origin.x:rect.origin.y];
[self scaleCTM:rect.size.width:rect.size.height];
[self contentWithFormat:@"%@ Do ",name];
[self emitRestoreGState];
[self emitRestoreGState];
[self emitRestoreGState];
}
-(void)drawLayer:(O2LayerRef)layer inRect:(O2Rect)rect {
}
-(void)beginPage:(const O2Rect *)mediaBox {
O2PDFObject *stream;
O2PDFObject *stream;
_page=[[O2PDFDictionary pdfDictionary] retain];
_page=[[O2PDFDictionary pdfDictionary] retain];
[_page setNameForKey:"Type" value:"Page"];
[_page setObjectForKey:"MediaBox" value:[O2PDFArray pdfArrayWithRect:*mediaBox]];
[_page setNameForKey:"Type" value:"Page"];
[_page setObjectForKey:"MediaBox" value:[O2PDFArray pdfArrayWithRect:*mediaBox]];
stream=[O2PDFStream pdfStream];
[_page setObjectForKey:"Contents" value:stream];
[_contentStreamStack addObject:stream];
stream=[O2PDFStream pdfStream];
[_page setObjectForKey:"Contents" value:stream];
[_contentStreamStack addObject:stream];
[_page setObjectForKey:"Parent" value:[self referenceForObject:_pages]];
[_page setObjectForKey:"Parent" value:[self referenceForObject:_pages]];
[self referenceForObject:_page];
[self referenceForObject:_page];
}
-(void)internIndirectObjects {
int i;
int i;
for(i=0;i<[_indirectObjects count];i++){ // do not cache 'count', can grow during encoding
O2PDFObject *object=[_indirectObjects objectAtIndex:i];
O2PDFxrefEntry *entry=[_indirectEntries objectAtIndex:i];
if (![object isKindOfClass:[NSNull class]]) {
unsigned position=[self length];
[entry setPosition:position];
for(i=0;i<[_indirectObjects count];i++){ // do not cache 'count', can grow during encoding
O2PDFObject *object=[_indirectObjects objectAtIndex:i];
O2PDFxrefEntry *entry=[_indirectEntries objectAtIndex:i];
if (![object isKindOfClass:[NSNull class]]) {
unsigned position=[self length];
[entry setPosition:position];
[self appendFormat:@"%d %d obj\n",[entry number],[entry generation]];
[object encodeWithPDFContext:self];
[self appendFormat:@"endobj\n"];
}
}
[_indirectObjects removeAllObjects];
[_indirectEntries removeAllObjects];
[self appendFormat:@"%d %d obj\n",[entry number],[entry generation]];
[object encodeWithPDFContext:self];
[self appendFormat:@"endobj\n"];
}
}
[_indirectObjects removeAllObjects];
[_indirectEntries removeAllObjects];
}
-(void)internIndirectObjectsExcluding:(NSArray *)array {
int i;
int i;
for(i=0;i<[_indirectObjects count];i++){ // do not cache 'count', can grow during encoding
O2PDFObject *object=[[[_indirectObjects objectAtIndex:i] retain] autorelease];
if (![array containsObject:object]) {
O2PDFxrefEntry *entry=[_indirectEntries objectAtIndex:i];
[_indirectObjects replaceObjectAtIndex:i withObject:[NSNull null]];
if (![object isKindOfClass:[NSNull class]]) {
unsigned position=[self length];
[entry setPosition:position];
for(i=0;i<[_indirectObjects count];i++){ // do not cache 'count', can grow during encoding
O2PDFObject *object=[[[_indirectObjects objectAtIndex:i] retain] autorelease];
if (![array containsObject:object]) {
O2PDFxrefEntry *entry=[_indirectEntries objectAtIndex:i];
[_indirectObjects replaceObjectAtIndex:i withObject:[NSNull null]];
if (![object isKindOfClass:[NSNull class]]) {
unsigned position=[self length];
[entry setPosition:position];
[self appendFormat:@"%d %d obj\n",[entry number],[entry generation]];
[object encodeWithPDFContext:self];
[self appendFormat:@"endobj\n"];
[self appendFormat:@"%d %d obj\n",[entry number],[entry generation]];
[object encodeWithPDFContext:self];
[self appendFormat:@"endobj\n"];
// We're done with this object
NSMapRemove(_objectToRef,object);
}
}
}
// We're done with this object
NSMapRemove(_objectToRef,object);
}
}
}
}
-(void)endPage {
@ -652,15 +652,18 @@ const NSString *kO2PDFContextTitle=@"kO2PDFContextTitle";
// Encode any indirect object now, so they can be released - don't encode the catalog, kids or pages now
// else subsequent pages are not saved, because the 'Kids' array has already been encoded and we get
// some invalid PDF
[self internIndirectObjectsExcluding:[NSArray arrayWithObjects:_kids, _pages, _catalog, nil]];
// FIXME: The following (i.e. per page spooling) does not work as supposed. If uncommented, the generated PDF
// would contain the Kids object more than once, and its structure would be spoiled.
// Leaving this commented, deactivates per page spooling, however the final PDF will be perfectly valid.
// [self internIndirectObjectsExcluding:[NSArray arrayWithObjects:_kids, _pages, _catalog, nil]];
}
-(void)close {
// Encode the remaining references
[self internIndirectObjects];
[self encodePDFObject:(id)_xref];
[_dataConsumer release];
_dataConsumer=nil;
// Encode the remaining references
[self internIndirectObjects];
[self encodePDFObject:(id)_xref];
[_dataConsumer release];
_dataConsumer=nil;
}
@end