Project

General

Profile

« Previous | Next » 

Revision 33303

better font for pdfs

View differences:

modules/dnet-eagle-workflows/trunk/src/main/java/eu/dnetlib/data/provision/pdf/PdfMaterializerController.java
6 6
import java.util.List;
7 7

  
8 8
import javax.annotation.Resource;
9
import javax.servlet.ServletOutputStream;
9 10
import javax.servlet.http.HttpServletRequest;
10 11
import javax.servlet.http.HttpServletResponse;
11 12

  
......
14 15
import org.apache.pdfbox.exceptions.COSVisitorException;
15 16
import org.apache.pdfbox.pdmodel.PDDocument;
16 17
import org.apache.pdfbox.pdmodel.PDPage;
17
import org.apache.pdfbox.pdmodel.common.PDRectangle;
18 18
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
19 19
import org.apache.pdfbox.pdmodel.font.PDFont;
20
import org.apache.pdfbox.pdmodel.font.PDType1Font;
20
import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
21 21
import org.dom4j.DocumentException;
22 22
import org.dom4j.io.SAXReader;
23 23
import org.springframework.beans.factory.annotation.Value;
24
import org.springframework.core.io.ClassPathResource;
24 25
import org.springframework.http.HttpStatus;
25 26
import org.springframework.stereotype.Controller;
26 27
import org.springframework.web.bind.annotation.ExceptionHandler;
......
62 63
	@Value("${eagle.provision.pdf.index.text.xpath}")
63 64
	private String textXpath;
64 65

  
66
	private ClassPathResource trueType = new ClassPathResource("/eu/dnetlib/data/provision/pdf/lmroman10-regular.ttf");
67

  
65 68
	@RequestMapping("/pdfs/{id}")
66 69
	public void generatePdfFromId(final HttpServletRequest request, final HttpServletResponse response, @PathVariable final String id) throws IOException,
67 70
	COSVisitorException, IndexClientException, DocumentException {
68 71
		log.info("Materializing pdf");
69
		PDDocument document = null;
70
		try {
71
			// Create a document and add a page to it
72
			document = new PDDocument();
73
			PDPage page = new PDPage();
74
			document.addPage(page);
75 72

  
76
			// Start a new content stream which will "hold" the to be created content
77
			PDPageContentStream contentStream = new PDPageContentStream(document, page);
73
		List<String> arrayList = new ArrayList<String>();
74
		arrayList.add(getTextToPrint(id));
78 75

  
79
			PDFont font = PDType1Font.HELVETICA;
80
			float leading = LEADING_SPACE * FONT_SIZE;
76
		writeText(arrayList, response.getOutputStream());
81 77

  
82
			PDRectangle mediabox = page.findMediaBox();
83
			float width = mediabox.getWidth() - 2 * MARGIN;
84
			float startX = mediabox.getLowerLeftX() + MARGIN;
85
			float startY = mediabox.getUpperRightY() - MARGIN;
78
	}
86 79

  
87
			String text = getTextToPrint(id);
80
	public void writeText(final List<String> arrayList, final ServletOutputStream outputStream) throws IOException,
81
	COSVisitorException {
82
		PDDocument document = new PDDocument();
83
		PDPage page = new PDPage();
84
		// PDFont font = PDType1Font.HELVETICA;
85
		PDFont font = PDTrueTypeFont.loadTTF(document, trueType.getInputStream());
86
		int positionX = 30;
87
		int positionY = 750;
88 88

  
89
			// Chunk lines
90
			List<String> lines = new ArrayList<String>();
91
			int lastSpace = -1;
92
			while (text.length() > 0) {
93
				int spaceIndex = text.indexOf(' ', lastSpace + 1);
94
				if (spaceIndex < 0) {
95
					lines.add(text);
96
					text = "";
97
				}
98
				else {
99
					String subString = text.substring(0, spaceIndex);
100
					float size = FONT_SIZE * font.getStringWidth(subString) / 1000;
101
					if (size > width) {
102
						if (lastSpace < 0) {
103
							lastSpace = spaceIndex;
104
						}
105
						subString = text.substring(0, lastSpace);
106
						lines.add(subString);
107
						text = text.substring(lastSpace).trim();
108
						lastSpace = -1;
109
					}
110
					else {
111
						lastSpace = spaceIndex;
112
					}
113
				}
114
			}
89
		document.addPage(page);
115 90

  
116
			contentStream.beginText();
117
			contentStream.setFont(font, FONT_SIZE);
118
			contentStream.moveTextPositionByAmount(startX, startY);
119
			for (String line : lines) {
120
				contentStream.drawString(line);
121
				contentStream.moveTextPositionByAmount(0, -leading);
91
		// Start a new content stream
92
		PDPageContentStream contentStream = new PDPageContentStream(document, page);
93

  
94
		// Define a text content stream using the selected font, moving the cursor and drawing the text in arrayList
95
		for (int i = 0; i < arrayList.size(); i++) {
96
			String text = arrayList.get(i);
97
			String[] tmpText = splitString(text);
98
			for (int k = 0; k < tmpText.length; k++) {
99
				contentStream.beginText();
100
				contentStream.setFont(font, 12);
101
				contentStream.moveTextPositionByAmount(positionX, positionY);
102
				contentStream.drawString(tmpText[k]);
103
				contentStream.endText();
104
				positionY = positionY - 20;
122 105
			}
123
			contentStream.endText();
124
			contentStream.close();
106
			contentStream.setLineWidth((float) 0.25);
107
		}
125 108

  
126
			document.save(response.getOutputStream());
127
		} finally {
128
			if (document != null) {
129
				document.close();
109
		// Make sure that the content stream is closed:
110
		contentStream.close();
111
		document.save(outputStream);
112
		document.close();
113
	}
114

  
115
	public String[] splitString(final String text) {
116
		/*
117
		 * pdfBox doesnt support linebreaks. Therefore, following steps are requierd to automatically put linebreaks in the pdf 1) split
118
		 * each word in string that has to be linefeded and put them into an array of string, e.g. String [] parts 2) create an array of
119
		 * stringbuffer with (textlength/(number of characters in a line)), e.g. 280/70=5 >> we need 5 linebreaks! 3) put the parts into the
120
		 * stringbuffer[i], until the limit of maximum number of characters in a line is allowed, 4) loop until stringbuffer.length <
121
		 * linebreaks
122
		 */
123
		int linebreaks = text.length() / 40; // how many linebreaks do I need?
124
		String[] newText = new String[linebreaks + 1];
125
		String tmpText = text;
126
		String[] parts = tmpText.split(" "); // save each word into an array-element
127

  
128
		// split each word in String into a an array of String text.
129
		StringBuffer[] stringBuffer = new StringBuffer[linebreaks + 1]; // StringBuffer is necessary because of manipulating text
130
		int i = 0; // initialize counter
131
		int totalTextLength = 0;
132
		for (int k = 0; k < linebreaks + 1; k++) {
133
			stringBuffer[k] = new StringBuffer();
134
			while (true) {
135
				if (i >= parts.length)
136
				{
137
					break; // avoid NullPointerException
138
				}
139
				totalTextLength = totalTextLength + parts[i].length(); // count each word in String
140
				if (totalTextLength > 40)
141
				{
142
					break; // put each word in a stringbuffer until string length is >80
143
				}
144
				stringBuffer[k].append(parts[i]);
145
				stringBuffer[k].append(" ");
146
				i++;
130 147
			}
148
			// reset counter, save linebreaked text into the array, finally convert it to a string
149
			totalTextLength = 0;
150
			newText[k] = stringBuffer[k].toString();
131 151
		}
152
		return newText;
132 153
	}
133 154

  
134 155
	private String getTextToPrint(final String id) throws IndexClientException, DocumentException {

Also available in: Unified diff