论坛首页 Java企业应用论坛

介绍一个PDF的生成方案

浏览 150980 次
该帖已经被评为良好帖
作者 正文
   发表时间:2010-07-01  
先谢谢各位,这正是我想在寻找的方案,但是在分页的时候我有一个困境,能否提供一个简单分页的例子吗?或者提供一下思路。

另外,提醒一下,如果替换了  yye_javaeye  提供的jar包,还不能实现中文换行,可能是因为项目中存在core-renderer-minimal.jar包冲突,删除它就可以了。
0 请登录后投票
   发表时间:2010-07-01  
我的pdf文档中有一张表格和其它一些信息,想要的分页效果是,只自适应将表格数据进行分页,其它信息都相同。
0 请登录后投票
   发表时间:2010-07-15  
最新发现!!!
如果修改中文显示问题中文换行就不行了(前提是不设置中文字体)。
try {  
            cb.setFontAndSize(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED), _font.getSize2D()/_dotsPerPoint);  
        } catch (Exception e) {  
            System.out.println("ITextOutputDevice.java drawString方法字体设置错误!");  
            e.printStackTrace();
        }
想换行必须加上这个
ITextFontResolver fontResolver = renderer.getFontResolver();  
fontResolver.addFont("C:\\Windows\\Fonts\\simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);  
0 请登录后投票
   发表时间:2010-07-24  
中文好像不能bold, 谁有办法解决一下 ? 谢谢
0 请登录后投票
   发表时间:2010-08-12   最后修改:2010-08-12

非常感谢yye_javaeye中文换行的代码,我参照代码修改后确实有效了。不过在yye_javaeye贴的代码里有一个bug会导致死循环,在110和122行处,应该改成
 int right = getStrRight(currentString, left + 1);

关键是left+1,如果写成left的话会导致永远对同一处的字符进行判断而导致死循环。

yye_javaeye 写道

呵呵,没注意到这个帖子,当时因为项目正着急,忘了贴上来了
修改了org.xhtmlrenderer.layout.Breaker类,添加了2个方法,修改了109行和121行,由原来的按空格分组改为调用getStrRight按新的方式分组来获取字符的右边界值:
/*
 * Breaker.java
 * Copyright (c) 2004, 2005 Torbj�rn Gannholm, 
 * Copyright (c) 2005 Wisconsin Court System
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 */
package org.xhtmlrenderer.layout;

import org.xhtmlrenderer.css.constants.IdentValue;
import org.xhtmlrenderer.css.style.CalculatedStyle;
import org.xhtmlrenderer.render.FSFont;

/**
 * A utility class that scans the text of a single inline box, looking for the 
 * next break point.
 * @author Torbj�rn Gannholm
 */
public class Breaker {

    public static void breakFirstLetter(LayoutContext c, LineBreakContext context,
            int avail, CalculatedStyle style) {
        FSFont font = style.getFSFont(c);
        context.setEnd(getFirstLetterEnd(context.getMaster(), context.getStart()));
        context.setWidth(c.getTextRenderer().getWidth(
                c.getFontContext(), font, context.getCalculatedSubstring()));
        
        if (context.getWidth() > avail) {
            context.setNeedsNewLine(true);
            context.setUnbreakable(true);
        }
    }
    
    private static int getFirstLetterEnd(String text, int start) {
        int i = start;
        while (i < text.length()) {
            char c = text.charAt(i);
            int type = Character.getType(c);
            if (type == Character.START_PUNCTUATION || 
                    type == Character.END_PUNCTUATION ||
                    type == Character.INITIAL_QUOTE_PUNCTUATION ||
                    type == Character.FINAL_QUOTE_PUNCTUATION ||
                    type == Character.OTHER_PUNCTUATION) {
                i++;
            } else {
                break;
            }
        }
        if (i < text.length()) {
            i++;
        }
        return i;
    }    
    
    public static void breakText(LayoutContext c, 
            LineBreakContext context, int avail, CalculatedStyle style) {
        FSFont font = style.getFSFont(c);
        IdentValue whitespace = style.getWhitespace();
        
        // ====== handle nowrap
        if (whitespace == IdentValue.NOWRAP) {
        	context.setEnd(context.getLast());
        	context.setWidth(c.getTextRenderer().getWidth(
                    c.getFontContext(), font, context.getCalculatedSubstring()));
            return;
        }

        //check if we should break on the next newline
        if (whitespace == IdentValue.PRE ||
                whitespace == IdentValue.PRE_WRAP ||
                whitespace == IdentValue.PRE_LINE) {
            int n = context.getStartSubstring().indexOf(WhitespaceStripper.EOL);
            if (n > -1) {
                context.setEnd(context.getStart() + n + 1);
                context.setWidth(c.getTextRenderer().getWidth(
                        c.getFontContext(), font, context.getCalculatedSubstring()));
                context.setNeedsNewLine(true);
                context.setEndsOnNL(true);
            } else if (whitespace == IdentValue.PRE) {
            	context.setEnd(context.getLast());
                context.setWidth(c.getTextRenderer().getWidth(
                        c.getFontContext(), font, context.getCalculatedSubstring()));  
            }
        }

        //check if we may wrap
        if (whitespace == IdentValue.PRE || 
                (context.isNeedsNewLine() && context.getWidth() <= avail)) {
            return;
        }
        
        context.setEndsOnNL(false);

        String currentString = context.getStartSubstring();
        int left = 0;
//        int right = currentString.indexOf(WhitespaceStripper.SPACE, left + 1);
        int right = getStrRight(currentString,left);
        int lastWrap = 0;
        int graphicsLength = 0;
        int lastGraphicsLength = 0;

        while (right > 0 && graphicsLength <= avail) {
            lastGraphicsLength = graphicsLength;
            graphicsLength += c.getTextRenderer().getWidth(
                    c.getFontContext(), font, currentString.substring(left, right));
            lastWrap = left;
            left = right;
//            right = currentString.indexOf(WhitespaceStripper.SPACE, left + 1);
            right = getStrRight(currentString,left+1);
        }

        if (graphicsLength <= avail) {
            //try for the last bit too!
            lastWrap = left;
            lastGraphicsLength = graphicsLength;
            graphicsLength += c.getTextRenderer().getWidth(
                    c.getFontContext(), font, currentString.substring(left));
        }

        if (graphicsLength <= avail) {
            context.setWidth(graphicsLength);
            context.setEnd(context.getMaster().length());
            //It fit!
            return;
        }
        
        context.setNeedsNewLine(true);

        if (lastWrap != 0) {//found a place to wrap
            context.setEnd(context.getStart() + lastWrap);
            context.setWidth(lastGraphicsLength);
        } else {//unbreakable string
            if (left == 0) {
                left = currentString.length();
            }
            
            context.setEnd(context.getStart() + left);
            context.setUnbreakable(true);
            
            if (left == currentString.length()) {
                context.setWidth(c.getTextRenderer().getWidth(
                        c.getFontContext(), font, context.getCalculatedSubstring()));
            } else {
                context.setWidth(graphicsLength);
            }
        }
        return;
    }

    private static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
            return true;
        }
        return false;
    }

    private static int getStrRight(String s,int left){
        if(left>=s.length())
            return -1;
        char[] ch = s.toCharArray();
        for(int i = left;i<ch.length;i++){
            if(isChinese(ch[i]) || ' ' == ch[i]){
                return i==0?i+1:i;
            }
        }
        return -1;
    }

}

0 请登录后投票
   发表时间:2010-08-12  
我测试了一下你写的这个CSS没有生效呢?
而且我去Flying Saucer官方网站https://xhtmlrenderer.dev.java.net/,上面写的这是一个
An XML/XHTML/CSS 2.1 Renderer,作者没说它支持CSS3啊?你的CSS3怎么能生效呢?

l116116116 写道


3。还弄过页眉上的图片,利用fs 支持css3,设置page 属性

@top-left {
                content: "sssssss";
                border-bottom: solid 0.01mm #000;
                background:transparent url(images/PartnerMgr.gif) top left no-repeat;    /*add a image at left-top corner*/
              }

0 请登录后投票
   发表时间:2010-08-12  
flyslowfood 写道
中文好像不能bold, 谁有办法解决一下 ? 谢谢

用CSS的font-weight:bold来设置试一下,不要使用<b>标签
0 请登录后投票
   发表时间:2010-08-25  
相比搂主,在javaeye里面,导出过pdf博文把! 如果这种需求呢?该如何实现?请指点!
0 请登录后投票
   发表时间:2010-08-25  
Javakeith 写道
相比搂主,在javaeye里面,导出过pdf博文把! 如果这种需求呢?该如何实现?请指点!

je的文章数据在数据库中。
套用模板生成即可。
0 请登录后投票
   发表时间:2010-08-30  
利用flyingsaucer生产PDF时遇到一些问题,比如input 怎么处理,比如<input type='text' value='111'>这样生成不了,必须<input type='text'>111</input>,页面中如果有checkbox的话也显示不出来!
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics