Can I make QPainter fonts operate in the same unit

2019-08-20 14:46发布

问题:

I started with this

void draw_text (QPainter & p, const QString & text, QRectF target)
{
    float scale = calculate_font_scale (p, text, target); // about 0.0005

    QFont f = p .font ();
    float old_size = f .pointSizeF ();
    f .setPointSizeF (old_size * scale);
    p .setFont (f);

    // this prints the new font size correctly
    qWarning ("old: %f, new: %f", old_size, p .font () .pointSizeF ());

    // but that doesn't seem to affect this at all
    p .drawText (position, text);
}

The QPainter's font has size has been correctly updated, as the qWarning line indicates, but the text draws much, much to big. I think this is because the QPainter coordinate system has been zoomed-in quite a lot and it seems setPointSizeF only works with sizes of at least 1. By eye it seems that the font is one "unit" high so I'll buy that explanation, although it's stupid.

I experimented with using setPixelSize instead, and although p.fontMetrics().boundingRect(text) yields a sane-looking answer, it is given in pixel units. One requirement for the above-function is that the bounding rect of the text is horizontally and vertically centred with respect to the target argument, which is in coordinates of a vastly different scale, so the arithmetic is no longer valid and the text is drawn miles off-screen.

I want to be able to transform the coordinate system arbitrarily and if, at the point, one "unit" is a thousand pixels high and I'm drawing text in a 0.03x0.03 unit box then I want the font to be 30 pixels high, obviously, but I need all my geometry to be calculated in general units all the time, and I need fontMetrics::boundingRect to be in these same general units.

Is there any way out of this or do I have to dick around with pixel calculations to appease the font API?

回答1:

You simply have to undo whatever "crazy" scaling there was on the painter.

// Save the state
p.save();
// Translate the center of `target` to 0,0.
p.translate(-target.center());
// Scale so that the target has a "reasonable" size
qreal dim = 256.0;
qreal sf = dim/qMin(target.height(), target.width());
p.scale(sf, sf);
// Draw your text
p.setPointSize(48);
p.drawText(QRectF(dim, dim), Qt::AlignCenter | Qt::WordWrap, text);
// Restore the state
p.restore();


标签: qt fonts