Add color font support on Windows
Detect if DirectWrite 2 is available, and support color fonts if possible. One limitation worth mentioning is that if the color font contains regular, monochrome glyphs as well, then these will be drawn in black, and not in the pen color. Fixing this would require some elaborate rewrites in the font rendering system, since we would have to have two font caches per color font (one for mono and one for colors), or do some sort of trick where we make argb(r, g, b, 0) mean subpixel alpha instead, and detect glyphs that are not correctly premultiplied when blitting to the screen. Another limitation is that the approach does not work with distance field rendering. In principle we could support this on Windows, since the format is vector based, but it would also require substantial work and it is not possible to support for Apple/Google fonts anyway, so it would just lead to code which is not cross-platform. [ChangeLog][Windows] Added support for color fonts (color emojis) when DirectWrite 2 is available. Change-Id: I6a608dd5d2aa3a7e762a06830902bddac7c550a5 Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
This commit is contained in:
parent
0b3e45fa0a
commit
33044b83c2
50
config.tests/win/directwrite2/directwrite2.cpp
Normal file
50
config.tests/win/directwrite2/directwrite2.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the config.tests of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <dwrite_2.h>
|
||||
#include <d2d1.h>
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
IUnknown *factory = 0;
|
||||
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
|
||||
__uuidof(IDWriteFactory2),
|
||||
&factory);
|
||||
return 0;
|
||||
}
|
4
config.tests/win/directwrite2/directwrite2.pro
Normal file
4
config.tests/win/directwrite2/directwrite2.pro
Normal file
@ -0,0 +1,4 @@
|
||||
SOURCES = directwrite2.cpp
|
||||
LIBS += -ldwrite
|
||||
CONFIG -= qt
|
||||
CONFIG += console
|
14
configure
vendored
14
configure
vendored
@ -783,6 +783,7 @@ CFG_PCRE=auto
|
||||
QPA_PLATFORM_GUARD=yes
|
||||
CFG_STDCXX=auto
|
||||
CFG_DIRECTWRITE=no
|
||||
CFG_DIRECTWRITE2=auto
|
||||
CFG_WERROR=auto
|
||||
CFG_HEADERSCLEAN=auto
|
||||
CFG_QREAL=double
|
||||
@ -6301,6 +6302,18 @@ if [ "$CFG_LARGEFILE" != "yes" ] && [ "$XPLATFORM_MINGW" = "yes" ]; then
|
||||
CFG_LARGEFILE="yes"
|
||||
fi
|
||||
|
||||
# Detect DirectWrite 2 support on Windows
|
||||
if [ "$CFG_DIRECTWRITE" = "no" ]; then
|
||||
CFG_DIRECTWRITE2=no
|
||||
fi
|
||||
if [ "$CFG_DIRECTWRITE2" = "auto" ]; then
|
||||
if compileTest win/directwrite2 "directwrite2"; then
|
||||
CFG_DIRECTWRITE2=yes
|
||||
else
|
||||
CFG_DIRECTWRITE2=no
|
||||
fi
|
||||
fi
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# ask for all that hasn't been auto-detected or specified in the arguments
|
||||
#-------------------------------------------------------------------------------
|
||||
@ -6568,6 +6581,7 @@ fi
|
||||
[ "$CFG_XINPUT2" = "yes" ] && QT_CONFIG="$QT_CONFIG xinput2"
|
||||
[ "$CFG_SYSTEM_PROXIES" = "yes" ] && QT_CONFIG="$QT_CONFIG system-proxies"
|
||||
[ "$CFG_DIRECTWRITE" = "yes" ] && QT_CONFIG="$QT_CONFIG directwrite"
|
||||
[ "$CFG_DIRECTWRITE2" = "yes" ] && QT_CONFIG="$QT_CONFIG directwrite2"
|
||||
|
||||
[ '!' -z "$DEFINES" ] && QMakeVar add EXTRA_DEFINES "$DEFINES"
|
||||
[ '!' -z "$INCLUDES" ] && QMakeVar add EXTRA_INCLUDEPATH "$INCLUDES"
|
||||
|
@ -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);
|
||||
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
|
||||
|
||||
wchar_t n[64];
|
||||
GetTextFace(data->hdc, 64, n);
|
||||
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);
|
||||
|
||||
QFontDef fontDef = request;
|
||||
fontDef.family = QString::fromWCharArray(n);
|
||||
wchar_t n[64];
|
||||
GetTextFace(data->hdc, 64, n);
|
||||
|
||||
fedw->initFontInfo(fontDef, dpi);
|
||||
fe = fedw;
|
||||
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);
|
||||
|
@ -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 = rect.right - rect.left;
|
||||
const int height = rect.bottom - rect.top;
|
||||
|
||||
const int size = width * height * 3;
|
||||
if (size > 0) {
|
||||
BYTE *alphaValues = new BYTE[size];
|
||||
memset(alphaValues, 0, size);
|
||||
const int width = boundingRect.width() - 1; // -1 due to Qt's off-by-one definition of a QRect
|
||||
const int height = boundingRect.height() - 1;
|
||||
|
||||
hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
|
||||
&rect,
|
||||
alphaValues,
|
||||
size);
|
||||
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 (SUCCEEDED(hr)) {
|
||||
QImage img(width, height, QImage::Format_RGB32);
|
||||
img.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;
|
||||
}
|
||||
|
||||
for (int y=0; y<height; ++y) {
|
||||
uint *dest = reinterpret_cast<uint *>(img.scanLine(y));
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
|
||||
r *= 255.0;
|
||||
g *= 255.0;
|
||||
b *= 255.0;
|
||||
|
||||
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;
|
||||
|
||||
for (int x=0; x<width; ++x) {
|
||||
dest[x] = *(src) << 16
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
} 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 + 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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -161,6 +161,7 @@ Configure::Configure(int& argc, char** argv) : verbose(0)
|
||||
dictionary[ "QML_DEBUG" ] = "yes";
|
||||
dictionary[ "PLUGIN_MANIFESTS" ] = "no";
|
||||
dictionary[ "DIRECTWRITE" ] = "auto";
|
||||
dictionary[ "DIRECTWRITE2" ] = "auto";
|
||||
dictionary[ "DIRECT2D" ] = "no";
|
||||
dictionary[ "NIS" ] = "no";
|
||||
dictionary[ "NEON" ] = "auto";
|
||||
@ -2235,6 +2236,8 @@ bool Configure::checkAvailability(const QString &part)
|
||||
available = findFile("mfapi.h") && findFile("mf.lib");
|
||||
} else if (part == "DIRECTWRITE") {
|
||||
available = tryCompileProject("win/directwrite");
|
||||
} else if (part == "DIRECTWRITE2") {
|
||||
available = tryCompileProject("win/directwrite2");
|
||||
} else if (part == "DIRECT2D") {
|
||||
available = tryCompileProject("qpa/direct2d");
|
||||
} else if (part == "ICONV") {
|
||||
@ -2488,6 +2491,9 @@ void Configure::autoDetection()
|
||||
if (dictionary["DIRECTWRITE"] == "auto")
|
||||
dictionary["DIRECTWRITE"] = checkAvailability("DIRECTWRITE") ? "yes" : "no";
|
||||
|
||||
if (dictionary["DIRECTWRITE2"] == "auto")
|
||||
dictionary["DIRECTWRITE2"] = checkAvailability("DIRECTWRITE2") ? "yes" : "no";
|
||||
|
||||
// Mark all unknown "auto" to the default value..
|
||||
for (QMap<QString,QString>::iterator i = dictionary.begin(); i != dictionary.end(); ++i) {
|
||||
if (i.value() == "auto")
|
||||
@ -2903,6 +2909,9 @@ void Configure::generateOutputVars()
|
||||
if (dictionary["DIRECTWRITE"] == "yes")
|
||||
qtConfig += "directwrite";
|
||||
|
||||
if (dictionary["DIRECTWRITE2"] == "yes")
|
||||
qtConfig += "directwrite2";
|
||||
|
||||
if (dictionary["DIRECT2D"] == "yes")
|
||||
qtConfig += "direct2d";
|
||||
|
||||
@ -3428,6 +3437,9 @@ void Configure::generateQConfigPri()
|
||||
if (dictionary["DIRECTWRITE"] == "yes")
|
||||
configStream << " directwrite";
|
||||
|
||||
if (dictionary["DIRECTWRITE2"] == "yes")
|
||||
configStream << " directwrite2";
|
||||
|
||||
if (dictionary["ANDROID_STYLE_ASSETS"] == "yes")
|
||||
configStream << " android-style-assets";
|
||||
|
||||
@ -3790,6 +3802,7 @@ void Configure::displayConfig()
|
||||
sout << "Qt GUI module support......." << dictionary[ "GUI" ] << endl;
|
||||
sout << "QML debugging..............." << dictionary[ "QML_DEBUG" ] << endl;
|
||||
sout << "DirectWrite support........." << dictionary[ "DIRECTWRITE" ] << endl;
|
||||
sout << "DirectWrite 2 support......." << dictionary[ "DIRECTWRITE2" ] << endl;
|
||||
sout << "Use system proxies.........." << dictionary[ "SYSTEM_PROXIES" ] << endl;
|
||||
sout << endl;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user