首先,当然是找到能够解析PDF的完美组件,百度和谷歌不约而同的告诉我们。IText是王道。而目前开源的组件中,Itext的确是一个First Choice,如果各位单纯是做把图片转成PDF或者自己写了Velocity或者FreeMarker模板生成了HTML是非常推荐直接用Itext来进行的。
下面就是用Flying Saucer(xhtmlrendere)来实现的代码:
loading...
传入对应的HTML路径和PDF生成完成后的输入路径,字体我是先在工程中建立一个文件夹然后把对应的字体放入进去,这样做的一个好处不管工程是在Windows还是linux都可以识别出来使用的字体。renderer.getSharedContext().setBaseURL(src);指定图片的路径。
修改源码包中的BREAK.class重新计算右边距即可解决,代码:
/** <a href="http://www.cpupk.com/decompiler">Eclipse Class Decompiler</a> plugin, Copyright (c) 2017 Chen Chao. **/
/* */ package org.xhtmlrenderer.layout;
/* */
/* */ import org.xhtmlrenderer.css.constants.IdentValue;
/* */ import org.xhtmlrenderer.css.style.CalculatedStyle;
/* */ import org.xhtmlrenderer.extend.TextRenderer;
/* */ import org.xhtmlrenderer.render.FSFont;
/* */
/* */ public class Breaker
/* */ {
/* */ public static void breakFirstLetter(LayoutContext c, LineBreakContext context, int avail,
CalculatedStyle style)
/* */ {
/* 12 */ FSFont font = style.getFSFont(c);
/* 13 */ context.setEnd(getFirstLetterEnd(context.getMaster(), context.getStart()));
/* 14 */ context.setWidth(
c.getTextRenderer().getWidth(/* 15 */ c.getFontContext(), font, context.getCalculatedSubstring()));
/* */
/* 17 */ if (context.getWidth() > avail) {
/* 18 */ context.setNeedsNewLine(true);
/* 19 */ context.setUnbreakable(true);
/* */ }
/* */ }
/* */
/* */ private static int getFirstLetterEnd(String text, int start) {
/* 24 */ int i = start;
/* 25 */ while (i < text.length()) {
/* 26 */ char c = text.charAt(i);
/* 27 */ int type = Character.getType(c);
/* 28 */ if ((type != 21) &&
/* 29 */ (type != 22) &&
/* 30 */ (type != 29) &&
/* 31 */ (type != 30) &&
/* 32 */ (type != 24))
break;
/* 33 */ ++i;
/* */ }
/* */
/* 36 */ if (i < text.length()) {
/* 37 */ ++i;
/* */ }
/* 39 */ return i;
/* */ }
/* */
/* */ public static void breakText(LayoutContext c, LineBreakContext context, int avail, CalculatedStyle style)
/* */ {
/* 44 */ FSFont font = style.getFSFont(c);
/* 45 */ IdentValue whitespace = style.getWhitespace();
/* */
/* 47 */ if (whitespace == IdentValue.NOWRAP) {
/* 48 */ context.setEnd(context.getLast());
/* 49 */ context.setWidth(
c.getTextRenderer().getWidth(/* 50 */ c.getFontContext(), font, context.getCalculatedSubstring()));
/* 51 */ return;
/* */ }
/* */
/* 54 */ if ((whitespace == IdentValue.PRE) ||
/* 55 */ (whitespace == IdentValue.PRE_WRAP) ||
/* 56 */ (whitespace == IdentValue.PRE_LINE)) {
/* 57 */ int n = context.getStartSubstring().indexOf("\n");
/* 58 */ if (n > -1) {
/* 59 */ context.setEnd(context.getStart() + n + 1);
/* 60 */ context.setWidth(c.getTextRenderer().getWidth(/* 61 */ c.getFontContext(), font,
context.getCalculatedSubstring()));
/* 62 */ context.setNeedsNewLine(true);
/* 63 */ context.setEndsOnNL(true);
/* 64 */ } else if (whitespace == IdentValue.PRE) {
/* 65 */ context.setEnd(context.getLast());
/* 66 */ context.setWidth(c.getTextRenderer().getWidth(/* 67 */ c.getFontContext(), font,
context.getCalculatedSubstring()));
/* */ }
/* */
/* */ }
/* */
/* 72 */ if ((whitespace == IdentValue.PRE) || (
/* 73 */ (context.isNeedsNewLine()) && (context.getWidth() <= avail))) {
/* 74 */ return;
/* */ }
/* */
/* 77 */ context.setEndsOnNL(false);
/* */
/* 79 */ String currentString = context.getStartSubstring();
/* 80 */ int left = 0;
/* */
/* 82 */ int right = getStrRight(currentString, left + 1);
/* 83 */ int lastWrap = 0;
/* 84 */ int graphicsLength = 0;
/* 85 */ int lastGraphicsLength = 0;
/* */
/* 87 */ while ((right > 0) && (graphicsLength <= avail)) {
/* 88 */ lastGraphicsLength = graphicsLength;
/* */
/* 91 */ graphicsLength = graphicsLength + c.getTextRenderer()/* 91 */ .getWidth(c.getFontContext(), font,
currentString.substring(left, right));
/* 92 */ lastWrap = left;
/* 93 */ left = right;
/* */
/* 95 */ right = getStrRight(currentString, left + 1);
/* */ }
/* */
/* 98 */ if (graphicsLength <= avail)
/* */ {
/* 100 */ lastWrap = left;
/* 101 */ lastGraphicsLength = graphicsLength;
/* */
/* 104 */ graphicsLength = graphicsLength
+ c.getTextRenderer()/* 104 */ .getWidth(c.getFontContext(), font, currentString.substring(left));
/* */ }
/* */
/* 107 */ if (graphicsLength <= avail) {
/* 108 */ context.setWidth(graphicsLength);
/* 109 */ context.setEnd(context.getMaster().length());
/* */
/* 111 */ return;
/* */ }
/* */
/* 114 */ context.setNeedsNewLine(true);
/* */
/* 116 */ if (lastWrap != 0) {
/* 117 */ context.setEnd(context.getStart() + lastWrap);
/* 118 */ context.setWidth(lastGraphicsLength);
/* */ } else {
/* 120 */ if (left == 0) {
/* 121 */ left = currentString.length();
/* */ }
/* */
/* 124 */ context.setEnd(context.getStart() + left);
/* 125 */ context.setUnbreakable(true);
/* */
/* 127 */ if (left == currentString.length())
/* 128 */ context.setWidth(c.getTextRenderer().getWidth(/* 129 */ c.getFontContext(), font,
context.getCalculatedSubstring()));
/* */ else/* 131 */ context.setWidth(graphicsLength);
/* */ }
/* */ }
/* */
/* */ private static boolean isChinese(char c)
/* */ {
/* 137 */ Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
/* */
/* 144 */ return ((ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS) ||
/* 139 */ (ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS) ||
/* 140 */ (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A) ||
/* 141 */ (ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION) ||
/* 142 */ (ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) ||
/* 143 */ (ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS));
/* */ }
/* */
/* */ private static int getStrRight(String a, int left)
/* */ {
/* 150 */ if (left > a.length())
return -1;
/* 151 */ char[] ch = a.toCharArray();
/* 152 */ int i = left;
if (i < ch.length) {
/* 153 */ if ((isChinese(ch[i])) || (' ' == ch[i])) {
/* 154 */ return ((i == 0) ? i + 1 : i);
/* */ }
/* 156 */ return ((i == 0) ? i + 1 : i);
/* */ }
/* */
/* 159 */ return -1;
/* */ }
/* */ }
本人是个新手程序员,如有写错请大牛指导,有关xhtmlrenderer进行HTML转PDF的知识可以互相交流。