aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@digia.com>2013-03-12 18:43:21 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-04-05 15:38:04 +0200
commit57855fd6a2d3d0d3a1abbafa1000d6a1a7ce3d40 (patch)
tree75e3fccd73525341dfc5b66b4661afaeac5cdde6 /src
parentfedd27e1faa65d38a1a5b11f750b5ae2fb5c4006 (diff)
Implemented text styles for QSGDefaultGlyphNode.
Used when Text has renderType: Text.NativeRendering. Task-number: QTBUG-27867 Change-Id: Id1262ef49e26229c86ebd2533b9f6de638bc75cb Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode.cpp63
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp279
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.h12
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p_p.h45
4 files changed, 357 insertions, 42 deletions
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode.cpp b/src/quick/scenegraph/qsgdefaultglyphnode.cpp
index 55eadab704..8f24485fc0 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode.cpp
@@ -48,7 +48,8 @@
QT_BEGIN_NAMESPACE
QSGDefaultGlyphNode::QSGDefaultGlyphNode()
- : m_material(0)
+ : m_style(QQuickText::Normal)
+ , m_material(0)
, m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0)
{
m_geometry.setDrawingMode(GL_TRIANGLES);
@@ -74,22 +75,62 @@ void QSGDefaultGlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &gl
if (m_material != 0)
delete m_material;
- QRawFont font = glyphs.rawFont();
- m_material = new QSGTextMaskMaterial(font);
+ m_position = position;
+ m_glyphs = glyphs;
+
+#ifdef QML_RUNTIME_TESTING
+ description = QLatin1String("glyphs");
+#endif
+}
+
+void QSGDefaultGlyphNode::setStyle(QQuickText::TextStyle style)
+{
+ if (m_style == style)
+ return;
+ m_style = style;
+}
+
+void QSGDefaultGlyphNode::setStyleColor(const QColor &color)
+{
+ if (m_styleColor == color)
+ return;
+ m_styleColor = color;
+}
+
+void QSGDefaultGlyphNode::update()
+{
+ QRawFont font = m_glyphs.rawFont();
+ QMargins margins(0, 0, 0, 0);
+
+ if (m_style == QQuickText::Normal) {
+ m_material = new QSGTextMaskMaterial(font);
+ } else if (m_style == QQuickText::Outline) {
+ QSGOutlinedTextMaterial *material = new QSGOutlinedTextMaterial(font);
+ material->setStyleColor(m_styleColor);
+ m_material = material;
+ margins = QMargins(1, 1, 1, 1);
+ } else {
+ QSGStyledTextMaterial *material = new QSGStyledTextMaterial(font);
+ if (m_style == QQuickText::Sunken) {
+ material->setStyleShift(QPointF(0, -1));
+ margins.setTop(1);
+ } else if (m_style == QQuickText::Raised) {
+ material->setStyleShift(QPointF(0, 1));
+ margins.setBottom(1);
+ }
+ material->setStyleColor(m_styleColor);
+ m_material = material;
+ }
+
m_material->setColor(m_color);
QRectF boundingRect;
- m_material->populate(position, glyphs.glyphIndexes(), glyphs.positions(), geometry(),
- &boundingRect, &m_baseLine);
-
- setMaterial(m_material);
+ m_material->populate(m_position, m_glyphs.glyphIndexes(), m_glyphs.positions(), geometry(),
+ &boundingRect, &m_baseLine, margins);
setBoundingRect(boundingRect);
+ setMaterial(m_material);
markDirty(DirtyGeometry);
-
-#ifdef QML_RUNTIME_TESTING
- description = QLatin1String("glyphs");
-#endif
}
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index 9e0cfca069..419062d025 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -43,7 +43,6 @@
#include <qopenglshaderprogram.h>
-#include <QtGui/private/qopengltextureglyphcache_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
#include <private/qfontengine_p.h>
@@ -67,7 +66,7 @@ public:
virtual void activate();
virtual void deactivate();
-private:
+protected:
virtual void initialize();
virtual const char *vertexShader() const;
virtual const char *fragmentShader() const;
@@ -210,8 +209,197 @@ void QSGTextMaskMaterialData::updateState(const RenderState &state, QSGMaterial
}
}
-QSGTextMaskMaterial::QSGTextMaskMaterial(const QRawFont &font)
- : m_texture(0), m_glyphCache(), m_font(font)
+class QSGStyledTextMaterialData : public QSGTextMaskMaterialData
+{
+public:
+ QSGStyledTextMaterialData() { }
+
+ virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
+ virtual void activate();
+ virtual void deactivate();
+
+private:
+ virtual void initialize();
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
+
+ int m_shift_id;
+ int m_styleColor_id;
+};
+
+void QSGStyledTextMaterialData::initialize()
+{
+ QSGTextMaskMaterialData::initialize();
+ m_shift_id = program()->uniformLocation("shift");
+ m_styleColor_id = program()->uniformLocation("styleColor");
+}
+
+void QSGStyledTextMaterialData::updateState(const RenderState &state,
+ QSGMaterial *newEffect,
+ QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
+
+ QSGStyledTextMaterial *material = static_cast<QSGStyledTextMaterial *>(newEffect);
+ QSGStyledTextMaterial *oldMaterial = static_cast<QSGStyledTextMaterial *>(oldEffect);
+
+ if (oldMaterial == 0 || oldMaterial->styleShift() != material->styleShift())
+ program()->setUniformValue(m_shift_id, material->styleShift());
+
+ if (oldMaterial == 0 || material->color() != oldMaterial->color() || state.isOpacityDirty()) {
+ QColor c = material->color();
+ QVector4D color(c.redF() * c.alphaF(), c.greenF() * c.alphaF(), c.blueF() * c.alphaF(), c.alphaF());
+ color *= state.opacity();
+ program()->setUniformValue(m_color_id, color);
+ }
+
+ if (oldMaterial == 0 || material->styleColor() != oldMaterial->styleColor() || state.isOpacityDirty()) {
+ QColor c = material->styleColor();
+ QVector4D color(c.redF() * c.alphaF(), c.greenF() * c.alphaF(), c.blueF() * c.alphaF(), c.alphaF());
+ color *= state.opacity();
+ program()->setUniformValue(m_styleColor_id, color);
+ }
+
+ bool updated = material->ensureUpToDate();
+ Q_ASSERT(material->texture());
+
+ Q_ASSERT(oldMaterial == 0 || oldMaterial->texture());
+ if (updated
+ || oldMaterial == 0
+ || oldMaterial->texture()->textureId() != material->texture()->textureId()) {
+ program()->setUniformValue(m_textureScale_id, QVector2D(1.0 / material->cacheTextureWidth(),
+ 1.0 / material->cacheTextureHeight()));
+ glBindTexture(GL_TEXTURE_2D, material->texture()->textureId());
+
+ // Set the mag/min filters to be linear. We only need to do this when the texture
+ // has been recreated.
+ if (updated) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+ }
+
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_matrix_id, state.combinedMatrix());
+}
+
+void QSGStyledTextMaterialData::activate()
+{
+ QSGMaterialShader::activate();
+
+#if !defined(QT_OPENGL_ES_2) && defined(GL_ARB_framebuffer_sRGB)
+ // 0.25 was found to be acceptable error margin by experimentation. On Mac, the gamma is 2.0,
+ // but using sRGB looks okay.
+ if (qAbs(fontSmoothingGamma() - 2.2) < 0.25)
+ glEnable(GL_FRAMEBUFFER_SRGB);
+#endif
+}
+
+void QSGStyledTextMaterialData::deactivate()
+{
+ QSGMaterialShader::deactivate();
+
+#if !defined(QT_OPENGL_ES_2) && defined(GL_ARB_framebuffer_sRGB)
+ if (qAbs(fontSmoothingGamma() - 2.2) < 0.25)
+ glDisable(GL_FRAMEBUFFER_SRGB);
+#endif
+}
+
+const char *QSGStyledTextMaterialData::vertexShader() const
+{
+ return
+ "uniform highp mat4 matrix; \n"
+ "uniform highp vec2 textureScale; \n"
+ "uniform highp vec2 shift; \n"
+ "attribute highp vec4 vCoord; \n"
+ "attribute highp vec2 tCoord; \n"
+ "varying highp vec2 sampleCoord; \n"
+ "varying highp vec2 shiftedSampleCoord; \n"
+ "void main() { \n"
+ " sampleCoord = tCoord * textureScale; \n"
+ " shiftedSampleCoord = (tCoord - shift) * textureScale; \n"
+ " gl_Position = matrix * vCoord; \n"
+ "}";
+}
+
+const char *QSGStyledTextMaterialData::fragmentShader() const
+{
+ return
+ "varying highp vec2 sampleCoord; \n"
+ "varying highp vec2 shiftedSampleCoord; \n"
+ "uniform sampler2D texture; \n"
+ "uniform lowp vec4 color; \n"
+ "uniform lowp vec4 styleColor; \n"
+ "void main() { \n"
+ " lowp float glyph = texture2D(texture, sampleCoord).a; \n"
+ " lowp float style = clamp(texture2D(texture, shiftedSampleCoord).a - glyph, \n"
+ " 0.0, 1.0); \n"
+ " gl_FragColor = style * styleColor + glyph * color; \n"
+ "}";
+}
+
+
+class QSGOutlinedTextMaterialData : public QSGStyledTextMaterialData
+{
+public:
+ QSGOutlinedTextMaterialData() { }
+
+private:
+ const char *vertexShader() const;
+ const char *fragmentShader() const;
+};
+
+const char *QSGOutlinedTextMaterialData::vertexShader() const
+{
+ return
+ "uniform highp mat4 matrix; \n"
+ "uniform highp vec2 textureScale; \n"
+ "uniform highp vec2 shift; \n"
+ "attribute highp vec4 vCoord; \n"
+ "attribute highp vec2 tCoord; \n"
+ "varying highp vec2 sampleCoord; \n"
+ "varying highp vec2 sCoordUp; \n"
+ "varying highp vec2 sCoordDown; \n"
+ "varying highp vec2 sCoordLeft; \n"
+ "varying highp vec2 sCoordRight; \n"
+ "void main() { \n"
+ " sampleCoord = tCoord * textureScale; \n"
+ " sCoordUp = (tCoord - vec2(0.0, -1.0)) * textureScale; \n"
+ " sCoordDown = (tCoord - vec2(0.0, 1.0)) * textureScale; \n"
+ " sCoordLeft = (tCoord - vec2(-1.0, 0.0)) * textureScale; \n"
+ " sCoordRight = (tCoord - vec2(1.0, 0.0)) * textureScale; \n"
+ " gl_Position = matrix * vCoord; \n"
+ "}";
+}
+
+const char *QSGOutlinedTextMaterialData::fragmentShader() const
+{
+ return
+ "varying highp vec2 sampleCoord; \n"
+ "varying highp vec2 sCoordUp; \n"
+ "varying highp vec2 sCoordDown; \n"
+ "varying highp vec2 sCoordLeft; \n"
+ "varying highp vec2 sCoordRight; \n"
+ "uniform sampler2D texture; \n"
+ "uniform lowp vec4 color; \n"
+ "uniform lowp vec4 styleColor; \n"
+ "void main() { \n"
+ "lowp float glyph = texture2D(texture, sampleCoord).a; \n"
+ " lowp float outline = clamp(clamp(texture2D(texture, sCoordUp).a + \n"
+ " texture2D(texture, sCoordDown).a + \n"
+ " texture2D(texture, sCoordLeft).a + \n"
+ " texture2D(texture, sCoordRight).a, \n"
+ " 0.0, 1.0) - glyph, \n"
+ " 0.0, 1.0); \n"
+ " gl_FragColor = outline * styleColor + glyph * color; \n"
+ "}";
+}
+
+QSGTextMaskMaterial::QSGTextMaskMaterial(const QRawFont &font, QFontEngineGlyphCache::Type cacheType)
+ : m_texture(0)
+ , m_cacheType(cacheType)
+ , m_glyphCache(0)
+ , m_font(font)
{
init();
}
@@ -224,7 +412,6 @@ void QSGTextMaskMaterial::init()
{
Q_ASSERT(m_font.isValid());
- QFontEngineGlyphCache::Type type = QFontEngineGlyphCache::Raster_RGBMask;
setFlag(Blending, true);
QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
@@ -232,20 +419,21 @@ void QSGTextMaskMaterial::init()
QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
if (fontD->fontEngine != 0) {
- m_glyphCache = fontD->fontEngine->glyphCache(ctx, type, QTransform());
- if (!m_glyphCache || m_glyphCache->cacheType() != type) {
- m_glyphCache = new QOpenGLTextureGlyphCache(type, QTransform());
+ m_glyphCache = fontD->fontEngine->glyphCache(ctx, m_cacheType, QTransform());
+ if (!m_glyphCache || m_glyphCache->cacheType() != m_cacheType) {
+ m_glyphCache = new QOpenGLTextureGlyphCache(m_cacheType, QTransform());
fontD->fontEngine->setGlyphCache(ctx, m_glyphCache.data());
}
}
}
void QSGTextMaskMaterial::populate(const QPointF &p,
- const QVector<quint32> &glyphIndexes,
- const QVector<QPointF> &glyphPositions,
- QSGGeometry *geometry,
- QRectF *boundingRect,
- QPointF *baseLine)
+ const QVector<quint32> &glyphIndexes,
+ const QVector<QPointF> &glyphPositions,
+ QSGGeometry *geometry,
+ QRectF *boundingRect,
+ QPointF *baseLine,
+ const QMargins &margins)
{
Q_ASSERT(m_font.isValid());
QVector<QFixedPoint> fixedPointPositions;
@@ -283,15 +471,15 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
*boundingRect |= QRectF(x + margin, y + margin, c.w, c.h);
- float cx1 = x;
- float cx2 = x + c.w;
- float cy1 = y;
- float cy2 = y + c.h;
+ float cx1 = x - margins.left();
+ float cx2 = x + c.w + margins.right();
+ float cy1 = y - margins.top();
+ float cy2 = y + c.h + margins.bottom();
- float tx1 = c.x;
- float tx2 = (c.x + c.w);
- float ty1 = c.y;
- float ty2 = (c.y + c.h);
+ float tx1 = c.x - margins.left();
+ float tx2 = c.x + c.w + margins.right();
+ float ty1 = c.y - margins.top();
+ float ty2 = c.y + c.h + margins.bottom();
if (baseLine->isNull())
*baseLine = glyphPosition;
@@ -367,4 +555,53 @@ int QSGTextMaskMaterial::cacheTextureHeight() const
return glyphCache()->height();
}
+
+QSGStyledTextMaterial::QSGStyledTextMaterial(const QRawFont &font)
+ : QSGTextMaskMaterial(font, QFontEngineGlyphCache::Raster_A8)
+{
+}
+
+QSGMaterialType *QSGStyledTextMaterial::type() const
+{
+ static QSGMaterialType type;
+ return &type;
+}
+
+QSGMaterialShader *QSGStyledTextMaterial::createShader() const
+{
+ return new QSGStyledTextMaterialData;
+}
+
+int QSGStyledTextMaterial::compare(const QSGMaterial *o) const
+{
+ const QSGStyledTextMaterial *other = static_cast<const QSGStyledTextMaterial *>(o);
+
+ if (m_styleShift != other->m_styleShift)
+ return m_styleShift.y() - other->m_styleShift.y();
+
+ QRgb c1 = m_styleColor.rgba();
+ QRgb c2 = other->m_styleColor.rgba();
+ if (c1 != c2)
+ return int(c2 < c1) - int(c1 < c2);
+
+ return QSGTextMaskMaterial::compare(o);
+}
+
+
+QSGOutlinedTextMaterial::QSGOutlinedTextMaterial(const QRawFont &font)
+ : QSGStyledTextMaterial(font)
+{
+}
+
+QSGMaterialType *QSGOutlinedTextMaterial::type() const
+{
+ static QSGMaterialType type;
+ return &type;
+}
+
+QSGMaterialShader *QSGOutlinedTextMaterial::createShader() const
+{
+ return new QSGOutlinedTextMaterialData;
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
index a3d5d7c3ae..e264c1b70e 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
@@ -53,22 +53,24 @@ class QSGDefaultGlyphNode: public QSGGlyphNode
{
public:
QSGDefaultGlyphNode();
- ~QSGDefaultGlyphNode();
+ virtual ~QSGDefaultGlyphNode();
virtual QPointF baseLine() const { return m_baseLine; }
virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs);
virtual void setColor(const QColor &color);
virtual void setPreferredAntialiasingMode(AntialiasingMode) { }
- virtual void setStyle(QQuickText::TextStyle) { }
- virtual void setStyleColor(const QColor &) { }
+ virtual void setStyle(QQuickText::TextStyle);
+ virtual void setStyleColor(const QColor &);
- virtual void update() { }
+ virtual void update();
-private:
+protected:
QGlyphRun m_glyphs;
QPointF m_position;
QColor m_color;
+ QQuickText::TextStyle m_style;
+ QColor m_styleColor;
QPointF m_baseLine;
QSGTextMaskMaterial *m_material;
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h
index 263523221e..d1a739de88 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h
@@ -43,24 +43,25 @@
#define QSGDEFAULTGLYPHNODE_P_P_H
#include <qcolor.h>
+#include <QtGui/private/qopengltextureglyphcache_p.h>
#include <QtQuick/qsgmaterial.h>
#include <QtQuick/qsgtexture.h>
#include <QtQuick/qsggeometry.h>
#include <qshareddata.h>
#include <QtQuick/private/qsgtexture_p.h>
#include <qrawfont.h>
+#include <qmargins.h>
QT_BEGIN_NAMESPACE
-class QFontEngineGlyphCache;
-class QOpenGLTextureGlyphCache;
class QFontEngine;
class Geometry;
class QSGTextMaskMaterial: public QSGMaterial
{
public:
- QSGTextMaskMaterial(const QRawFont &font);
- ~QSGTextMaskMaterial();
+ QSGTextMaskMaterial(const QRawFont &font,
+ QFontEngineGlyphCache::Type cacheType = QFontEngineGlyphCache::Raster_RGBMask);
+ virtual ~QSGTextMaskMaterial();
virtual QSGMaterialType *type() const;
virtual QSGMaterialShader *createShader() const;
@@ -79,18 +80,52 @@ public:
QOpenGLTextureGlyphCache *glyphCache() const;
void populate(const QPointF &position,
const QVector<quint32> &glyphIndexes, const QVector<QPointF> &glyphPositions,
- QSGGeometry *geometry, QRectF *boundingRect, QPointF *baseLine);
+ QSGGeometry *geometry, QRectF *boundingRect, QPointF *baseLine,
+ const QMargins &margins = QMargins(0, 0, 0, 0));
private:
void init();
QSGPlainTexture *m_texture;
+ QFontEngineGlyphCache::Type m_cacheType;
QExplicitlySharedDataPointer<QFontEngineGlyphCache> m_glyphCache;
QRawFont m_font;
QColor m_color;
QSize m_size;
};
+class QSGStyledTextMaterial : public QSGTextMaskMaterial
+{
+public:
+ QSGStyledTextMaterial(const QRawFont &font);
+ virtual ~QSGStyledTextMaterial() { }
+
+ void setStyleShift(const QPointF &shift) { m_styleShift = shift; }
+ const QPointF &styleShift() const { return m_styleShift; }
+
+ void setStyleColor(const QColor &color) { m_styleColor = color; }
+ const QColor &styleColor() const { return m_styleColor; }
+
+ virtual QSGMaterialType *type() const;
+ virtual QSGMaterialShader *createShader() const;
+
+ int compare(const QSGMaterial *other) const;
+
+private:
+ QPointF m_styleShift;
+ QColor m_styleColor;
+};
+
+class QSGOutlinedTextMaterial : public QSGStyledTextMaterial
+{
+public:
+ QSGOutlinedTextMaterial(const QRawFont &font);
+ ~QSGOutlinedTextMaterial() { }
+
+ QSGMaterialType *type() const;
+ QSGMaterialShader *createShader() const;
+};
+
QT_END_NAMESPACE
#endif