DirectWrite: Fix embedding fonts in PDF
If no filename is stored in the faceId() of the font engine, then the PDF engine will bail out and embed each glyph separately instead of embedding the font. This would cause PDFs to be huge and unsearchable when high-dpi was active, since we will automatically default to the DirectWrite engine in this case. [ChangeLog][QtGui][Windows] Fixed embedding fonts in PDF when dpi scaling is active or when the hinting preference was none or vertical hinting. Task-number: QTBUG-54740 Change-Id: I20630595f51660109c5a12c52076738a04036520 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Simon Hausmann <simon.hausmann@qt.io> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
parent
60e8714e58
commit
001efe14f2
|
|
@ -46,6 +46,7 @@
|
|||
#include <QtCore/QSettings>
|
||||
#include <QtCore/QtEndian>
|
||||
#include <QtCore/QVarLengthArray>
|
||||
#include <QtCore/QFile>
|
||||
#include <private/qstringiterator_p.h>
|
||||
#include <QtCore/private/qsystemlibrary_p.h>
|
||||
|
||||
|
|
@ -236,6 +237,82 @@ QWindowsFontEngineDirectWrite::~QWindowsFontEngineDirectWrite()
|
|||
m_directWriteBitmapRenderTarget->Release();
|
||||
}
|
||||
|
||||
#ifndef Q_CC_MINGW
|
||||
typedef IDWriteLocalFontFileLoader QIdWriteLocalFontFileLoader;
|
||||
|
||||
static UUID uuidIdWriteLocalFontFileLoader()
|
||||
{
|
||||
return __uuidof(IDWriteLocalFontFileLoader);
|
||||
}
|
||||
#else // !Q_CC_MINGW
|
||||
DECLARE_INTERFACE_(QIdWriteLocalFontFileLoader, IDWriteFontFileLoader)
|
||||
{
|
||||
STDMETHOD(GetFilePathLengthFromKey)(THIS_ void const *, UINT32, UINT32*) PURE;
|
||||
STDMETHOD(GetFilePathFromKey)(THIS_ void const *, UINT32, WCHAR *, UINT32) PURE;
|
||||
STDMETHOD(GetLastWriteTimeFromKey)(THIS_ void const *, UINT32, FILETIME *) PURE;
|
||||
};
|
||||
|
||||
static UUID uuidIdWriteLocalFontFileLoader()
|
||||
{
|
||||
static const UUID result = { 0xb2d9f3ec, 0xc9fe, 0x4a11, {0xa2, 0xec, 0xd8, 0x62, 0x8, 0xf7, 0xc0, 0xa2}};
|
||||
return result;
|
||||
}
|
||||
#endif // Q_CC_MINGW
|
||||
|
||||
QString QWindowsFontEngineDirectWrite::filenameFromFontFile(IDWriteFontFile *fontFile)
|
||||
{
|
||||
IDWriteFontFileLoader *loader = Q_NULLPTR;
|
||||
|
||||
HRESULT hr = fontFile->GetLoader(&loader);
|
||||
if (FAILED(hr)) {
|
||||
qErrnoWarning("%s: GetLoader failed", __FUNCTION__);
|
||||
return QString();
|
||||
}
|
||||
|
||||
QIdWriteLocalFontFileLoader *localLoader = Q_NULLPTR;
|
||||
hr = loader->QueryInterface(uuidIdWriteLocalFontFileLoader(),
|
||||
reinterpret_cast<void **>(&localLoader));
|
||||
|
||||
const void *fontFileReferenceKey = Q_NULLPTR;
|
||||
UINT32 fontFileReferenceKeySize = 0;
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = fontFile->GetReferenceKey(&fontFileReferenceKey,
|
||||
&fontFileReferenceKeySize);
|
||||
if (FAILED(hr))
|
||||
qErrnoWarning(hr, "%s: GetReferenceKey failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
UINT32 filePathLength = 0;
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = localLoader->GetFilePathLengthFromKey(fontFileReferenceKey,
|
||||
fontFileReferenceKeySize,
|
||||
&filePathLength);
|
||||
if (FAILED(hr))
|
||||
qErrnoWarning(hr, "GetFilePathLength failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
QString ret;
|
||||
if (SUCCEEDED(hr) && filePathLength > 0) {
|
||||
QVarLengthArray<wchar_t> filePath(filePathLength + 1);
|
||||
|
||||
hr = localLoader->GetFilePathFromKey(fontFileReferenceKey,
|
||||
fontFileReferenceKeySize,
|
||||
filePath.data(),
|
||||
filePathLength + 1);
|
||||
if (FAILED(hr))
|
||||
qErrnoWarning(hr, "%s: GetFilePathFromKey failed", __FUNCTION__);
|
||||
else
|
||||
ret = QString::fromWCharArray(filePath.data());
|
||||
}
|
||||
|
||||
if (localLoader != Q_NULLPTR)
|
||||
localLoader->Release();
|
||||
|
||||
if (loader != Q_NULLPTR)
|
||||
loader->Release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void QWindowsFontEngineDirectWrite::collectMetrics()
|
||||
{
|
||||
DWRITE_FONT_METRICS metrics;
|
||||
|
|
@ -250,6 +327,13 @@ void QWindowsFontEngineDirectWrite::collectMetrics()
|
|||
m_xHeight = DESIGN_TO_LOGICAL(metrics.xHeight);
|
||||
m_lineGap = DESIGN_TO_LOGICAL(metrics.lineGap);
|
||||
m_underlinePosition = DESIGN_TO_LOGICAL(metrics.underlinePosition);
|
||||
|
||||
IDWriteFontFile *fontFile = Q_NULLPTR;
|
||||
UINT32 numberOfFiles = 1;
|
||||
if (SUCCEEDED(m_directWriteFontFace->GetFiles(&numberOfFiles, &fontFile))) {
|
||||
m_faceId.filename = QFile::encodeName(filenameFromFontFile(fontFile));
|
||||
fontFile->Release();
|
||||
}
|
||||
}
|
||||
|
||||
QFixed QWindowsFontEngineDirectWrite::underlinePosition() const
|
||||
|
|
@ -351,6 +435,11 @@ bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGly
|
|||
return true;
|
||||
}
|
||||
|
||||
QFontEngine::FaceId QWindowsFontEngineDirectWrite::faceId() const
|
||||
{
|
||||
return m_faceId;
|
||||
}
|
||||
|
||||
void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const
|
||||
{
|
||||
QVarLengthArray<UINT16> glyphIndices(glyphs->numGlyphs);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
struct IDWriteFont;
|
||||
struct IDWriteFontFace;
|
||||
struct IDWriteFontFile;
|
||||
struct IDWriteFactory;
|
||||
struct IDWriteBitmapRenderTarget;
|
||||
struct IDWriteGdiInterop;
|
||||
|
|
@ -92,6 +93,7 @@ public:
|
|||
QFixed leading() const Q_DECL_OVERRIDE;
|
||||
QFixed xHeight() const Q_DECL_OVERRIDE;
|
||||
qreal maxCharWidth() const Q_DECL_OVERRIDE;
|
||||
FaceId faceId() const Q_DECL_OVERRIDE;
|
||||
|
||||
bool supportsSubPixelPositions() const Q_DECL_OVERRIDE;
|
||||
|
||||
|
|
@ -113,6 +115,7 @@ 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);
|
||||
static QString filenameFromFontFile(IDWriteFontFile *fontFile);
|
||||
|
||||
const QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue