[SCM] qtbase packaging branch, ubuntu, updated. ubuntu/5.6.1+dfsg-3ubuntu2-10-ge76670e
Timo Jyrinki
timo at moszumanska.debian.org
Thu Aug 25 06:51:22 UTC 2016
Gitweb-URL: http://git.debian.org/?p=pkg-kde/qt/qtbase.git;a=commitdiff;h=d8ef303
The following commit has been merged in the ubuntu branch:
commit d8ef303b321d6192dabb326f00e492ed95a900ca
Author: Timo Jyrinki <timo.jyrinki at canonical.com>
Date: Wed Jul 20 08:21:22 2016 +0000
debian/patches/color-fonts.patch, debian/patches/fix-scalable-bitmap-factor-caching.patch:
* debian/patches/color-fonts.patch,
debian/patches/fix-scalable-bitmap-factor-caching.patch:
- Add patches required for color font rendering (LP: #1594851)
---
debian/changelog | 3 +
debian/patches/color-fonts.patch | 707 +++++++++++++++++++++
.../fix-scalable-bitmap-factor-caching.patch | 175 +++++
debian/patches/series | 2 +
4 files changed, 887 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index 89d3529..b22355c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -17,6 +17,9 @@ qtbase-opensource-src (5.6.1+dfsg-3ubuntu1) UNRELEASED; urgency=medium
remaining parts of qnam-ubuntu-fix6.patch, half of which were upstreamed
in Qt 5.6.1
* Skip a test related to LP: #1603991
+ * debian/patches/color-fonts.patch,
+ debian/patches/fix-scalable-bitmap-factor-caching.patch:
+ - Add patches required for color font rendering (LP: #1594851)
-- Timo Jyrinki <timo-jyrinki at ubuntu.com> Mon, 18 Jan 2016 10:06:17 +0000
diff --git a/debian/patches/color-fonts.patch b/debian/patches/color-fonts.patch
new file mode 100644
index 0000000..c3bc5f3
--- /dev/null
+++ b/debian/patches/color-fonts.patch
@@ -0,0 +1,707 @@
+From 347832d7593e2369f8597bbd06213b80b3087433 Mon Sep 17 00:00:00 2001
+From: Jian Liang <jianliang79 at gmail.com>
+Date: Fri, 1 Apr 2016 22:03:15 +0800
+Subject: [PATCH] Support color font rendering for freetype engine
+
+This patch mainly do two things:
+1) Support color bitmap font for freetype fontengine. This partially
+ based on Corentin Jabot's patch
+
+2) Support ARGB opengl glyph cache when workaround_brokenFBOReadBack is
+true (It is always true under Android). Some code refactor has been
+done in QOpenGLTextureGlyphCache.
+
+This patch also bump the minimal required freetype version to 2.2
+
+[ChangeLog][General][Freetype] Support color font rendering
+
+Task-number: QTBUG-35156
+Change-Id: I35aae5f98ba9a27b70a48db3f2647fc070c39c33
+Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt at qt.io>
+---
+ config.tests/unix/freetype/freetype.cpp | 2 +-
+ src/3rdparty/freetype/freetype.pro | 3 +
+ src/gui/opengl/qopengltextureglyphcache.cpp | 171 ++++++++++----------
+ src/gui/text/qfontengine_ft.cpp | 234 ++++++++++++++++++++++------
+ src/gui/text/qfontengine_ft_p.h | 7 +
+ 5 files changed, 289 insertions(+), 128 deletions(-)
+
+diff --git a/config.tests/unix/freetype/freetype.cpp b/config.tests/unix/freetype/freetype.cpp
+index 29bbfd8..c051600 100644
+--- a/config.tests/unix/freetype/freetype.cpp
++++ b/config.tests/unix/freetype/freetype.cpp
+@@ -40,7 +40,7 @@
+ #include <ft2build.h>
+ #include FT_FREETYPE_H
+
+-#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) < 20110)
++#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) < 20200)
+ # error "This version of freetype is too old."
+ #endif
+
+diff --git a/src/3rdparty/freetype/freetype.pro b/src/3rdparty/freetype/freetype.pro
+index 04aa3b8..d73d8ec 100644
+--- a/src/3rdparty/freetype/freetype.pro
++++ b/src/3rdparty/freetype/freetype.pro
+@@ -71,6 +71,9 @@ contains(QT_CONFIG, system-zlib) {
+ contains(QT_CONFIG, system-png) {
+ DEFINES += FT_CONFIG_OPTION_USE_PNG
+ include($$PWD/../png_dependency.pri)
++} else:!contains(QT_CONFIG, no-png):!win32 {
++ DEFINES += FT_CONFIG_OPTION_USE_PNG
++ include($$PWD/../libpng.pri)
+ }
+
+ DEFINES += TT_CONFIG_OPTION_SUBPIXEL_HINTING
+diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp
+index 8f69095..9a7b1eb 100644
+--- a/src/gui/opengl/qopengltextureglyphcache.cpp
++++ b/src/gui/opengl/qopengltextureglyphcache.cpp
+@@ -181,6 +181,94 @@ void QOpenGLTextureGlyphCache::setupVertexAttribs()
+ m_buffer.release();
+ }
+
++static void load_glyph_image_to_texture(QOpenGLContext *ctx,
++ QImage &img,
++ GLuint texture,
++ int tx, int ty)
++{
++ QOpenGLFunctions *funcs = ctx->functions();
++
++ const int imgWidth = img.width();
++ const int imgHeight = img.height();
++
++ if (img.format() == QImage::Format_Mono) {
++ img = img.convertToFormat(QImage::Format_Grayscale8);
++ } else if (img.depth() == 32) {
++ if (img.format() == QImage::Format_RGB32
++ // We need to make the alpha component equal to the average of the RGB values.
++ // This is needed when drawing sub-pixel antialiased text on translucent targets.
++#if Q_BYTE_ORDER == Q_BIG_ENDIAN
++ || img.format() == QImage::Format_ARGB32_Premultiplied
++#else
++ || (img.format() == QImage::Format_ARGB32_Premultiplied
++ && ctx->isOpenGLES())
++#endif
++ ) {
++ for (int y = 0; y < imgHeight; ++y) {
++ QRgb *src = (QRgb *) img.scanLine(y);
++ for (int x = 0; x < imgWidth; ++x) {
++ int r = qRed(src[x]);
++ int g = qGreen(src[x]);
++ int b = qBlue(src[x]);
++ int avg;
++ if (img.format() == QImage::Format_RGB32)
++ avg = (r + g + b + 1) / 3; // "+1" for rounding.
++ else // Format_ARGB_Premultiplied
++ avg = qAlpha(src[x]);
++
++ src[x] = qRgba(r, g, b, avg);
++ // swizzle the bits to accommodate for the GL_RGBA upload.
++#if Q_BYTE_ORDER != Q_BIG_ENDIAN
++ if (ctx->isOpenGLES())
++#endif
++ src[x] = ARGB2RGBA(src[x]);
++ }
++ }
++ }
++ }
++
++ funcs->glBindTexture(GL_TEXTURE_2D, texture);
++ if (img.depth() == 32) {
++#ifdef QT_OPENGL_ES_2
++ GLenum fmt = GL_RGBA;
++#else
++ GLenum fmt = ctx->isOpenGLES() ? GL_RGBA : GL_BGRA;
++#endif // QT_OPENGL_ES_2
++
++#if Q_BYTE_ORDER == Q_BIG_ENDIAN
++ fmt = GL_RGBA;
++#endif
++ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, imgWidth, imgHeight, fmt, GL_UNSIGNED_BYTE, img.constBits());
++ } else {
++ // The scanlines in image are 32-bit aligned, even for mono or 8-bit formats. This
++ // is good because it matches the default of 4 bytes for GL_UNPACK_ALIGNMENT.
++#if !defined(QT_OPENGL_ES_2)
++ const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
++#else
++ const GLenum format = GL_ALPHA;
++#endif
++ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, imgWidth, imgHeight, format, GL_UNSIGNED_BYTE, img.constBits());
++ }
++}
++
++static void load_glyph_image_region_to_texture(QOpenGLContext *ctx,
++ const QImage &srcImg,
++ int x, int y,
++ int w, int h,
++ GLuint texture,
++ int tx, int ty)
++{
++ Q_ASSERT(x + w <= srcImg.width() && y + h <= srcImg.height());
++
++ QImage img;
++ if (x != 0 || y != 0 || w != srcImg.width() || h != srcImg.height())
++ img = srcImg.copy(x, y, w, h);
++ else
++ img = srcImg;
++
++ load_glyph_image_to_texture(ctx, img, texture, tx, ty);
++}
++
+ void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height)
+ {
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+@@ -207,9 +295,8 @@ void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height)
+
+ if (ctx->d_func()->workaround_brokenFBOReadBack) {
+ QImageTextureGlyphCache::resizeTextureData(width, height);
+- Q_ASSERT(image().depth() == 8);
+- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits());
+- funcs->glDeleteTextures(1, &oldTexture);
++ load_glyph_image_region_to_texture(ctx, image(), 0, 0, qMin(oldWidth, width), qMin(oldHeight, height),
++ m_textureResource->m_texture, 0, 0);
+ return;
+ }
+
+@@ -336,88 +423,14 @@ void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed
+ return;
+ }
+
+- QOpenGLFunctions *funcs = ctx->functions();
+ if (ctx->d_func()->workaround_brokenFBOReadBack) {
+ QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition);
+-
+- funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
+- const QImage &texture = image();
+- const uchar *bits = texture.constBits();
+- bits += c.y * texture.bytesPerLine() + c.x;
+- for (int i=0; i<c.h; ++i) {
+- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits);
+- bits += texture.bytesPerLine();
+- }
++ load_glyph_image_region_to_texture(ctx, image(), c.x, c.y, c.w, c.h, m_textureResource->m_texture, c.x, c.y);
+ return;
+ }
+
+ QImage mask = textureMapForGlyph(glyph, subPixelPosition);
+- const int maskWidth = mask.width();
+- const int maskHeight = mask.height();
+-
+- if (mask.format() == QImage::Format_Mono) {
+- mask = mask.convertToFormat(QImage::Format_Indexed8);
+- for (int y = 0; y < maskHeight; ++y) {
+- uchar *src = (uchar *) mask.scanLine(y);
+- for (int x = 0; x < maskWidth; ++x)
+- src[x] = -src[x]; // convert 0 and 1 into 0 and 255
+- }
+- } else if (mask.depth() == 32) {
+- if (mask.format() == QImage::Format_RGB32
+- // We need to make the alpha component equal to the average of the RGB values.
+- // This is needed when drawing sub-pixel antialiased text on translucent targets.
+-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+- || mask.format() == QImage::Format_ARGB32_Premultiplied
+-#else
+- || (mask.format() == QImage::Format_ARGB32_Premultiplied
+- && ctx->isOpenGLES())
+-#endif
+- ) {
+- for (int y = 0; y < maskHeight; ++y) {
+- QRgb *src = (QRgb *) mask.scanLine(y);
+- for (int x = 0; x < maskWidth; ++x) {
+- int r = qRed(src[x]);
+- int g = qGreen(src[x]);
+- int b = qBlue(src[x]);
+- int avg;
+- if (mask.format() == QImage::Format_RGB32)
+- avg = (r + g + b + 1) / 3; // "+1" for rounding.
+- else // Format_ARGB_Premultiplied
+- avg = qAlpha(src[x]);
+-
+- src[x] = qRgba(r, g, b, avg);
+- // swizzle the bits to accommodate for the GL_RGBA upload.
+-#if Q_BYTE_ORDER != Q_BIG_ENDIAN
+- if (ctx->isOpenGLES())
+-#endif
+- src[x] = ARGB2RGBA(src[x]);
+- }
+- }
+- }
+- }
+-
+- funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
+- if (mask.depth() == 32) {
+-#ifdef QT_OPENGL_ES_2
+- GLenum fmt = GL_RGBA;
+-#else
+- GLenum fmt = ctx->isOpenGLES() ? GL_RGBA : GL_BGRA;
+-#endif // QT_OPENGL_ES_2
+-
+-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+- fmt = GL_RGBA;
+-#endif
+- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, fmt, GL_UNSIGNED_BYTE, mask.bits());
+- } else {
+- // The scanlines in mask are 32-bit aligned, even for mono or 8-bit formats. This
+- // is good because it matches the default of 4 bytes for GL_UNPACK_ALIGNMENT.
+-#if !defined(QT_OPENGL_ES_2)
+- const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+-#else
+- const GLenum format = GL_ALPHA;
+-#endif
+- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, format, GL_UNSIGNED_BYTE, mask.bits());
+- }
++ load_glyph_image_to_texture(ctx, mask, m_textureResource->m_texture, c.x, c.y);
+ }
+
+ int QOpenGLTextureGlyphCache::glyphPadding() const
+diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
+index ec995d5..e89522f 100644
+--- a/src/gui/text/qfontengine_ft.cpp
++++ b/src/gui/text/qfontengine_ft.cpp
+@@ -52,6 +52,7 @@
+ #include <qscopedvaluerollback.h>
+ #include "qthreadstorage.h"
+ #include <qmath.h>
++#include <qendian.h>
+
+ #include <ft2build.h>
+ #include FT_FREETYPE_H
+@@ -192,6 +193,15 @@ int QFreetypeFace::getPointInOutline(glyph_t glyph, int flags, quint32 point, QF
+ return Err_Ok;
+ }
+
++bool QFreetypeFace::isScalableBitmap() const
++{
++#ifdef FT_HAS_COLOR
++ return !FT_IS_SCALABLE(face) && FT_HAS_COLOR(face);
++#else
++ return false;
++#endif
++}
++
+ extern QByteArray qt_fontdata_from_index(int);
+
+ /*
+@@ -249,6 +259,7 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
+ newFreetype->ref.store(1);
+ newFreetype->xsize = 0;
+ newFreetype->ysize = 0;
++ newFreetype->scalableBitmapScaleFactor = 1;
+ newFreetype->matrix.xx = 0x10000;
+ newFreetype->matrix.yy = 0x10000;
+ newFreetype->matrix.xy = 0;
+@@ -330,36 +341,46 @@ void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize,
+ *xsize = *ysize * fontDef.stretch / 100;
+ *outline_drawing = false;
+
+- /*
+- * Bitmap only faces must match exactly, so find the closest
+- * one (height dominant search)
+- */
+ if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) {
+ int best = 0;
+- for (int i = 1; i < face->num_fixed_sizes; i++) {
+- if (qAbs(*ysize - face->available_sizes[i].y_ppem) <
+- qAbs(*ysize - face->available_sizes[best].y_ppem) ||
+- (qAbs(*ysize - face->available_sizes[i].y_ppem) ==
+- qAbs(*ysize - face->available_sizes[best].y_ppem) &&
+- qAbs(*xsize - face->available_sizes[i].x_ppem) <
+- qAbs(*xsize - face->available_sizes[best].x_ppem))) {
+- best = i;
++ if (!isScalableBitmap()) {
++ /*
++ * Bitmap only faces must match exactly, so find the closest
++ * one (height dominant search)
++ */
++ for (int i = 1; i < face->num_fixed_sizes; i++) {
++ if (qAbs(*ysize - face->available_sizes[i].y_ppem) <
++ qAbs(*ysize - face->available_sizes[best].y_ppem) ||
++ (qAbs(*ysize - face->available_sizes[i].y_ppem) ==
++ qAbs(*ysize - face->available_sizes[best].y_ppem) &&
++ qAbs(*xsize - face->available_sizes[i].x_ppem) <
++ qAbs(*xsize - face->available_sizes[best].x_ppem))) {
++ best = i;
++ }
++ }
++ } else {
++ // Select the shortest bitmap strike whose height is larger than the desired height
++ for (int i = 1; i < face->num_fixed_sizes; i++) {
++ if (face->available_sizes[i].y_ppem < *ysize) {
++ if (face->available_sizes[i].y_ppem > face->available_sizes[best].y_ppem)
++ best = i;
++ } else if (face->available_sizes[best].y_ppem < *ysize) {
++ best = i;
++ } else if (face->available_sizes[i].y_ppem < face->available_sizes[best].y_ppem) {
++ best = i;
++ }
+ }
+ }
+- if (FT_Set_Char_Size(face, face->available_sizes[best].x_ppem, face->available_sizes[best].y_ppem, 0, 0) == 0) {
++
++ // According to freetype documentation we must use FT_Select_Size
++ // to make sure we can select the desired bitmap strike index
++ if (FT_Select_Size(face, best) == 0) {
++ if (isScalableBitmap())
++ scalableBitmapScaleFactor = QFixed::fromReal((qreal)fontDef.pixelSize / face->available_sizes[best].height);
+ *xsize = face->available_sizes[best].x_ppem;
+ *ysize = face->available_sizes[best].y_ppem;
+ } else {
+- int err = 1;
+- if (!(face->face_flags & FT_FACE_FLAG_SCALABLE) && ysize == 0 && face->num_fixed_sizes >= 1) {
+- // work around FT 2.1.10 problem with BDF without PIXEL_SIZE property
+- err = FT_Set_Pixel_Sizes(face, face->available_sizes[0].width, face->available_sizes[0].height);
+- if (err && face->num_fixed_sizes == 1)
+- err = 0; //even more of a workaround...
+- }
+-
+- if (err)
+- *xsize = *ysize = 0;
++ *xsize = *ysize = 0;
+ }
+ } else {
+ *outline_drawing = (*xsize > (QT_MAX_CACHED_GLYPH_SIZE<<6) || *ysize > (QT_MAX_CACHED_GLYPH_SIZE<<6));
+@@ -736,6 +757,11 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
+ if (line_thickness < 2 && score >= 1050)
+ line_thickness = 2;
+ underline_position = ((line_thickness * 2) + 3) / 6;
++
++ if (isScalableBitmap()) {
++ glyphFormat = defaultFormat = GlyphFormat::Format_ARGB;
++ cacheEnabled = false;
++ }
+ }
+ if (line_thickness < 1)
+ line_thickness = 1;
+@@ -829,6 +855,10 @@ int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
+ load_target = FT_LOAD_TARGET_LCD_V;
+ vfactor = 3;
+ }
++ } else if (format == Format_ARGB) {
++#ifdef FT_LOAD_COLOR
++ load_flags |= FT_LOAD_COLOR;
++#endif
+ }
+
+ if (set && set->outline_drawing)
+@@ -890,7 +920,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
+ || matrix.xy != 0
+ || matrix.yx != 0;
+
+- if (transform || (format != Format_Mono && !embeddedbitmap))
++ if (transform || (format != Format_Mono && !isScalableBitmap()))
+ load_flags |= FT_LOAD_NO_BITMAP;
+
+ FT_Error err = FT_Load_Glyph(face, glyph, load_flags);
+@@ -1121,7 +1151,11 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
+ if (bitmap.buffer != glyph_buffer.data())
+ delete [] bitmap.buffer;
+ } else if (slot->format == FT_GLYPH_FORMAT_BITMAP) {
++#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100) >= 20500)
++ Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO || slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA);
++#else
+ Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO);
++#endif
+ uchar *src = slot->bitmap.buffer;
+ uchar *dst = glyph_buffer.data();
+ int h = slot->bitmap.rows;
+@@ -1132,7 +1166,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
+ dst += pitch;
+ src += slot->bitmap.pitch;
+ }
+- } else {
++ } else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
+ if (hsubpixel) {
+ while (h--) {
+ uint *dd = (uint *)dst;
+@@ -1166,6 +1200,29 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
+ }
+ }
+ }
++#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100) >= 20500)
++ else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
++ {
++ while (h--) {
++#if Q_BYTE_ORDER == Q_BIG_ENDIAN
++ const quint32 *srcPixel = (const quint32 *)src;
++ quint32 *dstPixel = (quint32 *)dst;
++ for (int x = 0; x < static_cast<int>(slot->bitmap.width); x++, srcPixel++, dstPixel++) {
++ const quint32 pixel = *srcPixel;
++ *dstPixel = qbswap(pixel);
++ }
++#else
++ memcpy(dst, src, slot->bitmap.width * 4);
++#endif
++ dst += slot->bitmap.pitch;
++ src += slot->bitmap.pitch;
++ }
++ info.width = info.linearAdvance = info.xOff = slot->bitmap.width;
++ info.height = slot->bitmap.rows;
++ info.x = slot->bitmap_left;
++ info.y = slot->bitmap_top;
++ }
++#endif
+ } else {
+ qWarning("QFontEngine: Glyph neither outline nor bitmap format=%d", slot->format);
+ return 0;
+@@ -1236,46 +1293,68 @@ int QFontEngineFT::synthesized() const
+
+ QFixed QFontEngineFT::ascent() const
+ {
+- return QFixed::fromFixed(metrics.ascender);
++ QFixed v = QFixed::fromFixed(metrics.ascender);
++ if (freetype->scalableBitmapScaleFactor != 1)
++ v *= freetype->scalableBitmapScaleFactor;
++ return v;
+ }
+
+ QFixed QFontEngineFT::descent() const
+ {
+- return QFixed::fromFixed(-metrics.descender);
++ QFixed v = QFixed::fromFixed(-metrics.descender);
++ if (freetype->scalableBitmapScaleFactor != 1)
++ v *= freetype->scalableBitmapScaleFactor;
++ return v;
+ }
+
+ QFixed QFontEngineFT::leading() const
+ {
+- return QFixed::fromFixed(metrics.height - metrics.ascender + metrics.descender);
++ QFixed v = QFixed::fromFixed(metrics.height - metrics.ascender + metrics.descender);
++ if (freetype->scalableBitmapScaleFactor != 1)
++ v *= freetype->scalableBitmapScaleFactor;
++ return v;
+ }
+
+ QFixed QFontEngineFT::xHeight() const
+ {
+- TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
+- if (os2 && os2->sxHeight) {
+- lockFace();
+- QFixed answer = QFixed(os2->sxHeight * freetype->face->size->metrics.y_ppem) / emSquareSize();
+- unlockFace();
+- return answer;
++ if (!isScalableBitmap()) {
++ TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
++ if (os2 && os2->sxHeight) {
++ lockFace();
++ QFixed answer = QFixed(os2->sxHeight * freetype->face->size->metrics.y_ppem) / emSquareSize();
++ unlockFace();
++ return answer;
++ }
++ } else {
++ return QFixed(freetype->face->size->metrics.y_ppem) * freetype->scalableBitmapScaleFactor;
+ }
+ return QFontEngine::xHeight();
+ }
+
+ QFixed QFontEngineFT::averageCharWidth() const
+ {
+- TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
+- if (os2 && os2->xAvgCharWidth) {
+- lockFace();
+- QFixed answer = QFixed(os2->xAvgCharWidth * freetype->face->size->metrics.x_ppem) / emSquareSize();
+- unlockFace();
+- return answer;
+- }
+- return QFontEngine::averageCharWidth();
++ if (!isScalableBitmap()) {
++ TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
++ if (os2 && os2->xAvgCharWidth) {
++ lockFace();
++ QFixed answer = QFixed(os2->xAvgCharWidth * freetype->face->size->metrics.x_ppem) / emSquareSize();
++ unlockFace();
++ return answer;
++ }
++ } else {
++ const qreal aspectRatio = (qreal)xsize / ysize;
++ return QFixed::fromReal(fontDef.pixelSize * aspectRatio);
++ }
++
++ return QFontEngine::averageCharWidth();
+ }
+
+ qreal QFontEngineFT::maxCharWidth() const
+ {
+- return metrics.max_advance >> 6;
++ QFixed max_advance = QFixed::fromFixed(metrics.max_advance);
++ if (freetype->scalableBitmapScaleFactor != 1)
++ max_advance *= freetype->scalableBitmapScaleFactor;
++ return max_advance.toReal();
+ }
+
+ QFixed QFontEngineFT::lineThickness() const
+@@ -1558,6 +1637,23 @@ bool QFontEngineFT::shouldUseDesignMetrics(QFontEngine::ShaperFlags flags) const
+ return default_hint_style == HintNone || default_hint_style == HintLight || (flags & DesignMetrics);
+ }
+
++QFixed QFontEngineFT::scaledBitmapMetrics(QFixed m) const
++{
++ return m * freetype->scalableBitmapScaleFactor;
++}
++
++glyph_metrics_t QFontEngineFT::scaledBitmapMetrics(const glyph_metrics_t &m) const
++{
++ glyph_metrics_t metrics;
++ metrics.x = scaledBitmapMetrics(m.x);
++ metrics.y = scaledBitmapMetrics(m.y);
++ metrics.width = scaledBitmapMetrics(m.width);
++ metrics.height = scaledBitmapMetrics(m.height);
++ metrics.xoff = scaledBitmapMetrics(m.xoff);
++ metrics.yoff = scaledBitmapMetrics(m.yoff);
++ return metrics;
++}
++
+ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const
+ {
+ FT_Face face = 0;
+@@ -1580,6 +1676,9 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag
+ if (!cacheEnabled && g != &emptyGlyph)
+ delete g;
+ }
++
++ if (freetype->scalableBitmapScaleFactor != 1)
++ glyphs->advances[i] *= freetype->scalableBitmapScaleFactor;
+ }
+ if (face)
+ unlockFace();
+@@ -1596,8 +1695,13 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
+
+ glyph_metrics_t overall;
+ // initialize with line height, we get the same behaviour on all platforms
+- overall.y = -ascent();
+- overall.height = ascent() + descent();
++ if (!isScalableBitmap()) {
++ overall.y = -ascent();
++ overall.height = ascent() + descent();
++ } else {
++ overall.y = QFixed::fromFixed(-metrics.ascender);
++ overall.height = QFixed::fromFixed(metrics.ascender - metrics.descender);
++ }
+
+ QFixed ymax = 0;
+ QFixed xmax = 0;
+@@ -1639,6 +1743,8 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
+ if (face)
+ unlockFace();
+
++ if (isScalableBitmap())
++ overall = scaledBitmapMetrics(overall);
+ return overall;
+ }
+
+@@ -1675,6 +1781,9 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
+ }
+ if (face)
+ unlockFace();
++
++ if (isScalableBitmap())
++ overall = scaledBitmapMetrics(overall);
+ return overall;
+ }
+
+@@ -1710,6 +1819,9 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe
+ overall.xoff = TRUNC(ROUND(face->glyph->advance.x));
+ unlockFace();
+ }
++
++ if (isScalableBitmap())
++ overall = scaledBitmapMetrics(overall);
+ return overall;
+ }
+
+@@ -1857,6 +1969,31 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, co
+ return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
+ }
+
++QImage QFontEngineFT::bitmapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
++{
++ Glyph *glyph = loadGlyphFor(g, subPixelPosition, defaultFormat, t);
++ if (glyph == Q_NULLPTR)
++ return QImage();
++
++ QImage img;
++ if (defaultFormat == GlyphFormat::Format_ARGB)
++ img = QImage(glyph->data, glyph->width, glyph->height, QImage::Format_ARGB32_Premultiplied).copy();
++ else if (defaultFormat == GlyphFormat::Format_Mono)
++ img = QImage(glyph->data, glyph->width, glyph->height, QImage::Format_Mono).copy();
++
++ if (!img.isNull() && (!t.isIdentity() || freetype->scalableBitmapScaleFactor != 1)) {
++ QTransform trans(t);
++ const qreal scaleFactor = freetype->scalableBitmapScaleFactor.toReal();
++ trans.scale(scaleFactor, scaleFactor);
++ img = img.transformed(trans, Qt::SmoothTransformation);
++ }
++
++ if (!cacheEnabled && glyph != &emptyGlyph)
++ delete glyph;
++
++ return img;
++}
++
+ void QFontEngineFT::removeGlyphFromCache(glyph_t glyph)
+ {
+ defaultGlyphSet.removeGlyphFromCache(glyph, 0);
+@@ -1878,9 +2015,10 @@ FT_Face QFontEngineFT::lockFace(Scaling scale) const
+ freetype->lock();
+ FT_Face face = freetype->face;
+ if (scale == Unscaled) {
+- FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0);
+- freetype->xsize = face->units_per_EM << 6;
+- freetype->ysize = face->units_per_EM << 6;
++ if (FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0) == 0) {
++ freetype->xsize = face->units_per_EM << 6;
++ freetype->ysize = face->units_per_EM << 6;
++ }
+ } else if (freetype->xsize != xsize || freetype->ysize != ysize) {
+ FT_Set_Char_Size(face, xsize, ysize, 0, 0);
+ freetype->xsize = xsize;
+diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
+index ee2df6f..3f4bf84 100644
+--- a/src/gui/text/qfontengine_ft_p.h
++++ b/src/gui/text/qfontengine_ft_p.h
+@@ -96,6 +96,7 @@ public:
+ FT_Face face;
+ int xsize; // 26.6
+ int ysize; // 26.6
++ QFixed scalableBitmapScaleFactor;
+ FT_Matrix matrix;
+ FT_CharMap unicode_map;
+ FT_CharMap symbol_map;
+@@ -107,6 +108,8 @@ public:
+
+ int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints);
+
++ bool isScalableBitmap() const;
++
+ static void addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale);
+ static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path);
+
+@@ -239,6 +242,7 @@ private:
+ QImage alphaMapForGlyph(glyph_t, QFixed) Q_DECL_OVERRIDE;
+ QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
+ QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
++ QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
+ glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
+ QFixed subPixelPosition,
+ const QTransform &matrix,
+@@ -266,6 +270,7 @@ private:
+ inline bool drawAntialiased() const { return antialias; }
+ inline bool invalid() const { return xsize == 0 && ysize == 0; }
+ inline bool isBitmapFont() const { return defaultFormat == Format_Mono; }
++ inline bool isScalableBitmap() const { return freetype->isScalableBitmap(); }
+
+ inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
+ { return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly); }
+@@ -316,6 +321,8 @@ private:
+
+ int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;
+ bool shouldUseDesignMetrics(ShaperFlags flags) const;
++ QFixed scaledBitmapMetrics(QFixed m) const;
++ glyph_metrics_t scaledBitmapMetrics(const glyph_metrics_t &m) const;
+
+ GlyphFormat defaultFormat;
+ FT_Matrix matrix;
+--
+2.7.4
+
diff --git a/debian/patches/fix-scalable-bitmap-factor-caching.patch b/debian/patches/fix-scalable-bitmap-factor-caching.patch
new file mode 100644
index 0000000..b41a0a4
--- /dev/null
+++ b/debian/patches/fix-scalable-bitmap-factor-caching.patch
@@ -0,0 +1,175 @@
+From 267c01390544ba12f81783c8b0e37ed38db231d6 Mon Sep 17 00:00:00 2001
+From: Michael Sheldon <elleo at gnu.org>
+Date: Thu, 26 May 2016 16:20:33 +0100
+Subject: [PATCH] Preserve the scale of fonts when caching the font engine
+
+Associates the scalableBitmapFactor with the freetype QFontEngine
+so that it is preserved when caching the engine
+
+Task-number: QTBUG-53652
+Change-Id: I010f9d235ccf30679b112e0c05e01bc247a3693f
+Reviewed-by: jian liang <jianliang79 at gmail.com>
+Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt at qt.io>
+---
+ src/gui/text/qfontengine_ft.cpp | 36 ++++++++++++++++++------------------
+ src/gui/text/qfontengine_ft_p.h | 4 ++--
+ 2 files changed, 20 insertions(+), 20 deletions(-)
+
+diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
+index e89522f..26ed81a 100644
+--- a/src/gui/text/qfontengine_ft.cpp
++++ b/src/gui/text/qfontengine_ft.cpp
+@@ -259,7 +259,6 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
+ newFreetype->ref.store(1);
+ newFreetype->xsize = 0;
+ newFreetype->ysize = 0;
+- newFreetype->scalableBitmapScaleFactor = 1;
+ newFreetype->matrix.xx = 0x10000;
+ newFreetype->matrix.yy = 0x10000;
+ newFreetype->matrix.xy = 0;
+@@ -335,10 +334,11 @@ void QFreetypeFace::release(const QFontEngine::FaceId &face_id)
+ }
+
+
+-void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing)
++void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing, QFixed *scalableBitmapScaleFactor)
+ {
+ *ysize = qRound(fontDef.pixelSize * 64);
+ *xsize = *ysize * fontDef.stretch / 100;
++ *scalableBitmapScaleFactor = 1;
+ *outline_drawing = false;
+
+ if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) {
+@@ -376,7 +376,7 @@ void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize,
+ // to make sure we can select the desired bitmap strike index
+ if (FT_Select_Size(face, best) == 0) {
+ if (isScalableBitmap())
+- scalableBitmapScaleFactor = QFixed::fromReal((qreal)fontDef.pixelSize / face->available_sizes[best].height);
++ *scalableBitmapScaleFactor = QFixed::fromReal((qreal)fontDef.pixelSize / face->available_sizes[best].height);
+ *xsize = face->available_sizes[best].x_ppem;
+ *ysize = face->available_sizes[best].y_ppem;
+ } else {
+@@ -729,7 +729,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
+ symbol = bool(fontDef.family.contains(QLatin1String("symbol"), Qt::CaseInsensitive));
+ }
+
+- freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing);
++ freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing, &scalableBitmapScaleFactor);
+
+ FT_Face face = lockFace();
+
+@@ -1294,24 +1294,24 @@ int QFontEngineFT::synthesized() const
+ QFixed QFontEngineFT::ascent() const
+ {
+ QFixed v = QFixed::fromFixed(metrics.ascender);
+- if (freetype->scalableBitmapScaleFactor != 1)
+- v *= freetype->scalableBitmapScaleFactor;
++ if (scalableBitmapScaleFactor != 1)
++ v *= scalableBitmapScaleFactor;
+ return v;
+ }
+
+ QFixed QFontEngineFT::descent() const
+ {
+ QFixed v = QFixed::fromFixed(-metrics.descender);
+- if (freetype->scalableBitmapScaleFactor != 1)
+- v *= freetype->scalableBitmapScaleFactor;
++ if (scalableBitmapScaleFactor != 1)
++ v *= scalableBitmapScaleFactor;
+ return v;
+ }
+
+ QFixed QFontEngineFT::leading() const
+ {
+ QFixed v = QFixed::fromFixed(metrics.height - metrics.ascender + metrics.descender);
+- if (freetype->scalableBitmapScaleFactor != 1)
+- v *= freetype->scalableBitmapScaleFactor;
++ if (scalableBitmapScaleFactor != 1)
++ v *= scalableBitmapScaleFactor;
+ return v;
+ }
+
+@@ -1326,7 +1326,7 @@ QFixed QFontEngineFT::xHeight() const
+ return answer;
+ }
+ } else {
+- return QFixed(freetype->face->size->metrics.y_ppem) * freetype->scalableBitmapScaleFactor;
++ return QFixed(freetype->face->size->metrics.y_ppem) * scalableBitmapScaleFactor;
+ }
+ return QFontEngine::xHeight();
+ }
+@@ -1352,8 +1352,8 @@ QFixed QFontEngineFT::averageCharWidth() const
+ qreal QFontEngineFT::maxCharWidth() const
+ {
+ QFixed max_advance = QFixed::fromFixed(metrics.max_advance);
+- if (freetype->scalableBitmapScaleFactor != 1)
+- max_advance *= freetype->scalableBitmapScaleFactor;
++ if (scalableBitmapScaleFactor != 1)
++ max_advance *= scalableBitmapScaleFactor;
+ return max_advance.toReal();
+ }
+
+@@ -1639,7 +1639,7 @@ bool QFontEngineFT::shouldUseDesignMetrics(QFontEngine::ShaperFlags flags) const
+
+ QFixed QFontEngineFT::scaledBitmapMetrics(QFixed m) const
+ {
+- return m * freetype->scalableBitmapScaleFactor;
++ return m * scalableBitmapScaleFactor;
+ }
+
+ glyph_metrics_t QFontEngineFT::scaledBitmapMetrics(const glyph_metrics_t &m) const
+@@ -1677,8 +1677,8 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag
+ delete g;
+ }
+
+- if (freetype->scalableBitmapScaleFactor != 1)
+- glyphs->advances[i] *= freetype->scalableBitmapScaleFactor;
++ if (scalableBitmapScaleFactor != 1)
++ glyphs->advances[i] *= scalableBitmapScaleFactor;
+ }
+ if (face)
+ unlockFace();
+@@ -1981,9 +1981,9 @@ QImage QFontEngineFT::bitmapForGlyph(glyph_t g, QFixed subPixelPosition, const Q
+ else if (defaultFormat == GlyphFormat::Format_Mono)
+ img = QImage(glyph->data, glyph->width, glyph->height, QImage::Format_Mono).copy();
+
+- if (!img.isNull() && (!t.isIdentity() || freetype->scalableBitmapScaleFactor != 1)) {
++ if (!img.isNull() && (!t.isIdentity() || scalableBitmapScaleFactor != 1)) {
+ QTransform trans(t);
+- const qreal scaleFactor = freetype->scalableBitmapScaleFactor.toReal();
++ const qreal scaleFactor = scalableBitmapScaleFactor.toReal();
+ trans.scale(scaleFactor, scaleFactor);
+ img = img.transformed(trans, Qt::SmoothTransformation);
+ }
+diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
+index 3f4bf84..3cdf0cd 100644
+--- a/src/gui/text/qfontengine_ft_p.h
++++ b/src/gui/text/qfontengine_ft_p.h
+@@ -75,7 +75,7 @@ class QFontconfigDatabase;
+ class QFreetypeFace
+ {
+ public:
+- void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing);
++ void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing, QFixed *scalableBitmapScaleFactor);
+ QFontEngine::Properties properties() const;
+ bool getSfntTable(uint tag, uchar *buffer, uint *length) const;
+
+@@ -96,7 +96,6 @@ public:
+ FT_Face face;
+ int xsize; // 26.6
+ int ysize; // 26.6
+- QFixed scalableBitmapScaleFactor;
+ FT_Matrix matrix;
+ FT_CharMap unicode_map;
+ FT_CharMap symbol_map;
+@@ -340,6 +339,7 @@ private:
+
+ FT_Size_Metrics metrics;
+ mutable bool kerning_pairs_loaded;
++ QFixed scalableBitmapScaleFactor;
+ };
+
+ inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g)
+--
+2.7.4
+
diff --git a/debian/patches/series b/debian/patches/series
index 17532d8..074c293 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,5 +1,7 @@
# Backported from upstream
no_dbus_dependency.diff
+color-fonts.patch
+fix-scalable-bitmap-factor-caching.patch
# Debian specific.
gnukfreebsd.diff
--
qtbase packaging
More information about the pkg-kde-commits
mailing list