diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-03-24 16:10:15 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-03-24 16:10:15 +0100 |
commit | 3b5c0bc0780f1749fed7c07bd8b691400a0282b7 (patch) | |
tree | 1022f5553ad5a0aca9b5f3b49ca38a01c2329d20 /src/plugins/platforms/winrt | |
parent | c79918733a194ebbe5a2fe1617c884659f3e4b9f (diff) | |
parent | 21f1738a94fc8544ece04b3b1ee03a11986fe59b (diff) |
Merge remote-tracking branch 'origin/stable' into dev
Conflicts:
src/gui/image/qjpeghandler.cpp
Change-Id: I9db3acea7d5c82f5da679c8eaeb29431136665f0
Diffstat (limited to 'src/plugins/platforms/winrt')
-rw-r--r-- | src/plugins/platforms/winrt/qwinrtbackingstore.cpp | 32 | ||||
-rw-r--r-- | src/plugins/platforms/winrt/qwinrtbackingstore.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/winrt/qwinrtfontdatabase.cpp | 314 | ||||
-rw-r--r-- | src/plugins/platforms/winrt/qwinrtfontdatabase.h | 19 | ||||
-rw-r--r-- | src/plugins/platforms/winrt/qwinrtservices.cpp | 3 | ||||
-rw-r--r-- | src/plugins/platforms/winrt/winrt.pro | 5 |
6 files changed, 367 insertions, 8 deletions
diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp index 10136dbead..9b623048af 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp @@ -207,14 +207,24 @@ QWinRTBackingStore::QWinRTBackingStore(QWindow *window) , m_fbo(0) , m_texture(0) , m_screen(static_cast<QWinRTScreen*>(window->screen()->handle())) + , m_initialized(false) { window->setSurfaceType(QSurface::OpenGLSurface); // Required for flipping, but could be done in the swap +} - m_context->setFormat(window->requestedFormat()); - m_context->setScreen(window->screen()); - m_context->create(); +bool QWinRTBackingStore::initialize() +{ + if (m_initialized) + return true; + + m_context->setFormat(window()->requestedFormat()); + m_context->setScreen(window()->screen()); + if (!m_context->create()) + return false; + + if (!m_context->makeCurrent(window())) + return false; - m_context->makeCurrent(window); glGenFramebuffers(1, &m_fbo); glGenRenderbuffers(1, &m_rbo); glGenTextures(1, &m_texture); @@ -258,11 +268,14 @@ QWinRTBackingStore::QWinRTBackingStore(QWindow *window) glProgramBinaryOES(m_shaderProgram, GL_PROGRAM_BINARY_ANGLE, binary.constData(), binary.size()); #endif m_context->doneCurrent(); - resize(window->size(), QRegion()); + m_initialized = true; + return true; } QWinRTBackingStore::~QWinRTBackingStore() { + if (!m_initialized) + return; glDeleteBuffers(1, &m_fbo); glDeleteRenderbuffers(1, &m_rbo); glDeleteTextures(1, &m_texture); @@ -277,6 +290,8 @@ QPaintDevice *QWinRTBackingStore::paintDevice() void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { Q_UNUSED(offset) + if (m_size.isEmpty()) + return; const QImage *image = static_cast<QImage *>(m_paintDevice.data()); @@ -334,10 +349,16 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents) { Q_UNUSED(staticContents) + if (!initialize()) + return; + if (m_size == size) return; m_size = size; + if (m_size.isEmpty()) + return; + m_paintDevice.reset(new QImage(m_size, QImage::Format_ARGB32_Premultiplied)); m_context->makeCurrent(window()); @@ -360,6 +381,7 @@ void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents void QWinRTBackingStore::beginPaint(const QRegion ®ion) { Q_UNUSED(region) + resize(window()->size(), QRegion()); } void QWinRTBackingStore::endPaint() diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h index 8be549b441..726f7c838f 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.h +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h @@ -62,6 +62,8 @@ public: void resize(const QSize &size, const QRegion &staticContents); private: + bool initialize(); + bool m_initialized; QSize m_size; QScopedPointer<QPaintDevice> m_paintDevice; QScopedPointer<QOpenGLContext> m_context; diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp index c7fa339fad..3da87de708 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp @@ -44,6 +44,14 @@ #include <QtCore/QCoreApplication> #include <QtCore/QFile> +#ifndef Q_OS_WINPHONE +#include <QtCore/QUuid> +#include <QtGui/private/qfontengine_ft_p.h> +#include <dwrite_1.h> +#include <wrl.h> +using namespace Microsoft::WRL; +#endif // !Q_OS_WINPHONE + QT_BEGIN_NAMESPACE QString QWinRTFontDatabase::fontDir() const @@ -54,11 +62,315 @@ QString QWinRTFontDatabase::fontDir() const const QString applicationDirPath = QCoreApplication::applicationDirPath(); fontDirectory = applicationDirPath + QLatin1String("/fonts"); if (!QFile::exists(fontDirectory)) { - qWarning("No fonts directory found in application package."); +#ifndef Q_OS_WINPHONE + if (m_fonts.isEmpty()) +#endif + qWarning("No fonts directory found in application package."); fontDirectory = applicationDirPath; } } return fontDirectory; } +#ifndef Q_OS_WINPHONE + +QWinRTFontDatabase::~QWinRTFontDatabase() +{ + foreach (IDWriteFontFile *fontFile, m_fonts.keys()) + fontFile->Release(); +} + +QFont QWinRTFontDatabase::defaultFont() const +{ + return QFont(QStringLiteral("Segoe UI")); +} + +void QWinRTFontDatabase::populateFontDatabase() +{ + ComPtr<IDWriteFactory1> factory; + HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory1), &factory); + if (FAILED(hr)) { + qWarning("Failed to create DirectWrite factory: %s", qPrintable(qt_error_string(hr))); + QBasicFontDatabase::populateFontDatabase(); + return; + } + + ComPtr<IDWriteFontCollection> fontCollection; + hr = factory->GetSystemFontCollection(&fontCollection); + if (FAILED(hr)) { + qWarning("Failed to open system font collection: %s", qPrintable(qt_error_string(hr))); + QBasicFontDatabase::populateFontDatabase(); + return; + } + + int fontFamilyCount = fontCollection->GetFontFamilyCount(); + for (int i = 0; i < fontFamilyCount; ++i) { + ComPtr<IDWriteFontFamily> fontFamily; + hr = fontCollection->GetFontFamily(i, &fontFamily); + if (FAILED(hr)) { + qWarning("Unable to get font family: %s", qPrintable(qt_error_string(hr))); + continue; + } + + ComPtr<IDWriteLocalizedStrings> names; + hr = fontFamily->GetFamilyNames(&names); + if (FAILED(hr)) { + qWarning("Unable to get font family names: %s", qPrintable(qt_error_string(hr))); + continue; + } + quint32 familyNameLength; + hr = names->GetStringLength(0, &familyNameLength); + if (FAILED(hr)) { + qWarning("Unable to get family name length: %s", qPrintable(qt_error_string(hr))); + continue; + } + QVector<wchar_t> familyBuffer(familyNameLength + 1); + hr = names->GetString(0, familyBuffer.data(), familyBuffer.size()); + if (FAILED(hr)) { + qWarning("Unable to create font family name: %s", qPrintable(qt_error_string(hr))); + continue; + } + QString familyName = QString::fromWCharArray(familyBuffer.data(), familyNameLength); + + int fontCount = fontFamily->GetFontCount(); + for (int j = 0; j < fontCount; ++j) { + ComPtr<IDWriteFont> font; + hr = fontFamily->GetFont(j, &font); + if (FAILED(hr)) { + qWarning("Unable to get base font: %s", qPrintable(qt_error_string(hr))); + continue; + } + + ComPtr<IDWriteFontFace> baseFontFace; + hr = font->CreateFontFace(&baseFontFace); + if (FAILED(hr)) { + qWarning("Unable to create base font face: %s", qPrintable(qt_error_string(hr))); + continue; + } + ComPtr<IDWriteFontFace1> fontFace; + hr = baseFontFace.As(&fontFace); + if (FAILED(hr)) { + qWarning("Unable to create font face: %s", qPrintable(qt_error_string(hr))); + continue; + } + + // Only try to load true-type fonts + DWRITE_FONT_FACE_TYPE type = fontFace->GetType(); + if (!(type == DWRITE_FONT_FACE_TYPE_TRUETYPE + || type == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)) { + continue; + } + + // We can't deal with multi-file fonts + quint32 fileCount; + hr = fontFace->GetFiles(&fileCount, NULL); + if (FAILED(hr)) { + qWarning("Unable to get font file count: %s", qPrintable(qt_error_string(hr))); + continue; + } + if (fileCount != 1) // Should not happen as we only look at TT fonts + continue; + + ComPtr<IDWriteLocalizedStrings> informationalStrings; + BOOL exists; + hr = font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_MANUFACTURER, + &informationalStrings, &exists); + if (FAILED(hr)) { + qWarning("Unable to get font foundry: %s", qPrintable(qt_error_string(hr))); + continue; + } + QString foundryName; + if (exists) { + quint32 length; + hr = informationalStrings->GetStringLength(0, &length); + if (FAILED(hr)) + qWarning("Unable to get foundry name length: %s", qPrintable(qt_error_string(hr))); + if (SUCCEEDED(hr)) { + QVector<wchar_t> buffer(length + 1); + hr = informationalStrings->GetString(0, buffer.data(), buffer.size()); + if (FAILED(hr)) + qWarning("Unable to get foundry name: %s", qPrintable(qt_error_string(hr))); + if (SUCCEEDED(hr)) + foundryName = QString::fromWCharArray(buffer.data(), length); + } + } + + QFont::Weight weight; + switch (font->GetWeight()) { + case DWRITE_FONT_WEIGHT_THIN: + case DWRITE_FONT_WEIGHT_EXTRA_LIGHT: + case DWRITE_FONT_WEIGHT_LIGHT: + case DWRITE_FONT_WEIGHT_SEMI_LIGHT: + weight = QFont::Light; + break; + default: + case DWRITE_FONT_WEIGHT_NORMAL: + case DWRITE_FONT_WEIGHT_MEDIUM: + weight = QFont::Normal; + break; + case DWRITE_FONT_WEIGHT_DEMI_BOLD: + weight = QFont::DemiBold; + break; + case DWRITE_FONT_WEIGHT_BOLD: + case DWRITE_FONT_WEIGHT_EXTRA_BOLD: + weight = QFont::Bold; + break; + case DWRITE_FONT_WEIGHT_BLACK: + case DWRITE_FONT_WEIGHT_EXTRA_BLACK: + weight = QFont::Black; + break; + } + + QFont::Style style; + switch (font->GetStyle()) { + default: + case DWRITE_FONT_STYLE_NORMAL: + style = QFont::StyleNormal; + break; + case DWRITE_FONT_STYLE_OBLIQUE: + style = QFont::StyleOblique; + break; + case DWRITE_FONT_STYLE_ITALIC: + style = QFont::StyleItalic; + break; + } + + QFont::Stretch stretch; + switch (font->GetStretch()) { + default: + case DWRITE_FONT_STRETCH_UNDEFINED: + case DWRITE_FONT_STRETCH_NORMAL: + stretch = QFont::Unstretched; + break; + case DWRITE_FONT_STRETCH_ULTRA_CONDENSED: + stretch = QFont::UltraCondensed; + break; + case DWRITE_FONT_STRETCH_EXTRA_CONDENSED: + stretch = QFont::ExtraCondensed; + break; + case DWRITE_FONT_STRETCH_CONDENSED: + stretch = QFont::Condensed; + break; + case DWRITE_FONT_STRETCH_SEMI_CONDENSED: + stretch = QFont::SemiCondensed; + break; + case DWRITE_FONT_STRETCH_SEMI_EXPANDED: + stretch = QFont::SemiExpanded; + break; + case DWRITE_FONT_STRETCH_EXPANDED: + stretch = QFont::Expanded; + break; + case DWRITE_FONT_STRETCH_EXTRA_EXPANDED: + stretch = QFont::ExtraExpanded; + break; + case DWRITE_FONT_STRETCH_ULTRA_EXPANDED: + stretch = QFont::UltraExpanded; + break; + } + + const bool fixedPitch = fontFace->IsMonospacedFont(); + + quint32 unicodeRange[4]; + quint32 actualRangeCount; + hr = fontFace->GetUnicodeRanges( + 2, reinterpret_cast<DWRITE_UNICODE_RANGE *>(unicodeRange), &actualRangeCount); + if (FAILED(hr) && hr != E_NOT_SUFFICIENT_BUFFER) { // Ignore insufficient buffer; we only need 4 indices + qWarning("Unable to get font unicode range: %s", qPrintable(qt_error_string(hr))); + continue; + } + quint32 codePageRange[2] = { 0, 0 }; + QSupportedWritingSystems writingSystems = + QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange); + + IDWriteFontFile *fontFile; + hr = fontFace->GetFiles(&fileCount, &fontFile); + if (FAILED(hr)) { + qWarning("Unable to get font file: %s", qPrintable(qt_error_string(hr))); + continue; + } + + FontDescription description = { fontFace->GetIndex(), QUuid::createUuid().toByteArray() }; + m_fonts.insert(fontFile, description); + registerFont(familyName, QString(), foundryName, weight, style, stretch, + true, true, 0, fixedPitch, writingSystems, fontFile); + } + } + + QBasicFontDatabase::populateFontDatabase(); +} + +QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) +{ + IDWriteFontFile *fontFile = reinterpret_cast<IDWriteFontFile *>(handle); + if (!m_fonts.contains(fontFile)) + return QBasicFontDatabase::fontEngine(fontDef, handle); + + const void *referenceKey; + quint32 referenceKeySize; + HRESULT hr = fontFile->GetReferenceKey(&referenceKey, &referenceKeySize); + if (FAILED(hr)) { + qWarning("Unable to get font file reference key: %s", qPrintable(qt_error_string(hr))); + return 0; + } + + ComPtr<IDWriteFontFileLoader> loader; + hr = fontFile->GetLoader(&loader); + if (FAILED(hr)) { + qWarning("Unable to get font file loader: %s", qPrintable(qt_error_string(hr))); + return 0; + } + + ComPtr<IDWriteFontFileStream> stream; + hr =loader->CreateStreamFromKey(referenceKey, referenceKeySize, &stream); + if (FAILED(hr)) { + qWarning("Unable to get font file stream: %s", qPrintable(qt_error_string(hr))); + return 0; + } + + quint64 fileSize; + hr = stream->GetFileSize(&fileSize); + if (FAILED(hr)) { + qWarning("Unable to get font file size: %s", qPrintable(qt_error_string(hr))); + return 0; + } + + const void *data; + void *context; + hr = stream->ReadFileFragment(&data, 0, fileSize, &context); + if (FAILED(hr)) { + qWarning("Unable to get font file data: %s", qPrintable(qt_error_string(hr))); + return 0; + } + const QByteArray fontData((const char *)data, fileSize); + stream->ReleaseFileFragment(context); + + QFontEngine::FaceId faceId; + const FontDescription description = m_fonts.value(fontFile); + faceId.uuid = description.uuid; + faceId.index = description.index; + const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + QFontEngineFT::GlyphFormat format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; + QFontEngineFT *engine = new QFontEngineFT(fontDef); + if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) { + delete engine; + return 0; + } + + return engine; +} + +void QWinRTFontDatabase::releaseHandle(void *handle) +{ + IDWriteFontFile *fontFile = reinterpret_cast<IDWriteFontFile *>(handle); + if (m_fonts.contains(fontFile)) { + m_fonts.remove(fontFile); + fontFile->Release(); + return; + } + + QBasicFontDatabase::releaseHandle(handle); +} + +#endif // !Q_OS_WINPHONE + QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h index 49e32470c2..6f194a10cc 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h @@ -46,10 +46,29 @@ QT_BEGIN_NAMESPACE +#ifndef Q_OS_WINPHONE +struct IDWriteFontFile; + +struct FontDescription +{ + quint32 index; + QByteArray uuid; +}; +#endif + class QWinRTFontDatabase : public QBasicFontDatabase { public: QString fontDir() const; +#ifndef Q_OS_WINPHONE + ~QWinRTFontDatabase(); + QFont defaultFont() const Q_DECL_OVERRIDE; + void populateFontDatabase() Q_DECL_OVERRIDE; + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; + void releaseHandle(void *handle) Q_DECL_OVERRIDE; +private: + QHash<IDWriteFontFile *, FontDescription> m_fonts; +#endif // !Q_OS_WINPHONE }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp index 8f0a1d55bb..73c090351b 100644 --- a/src/plugins/platforms/winrt/qwinrtservices.cpp +++ b/src/plugins/platforms/winrt/qwinrtservices.cpp @@ -106,8 +106,7 @@ bool QWinRTServices::openDocument(const QUrl &url) if (!(m_fileFactory && m_launcher)) return QPlatformServices::openDocument(url); - QString pathString = QDir::toNativeSeparators( - QDir::cleanPath(qApp->applicationDirPath().append(url.toString(QUrl::RemoveScheme)))); + const QString pathString = QDir::toNativeSeparators(url.toLocalFile()); HSTRING_HEADER header; HSTRING path; WindowsCreateStringReference((const wchar_t*)pathString.utf16(), pathString.length(), &header, &path); IAsyncOperation<StorageFile*> *fileOp; diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index 6e3cfb1d20..306bbc8174 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -11,6 +11,11 @@ DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ GL_GLEXT_PROTOTYPES LIBS += $$QMAKE_LIBS_CORE +!winphone { + LIBS += -ldwrite + INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/freetype/include +} + SOURCES = \ main.cpp \ qwinrtbackingstore.cpp \ |