/************************************************************************ ** ** @file vposter.cpp ** @author Roman Telezhynskyi ** @date 11 4, 2015 ** ** @brief ** @copyright ** This source code is part of the Valentine project, a pattern making ** program, whose allow create and modeling patterns of clothing. ** Copyright (C) 2015 Valentina project ** All Rights Reserved. ** ** Valentina is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** Valentina 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 General Public License ** along with Valentina. If not, see . ** *************************************************************************/ #include "vposter.h" #include #include #include #include #include #include #include #include #include #include #include "../vmisc/vmath.h" #include "../vmisc/def.h" //--------------------------------------------------------------------------------------------------------------------- VPoster::VPoster(const QPrinter *printer) :printer(printer), allowence(static_cast(qRound(10./25.4*PrintDPI)))//1 cm { } //--------------------------------------------------------------------------------------------------------------------- QVector VPoster::Calc(const QRect &imageRect, int page) const { QVector poster; if (printer == nullptr) { return poster; } const int rows = CountRows(imageRect.height()); const int columns = CountColumns(imageRect.width()); for (int i=0; i < rows; i++) { for (int j=0; j< columns; j++) { PosterData data = Cut(i, j, imageRect); data.index = page; data.rows = rows; data.columns = columns; poster.append(data); } } return poster; } //--------------------------------------------------------------------------------------------------------------------- QVector VPoster::Borders(QGraphicsItem *parent, const PosterData &img, int sheets) const { QVector data; QPen pen(Qt::NoBrush, 1, Qt::DashLine); pen.setColor(Qt::black); const QRect rec = img.rect; if (img.column != 0) {// Left border auto *line = new QGraphicsLineItem(parent); line->setPen(pen); line->setLine(rec.x(), rec.y(), rec.x(), rec.y() + rec.height()); data.append(line); auto *scissors = new QGraphicsPixmapItem(QPixmap("://scissors_vertical.png"), parent); scissors->setPos(rec.x(), rec.y() + rec.height()-static_cast(allowence)); data.append(scissors); } if (img.column != img.columns-1) {// Right border auto *line = new QGraphicsLineItem(parent); line->setPen(pen); line->setLine(rec.x() + rec.width()-static_cast(allowence), rec.y(), rec.x() + rec.width()-static_cast(allowence), rec.y() + rec.height()); data.append(line); } if (img.row != 0) {// Top border auto *line = new QGraphicsLineItem(parent); line->setPen(pen); line->setLine(rec.x(), rec.y(), rec.x() + rec.width(), rec.y()); data.append(line); auto *scissors = new QGraphicsPixmapItem(QPixmap("://scissors_horizontal.png"), parent); scissors->setPos(rec.x() + rec.width()-static_cast(allowence), rec.y()); data.append(scissors); } if (img.rows*img.columns > 1) { // Don't show bottom border if only one page need // Bottom border (mandatory) auto *line = new QGraphicsLineItem(parent); line->setPen(pen); line->setLine(rec.x(), rec.y() + rec.height()-static_cast(allowence), rec.x() + rec.width(), rec.y() + rec.height()-static_cast(allowence)); data.append(line); if (img.row == img.rows-1) { auto *scissors = new QGraphicsPixmapItem(QPixmap("://scissors_horizontal.png"), parent); scissors->setPos(rec.x() + rec.width()-static_cast(allowence), rec.y() + rec.height()-static_cast(allowence)); data.append(scissors); } } // Labels auto *labels = new QGraphicsTextItem(parent); const int layoutX = 15; const int layoutY = 5; labels->setPos(rec.x() + layoutX, rec.y() + rec.height()-static_cast(allowence)+layoutY); labels->setTextWidth(rec.width()-(static_cast(allowence)+layoutX)); const QString grid = tr("Grid ( %1 , %2 )").arg(img.row+1).arg(img.column+1); const QString page = tr("Page %1 of %2").arg(img.row*(img.columns)+img.column+1).arg(img.rows*img.columns); QString sheet; if (sheets > 1) { sheet = tr("Sheet %1 of %2").arg(img.index+1).arg(sheets); } labels->setHtml(QString("" "" "" "" "
%1%2%3
") .arg(grid, page, sheet)); data.append(labels); return data; } //--------------------------------------------------------------------------------------------------------------------- int VPoster::CountRows(int height) const { const qreal imgLength = height; const qreal pageLength = PageRect().height(); // Example // ― ― // * * // * * // * * // * * ― // ― ― * // * * // * * // * * ― // * ― * // — * // * * // * * ― // * ― * // * * // — * // * * ― // * ― * <-(2) // * + * // * + * // — + * ― <-(4) // ^ ^ ― * //(3) (1) * // * // * // ― const int pCount = qCeil(imgLength/pageLength);// Pages count without allowence (or allowence = 0) (3) // Calculate how many pages will be after using allowence. // We know start pages count. This number not enought because // each n-1 pages add (n-1)*allowence length to page (1). const qreal addionalLength = (pCount-1)*static_cast(allowence); //-V636 // Calculate additional length form pages that will cover this length (2). // In the end add page length (3). // Bottom page have mandatory border (4) return qCeil((addionalLength + qCeil(addionalLength/pageLength)*static_cast(allowence) + static_cast(allowence) + imgLength)/pageLength); } //--------------------------------------------------------------------------------------------------------------------- int VPoster::CountColumns(int width) const { const qreal imgLength = width; const qreal pageLength = PageRect().width(); // Example // |----|----|----|----| <- (3) // |----|+++++++++++++++ // |----|+++++++++++ // |----|+++++++ // |----|+++ <- (1) // |----| // ^ // (2) const int pCount = qCeil(imgLength/pageLength);// Pages count without allowence (or allowence = 0) (3) // Calculate how many pages will be after using allowence. // We know start pages count. This number not enought because // each n-1 pages add (n-1)*allowence length to page (1). const qreal addionalLength = (pCount-1)*static_cast(allowence); //-V636 // Calculate additional length form pages that will cover this length (2). // In the end add page length (3). return qCeil((addionalLength + qCeil(addionalLength/pageLength)*static_cast(allowence) + imgLength)/pageLength); } //--------------------------------------------------------------------------------------------------------------------- PosterData VPoster::Cut(int i, int j, const QRect &imageRect) const { Q_UNUSED(imageRect); const int x = j*PageRect().width() - j*static_cast(allowence); const int y = i*PageRect().height() - i*static_cast(allowence); SCASSERT(x <= imageRect.width()); SCASSERT(y <= imageRect.height()); PosterData data; data.row = i; data.column = j; data.rect = QRect(x, y, PageRect().width(), PageRect().height()); return data; } //--------------------------------------------------------------------------------------------------------------------- QRect VPoster::PageRect() const { // Because the Point unit is defined to be 1/72th of an inch // we can't use method pageRect(QPrinter::Point). Our dpi value can be different. // We convert value yourself to pixels. const QRectF rect = printer->pageRect(QPrinter::Millimeter); const QRect pageRect(0, 0, qFloor(ToPixel(rect.width())), qFloor(ToPixel(rect.height()))); return pageRect; } //--------------------------------------------------------------------------------------------------------------------- qreal VPoster::ToPixel(qreal val) { return val / 25.4 * PrintDPI; // Mm to pixels with current dpi. }