{"id":111,"date":"2015-12-08T10:39:10","date_gmt":"2015-12-08T15:39:10","guid":{"rendered":"http:\/\/jsevy.com\/wordpress\/?page_id=111"},"modified":"2022-03-08T12:22:55","modified_gmt":"2022-03-08T17:22:55","slug":"android-pdf-library","status":"publish","type":"page","link":"https:\/\/jsevy.com\/wordpress\/index.php\/java-and-android\/android-apps-and-libraries\/android-pdf-library\/","title":{"rendered":"Android PDF Library (GnuAPDF)"},"content":{"rendered":"<p>The GnuAPDF library provides support for generation of PDF files using standard Android &#8220;draw&#8221; commands. The library provides a special Canvas subclass, PDFCanvas, that is associated with a PDF document and that renders draw commands into PDF syntax. A sequence of Android Canvas drawing method calls will thus create a structured PDF document that, when viewed with a standard PDF reader, will display the corresponding image. Note that Android version 5.0 has this functionality as part of the standard API; however, earlier versions did not provide PDF generation, and the Android support library didn&#8217;t include this as of the time of this writing.<\/p>\n<p>This library is derived from the <a href=\"http:\/\/gnujpdf.sourceforge.net\">GnuJPDF library<\/a>, which provides similar functionality for the Java AWT graphics system, and as such is similarly released under the <a href=\"https:\/\/www.gnu.org\/licenses\/lgpl.html\">LGPL License<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h2>Basic Workflow<\/h2>\n<p>The class PDFCanvas implements the graphics operations defined by the standard Android Canvas class. To draw something into a PDF document, you use the standard Android Canvas drawing calls (including drawing, transformations, clips, etc.) on an instance of PDFCanvas. The PDFCanvas will encode these as PDF drawing commands.<\/p>\n<p>A PDFCanvas is associated with a PDFPage, which is part of a PDFDocument. The basic workflow is:<\/p>\n<p>\/\/ Create a PDF document, a page in the document, and get that page&#8217;s PDFCanvas<br \/>\nPDFDocument pdfDoc = new PDFDocument();<br \/>\nPDFPage page = new PDFPage(PageFormat.LETTER);<br \/>\npdfDoc.add(page);<br \/>\nPDFCanvas pdfCanvas = page.getCanvas();<\/p>\n<p>\/\/ do drawing commands as on any other Canvas<br \/>\nPaint paint = new Paint();<br \/>\npaint.setColor(Color.RED);<br \/>\npaint.setTypeface(Typeface.SERIF);<br \/>\npaint.setTextSize(38);<br \/>\npaint.setStyle(Style.STROKE);<br \/>\npdfCanvas.drawLine(0, 0,100, 100, paint);<br \/>\npdfCanvas.drawRect(120, 180, 400, 400, paint);<br \/>\npdfCanvas.drawText(&#8220;Some text&#8221;, 200, 600, paint);<br \/>\npaint.setStyle(Style.FILL);<br \/>\npdfCanvas.drawCircle(300, 300, 100, paint);<\/p>\n<p>\/\/ write the PDF content for the page to a file<br \/>\nBufferedOutputStream fileStream = new BufferedOutputStream(new FileOutputStream(file));<br \/>\npdfDoc.write(outStream);<br \/>\nfileStream.flush();<br \/>\nfileStream.close();<\/p>\n<h2>Features<\/h2>\n<p>The GnuAPDF library provides most of the drawing operations available in the standard Canvas class. However, certain methods are unimplemented due to lack of support in PDF; these will throw an UnsupportedOperationException if used. Some additional features currently have no or limited support, as indicated below.<\/p>\n<h3>Supported operations<\/h3>\n<ul>\n<li>Drawing operations, including\n<ul>\n<li>drawLine<\/li>\n<li>drawArc<\/li>\n<li>drawCircle<\/li>\n<li>drawOval<\/li>\n<li>drawRect<\/li>\n<li>drawRoundRect<\/li>\n<li>drawPoints<\/li>\n<li>drawColor<\/li>\n<li>drawPaint<\/li>\n<\/ul>\n<\/li>\n<li>Image drawing through drawBitmap<\/li>\n<li>Grid and 3D drawing through drawBitmapMesh and drawVertices<\/li>\n<li>Text operations drawText, drawPosText, drawTextOnPath<\/li>\n<li>Clipping through clipRect<\/li>\n<li>Matrix transformation operations including scale, skew, translate, rotate and concat<\/li>\n<li>State save and restore<\/li>\n<\/ul>\n<h3>Not supported<\/h3>\n<ul>\n<li>Dotted lines<\/li>\n<li>Underlined and strikethrough text<\/li>\n<li>quickReject() methods (always return false)<\/li>\n<li>drawTextRun method (throws UnsupportedOperationException)<\/li>\n<li>clipPath method (throws UnsupportedOperationException)<\/li>\n<li>clipRect method with operation other than intersect (throws UnsupportedOperationException)<\/li>\n<li>clipRegion method (throws UnsupportedOperationException)<\/li>\n<li>drawPath method (throws UnsupportedOperationException)<\/li>\n<li>drawPicture method (throws UnsupportedOperationException)<\/li>\n<li>drawPatch method (throws UnsupportedOperationException)<\/li>\n<li>Paint xfermodes<\/li>\n<li>State-save flags and layer information are ignored; save(flags), saveLayer, and saveLayerAlpha all behave the same as plain save()<\/li>\n<\/ul>\n<h2>Example PDF Files<\/h2>\n<p>Some example files generated with GnuAPDF are at the links below. The source code for these is available in the Example Code section.<\/p>\n<ul>\n<li><a href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/examples\/gnuapdf_example_pdf\/graphics.pdf\">Example of basic graphics operations<\/a><\/li>\n<li><a href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/examples\/gnuapdf_example_pdf\/drawText.pdf\">Example of basic text operations<\/a><\/li>\n<li><a href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/examples\/gnuapdf_example_pdf\/transformations.pdf\">Example of matrix transformation operations<\/a><\/li>\n<li><a href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/examples\/gnuapdf_example_pdf\/clipping.pdf\">Example of clipping operations<\/a><\/li>\n<li><a href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/examples\/gnuapdf_example_pdf\/drawImage.pdf\">Example of image-handling operations<\/a><\/li>\n<li><a href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/examples\/gnuapdf_example_pdf\/drawBitmapMesh.pdf\">Example of advanced bitmap-mesh support<\/a> (stretching a bitmap across a rectangular mesh)<\/li>\n<li><a href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/examples\/gnuapdf_example_pdf\/drawVertices.pdf\">Example of advanced draw-vertices support<\/a> (Gouraud shading across a triangular mesh)<\/li>\n<\/ul>\n<h2>Example Code<\/h2>\n<p>A test project is available that illustrates how to use the library and can also be used to test its functionality.<\/p>\n<ul>\n<li><a href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/examples\/gnuapdf_example_src\/gnu\/apdftest\/PDFTest.java\">PDFTest.java<\/a><\/li>\n<li><a href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/examples\/gnuapdf_example_src\/gnu\/apdftest\/PDFTestView.java\">PDFTestView.java<\/a><\/li>\n<\/ul>\n<p><a href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/examples\/gnuapdf_example_src.tar.gz\">Download example source<\/a><\/p>\n<h2><\/h2>\n<h2>Documentation<\/h2>\n<p><a title=\"GnuAPDF Javadoc Documentation\" href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/doc\/index.html\">Browse Javadoc documentation<\/a><\/p>\n<h2><\/h2>\n<h2>Downloads<\/h2>\n<p>The downloads are supplied as compressed archives; the library archive contains the compiled gnuapdf.jar file for inclusion in a project, while the source archive contains the Java source files that can be used to rebuild the .jar file or included as source files in a referencing project.<\/p>\n<table style=\"width: 413px;\" border=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 83px;\"><strong>Version<br \/>\n<\/strong><\/td>\n<td style=\"width: 163px;\"><strong>Library (.jar)<br \/>\n<\/strong><\/td>\n<td style=\"width: 167px;\"><strong>Source<br \/>\n<\/strong><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 83px;\">Version 1.3<\/td>\n<td style=\"width: 163px;\"><a title=\"GnuAPDF Library v1.3\" href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/v1.3\/gnuapdf_lib_v1.3.zip\">gnuapdf_lib_v1.3.zip<\/a><\/td>\n<td style=\"width: 167px;\"><a title=\"GnuAPDF Source v 1.3\" href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/v1.3\/gnuapdf_src_v1.3.zip\">gnuapdf_src_v1.3.zip<\/a><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 83px;\">Version 1.2<\/td>\n<td style=\"width: 163px;\"><a title=\"GnuAPDF Library v1.2\" href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/v1.2\/gnuapdf_lib_v1.2.tar.gz\">gnuapdf_lib_v1.2.tar.gz<\/a><\/td>\n<td style=\"width: 167px;\"><a title=\"GnuAPDF Source v 1.2\" href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/v1.2\/gnuapdf_src_v1.2.tar.gz\">gnuapdf_src_v1.2.tar.gz<\/a><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 83px;\">Version 1.1<\/td>\n<td style=\"width: 163px;\"><a title=\"GnuAPDF Library v1.1\" href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/v1.1\/gnuapdf_lib_v1.1.tar.gz\">gnuapdf_lib_v1.1.tar.gz<\/a><\/td>\n<td style=\"width: 167px;\"><a title=\"GnuAPDF Source v 1.1\" href=\"http:\/\/jsevy.com\/android\/apps\/gnuapdf\/v1.1\/gnuapdf_src_v1.1.tar.gz\">gnuapdf_src_v1.1.tar.gz<\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><\/h3>\n<h3>Revision History<\/h3>\n<table style=\"height: 133px;\" border=\"1\" width=\"488\">\n<tbody>\n<tr>\n<td><strong>Version<br \/>\n<\/strong><\/td>\n<td><strong>Changes<br \/>\n<\/strong><\/td>\n<\/tr>\n<tr>\n<td>1.0<\/td>\n<td>Initial release<\/td>\n<\/tr>\n<tr>\n<td>1.1<\/td>\n<td>Bug fix for clipRect<\/td>\n<\/tr>\n<tr>\n<td>1.2<\/td>\n<td>Add support for extended ASCII (ISO-8859-1) characters<\/td>\n<\/tr>\n<tr>\n<td>1.3<\/td>\n<td>Add internationalization support for number conventions using commas in place of decimal points<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n","protected":false},"excerpt":{"rendered":"<p>The GnuAPDF library provides support for generation of PDF files using standard Android &#8220;draw&#8221; commands. The library provides a special Canvas subclass, PDFCanvas, that is associated with a PDF document and that renders draw commands into PDF syntax. A sequence of Android Canvas drawing method calls will thus create a structured PDF document that, when &hellip; <a href=\"https:\/\/jsevy.com\/wordpress\/index.php\/java-and-android\/android-apps-and-libraries\/android-pdf-library\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Android PDF Library (GnuAPDF)<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":116,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-111","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/jsevy.com\/wordpress\/index.php\/wp-json\/wp\/v2\/pages\/111","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jsevy.com\/wordpress\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/jsevy.com\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/jsevy.com\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jsevy.com\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=111"}],"version-history":[{"count":9,"href":"https:\/\/jsevy.com\/wordpress\/index.php\/wp-json\/wp\/v2\/pages\/111\/revisions"}],"predecessor-version":[{"id":2009,"href":"https:\/\/jsevy.com\/wordpress\/index.php\/wp-json\/wp\/v2\/pages\/111\/revisions\/2009"}],"up":[{"embeddable":true,"href":"https:\/\/jsevy.com\/wordpress\/index.php\/wp-json\/wp\/v2\/pages\/116"}],"wp:attachment":[{"href":"https:\/\/jsevy.com\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=111"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}