You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PDF-lib.js多行文本框文本测量与实际渲染间距不符的问题及解决方案咨询

PDF-lib.js多行文本框文本测量与实际渲染间距不符的问题及解决方案咨询

我目前正在开发一个PDF表单,需要限制多行文本框的输入内容,避免用户输入的文本超出文本框的可视范围,但现在卡在了文本测量的准确性问题上——测量结果和PDF实际渲染的文本间距总是对不上。

举个具体的例子:像"T."、"Te"、"V."这类字符串,我用context.measureText()测量时,计算出来的点(或者字母)的位置好像是紧贴着T的横杠下方、竖线右侧,但实际PDF渲染出来后,点是在T的横杠结束之后的位置。这种测量逻辑和实际渲染效果的差异,导致我总是误判文本是否已经达到最大允许宽度,完全没法精准控制输入范围。

核心问题在于:context.measureText()的测量结果,完全反映不了PDF实际渲染时的字距(kerning)和字形(glyph)定位细节——尤其是那些存在字形重叠、特殊字距的场景。我甚至确认过测量时用的字体和PDF渲染的字体是一致的,但问题依然存在。

我已经试过各种方法试图修正,但都效果很差:

  • 逐个测量每个字符的宽度然后求和
  • 用Canvas的metrics参数尝试手动调整字距

但因为根本不知道PDF渲染时实际使用的字距参数,这些方法要么误差巨大,要么完全没法适配所有字形组合,完全不是靠谱的解决方案。

附上我尝试的Canvas测量代码:

const textField = document.getElementById('text');
const statusMessage = document.getElementById('statusMessage');
const maxTextWidth = 600; // Maximum width per line in pixels
const allowedLines = 12;

// Create an offscreen canvas for text measurement
const measurementCanvas = document.createElement('canvas');
const measurementContext = measurementCanvas.getContext('2d');
measurementContext.font = '10pt Arial';

// Function to count how many wrapped lines the text occupies
function getWrappedLineCount(text, maxWidth, context) {
    let lines = 0;
    const paragraphs = text.split('\n');
    paragraphs.forEach(para => {
        if (para === "") {
            lines++;
        } else {
            const words = para.split(' ');
            let line = '';
            words.forEach(word => {
                const testLine = line ? line + ' ' + word : word;
                if (context.measureText(testLine).width > maxWidth && line !== '') {
                    lines++;
                    line = word;
                } else {
                    line = testLine;
                }
            });
            if (line !== '') {
                lines++;
            }
        }
    });
    return lines;
}

// Listen for input on the multiline text field and restrict further input if needed
textField.addEventListener('input', function() {
    let text = textField.value;
    let lines = getWrappedLineCount(text, maxTextWidth, measurementContext);
    if (lines <= allowedLines) {
        statusMessage.textContent = "Platz vorhanden";
        statusMessage.style.color = "green";
    } else {
        // Trim the text until it fits within the allowed lines.
        while (getWrappedLineCount(text, maxTextWidth, measurementContext) > allowedLines && text.length > 0) {
            text = text.slice(0, -1);
        }
        textField.value = text;
        statusMessage.textContent = "Keine Zeicheneingabe mehr möglich";
        statusMessage.style.color = "red";
    }
});

有没有大佬遇到过类似的问题?有没有什么靠谱的库或者方法,能准确测量PDF渲染时的字形定位和字距细节,从而精准限制文本输入?只要测量逻辑能和PDF渲染的字体、字形规则完全对齐,应该就能解决这个问题,但我现在实在找不到合适的方案...

备注:内容来源于stack exchange,提问作者mr_dschingis

火山引擎 最新活动