Redesign printing system. ref #494. Printing is not working.

Made complete redesign of printing code. Now the code check printer's dpi and
calculate  scale factor. Instead of printing with QImage buffer the code print
directly on printer. Help avoid limitations of QImage class.

Also removed menu option "Save as PDF". The option duplicate option "Export As"
and also mislead a user about purpose of option "Print preview".

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2016-06-15 13:55:43 +03:00
parent 00f854f1d9
commit 972dd36fcf
9 changed files with 280 additions and 246 deletions

View File

@ -3153,7 +3153,6 @@ void MainWindow::SetLayoutModeActions(bool enable)
ui->actionExportAs->setEnabled(value); ui->actionExportAs->setEnabled(value);
ui->actionPrintPreview->setEnabled(value); ui->actionPrintPreview->setEnabled(value);
ui->actionPrintPreviewTiled->setEnabled(value); ui->actionPrintPreviewTiled->setEnabled(value);
ui->actionSaveAsPDF->setEnabled(value);
ui->actionSaveAsTiledPDF->setEnabled(value); ui->actionSaveAsTiledPDF->setEnabled(value);
ui->actionPrint->setEnabled(value); ui->actionPrint->setEnabled(value);
ui->actionPrintTiled->setEnabled(value); ui->actionPrintTiled->setEnabled(value);
@ -3645,7 +3644,6 @@ void MainWindow::CreateActions()
connect(ui->actionExportAs, &QAction::triggered, this, &MainWindow::ExportLayoutAs); connect(ui->actionExportAs, &QAction::triggered, this, &MainWindow::ExportLayoutAs);
connect(ui->actionPrintPreview, &QAction::triggered, this, &MainWindow::PrintPreviewOrigin); connect(ui->actionPrintPreview, &QAction::triggered, this, &MainWindow::PrintPreviewOrigin);
connect(ui->actionPrintPreviewTiled, &QAction::triggered, this, &MainWindow::PrintPreviewTiled); connect(ui->actionPrintPreviewTiled, &QAction::triggered, this, &MainWindow::PrintPreviewTiled);
connect(ui->actionSaveAsPDF, &QAction::triggered, this, &MainWindow::SaveAsPDF);
connect(ui->actionSaveAsTiledPDF, &QAction::triggered, this, &MainWindow::SaveAsTiledPDF); connect(ui->actionSaveAsTiledPDF, &QAction::triggered, this, &MainWindow::SaveAsTiledPDF);
connect(ui->actionPrint, &QAction::triggered, this, &MainWindow::PrintOrigin); connect(ui->actionPrint, &QAction::triggered, this, &MainWindow::PrintOrigin);
connect(ui->actionPrintTiled, &QAction::triggered, this, &MainWindow::PrintTiled); connect(ui->actionPrintTiled, &QAction::triggered, this, &MainWindow::PrintTiled);

View File

@ -1189,7 +1189,6 @@
<property name="title"> <property name="title">
<string>Layout</string> <string>Layout</string>
</property> </property>
<addaction name="actionSaveAsPDF"/>
<addaction name="actionPrintPreview"/> <addaction name="actionPrintPreview"/>
<addaction name="actionPrint"/> <addaction name="actionPrint"/>
<addaction name="separator"/> <addaction name="separator"/>
@ -2048,24 +2047,6 @@
<enum>QAction::NoRole</enum> <enum>QAction::NoRole</enum>
</property> </property>
</action> </action>
<action name="actionSaveAsPDF">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset resource="../../libs/vmisc/share/resources/icon.qrc">
<normaloff>:/icon/32x32/pdf.png</normaloff>:/icon/32x32/pdf.png</iconset>
</property>
<property name="text">
<string>Save as PDF</string>
</property>
<property name="toolTip">
<string>Save original layout</string>
</property>
<property name="shortcut">
<string notr="true"/>
</property>
</action>
<action name="actionSaveAsTiledPDF"> <action name="actionSaveAsTiledPDF">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>

View File

@ -266,19 +266,6 @@ void MainWindowsNoGUI::ExportLayout(const DialogSaveLayout &dialog)
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void MainWindowsNoGUI::SaveAsPDF()
{
if (not isPagesUniform())
{
qCritical()<<tr("For saving multipage document all sheet should have the same size. Use export "
"function instead.");
return;
}
isTiled = false;
SaveLayoutAs();
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void MainWindowsNoGUI::SaveAsTiledPDF() void MainWindowsNoGUI::SaveAsTiledPDF()
{ {
@ -289,26 +276,13 @@ void MainWindowsNoGUI::SaveAsTiledPDF()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void MainWindowsNoGUI::PrintPages(QPrinter *printer) void MainWindowsNoGUI::PrintPages(QPrinter *printer)
{ {
if (printer == nullptr) // Here we try understand difference between printer's dpi and our.
{ // Get printer rect acording to our dpi.
return; const QRectF printerPageRect(0, 0, ToPixel(printer->pageRect(QPrinter::Millimeter).width(), Unit::Mm),
} ToPixel(printer->pageRect(QPrinter::Millimeter).height(), Unit::Mm));
const double xscale = printer->pageRect().width() / printerPageRect.width();
const QVector<QImage> images = AllSheets(printer); const double yscale = printer->pageRect().height() / printerPageRect.height();
const double scale = qMin(xscale, yscale);
QVector<QImage> poster;
if (isTiled)
{
VPoster posterazor(printer);
for (int i=0; i < images.size(); i++)
{
poster += posterazor.Generate(images.at(i), i+1, images.size());
}
}
else
{
poster = images;
}
QPainter painter; QPainter painter;
if (not painter.begin(printer)) if (not painter.begin(printer))
@ -317,9 +291,40 @@ void MainWindowsNoGUI::PrintPages(QPrinter *printer)
return; return;
} }
painter.setFont( QFont( "Arial", 8, QFont::Normal ) );
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(QPen(Qt::black, qApp->toPixel(WidthMainLine(*pattern->GetPatternUnit())), Qt::SolidLine,
Qt::RoundCap, Qt::RoundJoin));
painter.setBrush ( QBrush ( Qt::NoBrush ) );
int count = 0;
QSharedPointer<QVector<PosterData>> poster;
QSharedPointer<VPoster> posterazor;
if (isTiled)
{
poster = QSharedPointer<QVector<PosterData>>(new QVector<PosterData>());
posterazor = QSharedPointer<VPoster>(new VPoster(printer));
for (int i=0; i < scenes.size(); ++i)
{
auto *paper = qgraphicsitem_cast<QGraphicsRectItem *>(papers.at(i));
if (paper)
{
*poster += posterazor->Calc(paper->rect().toRect(), i);
}
}
count = poster->size();
}
else
{
count = scenes.size();
}
// Handle the fromPage(), toPage(), supportsMultipleCopies(), and numCopies() values from QPrinter. // Handle the fromPage(), toPage(), supportsMultipleCopies(), and numCopies() values from QPrinter.
int firstPage = printer->fromPage() - 1; int firstPage = printer->fromPage() - 1;
if (firstPage >= poster.size()) if (firstPage >= count)
{ {
return; return;
} }
@ -329,9 +334,9 @@ void MainWindowsNoGUI::PrintPages(QPrinter *printer)
} }
int lastPage = printer->toPage() - 1; int lastPage = printer->toPage() - 1;
if (lastPage == -1 || lastPage >= poster.size()) if (lastPage == -1 || lastPage >= count)
{ {
lastPage = poster.size() - 1; lastPage = count - 1;
} }
const int numPages = lastPage - firstPage + 1; const int numPages = lastPage - firstPage + 1;
@ -362,7 +367,38 @@ void MainWindowsNoGUI::PrintPages(QPrinter *printer)
{ {
index = lastPage - j; index = lastPage - j;
} }
painter.drawImage(QPointF(), poster.at(index));
int paperIndex = -1;
isTiled ? paperIndex = poster->at(index).index : paperIndex = index;
auto *paper = qgraphicsitem_cast<QGraphicsRectItem *>(papers.at(paperIndex));
if (paper)
{
QVector<QGraphicsItem *> posterData;
if (isTiled)
{
// Draw borders
posterData = posterazor->Borders(paper, poster->at(index), scenes.size());
}
PreparePaper(paperIndex);
// Render
QRectF source;
isTiled ? source = poster->at(index).rect : source = paper->rect();
QRectF target(0, 0, source.width() * scale, source.height() * scale);
scenes.at(paperIndex)->render(&painter, target, source, Qt::IgnoreAspectRatio);
if (isTiled)
{
// Remove borders
qDeleteAll(posterData);
}
// Restore
RestorePaper(paperIndex);
}
} }
} }
@ -738,62 +774,31 @@ void MainWindowsNoGUI::DxfFile(const QString &name, int i) const
#endif #endif
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QVector<QImage> MainWindowsNoGUI::AllSheets(const QPrinter *printer) const void MainWindowsNoGUI::PreparePaper(int index) const
{ {
QVector<QImage> images; auto *paper = qgraphicsitem_cast<QGraphicsRectItem *>(papers.at(index));
for (int i=0; i < scenes.size(); ++i) if (paper)
{ {
QGraphicsRectItem *paper = qgraphicsitem_cast<QGraphicsRectItem *>(papers.at(i)); QBrush brush(Qt::white);
if (paper) scenes.at(index)->setBackgroundBrush(brush);
{ shadows.at(index)->setVisible(false);
// Hide shadow and paper border paper->setPen(QPen(Qt::white, 0.1, Qt::NoPen));// border
QBrush *brush = new QBrush(); }
brush->setColor( QColor( Qt::white ) );
scenes[i]->setBackgroundBrush( *brush ); }
shadows[i]->setVisible(false);
paper->setPen(QPen(Qt::white, 0.1, Qt::NoPen));// border //---------------------------------------------------------------------------------------------------------------------
void MainWindowsNoGUI::RestorePaper(int index) const
// Render png {
const QRectF source = paper->rect(); auto *paper = qgraphicsitem_cast<QGraphicsRectItem *>(papers.at(index));
QRectF target = source; if (paper)
{
if (printer) // Restore
{ paper->setPen(QPen(Qt::black, qApp->toPixel(WidthMainLine(*pattern->GetPatternUnit()))));
// Here we try understand difference between printer's dpi and our. QBrush brush(Qt::gray);
// Get printer rect acording to our dpi. scenes.at(index)->setBackgroundBrush(brush);
const QRectF printerPageRect(0, 0, ToPixel(printer->pageSizeMM().width(), Unit::Mm), shadows.at(index)->setVisible(true);
ToPixel(printer->pageSizeMM().height(), Unit::Mm));
const double xscale = printer->pageRect().width() / printerPageRect.width();
const double yscale = printer->pageRect().height() / printerPageRect.height();
const double scale = qMin(xscale, yscale);
target.setWidth(target.width() * scale);
target.setHeight(target.height() * scale);
}
// Create the image with the exact size of the shrunk scene
QImage image(QSize(static_cast<qint32>(target.width()), static_cast<qint32>(target.height())),
QImage::Format_RGB32);
image.fill(Qt::white);
QPainter painter(&image);
painter.setFont( QFont( "Arial", 8, QFont::Normal ) );
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(QPen(Qt::black, qApp->toPixel(WidthMainLine(*pattern->GetPatternUnit())), Qt::SolidLine,
Qt::RoundCap, Qt::RoundJoin));
painter.setBrush ( QBrush ( Qt::NoBrush ) );
scenes.at(i)->render(&painter, target, source, Qt::IgnoreAspectRatio);
painter.end();
images.append(image);
// Restore
paper->setPen(QPen(Qt::black, qApp->toPixel(WidthMainLine(*pattern->GetPatternUnit()))));
brush->setColor( QColor( Qt::gray ) );
brush->setStyle( Qt::SolidPattern );
scenes[i]->setBackgroundBrush( *brush );
shadows[i]->setVisible(true);
delete brush;
}
} }
return images;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -855,7 +860,7 @@ void MainWindowsNoGUI::PrintPreview()
SetPrinterSettings(printer.data(), PrintType::PrintPreview); SetPrinterSettings(printer.data(), PrintType::PrintPreview);
printer->setResolution(static_cast<int>(PrintDPI)); printer->setResolution(static_cast<int>(PrintDPI));
// display print preview dialog // display print preview dialog
QPrintPreviewDialog preview(printer.data()); QPrintPreviewDialog preview(printer.data());
connect(&preview, &QPrintPreviewDialog::paintRequested, this, &MainWindowsNoGUI::PrintPages); connect(&preview, &QPrintPreviewDialog::paintRequested, this, &MainWindowsNoGUI::PrintPages);
preview.exec(); preview.exec();
} }
@ -897,21 +902,16 @@ void MainWindowsNoGUI::SetPrinterSettings(QPrinter *printer, const PrintType &pr
printer->setCreator(qApp->applicationDisplayName()+" "+qApp->applicationVersion()); printer->setCreator(qApp->applicationDisplayName()+" "+qApp->applicationVersion());
// Set orientation // Set orientation
if (papers.size() > 0) if (paperSize.height() >= paperSize.width())
{ {
QGraphicsRectItem *paper = qgraphicsitem_cast<QGraphicsRectItem *>(papers.at(0)); printer->setOrientation(QPrinter::Portrait);
SCASSERT(paper != nullptr) }
if (paper->rect().height()>= paper->rect().width()) else
{ {
printer->setOrientation(QPrinter::Portrait); printer->setOrientation(QPrinter::Landscape);
}
else
{
printer->setOrientation(QPrinter::Landscape);
}
} }
if (not isTiled && papers.size() > 0) if (not isTiled)
{ {
const QSizeF size = QSizeF(FromPixel(paperSize.width(), Unit::Mm), FromPixel(paperSize.height(), Unit::Mm)); const QSizeF size = QSizeF(FromPixel(paperSize.width(), Unit::Mm), FromPixel(paperSize.height(), Unit::Mm));
const QPrinter::PageSize pSZ = FindTemplate(size); const QPrinter::PageSize pSZ = FindTemplate(size);
@ -968,13 +968,33 @@ void MainWindowsNoGUI::SetPrinterSettings(QPrinter *printer, const PrintType &pr
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool MainWindowsNoGUI::IsLayoutGrayscale() const bool MainWindowsNoGUI::IsLayoutGrayscale() const
{ {
const QVector<QImage> images = AllSheets(); const QRect target = QRect(0, 0, 100, 100);//Small image less memory need
for(int i=0; i < images.size(); ++i) for (int i=0; i < scenes.size(); ++i)
{ {
if (not images.at(i).isGrayscale()) auto *paper = qgraphicsitem_cast<QGraphicsRectItem *>(papers.at(i));
if (paper)
{ {
return false; // Hide shadow and paper border
PreparePaper(i);
// Render png
QImage image(target.size(), QImage::Format_RGB32);
image.fill(Qt::white);
QPainter painter(&image);
painter.setPen(QPen(Qt::black, qApp->toPixel(WidthMainLine(*pattern->GetPatternUnit())), Qt::SolidLine,
Qt::RoundCap, Qt::RoundJoin));
painter.setBrush ( QBrush ( Qt::NoBrush ) );
scenes.at(i)->render(&painter, target, paper->rect(), Qt::KeepAspectRatio);
painter.end();
// Restore
RestorePaper(i);
if (not image.isGrayscale())
{
return false;
}
} }
} }
@ -1031,11 +1051,11 @@ bool MainWindowsNoGUI::isPagesUniform() const
} }
else else
{ {
QGraphicsRectItem *paper = qgraphicsitem_cast<QGraphicsRectItem *>(papers.at(0)); auto *paper = qgraphicsitem_cast<QGraphicsRectItem *>(papers.at(0));
SCASSERT(paper != nullptr) SCASSERT(paper != nullptr)
for (int i=1; i < papers.size(); ++i) for (int i=1; i < papers.size(); ++i)
{ {
QGraphicsRectItem *p = qgraphicsitem_cast<QGraphicsRectItem *>(papers.at(i)); auto *p = qgraphicsitem_cast<QGraphicsRectItem *>(papers.at(i));
SCASSERT(p != nullptr) SCASSERT(p != nullptr)
if (paper->rect() != p->rect()) if (paper->rect() != p->rect())
{ {

View File

@ -41,7 +41,7 @@
class QGraphicsScene; class QGraphicsScene;
class QPrinter; class QPrinter;
class PosterData;
class MainWindowsNoGUI : public QMainWindow class MainWindowsNoGUI : public QMainWindow
{ {
@ -53,7 +53,6 @@ public:
public slots: public slots:
void ToolLayoutSettings(bool checked); void ToolLayoutSettings(bool checked);
void ExportLayoutAs(); void ExportLayoutAs();
void SaveAsPDF();
void SaveAsTiledPDF(); void SaveAsTiledPDF();
void PrintPages (QPrinter *printer); void PrintPages (QPrinter *printer);
void PrintPreviewOrigin(); void PrintPreviewOrigin();
@ -117,7 +116,8 @@ private:
void ObjFile(const QString &name, int i)const; void ObjFile(const QString &name, int i)const;
void DxfFile(const QString &name, int i)const; void DxfFile(const QString &name, int i)const;
QVector<QImage> AllSheets(const QPrinter *printer = nullptr) const; void PreparePaper(int index) const;
void RestorePaper(int index) const;
void SaveLayoutAs(); void SaveLayoutAs();
void PrintPreview(); void PrintPreview();

View File

@ -27,8 +27,9 @@
*************************************************************************/ *************************************************************************/
#include "vposter.h" #include "vposter.h"
#include <QPainter>
#include <QPrinter> #include <QPrinter>
#include <QGraphicsLineItem>
#include <QPen>
#if QT_VERSION < QT_VERSION_CHECK(5, 1, 0) #if QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
# include "../vmisc/vmath.h" # include "../vmisc/vmath.h"
@ -40,36 +41,126 @@
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPoster::VPoster(const QPrinter *printer) VPoster::VPoster(const QPrinter *printer)
:printer(printer), allowence(static_cast<quint32>(qRound(10./25.4*printer->resolution())))//1 cm :printer(printer), allowence(static_cast<quint32>(qRound(10./25.4*PrintDPI)))//1 cm
{ {
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QVector<QImage> VPoster::Generate(const QImage &image, int page, int sheets) const QVector<PosterData> VPoster::Calc(const QRect &imageRect, int page) const
{ {
QVector<QImage> poster; QVector<PosterData> poster;
if (printer == nullptr) if (printer == nullptr)
{ {
return poster; return poster;
} }
const int rows = CountRows(image.rect().height()); const int rows = CountRows(imageRect.height());
const int columns = CountColumns(image.rect().width()); const int columns = CountColumns(imageRect.width());
for (int i=0; i < rows; i++) for (int i=0; i < rows; i++)
{ {
for (int j=0; j< columns; j++) for (int j=0; j< columns; j++)
{ {
QImage img = Cut(i, j, image); PosterData data = Cut(i, j, imageRect);
img = Borders(rows, columns, i, j, img, page, sheets); data.index = page;
poster.append(img); data.rows = rows;
data.columns = columns;
poster.append(data);
} }
} }
return poster; return poster;
} }
//---------------------------------------------------------------------------------------------------------------------
QVector<QGraphicsItem *> VPoster::Borders(QGraphicsItem *parent, const PosterData &img, int sheets) const
{
QVector<QGraphicsItem *> 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<int>(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<int>(allowence), rec.y(),
rec.x() + rec.width()-static_cast<int>(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<int>(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<int>(allowence),
rec.x() + rec.width(), rec.y() + rec.height()-static_cast<int>(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<int>(allowence),
rec.y() + rec.height()-static_cast<int>(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<int>(allowence)+layoutY);
labels->setTextWidth(rec.width()-(static_cast<int>(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("<table width='100%'>"
"<tr>"
"<td>%1</td><td align='center'>%2</td><td align='right'>%3</td>"
"</tr>"
"</table>")
.arg(grid, page, sheet));
data.append(labels);
return data;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
int VPoster::CountRows(int height) const int VPoster::CountRows(int height) const
{ {
@ -148,96 +239,20 @@ int VPoster::CountColumns(int width) const
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QImage VPoster::Cut(int i, int j, const QImage &image) const PosterData VPoster::Cut(int i, int j, const QRect &imageRect) const
{ {
const int x = j*PageRect().width() - j*static_cast<int>(allowence); const int x = j*PageRect().width() - j*static_cast<int>(allowence);
const int y = i*PageRect().height() - i*static_cast<int>(allowence); const int y = i*PageRect().height() - i*static_cast<int>(allowence);
SCASSERT(x <= image.rect().width()); SCASSERT(x <= imageRect.width());
SCASSERT(y <= image.rect().height()); SCASSERT(y <= imageRect.height());
QRect copyRect(x, y, PageRect().width(), PageRect().height()); PosterData data;
data.row = i;
data.column = j;
data.rect = QRect(x, y, PageRect().width(), PageRect().height());
if (not image.rect().contains(copyRect)) return data;
{
// Create full page with white background
QImage fullPage(copyRect.size(), image.format());
fullPage.fill(Qt::white);
// Real size that we can copy from image.
// Because in areas beyond the image, pixels are set to 0 by copy() method.
// For 32-bit RGB images, this means black.
copyRect = image.rect().intersected(copyRect);
QPainter painter(&fullPage);
painter.drawImage(QPointF(), image.copy( copyRect));
painter.end();
return fullPage;
}
else
{
return image.copy(copyRect);
}
}
//---------------------------------------------------------------------------------------------------------------------
QImage VPoster::Borders(int rows, int columns, int i, int j, QImage &image, int page, int sheets) const
{
QPainter painter(&image);
QPen pen = QPen(Qt::NoBrush, 1, Qt::DashLine);
pen.setColor(Qt::black);
painter.setPen(pen);
const QRect rec = image.rect();
if (j != 0 && PageRect().x() > 0)
{// Left border
painter.drawLine(QLine(0, 0, 0, rec.height()));
painter.drawImage(QPoint(0, rec.height()-static_cast<int>(allowence)),
QImage("://scissors_vertical.png"));
}
if (j != columns-1)
{// Right border
painter.drawLine(QLine(rec.width()-static_cast<int>(allowence), 0,
rec.width()-static_cast<int>(allowence), rec.height()));
}
if (i != 0 && PageRect().y() > 0)
{// Top border
painter.drawLine(QLine(0, 0, rec.width(), 0));
painter.drawImage(QPoint(rec.width()-static_cast<int>(allowence), 0),
QImage("://scissors_horizontal.png"));
}
if (rows*columns > 1)
{ // Don't show bottom border if only one page need
// Bottom border (mandatory)
painter.drawLine(QLine(0, rec.height()-static_cast<int>(allowence),
rec.width(), rec.height()-static_cast<int>(allowence)));
if (i == rows-1)
{
painter.drawImage(QPoint(rec.width()-static_cast<int>(allowence),
rec.height()-static_cast<int>(allowence)),
QImage("://scissors_horizontal.png"));
}
}
// Labels
const int layoutX = 15;
const int layoutY = 5;
QRect labels(layoutX, rec.height()-static_cast<int>(allowence)+layoutY,
rec.width()-(static_cast<int>(allowence)+layoutX), static_cast<int>(allowence)-layoutY);
painter.drawText(labels, Qt::AlignLeft, tr("Grid ( %1 , %2 )").arg(i+1).arg(j+1));
painter.drawText(labels, Qt::AlignHCenter, tr("Page %1 of %2").arg(i*(columns)+j+1).arg(rows*columns));
if (sheets > 1)
{
painter.drawText(labels, Qt::AlignRight, tr("Sheet %1 of %2").arg(page).arg(sheets));
}
painter.end();
return image;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -247,13 +262,12 @@ QRect VPoster::PageRect() const
// we can't use method pageRect(QPrinter::Point). Our dpi value can be different. // we can't use method pageRect(QPrinter::Point). Our dpi value can be different.
// We convert value yourself to pixels. // We convert value yourself to pixels.
const QRectF rect = printer->pageRect(QPrinter::Millimeter); const QRectF rect = printer->pageRect(QPrinter::Millimeter);
const QRect pageRect(qFloor(ToPixel(rect.x())), qFloor(ToPixel(rect.y())), qFloor(ToPixel(rect.width())), const QRect pageRect(0, 0, qFloor(ToPixel(rect.width())), qFloor(ToPixel(rect.height())));
qFloor(ToPixel(rect.height())));
return pageRect; return pageRect;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
qreal VPoster::ToPixel(qreal val) const qreal VPoster::ToPixel(qreal val)
{ {
return val / 25.4 * printer->resolution(); // Mm to pixels with current dpi. return val / 25.4 * PrintDPI; // Mm to pixels with current dpi.
} }

View File

@ -29,11 +29,29 @@
#ifndef VPOSTER_H #ifndef VPOSTER_H
#define VPOSTER_H #define VPOSTER_H
#include <QImage>
#include <QRect> #include <QRect>
#include <QCoreApplication> #include <QCoreApplication>
class QPrinter; class QPrinter;
class QGraphicsItem;
struct PosterData
{
PosterData()
: index(0),
row(0),
column(0),
rows(0),
columns(0),
rect(){}
quint32 index; // paper index
quint32 row; // positions in the greed
quint32 column;
quint32 rows;
quint32 columns;
QRect rect; // rect section
};
class VPoster class VPoster
{ {
@ -41,7 +59,9 @@ class VPoster
public: public:
explicit VPoster(const QPrinter *printer); explicit VPoster(const QPrinter *printer);
QVector<QImage> Generate(const QImage &image, int page, int sheets = 1) const; QVector<PosterData> Calc(const QRect &imageRect, int page) const;
QVector<QGraphicsItem *> Borders(QGraphicsItem *parent, const PosterData &img, int sheets) const;
private: private:
const QPrinter *printer; const QPrinter *printer;
quint32 allowence; quint32 allowence;
@ -49,12 +69,12 @@ private:
int CountRows(int height) const; int CountRows(int height) const;
int CountColumns(int width) const; int CountColumns(int width) const;
QImage Cut(int i, int j, const QImage &image) const; PosterData Cut(int i, int j, const QRect &imageRect) const;
QImage Borders(int rows, int columns, int i, int j, QImage &image, int page, int sheets) const; QImage Borders(int rows, int columns, int i, int j, QImage &image, int page, int sheets) const;
QRect PageRect() const; QRect PageRect() const;
qreal ToPixel(qreal val) const; static qreal ToPixel(qreal val);
}; };
#endif // VPOSTER_H #endif // VPOSTER_H

View File

@ -1767,7 +1767,7 @@ QSharedPointer<QPrinter> DefaultPrinter(QPrinter::PrinterMode mode)
} }
} }
QSharedPointer<QPrinter> printer = QSharedPointer<QPrinter>(new QPrinter(def, mode)); auto printer = QSharedPointer<QPrinter>(new QPrinter(def, mode));
printer->setResolution(static_cast<int>(PrintDPI)); printer->setResolution(static_cast<int>(PrintDPI));
return printer; return printer;
} }

View File

@ -28,6 +28,7 @@
#include "tst_vposter.h" #include "tst_vposter.h"
#include "../vlayout/vposter.h" #include "../vlayout/vposter.h"
#include "../vmisc/def.h"
#include <QImage> #include <QImage>
#include <QPrinter> #include <QPrinter>
@ -49,15 +50,15 @@ void TST_VPoster::BigPoster()
printer.setFullPage(true); printer.setFullPage(true);
// We need to set full page because otherwise QPrinter->pageRect returns different values in Windows and Linux // We need to set full page because otherwise QPrinter->pageRect returns different values in Windows and Linux
const QImage image(2622, 3178, QImage::Format_RGB32); // Little bit bigger than A1 const QRect image(0, 0, 2622, 3178); // Little bit bigger than A1
VPoster posterazor(&printer); VPoster posterazor(&printer);
const QVector<QImage> poster = posterazor.Generate(image, 1, 1); const QVector<PosterData> poster = posterazor.Calc(image, 0);
QCOMPARE(poster.size(), 12); QCOMPARE(poster.size(), 12);
for (int i=0; i < poster.size(); i++) for (int i=0; i < poster.size(); i++)
{ {
QCOMPARE(poster.at(i).rect().size(), PageRect(printer).size()); QCOMPARE(poster.at(i).rect.size(), PageRect(printer).size());
} }
} }
@ -69,13 +70,13 @@ void TST_VPoster::SmallPoster()
printer.setResolution(96);// By default printer.setResolution(96);// By default
printer.setPaperSize(QPrinter::A4); printer.setPaperSize(QPrinter::A4);
const QImage image(700, 1000, QImage::Format_RGB32); // Little bit less than A4 const QRect image(0, 0, 700, 1000); // Little bit less than A4
VPoster posterazor(&printer); VPoster posterazor(&printer);
const QVector<QImage> poster = posterazor.Generate(image, 1, 1); const QVector<PosterData> poster = posterazor.Calc(image, 0);
QCOMPARE(poster.size(), 1); QCOMPARE(poster.size(), 1);
QCOMPARE(poster.at(0).rect().size(), PageRect(printer).size()); QCOMPARE(poster.at(0).rect.size(), PageRect(printer).size());
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -85,13 +86,13 @@ QRect TST_VPoster::PageRect(const QPrinter &printer) const
// we can't use method pageRect(QPrinter::Point). Our dpi different can be different. // we can't use method pageRect(QPrinter::Point). Our dpi different can be different.
// We convert value yourself to pixels. // We convert value yourself to pixels.
const QRectF rect = printer.pageRect(QPrinter::Millimeter); const QRectF rect = printer.pageRect(QPrinter::Millimeter);
QRect pageRect(qFloor(ToPixel(rect.x(), printer)), qFloor(ToPixel(rect.y(), printer)), QRect pageRect(qFloor(ToPixel(rect.x())), qFloor(ToPixel(rect.y())),
qFloor(ToPixel(rect.width(), printer)), qFloor(ToPixel(rect.height(), printer))); qFloor(ToPixel(rect.width())), qFloor(ToPixel(rect.height())));
return pageRect; return pageRect;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
qreal TST_VPoster::ToPixel(qreal val, const QPrinter &printer) const qreal TST_VPoster::ToPixel(qreal val) const
{ {
return val / 25.4 * printer.resolution(); // Mm to pixels with current dpi. return val / 25.4 * PrintDPI; // Mm to pixels with current dpi.
} }

View File

@ -47,7 +47,7 @@ private slots:
void SmallPoster(); void SmallPoster();
private: private:
qreal ToPixel(qreal val, const QPrinter &printer) const; qreal ToPixel(qreal val) const;
QRect PageRect(const QPrinter &printer) const; QRect PageRect(const QPrinter &printer) const;
}; };