xhtmlrenderer xhtml to pdf font problem - java

I'm using org.xhtmlrenderer.pdf.ITextRenderer to convert my (x)html page to pdf using Java.
I've got most of it working, except the font part.
I'm using verdana in my page and the pdf is rendered using default font.
I have added the verdana.ttf to my jar and use the following code:
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(new StringBufferInputStream(html));
File tmpFontFile = new File(TEMP_FOLDER + "/verdana.ttf");
if(!tmpFontFile.exists())
{
tmpFontFile.createNewFile();
InputStream fontIs = getClass().getResourceAsStream("/com/mycompany/util/font/verdana.ttf");
OutputStream fontOs = new FileOutputStream(tmpFontFile);
byte buf[] = new byte[1024];
int len;
while((len = fontIs.read(buf)) > 0)
fontOs.write(buf,0,len);
fontOs.close();
fontIs.close();
}
ITextRenderer renderer = new ITextRenderer();
renderer.getFontResolver().addFont(
tmpFontFile.getAbsolutePath(), BaseFont.IDENTITY_H ,BaseFont.EMBEDDED);
renderer.setDocument(doc, null);
String outputFile = TEMP_FOLDER + "/mypdf.pdf";
OutputStream os = new FileOutputStream(outputFile);
renderer.layout();
renderer.createPDF(os);
os.close();
What am I missing here?
Thanks,
Bart

For xhtmlrenderer to work, the CSS must read:
font-family: Verdana;
instead of
font-family:verdana;
It's case-sensitive.

Related

How to Read and write InputStream to a pdf file using iText?

I have an InputStream. I am trying to read the InputStream and write it to a pdf file using iText.
I tried the following :
FileOutputStream fileout = new FileOutputStream(file);
Document document = new Document();
PdfWriter.getInstance(document, fileout);
InputStream is=null;
is = myInfo.getInputStream();
String result = IOUtils.toString(is, "UTF-8");
Paragraph paragraph=new Paragraph();
paragraph.add(result);
document.add(paragraph);
is.close();
document.close();
Here the output file contains so many unwanted characters, some XML tags etc. The output pdf file is dumped with a lot of things which are non-readable.
And I am able to write it to pdf file using the following code:
OutputStream ostream = new FileOutputStream("c:\\test\\newfile1.pdf");
byte[] data = new byte[4096];
int r = 0;
while((r = is.read(data, 0, data.length)) != -1)
{
ostream.write(data, 0, r);
}
ostream.flush();
ostream.close();
The above code helps me to write the inputstream to the pdf file. But I want to do the same thing with itext.
I am using iText for the first time and confused how to use it properly. Could someone please help me with this? Thanks.
Solution :
I changed the inputstream to bytearraay.
PdfReader pdfreader;
pdfreader = new PdfReader(myInfo.getByteArray());
PdfStamper pdfStamper = new PdfStamper(pdfreader, fileout);
pdfStamper.close();
pdfreader.close();
In this way, I am able to read the inputsteam and write to pdf using itext. Thanks everyone.

Using flying saucer convert html to Image

Using flying saucer, i successfully convert html to image using below code
//doc - html source code as org.w3c.dom.Document
Java2DRenderer renderer = new Java2DRenderer(doc, width, height);
BufferedImage img = renderer.getImage();
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", os);
But i have problems in the above code like it does not render the font properly in the html.
Also if the chinese ,Japanese or other than Ascii characters given, the image has not been rendered with proper content(characters are boxed like below).
But actual html content is
<div ><ul><li><dl><dt>イベントについて<br></dt><dd><ul><li>サポーター&フレンズ<br></li></ul></dd></dl><dl><dt>イベント・セミナー一覧<br></dt></dl></li></ul><div><br></div></div>
Also in my case, any language will come, but all encoded using unicode. How to solve this.
Please help.
String html = "<div ><ul><li><dl><dt>イベントについて<br></dt><dd><ul><li>サポーター&フレンズ<br></li></ul></dd></dl><dl><dt>イベント・セミナー一覧<br></dt></dl></li></ul><div><br></div></div>"
//Read it using Utf-8 - Based on encoding, change the encoding name if you know it
InputStream htmlStream = new ByteArrayInputStream(html.getBytes("UTF-8"));
Tidy tidy = new Tidy();
org.w3c.dom.Document doc = tidy.parseDOM(new InputStreamReader(htmlStream,"UTF-8"), null);
Java2DRenderer renderer = new Java2DRenderer(doc, width, height);
BufferedImage img = renderer.getImage();
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", os);
This solves my issue. On reading html stream using UTF-8 solves the issue.

Batik - Modify and saving of SVG results in not well formed XML

I'm trying to edit an existing SVG and save it afterwards using Batik (I need different formats and DOM-Manipulation).
What I do:
Adobe Illustrator Source File (CS 4.0) saved as SVG 1.0 with all Glyphs (two embedded Fonts)
Loaded with Batik (using SAXSVGDocumentFactory, source below)
DOM-Modifications (even without modifications the problem occurs)
Saving using SVGTranscoder
After transcoding I get a new SVG-File, which is filled with XML, but is not able to render properly in Firefox or Illustrator.
In Firefox I get the message that the XML is not well formed e.g.,
<glyph horiz-adv-x="249" unicode=""/>
My Code:
///////////////
// Load Template File (with embedded Fonts)
///////////////
File file = new File(SVGFilePath);
FileInputStream svgInputStream = new FileInputStream(file);
////////////////////
// Load SVG into DOM-Tree
////////////////////
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
Document doc = factory.createDocument(parser, svgInputStream);
//...
///////////////////////
// Generate Output File
///////////////////////
String savepath = "test.svg";
byte[] fileData = transcodeToSVG(doc);
FileOutputStream fileSave = new FileOutputStream(savepath);
fileSave.write(fileData);
fileSave.close();
My Transcoding Code:
public byte[] transcodeToSVG(Document doc) throws TranscoderException {
try {
//Determine output type:
SVGTranscoder t = new SVGTranscoder();
//Set transcoder input/output
TranscoderInput input = new TranscoderInput(doc);
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
OutputStreamWriter ostream = new OutputStreamWriter(bytestream);
TranscoderOutput output = new TranscoderOutput(ostream);
//Perform transcoding
t.transcode(input, output);
ostream.flush();
ostream.close();
return bytestream.toByteArray();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
David Conrads hint with the Unicode character lead me to the solution:
I was missing the right encoding of the file.
After changing
OutputStreamWriter ostream = new OutputStreamWriter(bytestream);
to
OutputStreamWriter ostream = new OutputStreamWriter(bytestream, "UTF-8");
it works well.

How do I create barcode image containing text at bottom using iText library

I created a pdf using the iText 2.1.7 library. The Pdf (barcodes.pdf) contains a barcode with some text at the bottom. Additionally I saved this barcode as an image (barcode.png), however then the text at bottom is lost.
How do I create the barcode image which also contains the text at bottom?
String RESULT = "c:/BarCodeQRCodeGenerator/barcodes.pdf";
Document document = new Document(new Rectangle(340, 842));
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
document.open();
PdfContentByte cb = writer.getDirectContent();
document.add(new Paragraph("Barcode 128"));
Barcode128 code128 = new Barcode128();
code128.setCode("1234567890");
Image image = code128.createImageWithBarcode(cb, null, null)
document.add(image);
java.awt.Image rawImage = code128.createAwtImage(Color.BLACK, Color.WHITE);
BufferedImage outImage = new BufferedImage(rawImage.getWidth(null), rawImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
outImage.getGraphics().drawImage(rawImage, 0, 0, null);
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
ImageIO.write(outImage, "png", bytesOut);
bytesOut.flush();
byte[] pngImageData = bytesOut.toByteArray();
FileOutputStream fos = new FileOutputStream("c:/BarCodeQRCodeGenerator/barcode.png");
fos.write(pngImageData);
fos.close();
In your code you forgot to close the document. The solution is not so easy using the plain iText classes. Thus I used barcode4j (to test the example you need to download it and put it in your classpath):
Code128Bean code128 = new Code128Bean();
code128.setHeight(15f);
code128.setModuleWidth(0.3);
code128.setQuietZone(10);
code128.doQuietZone(true);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BitmapCanvasProvider canvas = new BitmapCanvasProvider(baos, "image/x-png", 300, BufferedImage.TYPE_BYTE_BINARY, false, 0);
code128.generateBarcode(canvas, "1234567890");
canvas.finish();
//write to png file
FileOutputStream fos = new FileOutputStream("barcode.png");
fos.write(baos.toByteArray());
fos.flush();
fos.close();
//write to pdf
Image png = Image.getInstance(baos.toByteArray());
png.setAbsolutePosition(400, 685);
png.scalePercent(25);
Document document = new Document(new Rectangle(595, 842));
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("barcodes.pdf"));
document.open();
document.add(png);
document.close();
writer.close();

iText/flying-saucer PdfStamper using an OutputStream

I'm almost there (I think) on being able to render a PDF with a servlet without saving it first. I've been able to successfully set it up, but I'm stuck at trying to make the PDF open in the client's browser with a Print Dialog initially.
I've been able to send my PDF to the client successfully with the following:
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(new StringBufferInputStream(buf.toString()));
OutputStream os = resp.getOutputStream();
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, null);
renderer.layout();
renderer.createPDF(os);
os.close();
But, I'm not sure how to put a print dialog on open of it.
I've used this code for a physical PDF file, but I need to be able to read the contents of the OutputStream in as a byte array for input to the PdfReader (I think):
PdfReader reader = new PdfReader("a_physical_file.pdf");
PdfStamper stamper = new PdfStamper(reader, os);
stamper.setPageAction(PdfWriter.PAGE_OPEN, new PdfAction(PdfAction.PRINTDIALOG), 1);
stamper.close();
Not sure how to do this with an OutputStream rather than an actual file...
I've also created an iText chat room if you would like to post there: https://chat.stackoverflow.com/rooms/8945/itext
Warning : I use an old version of Itext, so my experience may not be applicable.
PdfReader can use a byte array. so you could use a ByteArrayOutputStream as your first output stream, then use it to get the reader, instead of a filename.
Regards
Edit : Regarding your question :
i'm doing it the others way around : i'm working on a ByteArrayOutputStream and then writing it in the response stream :
ByteArrayOutputStream out = new ByteArrayOutputStream();
// creating / modifying the pdf
...
byte[] pdfoutput = out.toByteArray();
res.setContentLength(pdfoutput.length);
res.getOutputStream().write(pdfoutput);
Edit 2 : the final solution (from the chat room)
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(new StringBufferInputStream(buf.toString()));
OutputStream os = new ByteArrayOutputStream();
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, null);
renderer.layout();
renderer.createPDF(os);
os.close();
PdfReader reader = new PdfReader(((ByteArrayOutputStream)os).toByteArray());
OutputStream out = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(reader, out);
stamper.setPageAction(PdfWriter.PAGE_OPEN, new PdfAction(PdfAction.PRINTDIALOG), 1);
stamper.close();
resp.getOutputStream().write(((ByteArrayOutputStream)out).toByteArray());
Instead of using PdfStamper, why don't you implement PDFCreationListener of flyingsacuer to massage any pdf created. You can get the PdfWriter instance and set the print dialogue from within the implementation class.
From the javadoc of PDFCreationListener
PDFCreationListener is the callback listener for PDF creation. To use this, call ITextRenderer.setListener(PDFCreationListener).Note that with a handle on the ITextRenderer instance (provided in the callback arguments) you can access the com.lowagie.text.pdf.PdfWriter instance being used to create the document, using
ITextRenderer.getOutputDevice(), then calling ITextOutputDevice.getWriter().
The related thread is here.

Categories

Resources