diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/image/qpixmap_blitter.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qopenglcontext.h | 8 | ||||
-rw-r--r-- | src/gui/kernel/qwindow.h | 2 | ||||
-rw-r--r-- | src/gui/opengl/qopenglframebufferobject.cpp | 3 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 157 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 18 | ||||
-rw-r--r-- | src/gui/text/qfontengine.cpp | 9 | ||||
-rw-r--r-- | src/gui/text/qfontengine_ft.cpp | 36 | ||||
-rw-r--r-- | src/gui/text/qfontengine_p.h | 2 | ||||
-rw-r--r-- | src/gui/text/qtextcursor.cpp | 2 | ||||
-rw-r--r-- | src/gui/text/qtextengine.cpp | 2 |
11 files changed, 214 insertions, 29 deletions
diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index 839a7a709f..2915cdda2d 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -59,6 +59,7 @@ static int global_ser_no = 0; QBlittablePlatformPixmap::QBlittablePlatformPixmap() : QPlatformPixmap(QPlatformPixmap::PixmapType,BlitterClass) , m_alpha(false) + , m_devicePixelRatio(1.0) #ifdef QT_BLITTER_RASTEROVERLAY ,m_rasterOverlay(0), m_unmergedCopy(0) #endif //QT_BLITTER_RASTEROVERLAY @@ -121,7 +122,7 @@ int QBlittablePlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) con case QPaintDevice::PdmPhysicalDpiY: return qt_defaultDpiY(); case QPaintDevice::PdmDevicePixelRatio: - return 1; + return devicePixelRatio(); default: qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric); break; @@ -178,6 +179,7 @@ void QBlittablePlatformPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags) { m_alpha = image.hasAlphaChannel(); + m_devicePixelRatio = image.devicePixelRatio(); resize(image.width(),image.height()); markRasterOverlay(QRect(0,0,w,h)); QImage *thisImg = buffer(); diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h index 402989b4d0..99f2fece51 100644 --- a/src/gui/kernel/qopenglcontext.h +++ b/src/gui/kernel/qopenglcontext.h @@ -199,19 +199,13 @@ public: enum OpenGLModuleType { LibGL, - LibGLES, - - // ### - DesktopGL = LibGL, - GLES2 = LibGLES + LibGLES }; static OpenGLModuleType openGLModuleType(); bool isOpenGLES() const; - bool isES() const { return isOpenGLES(); } // ### - Q_SIGNALS: void aboutToBeDestroyed(); diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h index 3278b7233c..0d13cfa648 100644 --- a/src/gui/kernel/qwindow.h +++ b/src/gui/kernel/qwindow.h @@ -297,7 +297,7 @@ Q_SIGNALS: void screenChanged(QScreen *screen); void modalityChanged(Qt::WindowModality modality); void windowStateChanged(Qt::WindowState windowState); - void windowTitleChanged(const QString &title); + Q_REVISION(2) void windowTitleChanged(const QString &title); void xChanged(int arg); void yChanged(int arg); diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index cc829df950..7fb6815120 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -1112,6 +1112,9 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, \fn QImage QOpenGLFramebufferObject::toImage() const Returns the contents of this framebuffer object as a QImage. + + Will try to return a premultiplied ARBG32 or RGB32 image. Since 5.2 it will fall back to + a premultiplied RGBA8888 or RGBx8888 image when reading to ARGB32 is not supported. */ QImage QOpenGLFramebufferObject::toImage() const { diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 7a5c5dc660..b5ccafdf9a 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -1709,6 +1709,163 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c } } else { //we are zooming less than 8x, use 4bit precision + + if (blendType != BlendTransformedBilinearTiled) { +#define BILINEAR_ROTATE_BOUNDS_PROLOG \ + while (b < end) { \ + int x1 = (fx >> 16); \ + int x2; \ + int y1 = (fy >> 16); \ + int y2; \ + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); \ + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); \ + if (x1 != x2 && y1 != y2) \ + break; \ + const uint *s1 = (const uint *)data->texture.scanLine(y1); \ + const uint *s2 = (const uint *)data->texture.scanLine(y2); \ + uint tl = s1[x1]; \ + uint tr = s1[x2]; \ + uint bl = s2[x1]; \ + uint br = s2[x2]; \ + int distx = (fx & 0x0000ffff) >> 12; \ + int disty = (fy & 0x0000ffff) >> 12; \ + *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); \ + fx += fdx; \ + fy += fdy; \ + ++b; \ + } \ + uint *boundedEnd = end - 3; \ + boundedEnd -= 3; + +#if defined(__SSE2__) + BILINEAR_ROTATE_BOUNDS_PROLOG + + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + const __m128i v_256 = _mm_set1_epi16(256); + __m128i v_fdx = _mm_set1_epi32(fdx*4); + __m128i v_fdy = _mm_set1_epi32(fdy*4); + + const uchar *textureData = data->texture.imageData; + const int bytesPerLine = data->texture.bytesPerLine; + + union Vect_buffer { __m128i vect; qint32 i[4]; }; + Vect_buffer v_fx, v_fy; + + for (int i = 0; i < 4; i++) { + v_fx.i[i] = fx; + v_fy.i[i] = fy; + fx += fdx; + fy += fdy; + } + + while (b < boundedEnd) { + if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2) + break; + if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1) + break; + if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2) + break; + if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1) + break; + + Vect_buffer tl, tr, bl, br; + Vect_buffer v_fx_shifted, v_fy_shifted; + v_fx_shifted.vect = _mm_srli_epi32(v_fx.vect, 16); + v_fy_shifted.vect = _mm_srli_epi32(v_fy.vect, 16); + + for (int i = 0; i < 4; i++) { + const int x1 = v_fx_shifted.i[i]; + const int y1 = v_fy_shifted.i[i]; + const uchar *sl = textureData + bytesPerLine * y1; + const uint *s1 = (const uint *)sl; + const uint *s2 = (const uint *)(sl + bytesPerLine); + tl.i[i] = s1[x1]; + tr.i[i] = s1[x1+1]; + bl.i[i] = s2[x1]; + br.i[i] = s2[x1+1]; + } + __m128i v_distx = _mm_srli_epi16(v_fx.vect, 12); + __m128i v_disty = _mm_srli_epi16(v_fy.vect, 12); + v_distx = _mm_shufflehi_epi16(v_distx, _MM_SHUFFLE(2,2,0,0)); + v_distx = _mm_shufflelo_epi16(v_distx, _MM_SHUFFLE(2,2,0,0)); + v_disty = _mm_shufflehi_epi16(v_disty, _MM_SHUFFLE(2,2,0,0)); + v_disty = _mm_shufflelo_epi16(v_disty, _MM_SHUFFLE(2,2,0,0)); + + interpolate_4_pixels_16_sse2(tl.vect, tr.vect, bl.vect, br.vect, v_distx, v_disty, colorMask, v_256, b); + b+=4; + v_fx.vect = _mm_add_epi32(v_fx.vect, v_fdx); + v_fy.vect = _mm_add_epi32(v_fy.vect, v_fdy); + } + fx = v_fx.i[0]; + fy = v_fy.i[0]; +#elif defined(__ARM_NEON__) + BILINEAR_ROTATE_BOUNDS_PROLOG + + const int16x8_t colorMask = vdupq_n_s16(0x00ff); + const int16x8_t invColorMask = vmvnq_s16(colorMask); + const int16x8_t v_256 = vdupq_n_s16(256); + int32x4_t v_fdx = vdupq_n_s32(fdx*4); + int32x4_t v_fdy = vdupq_n_s32(fdy*4); + + const uchar *textureData = data->texture.imageData; + const int bytesPerLine = data->texture.bytesPerLine; + + union Vect_buffer { int32x4_t vect; quint32 i[4]; }; + Vect_buffer v_fx, v_fy; + + for (int i = 0; i < 4; i++) { + v_fx.i[i] = fx; + v_fy.i[i] = fy; + fx += fdx; + fy += fdy; + } + + const int32x4_t v_ffff_mask = vdupq_n_s32(0x0000ffff); + + while (b < boundedEnd) { + if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2) + break; + if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1) + break; + if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2) + break; + if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1) + break; + + Vect_buffer tl, tr, bl, br; + + Vect_buffer v_fx_shifted, v_fy_shifted; + v_fx_shifted.vect = vshrq_n_s32(v_fx.vect, 16); + v_fy_shifted.vect = vshrq_n_s32(v_fy.vect, 16); + + for (int i = 0; i < 4; i++) { + const int x1 = v_fx_shifted.i[i]; + const int y1 = v_fy_shifted.i[i]; + const uchar *sl = textureData + bytesPerLine * y1; + const uint *s1 = (const uint *)sl; + const uint *s2 = (const uint *)(sl + bytesPerLine); + tl.i[i] = s1[x1]; + tr.i[i] = s1[x1+1]; + bl.i[i] = s2[x1]; + br.i[i] = s2[x1+1]; + } + + int32x4_t v_distx = vshrq_n_s32(vandq_s32(v_fx.vect, v_ffff_mask), 12); + int32x4_t v_disty = vshrq_n_s32(vandq_s32(v_fy.vect, v_ffff_mask), 12); + v_distx = vorrq_s32(v_distx, vshlq_n_s32(v_distx, 16)); + v_disty = vorrq_s32(v_disty, vshlq_n_s32(v_disty, 16)); + int16x8_t v_disty_ = vshlq_n_s16(v_disty, 4); + + interpolate_4_pixels_16_neon(vreinterpretq_s16_s32(tl.vect), vreinterpretq_s16_s32(tr.vect), vreinterpretq_s16_s32(bl.vect), vreinterpretq_s16_s32(br.vect), vreinterpretq_s16_s32(v_distx), v_disty, v_disty_, colorMask, invColorMask, v_256, b); + b+=4; + v_fx.vect = vaddq_s32(v_fx.vect, v_fdx); + v_fy.vect = vaddq_s32(v_fy.vect, v_fdy); + } + fx = v_fx.i[0]; + fy = v_fy.i[0]; +#endif + } + while (b < end) { int x1 = (fx >> 16); int x2; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index a3b1f07c69..7c691c9670 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -147,8 +147,9 @@ static inline uint line_emulation(uint emulation) } #ifndef QT_NO_DEBUG -static bool qt_painter_thread_test(int devType, const char *what) +static bool qt_painter_thread_test(int devType, int engineType, const char *what) { + const QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration(); switch (devType) { case QInternal::Image: case QInternal::Printer: @@ -157,8 +158,13 @@ static bool qt_painter_thread_test(int devType, const char *what) break; default: if (QThread::currentThread() != qApp->thread() - && (devType!=QInternal::Pixmap || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps)) - && (devType!=QInternal::OpenGL || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL))) { + // pixmaps cannot be targets unless threaded pixmaps are supported + && (devType != QInternal::Pixmap || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedPixmaps)) + // framebuffer objects and such cannot be targets unless threaded GL is supported + && (devType != QInternal::OpenGL || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedOpenGL)) + // widgets cannot be targets except for QGLWidget + && (devType != QInternal::Widget || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedOpenGL) + || (engineType != QPaintEngine::OpenGL && engineType != QPaintEngine::OpenGL2))) { qWarning("QPainter: It is not safe to use %s outside the GUI thread", what); return false; } @@ -5054,7 +5060,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawPixmap()"); + qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawPixmap()"); #endif if (d->extended) { @@ -5125,7 +5131,7 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) if (!d->engine || pm.isNull()) return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawPixmap()"); + qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawPixmap()"); #endif qreal x = r.x(); @@ -6612,7 +6618,7 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()"); + qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawTiledPixmap()"); #endif qreal sw = pixmap.width(); diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index b2254c4826..078e16574f 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1335,6 +1335,15 @@ QByteArray QFontEngine::convertToPostscriptFontFamilyName(const QByteArray &fami return f; } +/** + * Some font engines like the windows font engine + * can not reliable create outline paths + */ +bool QFontEngine::hasUnreliableGlyphOutline() const +{ + return false; +} + QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round) { if (glyphs.numGlyphs >= 1) { diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index fe38755ffd..f5ca559d62 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -450,6 +450,7 @@ static void scaleOutline(FT_Face face, FT_GlyphSlot g, FT_Fixed x_scale, FT_Fixe } } +#define GLYPH2PATH_DEBUG QT_NO_QDEBUG_MACRO // qDebug void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale) { const qreal factor = 1/64.; @@ -461,22 +462,32 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi int i = 0; for (int j = 0; j < g->outline.n_contours; ++j) { int last_point = g->outline.contours[j]; - QPointF start = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor); - if(!(g->outline.tags[i] & 1)) { - start += cp + QPointF(g->outline.points[last_point].x*factor, -g->outline.points[last_point].y*factor); - start /= 2; + GLYPH2PATH_DEBUG() << "contour:" << i << "to" << last_point; + QPointF start = QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor); + if (!(g->outline.tags[i] & 1)) { // start point is not on curve: + if (!(g->outline.tags[last_point] & 1)) { // end point is not on curve: + GLYPH2PATH_DEBUG() << " start and end point are not on curve"; + start = (QPointF(g->outline.points[last_point].x*factor, + -g->outline.points[last_point].y*factor) + start) / 2.0; + } else { + GLYPH2PATH_DEBUG() << " end point is on curve, start is not"; + start = QPointF(g->outline.points[last_point].x*factor, + -g->outline.points[last_point].y*factor); + } + --i; // to use original start point as control point below } -// qDebug("contour: %d -- %d", i, g->outline.contours[j]); -// qDebug("first point at %f %f", start.x(), start.y()); - path->moveTo(start); + start += cp; + GLYPH2PATH_DEBUG() << " start at" << start; + path->moveTo(start); QPointF c[4]; c[0] = start; int n = 1; while (i < last_point) { ++i; c[n] = cp + QPointF(g->outline.points[i].x*factor, -g->outline.points[i].y*factor); -// qDebug() << " i=" << i << " flag=" << (int)g->outline.tags[i] << "point=" << c[n]; + GLYPH2PATH_DEBUG() << " " << i << c[n] << "tag =" << (int)g->outline.tags[i] + << ": on curve =" << (bool)(g->outline.tags[i] & 1); ++n; switch (g->outline.tags[i] & 3) { case 2: @@ -498,7 +509,7 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi case 1: case 3: if (n == 2) { -// qDebug() << "lineTo" << c[1]; + GLYPH2PATH_DEBUG() << " lineTo" << c[1]; path->lineTo(c[1]); c[0] = c[1]; n = 1; @@ -510,13 +521,14 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi } break; } -// qDebug() << "cubicTo" << c[1] << c[2] << c[3]; + GLYPH2PATH_DEBUG() << " cubicTo" << c[1] << c[2] << c[3]; path->cubicTo(c[1], c[2], c[3]); c[0] = c[3]; n = 1; } + if (n == 1) { -// qDebug() << "closeSubpath"; + GLYPH2PATH_DEBUG() << " closeSubpath"; path->closeSubpath(); } else { c[3] = start; @@ -524,7 +536,7 @@ void QFreetypeFace::addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoi c[2] = (2*c[1] + c[3])/3; c[1] = (2*c[1] + c[0])/3; } -// qDebug() << "cubicTo" << c[1] << c[2] << c[3]; + GLYPH2PATH_DEBUG() << " close cubicTo" << c[1] << c[2] << c[3]; path->cubicTo(c[1], c[2], c[3]); } ++i; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 5e40abbda6..fc849d788f 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -251,6 +251,8 @@ public: static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily); + virtual bool hasUnreliableGlyphOutline() const; + enum HintStyle { HintNone, HintLight, diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp index ac9762b183..731b6adde8 100644 --- a/src/gui/text/qtextcursor.cpp +++ b/src/gui/text/qtextcursor.cpp @@ -132,7 +132,7 @@ QTextCursorPrivate::AdjustResult QTextCursorPrivate::adjustPosition(int position void QTextCursorPrivate::setX() { - if (priv->isInEditBlock()) { + if (priv->isInEditBlock() || priv->inContentsChange) { x = -1; // mark dirty return; } diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 34788dc4dc..67dedca760 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2057,7 +2057,7 @@ void QTextEngine::justify(const QScriptLine &line) // subtract one char more, as we can't justfy after the last character --line_length; - if (!line_length) + if (line_length <= 0) return; int firstItem = findItem(line.from); |