summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp2
-rw-r--r--src/gui/kernel/qplatformintegration.cpp2
-rw-r--r--src/gui/kernel/qplatformintegration.h3
-rw-r--r--src/gui/kernel/qstylehints.cpp31
-rw-r--r--src/gui/kernel/qstylehints.h4
-rw-r--r--src/gui/opengl/qopenglprogrambinarycache.cpp136
-rw-r--r--src/gui/painting/qdrawhelper.cpp30
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp2
-rw-r--r--src/gui/painting/qdrawhelper_neon_p.h2
-rw-r--r--src/gui/painting/qdrawhelper_p.h4
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp15
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h2
-rw-r--r--src/gui/text/qfontengine.cpp5
-rw-r--r--src/gui/text/qfontengine_ft.cpp36
-rw-r--r--src/gui/text/qfontengine_ft_p.h2
-rw-r--r--src/gui/text/qfontengine_p.h1
16 files changed, 193 insertions, 84 deletions
diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp
index e8a86590b5..307bc5e62f 100644
--- a/src/gui/kernel/qoffscreensurface.cpp
+++ b/src/gui/kernel/qoffscreensurface.cpp
@@ -335,7 +335,7 @@ void QOffscreenSurface::setScreen(QScreen *newScreen)
}
/*!
- Sets the native handle to which the offscreen surface is connected.
+ Sets the native handle to which the offscreen surface is connected to \a handle.
The native handle will be resolved in the create() function. Calling
this function after create() will not re-create a native surface.
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index fd7f475bee..fe1861e08b 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -409,6 +409,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
return QPlatformTheme::defaultThemeHint(QPlatformTheme::ItemViewActivateItemOnSingleClick);
case UiEffects:
return QPlatformTheme::defaultThemeHint(QPlatformTheme::UiEffects);
+ case WheelScrollLines:
+ return QPlatformTheme::defaultThemeHint(QPlatformTheme::WheelScrollLines);
}
return 0;
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 22a834f0e1..466b3348bd 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -157,7 +157,8 @@ public:
TabFocusBehavior,
ReplayMousePressOutsidePopup,
ItemViewActivateItemOnSingleClick,
- UiEffects
+ UiEffects,
+ WheelScrollLines,
};
virtual QVariant styleHint(StyleHint hint) const;
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 22c077da41..85c0768e35 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -78,6 +78,7 @@ public:
, m_cursorFlashTime(-1)
, m_tabFocusBehavior(-1)
, m_uiEffects(-1)
+ , m_wheelScrollLines(-1)
{}
int m_mouseDoubleClickInterval;
@@ -88,6 +89,7 @@ public:
int m_cursorFlashTime;
int m_tabFocusBehavior;
int m_uiEffects;
+ int m_wheelScrollLines;
};
/*!
@@ -495,4 +497,33 @@ void QStyleHints::setUseHoverEffects(bool useHoverEffects)
emit useHoverEffectsChanged(useHoverEffects);
}
+/*!
+ \property QStyleHints::wheelScrollLines
+ \brief Number of lines to scroll by default for each wheel click.
+
+ \since 5.9
+*/
+int QStyleHints::wheelScrollLines() const
+{
+ Q_D(const QStyleHints);
+ if (d->m_wheelScrollLines > 0)
+ return d->m_wheelScrollLines;
+ return themeableHint(QPlatformTheme::WheelScrollLines, QPlatformIntegration::WheelScrollLines).toInt();
+}
+
+/*!
+ Sets the \a wheelScrollLines.
+ \internal
+ \sa wheelScrollLines()
+ \since 5.9
+*/
+void QStyleHints::setWheelScrollLines(int scrollLines)
+{
+ Q_D(QStyleHints);
+ if (d->m_wheelScrollLines == scrollLines)
+ return;
+ d->m_wheelScrollLines = scrollLines;
+ emit wheelScrollLinesChanged(scrollLines);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index fb55cc7ed6..b9bf428edd 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -71,6 +71,7 @@ class Q_GUI_EXPORT QStyleHints : public QObject
Q_PROPERTY(Qt::TabFocusBehavior tabFocusBehavior READ tabFocusBehavior NOTIFY tabFocusBehaviorChanged FINAL)
Q_PROPERTY(bool singleClickActivation READ singleClickActivation STORED false CONSTANT FINAL)
Q_PROPERTY(bool useHoverEffects READ useHoverEffects WRITE setUseHoverEffects NOTIFY useHoverEffectsChanged FINAL)
+ Q_PROPERTY(int wheelScrollLines READ wheelScrollLines NOTIFY wheelScrollLinesChanged FINAL)
public:
void setMouseDoubleClickInterval(int mouseDoubleClickInterval);
@@ -99,6 +100,8 @@ public:
bool singleClickActivation() const;
bool useHoverEffects() const;
void setUseHoverEffects(bool useHoverEffects);
+ int wheelScrollLines() const;
+ void setWheelScrollLines(int scrollLines);
Q_SIGNALS:
void cursorFlashTimeChanged(int cursorFlashTime);
@@ -109,6 +112,7 @@ Q_SIGNALS:
void startDragTimeChanged(int startDragTime);
void tabFocusBehaviorChanged(Qt::TabFocusBehavior tabFocusBehavior);
void useHoverEffectsChanged(bool useHoverEffects);
+ void wheelScrollLinesChanged(int scrollLines);
private:
friend class QGuiApplication;
diff --git a/src/gui/opengl/qopenglprogrambinarycache.cpp b/src/gui/opengl/qopenglprogrambinarycache.cpp
index 5c8e425e29..06373e1113 100644
--- a/src/gui/opengl/qopenglprogrambinarycache.cpp
+++ b/src/gui/opengl/qopenglprogrambinarycache.cpp
@@ -59,7 +59,7 @@ Q_DECLARE_LOGGING_CATEGORY(DBG_SHADER_CACHE)
#endif
const quint32 BINSHADER_MAGIC = 0x5174;
-const quint32 BINSHADER_VERSION = 0x1;
+const quint32 BINSHADER_VERSION = 0x2;
const quint32 BINSHADER_QTVERSION = QT_VERSION;
struct GLEnvInfo
@@ -114,24 +114,42 @@ QString QOpenGLProgramBinaryCache::cacheFileName(const QByteArray &cacheKey) con
return m_cacheDir + QString::fromUtf8(cacheKey);
}
-static const int HEADER_SIZE = 3 * sizeof(quint32);
+#define BASE_HEADER_SIZE (int(3 * sizeof(quint32)))
+#define FULL_HEADER_SIZE(stringsSize) (BASE_HEADER_SIZE + 12 + stringsSize + 8)
+#define PADDING_SIZE(fullHeaderSize) (((fullHeaderSize + 3) & ~3) - fullHeaderSize)
+
+static inline quint32 readUInt(const uchar **p)
+{
+ quint32 v;
+ memcpy(&v, *p, sizeof(quint32));
+ *p += sizeof(quint32);
+ return v;
+}
+
+static inline QByteArray readStr(const uchar **p)
+{
+ quint32 len = readUInt(p);
+ QByteArray ba = QByteArray::fromRawData(reinterpret_cast<const char *>(*p), len);
+ *p += len;
+ return ba;
+}
bool QOpenGLProgramBinaryCache::verifyHeader(const QByteArray &buf) const
{
- if (buf.size() < HEADER_SIZE) {
+ if (buf.size() < BASE_HEADER_SIZE) {
qCDebug(DBG_SHADER_CACHE, "Cached size too small");
return false;
}
- const quint32 *p = reinterpret_cast<const quint32 *>(buf.constData());
- if (*p++ != BINSHADER_MAGIC) {
+ const uchar *p = reinterpret_cast<const uchar *>(buf.constData());
+ if (readUInt(&p) != BINSHADER_MAGIC) {
qCDebug(DBG_SHADER_CACHE, "Magic does not match");
return false;
}
- if (*p++ != BINSHADER_VERSION) {
+ if (readUInt(&p) != BINSHADER_VERSION) {
qCDebug(DBG_SHADER_CACHE, "Version does not match");
return false;
}
- if (*p++ != BINSHADER_QTVERSION) {
+ if (readUInt(&p) != BINSHADER_QTVERSION) {
qCDebug(DBG_SHADER_CACHE, "Qt version does not match");
return false;
}
@@ -219,15 +237,15 @@ bool QOpenGLProgramBinaryCache::load(const QByteArray &cacheKey, uint programId)
FdWrapper fdw(fn);
if (fdw.fd == -1)
return false;
- char header[HEADER_SIZE];
- qint64 bytesRead = qt_safe_read(fdw.fd, header, HEADER_SIZE);
- if (bytesRead == HEADER_SIZE)
- buf = QByteArray::fromRawData(header, HEADER_SIZE);
+ char header[BASE_HEADER_SIZE];
+ qint64 bytesRead = qt_safe_read(fdw.fd, header, BASE_HEADER_SIZE);
+ if (bytesRead == BASE_HEADER_SIZE)
+ buf = QByteArray::fromRawData(header, BASE_HEADER_SIZE);
#else
QFile f(fn);
if (!f.open(QIODevice::ReadOnly))
return false;
- buf = f.read(HEADER_SIZE);
+ buf = f.read(BASE_HEADER_SIZE);
#endif
if (!verifyHeader(buf)) {
@@ -235,52 +253,63 @@ bool QOpenGLProgramBinaryCache::load(const QByteArray &cacheKey, uint programId)
return false;
}
- const quint32 *p;
+ const uchar *p;
#ifdef Q_OS_UNIX
if (!fdw.map()) {
undertaker.setActive();
return false;
}
- p = reinterpret_cast<const quint32 *>(static_cast<const char *>(fdw.ptr) + HEADER_SIZE);
+ p = static_cast<const uchar *>(fdw.ptr) + BASE_HEADER_SIZE;
#else
buf = f.readAll();
- p = reinterpret_cast<const quint32 *>(buf.constData());
+ p = reinterpret_cast<const uchar *>(buf.constData());
#endif
GLEnvInfo info;
- quint32 v = *p++;
- QByteArray vendor = QByteArray::fromRawData(reinterpret_cast<const char *>(p), v);
+ QByteArray vendor = readStr(&p);
if (vendor != info.glvendor) {
- qCDebug(DBG_SHADER_CACHE, "GL_VENDOR does not match (%s, %s)", vendor.constData(), info.glvendor.constData());
+ // readStr returns non-null terminated strings just pointing to inside
+ // 'p' so must print these via the stream qCDebug and not constData().
+ qCDebug(DBG_SHADER_CACHE) << "GL_VENDOR does not match" << vendor << info.glvendor;
undertaker.setActive();
return false;
}
- p = reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(p) + v);
- v = *p++;
- QByteArray renderer = QByteArray::fromRawData(reinterpret_cast<const char *>(p), v);
+ QByteArray renderer = readStr(&p);
if (renderer != info.glrenderer) {
- qCDebug(DBG_SHADER_CACHE, "GL_RENDERER does not match (%s, %s)", renderer.constData(), info.glrenderer.constData());
+ qCDebug(DBG_SHADER_CACHE) << "GL_RENDERER does not match" << renderer << info.glrenderer;
undertaker.setActive();
return false;
}
- p = reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(p) + v);
- v = *p++;
- QByteArray version = QByteArray::fromRawData(reinterpret_cast<const char *>(p), v);
+ QByteArray version = readStr(&p);
if (version != info.glversion) {
- qCDebug(DBG_SHADER_CACHE, "GL_VERSION does not match (%s, %s)", version.constData(), info.glversion.constData());
+ qCDebug(DBG_SHADER_CACHE) << "GL_VERSION does not match" << version << info.glversion;
undertaker.setActive();
return false;
}
- p = reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(p) + v);
- quint32 blobFormat = *p++;
- quint32 blobSize = *p++;
+ quint32 blobFormat = readUInt(&p);
+ quint32 blobSize = readUInt(&p);
+
+ p += PADDING_SIZE(FULL_HEADER_SIZE(vendor.size() + renderer.size() + version.size()));
return setProgramBinary(programId, blobFormat, p, blobSize)
&& m_memCache.insert(cacheKey, new MemCacheEntry(p, blobSize, blobFormat));
}
+static inline void writeUInt(uchar **p, quint32 value)
+{
+ memcpy(*p, &value, sizeof(quint32));
+ *p += sizeof(quint32);
+}
+
+static inline void writeStr(uchar **p, const QByteArray &str)
+{
+ writeUInt(p, str.size());
+ memcpy(*p, str.constData(), str.size());
+ *p += str.size();
+}
+
void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
{
if (!m_cacheWritable)
@@ -292,37 +321,48 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
GLint blobSize = 0;
while (funcs->glGetError() != GL_NO_ERROR) { }
funcs->glGetProgramiv(programId, GL_PROGRAM_BINARY_LENGTH, &blobSize);
- int totalSize = blobSize + 8 + 12 + 12 + info.glvendor.size() + info.glrenderer.size() + info.glversion.size();
+
+ const int headerSize = FULL_HEADER_SIZE(info.glvendor.size() + info.glrenderer.size() + info.glversion.size());
+
+ // Add padding to make the blob start 4-byte aligned in order to support
+ // OpenGL implementations on ARM that choke on non-aligned pointers passed
+ // to glProgramBinary.
+ const int paddingSize = PADDING_SIZE(headerSize);
+
+ const int totalSize = headerSize + paddingSize + blobSize;
+
qCDebug(DBG_SHADER_CACHE, "Program binary is %d bytes, err = 0x%x, total %d", blobSize, funcs->glGetError(), totalSize);
if (!blobSize)
return;
QByteArray blob(totalSize, Qt::Uninitialized);
- quint32 *p = reinterpret_cast<quint32 *>(blob.data());
-
- *p++ = BINSHADER_MAGIC;
- *p++ = BINSHADER_VERSION;
- *p++ = BINSHADER_QTVERSION;
-
- *p++ = info.glvendor.size();
- memcpy(p, info.glvendor.constData(), info.glvendor.size());
- p = reinterpret_cast<quint32 *>(reinterpret_cast<char *>(p) + info.glvendor.size());
- *p++ = info.glrenderer.size();
- memcpy(p, info.glrenderer.constData(), info.glrenderer.size());
- p = reinterpret_cast<quint32 *>(reinterpret_cast<char *>(p) + info.glrenderer.size());
- *p++ = info.glversion.size();
- memcpy(p, info.glversion.constData(), info.glversion.size());
- p = reinterpret_cast<quint32 *>(reinterpret_cast<char *>(p) + info.glversion.size());
+ uchar *p = reinterpret_cast<uchar *>(blob.data());
+
+ writeUInt(&p, BINSHADER_MAGIC);
+ writeUInt(&p, BINSHADER_VERSION);
+ writeUInt(&p, BINSHADER_QTVERSION);
+
+ writeStr(&p, info.glvendor);
+ writeStr(&p, info.glrenderer);
+ writeStr(&p, info.glversion);
+
+ quint32 blobFormat = 0;
+ uchar *blobFormatPtr = p;
+ writeUInt(&p, blobFormat);
+ writeUInt(&p, blobSize);
+
+ for (int i = 0; i < paddingSize; ++i)
+ *p++ = 0;
GLint outSize = 0;
- quint32 *blobFormat = p++;
- *p++ = blobSize;
- funcs->glGetProgramBinary(programId, blobSize, &outSize, blobFormat, p);
+ funcs->glGetProgramBinary(programId, blobSize, &outSize, &blobFormat, p);
if (blobSize != outSize) {
qCDebug(DBG_SHADER_CACHE, "glGetProgramBinary returned size %d instead of %d", outSize, blobSize);
return;
}
+ writeUInt(&blobFormatPtr, blobFormat);
+
QSaveFile f(cacheFileName(cacheKey));
if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
f.write(blob);
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 7cf0dd7f03..021361b738 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -5547,7 +5547,7 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *)
+ const QClipData *, bool /*useGammaCorrection*/)
{
const quint16 c = color.toRgb16();
quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
@@ -5572,18 +5572,16 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
}
}
-static inline void rgbBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorProfile *colorProfile)
+static inline void rgbBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorProfile *colorProfile, bool useGammaCorrection)
{
// Do a gammacorrected RGB alphablend...
- const QRgba64 dlinear = colorProfile->toLinear64(*dst);
+ const QRgba64 dlinear = useGammaCorrection ? colorProfile->toLinear64(*dst) : QRgba64::fromArgb32(*dst);
QRgba64 blend = rgbBlend(dlinear, slinear, coverage);
- *dst = colorProfile->fromLinear64(blend);
+ *dst = useGammaCorrection ? colorProfile->fromLinear64(blend) : toArgb32(blend);
}
-Q_GUI_EXPORT bool qt_needs_a8_gamma_correction = false;
-
static inline void grayBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorProfile *colorProfile)
{
// Do a gammacorrected gray alphablend...
@@ -5598,7 +5596,7 @@ static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer,
int x, int y, quint32 color,
const uchar *map,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip)
+ const QClipData *clip, bool useGammaCorrection)
{
const quint32 c = color;
const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32);
@@ -5610,7 +5608,7 @@ static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer,
const QRgba64 slinear = colorProfile->toLinear64(c);
bool opaque_src = (qAlpha(color) == 255);
- bool doGrayBlendPixel = opaque_src && qt_needs_a8_gamma_correction;
+ bool doGrayBlendPixel = opaque_src && useGammaCorrection;
if (!clip) {
quint32 *dest = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x;
@@ -5680,9 +5678,9 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip)
+ const QClipData *clip, bool useGammaCorrection)
{
- qt_alphamapblit_uint32(rasterBuffer, x, y, color.toArgb32(), map, mapWidth, mapHeight, mapStride, clip);
+ qt_alphamapblit_uint32(rasterBuffer, x, y, color.toArgb32(), map, mapWidth, mapHeight, mapStride, clip, useGammaCorrection);
}
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
@@ -5690,9 +5688,9 @@ static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *map,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip)
+ const QClipData *clip, bool useGammaCorrection)
{
- qt_alphamapblit_uint32(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), map, mapWidth, mapHeight, mapStride, clip);
+ qt_alphamapblit_uint32(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), map, mapWidth, mapHeight, mapStride, clip, useGammaCorrection);
}
#endif
@@ -5704,7 +5702,7 @@ inline static int qRgbAvg(QRgb rgb)
static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uint *src, int mapWidth, int mapHeight, int srcStride,
- const QClipData *clip)
+ const QClipData *clip, bool useGammaCorrection)
{
const quint32 c = color.toArgb32();
@@ -5714,7 +5712,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
if (!colorProfile)
return;
- const QRgba64 slinear = colorProfile->toLinear64(c);
+ const QRgba64 slinear = useGammaCorrection ? colorProfile->toLinear64(c) : color;
if (sa == 0)
return;
@@ -5729,7 +5727,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
dst[i] = c;
} else if (coverage != 0xff000000) {
if (dst[i] >= 0xff000000) {
- rgbBlendPixel(dst+i, coverage, slinear, colorProfile);
+ rgbBlendPixel(dst+i, coverage, slinear, colorProfile, useGammaCorrection);
} else {
// Give up and do a naive blend.
const int a = qRgbAvg(coverage);
@@ -5765,7 +5763,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
dst[xp] = c;
} else if (coverage != 0xff000000) {
if (dst[xp] >= 0xff000000) {
- rgbBlendPixel(dst+xp, coverage, slinear, colorProfile);
+ rgbBlendPixel(dst+xp, coverage, slinear, colorProfile, useGammaCorrection);
} else {
// Give up and do a naive blend.
const int a = qRgbAvg(coverage);
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index a833520b00..cdb374f823 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -539,7 +539,7 @@ void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *bitmap,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *)
+ const QClipData *, bool /*useGammaCorrection*/)
{
quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16);
diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h
index 3cf949fc32..40475a9bde 100644
--- a/src/gui/painting/qdrawhelper_neon_p.h
+++ b/src/gui/painting/qdrawhelper_neon_p.h
@@ -91,7 +91,7 @@ void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *bitmap,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip);
+ const QClipData *clip, bool /*useGammaCorrection*/);
void qt_scale_image_argb32_on_rgb16_neon(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl, int srch,
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index e4a1faf25b..cf2213042d 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -113,13 +113,13 @@ typedef void (*AlphamapBlitFunc)(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uchar *bitmap,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip);
+ const QClipData *clip, bool useGammaCorrection);
typedef void (*AlphaRGBBlitFunc)(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uint *rgbmask,
int mapWidth, int mapHeight, int mapStride,
- const QClipData *clip);
+ const QClipData *clip, bool useGammaCorrection);
typedef void (*RectFillFunc)(QRasterBuffer *rasterBuffer,
int x, int y, int width, int height,
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 43464d5d2c..09177db2ab 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -2555,7 +2555,7 @@ QRasterBuffer *QRasterPaintEngine::rasterBuffer()
/*!
\internal
*/
-void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h)
+void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h, bool useGammaCorrection)
{
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
@@ -2610,14 +2610,14 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
} else if (depth == 8) {
if (s->penData.alphamapBlit) {
s->penData.alphamapBlit(rb, rx, ry, s->penData.solid.color,
- scanline, w, h, bpl, 0);
+ scanline, w, h, bpl, 0, useGammaCorrection);
return;
}
} else if (depth == 32) {
// (A)RGB Alpha mask where the alpha component is not used.
if (s->penData.alphaRGBBlit) {
s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solid.color,
- (const uint *) scanline, w, h, bpl / 4, 0);
+ (const uint *) scanline, w, h, bpl / 4, 0, useGammaCorrection);
return;
}
}
@@ -2646,10 +2646,10 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
}
if (depth == 8)
s->penData.alphamapBlit(rb, rx, ry, s->penData.solid.color,
- scanline, w, h, bpl, clip);
+ scanline, w, h, bpl, clip, useGammaCorrection);
else if (depth == 32)
s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solid.color,
- (const uint *) scanline, w, h, bpl / 4, clip);
+ (const uint *) scanline, w, h, bpl / 4, clip, useGammaCorrection);
return;
}
}
@@ -2807,7 +2807,8 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
alphaPenBlt(alphaMap->constBits(), alphaMap->bytesPerLine(), alphaMap->depth(),
qFloor(positions[i].x) + offset.x(),
qRound(positions[i].y) + offset.y(),
- alphaMap->width(), alphaMap->height());
+ alphaMap->width(), alphaMap->height(),
+ fontEngine->expectsGammaCorrectedBlending());
fontEngine->unlockAlphaMapForGlyph();
}
@@ -2868,7 +2869,7 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
drawImage(QPoint(x, y), QImage(glyphBits, c.w, c.h, bpl, image.format()));
s->matrix = originalTransform;
} else {
- alphaPenBlt(glyphBits, bpl, depth, x, y, c.w, c.h);
+ alphaPenBlt(glyphBits, bpl, depth, x, y, c.w, c.h, fontEngine->expectsGammaCorrectedBlending());
}
}
}
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 59213220a6..d0b82b3a93 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -225,7 +225,7 @@ public:
#endif
QRasterBuffer *rasterBuffer();
- void alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h);
+ void alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h, bool useGammaCorrection);
Type type() const Q_DECL_OVERRIDE { return Raster; }
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 0b2972f189..8d8ca1ba2c 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -445,6 +445,11 @@ bool QFontEngine::supportsTransformation(const QTransform &transform) const
return transform.type() < QTransform::TxProject;
}
+bool QFontEngine::expectsGammaCorrectedBlending() const
+{
+ return true;
+}
+
void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,
QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions)
{
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index de6da88245..03e72546eb 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -61,17 +61,19 @@
#include FT_TRUETYPE_TABLES_H
#include FT_TYPE1_TABLES_H
#include FT_GLYPH_H
+#include FT_MODULE_H
#if defined(FT_LCD_FILTER_H)
#include FT_LCD_FILTER_H
+#define QT_USE_FREETYPE_LCDFILTER
#endif
#if defined(FT_CONFIG_OPTIONS_H)
#include FT_CONFIG_OPTIONS_H
#endif
-#if defined(FT_LCD_FILTER_H)
-#define QT_USE_FREETYPE_LCDFILTER
+#if defined(FT_FONT_FORMATS_H)
+#include FT_FONT_FORMATS_H
#endif
#ifdef QT_LINUXBASE
@@ -151,6 +153,14 @@ QtFreetypeData *qt_getFreetypeData()
QtFreetypeData *&freetypeData = theFreetypeData()->localData();
if (!freetypeData)
freetypeData = new QtFreetypeData;
+ if (!freetypeData->library) {
+ FT_Init_FreeType(&freetypeData->library);
+#if defined(FT_FONT_FORMATS_H)
+ // Freetype defaults to disabling stem-darkening on CFF, we re-enable it.
+ FT_Bool no_darkening = false;
+ FT_Property_Set(freetypeData->library, "cff", "no-stem-darkening", &no_darkening);
+#endif
+ }
return freetypeData;
}
#endif
@@ -158,8 +168,7 @@ QtFreetypeData *qt_getFreetypeData()
FT_Library qt_getFreetype()
{
QtFreetypeData *freetypeData = qt_getFreetypeData();
- if (!freetypeData->library)
- FT_Init_FreeType(&freetypeData->library);
+ Q_ASSERT(freetypeData->library);
return freetypeData->library;
}
@@ -218,8 +227,6 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
return 0;
QtFreetypeData *freetypeData = qt_getFreetypeData();
- if (!freetypeData->library)
- FT_Init_FreeType(&freetypeData->library);
QFreetypeFace *freetype = freetypeData->faces.value(face_id, 0);
if (freetype) {
@@ -687,6 +694,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
cacheEnabled = env.isEmpty() || env.toInt() == 0;
m_subPixelPositionCount = 4;
forceAutoHint = false;
+ stemDarkeningDriver = false;
}
QFontEngineFT::~QFontEngineFT()
@@ -798,6 +806,17 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
}
}
}
+#if defined(FT_FONT_FORMATS_H)
+ const char *fmt = FT_Get_Font_Format(face);
+ if (fmt && qstrncmp(fmt, "CFF", 4) == 0) {
+ FT_Bool no_stem_darkening = true;
+ FT_Error err = FT_Property_Get(qt_getFreetype(), "cff", "no-stem-darkening", &no_stem_darkening);
+ if (err == FT_Err_Ok)
+ stemDarkeningDriver = !no_stem_darkening;
+ else
+ stemDarkeningDriver = false;
+ }
+#endif
fontDef.styleName = QString::fromUtf8(face->style_name);
@@ -841,6 +860,11 @@ void QFontEngineFT::setDefaultHintStyle(HintStyle style)
default_hint_style = style;
}
+bool QFontEngineFT::expectsGammaCorrectedBlending() const
+{
+ return stemDarkeningDriver;
+}
+
int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
bool &hsubpixel, int &vfactor) const
{
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index 32357d0076..47f13eb274 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -252,6 +252,7 @@ private:
QPoint *offset) Q_DECL_OVERRIDE;
bool hasInternalCaching() const Q_DECL_OVERRIDE { return cacheEnabled; }
void unlockAlphaMapForGlyph() Q_DECL_OVERRIDE;
+ bool expectsGammaCorrectedBlending() const Q_DECL_OVERRIDE;
void removeGlyphFromCache(glyph_t glyph) Q_DECL_OVERRIDE;
int glyphMargin(QFontEngine::GlyphFormat /* format */) Q_DECL_OVERRIDE { return 0; }
@@ -311,6 +312,7 @@ protected:
bool embeddedbitmap;
bool cacheEnabled;
bool forceAutoHint;
+ bool stemDarkeningDriver;
private:
friend class QFontEngineFTRawFont;
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index c0e350f755..514e9424b2 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -254,6 +254,7 @@ public:
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily);
virtual bool hasUnreliableGlyphOutline() const;
+ virtual bool expectsGammaCorrectedBlending() const;
enum HintStyle {
HintNone,