Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/painting/qdrawutil.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtGui module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4646#include "qpainter.h"
    4747#include "qpalette.h"
     48#include <private/qpaintengineex_p.h>
     49#include <qvarlengtharray.h>
     50#include <qmath.h>
    4851
    4952QT_BEGIN_NAMESPACE
     53
     54/*!
     55    \headerfile <qdrawutil.h>
     56    \title Drawing Utility Functions
     57
     58    \sa QPainter
     59*/
    5060
    5161/*!
     
    5363                     const QPalette &palette, bool sunken,
    5464                     int lineWidth, int midLineWidth)
    55     \relates QPainter
     65    \relates <qdrawutil.h>
    5666
    5767    Draws a horizontal (\a y1 == \a y2) or vertical (\a x1 == \a x2)
     
    167177                     int lineWidth, int midLineWidth,
    168178                     const QBrush *fill)
    169     \relates QPainter
     179    \relates <qdrawutil.h>
    170180
    171181    Draws the shaded rectangle beginning at (\a x, \a y) with the
     
    271281                      const QPalette &palette, bool sunken,
    272282                      int lineWidth, const QBrush *fill)
    273     \relates QPainter
     283    \relates <qdrawutil.h>
    274284
    275285    Draws the shaded panel beginning at (\a x, \a y) with the given \a
     
    407417                     const QPalette &palette, bool sunken,
    408418                     const QBrush *fill)
    409     \relates QPainter
     419    \relates <qdrawutil.h>
    410420
    411421    Draws the Windows-style button specified by the given point (\a x,
     
    445455                    const QPalette &palette, bool        sunken,
    446456                    const QBrush *fill)
    447     \relates QPainter
     457    \relates <qdrawutil.h>
    448458
    449459    Draws the Windows-style panel specified by the given point(\a x,
     
    484494    \fn void qDrawPlainRect(QPainter *painter, int x, int y, int width, int height, const QColor &lineColor,
    485495                     int lineWidth, const QBrush *fill)
    486     \relates QPainter
     496    \relates <qdrawutil.h>
    487497
    488498    Draws the plain rectangle beginning at (\a x, \a y) with the given
     
    533543    \fn void qDrawShadeLine(QPainter *painter, const QPoint &p1, const QPoint &p2,
    534544             const QPalette &palette, bool sunken, int lineWidth, int midLineWidth)
    535     \relates QPainter
     545    \relates <qdrawutil.h>
    536546    \overload
    537547
     
    573583    \fn void qDrawShadeRect(QPainter *painter, const QRect &rect, const QPalette &palette,
    574584             bool sunken, int lineWidth, int midLineWidth, const QBrush *fill)
    575     \relates QPainter
     585    \relates <qdrawutil.h>
    576586    \overload
    577587
     
    613623    \fn void qDrawShadePanel(QPainter *painter, const QRect &rect, const QPalette &palette,
    614624             bool sunken, int lineWidth, const QBrush *fill)
    615     \relates QPainter
     625    \relates <qdrawutil.h>
    616626    \overload
    617627
     
    649659    \fn void qDrawWinButton(QPainter *painter, const QRect &rect, const QPalette &palette,
    650660             bool sunken, const QBrush *fill)
    651     \relates QPainter
     661    \relates <qdrawutil.h>
    652662    \overload
    653663
     
    707717/*!
    708718    \fn void qDrawPlainRect(QPainter *painter, const QRect &rect, const QColor &lineColor, int lineWidth, const QBrush *fill)
    709     \relates QPainter
     719    \relates <qdrawutil.h>
    710720    \overload
    711721
     
    10091019#ifndef QT_NO_IMAGE_HEURISTIC_MASK
    10101020            } else {                                // color pixmap, no mask
    1011                 QString k;
    1012                 k.sprintf("$qt-drawitem-%llx", pm.cacheKey());
     1021                QString k = QString::fromLatin1("$qt-drawitem-%1").arg(pm.cacheKey());
    10131022                if (!QPixmapCache::find(k, pm)) {
    10141023                    pm = pm.createHeuristicMask();
     
    10391048#endif
    10401049
     1050/*!
     1051    \class QTileRules
     1052    \since 4.6
     1053
     1054    Holds the rules used to draw a pixmap or image split into nine segments,
     1055    similar to \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}.
     1056
     1057    \sa Qt::TileRule, QMargins
     1058*/
     1059
     1060/*! \fn QTileRules::QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule)
     1061  Constructs a QTileRules with the given \a horizontalRule and
     1062  \a verticalRule.
     1063 */
     1064
     1065/*! \fn QTileRules::QTileRules(Qt::TileRule rule)
     1066  Constructs a QTileRules with the given \a rule used for both
     1067  the horizontal rule and the vertical rule.
     1068 */
     1069
     1070/*!
     1071    \fn void qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap)
     1072    \relates <qdrawutil.h>
     1073    \since 4.6
     1074    \overload
     1075
     1076    \brief The qDrawBorderPixmap function is for drawing a pixmap into
     1077    the margins of a rectangle.
     1078
     1079    Draws the given \a pixmap into the given \a target rectangle, using the
     1080    given \a painter. The pixmap will be split into nine segments and drawn
     1081    according to the \a margins structure.
     1082*/
     1083
     1084typedef QVarLengthArray<QDrawPixmaps::Data, 16> QDrawPixmapsDataArray;
     1085
     1086/*!
     1087    \since 4.6
     1088
     1089    Draws the indicated \a sourceRect rectangle from the given \a pixmap into
     1090    the given \a targetRect rectangle, using the given \a painter. The pixmap
     1091    will be split into nine segments according to the given \a targetMargins
     1092    and \a sourceMargins structures. Finally, the pixmap will be drawn
     1093    according to the given \a rules.
     1094
     1095    This function is used to draw a scaled pixmap, similar to
     1096    \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}
     1097
     1098    \sa Qt::TileRule, QTileRules, QMargins
     1099*/
     1100
     1101void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins,
     1102                       const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins,
     1103                       const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints)
     1104{
     1105    QDrawPixmaps::Data d;
     1106    d.opacity = 1.0;
     1107    d.rotation = 0.0;
     1108
     1109    QDrawPixmapsDataArray opaqueData;
     1110    QDrawPixmapsDataArray translucentData;
     1111
     1112    // source center
     1113    const int sourceCenterTop = sourceRect.top() + sourceMargins.top();
     1114    const int sourceCenterLeft = sourceRect.left() + sourceMargins.left();
     1115    const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1;
     1116    const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1;
     1117    const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft;
     1118    const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop;
     1119    // target center
     1120    const int targetCenterTop = targetRect.top() + targetMargins.top();
     1121    const int targetCenterLeft = targetRect.left() + targetMargins.left();
     1122    const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1;
     1123    const int targetCenterRight = targetRect.right() - targetMargins.right() + 1;
     1124    const int targetCenterWidth = targetCenterRight - targetCenterLeft;
     1125    const int targetCenterHeight = targetCenterBottom - targetCenterTop;
     1126
     1127    QVarLengthArray<qreal, 16> xTarget; // x-coordinates of target rectangles
     1128    QVarLengthArray<qreal, 16> yTarget; // y-coordinates of target rectangles
     1129
     1130    int columns = 3;
     1131    int rows = 3;
     1132    if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0)
     1133        columns = qMax(3, 2 + qCeil(targetCenterWidth / qreal(sourceCenterWidth)));
     1134    if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0)
     1135        rows = qMax(3, 2 + qCeil(targetCenterHeight / qreal(sourceCenterHeight)));
     1136
     1137    xTarget.resize(columns + 1);
     1138    yTarget.resize(rows + 1);
     1139
     1140    xTarget[0] = targetRect.left();
     1141    xTarget[1] = targetCenterLeft;
     1142    xTarget[columns - 1] = targetCenterRight;
     1143    xTarget[columns] = targetRect.left() + targetRect.width();
     1144
     1145    yTarget[0] = targetRect.top();
     1146    yTarget[1] = targetCenterTop;
     1147    yTarget[rows - 1] = targetCenterBottom;
     1148    yTarget[rows] = targetRect.top() + targetRect.height();
     1149
     1150    qreal dx = targetCenterWidth;
     1151    qreal dy = targetCenterHeight;
     1152
     1153    switch (rules.horizontal) {
     1154    case Qt::StretchTile:
     1155        dx = targetCenterWidth;
     1156        break;
     1157    case Qt::RepeatTile:
     1158        dx = sourceCenterWidth;
     1159        break;
     1160    case Qt::RoundTile:
     1161        dx = targetCenterWidth / qreal(columns - 2);
     1162        break;
     1163    }
     1164
     1165    for (int i = 2; i < columns - 1; ++i)
     1166        xTarget[i] = xTarget[i - 1] + dx;
     1167
     1168    switch (rules.vertical) {
     1169    case Qt::StretchTile:
     1170        dy = targetCenterHeight;
     1171        break;
     1172    case Qt::RepeatTile:
     1173        dy = sourceCenterHeight;
     1174        break;
     1175    case Qt::RoundTile:
     1176        dy = targetCenterHeight / qreal(rows - 2);
     1177        break;
     1178    }
     1179
     1180    for (int i = 2; i < rows - 1; ++i)
     1181        yTarget[i] = yTarget[i - 1] + dy;
     1182
     1183    // corners
     1184    if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left
     1185        d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
     1186        d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
     1187        d.source = QRectF(sourceRect.left(), sourceRect.top(), sourceMargins.left(), sourceMargins.top());
     1188        d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
     1189        d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
     1190        if (hints & QDrawBorderPixmap::OpaqueTopLeft)
     1191            opaqueData.append(d);
     1192        else
     1193            translucentData.append(d);
     1194    }
     1195    if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right
     1196        d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
     1197        d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
     1198        d.source = QRectF(sourceCenterRight, sourceRect.top(), sourceMargins.right(), sourceMargins.top());
     1199        d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
     1200        d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
     1201        if (hints & QDrawBorderPixmap::OpaqueTopRight)
     1202            opaqueData.append(d);
     1203        else
     1204            translucentData.append(d);
     1205    }
     1206    if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left
     1207        d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
     1208        d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
     1209        d.source = QRectF(sourceRect.left(), sourceCenterBottom, sourceMargins.left(), sourceMargins.bottom());
     1210        d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
     1211        d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
     1212        if (hints & QDrawBorderPixmap::OpaqueBottomLeft)
     1213            opaqueData.append(d);
     1214        else
     1215            translucentData.append(d);
     1216    }
     1217    if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right
     1218        d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
     1219        d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
     1220        d.source = QRectF(sourceCenterRight, sourceCenterBottom, sourceMargins.right(), sourceMargins.bottom());
     1221        d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
     1222        d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
     1223        if (hints & QDrawBorderPixmap::OpaqueBottomRight)
     1224            opaqueData.append(d);
     1225        else
     1226            translucentData.append(d);
     1227    }
     1228
     1229    // horizontal edges
     1230    if (targetCenterWidth > 0 && sourceCenterWidth > 0) {
     1231        if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
     1232            QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
     1233            d.source = QRectF(sourceCenterLeft, sourceRect.top(), sourceCenterWidth, sourceMargins.top());
     1234            d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
     1235            d.scaleX = dx / d.source.width();
     1236            d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
     1237            for (int i = 1; i < columns - 1; ++i) {
     1238                d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
     1239                data.append(d);
     1240            }
     1241            if (rules.horizontal == Qt::RepeatTile)
     1242                data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
     1243        }
     1244        if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
     1245            QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
     1246            d.source = QRectF(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom());;
     1247            d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
     1248            d.scaleX = dx / d.source.width();
     1249            d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
     1250            for (int i = 1; i < columns - 1; ++i) {
     1251                d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
     1252                data.append(d);
     1253            }
     1254            if (rules.horizontal == Qt::RepeatTile)
     1255                data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
     1256        }
     1257    }
     1258
     1259    // vertical edges
     1260    if (targetCenterHeight > 0 && sourceCenterHeight > 0) {
     1261        if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
     1262            QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
     1263            d.source = QRectF(sourceRect.left(), sourceCenterTop, sourceMargins.left(), sourceCenterHeight);
     1264            d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
     1265            d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
     1266            d.scaleY = dy / d.source.height();
     1267            for (int i = 1; i < rows - 1; ++i) {
     1268                d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
     1269                data.append(d);
     1270            }
     1271            if (rules.vertical == Qt::RepeatTile)
     1272                data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
     1273        }
     1274        if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
     1275            QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
     1276            d.source = QRectF(sourceCenterRight, sourceCenterTop, sourceMargins.right(), sourceCenterHeight);
     1277            d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
     1278            d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
     1279            d.scaleY = dy / d.source.height();
     1280            for (int i = 1; i < rows - 1; ++i) {
     1281                d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
     1282                data.append(d);
     1283            }
     1284            if (rules.vertical == Qt::RepeatTile)
     1285                data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
     1286        }
     1287    }
     1288
     1289    // center
     1290    if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
     1291        QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
     1292        d.source = QRectF(sourceCenterLeft, sourceCenterTop, sourceCenterWidth, sourceCenterHeight);
     1293        d.scaleX = dx / d.source.width();
     1294        d.scaleY = dy / d.source.height();
     1295
     1296        qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX;
     1297        qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY;
     1298
     1299        for (int j = 1; j < rows - 1; ++j) {
     1300            d.point.setY(0.5 * (yTarget[j + 1] + yTarget[j]));
     1301            for (int i = 1; i < columns - 1; ++i) {
     1302                d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
     1303                data.append(d);
     1304            }
     1305            if (rules.horizontal == Qt::RepeatTile)
     1306                data[data.size() - 1].source.setWidth(repeatWidth);
     1307        }
     1308        if (rules.vertical == Qt::RepeatTile) {
     1309            for (int i = 1; i < columns - 1; ++i)
     1310                data[data.size() - i].source.setHeight(repeatHeight);
     1311        }
     1312    }
     1313
     1314    if (opaqueData.size())
     1315        qDrawPixmaps(painter, opaqueData.data(), opaqueData.size(), pixmap, QDrawPixmaps::OpaqueHint);
     1316    if (translucentData.size())
     1317        qDrawPixmaps(painter, translucentData.data(), translucentData.size(), pixmap);
     1318}
     1319
     1320/*!
     1321    \class QDrawPixmaps::Data
     1322    \since 4.6
     1323    \internal
     1324
     1325    This structure is used with the qDrawPixmaps() function.
     1326
     1327    QPointF point:  Specifies the center of the target rectangle.
     1328    QRectF source:  Specifies the source rectangle in the pixmap passed into the qDrawPixmaps() call.
     1329    qreal scaleX:   Specifies the horizontal scale of the target rectangle.
     1330    qreal scaleY:   Specifies the vertical scale of the target rectangle.
     1331    qreal rotation: Specifies the rotation of the target rectangle in degrees.
     1332                    The target rectangle is rotated after scaling.
     1333    qreal opacity:  Specifies the opacity of the rectangle.
     1334*/
     1335
     1336/*!
     1337    \enum QDrawPixmaps::DrawingHint
     1338    \internal
     1339*/
     1340
     1341/*!
     1342    \internal
     1343    \since 4.6
     1344
     1345    This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap, at multiple positions
     1346    with different scale, rotation and opacity on \a painter. \a drawingData is an array of \a
     1347    dataCount elements specifying the parameters used to draw each pixmap instance.
     1348    This can be used for example to implement a particle system.
     1349*/
     1350void qDrawPixmaps(QPainter *painter, const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
     1351{
     1352    QPaintEngine *engine = painter->paintEngine();
     1353    if (!engine)
     1354        return;
     1355
     1356    if (engine->isExtended()) {
     1357        static_cast<QPaintEngineEx *>(engine)->drawPixmaps(drawingData, dataCount, pixmap, hints);
     1358    } else {
     1359        qreal oldOpacity = painter->opacity();
     1360        QTransform oldTransform = painter->transform();
     1361
     1362        for (int i = 0; i < dataCount; ++i) {
     1363            QTransform transform = oldTransform;
     1364            transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
     1365            transform.rotate(drawingData[i].rotation);
     1366            painter->setOpacity(oldOpacity * drawingData[i].opacity);
     1367            painter->setTransform(transform);
     1368
     1369            qreal w = drawingData[i].scaleX * drawingData[i].source.width();
     1370            qreal h = drawingData[i].scaleY * drawingData[i].source.height();
     1371            painter->drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, drawingData[i].source);
     1372        }
     1373
     1374        painter->setOpacity(oldOpacity);
     1375        painter->setTransform(oldTransform);
     1376    }
     1377}
     1378
    10411379QT_END_NAMESPACE
Note: See TracChangeset for help on using the changeset viewer.