Back to Blog

    Developer Blog

    How to render with Foxit PDF SDK for iOS

    Foxit PDF SDK for iOS

    PDF rendering is done with the Foxit renderer, a graphic engine that is used to render pages to a bitmap or a platform device. Foxit PDF SDK provides APIs to set rendering options/flags. For example, to set a flag to decide whether to render form fields and a signature, whether to draw anti-aliasing images and anti-aliasing paths. To render, you can use the following APIs:

    • To render a page and its annotations, first use the function FSRenderer::setRenderContentFlags to decide whether to render both the page and annotations, and then use the function FSRenderer::startRender to render. The function FSRenderer::startQuickRender can also be used to render page but only for thumbnail purposes.
    • To render a single annotation, use the function FSRenderer::renderAnnot
    • To render on a bitmap, use the function FSRenderer::startRenderBitmap
    • To render a reflowed page, use the function FSRenderer::startRenderReflowPage

    Widget annotation is always associated with a form field and form control in Foxit PDF SDK. For how to render widget annotations, here is a recommended flow:

    • After loading a PDF page, first render the page and all annotations in the page (including widget annotations).
    • Then, if you are using the FSFiller object to fill the form, the function FSFiller::render should be used to render the focused form control instead of the function FSRenderer::renderAnnot.

    Example:

    How to render a specified page to a bitmap

    #import "ViewController.h"
    #import 
    ...
    -(FSBitmap*)renderPageToBitmap: (FSPDFPage*) pdfPage drawWidth: (int)drawPageWidth drawHeight: (int)drawPageHeight
    {
        // If the page hasn't been parsed yet, throw an exception.
        if(![pdfPage isParsed])
            @throw [NSException exceptionWithName:NSGenericException reason:@"PDF Page should be parsed first" userInfo:nil];
        // Pepare matrix to render on the bitmap.
        FSMatrix2D* matrix = [pdfPage getDisplayMatrix:0 top:0 width:drawPageWidth height:drawPageHeight rotate:FSRotation0];
        // Create a bitmap according to the required drawPageWidth and drawPageHeight.
        FSBitmap* bitmap = [[FSBitmap alloc] initWithWidth:drawPageWidth height:drawPageHeight format:FSBitmapDIBRgb];
        // Fill the bitmap with white color.
        [bitmap fillRect:0xFFFFFFFF rect:nil];
        FSRenderer* renderer = [[FSRenderer alloc] initWithBitmap:bitmap is_rgb_order:YES];
        // Set the render flag, both page content and annotation will be rendered.
        [renderer setRenderContentFlags:FSRendererRenderPage | FSRendererRenderAnnot];
        // Start to render the page progressively.
        FSProgressive* progress = [renderer startRender:pdfPage matrix:matrix pause:nil];
        if(progress) {
            FSProgressiveState state = [progress resume];
            while (state == FSProgressiveToBeContinued) {
                state = [progress resume];
            }
            if(state != FSProgressiveFinished)
                return nil;
        }
        return bitmap;
    }
    

    How to render a specified page to a platform device context

    #import "ViewController.h"
    #import 
    ...
    -(void)renderPageToContext: (FSPDFPage*) pdfPage context: (CGContextRef)context
    {
        // If the page hasn't been parsed yet, throw an exception.
        if(![pdfPage isParsed])
            @throw [NSException exceptionWithName:NSGenericException reason:@"PDF Page should be parsed first" userInfo:nil];
        // We set the width of drawing page to be equal to screen width, the drawing page height is calculated according to the ratio of page height and width.
        CGFloat scale = [UIScreen mainScreen].scale;
        int drawPageWidth = (int)[[UIScreen mainScreen] bounds].size.width * scale;
        float pageWidth = [pdfPage getWidth];
        float pageHeight = [pdfPage getHeight];
        int drawPageHeight = (int)drawPageWidth * (pageHeight/pageWidth) * scale;
        // Erase the background of context with white color.
        CGContextSaveGState(context);
        CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
        CGContextFillRect(context, CGRectMake(0, 0, drawPageWidth, drawPageHeight));
        // Render to screen in the device coordinate, left:0, top:0, right:drawPageWidth, bottom:drawPageHeight.
        FSMatrix2D* matrix = [pdfPage getDisplayMatrix:0 top:0 width:drawPageWidth height:drawPageHeight rotate:FSRotation0];
        FSRenderer* renderer = [[FSRenderer alloc] initWithContext:context device_type:FSRendererDeviceDisplay];
        [renderer setRenderContentFlags:FSRendererRenderPage | FSRendererRenderAnnot];
        // Start to render the page progressively.
        FSProgressive* progress = [renderer startRender:pdfPage matrix:matrix pause:nil];
        if(progress) {
            FSProgressiveState state = [progress resume];
            while (state == FSProgressiveToBeContinued) {
                state = [progress resume];
            }
        }
        CGContextRestoreGState(context);   
    }