/************************************************************************ ** ** @file vposter.cpp ** @author Roman Telezhynskyi ** @date 11 4, 2015 ** ** @brief ** @copyright ** This source code is part of the Valentina 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 #include #include #include "../vmisc/vmath.h" #include "../vmisc/def.h" #include "../vmisc/vabstractapplication.h" namespace { //--------------------------------------------------------------------------------------------------------------------- qreal ToPixel(qreal val) { return val / 25.4 * PrintDPI; // Mm to pixels with current dpi. } } //--------------------------------------------------------------------------------------------------------------------- VPoster::VPoster(const QPrinter *printer) :printer(printer), allowance(static_cast(qRound(10./25.4*PrintDPI)))//1 cm { } //--------------------------------------------------------------------------------------------------------------------- QVector VPoster::Calc(const QRect &imageRect, int page, PageOrientation orientation) const { QVector poster; if (printer == nullptr) { return poster; } const int rows = CountRows(imageRect.height(), orientation); const int columns = CountColumns(imageRect.width(), orientation); for (int i=0; i < rows; i++) { for (int j=0; j< columns; j++) { PosterData data = Cut(i, j, imageRect, orientation); data.index = static_cast(page); data.rows = static_cast(rows); data.columns = static_cast(columns); poster.append(data); } } return poster; } //--------------------------------------------------------------------------------------------------------------------- QVector VPoster::Borders(QGraphicsItem *parent, const PosterData &img, int sheets) const { SCASSERT(parent != nullptr) QVector data; QPen pen(Qt::NoBrush, 1, Qt::DashLine); pen.setColor(Qt::black); if (img.columns == 1 && img.rows == 1) { return data; } 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(QStringLiteral("://scissors_vertical.png")), parent); scissors->setPos(rec.x(), rec.y() + rec.height()-static_cast(allowance)); 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(allowance), rec.y(), rec.x() + rec.width()-static_cast(allowance), 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(QStringLiteral("://scissors_horizontal.png")), parent); scissors->setPos(rec.x() + rec.width()-static_cast(allowance), rec.y()); data.append(scissors); } // Bottom border (mandatory) auto *line = new QGraphicsLineItem(parent); line->setPen(pen); line->setLine(rec.x(), rec.y() + rec.height()-static_cast(allowance), rec.x() + rec.width(), rec.y() + rec.height()-static_cast(allowance)); data.append(line); // Ruler Ruler(data, parent, rec); // 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(allowance)+layoutY); labels->setTextWidth(rec.width()-(static_cast(allowance)+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, PageOrientation orientation) const { const qreal imgLength = height; qreal pageLength = 0; if(orientation == PageOrientation::Landscape) { pageLength = PageRect().width(); } else { pageLength = PageRect().height(); } if (pageLength >= imgLength) { return 1; } else { return qCeil(imgLength/(pageLength - static_cast(allowance))); } } //--------------------------------------------------------------------------------------------------------------------- int VPoster::CountColumns(int width, PageOrientation orientation) const { const qreal imgLength = width; qreal pageLength = 0; if(orientation == PageOrientation::Landscape) { pageLength = PageRect().height(); } else { pageLength = PageRect().width(); } if (pageLength >= imgLength) { return 1; } else { return qCeil(imgLength/(pageLength-static_cast(allowance))); } } //--------------------------------------------------------------------------------------------------------------------- PosterData VPoster::Cut(int i, int j, const QRect &imageRect, PageOrientation orientation) const { Q_UNUSED(imageRect) int pageLengthX, pageLengthY; if(orientation == PageOrientation::Landscape) { pageLengthX = PageRect().height(); pageLengthY = PageRect().width(); } else { pageLengthX = PageRect().width(); pageLengthY = PageRect().height(); } const int x = j*pageLengthX - j*static_cast(allowance); const int y = i*pageLengthY - i*static_cast(allowance); SCASSERT(x <= imageRect.width()) SCASSERT(y <= imageRect.height()) PosterData data; data.row = static_cast(i); data.column = static_cast(j); data.rect = QRect(x, y, pageLengthX, pageLengthY); 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); if(printer->fullPage()) { QMarginsF pMargins = printer->pageLayout().margins(); QRectF newRect = rect.marginsRemoved(pMargins); const QRect pageRectFP(0, 0, qFloor(ToPixel(newRect.width())), qFloor(ToPixel(newRect.height()))); return pageRectFP; } else { const QRect pageRect(0, 0, qFloor(ToPixel(rect.width())), qFloor(ToPixel(rect.height()))); return pageRect; } } //--------------------------------------------------------------------------------------------------------------------- void VPoster::Ruler(QVector &data, QGraphicsItem *parent, QRect rec) const { SCASSERT(parent != nullptr) QPen rulePen(Qt::NoBrush, 1, Qt::SolidLine); rulePen.setColor(Qt::black); const qreal notchHeight = ToPixel(3); // mm const qreal shortNotchHeight = ToPixel(1.1); // mm Unit patternUnits = qApp->patternUnit(); const qreal step = UnitConvertor(1, patternUnits, Unit::Px); double marksCount = rec.width() / step; int i = 0; while (i < marksCount) { if (i != 0) { // don't need 0 notch auto *middleRuleLine = new QGraphicsLineItem(parent); middleRuleLine->setPen(rulePen); middleRuleLine->setLine(rec.x() + step * i - step / 2., rec.y() + rec.height()-static_cast(allowance), rec.x() + step * i - step / 2., rec.y() + rec.height()-static_cast(allowance) + shortNotchHeight); data.append(middleRuleLine); auto *ruleLine = new QGraphicsLineItem(parent); ruleLine->setPen(rulePen); ruleLine->setLine(rec.x() + step * i, rec.y() + rec.height()-static_cast(allowance), rec.x() + step * i, rec.y() + rec.height()-static_cast(allowance) + notchHeight); data.append(ruleLine); } else { auto *units = new QGraphicsTextItem(parent); units->setPlainText(patternUnits == Unit::Cm || patternUnits == Unit::Mm ? tr("cm", "unit") : tr("in", "unit")); QFont fnt = units->font(); fnt.setPointSize(10); qreal unitsWidth = 0; QFontMetrics fm(fnt); #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) unitsWidth = fm.horizontalAdvance(units->toPlainText()); #else unitsWidth = fm.width(units->toPlainText()); #endif units->setPos(rec.x() + step*0.5-unitsWidth*0.7, rec.y() + rec.height()-static_cast(allowance)-shortNotchHeight); units->setFont(fnt); data.append(units); } ++i; } }