[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