summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarius Bugge Monsen <mmonsen@trolltech.com>2009-04-29 15:55:57 (GMT)
committerMarius Bugge Monsen <mmonsen@trolltech.com>2009-04-29 16:01:12 (GMT)
commit65e0d7c3b63fc4c1d7df7603b926ca013794b321 (patch)
tree80bdffda10fcc2f6bc06b137ad10667c04be2691
parentfa80385e0082fa9012ec08134a381e29b020c48f (diff)
downloadQt-65e0d7c3b63fc4c1d7df7603b926ca013794b321.zip
Qt-65e0d7c3b63fc4c1d7df7603b926ca013794b321.tar.gz
Qt-65e0d7c3b63fc4c1d7df7603b926ca013794b321.tar.bz2
Add qDrawBorderPixmap() function, Qt::TileRules enum, QMargins struct and QTileRules struct.
Implements a function to allow drawing CSS3-like border-images (also known as nine-grid images). Next step will be to convert the CSS-style code to use this function for drawing border-images. Task-number: none Reviewed-by: jbache
-rw-r--r--doc/src/qnamespace.qdoc13
-rw-r--r--src/corelib/global/qnamespace.h6
-rw-r--r--src/gui/painting/qdrawutil.cpp291
-rw-r--r--src/gui/painting/qdrawutil.h36
4 files changed, 346 insertions, 0 deletions
diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc
index 097333b..9ea6b52 100644
--- a/doc/src/qnamespace.qdoc
+++ b/doc/src/qnamespace.qdoc
@@ -2651,3 +2651,16 @@
\sa QGraphicsWidget::windowFrameSectionAt()
*/
+
+/*!
+ \enum Qt::TileRule
+ \since 4.6
+
+ This enum describes how to repeat or stretch the parts of an image when drawing.
+
+ \value Stretch Scale the image to fit to the available area.
+ \value Repeat Tile the image until there is no more space. May crop the last image.
+ \value Round Like Repeat, but scales the images down to ensure that the last image is not cropped.
+
+ \sa QPixmapBorders, qDrawBorderPixmap()
+*/
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index a519f4a..9b26ef3 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -188,6 +188,12 @@ public:
#endif
};
+ enum TileRule {
+ Stretch,
+ Repeat,
+ Round
+ };
+
// Text formatting flags for QPainter::drawText and QLabel.
// The following two enums can be combined to one integer which
// is passed as 'flags' to drawText and qt_format_text.
diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp
index 2beeb0e..4898b7e 100644
--- a/src/gui/painting/qdrawutil.cpp
+++ b/src/gui/painting/qdrawutil.cpp
@@ -1038,4 +1038,295 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs,
#endif
+/*!
+ \struct QMargins
+ \since 4.6
+
+ Holds the borders used to split a pixmap on into nine segments in order to draw it,
+ similar to CSS3 border-images \l http://www.w3.org/TR/css3-background/.
+
+ \sa qDrawBorderPixmap, Qt::TileRule, QTileRules
+ */
+
+/*!
+ \struct QTileRules
+ \since 4.6
+
+ Holds the rules used to draw a pixmap or image split into nine segments, similar to CSS3 border-images.
+
+ \sa qDrawBorderPixmap, Qt::TileRule, QMargins
+ */
+
+/*!
+ \fn qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap)
+ \since 4.6
+
+ Draws the given \a pixmap into the given \a target rectangle, using the given \a painter.
+ The pixmap will be splitt into nine segments and drawn according to the given \a margins structure.
+ */
+
+static inline void qVerticalRepeat(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
+ void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
+{
+ const int x = target.x();
+ const int width = target.width();
+ const int height = source.height();
+ const int bottom = target.bottom() - height;
+ int y = target.y();
+ for (; y < bottom; y += height)
+ (*drawPixmap)(painter, QRect(x, y, width, height), pixmap, source);
+ const QRect remaining(source.x(), source.y(), source.width(), target.bottom() - y + 1);
+ (*drawPixmap)(painter, QRect(x, y, width, remaining.height()), pixmap, remaining);
+}
+
+static inline void qHorizontalRepeat(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
+ void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
+{
+ const int y = target.y();
+ const int width = source.width();
+ const int height = target.height();
+ const int right = target.right() - width;
+ int x = target.x();
+ for (; x < right; x += width)
+ (*drawPixmap)(painter, QRect(x, y, width, height), pixmap, source);
+ const QRect remaining(source.x(), source.y(), target.right() - x + 1, source.height());
+ (*drawPixmap)(painter, QRect(x, y, remaining.width(), height), pixmap, remaining);
+}
+
+static inline void qVerticalRound(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
+ void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
+{
+ // qreal based - slow on non-fpu devices
+ const qreal x = target.x();
+ const qreal width = target.width();
+ const qreal verticalFactor = static_cast<qreal>(target.height()) / static_cast<qreal>(source.height());
+ const qreal verticalIncrement = static_cast<qreal>(target.height()) / static_cast<int>(verticalFactor + 0.5);
+ const qreal bottom = target.bottom();
+ for (qreal y = static_cast<qreal>(target.y()); y < bottom; y += verticalIncrement)
+ (*drawPixmap)(painter, QRectF(x, y, width, verticalIncrement).toRect(), pixmap, source);
+
+}
+
+static inline void qHorizontalRound(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
+ void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
+{
+ // qreal based - slow on non-fpu devices
+ const qreal y = target.y();
+ const qreal height = target.height();
+ const qreal horizontalFactor = static_cast<qreal>(target.width()) / static_cast<qreal>(source.width());
+ const qreal horizontalIncrement = static_cast<qreal>(target.width()) / static_cast<int>(horizontalFactor + 0.5);
+ const qreal right = target.right();
+ for (qreal x = target.x(); x < right; x += horizontalIncrement)
+ (*drawPixmap)(painter, QRectF(x, y, horizontalIncrement, height).toRect(), pixmap, source);
+}
+
+static inline void qDrawPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ painter->drawPixmap(target, pixmap, source);
+}
+
+static inline void qDrawVerticallyRepeatedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qVerticalRepeat(painter, target, pixmap, source, qDrawPixmap);
+}
+
+static inline void qDrawHorizontallyRepeatedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qHorizontalRepeat(painter, target, pixmap, source, qDrawPixmap);
+}
+
+static inline void qDrawVerticallyRoundedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qVerticalRound(painter, target, pixmap, source, qDrawPixmap);
+}
+
+static inline void qDrawHorizontallyRoundedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qHorizontalRound(painter, target, pixmap, source, qDrawPixmap);
+}
+
+/*!
+ \since 4.6
+
+ Draws the indicated \a sourceRect rectangle from the given \a pixmap into the given \a targetRect rectangle,
+ using the given \a painter.
+ The pixmap will be splitt into nine segments according to the given \a targetMargins and
+ \a sourceMargins structures and drawn according to the given \a rules.
+
+ This function is used to draw a scaled pixmap, similar to CSS3 border-images.
+
+ \sa Qt::TileRule, QTileRules, QMargins
+ */
+void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, const QPixmap &pixmap,
+ const QRect &sourceRect, const QMargins &sourceMargins, const QTileRules &rules)
+{
+ // source center
+ const int sourceTop = sourceRect.top();
+ const int sourceLeft = sourceRect.left();
+ const int sourceCenterTop = sourceTop + sourceMargins.top;
+ const int sourceCenterLeft = sourceLeft + sourceMargins.left;
+ const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom + 1;
+ const int sourceCenterRight = sourceRect.right() - sourceMargins.right + 1;
+ const int sourceCenterWidth = sourceCenterRight - sourceMargins.left;
+ const int sourceCenterHeight = sourceCenterBottom - sourceMargins.top;
+ // target center
+ const int targetTop = targetRect.top();
+ const int targetLeft = targetRect.left();
+ const int targetCenterTop = targetTop + targetMargins.top;
+ const int targetCenterLeft = targetLeft + targetMargins.left;
+ const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom + 1;
+ const int targetCenterRight = targetRect.right() - targetMargins.right + 1;
+ const int targetCenterWidth = targetCenterRight - targetCenterLeft;
+ const int targetCenterHeight = targetCenterBottom - targetCenterTop;
+
+ // corners
+ if (targetMargins.top > 0 && targetMargins.left > 0 && sourceMargins.top > 0 && sourceMargins.left > 0) { // top left
+ const QRect targetTopLeftRect(targetLeft, targetTop, targetMargins.left, targetMargins.top);
+ const QRect sourceTopLeftRect(sourceLeft, sourceTop, sourceMargins.left, sourceMargins.top);
+ qDrawPixmap(painter, targetTopLeftRect, pixmap, sourceTopLeftRect);
+ }
+ if (targetMargins.top > 0 && targetMargins.right > 0 && sourceMargins.top > 0 && sourceMargins.right > 0) { // top right
+ const QRect targetTopRightRect(targetCenterRight, targetTop, targetMargins.right, targetMargins.top);
+ const QRect sourceTopRightRect(sourceCenterRight, sourceTop, sourceMargins.right, sourceMargins.top);
+ qDrawPixmap(painter, targetTopRightRect, pixmap, sourceTopRightRect);
+ }
+ if (targetMargins.bottom > 0 && targetMargins.left > 0 && sourceMargins.bottom > 0 && sourceMargins.left > 0) { // bottom left
+ const QRect targetBottomLeftRect(targetLeft, targetCenterBottom, targetMargins.left, targetMargins.bottom);
+ const QRect sourceBottomLeftRect(sourceLeft, sourceCenterBottom, sourceMargins.left, sourceMargins.bottom);
+ qDrawPixmap(painter, targetBottomLeftRect, pixmap, sourceBottomLeftRect);
+ }
+ if (targetMargins.bottom > 0 && targetMargins.right > 0 && sourceMargins.bottom > 0 && sourceMargins.right > 0) { // bottom right
+ const QRect targetBottomRightRect(targetCenterRight, targetCenterBottom, targetMargins.right, targetMargins.bottom);
+ const QRect sourceBottomRightRect(sourceCenterRight, sourceCenterBottom, sourceMargins.right, sourceMargins.bottom);
+ qDrawPixmap(painter, targetBottomRightRect, pixmap, sourceBottomRightRect);
+ }
+
+ // horizontal edges
+ switch (rules.horizontal) {
+ case Qt::Stretch:
+ if (targetMargins.top > 0 && sourceMargins.top > 0) { // top
+ const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top);
+ const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top);
+ qDrawPixmap(painter, targetTopRect, pixmap, sourceTopRect);
+ }
+ if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom
+ const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom);
+ const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom);
+ qDrawPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
+ }
+ break;
+ case Qt::Repeat:
+ if (targetMargins.top > 0 && sourceMargins.top > 0) { // top
+ const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top);
+ const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top);
+ qDrawHorizontallyRepeatedPixmap(painter, targetTopRect, pixmap, sourceTopRect);
+ }
+ if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom
+ const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom);
+ const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom);
+ qDrawHorizontallyRepeatedPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
+ }
+ break;
+ case Qt::Round:
+ if (targetMargins.top > 0 && sourceMargins.top > 0) { // top
+ const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top);
+ const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top);
+ qDrawHorizontallyRoundedPixmap(painter, targetTopRect, pixmap, sourceTopRect);
+ }
+ if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom
+ const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom);
+ const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom);
+ qDrawHorizontallyRoundedPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
+ }
+ break;
+ }
+
+ // vertical edges
+ switch (rules.vertical) {
+ case Qt::Stretch:
+ if (targetMargins.left > 0 && sourceMargins.left > 0) { // left
+ const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight);
+ const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight);
+ qDrawPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
+ }
+ if (targetMargins.right > 0 && sourceMargins.right > 0) { // right
+ const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight);
+ const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight);
+ qDrawPixmap(painter, targetRightRect, pixmap, sourceRightRect);
+ }
+ break;
+ case Qt::Repeat:
+ if (targetMargins.left > 0 && sourceMargins.left > 0) { // left
+ const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight);
+ const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight);
+ qDrawVerticallyRepeatedPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
+ }
+ if (targetMargins.right > 0 && sourceMargins.right > 0) { // right
+ const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight);
+ const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight);
+ qDrawVerticallyRepeatedPixmap(painter, targetRightRect, pixmap, sourceRightRect);
+ }
+ break;
+ case Qt::Round:
+ if (targetMargins.left > 0 && sourceMargins.left > 0) { // left
+ const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight);
+ const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight);
+ qDrawVerticallyRoundedPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
+ }
+ if (targetMargins.right > 0 && sourceMargins.right > 0) { // right
+ const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight);
+ const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight);
+ qDrawVerticallyRoundedPixmap(painter, targetRightRect, pixmap, sourceRightRect);
+ }
+ break;
+ }
+
+ // center
+ if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
+ const QRect targetCenterRect(targetCenterLeft, targetCenterTop, targetCenterWidth, targetCenterHeight);
+ const QRect sourceCenterRect(sourceCenterLeft, sourceCenterTop, sourceCenterWidth, sourceCenterHeight);
+ switch (rules.horizontal) {
+ case Qt::Stretch:
+ switch (rules.vertical) {
+ case Qt::Stretch: // stretch stretch
+ qDrawPixmap(painter, targetCenterRect, pixmap, sourceCenterRect);
+ break;
+ case Qt::Repeat: // stretch repeat
+ qVerticalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ case Qt::Round: // stretch round
+ qVerticalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ }
+ break;
+ case Qt::Repeat:
+ switch (rules.vertical) {
+ case Qt::Stretch: // repeat stretch
+ qHorizontalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ case Qt::Repeat: // repeat repeat
+ qVerticalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawHorizontallyRepeatedPixmap);
+ break;
+ case Qt::Round: // repeat round
+ qVerticalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawHorizontallyRepeatedPixmap);
+ break;
+ }
+ break;
+ case Qt::Round:
+ switch (rules.vertical) {
+ case Qt::Stretch: // round stretch
+ qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ case Qt::Repeat: // round repeat
+ qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawVerticallyRepeatedPixmap);
+ break;
+ case Qt::Round: // round round
+ qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawVerticallyRoundedPixmap);
+ break;
+ }
+ break;
+ }
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawutil.h b/src/gui/painting/qdrawutil.h
index 14901f3..08fa1ab 100644
--- a/src/gui/painting/qdrawutil.h
+++ b/src/gui/painting/qdrawutil.h
@@ -133,6 +133,42 @@ Q_GUI_EXPORT QT3_SUPPORT void qDrawArrow(QPainter *p, Qt::ArrowType type, Qt::GU
const QPalette &pal, bool enabled);
#endif
+struct Q_GUI_EXPORT QMargins
+{
+ inline QMargins(int margin = 0)
+ : top(margin),
+ left(margin),
+ bottom(margin),
+ right(margin) {}
+ inline QMargins(int topMargin, int leftMargin, int bottomMargin, int rightMargin)
+ : top(topMargin),
+ left(leftMargin),
+ bottom(bottomMargin),
+ right(rightMargin) {}
+ int top;
+ int left;
+ int bottom;
+ int right;
+};
+
+struct Q_GUI_EXPORT QTileRules
+{
+ inline QTileRules(Qt::TileRule horizontalRule = Qt::Stretch,
+ Qt::TileRule verticalRule = Qt::Stretch)
+ : horizontal(horizontalRule),
+ vertical(verticalRule) {}
+ Qt::TileRule horizontal;
+ Qt::TileRule vertical;
+};
+
+Q_GUI_EXPORT void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, const QPixmap &pixmap,
+ const QRect &sourceRect, const QMargins &sourceMargins, const QTileRules &rules = QTileRules());
+
+Q_GUI_EXPORT inline void qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap)
+{
+ qDrawBorderPixmap(painter, target, margins, pixmap, pixmap.rect(), margins);
+}
+
QT_END_NAMESPACE
QT_END_HEADER