diff --git a/plasma/svgpanel.cpp b/plasma/svgpanel.cpp new file mode 100644 index 0000000000..914b517f43 --- /dev/null +++ b/plasma/svgpanel.cpp @@ -0,0 +1,307 @@ +/* + * Copyright 2008 by Aaron Seigo + * Copyright 2008 Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "svgpanel.h" + +#include +#include + +#include + +namespace Plasma +{ + +SvgPanel::SvgPanel(const QString& imagePath, QObject* parent) + : QObject(parent), + bFlags(DrawTop|DrawBottom|DrawLeft|DrawRight|ContentAtOrigin), + cachedBackground(0) +{ + m_background = new Svg(imagePath, this); + connect(m_background, SIGNAL(repaintNeeded()), this, SLOT(updateSizes())); + + updateSizes(); + panelSize = m_background->size(); +} + +SvgPanel::~SvgPanel() +{ +} + +void SvgPanel::setFile(const QString& imagePath) +{ + if (imagePath == m_background->file()) { + return; + } + + delete cachedBackground; + cachedBackground = 0; + m_background->setFile(imagePath); + updateSizes(); +} + +QString SvgPanel::file() const +{ + return m_background->file(); +} + +void SvgPanel::setBorderFlags(const BorderFlags flags) +{ + if (flags != bFlags) { + delete cachedBackground; + cachedBackground = 0; + } + + bFlags = flags; + updateSizes(); +} + +SvgPanel::BorderFlags SvgPanel::borderFlags() const +{ + return bFlags; +} + +void SvgPanel::resize(const QSizeF& size) +{ + if (!size.isValid() || size.width() < 1 || size.height() < 1 || size == panelSize) { + return; + } + + delete cachedBackground; + cachedBackground = 0; + updateSizes(); + panelSize = size; +} + +qreal SvgPanel::marginSize(const Plasma::Layout::MarginEdge edge) const +{ + if (noBorderPadding) { + return .0; + } + + switch (edge) { + case Plasma::Layout::TopMargin: + return topHeight; + break; + + case Plasma::Layout::LeftMargin: + return leftWidth; + break; + + case Plasma::Layout::RightMargin: + return rightWidth; + break; + + //Plasma::Layout::BottomMargin + default: + return bottomHeight; + break; + } +} + +void SvgPanel::paint(QPainter* painter, const QRectF& rect) +{ + bool useOrigin = bFlags & ContentAtOrigin; + const int topOffset = useOrigin ? 0 - topHeight : 0; + const int leftOffset = useOrigin ? 0 - leftWidth : 0; + + if (!cachedBackground) { + const int contentTop = 0; + const int contentLeft = 0; + const int contentWidth = panelSize.width() - leftWidth - rightWidth; + const int contentHeight = panelSize.height() - topHeight - bottomHeight; + const int rightOffset = contentWidth; + const int bottomOffset = contentHeight; + + scaledSize = QSizeF(panelSize.width() - + (leftWidth+rightWidth) + + panelSize.width()*(((qreal)(leftWidth+rightWidth))/panelSize.width()), + panelSize.height() - + (topHeight+bottomHeight) + + panelSize.height()*(((qreal)(topHeight+bottomHeight))/panelSize.height())); + + delete cachedBackground; + cachedBackground = new QPixmap(leftWidth + contentWidth + rightWidth, topHeight + contentHeight + bottomHeight); + cachedBackground->fill(Qt::transparent); + QPainter p(cachedBackground); + p.translate(leftWidth, topHeight); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.setRenderHint(QPainter::SmoothPixmapTransform); + + //FIXME: This is a hack to fix a drawing problems with svg files where a thin transparent border is drawn around the svg image. + // the transparent border around the svg seems to vary in size depending on the size of the svg and as a result increasing the + // svg image by 2 all around didn't resolve the issue. For now it resizes based on the border size. + + + //CENTER + if (contentHeight > 0 && contentWidth > 0) { + m_background->resize(scaledSize.width(), scaledSize.height()); + m_background->paint(&p, QRect(contentLeft-leftWidth, contentTop-topHeight, + contentWidth+leftWidth*2, contentHeight+topHeight*2), + "center"); + m_background->resize(); + } + + //EDGES + if (bFlags & DrawTop) { + if (bFlags & DrawLeft) { + m_background->paint(&p, QRect(leftOffset, topOffset, leftWidth, topHeight), "topleft"); + } + + if (bFlags & DrawRight) { + m_background->paint(&p, QRect(rightOffset, topOffset,rightWidth, topHeight), "topright"); + } + } + + if (bFlags & DrawBottom) { + if (bFlags & DrawLeft) { + m_background->paint(&p, QRect(leftOffset, bottomOffset, leftWidth, bottomHeight), "bottomleft"); + } + + if (bFlags & DrawRight) { + m_background->paint(&p, QRect(rightOffset, bottomOffset, rightWidth, bottomHeight), "bottomright"); + } + } + + //SIDES + if (stretchBorders) { + if (bFlags & DrawLeft) { + m_background->resize(m_background->size().width(), scaledSize.height()); + m_background->paint(&p, QRect(leftOffset, contentTop, leftWidth, contentHeight), "left"); + m_background->resize(); + } + + if (bFlags & DrawRight) { + m_background->resize(m_background->size().width(), scaledSize.height()); + m_background->paint(&p, QRect(rightOffset, contentTop, rightWidth, contentHeight), "right"); + m_background->resize(); + } + + if (bFlags & DrawTop) { + m_background->resize(scaledSize.width(), m_background->size().height()); + m_background->paint(&p, QRect(contentLeft, topOffset, contentWidth, topHeight), "top"); + m_background->resize(); + } + + if (bFlags & DrawBottom) { + m_background->resize(scaledSize.width(), m_background->size().height()); + m_background->paint(&p, QRect(contentLeft, bottomOffset, contentWidth, bottomHeight), "bottom"); + m_background->resize(); + } + } else { + if (bFlags & DrawLeft) { + QPixmap left(leftWidth, leftHeight); + left.fill(Qt::transparent); + + { + QPainter sidePainter(&left); + sidePainter.setCompositionMode(QPainter::CompositionMode_Source); + m_background->paint(&sidePainter, QPoint(0, 0), "left"); + } + + p.drawTiledPixmap(QRect(leftOffset, contentTop, leftWidth, contentHeight), left); + } + + if (bFlags & DrawRight) { + QPixmap right(rightWidth, leftHeight); + right.fill(Qt::transparent); + + { + QPainter sidePainter(&right); + sidePainter.setCompositionMode(QPainter::CompositionMode_Source); + m_background->paint(&sidePainter, QPoint(0, 0), "right"); + } + + p.drawTiledPixmap(QRect(rightOffset, contentTop, rightWidth, contentHeight), right); + } + + if (bFlags & DrawTop) { + QPixmap top(topWidth, topHeight); + top.fill(Qt::transparent); + + { + QPainter sidePainter(&top); + sidePainter.setCompositionMode(QPainter::CompositionMode_Source); + m_background->paint(&sidePainter, QPoint(0, 0), "top"); + } + + p.drawTiledPixmap(QRect(contentLeft, topOffset, contentWidth, topHeight), top); + } + + if (bFlags & DrawBottom) { + QPixmap bottom(topWidth, bottomHeight); + bottom.fill(Qt::transparent); + + { + QPainter sidePainter(&bottom); + sidePainter.setCompositionMode(QPainter::CompositionMode_Source); + m_background->paint(&sidePainter, QPoint(0, 0), "bottom"); + } + + p.drawTiledPixmap(QRect(contentLeft, bottomOffset, contentWidth, bottomHeight), bottom); + } + } + + // re-enable this once Qt's svg rendering is un-buggered + //resize(contentWidth, contentHeight); + //paint(&p, QRect(contentLeft, contentTop, contentWidth, contentHeight), "center"); + } + + //p2->drawPixmap(paintRect, *cachedBackground, paintRect.translated(-leftOffset,-topOffset)); + painter->drawPixmap(rect, *cachedBackground, rect.translated(-leftOffset, -topOffset)); +} + +void SvgPanel::updateSizes() +{ + m_background->resize(); + if (bFlags & DrawTop) { + topHeight = m_background->elementSize("top").height(); + } else { + topHeight = 0; + } + + if (bFlags & DrawLeft) { + leftWidth = m_background->elementSize("left").width(); + } else { + leftWidth = 0; + } + + if (bFlags & DrawRight) { + rightWidth = m_background->elementSize("right").width(); + } else { + rightWidth = 0; + } + + if (bFlags & DrawBottom) { + bottomHeight = m_background->elementSize("bottom").height(); + } else { + bottomHeight = 0; + } + + //since it's rectangular, topWidth and bottomWidth must be the same + topWidth = m_background->elementSize("top").width(); + leftHeight = m_background->elementSize("left").height(); + noBorderPadding = m_background->elementExists("hint-no-border-padding"); + stretchBorders = m_background->elementExists("hint-stretch-borders"); +} + + +} // Plasma namespace + +#include "svgpanel.moc"