如何提高Java2D中TextLayout.draw(..)的性能?

3
我正在使用Java2D的TextLayout类,结合LineBreakMeasurer和AttributedCharacterIterator将一段文本绘制到一个框中。文本已经被换行了。
分析表明代码非常慢,大部分时间都花费在TextLayout.draw(..)方法上。
有没有人有加速改进的建议?
    // Get iterator for string
    AttributedCharacterIterator iterator = attribText.getIterator();

    // Create measurer
    LineBreakMeasurer measurer = new LineBreakMeasurer(iterator, context);

    // loop over the lines
    int i = 1;
    while (measurer.getPosition() < iterator.getEndIndex()) {
        // Get line
        TextLayout textLayout = measurer.nextLayout(w);

        // get measurements
        float ascent  = textLayout.getAscent();
        float descent = textLayout.getDescent();
        float leading = textLayout.getLeading();
        float size    = ascent + descent;

        // Move down to baseline
        if( i == 1 ) {
            if( coverType == CoverType.SPINE ) {
                y = (box.height-size)/2;
                y -= (size+leading)*(lines-1)/2;
            } else if( vAlign == Alignment.Center ) {
                y += (h-size)/2-(size+leading)*(lines-1)/2;
            } else if( vAlign == Alignment.Bottom ) {
                y += (h-size) - (size+leading)*(lines-1);
            }
        }
        y += ascent;

        // calculate starting point for alignment
        float paintX = x;
        switch( hAlign ) {
            case Right: {
                paintX = x + w - textLayout.getVisibleAdvance();
                break;
            }
            case Center: {
                paintX = x + (w - textLayout.getVisibleAdvance())/2;
                break;
            }
        }

        // Draw line
        textLayout.draw(g2d, paintX, y);

        // Move down to top of next line
        y += descent + leading;
        i++;
    }

上面显示了相关的代码片段。attribText是先设置好的AttributtedString。context是g2d.getFontRenderContext()。

让我补充一些内容:该代码在全新的Ubuntu 10.04上运行。不确定为什么会有差异 - 但我注意到在旧的Windows XP上它实际上运行得更快(类似的机器)。不幸的是,Eclipse分析器在XP机器上无法使用,因此我无法判断该方法本身是否仍在使用更多资源,还是整体速度更快。 - kongo09
深入研究后,我意识到TextLayout.draw()隐式调用了drawGlyphVector(),这是耗时的部分。也许真正的问题是:如何使用Java2D绘制自动换行的文本,避免使用TextLayout,而是使用drawString()呢? - kongo09
你是对的!textlayout.draw()会绘制文本而不是写入;graphics.drawString()将写入文本,它比textlayout.draw()函数快得多。如果您没有特殊属性用于文本的小部分,则可以调用g2d.drawString(str.substring(posA, posB), paintX, y); 这将更快(我在我的应用程序中已经这样做了);posA和posB是在执行measurer.nextLayout(w)之前和之后刚好测量器.getPosition()。 - Alexxx
1个回答

0
这篇文章已经有些年头了,所以我希望您已经找到了适合您需求的解决方案。如果您还没有,这里有一些值得考虑的内容。您只需要绘制可见区域内的文本即可。由于您知道每行的y坐标,因此很容易检查y是否在getVisibleRect()的范围内。仅绘制必要的文本可以极大地提高性能(当然,前提是您的文本长度超过一页)。

虽然你说的通常是正确的,在我的情况下,我正在绘制一个将成为位图写入磁盘的画布。我需要绘制整个图像才能创建有意义的图像。但是我还没有找到任何好的解决方案。 - kongo09

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接