APP CPCL指令蓝牙打印文字大小自适应宽高

需求背景

一块固定宽高的区域需要打印一段文字,这段文字尽可能的大,且数据展示完整

分析

根据字数的不同,调整字体的大小,找到满足n(一行的字数)*m(多少列) < 文字字数的最大字体大小
n = Math.ceil(区域width / 文字width)
m = Math.ceil(区域height / 文字lineHeight)

字体、字体大小、文字宽高对应表CPCL指令集

在这里插入图片描述

在这里插入图片描述

方案一:

假设几种特定的字体和字体大小,计算出区域内各自n行分别展示的文字个数,写成不同的方法,根据文字个数区间调用不同的方法
缺点: 区域特定的情况下,使用情况较为特殊,适合使用场景不多的需求

方案二:

从大到小遍历CPCL字体和字体大小,获取对应的宽高,找到符合要求的m(列数)* lineHeight (行高)<= height
缺点:字体、字体大小、文字宽高是二维数组,遍历麻烦,对算法要求高

方案三

找到一个宽高适合的字体、字体大小,固定该字体和字体大小,使用指令放大该文字,找到满足m(列数)* lineHeight (行高)*scale(倍数)<= height
放大指令: SETMAG widthScale heightScale; // 为了保证字不变形,所以宽高放大同一倍数,基本的字体、字体大小选择 55 0(中文字体,个别数字英文可能会模糊);放大倍数取值0-16,0和1不放大
    /**
     * 自适应文字大小
     *
     * @param data   字符串数据
     * @param x      x位移
     * @param y      y位移
     * @param width  区域宽度
     * @param height 区域高度
     * @return
     */

    private String coverSelfAdapt(String data, int x, int y, int width, int height) {
        int scale = 16,
                // 默认文字宽高以 TEXT 55 0 x y 模式计算,不同字体、字体大小对应的基础宽高不一样
                baseWidth = 8,  // 文字基础宽度,
                baseHeight = 16, // 文字基础高度
                widthNum = 0, // 宽度可以展示多少文字
                num = 0; // 高度可以展示多少列
        boolean isFlag = false;
        while (scale > 0 && scale < 17 && !isFlag) {
            // 当字体大小满足在最小和最大之间,寻找最符合要求的最大值
            widthNum = (int) Math.ceil((double) width / (scale * baseWidth)); // 当前字体大小一行最多的字数个数
            num = (int) Math.ceil(((double) data.length()) / widthNum); // 可以打几行
            if (num == 0) {
                num = 1;
            }
            // 只能展示一行
            Log.d(TAG, "coverSelfAdapt: (" + scale + ")num: " + num + "    widthNum:" + widthNum + "    最多:" + num * widthNum + "   文字:" + data.length());
            if (num * baseHeight * scale <= height) {
                // 满足最大放大倍数条件内可以放下所有文字,跳出循环
                isFlag = true;
            } else {
                scale--;
            }
        }
        Log.e(TAG, "coverSelfAdapt: 高度差:" + (num * baseHeight * scale - height) + "     宽度差:" + (num * baseWidth * scale));
        Log.d(TAG, "coverSelfAdapt: 是否有最佳字体大小:" + isFlag + "     字体大小倍数为:" + scale + "    一行最多:" + widthNum);
        Log.d(TAG, "coverSelfAdapt: " + "    打印指令串:" + converMultiLine(data, x, y, scale, widthNum, baseHeight * scale, 4,0));
        if (isFlag && scale > 0) {
            return converMultiLine(data, x, y, scale, widthNum, baseHeight * scale,2,0);
        } else {
            Log.e(TAG, "coverSelfAdapt: no fontSize: ");
            // 不存在则最小展示,尽可能的展示多
            widthNum = (int) Math.floor(width / baseWidth);
            return converMultiLine(data, x, y, 1, widthNum, baseHeight,2,0);
        }
    }

  /**
     * 根据字体等返回多行打印指令
     *
     * @param data       文字
     * @param x          x位移
     * @param y          y位移
     * @param scale      放大倍数
     * @param num        一行的文字数量
     * @param lineHeight 文字的lineHeight
     * @return
     */
    private String converMultiLine(String data, int x, int y, int scale, int num, int lineHeight, int font, int fontSize) {
        int startY = y, startXNum = 0, endXNum = 0;
        String info = String.format("SETMAG %d %d\r\n", scale, scale);
        int index = (int) Math.ceil(((double) data.length()) / num);
        int i = 0;
        while (i < index) {
            startXNum = i * num;
            endXNum = startXNum + num;
            if (endXNum >= data.length()) {
                endXNum = data.length();
            }
            info += String.format("TEXT %d %d %d %d %s\r\n",font,fontSize, x, startY, data.substring(startXNum, endXNum));
            startY += lineHeight;
            i++;
        }
        info += "SETMAG 1 1\r\n"; // 不影响后面的文字打印
        return info;
    }

写在最后

更加自适应的方式是方案二和方案三的结合,动态计算font和fontSize再对应的找放大倍数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值