Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

PDF Creation Tutorial

2456

Replies

  • decaydecay Posts: 10Registered Users
    edited June 2009
    danielb21 wrote: »
    Spent more time today exploring the [NSString drawInRect:] method to see if I could get it to work, and I now have a working solution. The key is that you have to push the graphics context onto the stack. Below is how it works:
    NSString *string = @"Text to print.";
    
    UIGraphicsPushContext(context);
    CGContextTranslateCTM(context, 0, 20);
    CGContextScaleCTM(context, 1.0, -1.0);
    [string drawInRect:CGRectMake(0, 0, 300, 200) withFont:[UIFont fontWithName:@"Verdana" size:9]];
    UIGraphicsPopContext();
    

    So, the above code block pushes the context onto the stack, reverses the coordinates so that the text is drawn correctly, and then uses the drawInRect: withFont: method to draw the text, and finally calls the UIGraphicsPopContext() method.

    It's important to note that each time you call UIGraphicsPushContext(context); you must also call the pop context method, otherwise you'll be left with nothing.

    Thanks to decay for pushing me to investigate this more and enjoy everyone!

    Your welcome, Daniel. Actually, I only call UIGraphicsPushContext() at the very end of the document. In between, I also use [UIImage drawInRect:] to stick pictures in the document, as well as drawing a line graph. I am generating PDFs on the fly, sometimes in the 17-20 page range. My app that uses this will be submitted to Apple tomorrow actually.
  • prameshuprameshu Posts: 10Registered Users
    edited July 2009
    Thanks for the great tutorial. It helps me a lot. Finally I need to display the € currency symbol. In stead of Euro symbol, the pDF file shows some other unrecognized characters. Could you help me in this regard......

    thanks,
    Ramesh.
  • ZunePodZunePod Posts: 1,031Registered Users
    edited July 2009
    meowmix23F wrote: »
    You'd have to use the mailto: url scheme to open up mail.app, and, on non-jailbroken phones it is impossible to use the attachment paramter of mailto:, so you'l have to write an SMTP client.

    You can grab Mail account info?

    So its not all that hard.
    <div align="center">Will code for food</div>
  • danielb21danielb21 Posts: 48Tutorial Authors, Registered Users
    edited July 2009
    ZunePod wrote: »
    You can grab Mail account info?

    So its not all that hard.

    You'll want to check out the documentation on MessageUI for this.
  • micnguyenmicnguyen Posts: 2New Users
    edited July 2009
    It's frozen when I pressed the button... the pdf file was created but could not be opened by the adobe reader (invalid file)
  • CoasterCoaster Posts: 57Registered Users
    edited September 2009
    danielb21 wrote: »
    Spent more time today exploring the [NSString drawInRect:] method to see if I could get it to work, and I now have a working solution. The key is that you have to push the graphics context onto the stack. Below is how it works:
    NSString *string = @"Text to print.";
    
    UIGraphicsPushContext(context);
    CGContextTranslateCTM(context, 0, 20);
    CGContextScaleCTM(context, 1.0, -1.0);
    [string drawInRect:CGRectMake(0, 0, 300, 200) withFont:[UIFont fontWithName:@"Verdana" size:9]];
    UIGraphicsPopContext();
    

    So, the above code block pushes the context onto the stack, reverses the coordinates so that the text is drawn correctly, and then uses the drawInRect: withFont: method to draw the text, and finally calls the UIGraphicsPopContext() method.

    It's important to note that each time you call UIGraphicsPushContext(context); you must also call the pop context method, otherwise you'll be left with nothing.

    Thanks to decay for pushing me to investigate this more and enjoy everyone!


    ::edit nm:
  • SicgaSicga Posts: 133Registered Users
    edited September 2009
    Hi Daniel

    I know this is a late addition to your original post but I'm in desperate need of some help with the iPhone PDF stuff. I'm looking for the correct way to use a couple of CGPDF functions namely:
    CGPDFDocumentGetPage and CGPDFPageGetPageNumber

    I am trying to set up a bookmark for a locally loaded pdf document with multiple pages.
    I am trying to load the bookmarked page like so:
    if (iPhotoOg == 0) {
    	  pdfUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Stave1" ofType:@"pdf"]];
    		
    		pdfUrl = CGPDFDocumentGetPage(pdfUrl, pageNumber); 
    }
    [webView loadRequest:[NSURLRequest requestWithURL:pdfUrl]];
    

    and trying to bookmark the page like so:
    else if (iPhotoOg == 1){
    		chap = 2;
    		
    		pageNumber = CGPDFPageGetPageNumber(pageNumber);
    	}
    

    In the first instance I just get a blank screen in tehs econd instance I get incompatibility warnings.

    Any help would be greatly appreciated.
  • mmunozfermmunozfer Posts: 7New Users
    edited October 2009
    I don't know how do to create a CGContextRef in CGPDFContext to show a NSString. I'm trying with UIGraphicsGetCurrentContext(), but this function return nil.

    Somebody can help me?

    Thanks

    PS: sorry for my english
  • SicgaSicga Posts: 133Registered Users
    edited October 2009
    Hi mmunozfer

    Have a look at the Quartz Demo sample code Apple provides it might give the solution.
  • mmunozfermmunozfer Posts: 7New Users
    edited October 2009
    Sicga wrote: »
    Hi mmunozfer

    Have a look at the Quartz Demo sample code Apple provides it might give the solution.

    Thanks Sicga, i'll try it again with the quartz demo sample

    Miguel
  • mmunozfermmunozfer Posts: 7New Users
    edited October 2009
    I'm sorry, i don't get show a NSString in PDFContext, somebody can help me?

    Thanks
  • pmattfpmattf Posts: 48Registered Users
    edited October 2009
    Does anybody know how to take the current contents of a UIWebView and save them into a pdf file?

    Using this tutorial as a starting point, I took out everything between CGContextBeginPage and CGContextEndPage.

    I first tried
    // webView is my passed in UIWebView *
    [webView.layer drawInContext:pdfContext];
    

    The documentation says that UIView's have a layer property of type CALayer *, and CALayer has a drawInContext method. Yet I get a warning that there is no drawInContext method here, and nothing happens when I run it.

    Next I tried:
    UIGraphicsPushContext(pdfContext);
    [webView setNeedsDisplay];
    UIGraphicsPopContext();
    

    Which I think may be closer to the right track, but that still generates an empty pdf file.

    Any help would be appreciated.
  • wolverinewolverine Posts: 181Registered Users
    edited October 2009
    In the code, even for finding the resource(image) we use several steps which include lot of CF starting functions and CFRef objects.
    CGImageRef image;
        CGDataProviderRef provider;
        CFStringRef picturePath;
        CFURLRef pictureURL;
    	
        picturePath = CFStringCreateWithCString (NULL, picture,kCFStringEncodingUTF8);
        pictureURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), picturePath, CFSTR("png"), NULL);
        CFRelease(picturePath);
    

    Why cant we use
    [[NSBundle mainBundle] pathForResource:@"Picture" ofType:@"png"];
    
    . And then do UTF8 conversion.

    Its a big doubt for me since I am new to this pdf context and all??
  • pmattfpmattf Posts: 48Registered Users
    edited November 2009
    Well the good news is that I figured it out. The problem was I was using drawInContext, while renderInContext is the one to use....
    // PDF page drawing expects a Lower-Left coordinate system, so we flip the coordinate system
    	// before we start drawing.
    	CGContextTranslateCTM(pdfContext, 0.0, pageRect.size.height);
    	CGContextScaleCTM(pdfContext, 1.0, -1.0);
    	// webView is my UIWebView component
    	[webView.layer renderInContext:pdfContext];
    

    The bad news is that this just produces a screen sized bitmap in the pdf, so not that useful.
    pmattf wrote: »
    Does anybody know how to take the current contents of a UIWebView and save them into a pdf file?

    Using this tutorial as a starting point, I took out everything between CGContextBeginPage and CGContextEndPage.

    I first tried
    // webView is my passed in UIWebView *
    [webView.layer drawInContext:pdfContext];
    

    The documentation says that UIView's have a layer property of type CALayer *, and CALayer has a drawInContext method. Yet I get a warning that there is no drawInContext method here, and nothing happens when I run it.

    Next I tried:
    UIGraphicsPushContext(pdfContext);
    [webView setNeedsDisplay];
    UIGraphicsPopContext();
    

    Which I think may be closer to the right track, but that still generates an empty pdf file.

    Any help would be appreciated.
  • pmattfpmattf Posts: 48Registered Users
    edited November 2009
    Is everybody on this thread aware of the fact that any pdf's produced by the iPhone sdk which have text in them are not in fact valid in terms of the pdf spec? They work fine on the iPhone itself or MacOS, but on some Windows and other viewers they appear blank or garbled. For example, if you email one to a gmail acount, and look at it with gmail's inline viewer, it shows up as blank. If you then save it to a Mac, it looks fine.

    Here is a thread talking about the issue...
    orum/iphone-sdk-development/15505-pdf-font-problem-cant-get-cids-glyphs.html

    Post #12 on that thread especially.
  • apiphoneapiphone Posts: 140Registered Users
    edited December 2009
    Hi,

    I am getting an error while creating the pdf files.
    It says : GDB: Program received signal EXC_BAD_ACCESS

    I'm using the same code and it is creating a blank pfd file.
    Why????
  • pmattfpmattf Posts: 48Registered Users
    edited December 2009
    I think that error is usually generated when you try to call a method on an object which as already been released and reclaimed by the system.

    So maybe you are releasing something too soon?

    If you run it in debug mode, you should get a stack trace when you hit the error, then you should be able to see what method call is causing the error, and hence what object has the problem.
    apiphone wrote: »
    I am getting an error while creating the pdf files.
    It says : GDB: Program received signal EXC_BAD_ACCESS

    I'm using the same code and it is creating a blank pfd file.
    Why????
  • falcon76falcon76 Posts: 3New Users
    edited December 2009
    apiphone wrote: »
    Hi,

    I am getting an error while creating the pdf files.
    It says : GDB: Program received signal EXC_BAD_ACCESS

    I'm using the same code and it is creating a blank pfd file.
    Why????

    I have the same error, the problem should be somewhere here:

    provider = CGDataProviderCreateWithURL (pictureURL);
    CFRelease (pictureURL);
    image = CGImageCreateWithPNGDataProvider (provider, NULL, true, kCGRenderingIntentDefault);
    CGDataProviderRelease (provider);
    CGContextDrawImage (pdfContext, CGRectMake(200, 200, 207, 385),image);
    CGImageRelease (image);

    I'm trying to understand what's not working but I start programming one week ago.... I'm a totally noob!
    Thanks anyway for the code, I'm learning a lot from this.
  • aderringtonaderrington Posts: 46Registered Users
    edited December 2009
    pmattf wrote: »
    Well the good news is that I figured it out. The problem was I was using drawInContext, while renderInContext is the one to use....
    // PDF page drawing expects a Lower-Left coordinate system, so we flip the coordinate system
    	// before we start drawing.
    	CGContextTranslateCTM(pdfContext, 0.0, pageRect.size.height);
    	CGContextScaleCTM(pdfContext, 1.0, -1.0);
    	// webView is my UIWebView component
    	[webView.layer renderInContext:pdfContext];
    

    The bad news is that this just produces a screen sized bitmap in the pdf, so not that useful.

    Hi pmattf,
    Did you ever manage to get this to work and save correctly instead of a bitmap in the pdf??
    Trying to figure this out aswell.

    Cheers!!
  • pmattfpmattf Posts: 48Registered Users
    edited December 2009
    Hi pmattf,
    Did you ever manage to get this to work and save correctly instead of a bitmap in the pdf??
    Trying to figure this out aswell.

    Cheers!!

    No, there is no way to get anything out of the UIWebView other than a bitmap. And I could not figure out a way to get one out that is big enough to be useful (though I would not rule out the possibility that you could get a larger one than I did).

    In MacOS it is trivial, because there is pdf rendering built into the print system (i.e. the Save as PDF in the print dialog). So you can easily take most anything, and render it out as a pdf.

    But as far as I could determine, there is no existing code that runs on the iPhone that takes html and converts it to pdf. You would either need to find some C code that does this, and get it running on iPhone, or do it via a web service (there are plenty of options for libraries that would run on a web server to do it).

    What I ended up doing is vastly simplifying the formatting I was doing, so that I could just render it out as strings and images with the pdf functions that the iPhone does have. But per my post a couple up, the resulting pdf's are not actually valid, and will not work everywhere.
  • KennyChongKennyChong Posts: 411Registered Users @ @
    edited January 2010
    danielb21 wrote: »
    Good afternoon everyone!

    I have written an intro to PDF tutorial for those that are interested in PDF interactivity within your iPhone apps. This first tutorial, shows how to simply create a PDF that contains an image, some text and a border around the page.

    Ok, on to the goods! There are two custom methods in the PDFViewController.m file that you will be looking at mostly. The first is CreatePDFFile. This method does exactly what it says - creates a PDF file. The second method is called createPDF, and is an IBAction method hooked to an UIButton in IB. Upon touching the button this method calls our CreatePDFFile method.

    Important - there is no output after clicking the button, meaning you will not see the resulting PDF displayed on the phone. I can create a second tutorial for that purpose, but it seemed like most people were only interested in the creation of the file.

    In order to view the resulting PDF go to:
    Users/YourUserName/Library/Application Support/iPhone Simulator/User/Applications

    In this directory sort by Date Modified. If the example project here was the last app that you ran it will be at the top of this directory. Simply navigate to the documents directory of the PDF example app and you will be able to see the PDF it creates.

    Let me know if you have any questions!

    P.S. So it seems that the example project was larger than the allowed size for attachments. I will get the whole project up on the web for download soon, but in the meantime I have included the class files which is all you should need.



    Great! Thanks for your tutorial...I am sure this will help us all at Dev SDK forum. CHeers,
    KennyChong<br />
    iPhone SDK Fanatic!
  • CodeDropAccountCodeDropAccount Posts: 14Registered Users
    edited January 2010
    This tutorial was so much help so thank you so much for that.
    I am currently trying to create a multi page pdf, which is simple enough except that I have a string of text entered by the user (like a note) and now I need to divide this text into a string for each page.

    But I cannot figure out how to do this! I cannot simply get a substring to index whatever, because there is no way of getting the index, and it doesn't seem possible to know which characters you draw in [string drawInRect:rect].

    Can anyone help?
  • pmattfpmattf Posts: 48Registered Users
    edited January 2010
    The sizeWithFont methods (hidden in the documentation for NSString UIKit Additions, not in NSString itself) can tell you how much vertical space your string will take up for a given font in a given width box. You basically need to find the longest substring of your string which ends at a word boundary that returns the height you want for a single page. That could be done brute force, by starting with your entire string, testing it, chopping off one word from the end, testing that, etc. Or try to get clever, and do it like a binary search or something.
    This tutorial was so much help so thank you so much for that.
    I am currently trying to create a multi page pdf, which is simple enough except that I have a string of text entered by the user (like a note) and now I need to divide this text into a string for each page.

    But I cannot figure out how to do this! I cannot simply get a substring to index whatever, because there is no way of getting the index, and it doesn't seem possible to know which characters you draw in [string drawInRect:rect].

    Can anyone help?
  • Divya.RaiDivya.Rai Posts: 1New Users
    edited February 2010
    Thanks for making the tutorial...can you please help in writing a sample code presenting zoom-able single pages with a previous-next page function.

    Thanks in advance
    danielb21 wrote: »
    Good afternoon everyone!

    I have written an intro to PDF tutorial for those that are interested in PDF interactivity within your iPhone apps. This first tutorial, shows how to simply create a PDF that contains an image, some text and a border around the page.

    Ok, on to the goods! There are two custom methods in the PDFViewController.m file that you will be looking at mostly. The first is CreatePDFFile. This method does exactly what it says - creates a PDF file. The second method is called createPDF, and is an IBAction method hooked to an UIButton in IB. Upon touching the button this method calls our CreatePDFFile method.

    Important - there is no output after clicking the button, meaning you will not see the resulting PDF displayed on the phone. I can create a second tutorial for that purpose, but it seemed like most people were only interested in the creation of the file.

    In order to view the resulting PDF go to:
    Users/YourUserName/Library/Application Support/iPhone Simulator/User/Applications

    In this directory sort by Date Modified. If the example project here was the last app that you ran it will be at the top of this directory. Simply navigate to the documents directory of the PDF example app and you will be able to see the PDF it creates.

    Let me know if you have any questions!

    P.S. So it seems that the example project was larger than the allowed size for attachments. I will get the whole project up on the web for download soon, but in the meantime I have included the class files which is all you should need.
  • OmidOmid Posts: 4New Users
    edited February 2010
    danielb21 wrote: »
    Spent more time today exploring the [NSString drawInRect:] method to see if I could get it to work, and I now have a working solution. The key is that you have to push the graphics context onto the stack. Below is how it works:
    NSString *string = @"Text to print.";
    
    UIGraphicsPushContext(context);
    CGContextTranslateCTM(context, 0, 20);
    CGContextScaleCTM(context, 1.0, -1.0);
    [string drawInRect:CGRectMake(0, 0, 300, 200) withFont:[UIFont fontWithName:@"Verdana" size:9]];
    UIGraphicsPopContext();
    

    So, the above code block pushes the context onto the stack, reverses the coordinates so that the text is drawn correctly, and then uses the drawInRect: withFont: method to draw the text, and finally calls the UIGraphicsPopContext() method.

    It's important to note that each time you call UIGraphicsPushContext(context); you must also call the pop context method, otherwise you'll be left with nothing.

    Thanks to decay for pushing me to investigate this more and enjoy everyone!

    First of all thanks for the tutorial and the code above.
    Can anyone tell me how to position a rotated text correctly?
    I try this, but it's not correct:
    UIGraphicsPushContext(pdfContext);
    	
    	CGContextTranslateCTM(pdfContext,txtPos.origin.x, newY);
    	CGContextScaleCTM(pdfContext, 1.0, -1.0);
    	
    	CGAffineTransform textTransform = CGAffineTransformMakeRotation(/*M_PI*2 - */currentAngle);
    	CGContextConcatCTM(pdfContext, textTransform);
    	
    	
    	NSString *string =[NSString stringWithCString:text];
    	[string drawInRect:CGRectMake(0, 0, txtPos.size.width, txtPos.size.height) withFont:[UIFont fontWithName:@"Helvetica" size:48]];
    	
    	UIGraphicsPopContext();
    

    Thanks in advance,

    Omid
Sign In or Register to comment.