Support pen color with color fonts
Color fonts may also contain regular alphabet characters that should be rendered with the current pen. In Qt, however, these characters were drawn into the cache with a default pen color of black. Since all characters in a font is currently backed by the same cache, and it would require a lot of plumbing to get around this, a step in the right direction is to include the current pen color in the cache as long as it is an RGB cache. This means that drawing text with the color font with different pen colors will create different caches. There is no API to select font color on Freetype currently, but this problem has also not been observed there, as the fonts in question, with both regular and color glyphs, are not being detected as color fonts (so the text color will be correct). So Freetype will be left out for now. [ChangeLog][QtGui][Text] Fixed bug where regular text rendered with a color font would always display in black. Task-number: QTBUG-55096 Task-number: QTBUG-74761 Change-Id: Icc7dbf73241db1e7cc6a0de18c2de927aeecf713 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>bb10
parent
72ebc7458d
commit
78caba7ae6
|
|
@ -2927,9 +2927,9 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
|
|||
QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat != QFontEngine::Format_None ? fontEngine->glyphFormat : d->glyphCacheFormat;
|
||||
|
||||
QImageTextureGlyphCache *cache =
|
||||
static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(0, glyphFormat, s->matrix));
|
||||
static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(0, glyphFormat, s->matrix, QColor(s->penData.solid.color)));
|
||||
if (!cache) {
|
||||
cache = new QImageTextureGlyphCache(glyphFormat, s->matrix);
|
||||
cache = new QImageTextureGlyphCache(glyphFormat, s->matrix, QColor(s->penData.solid.color));
|
||||
fontEngine->setGlyphCache(0, cache);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition
|
|||
case QFontEngine::Format_A32:
|
||||
return m_current_fontengine->alphaRGBMapForGlyph(g, subPixelPosition, m_transform);
|
||||
case QFontEngine::Format_ARGB:
|
||||
return m_current_fontengine->bitmapForGlyph(g, subPixelPosition, m_transform);
|
||||
return m_current_fontengine->bitmapForGlyph(g, subPixelPosition, m_transform, color());
|
||||
default:
|
||||
return m_current_fontengine->alphaMapForGlyph(g, subPixelPosition, m_transform);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ class QTextItemInt;
|
|||
class Q_GUI_EXPORT QTextureGlyphCache : public QFontEngineGlyphCache
|
||||
{
|
||||
public:
|
||||
QTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix)
|
||||
: QFontEngineGlyphCache(format, matrix), m_current_fontengine(0),
|
||||
QTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix, const QColor &color = QColor())
|
||||
: QFontEngineGlyphCache(format, matrix, color), m_current_fontengine(0),
|
||||
m_w(0), m_h(0), m_cx(0), m_cy(0), m_currentRowHeight(0)
|
||||
{ }
|
||||
|
||||
|
|
@ -165,8 +165,8 @@ inline uint qHash(const QTextureGlyphCache::GlyphAndSubPixelPosition &g)
|
|||
class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache
|
||||
{
|
||||
public:
|
||||
QImageTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix)
|
||||
: QTextureGlyphCache(format, matrix) { }
|
||||
QImageTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix, const QColor &color = QColor())
|
||||
: QTextureGlyphCache(format, matrix, color) { }
|
||||
~QImageTextureGlyphCache();
|
||||
|
||||
virtual void createTextureData(int width, int height) override;
|
||||
|
|
|
|||
|
|
@ -899,7 +899,7 @@ QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition
|
|||
return rgbMask;
|
||||
}
|
||||
|
||||
QImage QFontEngine::bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform&)
|
||||
QImage QFontEngine::bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform&, const QColor &)
|
||||
{
|
||||
Q_UNUSED(subPixelPosition);
|
||||
|
||||
|
|
@ -1075,7 +1075,10 @@ void QFontEngine::setGlyphCache(const void *context, QFontEngineGlyphCache *cach
|
|||
|
||||
}
|
||||
|
||||
QFontEngineGlyphCache *QFontEngine::glyphCache(const void *context, GlyphFormat format, const QTransform &transform) const
|
||||
QFontEngineGlyphCache *QFontEngine::glyphCache(const void *context,
|
||||
GlyphFormat format,
|
||||
const QTransform &transform,
|
||||
const QColor &color) const
|
||||
{
|
||||
const QHash<const void*, GlyphCaches>::const_iterator caches = m_glyphCaches.constFind(context);
|
||||
if (caches == m_glyphCaches.cend())
|
||||
|
|
@ -1083,8 +1086,11 @@ QFontEngineGlyphCache *QFontEngine::glyphCache(const void *context, GlyphFormat
|
|||
|
||||
for (GlyphCaches::const_iterator it = caches->begin(), end = caches->end(); it != end; ++it) {
|
||||
QFontEngineGlyphCache *cache = it->cache.data();
|
||||
if (format == cache->glyphFormat() && qtransform_equals_no_translate(cache->m_transform, transform))
|
||||
if (format == cache->glyphFormat()
|
||||
&& (format != Format_ARGB || color == cache->color())
|
||||
&& qtransform_equals_no_translate(cache->m_transform, transform)) {
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ public:
|
|||
virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t);
|
||||
virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
|
||||
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
|
||||
virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
|
||||
virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color = QColor());
|
||||
virtual QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,
|
||||
GlyphFormat neededFormat,
|
||||
const QTransform &t = QTransform(),
|
||||
|
|
@ -252,7 +252,7 @@ public:
|
|||
|
||||
void clearGlyphCache(const void *key);
|
||||
void setGlyphCache(const void *key, QFontEngineGlyphCache *data);
|
||||
QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform) const;
|
||||
QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform, const QColor &color = QColor()) const;
|
||||
|
||||
static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize);
|
||||
static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,10 @@ QT_BEGIN_NAMESPACE
|
|||
class Q_GUI_EXPORT QFontEngineGlyphCache: public QSharedData
|
||||
{
|
||||
public:
|
||||
QFontEngineGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix) : m_format(format), m_transform(matrix)
|
||||
QFontEngineGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix, const QColor &color = QColor())
|
||||
: m_format(format)
|
||||
, m_transform(matrix)
|
||||
, m_color(color)
|
||||
{
|
||||
Q_ASSERT(m_format != QFontEngine::Format_None);
|
||||
}
|
||||
|
|
@ -74,9 +77,11 @@ public:
|
|||
|
||||
QFontEngine::GlyphFormat glyphFormat() const { return m_format; }
|
||||
const QTransform &transform() const { return m_transform; }
|
||||
const QColor &color() const { return m_color; }
|
||||
|
||||
QFontEngine::GlyphFormat m_format;
|
||||
QTransform m_transform;
|
||||
QColor m_color;
|
||||
};
|
||||
typedef QHash<void *, QList<QFontEngineGlyphCache *> > GlyphPointerHash;
|
||||
typedef QHash<int, QList<QFontEngineGlyphCache *> > GlyphIntHash;
|
||||
|
|
|
|||
|
|
@ -2105,8 +2105,10 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, co
|
|||
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
|
||||
}
|
||||
|
||||
QImage QFontEngineFT::bitmapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
|
||||
QImage QFontEngineFT::bitmapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t, const QColor &color)
|
||||
{
|
||||
Q_UNUSED(color);
|
||||
|
||||
Glyph *glyph = loadGlyphFor(g, subPixelPosition, defaultFormat, t);
|
||||
if (glyph == nullptr)
|
||||
return QImage();
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ private:
|
|||
QImage alphaMapForGlyph(glyph_t, QFixed) override;
|
||||
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override;
|
||||
QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
|
||||
QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
|
||||
QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override;
|
||||
glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
|
||||
QFixed subPixelPosition,
|
||||
const QTransform &matrix,
|
||||
|
|
|
|||
|
|
@ -747,7 +747,7 @@ qreal QCoreTextFontEngine::fontSmoothingGamma()
|
|||
return 2.0;
|
||||
}
|
||||
|
||||
QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix)
|
||||
QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, const QColor &color)
|
||||
{
|
||||
glyph_metrics_t br = alphaMapBoundingBox(glyph, subPixelPosition, matrix, glyphFormat);
|
||||
|
||||
|
|
@ -827,6 +827,8 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition
|
|||
CTFontDrawGlyphs(ctfont, &cgGlyph, &CGPointZero, 1, ctx);
|
||||
}
|
||||
} else {
|
||||
CGContextSetRGBFillColor(ctx, color.redF(), color.greenF(), color.blueF(), color.alphaF());
|
||||
|
||||
// CGContextSetTextMatrix does not work with color glyphs, so we use
|
||||
// the CTM instead. This means we must translate the CTM as well, to
|
||||
// set the glyph position, instead of using CGContextSetTextPosition.
|
||||
|
|
@ -884,12 +886,12 @@ QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPo
|
|||
return imageForGlyph(glyph, subPixelPosition, x);
|
||||
}
|
||||
|
||||
QImage QCoreTextFontEngine::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
|
||||
QImage QCoreTextFontEngine::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t, const QColor &color)
|
||||
{
|
||||
if (t.type() > QTransform::TxScale)
|
||||
return QFontEngine::bitmapForGlyph(glyph, subPixelPosition, t);
|
||||
return QFontEngine::bitmapForGlyph(glyph, subPixelPosition, t, color);
|
||||
|
||||
return imageForGlyph(glyph, subPixelPosition, t);
|
||||
return imageForGlyph(glyph, subPixelPosition, t, color);
|
||||
}
|
||||
|
||||
void QCoreTextFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ public:
|
|||
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override;
|
||||
QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
|
||||
glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat) override;
|
||||
QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
|
||||
QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override;
|
||||
QFixed emSquareSize() const override;
|
||||
void doKerning(QGlyphLayout *g, ShaperFlags flags) const override;
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ public:
|
|||
protected:
|
||||
QCoreTextFontEngine(const QFontDef &def);
|
||||
void init();
|
||||
QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &m);
|
||||
QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &m, const QColor &color = QColor());
|
||||
void loadAdvancesForGlyphs(QVarLengthArray<CGGlyph> &cgGlyphs, QGlyphLayout *glyphs) const;
|
||||
bool hasColorGlyphs() const;
|
||||
bool shouldAntialias() const;
|
||||
|
|
|
|||
|
|
@ -650,7 +650,8 @@ bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const
|
|||
QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
||||
QFixed subPixelPosition,
|
||||
int margin,
|
||||
const QTransform &originalTransform)
|
||||
const QTransform &originalTransform,
|
||||
const QColor &color)
|
||||
{
|
||||
UINT16 glyphIndex = t;
|
||||
FLOAT glyphAdvance = 0;
|
||||
|
|
@ -735,6 +736,7 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
|||
|
||||
#if defined(QT_USE_DIRECTWRITE2)
|
||||
BOOL ok = true;
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
while (SUCCEEDED(hr) && ok) {
|
||||
const DWRITE_COLOR_GLYPH_RUN *colorGlyphRun = 0;
|
||||
|
|
@ -759,10 +761,18 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
|||
break;
|
||||
}
|
||||
|
||||
float r = qBound(0.0f, colorGlyphRun->runColor.r, 1.0f);
|
||||
float g = qBound(0.0f, colorGlyphRun->runColor.g, 1.0f);
|
||||
float b = qBound(0.0f, colorGlyphRun->runColor.b, 1.0f);
|
||||
float a = qBound(0.0f, colorGlyphRun->runColor.a, 1.0f);
|
||||
float r, g, b, a;
|
||||
if (colorGlyphRun->paletteIndex == 0xFFFF) {
|
||||
r = float(color.redF());
|
||||
g = float(color.greenF());
|
||||
b = float(color.blueF());
|
||||
a = float(color.alphaF());
|
||||
} else {
|
||||
r = qBound(0.0f, colorGlyphRun->runColor.r, 1.0f);
|
||||
g = qBound(0.0f, colorGlyphRun->runColor.g, 1.0f);
|
||||
b = qBound(0.0f, colorGlyphRun->runColor.b, 1.0f);
|
||||
a = qBound(0.0f, colorGlyphRun->runColor.a, 1.0f);
|
||||
}
|
||||
|
||||
if (!qFuzzyIsNull(a)) {
|
||||
renderGlyphRun(&image,
|
||||
|
|
@ -784,11 +794,21 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
float r, g, b, a;
|
||||
if (glyphFormat == QFontEngine::Format_ARGB) {
|
||||
r = float(color.redF());
|
||||
g = float(color.greenF());
|
||||
b = float(color.blueF());
|
||||
a = float(color.alphaF());
|
||||
} else {
|
||||
r = g = b = a = 0.0;
|
||||
}
|
||||
|
||||
renderGlyphRun(&image,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
a,
|
||||
glyphAnalysis,
|
||||
boundingRect);
|
||||
}
|
||||
|
|
@ -1001,9 +1021,9 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph
|
|||
}
|
||||
}
|
||||
|
||||
QImage QWindowsFontEngineDirectWrite::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
|
||||
QImage QWindowsFontEngineDirectWrite::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t, const QColor &color)
|
||||
{
|
||||
return imageForGlyph(glyph, subPixelPosition, glyphMargin(QFontEngine::Format_A32), t);
|
||||
return imageForGlyph(glyph, subPixelPosition, glyphMargin(QFontEngine::Format_A32), t, color);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public:
|
|||
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) override;
|
||||
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override;
|
||||
QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) override;
|
||||
QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
|
||||
QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override;
|
||||
|
||||
QFontEngine *cloneWithSize(qreal pixelSize) const override;
|
||||
Qt::HANDLE handle() const override;
|
||||
|
|
@ -126,7 +126,7 @@ public:
|
|||
void setUniqueFamilyName(const QString &newName) { m_uniqueFamilyName = newName; }
|
||||
|
||||
private:
|
||||
QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform);
|
||||
QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform, const QColor &color = QColor());
|
||||
void collectMetrics();
|
||||
void renderGlyphRun(QImage *destination, float r, float g, float b, float a, IDWriteGlyphRunAnalysis *glyphAnalysis, const QRect &boundingRect);
|
||||
static QString filenameFromFontFile(IDWriteFontFile *fontFile);
|
||||
|
|
|
|||
Loading…
Reference in New Issue