Added support for the text-rotation-alignment style property

Code cleanup
This commit is contained in:
Martin Tůma 2018-11-19 23:09:34 +01:00
parent df073ffc2a
commit c48ea8c878
9 changed files with 58 additions and 40 deletions

View File

@ -274,7 +274,8 @@ bool Style::Layer::Paint::antialias(Layer::Type type, int zoom) const
Style::Layer::Layout::Layout(const QJsonObject &json)
: _textSize(16), _textMaxWidth(10), _textMaxAngle(45), _lineCap(Qt::FlatCap),
_lineJoin(Qt::MiterJoin), _font("Open Sans"), _capitalize(false)
_lineJoin(Qt::MiterJoin), _font("Open Sans"), _capitalize(false),
_viewportAlignment(false)
{
// line
if (json.contains("line-cap") && json["line-cap"].isString()) {
@ -310,6 +311,11 @@ Style::Layer::Layout::Layout(const QJsonObject &json)
_font = Font::fromJsonArray(json["text-font"].toArray());
if (json.contains("text-transform") && json["text-transform"].isString())
_capitalize = json["text-transform"].toString() == "uppercase";
if (json.contains("text-rotation-alignment")
&& json["text-rotation-alignment"].isString())
if (json["text-rotation-alignment"].toString() == "viewport")
_viewportAlignment = true;
}
QFont Style::Layer::Layout::font(int zoom) const
@ -411,9 +417,12 @@ void Style::Layer::addSymbol(int zoom, const QPainterPath &path,
if (tt.isEmpty())
return;
if (path.elementCount() == 1 && path.elementAt(0).isMoveTo())
if (_layout.viewportAlignment())
tile.text().addLabel(tt, path.elementAt(0), tile.painter(),
_layout.maxTextWidth(zoom));
_layout.maxTextWidth(zoom), false);
else if (path.elementCount() == 1 && path.elementAt(0).isMoveTo())
tile.text().addLabel(tt, path.elementAt(0), tile.painter(),
_layout.maxTextWidth(zoom), true);
else
tile.text().addLabel(tt, path, tile.painter(),
_layout.maxTextAngle(zoom));

View File

@ -84,7 +84,8 @@ private:
public:
Layout() : _textSize(16), _textMaxWidth(10), _textMaxAngle(45),
_lineCap(Qt::FlatCap), _lineJoin(Qt::MiterJoin),
_font("Open Sans"), _capitalize(false) {}
_font("Open Sans"), _capitalize(false), _viewportAlignment(false)
{}
Layout(const QJsonObject &json);
bool capitalize() const {return _capitalize;}
@ -97,6 +98,7 @@ private:
QFont font(int zoom) const;
Qt::PenCapStyle lineCap() const {return _lineCap;}
Qt::PenJoinStyle lineJoin() const {return _lineJoin;}
bool viewportAlignment() const {return _viewportAlignment;}
private:
QStringList _keys;
@ -108,6 +110,7 @@ private:
Qt::PenJoinStyle _lineJoin;
QFont _font;
bool _capitalize;
bool _viewportAlignment;
};
class Paint {

View File

@ -150,7 +150,7 @@ void Text::render(QPainter *painter) const
}
void Text::addLabel(const QString &text, const QPointF &pos,
const QPainter &painter, qreal maxTextWidth)
const QPainter &painter, qreal maxTextWidth, bool overlap)
{
if (text.isEmpty())
return;
@ -158,6 +158,10 @@ void Text::addLabel(const QString &text, const QPointF &pos,
TextPointItem *ti;
ti = new TextPointItem(text, pos, painter.font(), maxTextWidth);
if (!overlap && !_sceneRect.contains(ti->boundingRect())) {
delete ti;
return;
}
ti->setPen(painter.pen());
addItem(ti);

View File

@ -12,7 +12,7 @@ public:
void render(QPainter *painter) const;
void addLabel(const QString &text, const QPointF &pos,
const QPainter &painter, qreal maxTextWidth);
const QPainter &painter, qreal maxTextWidth, bool overlap);
void addLabel(const QString &text, const QPainterPath &path,
const QPainter &painter, qreal maxAngle);

View File

@ -6,9 +6,11 @@
class TextItem
{
public:
TextItem() : _visible(true) {}
TextItem(const QString &text) : _text(text), _visible(true) {}
virtual ~TextItem() {}
const QString &text() const {return _text;}
virtual QPainterPath shape() const = 0;
virtual QRectF boundingRect() const = 0;
virtual void paint(QPainter *painter) const = 0;
@ -28,6 +30,7 @@ public:
}
private:
QString _text;
bool _visible;
};

View File

@ -4,7 +4,7 @@
TextPathItem::TextPathItem(const QString &text, const QPainterPath &path,
const QFont &font) : _text(text), _path(path), _font(font)
const QFont &font) : TextItem(text), _path(path), _font(font)
{
QPainterPathStroker s;
s.setWidth(font.pixelSize());
@ -16,7 +16,7 @@ TextPathItem::TextPathItem(const QString &text, const QPainterPath &path,
void TextPathItem::paint(QPainter *painter) const
{
QFontMetrics fm(_font);
int textWidth = fm.width(_text);
int textWidth = fm.width(text());
qreal factor = (textWidth) / qMax(_path.length(), (qreal)textWidth);
qreal percent = (1.0 - factor) / 2.0;
@ -26,16 +26,16 @@ void TextPathItem::paint(QPainter *painter) const
QTransform t = painter->transform();
for (int i = 0; i < _text.size(); i++) {
for (int i = 0; i < text().size(); i++) {
QPointF point = _path.pointAtPercent(percent);
qreal angle = _path.angleAtPercent(percent);
painter->translate(point);
painter->rotate(-angle);
painter->drawText(QPoint(0, fm.descent()), _text.at(i));
painter->drawText(QPoint(0, fm.descent()), text().at(i));
painter->setTransform(t);
int width = fm.charWidth(_text, i);
int width = fm.charWidth(text(), i);
percent += ((qreal)width / (qreal)textWidth) * factor;
}

View File

@ -18,7 +18,6 @@ public:
void setPen(const QPen &pen) {_pen = pen;}
private:
QString _text;
QPainterPath _path;
QPainterPath _shape;
QRectF _boundingRect;

View File

@ -5,7 +5,29 @@
#define FLAGS (Qt::AlignCenter | Qt::TextWordWrap | Qt::TextDontClip)
static QRectF fuzzyBoundingRect(const QString &str, const QFont &font,
#ifdef USE_EXACT_TEXT_RECT
static QRectF textBoundingRect(const QString &str, const QFont &font,
int maxTextWidth)
{
QFontMetrics fm(font);
int limit = font.pixelSize() * maxTextWidth;
// Italic fonts overflow the computed bounding rect, so reduce it
// a little bit.
if (font.italic())
limit -= font.pixelSize() / 2.0;
QRect br = fm.boundingRect(QRect(0, 0, limit, 0), FLAGS, str);
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);
return br;
}
#else // USE_EXACT_TEXT_RECT
static QRectF textBoundingRect(const QString &str, const QFont &font,
int maxTextWidth)
{
int limit = font.pixelSize() * maxTextWidth;
@ -45,33 +67,12 @@ static QRectF fuzzyBoundingRect(const QString &str, const QFont &font,
return QRectF(0, 0, width, lines * lh);
}
/*
static QRectF exactBoundingRect(const QString &str, const QFont &font,
int maxTextWidth)
{
QFontMetrics fm(font);
int limit = font.pixelSize() * maxTextWidth;
// Italic fonts overflow the computed bounding rect, so reduce it
// a little bit.
if (font.italic())
limit -= font.pixelSize() / 2.0;
QRect br = fm.boundingRect(QRect(0, 0, limit, 0), FLAGS, str);
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);
return br;
}
*/
#endif // USE_EXACT_TEXT_RECT
TextPointItem::TextPointItem(const QString &text, const QPointF &pos,
const QFont &font, int maxTextWidth) :_text(text), _font(font)
const QFont &font, int maxTextWidth) : TextItem(text), _font(font)
{
_boundingRect = fuzzyBoundingRect(text, font, maxTextWidth);
//_boundingRect = exactBoundingRect(text, font, maxTextWidth);
_boundingRect = textBoundingRect(text, font, maxTextWidth);
_boundingRect.moveCenter(pos);
_shape.addRect(_boundingRect);
@ -81,7 +82,7 @@ void TextPointItem::paint(QPainter *painter) const
{
painter->setFont(_font);
painter->setPen(_pen);
painter->drawText(_boundingRect, FLAGS, _text);
painter->drawText(_boundingRect, FLAGS, text());
//painter->setPen(Qt::red);
//painter->drawRect(_boundingRect);

View File

@ -19,7 +19,6 @@ public:
void setPen(const QPen &pen) {_pen = pen;}
private:
QString _text;
QPainterPath _shape;
QRectF _boundingRect;
QFont _font;