• xhtmlrenderer渲染pdf,中文换行


    在实际开发中,发现在table中显示中文,渲染出来的pdf,中文内容不自动换行。经过搜索发现了一种解决方案,如下:

    重写Breaker,修改right计算方式

    /*
     * 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;
        }
    }
  • 相关阅读:
    windows 10 安装可视化mycat
    YYModel 源码解读(二)之NSObject+YYModel.h (1)
    NSCharacter​Set 使用说明
    YYModel 源码解读(二)之YYClassInfo.h (3)
    Cocoa深入学习:NSOperationQueue、NSRunLoop和线程安全 (转)
    Swift 必备开发库 (高级篇) (转)
    YYModel 源码解读(二)之YYClassInfo.h (2)
    YYModel 源码解读(二)之YYClassInfo.h (1)
    Runtime应用防止按钮连续点击 (转)
    YYModel 源码解读(一)之YYModel.h
  • 原文地址:https://www.cnblogs.com/tinyking/p/6202557.html
Copyright © 2020-2023  润新知