diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp | 23 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_windows.h | 49 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win.cpp | 10 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 18 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicswidget.cpp | 6 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicswidget_p.cpp | 164 | ||||
-rw-r--r-- | src/gui/kernel/qsizepolicy.h | 12 | ||||
-rw-r--r-- | src/gui/painting/qpaintbuffer.cpp | 101 | ||||
-rw-r--r-- | src/gui/painting/qpaintbuffer_p.h | 8 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 68 | ||||
-rw-r--r-- | src/gui/text/qtextdocument.cpp | 8 | ||||
-rw-r--r-- | src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp | 60 |
12 files changed, 391 insertions, 136 deletions
diff --git a/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp b/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp index f0d3b84..0eb0799 100644 --- a/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp @@ -73,6 +73,19 @@ namespace JSC { #define SYMBOL_STRING(name) #name #endif +#if PLATFORM(DARWIN) + // Mach-O platform +#define HIDE_SYMBOL(name) ".private_extern _" #name +#elif PLATFORM(AIX) + // IBM's own file format +#define HIDE_SYMBOL(name) ".lglobl " #name +#elif PLATFORM(LINUX) || PLATFORM(FREEBSD) || PLATFORM(OPENBSD) || PLATFORM(SOLARIS) || (PLATFORM(HPUX) && PLATFORM(IA64)) || PLATFORM(SYMBIAN) || PLATFORM(NETBSD) + // ELF platform +#define HIDE_SYMBOL(name) ".hidden " #name +#else +#define HIDE_SYMBOL(name) +#endif + #if COMPILER(GCC) && PLATFORM(X86) // These ASSERTs remind you that, if you change the layout of JITStackFrame, you @@ -83,6 +96,7 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_s asm volatile ( ".globl " SYMBOL_STRING(ctiTrampoline) "\n" +HIDE_SYMBOL(ctiTrampoline) "\n" SYMBOL_STRING(ctiTrampoline) ":" "\n" "pushl %ebp" "\n" "movl %esp, %ebp" "\n" @@ -103,6 +117,7 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n" asm volatile ( ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" +HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" #if !USE(JIT_STUB_ARGUMENT_VA_LIST) "movl %esp, %ecx" "\n" @@ -118,6 +133,7 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" asm volatile ( ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" +HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" "addl $0x1c, %esp" "\n" "popl %ebx" "\n" @@ -141,6 +157,7 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_s asm volatile ( ".globl " SYMBOL_STRING(ctiTrampoline) "\n" +HIDE_SYMBOL(ctiTrampoline) "\n" SYMBOL_STRING(ctiTrampoline) ":" "\n" "pushq %rbp" "\n" "movq %rsp, %rbp" "\n" @@ -167,6 +184,7 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n" asm volatile ( ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" +HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" "movq %rsp, %rdi" "\n" "call " SYMBOL_STRING(cti_vm_throw) "\n" @@ -182,6 +200,7 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" asm volatile ( ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" +HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" "addq $0x48, %rsp" "\n" "popq %rbx" "\n" @@ -203,6 +222,7 @@ asm volatile ( ".text" "\n" ".align 2" "\n" ".globl " SYMBOL_STRING(ctiTrampoline) "\n" +HIDE_SYMBOL(ctiTrampoline) "\n" ".thumb" "\n" ".thumb_func " SYMBOL_STRING(ctiTrampoline) "\n" SYMBOL_STRING(ctiTrampoline) ":" "\n" @@ -229,6 +249,7 @@ asm volatile ( ".text" "\n" ".align 2" "\n" ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" +HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" ".thumb" "\n" ".thumb_func " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" @@ -246,6 +267,7 @@ asm volatile ( ".text" "\n" ".align 2" "\n" ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" +HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" ".thumb" "\n" ".thumb_func " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" @@ -591,6 +613,7 @@ namespace JITStubs { ".text" "\n" \ ".align 2" "\n" \ ".globl " SYMBOL_STRING(cti_##op) "\n" \ + HIDE_SYMBOL(cti_##op) "\n" \ ".thumb" "\n" \ ".thumb_func " SYMBOL_STRING(cti_##op) "\n" \ SYMBOL_STRING(cti_##op) ":" "\n" \ diff --git a/src/corelib/arch/qatomic_windows.h b/src/corelib/arch/qatomic_windows.h index 6082d0b..07b0b25 100644 --- a/src/corelib/arch/qatomic_windows.h +++ b/src/corelib/arch/qatomic_windows.h @@ -102,9 +102,14 @@ #define QT_INTERLOCKED_CONCAT(prefix, suffix) \ QT_INTERLOCKED_CONCAT_I(prefix, suffix) -// MSVC intrinsics prefix function names with an underscore +// MSVC intrinsics prefix function names with an underscore. Also, if platform +// SDK headers have been included, the Interlocked names may be defined as +// macros. +// To avoid double underscores, we paste the prefix with Interlocked first and +// then the remainder of the function name. #define QT_INTERLOCKED_FUNCTION(name) \ - QT_INTERLOCKED_CONCAT(QT_INTERLOCKED_PREFIX, name) + QT_INTERLOCKED_CONCAT( \ + QT_INTERLOCKED_CONCAT(QT_INTERLOCKED_PREFIX, Interlocked), name) #ifdef QT_INTERLOCKED_NO_VOLATILE # define QT_INTERLOCKED_VOLATILE @@ -127,16 +132,16 @@ extern "C" { - long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( InterlockedIncrement )(long QT_INTERLOCKED_VOLATILE *); - long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( InterlockedDecrement )(long QT_INTERLOCKED_VOLATILE *); - long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( InterlockedCompareExchange )(long QT_INTERLOCKED_VOLATILE *, long, long); - long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( InterlockedExchange )(long QT_INTERLOCKED_VOLATILE *, long); - long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( InterlockedExchangeAdd )(long QT_INTERLOCKED_VOLATILE *, long); + long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Increment )(long QT_INTERLOCKED_VOLATILE *); + long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Decrement )(long QT_INTERLOCKED_VOLATILE *); + long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( CompareExchange )(long QT_INTERLOCKED_VOLATILE *, long, long); + long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( Exchange )(long QT_INTERLOCKED_VOLATILE *, long); + long QT_INTERLOCKED_PROTOTYPE QT_INTERLOCKED_FUNCTION( ExchangeAdd )(long QT_INTERLOCKED_VOLATILE *, long); # if !defined(Q_OS_WINCE) && !defined(__i386__) && !defined(_M_IX86) - void * QT_INTERLOCKED_FUNCTION( InterlockedCompareExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *, void *); - void * QT_INTERLOCKED_FUNCTION( InterlockedExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *); - __int64 QT_INTERLOCKED_FUNCTION( InterlockedExchangeAdd64 )(__int64 QT_INTERLOCKED_VOLATILE *, __int64); + void * QT_INTERLOCKED_FUNCTION( CompareExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *, void *); + void * QT_INTERLOCKED_FUNCTION( ExchangePointer )(void * QT_INTERLOCKED_VOLATILE *, void *); + __int64 QT_INTERLOCKED_FUNCTION( ExchangeAdd64 )(__int64 QT_INTERLOCKED_VOLATILE *, __int64); # endif } @@ -156,7 +161,7 @@ extern "C" { # pragma intrinsic (_InterlockedCompareExchange) # pragma intrinsic (_InterlockedExchangeAdd) -# ifndef _M_IX86 +# if !defined(Q_OS_WINCE) && !defined(_M_IX86) # pragma intrinsic (_InterlockedCompareExchangePointer) # pragma intrinsic (_InterlockedExchangePointer) # pragma intrinsic (_InterlockedExchangeAdd64) @@ -168,26 +173,26 @@ extern "C" { // Interlocked* replacement macros #define QT_INTERLOCKED_INCREMENT(value) \ - QT_INTERLOCKED_FUNCTION(InterlockedIncrement)( \ + QT_INTERLOCKED_FUNCTION( Increment )( \ QT_INTERLOCKED_REMOVE_VOLATILE( value ) ) #define QT_INTERLOCKED_DECREMENT(value) \ - QT_INTERLOCKED_FUNCTION(InterlockedDecrement)( \ + QT_INTERLOCKED_FUNCTION( Decrement )( \ QT_INTERLOCKED_REMOVE_VOLATILE( value ) ) #define QT_INTERLOCKED_COMPARE_EXCHANGE(value, newValue, expectedValue) \ - QT_INTERLOCKED_FUNCTION(InterlockedCompareExchange)( \ + QT_INTERLOCKED_FUNCTION( CompareExchange )( \ QT_INTERLOCKED_REMOVE_VOLATILE( value ), \ newValue, \ expectedValue ) #define QT_INTERLOCKED_EXCHANGE(value, newValue) \ - QT_INTERLOCKED_FUNCTION(InterlockedExchange)( \ + QT_INTERLOCKED_FUNCTION( Exchange )( \ QT_INTERLOCKED_REMOVE_VOLATILE( value ), \ newValue ) #define QT_INTERLOCKED_EXCHANGE_ADD(value, valueToAdd) \ - QT_INTERLOCKED_FUNCTION(InterlockedExchangeAdd)( \ + QT_INTERLOCKED_FUNCTION( ExchangeAdd )( \ QT_INTERLOCKED_REMOVE_VOLATILE( value ), \ valueToAdd ) @@ -195,36 +200,36 @@ extern "C" { # define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \ reinterpret_cast<void *>( \ - QT_INTERLOCKED_FUNCTION(InterlockedCompareExchange)( \ + QT_INTERLOCKED_FUNCTION( CompareExchange )( \ QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ (long)( newValue ), \ (long)( expectedValue ) )) # define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \ - QT_INTERLOCKED_FUNCTION(InterlockedExchange)( \ + QT_INTERLOCKED_FUNCTION( Exchange )( \ QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ (quintptr)( newValue ) ) # define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \ - QT_INTERLOCKED_FUNCTION(InterlockedExchangeAdd)( \ + QT_INTERLOCKED_FUNCTION( ExchangeAdd )( \ QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ valueToAdd ) #else // !defined(Q_OS_WINCE) && !defined(__i386__) && !defined(_M_IX86) # define QT_INTERLOCKED_COMPARE_EXCHANGE_POINTER(value, newValue, expectedValue) \ - QT_INTERLOCKED_FUNCTION(InterlockedCompareExchangePointer)( \ + QT_INTERLOCKED_FUNCTION( CompareExchangePointer )( \ reinterpret_cast<void * QT_INTERLOCKED_VOLATILE *>( QT_INTERLOCKED_REMOVE_VOLATILE( value ) ), \ newValue, \ expectedValue ) # define QT_INTERLOCKED_EXCHANGE_POINTER(value, newValue) \ - QT_INTERLOCKED_FUNCTION(InterlockedExchangePointer)( \ + QT_INTERLOCKED_FUNCTION( ExchangePointer )( \ reinterpret_cast<void * QT_INTERLOCKED_VOLATILE *>( QT_INTERLOCKED_REMOVE_VOLATILE( value ) ), \ newValue ) # define QT_INTERLOCKED_EXCHANGE_ADD_POINTER(value, valueToAdd) \ - QT_INTERLOCKED_FUNCTION(InterlockedExchangeAdd64)( \ + QT_INTERLOCKED_FUNCTION( ExchangeAdd64 )( \ QT_INTERLOCKED_REMOVE_VOLATILE( value ## _integral ), \ valueToAdd ) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index b7934db..9c308a3 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -331,7 +331,7 @@ public: WinTimerVec timerVec; WinTimerDict timerDict; void registerTimer(WinTimerInfo *t); - void unregisterTimer(WinTimerInfo *t); + void unregisterTimer(WinTimerInfo *t, bool closingDown = false); void sendTimerEvent(int timerId); // socket notifiers @@ -557,10 +557,10 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t) qErrnoWarning("QEventDispatcherWin32::registerTimer: Failed to create a timer"); } -void QEventDispatcherWin32Private::unregisterTimer(WinTimerInfo *t) +void QEventDispatcherWin32Private::unregisterTimer(WinTimerInfo *t, bool closingDown) { // mark timer as unused - if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent) + if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent && !closingDown) QAbstractEventDispatcherPrivate::releaseTimerId(t->timerId); if (t->interval == 0) { @@ -1019,8 +1019,8 @@ void QEventDispatcherWin32::closingDown() unregisterSocketNotifier((*(d->sn_except.begin()))->obj); // clean up any timers - while (!d->timerDict.isEmpty()) - unregisterTimer((*(d->timerDict.begin()))->timerId); + for (int i = 0; i < d->timerVec.count(); ++i) + d->unregisterTimer(d->timerVec.at(i), true); } bool QEventDispatcherWin32::event(QEvent *e) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index cdcb0c4..eae3e63 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -4770,7 +4770,7 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n { Q_ASSERT(inSetPosHelper); - if (!(ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) + if (inDestructor || !(ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) return; // Not clipped by any ancestor. // Find closest clip ancestor and transform. @@ -4780,15 +4780,19 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n if (transformData) thisToParentTransform = transformData->computedFullTransform(&thisToParentTransform); QGraphicsItem *clipParent = parent; - while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) { + while (clipParent && !clipParent->d_ptr->inDestructor && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) { thisToParentTransform *= clipParent->d_ptr->transformToParent(); clipParent = clipParent->d_ptr->parent; } - // thisToParentTransform is now the same as q->itemTransform(clipParent), except - // that the new position (which is not yet set on the item) is taken into account. - Q_ASSERT(clipParent); - Q_ASSERT(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); + // Ensure no parents are currently being deleted. This can only + // happen if the item is moved by a dying ancestor. + QGraphicsItem *p = clipParent; + while (p) { + if (p->d_ptr->inDestructor) + return; + p = p->d_ptr->parent; + } // From here everything is calculated in clip parent's coordinates. const QRectF parentBoundingRect(clipParent->boundingRect()); @@ -6850,6 +6854,8 @@ void QGraphicsItem::removeFromIndex() */ void QGraphicsItem::prepareGeometryChange() { + if (d_ptr->inDestructor) + return; if (d_ptr->scene) { d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true; d_ptr->geometryChanged = 1; diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index afabf49..d0f3b99 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -687,11 +687,13 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c Q_D(const QGraphicsWidget); QSizeF sh; if (d->layout) { - sh = d->layout->effectiveSizeHint(which, constraint); + QSizeF marginSize(0,0); if (d->margins) { - sh += QSizeF(d->margins[d->Left] + d->margins[d->Right], + marginSize = QSizeF(d->margins[d->Left] + d->margins[d->Right], d->margins[d->Top] + d->margins[d->Bottom]); } + sh = d->layout->effectiveSizeHint(which, constraint - marginSize); + sh += marginSize; } else { switch (which) { case Qt::MinimumSize: diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp index 787bbb1..bf826a9 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.cpp +++ b/src/gui/graphicsview/qgraphicswidget_p.cpp @@ -393,49 +393,162 @@ void QGraphicsWidgetPrivate::windowFrameMousePressEvent(QGraphicsSceneMouseEvent event->setAccepted(windowData->grabbedSection != Qt::NoSection); } +/*! + Used to calculate the + Precondition: + \a widget should support either hfw or wfh + + If \a heightForWidth is set to false, this function will query the width for height + instead. \a width will then be interpreted as height, \a minh and \a maxh will be interpreted + as minimum width and maximum width. + */ +static qreal minimumHeightForWidth(qreal width, qreal minh, qreal maxh, + const QGraphicsWidget *widget, + bool heightForWidth = true) +{ + qreal minimumHeightForWidth = -1; + const QSizePolicy sp = widget->layout() ? widget->layout()->sizePolicy() : widget->sizePolicy(); + const bool hasHFW = sp.hasHeightForWidth(); + if (hasHFW == heightForWidth) { + minimumHeightForWidth = hasHFW + ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height() + : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, width)).width(); //"width" is here height! + } else { + // widthForHeight + const qreal constraint = width; + while (maxh - minh > 0.1) { + qreal middle = minh + (maxh - minh)/2; + // ### really bad, if we are a widget with a layout it will call + // layout->effectiveSizeHint(Qt::MiniumumSize), which again will call + // sizeHint three times because of how the cache works + qreal hfw = hasHFW + ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(middle, -1)).height() + : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, middle)).width(); + if (hfw > constraint) { + minh = middle; + } else if (hfw <= constraint) { + maxh = middle; + } + } + minimumHeightForWidth = maxh; + } + return minimumHeightForWidth; +} + +static qreal minimumWidthForHeight(qreal height, qreal minw, qreal maxw, + const QGraphicsWidget *widget) +{ + return minimumHeightForWidth(height, minw, maxw, widget, false); +} + +static QSizeF closestAcceptableSize(const QSizeF &proposed, + const QGraphicsWidget *widget) +{ + const QSizeF current = widget->size(); + + qreal minw = proposed.width(); + qreal maxw = current.width(); + qreal minh = proposed.height(); + qreal maxh = current.height(); + + qreal middlew = maxw; + qreal middleh = maxh; + qreal min_hfw; + min_hfw = minimumHeightForWidth(maxw, minh, maxh, widget); + + do { + if (maxw - minw < 0.1) { + // we still havent found anything, cut off binary search + minw = maxw; + minh = maxh; + } + middlew = minw + (maxw - minw)/2.0; + middleh = minh + (maxh - minh)/2.0; + + min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget); + + if (min_hfw > middleh) { + minw = middlew; + minh = middleh; + } else if (min_hfw <= middleh) { + maxw = middlew; + maxh = middleh; + } + } while (maxw != minw); + + min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget); + + QSizeF result; + if (min_hfw < maxh) { + result = QSizeF(middlew, min_hfw); + } else { + // Needed because of the cut-off we do above. + result = QSizeF(minimumWidthForHeight(maxh, proposed.width(), current.width(), widget), maxh); + } + return result; +} + static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry, QRectF *rect, Qt::WindowFrameSection section, - const QSizeF &min, const QSizeF &max) + const QSizeF &min, const QSizeF &max, + const QGraphicsWidget *widget) { - int height; - int width; + const QRectF proposedRect = *rect; + qreal width = qBound(min.width(), proposedRect.width(), max.width()); + qreal height = qBound(min.height(), proposedRect.height(), max.height()); + + QSizePolicy sp = widget->sizePolicy(); + if (const QGraphicsLayout *l = widget->layout()) { + sp = l->sizePolicy(); + } + const bool hasHFW = sp.hasHeightForWidth(); // || sp.hasWidthForHeight(); + + const bool widthChanged = proposedRect.width() < widget->size().width(); + const bool heightChanged = proposedRect.height() < widget->size().height(); + + if (hasHFW) { + if (widthChanged || heightChanged) { + const qreal minh = min.height(); + const qreal maxh = max.height(); + const qreal proposedHFW = minimumHeightForWidth(width, minh, maxh, widget); + if (proposedHFW > proposedRect.height()) { + QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget); + width = effectiveSize.width(); + height = effectiveSize.height(); + } + } + } + switch (section) { case Qt::LeftSection: - width = qRound(qBound(min.width(), rect->width(), max.width())); - rect->setRect(startGeometry.right() - width, startGeometry.top(), - width, startGeometry.height()); + rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(), + qRound(width), startGeometry.height()); break; case Qt::TopLeftSection: - width = qRound(qBound(min.width(), rect->width(), max.width())); - height = qRound(qBound(min.height(), rect->height(), max.height())); - rect->setRect(startGeometry.right() - width, startGeometry.bottom() - height, - width, height); + rect->setRect(startGeometry.right() - qRound(width), startGeometry.bottom() - qRound(height), + qRound(width), qRound(height)); break; case Qt::TopSection: - height = qRound(qBound(min.height(), rect->height(), max.height())); - rect->setRect(startGeometry.left(), startGeometry.bottom() - height, - startGeometry.width(), height); + rect->setRect(startGeometry.left(), startGeometry.bottom() - qRound(height), + startGeometry.width(), qRound(height)); break; case Qt::TopRightSection: - height = qRound(qBound(min.height(), rect->height(), max.height())); - rect->setTop(rect->bottom() - height); - rect->setWidth(qBound(min.width(), rect->width(), max.width())); + rect->setTop(rect->bottom() - qRound(height)); + rect->setWidth(qRound(width)); break; case Qt::RightSection: - rect->setWidth(qBound(min.width(), rect->width(), max.width())); + rect->setWidth(qRound(width)); break; case Qt::BottomRightSection: - rect->setWidth(qBound(min.width(), rect->width(), max.width())); - rect->setHeight(qBound(min.height(), rect->height(), max.height())); + rect->setWidth(qRound(width)); + rect->setHeight(qRound(height)); break; case Qt::BottomSection: - rect->setHeight(qBound(min.height(), rect->height(), max.height())); + rect->setHeight(qRound(height)); break; case Qt::BottomLeftSection: - height = qRound(qBound(min.height(), rect->height(), max.height())); - width = qRound(qBound(min.width(), rect->width(), max.width())); - rect->setRect(startGeometry.right() - width, startGeometry.top(), - width, height); + rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(), + qRound(width), qRound(height)); break; default: break; @@ -506,7 +619,8 @@ void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent _q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry, windowData->grabbedSection, q->effectiveSizeHint(Qt::MinimumSize), - q->effectiveSizeHint(Qt::MaximumSize)); + q->effectiveSizeHint(Qt::MaximumSize), + q); q->setGeometry(newGeometry); } } diff --git a/src/gui/kernel/qsizepolicy.h b/src/gui/kernel/qsizepolicy.h index 4261dda..eb13788 100644 --- a/src/gui/kernel/qsizepolicy.h +++ b/src/gui/kernel/qsizepolicy.h @@ -64,6 +64,7 @@ private: VMask = HMask << HSize, CTShift = 9, CTSize = 5, + WFHShift = CTShift + CTSize, CTMask = ((0x1 << CTSize) - 1) << CTShift, UnusedShift = CTShift + CTSize, UnusedSize = 2 @@ -199,6 +200,17 @@ private: QSizePolicy(int i) : data(i) { } quint32 data; +/* use bit flags instead, keep it here for improved readability for now + quint32 horzPolicy : 4; + quint32 vertPolicy : 4; + quint32 hfw : 1; + quint32 ctype : 5; + quint32 wfh : 1; + quint32 padding : 1; // we cannot use the highest bit + quint32 horStretch : 8; + quint32 verStretch : 8; +*/ + }; Q_DECLARE_OPERATORS_FOR_FLAGS(QSizePolicy::ControlTypes) diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp index 04ddd7d..f9cb108 100644 --- a/src/gui/painting/qpaintbuffer.cpp +++ b/src/gui/painting/qpaintbuffer.cpp @@ -239,7 +239,7 @@ bool QPaintBuffer::isEmpty() const -void QPaintBuffer::draw(QPainter *painter) const +void QPaintBuffer::draw(QPainter *painter, int frame) const { #ifdef QPAINTBUFFER_DEBUG_DRAW qDebug() << "QPaintBuffer::draw() --------------------------------"; @@ -270,10 +270,10 @@ void QPaintBuffer::draw(QPainter *painter) const ? (QPaintEngineEx *) painter->paintEngine() : 0; if (xengine) { QPaintEngineExReplayer player; - player.draw(*this, painter); + player.draw(*this, painter, frame); } else { QPainterReplayer player; - player.draw(*this, painter); + player.draw(*this, painter, frame); } #ifdef QPAINTBUFFER_DEBUG_DRAW @@ -1035,17 +1035,31 @@ void QPainterReplayer::setupTransform(QPainter *_painter) painter->setTransform(m_world_matrix); } -void QPainterReplayer::draw(const QPaintBuffer &buffer, QPainter *_painter) +void QPainterReplayer::draw(const QPaintBuffer &buffer, QPainter *_painter, int frame) { d = buffer.d_ptr; setupTransform(_painter); - for (int cmdIndex=0; cmdIndex<d->commands.size(); ++cmdIndex) { + int frameStart = (frame == 0) ? 0 : d->frames.at(frame-1); + int frameEnd = (frame == d->frames.size()) ? d->commands.size() : d->frames.at(frame); + + for (int cmdIndex=frameStart; cmdIndex<frameEnd; ++cmdIndex) { const QPaintBufferCommand &cmd = d->commands.at(cmdIndex); process(cmd); } } +void QPaintBuffer::beginNewFrame() +{ + if (!d_ptr->commands.isEmpty()) + d_ptr->frames << d_ptr->commands.size(); +} + +int QPaintBuffer::numFrames() const +{ + return d_ptr->frames.size() + 1; +} + void QPainterReplayer::process(const QPaintBufferCommand &cmd) { switch (cmd.id) { @@ -1721,24 +1735,99 @@ QDataStream &operator>>(QDataStream &stream, QPaintBufferCommand &command) return stream; } +struct QPaintBufferCacheEntry +{ + QVariant::Type type; + quint64 cacheKey; +}; + +QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntry &entry) +{ + return stream << entry.type << entry.cacheKey; +} + +QDataStream &operator>>(QDataStream &stream, QPaintBufferCacheEntry &entry) +{ + return stream >> entry.type >> entry.cacheKey; +} + +static int qRegisterPaintBufferMetaTypes() +{ + qRegisterMetaType<QPaintBufferCacheEntry>(); + qRegisterMetaTypeStreamOperators<QPaintBufferCacheEntry>("QPaintBufferCacheEntry"); + + return 0; // something +} + +Q_DECLARE_METATYPE(QPaintBufferCacheEntry); +Q_CONSTRUCTOR_FUNCTION(qRegisterPaintBufferMetaTypes) + QDataStream &operator<<(QDataStream &stream, const QPaintBuffer &buffer) { + QHash<qint64, QPixmap> pixmaps; + QHash<qint64, QImage> images; + + QVector<QVariant> variants = buffer.d_ptr->variants; + for (int i = 0; i < variants.size(); ++i) { + const QVariant &v = variants.at(i); + if (v.type() == QVariant::Image) { + const QImage image(v.value<QImage>()); + images[image.cacheKey()] = image; + + QPaintBufferCacheEntry entry; + entry.type = QVariant::Image; + entry.cacheKey = image.cacheKey(); + variants[i] = QVariant::fromValue(entry); + } else if (v.type() == QVariant::Pixmap) { + const QPixmap pixmap(v.value<QPixmap>()); + pixmaps[pixmap.cacheKey()] = pixmap; + + QPaintBufferCacheEntry entry; + entry.type = QVariant::Pixmap; + entry.cacheKey = pixmap.cacheKey(); + variants[i] = QVariant::fromValue(entry); + } + } + + stream << pixmaps; + stream << images; + stream << buffer.d_ptr->ints; stream << buffer.d_ptr->floats; - stream << buffer.d_ptr->variants; + stream << variants; stream << buffer.d_ptr->commands; stream << buffer.d_ptr->boundingRect; + stream << buffer.d_ptr->frames; return stream; } QDataStream &operator>>(QDataStream &stream, QPaintBuffer &buffer) { + QHash<qint64, QPixmap> pixmaps; + QHash<qint64, QImage> images; + + stream >> pixmaps; + stream >> images; + stream >> buffer.d_ptr->ints; stream >> buffer.d_ptr->floats; stream >> buffer.d_ptr->variants; stream >> buffer.d_ptr->commands; stream >> buffer.d_ptr->boundingRect; + stream >> buffer.d_ptr->frames; + + QVector<QVariant> &variants = buffer.d_ptr->variants; + for (int i = 0; i < variants.size(); ++i) { + const QVariant &v = variants.at(i); + if (v.canConvert<QPaintBufferCacheEntry>()) { + QPaintBufferCacheEntry entry = v.value<QPaintBufferCacheEntry>(); + if (entry.type == QVariant::Image) + variants[i] = QVariant(images.value(entry.cacheKey)); + else + variants[i] = QVariant(pixmaps.value(entry.cacheKey)); + } + } return stream; } diff --git a/src/gui/painting/qpaintbuffer_p.h b/src/gui/painting/qpaintbuffer_p.h index b360279..2cb1d7c 100644 --- a/src/gui/painting/qpaintbuffer_p.h +++ b/src/gui/painting/qpaintbuffer_p.h @@ -71,7 +71,10 @@ public: bool isEmpty() const; - void draw(QPainter *painter) const; + void beginNewFrame(); + int numFrames() const; + + void draw(QPainter *painter, int frame = 0) const; void setBoundingRect(const QRectF &rect); QRectF boundingRect() const; @@ -270,6 +273,7 @@ public: QVector<QVariant> variants; QVector<QPaintBufferCommand> commands; + QList<int> frames; QPaintBufferEngine *engine; QRectF boundingRect; @@ -306,7 +310,7 @@ public: void setupTransform(QPainter *painter); void process(const QPaintBufferCommand &cmd); - void draw(const QPaintBuffer &buffer, QPainter *painter); + void draw(const QPaintBuffer &buffer, QPainter *painter, int frame); protected: QPaintBufferPrivate *d; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index a6bea76..263e53e 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7545,10 +7545,9 @@ void qt_format_text(const QFont &fnt, const QRectF &_r, if (!painter) tf |= Qt::TextDontPrint; - int maxUnderlines = 0; + uint maxUnderlines = 0; int numUnderlines = 0; - int underlinePositionStack[32]; - int *underlinePositions = underlinePositionStack; + QVarLengthArray<int, 32> underlinePositions(1); QFontMetricsF fm(fnt); QString text = str; @@ -7557,54 +7556,46 @@ start_lengthVariant: bool hasMoreLengthVariants = false; // compatible behaviour to the old implementation. Replace // tabs by spaces - QChar *chr = text.data() + offset; - QChar *end = text.data() + text.length(); bool has_tab = false; - while (chr != end) { - if (*chr == QLatin1Char('\r') || (singleline && *chr == QLatin1Char('\n'))) { - *chr = QLatin1Char(' '); - } else if (*chr == QLatin1Char('\n')) { - *chr = QChar::LineSeparator; - } else if (*chr == QLatin1Char('&')) { + int old_offset = offset; + for (; offset < text.length(); offset++) { + QChar chr = text.at(offset); + if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) { + text[offset] = QLatin1Char(' '); + } else if (chr == QLatin1Char('\n')) { + text[offset] = QChar::LineSeparator; + } else if (chr == QLatin1Char('&')) { ++maxUnderlines; - } else if (*chr == QLatin1Char('\t')) { + } else if (chr == QLatin1Char('\t')) { + if (!expandtabs) { + text[offset] = QLatin1Char(' '); + } else if (!tabarraylen && !tabstops) { + tabstops = qRound(fm.width(QLatin1Char('x'))*8); + } has_tab = true; - } else if (*chr == QChar(ushort(0x9c))) { + } else if (chr == QChar(ushort(0x9c))) { // string with multiple length variants - end = chr; hasMoreLengthVariants = true; break; } - ++chr; - } - if (has_tab) { - if (!expandtabs) { - chr = text.data() + offset; - while (chr != end) { - if (*chr == QLatin1Char('\t')) - *chr = QLatin1Char(' '); - ++chr; - } - } else if (!tabarraylen && !tabstops) { - tabstops = qRound(fm.width(QLatin1Char('x'))*8); - } } - QChar *cout = end; - if (hidemnmemonic || showmnemonic) { - if (maxUnderlines > 32) - underlinePositions = new int[maxUnderlines]; - cout = text.data() + offset; + int length = offset - old_offset; + if ((hidemnmemonic || showmnemonic) && maxUnderlines > 0) { + underlinePositions.resize(maxUnderlines + 1); + + QChar *cout = text.data() + old_offset; QChar *cin = cout; - int l = end - cout; + int l = length; while (l) { if (*cin == QLatin1Char('&')) { ++cin; + --length; --l; if (!l) break; if (*cin != QLatin1Char('&') && !hidemnmemonic) - underlinePositions[numUnderlines++] = cout - text.unicode(); + underlinePositions[numUnderlines++] = cout - text.data() - old_offset; } *cout = *cin; ++cout; @@ -7621,7 +7612,7 @@ start_lengthVariant: qreal height = 0; qreal width = 0; - QString finalText = text.mid(offset, cout - (text.data() + offset)); + QString finalText = text.mid(old_offset, length); QStackTextEngine engine(finalText, fnt); if (option) { engine.option = *option; @@ -7640,7 +7631,7 @@ start_lengthVariant: engine.forceJustification = true; QTextLayout textLayout(&engine); textLayout.setCacheEnabled(true); - textLayout.engine()->underlinePositions = underlinePositions; + textLayout.engine()->underlinePositions = underlinePositions.data(); if (finalText.isEmpty()) { height = fm.height(); @@ -7709,7 +7700,7 @@ start_lengthVariant: QRectF bounds = QRectF(r.x() + xoff, r.y() + yoff, width, height); if (hasMoreLengthVariants && !(tf & Qt::TextLongestVariant) && !r.contains(bounds)) { - offset = end - text.data() + 1; + offset++; goto start_lengthVariant; } if (brect) @@ -7738,9 +7729,6 @@ start_lengthVariant: painter->restore(); } } - - if (underlinePositions != underlinePositionStack) - delete [] underlinePositions; } /*! diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 1bdaceb..e565d0a 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -2521,13 +2521,15 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block) default: html += QLatin1String("<ul"); // ### should not happen } + html += QLatin1String(" style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px;"); + if (format.hasProperty(QTextFormat::ListIndent)) { - html += QLatin1String(" style=\"-qt-list-indent: "); + html += QLatin1String(" -qt-list-indent: "); html += QString::number(format.indent()); - html += QLatin1String(";\""); + html += QLatin1Char(';'); } - html += QLatin1Char('>'); + html += QLatin1String("\">"); } html += QLatin1String("<li"); diff --git a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp index 36a8df1..bbb6536 100644 --- a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp +++ b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp @@ -57,30 +57,35 @@ public: ~QTraceWindowSurface(); QPaintDevice *paintDevice(); + void beginPaint(const QRegion &rgn); void endPaint(const QRegion &rgn); + bool scroll(const QRegion &area, int dx, int dy); + private: QPaintBuffer *buffer; + QList<QRegion> updates; - QFile *outputFile; - QDataStream *out; - - int frameId; + qulonglong winId; }; QTraceWindowSurface::QTraceWindowSurface(QWidget *widget) : QRasterWindowSurface(widget) , buffer(0) - , outputFile(0) - , out(0) - , frameId(0) + , winId(0) { } QTraceWindowSurface::~QTraceWindowSurface() { - delete out; - delete outputFile; + if (buffer) { + QFile outputFile(QString(QLatin1String("qtgraphics-%0.trace")).arg(winId)); + if (outputFile.open(QIODevice::WriteOnly)) { + QDataStream out(&outputFile); + out << *buffer << updates; + } + delete buffer; + } } QPaintDevice *QTraceWindowSurface::paintDevice() @@ -92,28 +97,33 @@ QPaintDevice *QTraceWindowSurface::paintDevice() return buffer; } -void QTraceWindowSurface::endPaint(const QRegion &rgn) +void QTraceWindowSurface::beginPaint(const QRegion &rgn) { - if (!out) { - outputFile = new QFile(QString(QLatin1String("qtgraphics-%0.trace")).arg((qulonglong)window()->winId())); - if (outputFile->open(QIODevice::WriteOnly)) - out = new QDataStream(outputFile); - } + // ensure paint buffer is created + paintDevice(); + buffer->beginNewFrame(); + + QRasterWindowSurface::beginPaint(rgn); +} +void QTraceWindowSurface::endPaint(const QRegion &rgn) +{ QPainter p(QRasterWindowSurface::paintDevice()); - buffer->draw(&p); + buffer->draw(&p, buffer->numFrames()-1); p.end(); - if (out) { - *out << frameId++; - *out << (qulonglong)window()->winId(); - *out << geometry(); - *out << rgn; - *out << *buffer; - } + winId = (qulonglong)window()->winId(); + + updates << rgn; - delete buffer; - buffer = 0; + QRasterWindowSurface::endPaint(rgn); +} + +bool QTraceWindowSurface::scroll(const QRegion &, int, int) +{ + // TODO: scrolling should also be streamed and replayed + // to test scrolling performance + return false; } QTraceGraphicsSystem::QTraceGraphicsSystem() |