summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Bache-Wiig <jbache@trolltech.com>2010-09-20 18:27:00 +0200
committerJens Bache-Wiig <jbache@trolltech.com>2010-09-20 18:27:00 +0200
commit645b4b7ad0e69ae9063f56c33108209349317c08 (patch)
treec5740b9cb9d1c16d14251aff5b2172174d2a4565
parentfd0c78bb37e36dbdabe298e42c4931ea40fde1f3 (diff)
Add text align and baseline
-rw-r--r--src/context2d.cpp119
-rw-r--r--src/context2d.h14
2 files changed, 124 insertions, 9 deletions
diff --git a/src/context2d.cpp b/src/context2d.cpp
index 7d275fa..726fa4e 100644
--- a/src/context2d.cpp
+++ b/src/context2d.cpp
@@ -43,6 +43,7 @@
static const double Q_PI = 3.14159265358979323846; // pi
#include <QGraphicsItem>
+#include <QApplication>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsDropShadowEffect>
@@ -477,17 +478,78 @@ void Context2D::setShadowColor(const QString &str)
QString Context2D::textBaseline()
{
switch(m_state.textBaseline) {
+ case Context2D::Alphabetic:
+ return QLatin1String("alphabetic");
+ case Context2D::Hanging:
+ return QLatin1String("hanging");
+ case Context2D::Bottom:
+ return QLatin1String("bottom");
+ case Context2D::Top:
+ return QLatin1String("top");
+ case Context2D::Middle:
+ return QLatin1String("middle");
default:
- return "middle";
+ Q_ASSERT("invalid value");
+ return QLatin1String("start");
}
}
-void Context2D::setTextBaseline(const QString &)
+void Context2D::setTextBaseline(const QString &baseline)
+{
+ if (baseline==QLatin1String("alphabetic"))
+ m_state.textBaseline = Context2D::Alphabetic;
+ else if (baseline == QLatin1String("hanging"))
+ m_state.textBaseline = Context2D::Hanging;
+ else if (baseline == QLatin1String("top"))
+ m_state.textBaseline = Context2D::Top;
+ else if (baseline == QLatin1String("bottom"))
+ m_state.textBaseline = Context2D::Bottom;
+ else if (baseline == QLatin1String("middle"))
+ m_state.textBaseline = Context2D::Middle;
+ else {
+ m_state.textBaseline = Context2D::Alphabetic;
+ qWarning() << ("Context2D: invalid baseline:" + baseline);
+ }
+ m_state.flags |= DirtyTextBaseline;
+}
+
+QString Context2D::textAlign()
{
- qDebug("Baseline not implemented");
+ switch(m_state.textAlign) {
+ case Context2D::Left:
+ return QLatin1String("left");
+ case Context2D::Right:
+ return QLatin1String("right");
+ case Context2D::Center:
+ return QLatin1String("center");
+ case Context2D::Start:
+ return QLatin1String("start");
+ case Context2D::End:
+ return QLatin1String("end");
+ default:
+ Q_ASSERT("invalid value");
+ qWarning() << ("Context2D::invalid textAlign");
+ return QLatin1String("start");
+ }
+}
+void Context2D::setTextAlign(const QString &baseline)
+{
+ if (baseline==QLatin1String("start"))
+ m_state.textAlign = Context2D::Start;
+ else if (baseline == QLatin1String("end"))
+ m_state.textAlign = Context2D::End;
+ else if (baseline == QLatin1String("left"))
+ m_state.textAlign = Context2D::Left;
+ else if (baseline == QLatin1String("right"))
+ m_state.textAlign = Context2D::Right;
+ else if (baseline == QLatin1String("center"))
+ m_state.textAlign = Context2D::Center;
+ else {
+ m_state.textAlign= Context2D::Start;
+ qWarning("Context2D: invalid text align");
+ }
// ### alphabetic, ideographic, hanging
-
m_state.flags |= DirtyTextBaseline;
}
@@ -563,9 +625,46 @@ void Context2D::fillRect(qreal x, qreal y, qreal w, qreal h)
scheduleChange();
}
+int Context2D::baseLineOffset(Context2D::TextBaseLine value, const QFontMetrics &metrics)
+{
+ int offset;
+ switch(value) {
+ case Context2D::Top:
+ break;
+ case Context2D::Alphabetic:
+ case Context2D::Middle:
+ case Context2D::Hanging:
+ offset = metrics.ascent();
+ break;
+ case Context2D::Bottom:
+ offset = metrics.height();
+ break;
+ }
+ return offset;
+}
+
+int Context2D::textAlignOffset(Context2D::TextAlign value, const QFontMetrics &metrics, const QString &text)
+{
+ int offset;
+ if (value == Context2D::Start)
+ value = qApp->layoutDirection() == Qt::LeftToRight ? Context2D::Left : Context2D::Right;
+ else if (value == Context2D::End)
+ value = qApp->layoutDirection() == Qt::LeftToRight ? Context2D::Right: Context2D::Left;
+ switch(value) {
+ case Context2D::Center:
+ offset = metrics.width(text)/2;
+ break;
+ case Context2D::Right:
+ offset = metrics.width(text);
+ case Context2D::Left:
+ default:
+ break;
+ }
+ return offset;
+}
+
void Context2D::fillText(const QString &text, qreal x, qreal y)
{
- qDebug("here");
beginPainting();
m_painter.save();
m_painter.setPen(QPen(m_state.fillStyle, m_state.lineWidth));
@@ -573,8 +672,10 @@ void Context2D::fillText(const QString &text, qreal x, qreal y)
QFont font;
font.setBold(true);
m_painter.setFont(m_state.font);
+ int yoffset = baseLineOffset(m_state.textBaseline, m_painter.fontMetrics());
+ int xoffset = textAlignOffset(m_state.textAlign, m_painter.fontMetrics(), text);
QTextOption opt; // Adjust baseLine etc
- m_painter.drawText(QRectF(x, y, m_pixmap.width(), m_painter.fontMetrics().height()), text, opt);
+ m_painter.drawText(QRectF(x-xoffset, y-yoffset, m_pixmap.width(), m_painter.fontMetrics().height()), text, opt);
m_painter.restore();
scheduleChange();
}
@@ -589,7 +690,11 @@ void Context2D::strokeText(const QString &text, qreal x, qreal y)
QPainterPath textPath;
QFont font = m_state.font;
font.setStyleStrategy(QFont::ForceOutline);
- textPath.addText(x, y, font, text);
+ m_painter.setFont(font);
+ const QFontMetrics &metrics = m_painter.fontMetrics();
+ int yoffset = baseLineOffset(m_state.textBaseline, metrics);
+ int xoffset = textAlignOffset(m_state.textAlign, metrics, text);
+ textPath.addText(x-xoffset, y-yoffset+metrics.ascent(), font, text);
m_painter.strokePath(textPath, QPen(m_state.fillStyle, m_state.lineWidth));
m_painter.restore();
scheduleChange();
diff --git a/src/context2d.h b/src/context2d.h
index 46b0644..57cf922 100644
--- a/src/context2d.h
+++ b/src/context2d.h
@@ -124,6 +124,10 @@ class Context2D : public QObject
// fonts
Q_PROPERTY(QString font READ font WRITE setFont)
Q_PROPERTY(QString textBaseline READ textBaseline WRITE setTextBaseline)
+ Q_PROPERTY(QString textAlign READ textAlign WRITE setTextAlign)
+
+ enum TextBaseLine { Alphabetic=0, Top, Middle, Bottom, Hanging};
+ enum TextAlign { Start=0, End, Left, Right, Center};
public:
Context2D(QObject *parent = 0);
@@ -165,6 +169,8 @@ public:
QString font();
void setTextBaseline(const QString &font);
QString textBaseline();
+ void setTextAlign(const QString &font);
+ QString textAlign();
// shadows
qreal shadowOffsetX() const; // (default 0)
@@ -285,10 +291,14 @@ private:
QColor shadowColor;
QPainter::CompositionMode globalCompositeOperation;
QFont font;
- int textAlign;
- int textBaseline;
+ Context2D::TextAlign textAlign;
+ Context2D::TextBaseLine textBaseline;
int flags;
};
+
+ int baseLineOffset(Context2D::TextBaseLine value, const QFontMetrics &metrics);
+ int textAlignOffset(Context2D::TextAlign value, const QFontMetrics &metrics, const QString &string);
+
State m_state;
QStack<State> m_stateStack;
QPixmap m_pixmap;