mirror of
https://github.com/tumic0/QtPBFImagePlugin.git
synced 2024-11-23 19:25:55 +01:00
Improved fuzzy text bounding rect computation
This commit is contained in:
parent
a559b5237b
commit
6d02dafeb6
@ -32,7 +32,8 @@ SOURCES += src/pbfplugin.cpp \
|
||||
src/textpathitem.cpp \
|
||||
src/textpointitem.cpp \
|
||||
src/font.cpp \
|
||||
src/sprites.cpp
|
||||
src/sprites.cpp \
|
||||
src/textitem.cpp
|
||||
RESOURCES += pbfplugin.qrc
|
||||
|
||||
unix:!macx{
|
||||
|
@ -12,12 +12,12 @@ class QPainter;
|
||||
class TextItem
|
||||
{
|
||||
public:
|
||||
TextItem(const QString &text) : _text(text), _visible(true) {}
|
||||
TextItem(const QString &text, const QFont &font)
|
||||
: _text(text), _font(font), _visible(true) {}
|
||||
virtual ~TextItem() {}
|
||||
|
||||
const QString &text() const {return _text;}
|
||||
const QFont &font() const {return _font;}
|
||||
void setFont(const QFont &font) {_font = font;}
|
||||
const QPen &pen() const {return _pen;}
|
||||
void setPen(const QPen &pen) {_pen = pen;}
|
||||
|
||||
@ -28,33 +28,10 @@ public:
|
||||
bool isVisible() const {return _visible;}
|
||||
void setVisible(bool visible) {_visible = visible;}
|
||||
|
||||
bool collidesWithItem(const TextItem *other) const
|
||||
{
|
||||
QRectF r1(boundingRect());
|
||||
QRectF r2(other->boundingRect());
|
||||
|
||||
if (r1.isEmpty() || r2.isEmpty() || !r1.intersects(r2))
|
||||
return false;
|
||||
|
||||
return other->shape().intersects(shape());
|
||||
}
|
||||
bool collidesWithItem(const TextItem *other) const;
|
||||
|
||||
protected:
|
||||
static int avgCharWidth(const QString &str, const QFont &font)
|
||||
{
|
||||
qreal ratio;
|
||||
|
||||
if (str.at(0).unicode() >= 0x2E80)
|
||||
ratio = 1.0;
|
||||
else {
|
||||
ratio = (font.capitalization() == QFont::AllUppercase)
|
||||
? 0.66 : 0.55;
|
||||
if (font.bold())
|
||||
ratio *= 1.1;
|
||||
}
|
||||
|
||||
return ratio * font.pixelSize();
|
||||
}
|
||||
int avgCharWidth() const;
|
||||
|
||||
private:
|
||||
QString _text;
|
||||
|
@ -134,9 +134,9 @@ static bool reverse(const QPainterPath &path)
|
||||
|
||||
TextPathItem::TextPathItem(const QString &text, const QPainterPath &path,
|
||||
const QFont &font, int maxAngle, const QRectF &tileRect)
|
||||
: TextItem(text)
|
||||
: TextItem(text, font)
|
||||
{
|
||||
int cw = avgCharWidth(text, font);
|
||||
int cw = avgCharWidth();
|
||||
int textWidth = text.size() * cw;
|
||||
if (textWidth > path.length())
|
||||
return;
|
||||
@ -146,7 +146,6 @@ TextPathItem::TextPathItem(const QString &text, const QPainterPath &path,
|
||||
return;
|
||||
|
||||
_path = reverse(tp) ? tp.toReversed() : tp;
|
||||
setFont(font);
|
||||
|
||||
QPainterPathStroker s;
|
||||
s.setWidth(font.pixelSize());
|
||||
|
@ -5,37 +5,32 @@
|
||||
|
||||
#define FLAGS (Qt::AlignCenter | Qt::TextWordWrap | Qt::TextDontClip)
|
||||
|
||||
QRectF TextPointItem::exactBoundingRect(const QString &str,
|
||||
const QFont &font, int maxWidth)
|
||||
QRectF TextPointItem::exactBoundingRect() const
|
||||
{
|
||||
QFontMetrics fm(font);
|
||||
int limit = font.pixelSize() * maxWidth;
|
||||
QFontMetrics fm(font());
|
||||
int limit = font().pixelSize() * _maxWidth;
|
||||
// Italic fonts overflow the computed bounding rect, so reduce it
|
||||
// a little bit.
|
||||
if (font.italic())
|
||||
limit -= font.pixelSize() / 2.0;
|
||||
if (font().italic())
|
||||
limit -= font().pixelSize() / 2.0;
|
||||
|
||||
QRect br = fm.boundingRect(QRect(0, 0, limit, 0), FLAGS, str);
|
||||
QRect br = fm.boundingRect(QRect(0, 0, limit, 0), FLAGS, text());
|
||||
Q_ASSERT(br.isValid());
|
||||
// Expand the bounding rect back to the real content size
|
||||
if (font.italic())
|
||||
br.adjust(-font.pixelSize() / 4.0, 0, font.pixelSize() / 4.0, 0);
|
||||
if (font().italic())
|
||||
br.adjust(-font().pixelSize() / 4.0, 0, font().pixelSize() / 4.0, 0);
|
||||
|
||||
return br;
|
||||
}
|
||||
|
||||
QRectF TextPointItem::fuzzyBoundingRect(const QString &str,
|
||||
const QFont &font, int maxWidth)
|
||||
QRectF TextPointItem::fuzzyBoundingRect() const
|
||||
{
|
||||
int limit = font.pixelSize() * maxWidth;
|
||||
qreal cw = avgCharWidth(str, font);
|
||||
qreal lh = font.pixelSize() * 1.25;
|
||||
int limit = font().pixelSize() * _maxWidth;
|
||||
qreal cw = avgCharWidth();
|
||||
qreal lh = font().pixelSize() * 1.25;
|
||||
int width = 0, lines = 0;
|
||||
|
||||
if (font.italic())
|
||||
limit -= font.pixelSize() / 2.0;
|
||||
|
||||
QStringList l(str.split('\n'));
|
||||
QStringList l(text().split('\n'));
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
int lw = (int)(l.at(i).length() * cw);
|
||||
if (lw > limit) {
|
||||
@ -69,11 +64,11 @@ QRectF TextPointItem::fuzzyBoundingRect(const QString &str,
|
||||
}
|
||||
|
||||
|
||||
QRectF TextPointItem::computeTextRect(BoundingRectFunction brf) const
|
||||
QRectF TextPointItem::computeTextRect(bool exact) const
|
||||
{
|
||||
QRectF iconRect = _icon.isNull() ? QRectF()
|
||||
: QRectF(QPointF(0, 0), QSizeF(_icon.size()) / _icon.devicePixelRatioF());
|
||||
QRectF textRect = brf(text(), font(), _maxWidth);
|
||||
QRectF textRect = exact ? exactBoundingRect() : fuzzyBoundingRect();
|
||||
|
||||
switch (_anchor) {
|
||||
case Text::Center:
|
||||
@ -102,11 +97,10 @@ QRectF TextPointItem::computeTextRect(BoundingRectFunction brf) const
|
||||
|
||||
TextPointItem::TextPointItem(const QString &text, const QPointF &pos,
|
||||
const QFont &font, int maxWidth, Text::Anchor anchor, const QImage &icon)
|
||||
: TextItem(text), _pos(pos), _icon(icon), _maxWidth(maxWidth),
|
||||
: TextItem(text, font), _pos(pos), _icon(icon), _maxWidth(maxWidth),
|
||||
_anchor(anchor)
|
||||
{
|
||||
setFont(font);
|
||||
_boundingRect = computeTextRect(fuzzyBoundingRect);
|
||||
_boundingRect = computeTextRect(false);
|
||||
|
||||
if (!_icon.isNull()) {
|
||||
QRectF iconRect(QPointF(0, 0), QSizeF(_icon.size())
|
||||
@ -126,12 +120,12 @@ void TextPointItem::paint(QPainter *painter) const
|
||||
QRectF textRect;
|
||||
|
||||
if (!_icon.isNull()) {
|
||||
textRect = computeTextRect(exactBoundingRect);
|
||||
textRect = computeTextRect(true);
|
||||
painter->drawImage(_pos - QPointF(_icon.width()
|
||||
/ _icon.devicePixelRatioF() / 2, _icon.height()
|
||||
/ _icon.devicePixelRatioF() / 2), _icon);
|
||||
} else
|
||||
textRect = computeTextRect(fuzzyBoundingRect);
|
||||
textRect = _boundingRect;
|
||||
|
||||
painter->setFont(font());
|
||||
painter->setPen(pen());
|
||||
|
@ -16,14 +16,9 @@ public:
|
||||
void paint(QPainter *painter) const;
|
||||
|
||||
private:
|
||||
typedef QRectF (*BoundingRectFunction)(const QString &, const QFont &, int);
|
||||
|
||||
static QRectF exactBoundingRect(const QString &str, const QFont &font,
|
||||
int maxWidth);
|
||||
static QRectF fuzzyBoundingRect(const QString &str, const QFont &font,
|
||||
int maxWidth);
|
||||
|
||||
QRectF computeTextRect(BoundingRectFunction brf) const;
|
||||
QRectF exactBoundingRect() const;
|
||||
QRectF fuzzyBoundingRect() const;
|
||||
QRectF computeTextRect(bool exact) const;
|
||||
|
||||
QPointF _pos;
|
||||
QPainterPath _shape;
|
||||
|
Loading…
Reference in New Issue
Block a user