How can i convert HTML with SVG content to PDF usi

2019-08-18 04:55发布

问题:

I have a requirement to convert HTML with SVG Content to PDF using Itext. I am using latest Itext version along with Html2Pdf jar. I tried to implement but the generated PDF does not render the SVG content properly. The SVG content is messed up. I do not have any control on SVG content generation in PDF. I have pasted the implementation code and sample HTML below . Can anyone please let me know how can I achieve it ?

Here is the test code

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.MalformedURLException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.io.IOUtils;

import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.attach.impl.OutlineHandler;
import com.itextpdf.io.font.FontProgram;
import com.itextpdf.io.font.FontProgramFactory;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Style;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.borders.SolidBorder;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.font.FontProvider;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
import com.itextpdf.styledxmlparser.css.media.MediaDeviceDescription;

public class HtmlConvert {

public static void main(String[] args) {

        String uuid = UUID.randomUUID().toString();
          try{                           
              ConverterProperties properties = new ConverterProperties();
              String fonts[] = {Paths.get("fonts").toAbsolutePath() + "/TREBUC.TTF", Paths.get("fonts").toAbsolutePath() + "/TREBUCBD.TTF", Paths.get("fonts").toAbsolutePath() + "/TREBUCBI.TTF",Paths.get("fonts").toAbsolutePath() + "/TREBUCIT.TTF"};
              FontProvider fontProvider = new FontProvider();
               Map<String, PdfFont> pdfFontMap = new HashMap();
              for (String font : fonts) {
                 FontProgram fontProgram = FontProgramFactory.createFont(font);
                 if(font.endsWith("TREBUC.TTF")) {
                     pdfFontMap.put("NORMAL", PdfFontFactory.createFont(fontProgram, PdfEncodings.WINANSI, true));
                 } else if(font.endsWith("TREBUCBD.TTF")) {
                     pdfFontMap.put("BOLD", PdfFontFactory.createFont(fontProgram, PdfEncodings.WINANSI, true));
                 } else if(font.endsWith("TREBUCBI.TTF")) {
                     pdfFontMap.put("BOLD_ITALIC", PdfFontFactory.createFont(fontProgram, PdfEncodings.WINANSI, true));
                 } else if(font.endsWith("TREBUCIT.TTF")) {
                     pdfFontMap.put("ITALIC", PdfFontFactory.createFont(fontProgram, PdfEncodings.WINANSI, true));
                 }

                 fontProvider.addFont(fontProgram);
              }
             properties.setFontProvider(fontProvider);
             properties.setMediaDeviceDescription(new MediaDeviceDescription(com.itextpdf.styledxmlparser.css.media.MediaType.PRINT));
             List<Map<String, Object>> userData = new ArrayList<Map<String,Object>>();
             Map<String,Object> userMap = new HashMap<String, Object>();
             userMap.put("user","testusername");
             userMap.put("name","Nithin");
             userMap.put("dateTime","20/05/2019");
             userMap.put("orgnName","TEST");
             userMap.put("wGnrName","TEST");
             userMap.put("dpVerNum","3");
             userData.add(userMap);
             List<Map<String, Object>> headerData = new ArrayList<Map<String,Object>>();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            PdfWriter writer = new PdfWriter(byteArrayOutputStream);
            PdfDocument pdfDoc = new PdfDocument(writer);
            HtmlConvert htmlConvert = new HtmlConvert();
            NormalPageHeader headerHandler = htmlConvert.new NormalPageHeader(Paths.get("images").toAbsolutePath() + "\\logo.png", userData, headerData, pdfFontMap);
            pdfDoc.addEventHandler(PdfDocumentEvent.START_PAGE, headerHandler);
            PageEndEvent pageEndEvent = htmlConvert.new PageEndEvent(Paths.get("images").toAbsolutePath() + "\\FooterLineExternal.png" ,pdfFontMap);
            pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, pageEndEvent);

            OutlineHandler outlineHandler = OutlineHandler.createStandardHandler();
            properties.setOutlineHandler(outlineHandler);
            String theString2 = IOUtils.toString(new FileInputStream(new File(Paths.get("Input").toAbsolutePath()+"/test.html")), "UTF-8");
            HtmlConverter.convertToPdf(theString2, pdfDoc, properties);         
            FileOutputStream outputStream = new FileOutputStream(new File(Paths.get("Output").toAbsolutePath()+"/htmlconverted.pdf"));    
            outputStream.write(byteArrayOutputStream.toByteArray());
            outputStream.close();
            pdfDoc.close();
               System.out.println("Converted to PDF Succesfully >>> convertedSvg_"+uuid+".pdf");
           }catch(Exception e){
               e.printStackTrace();
               System.out.println("Error Occured while converting to PDF = " + e.getMessage());
           }
        }   


    class NormalPageHeader implements IEventHandler {

           String header;
           List<Map<String, Object>> data;
           List<Map<String, Object>> user;
           Map<String, PdfFont> font;
           public NormalPageHeader(String header, List<Map<String, Object>> user, List<Map<String, Object>> data, Map<String, PdfFont> font) {
             this.font = font;
               this.header = header;
               this.data = data;
               this.user = user;

           }

           @Override

           public void handleEvent(Event event) {

               //Retrieve document and

              PdfDocumentEvent docEvent = (PdfDocumentEvent) event;

              PdfDocument pdf = docEvent.getDocument();

              PdfPage page = docEvent.getPage();          
              Rectangle pageSize = page.getPageSize();

              PdfCanvas pdfCanvas = new PdfCanvas(

              page.getLastContentStream(), page.getResources(), pdf);

              Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);

              canvas.setFontSize(10f);
              Table table = new Table(3);

              table.setBorder(Border.NO_BORDER);
              table.setWidth(UnitValue.createPercentValue(100));
              Cell leftCell = new Cell();
              leftCell.setFont(font.get("NORMAL"));
              leftCell.setPaddingTop(15);
              leftCell.setPaddingLeft(20);
              leftCell.setBorder(Border.NO_BORDER);
              leftCell.setBorderBottom(new SolidBorder(0.5f));
              leftCell.setWidth(UnitValue.createPercentValue(33.3f));
              Text userLabel = new Text("Username: ");
              userLabel.setBold();
              Paragraph paragraph = new Paragraph(userLabel);
              paragraph.add( new Text(String.valueOf(user.get(0).get("user"))));
              paragraph.setFontColor(com.itextpdf.kernel.colors.ColorConstants.GRAY);
              paragraph.setTextAlignment(TextAlignment.LEFT);

              paragraph.setFontSize(8);
              leftCell.add(paragraph);
              Text dbLabel = new Text("Database: ");
              dbLabel.setBold();
              paragraph = new Paragraph(dbLabel);
              paragraph.add( new Text(String.valueOf(user.get(0).get("name"))));
              paragraph.setFontColor(com.itextpdf.kernel.colors.ColorConstants.GRAY);
              paragraph.setTextAlignment(TextAlignment.LEFT);
              paragraph.setFontSize(8);
              leftCell.add(paragraph);
              Text dtLabel = new Text("Date: ");
              dtLabel.setBold();
              paragraph = new Paragraph(dtLabel);
              paragraph.add( new Text(String.valueOf(user.get(0).get("dateTime"))));
              paragraph.setFontColor(com.itextpdf.kernel.colors.ColorConstants.GRAY);
              paragraph.setTextAlignment(TextAlignment.LEFT);
              paragraph.setFontSize(8);
              leftCell.add(paragraph);
              table.addCell(leftCell);
              Cell middleCell = new Cell();
              middleCell.setFont(font.get("NORMAL"));
              middleCell.setPaddingTop(15);
              middleCell.setBorder(Border.NO_BORDER);
              middleCell.setBorderBottom(new SolidBorder(0.5f));
              middleCell.setWidth(UnitValue.createPercentValue(33.3f));
              paragraph = new Paragraph("Test header");
              paragraph.setTextAlignment(TextAlignment.CENTER);
              paragraph.setBold();
              paragraph.setFontSize(12);
              middleCell.add(paragraph);
              paragraph = new Paragraph(String.valueOf(user.get(0).get("orgnName")));
              paragraph.setTextAlignment(TextAlignment.CENTER);
              paragraph.setBold();
              paragraph.setFontSize(10);
              middleCell.add(paragraph);

              paragraph = new Paragraph("TEST");
              paragraph.setTextAlignment(TextAlignment.CENTER);
              paragraph.setBold();
              paragraph.setFontSize(10);
              middleCell.add(paragraph);

              table.addCell(middleCell);
              Cell rightCell = new Cell();
              rightCell.setFont(font.get("NORMAL"));
              rightCell.setPaddingTop(20);
              rightCell.setWidth(UnitValue.createPercentValue(33.3f));
              rightCell.setHorizontalAlignment(HorizontalAlignment.RIGHT);
              rightCell.setBorder(Border.NO_BORDER);
              rightCell.setBorderBottom(new SolidBorder(0.5f));
              rightCell.setPaddingRight(20);
              //Write text at position
              Image img;
            try {
                img = new Image(ImageDataFactory.create(header));
                img.setHorizontalAlignment(HorizontalAlignment.RIGHT);
                Style style = new Style();
                style.setWidth(91);
                style.setHeight(25);

                img.addStyle(style);
                rightCell.add(img);
                table.addCell(rightCell);
                table.setMarginLeft(15);
                table.setMarginRight(15);
                canvas.add(table);
            } catch (MalformedURLException e) {

                e.printStackTrace();
            }

        }

       }
        class PageEndEvent implements IEventHandler {

           protected PdfFormXObject placeholder;

           protected float side = 20;

           protected float x = 420;

           protected float y = 20;

           protected float space = 4.5f;
           private String bar;
           protected float descent = 3;
           Map<String, PdfFont> font;
           public PageEndEvent(String bar, Map<String, PdfFont> font) {
             this.font = font;
             this.bar = bar;
               placeholder = new PdfFormXObject(new Rectangle(0, 0, side, side));

           }

           @Override

           public void handleEvent(Event event) {
             Table table = new Table(3);

               table.setBorder(Border.NO_BORDER);
               table.setWidth(UnitValue.createPercentValue(100));
               Cell confCell = new Cell();
               confCell.setFont(font.get("NORMAL"));
               confCell.setPaddingTop(15);
               confCell.setPaddingLeft(40);
               confCell.setBorder(Border.NO_BORDER);
               confCell.setBorderBottom(new SolidBorder(0.5f));
               confCell.setWidth(UnitValue.createPercentValue(100));
               PdfDocumentEvent docEvent = (PdfDocumentEvent) event;

               PdfDocument pdf = docEvent.getDocument();

               PdfPage page = docEvent.getPage();

               Rectangle pageSize = page.getPageSize();

               PdfCanvas pdfCanvas = new PdfCanvas(

               page.getLastContentStream(), page.getResources(), pdf);

               Canvas canvas = new Canvas(pdfCanvas, pdf, pageSize);
               Image img;
                try {
                        img = new Image(ImageDataFactory.create(bar));
                        img.setHorizontalAlignment(HorizontalAlignment.LEFT);
                        Style style = new Style();
                        style.setWidth(UnitValue.createPercentValue(100));
                        style.setHeight(50);
                        img.addStyle(style);

                        Paragraph p = new Paragraph().add("TEST FOOTER");
                        p.setFont(font.get("NORMAL"));
                        p.setFontSize(8);
                        p.setFontColor(com.itextpdf.kernel.colors.ColorConstants.GRAY);
                        canvas.showTextAligned(p, x, y, TextAlignment.CENTER);
                        pdfCanvas.addXObject(placeholder, x + space, y - descent);
                        pdfCanvas.release();
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }

           }

           public void writeTotal(PdfDocument pdf) {

               Canvas canvas = new Canvas(placeholder, pdf);

               canvas.showTextAligned(String.valueOf(pdf.getNumberOfPages()),

                       0, descent, TextAlignment.LEFT);

            }
          }

}

HTML code

<html>

    <head>
    <title></title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

</head>
<body>
    <div>
  <p>Taken from wikpedia</p>

    <svg xmlns="http://www.w3.org/2000/svg" height="400" width="100%">
   <path id="lineAB" d="M 100 350 l 150 -300" stroke="red"
   stroke-width="3" fill="none" />
   <path id="lineBC" d="M 250 50 l 150 300" stroke="red"
   stroke-width="3" fill="none" />
   <path d="M 175 200 l 150 0" stroke="green" stroke-width="3"
   fill="none" />
   <path d="M 100 350 q 150 -300 300 0" stroke="blue"
   stroke-width="5" fill="none" />
   <!-- Mark relevant points -->
   <g stroke="black" stroke-width="3" fill="black">
     <circle id="pointA" cx="100" cy="350" r="3" />
     <circle id="pointB" cx="250" cy="50" r="3" />
     <circle id="pointC" cx="400" cy="350" r="3" />
   </g>
   <!-- Label the points -->
   <g font-size="30" font-family="sans-serif" fill="black" stroke="none"
   text-anchor="middle">
     <text x="100" y="350" dx="-30">A</text>
     <text x="250" y="50" dy="-10">B</text>
     <text x="400" y="350" dx="30">C</text>
   </g>
    </svg> 
</div>
</body>
</html>