File indexing completed on 2024-05-26 16:14:25
0001 /* This file is part of the KDE project 0002 * 0003 * Copyright (C) 2007 Jan Hambrecht <jaham@gmx.net> 0004 * Copyright (C) 2009 Thomas Zander <zander@kde.org> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KoShapePainter.h" 0023 0024 #include "KoCanvasBase.h" 0025 #include "KoShapeManager.h" 0026 #include "KoShapeManagerPaintingStrategy.h" 0027 #include "KoShape.h" 0028 #include "KoViewConverter.h" 0029 #include "KoShapeStrokeModel.h" 0030 #include "KoShapeGroup.h" 0031 #include "KoShapeContainer.h" 0032 0033 #include <KoUnit.h> 0034 0035 #include <QPainter> 0036 #include <QImage> 0037 0038 class SimpleCanvas : public KoCanvasBase 0039 { 0040 public: 0041 SimpleCanvas() 0042 : KoCanvasBase(0), m_shapeManager(new KoShapeManager(this)) 0043 { 0044 } 0045 0046 ~SimpleCanvas() override 0047 { 0048 delete m_shapeManager; 0049 } 0050 0051 void gridSize(qreal *horizontal, qreal *vertical) const override 0052 { 0053 if (horizontal) 0054 *horizontal = 0; 0055 if (vertical) 0056 *vertical = 0; 0057 }; 0058 0059 bool snapToGrid() const override 0060 { 0061 return false; 0062 } 0063 0064 void addCommand(KUndo2Command *) override 0065 { 0066 } 0067 0068 KoShapeManager *shapeManager() const override 0069 { 0070 return m_shapeManager; 0071 } 0072 0073 void updateCanvas(const QRectF&) override 0074 { 0075 } 0076 0077 KoToolProxy *toolProxy() const override 0078 { 0079 return 0; 0080 } 0081 0082 KoViewConverter *viewConverter() const override 0083 { 0084 return 0; 0085 } 0086 0087 QWidget *canvasWidget() override 0088 { 0089 return 0; 0090 } 0091 0092 const QWidget *canvasWidget() const override 0093 { 0094 return 0; 0095 } 0096 0097 KoUnit unit() const override 0098 { 0099 return KoUnit(KoUnit::Point); 0100 } 0101 0102 void updateInputMethodInfo() override {} 0103 0104 void setCursor(const QCursor &) override {} 0105 0106 private: 0107 KoShapeManager *m_shapeManager; 0108 }; 0109 0110 class Q_DECL_HIDDEN KoShapePainter::Private 0111 { 0112 public: 0113 Private() 0114 : canvas(new SimpleCanvas()) 0115 { 0116 } 0117 0118 ~Private() { delete canvas; } 0119 SimpleCanvas * canvas; 0120 }; 0121 0122 KoShapePainter::KoShapePainter(KoShapeManagerPaintingStrategy *strategy) 0123 : d(new Private()) 0124 { 0125 if (strategy) { 0126 strategy->setShapeManager(d->canvas->shapeManager()); 0127 d->canvas->shapeManager()->setPaintingStrategy(strategy); 0128 } 0129 } 0130 0131 KoShapePainter::~KoShapePainter() 0132 { 0133 delete d; 0134 } 0135 0136 void KoShapePainter::setShapes(const QList<KoShape*> &shapes) 0137 { 0138 d->canvas->shapeManager()->setShapes(shapes, KoShapeManager::AddWithoutRepaint); 0139 } 0140 0141 void KoShapePainter::paint(QPainter &painter, KoViewConverter &converter) 0142 { 0143 foreach (KoShape *shape, d->canvas->shapeManager()->shapes()) { 0144 shape->waitUntilReady(converter, false); 0145 } 0146 0147 d->canvas->shapeManager()->paint(painter, converter, true); 0148 } 0149 0150 void KoShapePainter::paint(QPainter &painter, const QRect &painterRect, const QRectF &documentRect) 0151 { 0152 if (documentRect.width() == 0.0f || documentRect.height() == 0.0f) 0153 return; 0154 0155 KoViewConverter converter; 0156 // calculate the painter destination rectangle size in document coordinates 0157 QRectF paintBox = converter.viewToDocument(QRectF(QPointF(), painterRect.size())); 0158 0159 // compute the zoom factor based on the bounding rects in document coordinates 0160 // so that the content fits into the image 0161 qreal zoomW = paintBox.width() / documentRect.width(); 0162 qreal zoomH = paintBox.height() / documentRect.height(); 0163 qreal zoom = qMin(zoomW, zoomH); 0164 0165 // now set the zoom into the zoom handler used for painting the shape 0166 converter.setZoom(zoom); 0167 0168 painter.save(); 0169 0170 // initialize painter 0171 painter.setPen(QPen(Qt::NoPen)); 0172 painter.setBrush(Qt::NoBrush); 0173 painter.setRenderHint(QPainter::Antialiasing); 0174 painter.setClipRect(painterRect.adjusted(-1,-1,1,1)); 0175 0176 // convert document rectangle to view coordinates 0177 QRectF zoomedBound = converter.documentToView(documentRect); 0178 // calculate offset between painter rectangle and converted document rectangle 0179 QPointF offset = QRectF(painterRect).center() - zoomedBound.center(); 0180 // center content in painter rectangle 0181 painter.translate(offset.x(), offset.y()); 0182 0183 // finally paint the shapes 0184 paint(painter, converter); 0185 0186 painter.restore(); 0187 } 0188 0189 void KoShapePainter::paint(QImage &image) 0190 { 0191 if (image.isNull()) 0192 return; 0193 0194 QPainter painter(&image); 0195 0196 paint(painter, image.rect(), contentRect()); 0197 } 0198 0199 QRectF KoShapePainter::contentRect() const 0200 { 0201 QRectF bound; 0202 foreach (KoShape *shape, d->canvas->shapeManager()->shapes()) { 0203 if (!shape->isVisible(true)) 0204 continue; 0205 if (dynamic_cast<KoShapeGroup*>(shape)) 0206 continue; 0207 0208 QRectF shapeRect = shape->boundingRect(); 0209 0210 if (bound.isEmpty()) 0211 bound = shapeRect; 0212 else 0213 bound = bound.united(shapeRect); 0214 } 0215 return bound; 0216 }