2

What is the recommended way to draw a long string of text on two or more pages in a pdf document?

When you draw a string of text that is too long for a single page, the text is clipped at the end of the document. My initial idea was to calculate how much of the string can be drawn on the current page and then split the string in two substrings: (1) the part that can be drawn on the current page and (2) the part that is clipped. The next step would be to repeat this process until the entire string is drawn.

The question remains how to calculate how much of the string can be drawn on the current page. Am I overlooking something or is this a fairly tedious process that is error prone?

Bart Jacobs
  • 9,022
  • 7
  • 47
  • 88

3 Answers3

3

A long time ago I made this function it might help you, pass the spacing and font and it will return you the splited strings in limited width and requied size.

- (NSMutableArray *)getSplittedString:(NSString *)largeStr:(UIFont *)font:(NSInteger)horizontalSpace:(float)width {
    NSArray *strWords = [largeStr componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    //finding space width

    NSInteger currIndex = 0;
    NSString *tmpStr = @"";
    NSString *compareStr = @"";
    NSInteger currWidth;

    NSMutableArray *strArray = [[NSMutableArray alloc] init];
    NSMutableArray *strFrames = [[NSMutableArray alloc] init];

    while(TRUE) {
        while(TRUE) {
            compareStr = tmpStr;
            compareStr = [compareStr stringByAppendingString:[strWords objectAtIndex:currIndex]];
            currWidth = [compareStr sizeWithFont:font].width;
            if(currWidth < width) {
                currIndex = currIndex + 1;
                if(currIndex == [strWords count]) {
                    [strArray addObject:compareStr];
                    [strFrames addObject:[NSValue valueWithCGRect:[self findCenterAdjustedLocation:compareStr :width :font :horizontalSpace]]];
                    break;
                }
                tmpStr = [NSString stringWithFormat:@"%@ ",compareStr];

            } else if (currWidth == width) {
                [strArray addObject:compareStr];
                [strFrames addObject:[NSValue valueWithCGRect:[self findCenterAdjustedLocation:compareStr :width :font :horizontalSpace]]];
                tmpStr = @"";
                if(currIndex == [strWords count]) {
                    break;
                }
            } else {
                if([compareStr rangeOfString:@" "].location == NSNotFound) {
                    while(TRUE) {
                        NSInteger loc = [self findAdjustedLocation:compareStr :width :font];
                        if(loc == 0) {
                            tmpStr = [compareStr substringFromIndex:loc];
                            if(currIndex == [strWords count]) {
                                [strArray addObject:tmpStr];
                                [strFrames addObject:[NSValue valueWithCGRect:[self findCenterAdjustedLocation:tmpStr :width :font :horizontalSpace]]];
                                break;
                            }
                            tmpStr = [NSString stringWithFormat:@"%@ ",tmpStr];
                            break;
                        } else {
                            tmpStr = [compareStr substringWithRange:NSMakeRange(0, loc)];
                            [strArray addObject:tmpStr];
                            [strFrames addObject:[NSValue valueWithCGRect:[self findCenterAdjustedLocation:tmpStr :width :font :horizontalSpace]]];
                            tmpStr = [NSString stringWithFormat:@"%@ ",[compareStr substringFromIndex:loc]];
                            compareStr = tmpStr;
                            if ([tmpStr sizeWithFont:font].width < width) {
                                [strArray addObject:tmpStr];
                                [strFrames addObject:[NSValue valueWithCGRect:[self findCenterAdjustedLocation:tmpStr :width :font :horizontalSpace]]];
                                currIndex = currIndex + 1;
                                break;
                            }
                        }
                    }
                } else {
                    [strArray addObject:tmpStr];
                    [strFrames addObject:[NSValue valueWithCGRect:[self findCenterAdjustedLocation:tmpStr :width :font :horizontalSpace]]];
                    tmpStr = @"";
                }
                break;
            }
        }
        if(currIndex == [strWords count]) {
            return [[NSMutableArray alloc] initWithObjects:strArray, strFrames, nil];
            break;
        }
    }
}
Alex Markman
  • 1,450
  • 1
  • 13
  • 15
2

You could attempt to generate your PDF using the iOS print subsystem via UIMarkupTextPrintFormatter. I explain the technique here:

Is there any way to generate PDF file from a XML/HTML template in iOs

I haven't tried to see what would happen re. pagination, but in theory it would do the right thing.

Community
  • 1
  • 1
TomSwift
  • 39,369
  • 12
  • 121
  • 149
  • I don't know for normal text, it may work. For one of my app, I used HTML tables with rows and columns to print to PDF using iOS print subsystem. The result was on some pages, one of the rows of the table would get offset randomly. But yeah, it takes care of moving your text to a separate page for you. – Zhang Sep 18 '12 at 02:15
2

I tried to calculate the real height of a text once drawn onto a PDF but it seriously gets annoying as you can't really get the "real" line height. I ended up giving up CoreGraphics and drew everything using @TomSwift technique. Even easier than CoreGraphics, you can set the font, text color,... with CSS styles

nicolasthenoz
  • 1,852
  • 1
  • 13
  • 14