Algorithm 换行文本的算法(将文本换行以适应';页面';)

Algorithm 换行文本的算法(将文本换行以适应';页面';),algorithm,text,graphics,Algorithm,Text,Graphics,我开发了一些面向GUI的应用程序,它们实现了自己的文本换行算法。例如,考虑到我的应用程序是典型的GUI“小部件”,可以在屏幕上设置。复选框、文本字段、简单标签等小部件非常容易绘制。然而,像“段落”这样的小部件(任意数量的多行文本,应该放在指定的框中,必要时换行)由于换行部分的存在,难度要大得多 每次我实现这样一个算法时,我都会使用一种有效但效率很低的方法。我的一般方法(将字符串放入宽度为w的框中)是迭代地获取字符串s,使用字体度量来测量其像素长度l,并将其削至l w){ //从txt中删除一个单

我开发了一些面向GUI的应用程序,它们实现了自己的文本换行算法。例如,考虑到我的应用程序是典型的GUI“小部件”,可以在屏幕上设置。复选框、文本字段、简单标签等小部件非常容易绘制。然而,像“段落”这样的小部件(任意数量的多行文本,应该放在指定的框中,必要时换行)由于换行部分的存在,难度要大得多

每次我实现这样一个算法时,我都会使用一种有效但效率很低的方法。我的一般方法(将字符串放入宽度为w的框中)是迭代地获取字符串s,使用字体度量来测量其像素长度l,并将其削至l w){ //从txt中删除一个单词并重新测量它 txt=txt.substring(0,txt.lastIndexOf(“”)); m=ctx.measureText(txt); } 返回txt; };
我想知道在测量单词后跟空格的大小时,文本度量是否给出了可靠的结果。例如,
width(“aaa”)+width(“bbb”)=width(“aaa bbb”)
?如果是这样的话,你可以测量文本中的每个单词,后面有空格和没有空格,然后从中找出其余的单词。方案B(假设单词后跟空格的文本度量不能给出精确的结果)是测量没有空格的每个单词,并使用固定值来估计单词之间的空格

在我看来,当前算法的低效之处在于调用
measureText
方法O(n^2)次,并且测量长字符串的宽度。通过将文本拆分为单词并测量每个单词,您只需调用
measureText
O(n)次,并且可以在相对较短的字符串上调用它


然后,建议的算法是从每行的开头开始添加单词,直到达到换行限制。这个问题的加法方法减少了必须测量的字符串的数量,也减少了必须测量的字符串的长度。

我想知道在测量单词后跟空格的大小时,文本度量是否给出了可靠的结果。例如,
width(“aaa”)+width(“bbb”)=width(“aaa bbb”)
?如果是这样的话,你可以测量文本中的每个单词,后面有空格和没有空格,然后从中找出其余的单词。方案B(假设单词后跟空格的文本度量不能给出精确的结果)是测量没有空格的每个单词,并使用固定值来估计单词之间的空格

在我看来,当前算法的低效之处在于调用
measureText
方法O(n^2)次,并且测量长字符串的宽度。通过将文本拆分为单词并测量每个单词,您只需调用
measureText
O(n)次,并且可以在相对较短的字符串上调用它


然后,建议的算法是从每行的开头开始添加单词,直到达到换行限制。这个问题的加法方法减少了必须测量的字符串的数量,也减少了必须测量的字符串的长度。

我想知道在测量单词后跟空格的大小时,文本度量是否给出了可靠的结果。例如,
width(“aaa”)+width(“bbb”)=width(“aaa bbb”)
?如果是这样的话,你可以测量文本中的每个单词,后面有空格和没有空格,然后从中找出其余的单词。方案B(假设单词后跟空格的文本度量不能给出精确的结果)是测量没有空格的每个单词,并使用固定值来估计单词之间的空格

在我看来,当前算法的低效之处在于调用
measureText
方法O(n^2)次,并且测量长字符串的宽度。通过将文本拆分为单词并测量每个单词,您只需调用
measureText
O(n)次,并且可以在相对较短的字符串上调用它


然后,建议的算法是从每行的开头开始添加单词,直到达到换行限制。这个问题的加法方法减少了必须测量的字符串的数量,也减少了必须测量的字符串的长度。

我想知道在测量单词后跟空格的大小时,文本度量是否给出了可靠的结果。例如,
width(“aaa”)+width(“bbb”)=width(“aaa bbb”)
?如果是这样的话,你可以测量文本中的每个单词,后面有空格和没有空格,然后从中找出其余的单词。方案B(假设单词后跟空格的文本度量不能给出精确的结果)是测量没有空格的每个单词,并使用固定值来估计单词之间的空格

在我看来,当前算法的低效之处在于调用
measureText
方法O(n^2)次,并且测量长字符串的宽度。通过将文本拆分为单词并测量每个单词,您只需调用
measureText
O(n)次,并且可以在相对较短的字符串上调用它


然后,建议的算法是从每行的开头开始添加单词,直到达到换行限制。这种解决问题的附加方法减少了必须测量的字符串的数量,也减少了必须测量的字符串的长度。

您应该测量过长的字符串,以便知道瓶颈在哪里。我看不到任何明显的东西(但我不在此环境中编写代码)。从优化方面来说,避免堆垃圾(您得到了很多垃圾),例如,您将txt作为func传递
    // the paragraph widgets' main drawing function
    this.drawText = function(ctx) {
        ... 

        var lines = this.text.split("\n"); // here we account for user-entered line breaks
        var y = this.y;

        for (var i=0; i<lines.length; i++) {
            var currTxt = lines[i]; // a chunk of text in between user-entered line breaks
            var miniLines = this.breakToLines(currTxt, this.textWidth(), ctx);
            for (var j = 0; j < miniLines.length; j++) {
                var miniTxt = miniLines[j];

                var x = this.x + ( (this.round) ? this.cornerRadius : 0 );

                x += this.textOffset();
                y += this.fontSize;

                ctx.save();
                ctx.rect(this.x, this.y, this.width, this.height);
                ctx.clip();

                ctx.fillText(miniTxt, x, y);
                ctx.restore();
            }

        };
    };

    // take a chunk of text and break it into lines that fit within width 'w'
    this.breakToLines = function(txt, w, ctx) {
        var arr = [];
        while (true) {
            var txt2 = this.popLine(txt, w, ctx);
            if (txt2 == null)
                break;
            arr.push(txt2);
            if (txt.length <= txt2.length)
                break;
            txt = txt.substring(txt2.length);
        }
        return arr;
    };

    this.popLine = function(txt, w, ctx) {
        var m = ctx.measureText(txt); // 'm' represents the size of the text
        if (m.length == 0)
            return null;  // 'm' is empty, so we're done
        while (m.width > w) {
            // remove a word from txt and re-measure it
            txt = txt.substring(0, txt.lastIndexOf(' '));
            m = ctx.measureText(txt);
        }
        return txt;
    };