Home

Awesome

SimplyPDF

SimplyPDF is an android library that allows developers to generate PDF documents from within their application. It provides various composers which are used to draw various elements. It also provides a JSON template which can be used to create PDF documents. This will be useful to control the template from remote server and replace content provided by user, like forms.

Using it

You can use it in gradle as following:


maven { url 'https://jitpack.io' }

dependencies {
    implementation 'com.github.wwdablu:SimplyPDF:2.0.0'
}

PDF Document

To obtain the PDF document, the developer needs to use the SimplyPdf class to obtain the SimplyPdfDocument. This contains the methods to access the various properties and methods for the PDF document. This is also used by the Composers to perform the required operation to write the data on it.

simplyPdfDocument = SimplyPdf.with(this, new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/test.pdf"))
    .colorMode(DocumentInfo.ColorMode.COLOR)
    .paperSize(PrintAttributes.MediaSize.ISO_A4)
    .margin(Margin(startMargin, topMargin, endMargin, bottomMargin)
    .pageModifier(PageHeader())
    .firstPageBackgroundColor(Color.WHITE)
    .paperOrientation(DocumentInfo.Orientation.PORTRAIT)
    .build();

The above setup means that a PDF document named test will be created in the external directory. The PDF document will be in color mode with the paper size as A4. The specified margins will be used and the print orientation will be portrait. Also the background color of the first page will be white in color. Along with it page modifiers are also supported. They are applied to each of the pages when created. One example (provided support by the library) is a page header. This will get added everytime a new page is added to the document.

Following are the methods provided by the SimplyPdfDocument for use.

Method/PropertiesUsage
insertEmptyLines(LineCount)Inserts number of empty lines in the document
insertEmptySpace(Height)Inserts an empty content of the specified height
newPage(Color)Inserts a new page with the specific background color. Default: White
addContentHeight(Height)Used by composers. Used to specify how much content drawn in the page
finish()Completes all the rendering and saves the PDF file.
textAccess the default text composer
imageAccess the default image composer
shapeAccess the default shape composer
tableAccess the default table composer
usablePageWidthUsable width of the page considering margins
usablePageHeightUsable height of the page considering margins
currentPagePage object of the PDF Document. Can be used to access the page canvas
currentPageNumberPage number being currently worked on
pageContentHeightHeight of the contents rendered in the current page
documentInfoDocumentInfo for the current PDF Document
lineHeightHeight of a line considered by insertEmptyLines()

Note: The document will be created once finish() method is called. Till then everything is occurring in-memory.

Composers

The classes which are responsible for drawing content onto the PDF are called Composers in this library. Currently these are the supported composers:

TextComposer

TextComposer is used to perform Text operations on the document.

Method/PropertiesUsage
write(String, TextProperties, PageWidth, xMargin, yMargin)Writes the text with the specified width by applying the margins.

PageWidth has a default value set to usablePageWidth. xMargin by default is set to 0. yMargin by default is set to 0.

TextProperties

TextProperties are used to assign various properties that are associated with the TextComposer.

Method/PropertiesUsage
textSizeSet the size of the text to be displayed
textColorSet the color of the text to be displayed with
typefaceTypeface to be used to display the text content
alignmentAlignment of the center like Normal, Center, Opposite
underlineShould the text be underlined
strikethroughShould the text be strikethrough
bulletSymbolThe character to be displayed for bullet content

Sample:

simplyPdfDocument.text.write("Hello World", TextProperties().apply {
    textSize = 12
    textColor = "#000000"
    typeface = Typeface.DEFAULT
})

ImageComposer

ImageComposer is used to perform bitmap rendering or draw operations on the document.

Method/PropertiesUsage
drawBitmap(Bitmap, ImageProperties, xMargin, yMargin)Draws the bitmap with the given properties and margins.
drawFromUrl(String, Context, ImageProperties, xMargin, yMargin)Downloads the image from the URL and draws the bitmap.

xMargin by default is set to 0. yMargin by default is set to 0.

Note: The bitmap resource handling should be done by the caller. Any bitmaps received from outside the library recycle() will not be called on them.

ImageProperties

ImageProperties are used to assign various properties that are associated with the ImageComposer.

Method/PropertiesUsage
alignmentAlignment of the center like Start, Center, End

Sample:

simplyPdfDocument.image.drawBitmap(bitmap, ImageProperties().apply {
    alignment = Composer.Alignment.START
})

TableComposer

TableComposer is used to draw tables and show text and image contents inside it. It uses Cell objects to render the contents. The library provides support for TextCell to draw texts and ImageCell to draw bitmaps inside the table cell.

Method/PropertiesUsage
draw(LinkedList<LinkedList<Cell>>)Draws the cells in row and columns

TextCell: The TextCell encapsulates the TextComposer. It takes in the text content, the TextProperties and also the width of the cell compared to the width of the table.

ImageCell: The TextCell encapsulates the ImageComposer. It takes in the bitmap, the ImageProperties and also the width of the cell compared to the width of the table.

TableProperties

TableProperties are used to assign various properties that are associated with the TableComposer.

Method/PropertiesUsage
borderColorThe color of the border lines used to draw the table
borderWidthThe width of the border lines used to draw the table
drawBorderWhether to draw the border or not
borderStyleDefines the process to draw border, like ALL, OUTER, INNER, HORIZONTAL and VERTICAL
alignAlign the entire table to the left or center

Sample:

val rows = LinkedList<LinkedList<Cell>>().apply {

    //Row - 1
    add(LinkedList<Cell>().apply {

        //Column - 1
        add(TextCell("Hello World", TextProperties().apply {
            textSize = 12
            textColor = "#000000"
        }, Cell.MATCH_PARENT))
    })

    //Row - 2
    add(LinkedList<Cell>().apply {

        //Column - 1
        add(TextCell("Text Cell", TextProperties().apply {
            textSize = 12
            textColor = "#000000"
        }, simplyPdfDocument.usablePageWidth/2))

        //Column - 2
        add(ImageCell(bitmap, ImageProperties(), simplyPdfDocument.usablePageWidth/2))
    })
}

simplyPdfDocument.table.draw(rows, TableProperties().apply {
    borderColor = "#000000"
    borderWidth = 1
    drawBorder = true
})

Generating the PDF

Once all the content are written, the developer needs to be call finish() on SimplyPdfDocument.

simplyPdfDocument.finish();

This would generate the document in the given path.

Generating from JSON

There is a defined structure which can be used to generate the PDF document. In here no Composers are required. The library does everything internally based on the JSON provided. Consider the below example:

{
    "page" : [
    {
        "type" : "world"
    },
        {
            "type" : "setup",
            "margin" : {
                "start" : 125,
                "top" : 125,
                "end" : 125,
                "bottom" : 125
            },
            "backgroundcolor" : "#C8C8C8"
        },
        {
            "type" : "header",
            "contents" : [
                {
                    "type" : "text",
                    "content" : "Simplypdf",
                    "properties" : {
                        "size" : 24,
                        "color" : "#000000",
                        "underline" : false,
                        "strikethrough" : false,
                        "alignment" : "ALIGN_CENTER"
                    }
                },
                {
                    "type" : "text",
                    "content" : "Version 2.0",
                    "properties" : {
                        "size" : 20,
                        "color" : "#000000",
                        "underline" : true,
                        "strikethrough" : false,
                        "alignment" : "ALIGN_CENTER"
                    }
                }
            ]
        }
    ],
    "contents" : [
        {
            "type" : "text",
            "content" : "Simplypdf developed by Soumya Kanti Kar",
            "properties" : {
                "size" : 24,
                "color" : "#000000",
                "underline" : true,
                "strikethrough" : false
            }
        },
        {
            "type" : "image",
            "source" : "https://avatars0.githubusercontent.com/u/28639189?s=400&u=bd9a720624781e17b9caaa1489345274c07566ac&v=4"
        },
        {
            "type" : "text",
            "content" : "Source code published in GitHub",
            "properties" : {
                "size" : 20,
                "color" : "#000000",
                "underline" : true,
                "strikethrough" : false
            }
        },
        {
            "type" : "newpage"
        },
        {
            "type" : "space",
            "height" : 125
        },
        {
            "type" : "table",
            "contents" : [
                {
                    "row" : [
                        {
                            "type" : "text",
                            "content" : "Version",
                            "width" : 50,
                            "properties" : {
                                "size" : 24,
                                "color" : "#000000",
                                "underline" : true,
                                "strikethrough" : false
                            }
                        },
                        {
                            "type" : "text",
                            "content" : "2.0.0",
                            "width" : 50,
                            "properties" : {
                                "size" : 24,
                                "color" : "#000000",
                                "underline" : true,
                                "strikethrough" : false
                            }
                        }
                    ]
                },
                {
                    "row" : [
                        {
                            "type" : "text",
                            "content" : "Source Code Available in GitHub",
                            "width" : 100,
                            "properties" : {
                                "size" : 24,
                                "color" : "#000000",
                                "underline" : true,
                                "strikethrough" : false
                            }
                        }
                    ]
                },
                {
                    "row" : [
                        {
                            "type" : "image",
                            "type" : "image",
                            "source" : "https://avatars0.githubusercontent.com/u/28639189?s=400&u=bd9a720624781e17b9caaa1489345274c07566ac&v=4"
                        }
                    ]
                }
            ],
            "properties" : {
                "width" : 1,
                "color" : "#000000"
            }
        }
    ]
}

To use the above JSON to generate the PDF we need to just call:

val simplyPdfDocument = SimplyPdf.with(context,
        File(Environment.getExternalStorageDirectory().absolutePath + "/json_to_pdf.pdf"))
    .colorMode(DocumentInfo.ColorMode.COLOR)
    .paperSize(PrintAttributes.MediaSize.ISO_A4)
    .margin(Margin(start, top, end, bottom))
    .paperOrientation(DocumentInfo.Orientation.PORTRAIT)
    .build()

val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
    Log.e(MainActivity::class.java.simpleName, "JSON to PDF exception.", throwable)
}

CoroutineScope(Dispatchers.IO).launch(exceptionHandler) {
    SimplyPdf.usingJson(context, simplyPdfDocument, JSONStruct.payload)
    withContext(Dispatchers.Main) {
        Toast.makeText(context, "JSON to PDF Completed", Toast.LENGTH_SHORT).show()
    }
}

This will generate the PDF with the provided JSON.