diff options
Diffstat (limited to 'src/gui')
31 files changed, 303 insertions, 127 deletions
diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp index d048b36..ed5aa23 100644 --- a/src/gui/inputmethod/qximinputcontext_x11.cpp +++ b/src/gui/inputmethod/qximinputcontext_x11.cpp @@ -346,10 +346,7 @@ static XFontSet getFontSet(const QFont &f) extern bool qt_use_rtl_extensions; // from qapplication_x11.cpp #ifndef QT_NO_XKB -extern void q_getLocaleAndDirection(QLocale *locale, - Qt::LayoutDirection *direction, - const QByteArray &layoutName, - const QByteArray &variantName); +extern QLocale q_getKeyboardLocale(const QByteArray &layoutName, const QByteArray &variantName); #endif QXIMInputContext::QXIMInputContext() @@ -407,17 +404,12 @@ QXIMInputContext::QXIMInputContext() QList<QByteArray> layoutNames = QByteArray::fromRawData(names[2], qstrlen(names[2])).split(','); QList<QByteArray> variantNames = QByteArray::fromRawData(names[3], qstrlen(names[3])).split(','); for (int i = 0; i < qMin(layoutNames.count(), variantNames.count()); ++i ) { - QLocale keyboardInputLocale; - Qt::LayoutDirection keyboardInputDirection; QByteArray variantName = variantNames.at(i); const int dashPos = variantName.indexOf("-"); if (dashPos >= 0) variantName.truncate(dashPos); - q_getLocaleAndDirection(&keyboardInputLocale, - &keyboardInputDirection, - layoutNames.at(i), - variantName); - if (keyboardInputDirection == Qt::RightToLeft) + QLocale keyboardInputLocale = q_getKeyboardLocale(layoutNames.at(i), variantName); + if (keyboardInputLocale.textDirection() == Qt::RightToLeft) qt_use_rtl_extensions = true; } } diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index c9a3e8b..52767b8 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -146,7 +146,7 @@ static void initResources() QT_BEGIN_NAMESPACE -Q_DECL_IMPORT extern void qt_call_post_routines(); +Q_CORE_EXPORT void qt_call_post_routines(); int QApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0 @@ -3544,7 +3544,7 @@ int QApplication::startDragDistance() void QApplication::setLayoutDirection(Qt::LayoutDirection direction) { - if (layout_direction == direction) + if (layout_direction == direction || direction == Qt::LayoutDirectionAuto) return; layout_direction = direction; diff --git a/src/gui/kernel/qkeymapper_mac.cpp b/src/gui/kernel/qkeymapper_mac.cpp index a7145d4..873b8f9 100644 --- a/src/gui/kernel/qkeymapper_mac.cpp +++ b/src/gui/kernel/qkeymapper_mac.cpp @@ -672,23 +672,7 @@ QKeyMapperPrivate::updateKeyboard() #endif if (iso639Code) { keyboardInputLocale = QLocale(QCFString::toQString(iso639Code)); - QString monday = keyboardInputLocale.dayName(1); - bool rtl = false; - for (int i = 0; i < monday.length(); ++i) { - switch (monday.at(i).direction()) { - default: - break; - case QChar::DirR: - case QChar::DirAL: - case QChar::DirRLE: - case QChar::DirRLO: - rtl = true; - break; - } - if (rtl) - break; - } - keyboardInputDirection = rtl ? Qt::RightToLeft : Qt::LeftToRight; + keyboardInputDirection = keyboardInputLocale.textDirection(); } else { keyboardInputLocale = QLocale::c(); keyboardInputDirection = Qt::LeftToRight; diff --git a/src/gui/kernel/qkeymapper_qws.cpp b/src/gui/kernel/qkeymapper_qws.cpp index 5b6b1c4..63bb46b 100644 --- a/src/gui/kernel/qkeymapper_qws.cpp +++ b/src/gui/kernel/qkeymapper_qws.cpp @@ -52,7 +52,7 @@ QT_USE_NAMESPACE QKeyMapperPrivate::QKeyMapperPrivate() { keyboardInputLocale = QLocale::system(); - keyboardInputDirection = Qt::RightToLeft; + keyboardInputDirection = keyboardInputLocale.textDirection(); } QKeyMapperPrivate::~QKeyMapperPrivate() diff --git a/src/gui/kernel/qkeymapper_x11.cpp b/src/gui/kernel/qkeymapper_x11.cpp index 807959c..825edbc 100644 --- a/src/gui/kernel/qkeymapper_x11.cpp +++ b/src/gui/kernel/qkeymapper_x11.cpp @@ -80,22 +80,15 @@ QT_BEGIN_NAMESPACE (((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF)) #endif -void q_getLocaleAndDirection(QLocale *locale, - Qt::LayoutDirection *direction, - const QByteArray &layoutName, - const QByteArray &variantName) +QLocale q_getKeyboardLocale(const QByteArray &layoutName, const QByteArray &variantName) { int i = 0; while (xkbLayoutData[i].layout != 0) { - if (layoutName == xkbLayoutData[i].layout && variantName == xkbLayoutData[i].variant) { - *locale = QLocale(xkbLayoutData[i].language, xkbLayoutData[i].country); - *direction = xkbLayoutData[i].direction; - return; - } + if (layoutName == xkbLayoutData[i].layout && variantName == xkbLayoutData[i].variant) + return QLocale(xkbLayoutData[i].language, xkbLayoutData[i].country); ++i; } - *locale = QLocale::c(); - *direction = Qt::LeftToRight; + return QLocale::c(); } #endif // QT_NO_XKB @@ -523,10 +516,8 @@ void QKeyMapperPrivate::clearMappings() // if (keyboardLayoutName.isEmpty()) // qWarning("Qt: unable to determine keyboard layout, please talk to qt-bugs@trolltech.com"); ? - q_getLocaleAndDirection(&keyboardInputLocale, - &keyboardInputDirection, - layoutName, - variantName); + keyboardInputLocale = q_getKeyboardLocale(layoutName, variantName); + keyboardInputDirection = keyboardInputLocale.textDirection(); #if 0 qDebug() << "keyboard input locale =" diff --git a/src/gui/kernel/qkeymapper_x11_p.cpp b/src/gui/kernel/qkeymapper_x11_p.cpp index 20fcc86..6308973 100644 --- a/src/gui/kernel/qkeymapper_x11_p.cpp +++ b/src/gui/kernel/qkeymapper_x11_p.cpp @@ -271,13 +271,13 @@ static struct { // name = is:nodeadkeys, description = Iceland { "is", "nodeadkeys", Qt::LeftToRight, QLocale::Icelandic, QLocale::Iceland }, // name = il, description = Israel - { "il", "", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel }, + { "il", "", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, // name = il:lyx, description = Israel - { "il", "lyx", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel }, + { "il", "lyx", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, // name = il:si1452, description = Israel - { "il", "si1452", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel }, + { "il", "si1452", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, // name = il:phonetic, description = Israel - { "il", "phonetic", Qt::LeftToRight, QLocale::Hebrew, QLocale::Israel }, + { "il", "phonetic", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, // name = it, description = Italy { "it", "", Qt::LeftToRight, QLocale::Italian, QLocale::Italy }, // name = it:nodeadkeys, description = Italy @@ -419,11 +419,11 @@ static struct { // name = ch:fr_sundeadkeys, description = Switzerland { "ch", "fr_sundeadkeys", Qt::LeftToRight, QLocale::French, QLocale::Switzerland }, // name = sy, description = Syria - { "sy", "", Qt::RightToLeft, QLocale::Arabic, QLocale::SyrianArabRepublic }, + { "sy", "", Qt::RightToLeft, QLocale::Syriac, QLocale::SyrianArabRepublic }, // name = sy:syc, description = Syria - { "sy", "syc", Qt::RightToLeft, QLocale::Arabic, QLocale::SyrianArabRepublic }, + { "sy", "syc", Qt::RightToLeft, QLocale::Syriac, QLocale::SyrianArabRepublic }, // name = sy:syc_phonetic, description = Syria - { "sy", "syc_phonetic", Qt::RightToLeft, QLocale::Arabic, QLocale::SyrianArabRepublic }, + { "sy", "syc_phonetic", Qt::RightToLeft, QLocale::Syriac, QLocale::SyrianArabRepublic }, // name = tj, description = Tajikistan { "tj", "", Qt::LeftToRight, QLocale::Tajik, QLocale::Tajikistan }, // name = lk, description = Sri Lanka diff --git a/src/gui/kernel/qwhatsthis.cpp b/src/gui/kernel/qwhatsthis.cpp index 6181b62..ff4641e 100644 --- a/src/gui/kernel/qwhatsthis.cpp +++ b/src/gui/kernel/qwhatsthis.cpp @@ -143,7 +143,7 @@ QT_BEGIN_NAMESPACE \sa QToolTip */ -Q_DECL_IMPORT extern void qDeleteInEventHandler(QObject *o); +Q_CORE_EXPORT void qDeleteInEventHandler(QObject *o); class QWhatsThat : public QWidget { diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 895c85d..492954a 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -67,6 +67,7 @@ # include "qt_mac_p.h" # include "qt_cocoa_helpers_mac_p.h" # include "qmainwindow.h" +# include "qtoolbar.h" #endif #if defined(Q_WS_QWS) # include "qwsdisplay_qws.h" @@ -4828,6 +4829,11 @@ void QWidget::setLayoutDirection(Qt::LayoutDirection direction) { Q_D(QWidget); + if (direction == Qt::LayoutDirectionAuto) { + unsetLayoutDirection(); + return; + } + setAttribute(Qt::WA_SetLayoutDirection); d->setLayoutDirection_helper(direction); } @@ -9711,46 +9717,58 @@ QWidget *QWidget::childAt(const QPoint &p) const QWidget *QWidgetPrivate::childAt_helper(const QPoint &p, bool ignoreChildrenInDestructor) const { - Q_Q(const QWidget); + if (children.isEmpty()) + return 0; + #ifdef Q_WS_MAC + Q_Q(const QWidget); + // Unified tool bars on the Mac require special handling since they live outside + // QMainWindow's geometry(). See commit: 35667fd45ada49269a5987c235fdedfc43e92bb8 bool includeFrame = q->isWindow() && qobject_cast<const QMainWindow *>(q) && static_cast<const QMainWindow *>(q)->unifiedTitleAndToolBarOnMac(); + if (includeFrame) + return childAtRecursiveHelper(p, ignoreChildrenInDestructor, includeFrame); #endif - if ( -#ifdef Q_WS_MAC - !includeFrame && -#endif - !q->rect().contains(p)) + if (!pointInsideRectAndMask(p)) return 0; + return childAtRecursiveHelper(p, ignoreChildrenInDestructor); +} - for (int i = children.size(); i > 0 ;) { - --i; - QWidget *w = qobject_cast<QWidget *>(children.at(i)); - if (w && !w->isWindow() && !w->isHidden() - && (w->geometry().contains(p) -#ifdef Q_WS_MAC - || (includeFrame && w->geometry().contains(qt_mac_nativeMapFromParent(w, p))) +QWidget *QWidgetPrivate::childAtRecursiveHelper(const QPoint &p, bool ignoreChildrenInDestructor, bool includeFrame) const +{ +#ifndef Q_WS_MAC + Q_UNUSED(includeFrame); #endif - )) { - if (ignoreChildrenInDestructor && w->data->in_destructor) - continue; - if (w->testAttribute(Qt::WA_TransparentForMouseEvents)) - continue; - QPoint childPoint = w->mapFromParent(p); -#ifdef Q_WS_MAC - if (includeFrame && !w->geometry().contains(p)) - childPoint = qt_mac_nativeMapFromParent(w, p); -#endif - if (QWidget *t = w->d_func()->childAt_helper(childPoint, ignoreChildrenInDestructor)) - return t; - // if WMouseNoMask is set the widget mask is ignored, if - // the widget has no mask then the WMouseNoMask flag has no - // effect - if (w->testAttribute(Qt::WA_MouseNoMask) || w->mask().contains(childPoint) - || w->mask().isEmpty()) - return w; + for (int i = children.size() - 1; i >= 0; --i) { + QWidget *child = qobject_cast<QWidget *>(children.at(i)); + if (!child || child->isWindow() || child->isHidden() || child->testAttribute(Qt::WA_TransparentForMouseEvents) + || (ignoreChildrenInDestructor && child->data->in_destructor)) { + continue; } + + // Map the point 'p' from parent coordinates to child coordinates. + QPoint childPoint = p; +#ifdef Q_WS_MAC + // 'includeFrame' is true if the child's parent is a top-level QMainWindow with an unified tool bar. + // An unified tool bar on the Mac lives outside QMainWindow's geometry(), so a normal + // QWidget::mapFromParent won't do the trick. + if (includeFrame && qobject_cast<QToolBar *>(child)) + childPoint = qt_mac_nativeMapFromParent(child, p); + else +#endif + childPoint -= child->data->crect.topLeft(); + + // Check if the point hits the child. + if (!child->d_func()->pointInsideRectAndMask(childPoint)) + continue; + + // Do the same for the child's descendants. + if (QWidget *w = child->d_func()->childAtRecursiveHelper(childPoint, ignoreChildrenInDestructor)) + return w; + + // We have found our target; namely the child at position 'p'. + return child; } return 0; } diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 1928599..280712a 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2688,6 +2688,7 @@ QWidget::macCGHandle() const void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); + d->aboutToDestroy(); if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); @@ -3994,10 +3995,10 @@ static void qt_mac_update_widget_position(QWidget *q, QRect oldRect, QRect newRe (oldRect.isValid() == false || newRect.isValid() == false) || // the position update is a part of a drag-and-drop operation - QDragManager::self()->object || - - // we are on Panther (no HIViewSetNeedsDisplayInRect) - QSysInfo::MacintoshVersion < QSysInfo::MV_10_4 + QDragManager::self()->object || + + // we are on Panther (no HIViewSetNeedsDisplayInRect) + QSysInfo::MacintoshVersion < QSysInfo::MV_10_4 ){ HIViewSetFrame(view, &bounds); return; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 49a2dc8..587d7fb 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -542,13 +542,20 @@ public: bool setMinimumSize_helper(int &minw, int &minh); bool setMaximumSize_helper(int &maxw, int &maxh); void setConstraints_sys(); + bool pointInsideRectAndMask(const QPoint &) const; QWidget *childAt_helper(const QPoint &, bool) const; + QWidget *childAtRecursiveHelper(const QPoint &p, bool, bool includeFrame = false) const; void updateGeometry_helper(bool forceUpdate); void getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const; void setLayoutItemMargins(int left, int top, int right, int bottom); void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0); + // aboutToDestroy() is called just before the contents of + // QWidget::destroy() is executed. It's used to signal QWidget + // sub-classes that their internals are about to be released. + virtual void aboutToDestroy() {} + QInputContext *inputContext() const; inline QWidget *effectiveFocusWidget() { QWidget *w = q_func(); @@ -968,6 +975,13 @@ inline void QWidgetPrivate::setSharedPainter(QPainter *painter) x->sharedPainter = painter; } +inline bool QWidgetPrivate::pointInsideRectAndMask(const QPoint &p) const +{ + Q_Q(const QWidget); + return q->rect().contains(p) && (!extra || !extra->hasMask || q->testAttribute(Qt::WA_MouseNoMask) + || extra->mask.contains(p)); +} + inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const { Q_Q(const QWidget); diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp index b827e8b..3145136 100644 --- a/src/gui/kernel/qwidget_qws.cpp +++ b/src/gui/kernel/qwidget_qws.cpp @@ -256,7 +256,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool /*destro void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); - + d->aboutToDestroy(); if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 86b858d..68f9470 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -1177,6 +1177,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); + d->aboutToDestroy(); if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(geometry()); d->deactivateWidgetCleanup(); diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index a7e66bf..9c65aa0 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -544,6 +544,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); + d->aboutToDestroy(); if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 43f510c..e01489f 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -1023,6 +1023,7 @@ bool QWidgetPrivate::isBackgroundInherited() const void QWidget::destroy(bool destroyWindow, bool destroySubWindows) { Q_D(QWidget); + d->aboutToDestroy(); if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); d->deactivateWidgetCleanup(); diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 48974e8..08e14fb 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -68,6 +68,7 @@ // #include <private/qrasterizer_p.h> #include <private/qimage_p.h> #include <private/qstatictext_p.h> +#include "qmemrotate_p.h" #include "qpaintengine_raster_p.h" // #include "qbezier_p.h" @@ -2521,6 +2522,58 @@ QRectF qt_mapRect_non_normalizing(const QRectF &r, const QTransform &t) return QRectF(r.topLeft() * t, r.bottomRight() * t); } +namespace { + enum RotationType { + Rotation90, + Rotation180, + Rotation270, + NoRotation + }; + + inline RotationType qRotationType(const QTransform &transform) + { + QTransform::TransformationType type = transform.type(); + + if (type > QTransform::TxRotate) + return NoRotation; + + if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(-1)) + && qFuzzyCompare(transform.m21(), qreal(1)) && qFuzzyIsNull(transform.m22())) + return Rotation90; + + if (type == QTransform::TxScale && qFuzzyCompare(transform.m11(), qreal(-1)) && qFuzzyIsNull(transform.m12()) + && qFuzzyIsNull(transform.m21()) && qFuzzyCompare(transform.m22(), qreal(-1))) + return Rotation180; + + if (type == QTransform::TxRotate && qFuzzyIsNull(transform.m11()) && qFuzzyCompare(transform.m12(), qreal(1)) + && qFuzzyCompare(transform.m21(), qreal(-1)) && qFuzzyIsNull(transform.m22())) + return Rotation270; + + return NoRotation; + } + + template <typename T> void memRotate(RotationType type, const T *srcBase, int w, int h, int sbpl, T *dstBase, int dbpl) + { + switch (type) { + case Rotation90: + qt_memrotate90(srcBase, w, h, sbpl, dstBase, dbpl); + break; + case Rotation180: + qt_memrotate180(srcBase, w, h, sbpl, dstBase, dbpl); + break; + case Rotation270: + qt_memrotate270(srcBase, w, h, sbpl, dstBase, dbpl); + break; + case NoRotation: + break; + } + } + + inline bool isPixelAligned(const QRectF &rect) { + return QRectF(rect.toRect()) == rect; + } +} + /*! \reimp */ @@ -2582,6 +2635,58 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe const QClipData *clip = d->clip(); + if (s->matrix.type() > QTransform::TxTranslate + && !stretch_sr + && (!clip || clip->hasRectClip) + && s->intOpacity == 256 + && (d->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver + || d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source) + && d->rasterBuffer->format == img.format() + && (d->rasterBuffer->format == QImage::Format_RGB16 + || d->rasterBuffer->format == QImage::Format_RGB32 + || (d->rasterBuffer->format == QImage::Format_ARGB32_Premultiplied + && d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source))) + { + RotationType rotationType = qRotationType(s->matrix); + + if (rotationType != NoRotation && img.rect().contains(sr.toAlignedRect())) { + QRectF transformedTargetRect = s->matrix.mapRect(r); + + if ((!(s->renderHints & QPainter::SmoothPixmapTransform) && !(s->renderHints & QPainter::Antialiasing)) + || (isPixelAligned(transformedTargetRect) && isPixelAligned(sr))) + { + QRect clippedTransformedTargetRect = transformedTargetRect.toRect().intersected(clip ? clip->clipRect : d->deviceRect); + if (clippedTransformedTargetRect.isNull()) + return; + + QRectF clippedTargetRect = s->matrix.inverted().mapRect(QRectF(clippedTransformedTargetRect)); + + QRect clippedSourceRect + = QRectF(sr.x() + clippedTargetRect.x() - r.x(), sr.y() + clippedTargetRect.y() - r.y(), + clippedTargetRect.width(), clippedTargetRect.height()).toRect(); + + uint dbpl = d->rasterBuffer->bytesPerLine(); + uint sbpl = img.bytesPerLine(); + + uchar *dst = d->rasterBuffer->buffer(); + uint bpp = img.depth() >> 3; + + const uchar *srcBase = img.bits() + clippedSourceRect.y() * sbpl + clippedSourceRect.x() * bpp; + uchar *dstBase = dst + clippedTransformedTargetRect.y() * dbpl + clippedTransformedTargetRect.x() * bpp; + + uint cw = clippedSourceRect.width(); + uint ch = clippedSourceRect.height(); + + if (d->rasterBuffer->format == QImage::Format_RGB16) + memRotate(rotationType, (quint16 *)srcBase, cw, ch, sbpl, (quint16 *)dstBase, dbpl); + else + memRotate(rotationType, (quint32 *)srcBase, cw, ch, sbpl, (quint32 *)dstBase, dbpl); + + return; + } + } + } + if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) { if (s->flags.fast_images) { diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 97f754d..e8c4599 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1564,7 +1564,6 @@ void QPainter::initFrom(const QWidget *widget) d->engine->setDirty(QPaintEngine::DirtyBrush); d->engine->setDirty(QPaintEngine::DirtyFont); } - d->state->layoutDirection = widget->layoutDirection(); } @@ -1874,7 +1873,7 @@ bool QPainter::begin(QPaintDevice *pd) QWidget *widget = static_cast<QWidget *>(d->original_device); initFrom(widget); } else { - d->state->layoutDirection = QApplication::layoutDirection(); + d->state->layoutDirection = Qt::LayoutDirectionAuto; // make sure we have a font compatible with the paintdevice d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device()); } @@ -8056,7 +8055,10 @@ start_lengthVariant: Sets the layout direction used by the painter when drawing text, to the specified \a direction. - \sa layoutDirection(), drawText(), {QPainter#Settings}{Settings} + The default is Qt::LayoutDirectionAuto, which will implicitly determine the + direction from the text drawn. + + \sa QTextOption::setTextDirection(), layoutDirection(), drawText(), {QPainter#Settings}{Settings} */ void QPainter::setLayoutDirection(Qt::LayoutDirection direction) { @@ -8068,12 +8070,12 @@ void QPainter::setLayoutDirection(Qt::LayoutDirection direction) /*! Returns the layout direction used by the painter when drawing text. - \sa setLayoutDirection(), drawText(), {QPainter#Settings}{Settings} + \sa QTextOption::textDirection(), setLayoutDirection(), drawText(), {QPainter#Settings}{Settings} */ Qt::LayoutDirection QPainter::layoutDirection() const { Q_D(const QPainter); - return d->state ? d->state->layoutDirection : Qt::LeftToRight; + return d->state ? d->state->layoutDirection : Qt::LayoutDirectionAuto; } QPainterState::QPainterState(const QPainterState *s) diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 423cce9..47b7758 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -1626,7 +1626,7 @@ static QPainterPath mapProjective(const QTransform &transform, const QPainterPat QPainterPath QTransform::map(const QPainterPath &path) const { TransformationType t = inline_type(); - if (t == TxNone || path.isEmpty()) + if (t == TxNone || path.elementCount() == 0) return path; if (t >= TxProject) diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp index d6ac3aa..23849bc 100644 --- a/src/gui/text/qtextcursor.cpp +++ b/src/gui/text/qtextcursor.cpp @@ -362,7 +362,7 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor QTextBlock blockIt = block(); if (op >= QTextCursor::Left && op <= QTextCursor::WordRight - && blockIt.blockFormat().layoutDirection() == Qt::RightToLeft) { + && blockIt.textDirection() == Qt::RightToLeft) { if (op == QTextCursor::Left) op = QTextCursor::NextCharacter; else if (op == QTextCursor::Right) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index c7a9756..48aee8f 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -2496,13 +2496,10 @@ void QTextHtmlExporter::emitBlockAttributes(const QTextBlock &block) QTextBlockFormat format = block.blockFormat(); emitAlignment(format.alignment()); - Qt::LayoutDirection dir = format.layoutDirection(); - if (dir == Qt::LeftToRight) { - // assume default to not bloat the html too much - // html += QLatin1String(" dir='ltr'"); - } else { + // assume default to not bloat the html too much + // html += QLatin1String(" dir='ltr'"); + if (block.textDirection() == Qt::RightToLeft) html += QLatin1String(" dir='rtl'"); - } QLatin1String style(" style=\""); html += style; diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index eeb66ce..ff14490 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -1369,9 +1369,7 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p QTextLine firstLine = layout->lineAt(0); Q_ASSERT(firstLine.isValid()); QPointF pos = (offset + layout->position()).toPoint(); - Qt::LayoutDirection dir = docPrivate->defaultTextOption.textDirection(); - if (blockFormat.hasProperty(QTextFormat::LayoutDirection)) - dir = blockFormat.layoutDirection(); + Qt::LayoutDirection dir = bl.textDirection(); { QRectF textRect = firstLine.naturalTextRect(); pos += textRect.topLeft().toPoint(); @@ -2530,9 +2528,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi //QTextFrameData *fd = data(layoutStruct->frame); - Qt::LayoutDirection dir = docPrivate->defaultTextOption.textDirection(); - if (blockFormat.hasProperty(QTextFormat::LayoutDirection)) - dir = blockFormat.layoutDirection(); + Qt::LayoutDirection dir = bl.textDirection(); QFixed extraMargin; if (docPrivate->defaultTextOption.flags() & QTextOption::AddSpaceForLineAndParagraphSeparators) { diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 3486264..ac1fffd 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1404,7 +1404,10 @@ void QTextEngine::itemize() const #else bool ignore = ignoreBidi; #endif - if (!ignore && option.textDirection() == Qt::LeftToRight) { + + bool rtl = isRightToLeft(); + + if (!ignore && !rtl) { ignore = true; const QChar *start = layoutData->string.unicode(); const QChar * const end = start + length; @@ -1420,7 +1423,7 @@ void QTextEngine::itemize() const QVarLengthArray<QScriptAnalysis, 4096> scriptAnalysis(length); QScriptAnalysis *analysis = scriptAnalysis.data(); - QBidiControl control(option.textDirection() == Qt::RightToLeft); + QBidiControl control(rtl); if (ignore) { memset(analysis, 0, length*sizeof(QScriptAnalysis)); @@ -1515,6 +1518,23 @@ void QTextEngine::itemize() const resolveAdditionalFormats(); } +bool QTextEngine::isRightToLeft() const +{ + switch (option.textDirection()) { + case Qt::LeftToRight: + return false; + case Qt::RightToLeft: + return true; + default: + break; + } + // this places the cursor in the right position depending on the keyboard layout + if (layoutData->string.isEmpty()) + return QApplication::keyboardInputDirection() == Qt::RightToLeft; + return layoutData->string.isRightToLeft(); +} + + int QTextEngine::findItem(int strPos) const { itemize(); @@ -2511,7 +2531,7 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const QList<QTextOption::Tab> tabArray = option.tabs(); if (!tabArray.isEmpty()) { - if (option.textDirection() == Qt::RightToLeft) { // rebase the tabArray positions. + if (isRightToLeft()) { // rebase the tabArray positions. QList<QTextOption::Tab> newTabs; QList<QTextOption::Tab>::Iterator iter = tabArray.begin(); while(iter != tabArray.end()) { diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 00b1392..908a0ec 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -458,6 +458,7 @@ public: void validate() const; void itemize() const; + bool isRightToLeft() const; static void bidiReorder(int numRuns, const quint8 *levels, int *visualOrder); const HB_CharAttributes *attributes() const; diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index 140cf43..46db253 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -900,11 +900,14 @@ bool QTextFormat::boolProperty(int propertyId) const */ int QTextFormat::intProperty(int propertyId) const { + // required, since the default layout direction has to be LayoutDirectionAuto, which is not integer 0 + int def = (propertyId == QTextFormat::LayoutDirection) ? int(Qt::LayoutDirectionAuto) : 0; + if (!d) - return 0; + return def; const QVariant prop = d->property(propertyId); if (prop.userType() != QVariant::Int) - return 0; + return def; return prop.toInt(); } diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index f5e252c..ddf9411 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -69,7 +69,7 @@ static inline QFixed leadingSpaceWidth(QTextEngine *eng, const QScriptLine &line if (!line.hasTrailingSpaces || (eng->option.flags() & QTextOption::IncludeTrailingSpaces) || !(eng->option.alignment() & Qt::AlignRight) - || (eng->option.textDirection() != Qt::RightToLeft)) + || !eng->isRightToLeft()) return QFixed(); int pos = line.length; @@ -86,7 +86,7 @@ static QFixed alignLine(QTextEngine *eng, const QScriptLine &line) // if width is QFIXED_MAX that means we used setNumColumns() and that implicitly makes this line left aligned. if (!line.justified && line.width != QFIXED_MAX) { int align = eng->option.alignment(); - if (align & Qt::AlignJustify && eng->option.textDirection() == Qt::RightToLeft) + if (align & Qt::AlignJustify && eng->isRightToLeft()) align = Qt::AlignRight; if (align & Qt::AlignRight) x = line.width - (line.textAdvance + leadingSpaceWidth(eng, line)); @@ -1337,7 +1337,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition int itm = d->findItem(cursorPosition - 1); QFixed base = sl.base(); QFixed descent = sl.descent; - bool rightToLeft = (d->option.textDirection() == Qt::RightToLeft); + bool rightToLeft = d->isRightToLeft(); if (itm >= 0) { const QScriptItem &si = d->layoutData->items.at(itm); if (si.ascent > 0) diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp index 2986ee7..a0ff520 100644 --- a/src/gui/text/qtextlist.cpp +++ b/src/gui/text/qtextlist.cpp @@ -262,7 +262,7 @@ QString QTextList::itemText(const QTextBlock &blockIt) const default: Q_ASSERT(false); } - if (blockFormat.layoutDirection() == Qt::RightToLeft) + if (blockIt.textDirection() == Qt::RightToLeft) return result.prepend(QLatin1Char('.')); return result + QLatin1Char('.'); } diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index 088eb98..f386871 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -1140,6 +1140,49 @@ int QTextBlock::charFormatIndex() const } /*! + \since 4.7 + + Returns the resolved text direction. + + If the block has no explicit direction set, it will resolve the + direction from the blocks content. Returns either Qt::LeftToRight + or Qt::RightToLeft. + + \sa QTextBlock::layoutDirection(), QString::isRightToLeft(), Qt::LayoutDirection +*/ +Qt::LayoutDirection QTextBlock::textDirection() const +{ + Qt::LayoutDirection dir = blockFormat().layoutDirection(); + if (dir != Qt::LayoutDirectionAuto) + return dir; + + const QString buffer = p->buffer(); + + const int pos = position(); + QTextDocumentPrivate::FragmentIterator it = p->find(pos); + QTextDocumentPrivate::FragmentIterator end = p->find(pos + length() - 1); // -1 to omit the block separator char + for (; it != end; ++it) { + const QTextFragmentData * const frag = it.value(); + const QChar *p = buffer.constData() + frag->stringPosition; + const QChar * const end = p + frag->size_array[0]; + while (p < end) { + switch(QChar::direction(p->unicode())) + { + case QChar::DirL: + return Qt::LeftToRight; + case QChar::DirR: + case QChar::DirAL: + return Qt::RightToLeft; + default: + break; + } + ++p; + } + } + return Qt::LeftToRight; +} + +/*! Returns the block's contents as plain text. \sa length() charFormat() blockFormat() diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h index 67f67d8..a573a26 100644 --- a/src/gui/text/qtextobject.h +++ b/src/gui/text/qtextobject.h @@ -221,6 +221,8 @@ public: QTextCharFormat charFormat() const; int charFormatIndex() const; + Qt::LayoutDirection textDirection() const; + QString text() const; const QTextDocument *document() const; diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp index c1e254c..3b02ebe 100644 --- a/src/gui/text/qtextoption.cpp +++ b/src/gui/text/qtextoption.cpp @@ -65,7 +65,7 @@ QTextOption::QTextOption() tab(-1), d(0) { - direction = QApplication::layoutDirection(); + direction = Qt::LayoutDirectionAuto; } /*! diff --git a/src/gui/text/qtextoption.h b/src/gui/text/qtextoption.h index 1381ed1..fa8c6f2 100644 --- a/src/gui/text/qtextoption.h +++ b/src/gui/text/qtextoption.h @@ -134,8 +134,8 @@ private: uint align : 8; uint wordWrap : 4; uint design : 1; - uint direction : 1; - uint unused : 19; + uint direction : 2; + uint unused : 18; uint f; qreal tab; QTextOptionPrivate *d; diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 5da1831..7068f62 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -78,7 +78,7 @@ class Q_GUI_EXPORT QLineControl : public QObject public: QLineControl(const QString &txt = QString()) - : m_cursor(0), m_preeditCursor(0), m_cursorWidth(0), m_layoutDirection(Qt::LeftToRight), + : m_cursor(0), m_preeditCursor(0), m_cursorWidth(0), m_layoutDirection(Qt::LayoutDirectionAuto), m_hideCursor(false), m_separator(0), m_readOnly(0), m_dragEnabled(0), m_echoMode(0), m_textDirty(0), m_selDirty(0), m_validInput(1), m_blinkStatus(0), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), @@ -272,7 +272,14 @@ public: QChar passwordCharacter() const { return m_passwordCharacter; } void setPasswordCharacter(const QChar &character) { m_passwordCharacter = character; updateDisplayText(); } - Qt::LayoutDirection layoutDirection() const { return m_layoutDirection; } + Qt::LayoutDirection layoutDirection() const { + if (m_layoutDirection == Qt::LayoutDirectionAuto) { + if (m_text.isEmpty()) + return QApplication::keyboardInputDirection(); + return m_text.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; + } + return m_layoutDirection; + } void setLayoutDirection(Qt::LayoutDirection direction) { if (direction != m_layoutDirection) { diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index c1c4abf..1bffde1 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -1860,7 +1860,7 @@ void QLineEdit::paintEvent(QPaintEvent *) p.setClipRect(r); QFontMetrics fm = fontMetrics(); - Qt::Alignment va = QStyle::visualAlignment(layoutDirection(), QFlag(d->alignment)); + Qt::Alignment va = QStyle::visualAlignment(d->control->layoutDirection(), QFlag(d->alignment)); switch (va & Qt::AlignVertical_Mask) { case Qt::AlignBottom: d->vscroll = r.y() + r.height() - fm.height() - d->verticalMargin; @@ -2161,9 +2161,6 @@ void QLineEdit::changeEvent(QEvent *ev) } update(); break; - case QEvent::LayoutDirectionChange: - d->control->setLayoutDirection(layoutDirection()); - break; default: break; } |