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