File indexing completed on 2024-05-05 04:43:23

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com)
0003  * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk)
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public
0016  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0017  */
0018 
0019 #include "KReportPrintRenderer_p.h"
0020 #include "kreport_debug.h"
0021 #include "KReportRenderObjects.h"
0022 #include "KReportPageSize.h"
0023 #include "KReportUtils_p.h"
0024 
0025 #include <QApplication>
0026 #include <QPainter>
0027 #include <QPrinter>
0028 
0029 namespace KReportPrivate {
0030 
0031 PrintRenderer::PrintRenderer()
0032 {
0033 }
0034 
0035 PrintRenderer::~PrintRenderer()
0036 {
0037 }
0038 
0039 bool PrintRenderer::setupPrinter( ORODocument * document, QPrinter * pPrinter)
0040 {
0041     if (document == nullptr || pPrinter == nullptr)
0042         return false;
0043 
0044     pPrinter->setCreator(QLatin1String("KReport Print Renderer"));
0045     pPrinter->setDocName(document->title());
0046     pPrinter->setFullPage(true);
0047     pPrinter->setOrientation((document->pageLayout().orientation() == QPageLayout::Portrait ? QPrinter::Portrait : QPrinter::Landscape));
0048     pPrinter->setPageOrder(QPrinter::FirstPageFirst);
0049 
0050 //    if (!document->pageLayout().pageSize().isValid()) {
0051 //        pPrinter->setPageSize(QPageSize(QSize(document->pageLayout().getCustomWidth(), document->pageLayout().getCustomHeight()), QLatin1String("Custom"));
0052 //    } else {
0053         pPrinter->setPageSize(QPageSize(document->pageLayout().pageSize()));
0054 //    }
0055 
0056     return true;
0057 }
0058 
0059 bool PrintRenderer::render(const KReportRendererContext &context, ORODocument *document, int page)
0060 {
0061     Q_UNUSED(page);
0062     if (document == nullptr || context.printer() == nullptr || context.painter() == nullptr)
0063         return false;
0064 
0065     setupPrinter(document, context.printer());
0066 
0067     bool endWhenComplete = false;
0068 
0069 
0070     if (!context.painter()->isActive()) {
0071         endWhenComplete = true;
0072         if (!context.painter()->begin(context.printer()))
0073             return false;
0074     }
0075 
0076     int fromPage = context.printer()->fromPage();
0077     if (fromPage > 0)
0078         fromPage -= 1;
0079     int toPage = context.printer()->toPage();
0080     if (toPage == 0 || toPage > document->pageCount())
0081         toPage = document->pageCount();
0082 
0083     qreal scaleX = context.printer()->resolution() / qreal(KReportPrivate::dpiX());
0084     qreal scaleY = context.printer()->resolution() / qreal(KReportPrivate::dpiY());
0085 
0086 
0087     for (int copy = 0; copy < context.printer()->numCopies(); copy++) {
0088         for (int page = fromPage; page < toPage; page++) {
0089             if (page > fromPage)
0090                 context.printer()->newPage();
0091 
0092             OROPage * p = document->page(page);
0093             if (context.printer()->pageOrder() == QPrinter::LastPageFirst)
0094                 p = document->page(toPage - 1 - page);
0095 
0096             // Render Page Objects
0097             for (int i = 0; i < p->primitiveCount(); i++) {
0098                 OROPrimitive * prim = p->primitive(i);
0099 
0100 
0101                 prim->setPosition(QPointF(prim->position().x() * scaleX, prim->position().y() * scaleY));
0102                 prim->setSize(QSizeF(prim->size().width() * scaleX, prim->size().height() * scaleY));
0103                 //kreportDebug() << "Rendering object" << i << "type" << prim->type();
0104                 if (OROTextBox *tb = dynamic_cast<OROTextBox*>(prim)) {
0105                     QPointF ps = tb->position();
0106                     QSizeF sz = tb->size();
0107                     QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height());
0108 
0109                     context.painter()->save();
0110                     //Background
0111 
0112                     QColor bg = tb->textStyle().backgroundColor;
0113                     bg.setAlphaF(0.01 * tb->textStyle().backgroundOpacity);
0114 
0115                     //_painter()->setBackgroundMode(Qt::OpaqueMode);
0116                     context.painter()->fillRect(rc, bg);
0117 
0118                     //Text
0119                     context.painter()->setBackgroundMode(Qt::TransparentMode);
0120                     context.painter()->setFont(tb->textStyle().font);
0121                     context.painter()->setPen(tb->textStyle().foregroundColor);
0122                     context.painter()->drawText(rc, tb->flags(), tb->text());
0123 
0124                     //outer line
0125                     context.painter()->setPen(QPen(tb->lineStyle().color(), tb->lineStyle().weight() * scaleX, tb->lineStyle().penStyle()));
0126                     context.painter()->drawRect(rc);
0127 
0128                     //Reset back to defaults for next element
0129                     context.painter()->restore();
0130 
0131                 } else if (OROLine *ln = dynamic_cast<OROLine*>(prim)) {
0132                     QPointF s = ln->startPoint();
0133                     QPointF e(ln->endPoint().x() * scaleX, ln->endPoint().y() * scaleY);
0134                     //QPen pen ( _painter()->pen() );
0135                     QPen pen(ln->lineStyle().color(), ln->lineStyle().weight() * scaleX, ln->lineStyle().penStyle());
0136 
0137                     context.painter()->save();
0138                     context.painter()->setRenderHint(QPainter::Antialiasing, true);
0139                     context.painter()->setPen(pen);
0140                     context.painter()->drawLine(QLineF(s.x(), s.y(), e.x(), e.y()));
0141                     context.painter()->setRenderHint(QPainter::Antialiasing, false);
0142                     context.painter()->restore();
0143                 } else if (OROImage *im = dynamic_cast<OROImage*>(prim)) {
0144                     QPointF ps = im->position();
0145                     QSizeF sz = im->size();
0146                     QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height());
0147 
0148                     QImage img = im->image();
0149                     if (im->isScaled())
0150                         img = img.scaled(rc.size().toSize(), (Qt::AspectRatioMode) im->aspectRatioMode(), (Qt::TransformationMode) im->transformationMode());
0151 
0152                     QRectF sr = QRectF(QPointF(0.0, 0.0), rc.size().boundedTo(img.size()));
0153                     context.painter()->drawImage(rc.topLeft(), img, sr);
0154                 } else if (ORORect *re = dynamic_cast<ORORect*>(prim)) {
0155                     QPointF ps = re->position();
0156                     QSizeF sz = re->size();
0157                     QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height());
0158 
0159                     context.painter()->save();
0160                     context.painter()->setPen(re->pen());
0161                     context.painter()->setBrush(re->brush());
0162                     context.painter()->drawRect(rc);
0163                     context.painter()->restore();
0164                 } else if (OROEllipse *re = dynamic_cast<OROEllipse*>(prim)) {
0165                     QPointF ps = re->position();
0166                     QSizeF sz = re->size();
0167                     QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height());
0168 
0169                     context.painter()->save();
0170                     context.painter()->setPen(re->pen());
0171                     context.painter()->setBrush(re->brush());
0172                     context.painter()->drawEllipse(rc);
0173                     context.painter()->restore();
0174                 } else if (OROPicture *im = dynamic_cast<OROPicture*>(prim)) {
0175                     QPointF ps = im->position();
0176                     QSizeF sz = im->size();
0177                     QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height());
0178                     context.painter()->drawPicture(rc.topLeft(), *(im->picture()));
0179                 } else if (OROCheckBox *chk = dynamic_cast<OROCheckBox*>(prim)) {
0180                     QPointF ps = chk->position();
0181                     QSizeF sz = chk->size();
0182                     QRectF rc = QRectF(ps.x(), ps.y(), sz.width(), sz.height());
0183 
0184                     context.painter()->save();
0185 
0186                     context.painter()->setBackgroundMode(Qt::OpaqueMode);
0187                     context.painter()->setRenderHint(QPainter::Antialiasing);
0188 
0189                     context.painter()->setPen(chk->foregroundColor());
0190 
0191                     if (chk->lineStyle().penStyle() == Qt::NoPen || chk->lineStyle().weight() <= 0) {
0192                         context.painter()->setPen(QPen(Qt::lightGray));
0193                     } else {
0194                         context.painter()->setPen(QPen(chk->lineStyle().color(), chk->lineStyle().weight() * scaleX, chk->lineStyle().penStyle()));
0195                     }
0196 
0197                     qreal ox = sz.width() / 5;
0198                     qreal oy = sz.height() / 5;
0199 
0200                     //Checkbox Style
0201                     if (chk->checkType() == OROCheckBox::Type::Cross) {
0202                         context.painter()->drawRoundedRect(rc, sz.width() / 10 , sz.height() / 10);
0203 
0204                         if (chk->value()) {
0205                             QPen lp;
0206                             lp.setColor(chk->foregroundColor());
0207                             lp.setWidth(ox > oy ? oy : ox);
0208                             context.painter()->setPen(lp);
0209                             context.painter()->drawLine(QPointF(ox, oy) + ps, QPointF(sz.width() - ox, sz.height() - oy) + ps);
0210                             context.painter()->drawLine(QPointF(ox, sz.height() - oy) + ps, QPoint(sz.width() - ox, oy) + ps);
0211                         }
0212                     } else if (chk->checkType() == OROCheckBox::Type::Dot) {
0213                         //Radio Style
0214                         context.painter()->drawEllipse(rc);
0215 
0216                         if (chk->value()) {
0217                             QBrush lb(chk->foregroundColor());
0218                             context.painter()->setBrush(lb);
0219                             context.painter()->setPen(Qt::NoPen);
0220                             context.painter()->drawEllipse(rc.center(), sz.width() / 2 - ox, sz.height() / 2 - oy);
0221                         }
0222                     } else {
0223                         //Tickbox Style
0224                         context.painter()->drawRoundedRect(rc, sz.width() / 10 , sz.height() / 10);
0225 
0226                         if (chk->value()) {
0227                             QPen lp;
0228                             lp.setColor(chk->foregroundColor());
0229                             lp.setWidth(ox > oy ? oy : ox);
0230                             context.painter()->setPen(lp);
0231                             context.painter()->drawLine(QPointF(ox, sz.height() / 2) + ps, QPointF(sz.width() / 2, sz.height() - oy) + ps);
0232                             context.painter()->drawLine(QPointF(sz.width() / 2, sz.height() - oy) + ps, QPointF(sz.width() - ox, oy) + ps);
0233                         }
0234                     }
0235                     context.painter()->restore();
0236                 }
0237             }
0238         }
0239     }
0240 
0241     if (endWhenComplete)
0242         context.painter()->end();
0243 
0244     return true;
0245 }
0246 
0247 }