java 实现字符串自动换行(根据像素大小)

java 实现字符串自动换行(根据像素大小)

方法一:使用graphics2d绘图的方式实现

方法一会根据环境的字体来实现,如果是linux环境会出现异常

import lombok.extern.slf4j.Slf4j;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description:根据像素大小字符串实现换行
 * @date 2022-12-03 11:08
 */
@Slf4j
public class SubStrUtil {


    private static int index = 0;


    /**
     * 1、根据宽度截取字符串
     *
     * @param text       文本
     * @param font       字体
     * @param appointRow 行数
     * @param map        结果集
     * @param rows       行号
     * @param lineHeight 行高
     * @param maxWith    行宽
     */
    public static Map<String, Object> creatMyImage(String text, Font font, int appointRow, Map<String, Object> map, int rows, int lineHeight, int maxWith) {
        index = 0;
        BufferedImage bufferedImage = new BufferedImage(595, 842, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2d = bufferedImage.createGraphics();
        graphics2d.setColor(new Color(37, 37, 37));
        graphics2d.setFont(font);
        graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
        map = myDrawString(graphics2d, text, lineHeight, maxWith, appointRow, 0, 0, map, rows);
        return map;
    }

    /**
     * 2、根据宽度截取字符串
     *
     * @param graphics2d
     * @param text       文本
     * @param lineHeight 行高
     * @param maxWidth   行宽
     * @param maxLine    最大行数
     * @param left       左边距
     * @param top        上边距
     */
    private static Map<String, Object> myDrawString(Graphics2D graphics2d, String text, int lineHeight, int maxWidth,
                                                    int maxLine, int left, int top, Map<String, Object> map, int rows) {
        if (text == null || text.length() == 0) {
            return map;
        }
        FontMetrics fm = graphics2d.getFontMetrics();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < text.length(); i++) {
            char strChar = text.charAt(i);
            sb.append(strChar);
            int stringWidth = fm.stringWidth(sb.toString());
            if (i < 3) {
                log.error("i:" + i);
                log.error("stringWidth:" + stringWidth);
                log.error("text:" + text);
                log.error("sb.toString():" + sb.toString());
                log.error("--------------------------------------------------------------");
            }

            int strLength = text.substring(0, i).length();
            if (strLength >= 53 || strChar == '\n' || stringWidth >= maxWidth) {
                if (strChar == '\n') {
                    i += 1;

                }
                if (maxLine > 1) {
                    rows = rows + 1;
                    char value = ' ', value1 = ' ';
                    try {
                        value = text.substring(i).charAt(0);
                        value1 = text.substring(i - 1).charAt(0);
                    } catch (Exception e) {
                        /*e.printStackTrace();*/
                        System.err.println("----" + e.getMessage());
                    }

                    if (isChinesePunctuation(value) && checkCharCN(value1)) {
                        map.put("row" + rows, text.substring(0, i - 1));
                        myDrawString(graphics2d, text.substring(i - 1), lineHeight, maxWidth, maxLine - 1, left, top + lineHeight, map, rows);
                    } else {
                        map.put("row" + rows, text.substring(0, i));
                        myDrawString(graphics2d, text.substring(i), lineHeight, maxWidth, maxLine - 1, left, top + lineHeight, map, rows);
                    }
                    map.put("index", index);

                } else {
                    rows = rows + 1;
                    map.put("row" + rows, text.substring(0, i));
                    index = index + i;
                    map.put("index", index);
                }
                return map;
            }
        }
        map.put("remainingText", sb);
        return map;
    }

    // 2.1 判断字符是否是中文
    public static boolean checkCharCN(char c) {
        String s = String.valueOf(c);
        String regex = "[\u4e00-\u9fa5]";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(s);
        return m.matches();
    }

    // 2.2 判断字符是否是中文标点符号
    public static boolean isChinesePunctuation(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);

        if (ub == Character.UnicodeBlock.GENERAL_PUNCTUATION || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS
                || ub == Character.UnicodeBlock.VERTICAL_FORMS) {
            return true;

        } else {
            return false;
        }
    }
}

方法二:根据字体的具体像素和屏幕像素实现

import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.List;
import java.util.Map;


/**
 * @Description:根据像素大小字符串实现换行
 * @date 2022-12-03 11:08
 */
@Slf4j
public class SubStrUtil {
    public static String Substr(Map parm, double screenWith) {
        String text = StringUtil.doString(parm, "text");
        //占位符
        String placeholder1 = StringUtil.doString(parm, "placeholder1");
        String placeholder2 = StringUtil.doString(parm, "placeholder2");
        //统计字符串像素
        double num = 0;
        int startIndex = 0;
        int endIndex = 0;
        int textLength = text.length();
        int countLine = 0;
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < textLength; i++) {
            if (num >= screenWith) {
                if (countLine == 0) {
                    String substring = text.substring(startIndex, endIndex);
                    result.append(placeholder1 + substring + "</br>");
                    countLine = i;
                    startIndex = i;
                    num = 0;
                } else {
                    String substring = text.substring(startIndex, endIndex);
                    result.append(placeholder2 + substring + "</br>");
                    countLine = i;
                    startIndex = i;
                    num = 0;
                }


            } else if ((num < screenWith) && (i == textLength - 1)) {
                if (countLine == 0) {
                    String substring = text.substring(startIndex, endIndex + 1);
                    result.append(placeholder1 + substring + "</br>");
                    countLine = i;
                    startIndex = i;
                } else {
                    String substring = text.substring(startIndex, endIndex + 1);
                    result.append(placeholder2 + substring + "</br>");
                    countLine = i;
                    startIndex = i;
                }

            }
            double resultNum = countCharPx(text.charAt(i));
            endIndex = i + 1;
            num += resultNum;


        }
        return result.toString();
    }

    /**
     * 说明:默认字体为【font-family: 方正楷体简体; font-size: 11.0pt; font-weight: 400;】
     * <p>
     * 汉字:[19968,40869]
     * 数字:[48,57]
     * 大写字母:[65,90]
     * 小写字母:[97-122]
     * 连字符-:45
     * 圆括号:40,41
     * 全角圆括号(中文括号):65288,65289
     * 英文逗号 44
     * 英文句号 46
     * 中文逗号 65292
     *
     * @param chars 单个字符
     * @return
     */

    public static double countCharPx(char chars) {
        double maxWith = 0;
        //中文标点(包含中文文字)所占像素大小
        double chineseSymbolsPx = 14.67;
        //英文标点所占像素大小
        double englishSymbolsPx = 3.56;
        //数字所占像素大小
        double numPx = 8.61;
        //连接符所占像素大小
        double linePx = 6.34;
        //大写字母所占像素大小
        double upperCharPx = 10.33;
        //小写字母所占像素大小
        double lowerCharPx = 8.11;
        //其他符号所占像素大小
        double otherSymbolsPx = 9.36;

        //中文标点符号合集
        List chineseSymbols = Arrays.asList(8211, 8212, 8216, 8217, 8220, 8221,
                8230, 12289, 12290, 12296, 12297, 12298,
                12299, 12300, 12301, 12302, 12303, 12304,
                12305, 12308, 12309, 65281, 65288, 65289,
                65292, 65294, 65306, 65307, 65311);

        int charType = (int) chars;

        if (chineseSymbols.contains(charType) || (charType >= 19968 && charType <= 40869)) {
            //汉字/中文标点
            maxWith = chineseSymbolsPx;

        } else if (charType >= 48 && charType <= 57) {
            //数字
            maxWith = numPx;

        } else if (charType >= 65 && charType <= 90) {
            //大写字母
            maxWith = upperCharPx;
        } else if (charType >= 97 && charType <= 122) {
            //小写字母
            maxWith = lowerCharPx;
        } else if (charType == 44 || charType == 46) {
            //英文逗号/句号
            maxWith = englishSymbolsPx;
        } else {
            maxWith = otherSymbolsPx;
        }
        return maxWith;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值