summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp83
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp206
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h3
-rw-r--r--src/plugins/platforms/windows/windows.pri3
4 files changed, 232 insertions, 63 deletions
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index 966be8c991..68a8fc5390 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -62,7 +62,11 @@
#endif
#if !defined(QT_NO_DIRECTWRITE)
-# include <dwrite.h>
+# if defined(QT_USE_DIRECTWRITE2)
+# include <dwrite_2.h>
+# else
+# include <dwrite.h>
+# endif
# include <d2d1.h>
#endif
@@ -86,17 +90,27 @@ static inline DWriteCreateFactoryType resolveDWriteCreateFactory()
return reinterpret_cast<DWriteCreateFactoryType>(result);
}
-static IDWriteFactory *createDirectWriteFactory()
+static void createDirectWriteFactory(IDWriteFactory **factory)
{
+ *factory = Q_NULLPTR;
+
static const DWriteCreateFactoryType dWriteCreateFactory = resolveDWriteCreateFactory();
if (!dWriteCreateFactory)
- return Q_NULLPTR;
- IUnknown *result = Q_NULLPTR;
- if (FAILED(dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &result))) {
- qErrnoWarning("DWriteCreateFactory failed");
- return Q_NULLPTR;
+ return;
+
+ IUnknown *result = NULL;
+#if defined(QT_USE_DIRECTWRITE2)
+ dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &result);
+#endif
+
+ if (result == NULL) {
+ if (FAILED(dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &result))) {
+ qErrnoWarning("DWriteCreateFactory failed");
+ return;
+ }
}
- return reinterpret_cast<IDWriteFactory *>(result);
+
+ *factory = static_cast<IDWriteFactory *>(result);
}
#endif // !QT_NO_DIRECTWRITE
@@ -506,8 +520,10 @@ namespace {
class CustomFontFileLoader
{
public:
- CustomFontFileLoader() : m_directWriteFactory(createDirectWriteFactory()), m_directWriteFontFileLoader(0)
+ CustomFontFileLoader() : m_directWriteFontFileLoader(Q_NULLPTR)
{
+ createDirectWriteFactory(&m_directWriteFactory);
+
if (m_directWriteFactory) {
m_directWriteFontFileLoader = new DirectWriteFontFileLoader();
m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
@@ -606,7 +622,7 @@ qreal QWindowsFontDatabase::fontSmoothingGamma()
static inline bool initDirectWrite(QWindowsFontEngineData *d)
{
if (!d->directWriteFactory) {
- d->directWriteFactory = createDirectWriteFactory();
+ createDirectWriteFactory(&d->directWriteFactory);
if (!d->directWriteFactory)
return false;
}
@@ -1757,10 +1773,7 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request,
}
#if !defined(QT_NO_DIRECTWRITE)
- bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting)
- || (request.hintingPreference == QFont::PreferVerticalHinting)
- || (QHighDpiScaling::isActive() && request.hintingPreference == QFont::PreferDefaultHinting);
- if (useDirectWrite && initDirectWrite(data.data())) {
+ if (initDirectWrite(data.data())) {
const QString fam = QString::fromWCharArray(lf.lfFaceName);
const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam);
if (nameSubstitute != fam) {
@@ -1782,18 +1795,38 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request,
qWarning().noquote().nospace() << "DirectWrite: CreateFontFaceFromHDC() failed ("
<< errorString << ") for " << request << ' ' << lf << " dpi=" << dpi;
} else {
- QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace,
- request.pixelSize,
- data);
-
- wchar_t n[64];
- GetTextFace(data->hdc, 64, n);
-
- QFontDef fontDef = request;
- fontDef.family = QString::fromWCharArray(n);
+ bool isColorFont = false;
+#if defined(QT_USE_DIRECTWRITE2)
+ IDWriteFontFace2 *directWriteFontFace2 = Q_NULLPTR;
+ if (SUCCEEDED(directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace2),
+ reinterpret_cast<void **>(&directWriteFontFace2)))) {
+ if (directWriteFontFace2->IsColorFont())
+ isColorFont = true;
+ }
+#endif
- fedw->initFontInfo(fontDef, dpi);
- fe = fedw;
+ bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting)
+ || (request.hintingPreference == QFont::PreferVerticalHinting)
+ || (QHighDpiScaling::isActive() && request.hintingPreference == QFont::PreferDefaultHinting)
+ || isColorFont;
+ if (useDirectWrite) {
+ QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace,
+ request.pixelSize,
+ data);
+
+ wchar_t n[64];
+ GetTextFace(data->hdc, 64, n);
+
+ QFontDef fontDef = request;
+ fontDef.family = QString::fromWCharArray(n);
+
+ if (isColorFont)
+ fedw->glyphFormat = QFontEngine::Format_ARGB;
+ fedw->initFontInfo(fontDef, dpi);
+ fe = fedw;
+ } else {
+ directWriteFontFace->Release();
+ }
}
SelectObject(data->hdc, oldFont);
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
index 9dbfac34ef..5408ff41e5 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp
@@ -49,7 +49,12 @@
#include <private/qstringiterator_p.h>
#include <QtCore/private/qsystemlibrary_p.h>
-#include <dwrite.h>
+#if defined(QT_USE_DIRECTWRITE2)
+# include <dwrite_2.h>
+#else
+# include <dwrite.h>
+#endif
+
#include <d2d1.h>
QT_BEGIN_NAMESPACE
@@ -562,61 +567,181 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
RECT rect;
glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
- rect.left -= margin;
- rect.top -= margin;
- rect.right += margin;
- rect.bottom += margin;
+ QRect boundingRect = QRect(QPoint(rect.left - margin,
+ rect.top - margin),
+ QPoint(rect.right + margin,
+ rect.bottom + margin));
+
+
+ const int width = boundingRect.width() - 1; // -1 due to Qt's off-by-one definition of a QRect
+ const int height = boundingRect.height() - 1;
+
+ QImage image;
+#if defined(QT_USE_DIRECTWRITE2)
+ HRESULT hr = DWRITE_E_NOCOLOR;
+ IDWriteColorGlyphRunEnumerator *enumerator = 0;
+ IDWriteFactory2 *factory2 = Q_NULLPTR;
+ if (glyphFormat == QFontEngine::Format_ARGB
+ && SUCCEEDED(m_fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory2),
+ reinterpret_cast<void **>(&factory2)))) {
+ hr = factory2->TranslateColorGlyphRun(0.0f,
+ 0.0f,
+ &glyphRun,
+ NULL,
+ DWRITE_MEASURING_MODE_NATURAL,
+ NULL,
+ 0,
+ &enumerator);
+ image = QImage(width, height, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ } else
+#endif
+ {
+ image = QImage(width, height, QImage::Format_RGB32);
+ image.fill(0xffffffff);
+ }
+
+#if defined(QT_USE_DIRECTWRITE2)
+ BOOL ok = true;
+ if (SUCCEEDED(hr)) {
+ while (SUCCEEDED(hr) && ok) {
+ const DWRITE_COLOR_GLYPH_RUN *colorGlyphRun = 0;
+ hr = enumerator->GetCurrentRun(&colorGlyphRun);
+ if (FAILED(hr)) { // No colored runs, only outline
+ qErrnoWarning(hr, "%s: IDWriteColorGlyphRunEnumerator::GetCurrentRun failed", __FUNCTION__);
+ break;
+ }
+
+ IDWriteGlyphRunAnalysis *colorGlyphsAnalysis = NULL;
+ hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
+ &colorGlyphRun->glyphRun,
+ 1.0f,
+ &transform,
+ renderMode,
+ DWRITE_MEASURING_MODE_NATURAL,
+ 0.0, 0.0,
+ &colorGlyphsAnalysis
+ );
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "%s: CreateGlyphRunAnalysis failed for color run", __FUNCTION__);
+ 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);
+
+ if (!qFuzzyIsNull(a)) {
+ renderGlyphRun(&image,
+ r,
+ g,
+ b,
+ a,
+ colorGlyphsAnalysis,
+ boundingRect);
+ }
+ colorGlyphsAnalysis->Release();
+
+ hr = enumerator->MoveNext(&ok);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "%s: IDWriteColorGlyphRunEnumerator::MoveNext failed", __FUNCTION__);
+ break;
+ }
+ }
+ } else
+#endif
+ {
+ renderGlyphRun(&image,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ glyphAnalysis,
+ boundingRect);
+ }
+
+ glyphAnalysis->Release();
+ return image;
+ } else {
+ qErrnoWarning(hr, "%s: CreateGlyphRunAnalysis failed", __FUNCTION__);
+ return QImage();
+ }
+}
+
- const int width = rect.right - rect.left;
- const int height = rect.bottom - rect.top;
+void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
+ float r,
+ float g,
+ float b,
+ float a,
+ IDWriteGlyphRunAnalysis *glyphAnalysis,
+ const QRect &boundingRect)
+{
+ const int width = destination->width();
+ const int height = destination->height();
- const int size = width * height * 3;
- if (size > 0) {
- BYTE *alphaValues = new BYTE[size];
- memset(alphaValues, 0, size);
+ r *= 255.0;
+ g *= 255.0;
+ b *= 255.0;
- hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
- &rect,
- alphaValues,
- size);
+ const int size = width * height * 3;
+ if (size > 0) {
+ RECT rect;
+ rect.left = boundingRect.left();
+ rect.top = boundingRect.top();
+ rect.right = boundingRect.right();
+ rect.bottom = boundingRect.bottom();
+
+ QVarLengthArray<BYTE, 1024> alphaValueArray(size);
+ BYTE *alphaValues = alphaValueArray.data();
+ memset(alphaValues, 0, size);
+
+ HRESULT hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
+ &rect,
+ alphaValues,
+ size);
+ if (SUCCEEDED(hr)) {
+ if (destination->hasAlphaChannel()) {
+ for (int y = 0; y < height; ++y) {
+ uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
+ BYTE *src = alphaValues + width * 3 * y;
- if (SUCCEEDED(hr)) {
- QImage img(width, height, QImage::Format_RGB32);
- img.fill(0xffffffff);
+ for (int x = 0; x < width; ++x) {
+ float redAlpha = a * *src++ / 255.0;
+ float greenAlpha = a * *src++ / 255.0;
+ float blueAlpha = a * *src++ / 255.0;
+ float averageAlpha = (redAlpha + greenAlpha + blueAlpha) / 3.0;
+
+ QRgb currentRgb = dest[x];
+ dest[x] = qRgba(qRound(qRed(currentRgb) * (1.0 - averageAlpha) + averageAlpha * r),
+ qRound(qGreen(currentRgb) * (1.0 - averageAlpha) + averageAlpha * g),
+ qRound(qBlue(currentRgb) * (1.0 - averageAlpha) + averageAlpha * b),
+ qRound(qAlpha(currentRgb) * (1.0 - averageAlpha) + averageAlpha * 255));
+ }
+ }
- for (int y=0; y<height; ++y) {
- uint *dest = reinterpret_cast<uint *>(img.scanLine(y));
+ } else {
+ for (int y = 0; y < height; ++y) {
+ uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
BYTE *src = alphaValues + width * 3 * y;
- for (int x=0; x<width; ++x) {
- dest[x] = *(src) << 16
+ for (int x = 0; x < width; ++x) {
+ dest[x] = *(src + 0) << 16
| *(src + 1) << 8
| *(src + 2);
src += 3;
}
}
-
- delete[] alphaValues;
- glyphAnalysis->Release();
-
- return img;
- } else {
- delete[] alphaValues;
- glyphAnalysis->Release();
-
- qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__);
}
} else {
- glyphAnalysis->Release();
- qWarning("%s: Glyph has no bounds", __FUNCTION__);
+ qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__);
}
-
} else {
- qErrnoWarning("%s: CreateGlyphRunAnalysis failed", __FUNCTION__);
+ glyphAnalysis->Release();
+ qWarning("%s: Glyph has no bounds", __FUNCTION__);
}
-
- return QImage();
}
QImage QWindowsFontEngineDirectWrite::alphaRGBMapForGlyph(glyph_t t,
@@ -734,6 +859,11 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph
}
}
+QImage QWindowsFontEngineDirectWrite::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
+{
+ return imageForGlyph(glyph, subPixelPosition, glyphMargin(QFontEngine::Format_A32), t);
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DIRECTWRITE
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
index 0aa7e41500..f038dcfde4 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
@@ -52,6 +52,7 @@ struct IDWriteFontFace;
struct IDWriteFactory;
struct IDWriteBitmapRenderTarget;
struct IDWriteGdiInterop;
+struct IDWriteGlyphRunAnalysis;
QT_BEGIN_NAMESPACE
@@ -96,6 +97,7 @@ public:
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) Q_DECL_OVERRIDE;
QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) Q_DECL_OVERRIDE;
+ QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE;
Qt::HANDLE handle() const Q_DECL_OVERRIDE;
@@ -109,6 +111,7 @@ public:
private:
QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform);
void collectMetrics();
+ void renderGlyphRun(QImage *destination, float r, float g, float b, float a, IDWriteGlyphRunAnalysis *glyphAnalysis, const QRect &boundingRect);
const QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index d46cfbc43a..f4dbd10a49 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -13,6 +13,9 @@ wince: DEFINES *= QT_LIBINFIX=L"\"\\\"$${QT_LIBINFIX}\\\"\""
DEFINES *= QT_NO_CAST_FROM_ASCII
contains(QT_CONFIG, directwrite) {
+ contains(QT_CONFIG, directwrite2): \
+ DEFINES *= QT_USE_DIRECTWRITE2
+
SOURCES += $$PWD/qwindowsfontenginedirectwrite.cpp
HEADERS += $$PWD/qwindowsfontenginedirectwrite.h
} else {