mirror of https://github.com/JakubMelka/PDF4QT.git
Rendering tool + benchmarking tool
This commit is contained in:
parent
428e5dc2ad
commit
3c512d0e98
|
@ -374,7 +374,7 @@ public:
|
||||||
|
|
||||||
/// Font cache which caches both fonts, and realized fonts. Cache has individual limit
|
/// Font cache which caches both fonts, and realized fonts. Cache has individual limit
|
||||||
/// for fonts, and realized fonts.
|
/// for fonts, and realized fonts.
|
||||||
class PDFFontCache
|
class PDFFORQTLIBSHARED_EXPORT PDFFontCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline explicit PDFFontCache(size_t fontCacheLimit, size_t realizedFontCacheLimit) :
|
inline explicit PDFFontCache(size_t fontCacheLimit, size_t realizedFontCacheLimit) :
|
||||||
|
|
|
@ -400,7 +400,7 @@ void PDFRasterizerPool::render(const std::vector<PDFInteger>& pageIndices,
|
||||||
QElapsedTimer timer;
|
QElapsedTimer timer;
|
||||||
timer.start();
|
timer.start();
|
||||||
|
|
||||||
emit renderError(PDFRenderError(RenderErrorType::Information, PDFTranslationContext::tr("Start at %1...").arg(QTime::currentTime().toString(Qt::TextDate))));
|
emit renderError(PDFCatalog::INVALID_PAGE_INDEX, PDFRenderError(RenderErrorType::Information, PDFTranslationContext::tr("Start at %1...").arg(QTime::currentTime().toString(Qt::TextDate))));
|
||||||
|
|
||||||
if (progress)
|
if (progress)
|
||||||
{
|
{
|
||||||
|
@ -419,19 +419,27 @@ void PDFRasterizerPool::render(const std::vector<PDFInteger>& pageIndices,
|
||||||
{
|
{
|
||||||
progress->step();
|
progress->step();
|
||||||
}
|
}
|
||||||
emit renderError(PDFRenderError(RenderErrorType::Error, PDFTranslationContext::tr("Page %1 not found.").arg(pageIndex)));
|
emit renderError(pageIndex, PDFRenderError(RenderErrorType::Error, PDFTranslationContext::tr("Page %1 not found.").arg(pageIndex)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QElapsedTimer totalPageTimer;
|
||||||
|
totalPageTimer.start();
|
||||||
|
|
||||||
|
QElapsedTimer pageTimer;
|
||||||
|
pageTimer.start();
|
||||||
|
|
||||||
// Precompile the page
|
// Precompile the page
|
||||||
PDFPrecompiledPage precompiledPage;
|
PDFPrecompiledPage precompiledPage;
|
||||||
PDFCMSPointer cms = m_cmsManager->getCurrentCMS();
|
PDFCMSPointer cms = m_cmsManager->getCurrentCMS();
|
||||||
PDFRenderer renderer(m_document, m_fontCache, cms.data(), m_optionalContentActivity, m_features, m_meshQualitySettings);
|
PDFRenderer renderer(m_document, m_fontCache, cms.data(), m_optionalContentActivity, m_features, m_meshQualitySettings);
|
||||||
renderer.compile(&precompiledPage, pageIndex);
|
renderer.compile(&precompiledPage, pageIndex);
|
||||||
|
|
||||||
for (const PDFRenderError error : precompiledPage.getErrors())
|
qint64 pageCompileTime = pageTimer.restart();
|
||||||
|
|
||||||
|
for (const PDFRenderError& error : precompiledPage.getErrors())
|
||||||
{
|
{
|
||||||
emit renderError(PDFRenderError(error.type, PDFTranslationContext::tr("Page %1: %2").arg(pageIndex + 1).arg(error.message)));
|
emit renderError(pageIndex, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can const-cast here, because we do not modify the document in annotation manager.
|
// We can const-cast here, because we do not modify the document in annotation manager.
|
||||||
|
@ -443,12 +451,22 @@ void PDFRasterizerPool::render(const std::vector<PDFInteger>& pageIndices,
|
||||||
annotationManager.setDocument(modifiedDocument);
|
annotationManager.setDocument(modifiedDocument);
|
||||||
|
|
||||||
// Render page to image
|
// Render page to image
|
||||||
|
pageTimer.restart();
|
||||||
PDFRasterizer* rasterizer = acquire();
|
PDFRasterizer* rasterizer = acquire();
|
||||||
|
qint64 pageWaitTime = pageTimer.restart();
|
||||||
QImage image = rasterizer->render(pageIndex, page, &precompiledPage, imageSizeGetter(page), m_features, &annotationManager);
|
QImage image = rasterizer->render(pageIndex, page, &precompiledPage, imageSizeGetter(page), m_features, &annotationManager);
|
||||||
|
qint64 pageRenderTime = pageTimer.elapsed();
|
||||||
release(rasterizer);
|
release(rasterizer);
|
||||||
|
|
||||||
// Now, process the image
|
// Now, process the image
|
||||||
processImage(pageIndex, qMove(image));
|
PDFRenderedPageImage renderedPageImage;
|
||||||
|
renderedPageImage.pageIndex = pageIndex;
|
||||||
|
renderedPageImage.pageImage = qMove(image);
|
||||||
|
renderedPageImage.pageCompileTime = pageCompileTime;
|
||||||
|
renderedPageImage.pageWaitTime = pageWaitTime;
|
||||||
|
renderedPageImage.pageRenderTime = pageRenderTime;
|
||||||
|
renderedPageImage.pageTotalTime = totalPageTimer.elapsed();
|
||||||
|
processImage(renderedPageImage);
|
||||||
|
|
||||||
if (progress)
|
if (progress)
|
||||||
{
|
{
|
||||||
|
@ -462,14 +480,19 @@ void PDFRasterizerPool::render(const std::vector<PDFInteger>& pageIndices,
|
||||||
progress->finish();
|
progress->finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
emit renderError(PDFRenderError(RenderErrorType::Information, PDFTranslationContext::tr("Finished at %1...").arg(QTime::currentTime().toString(Qt::TextDate))));
|
emit renderError(PDFCatalog::INVALID_PAGE_INDEX, PDFRenderError(RenderErrorType::Information, PDFTranslationContext::tr("Finished at %1...").arg(QTime::currentTime().toString(Qt::TextDate))));
|
||||||
emit renderError(PDFRenderError(RenderErrorType::Information, PDFTranslationContext::tr("%1 miliseconds elapsed to render %2 pages...").arg(timer.nsecsElapsed() / 1000000).arg(pageIndices.size())));
|
emit renderError(PDFCatalog::INVALID_PAGE_INDEX, PDFRenderError(RenderErrorType::Information, PDFTranslationContext::tr("%1 miliseconds elapsed to render %2 pages...").arg(timer.nsecsElapsed() / 1000000).arg(pageIndices.size())));
|
||||||
}
|
}
|
||||||
|
|
||||||
int PDFRasterizerPool::getDefaultRasterizerCount()
|
int PDFRasterizerPool::getDefaultRasterizerCount()
|
||||||
{
|
{
|
||||||
int hint = QThread::idealThreadCount() / 2;
|
int hint = QThread::idealThreadCount() / 2;
|
||||||
return qBound(1, hint, 16);
|
return getCorrectedRasterizerCount(hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PDFRasterizerPool::getCorrectedRasterizerCount(int rasterizerCount)
|
||||||
|
{
|
||||||
|
return qBound(1, rasterizerCount, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFImageWriterSettings::PDFImageWriterSettings()
|
PDFImageWriterSettings::PDFImageWriterSettings()
|
||||||
|
@ -833,7 +856,7 @@ std::vector<PDFInteger> PDFPageImageExportSettings::getPages() const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PDFPageImageExportSettings::getOutputFileName(PDFInteger pageIndex, const QByteArray& outputFormat)
|
QString PDFPageImageExportSettings::getOutputFileName(PDFInteger pageIndex, const QByteArray& outputFormat) const
|
||||||
{
|
{
|
||||||
QString fileName = m_fileTemplate;
|
QString fileName = m_fileTemplate;
|
||||||
fileName.replace('%', QString::number(pageIndex + 1));
|
fileName.replace('%', QString::number(pageIndex + 1));
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <QSemaphore>
|
#include <QSemaphore>
|
||||||
#include <QImageWriter>
|
#include <QImageWriter>
|
||||||
#include <QSurfaceFormat>
|
#include <QSurfaceFormat>
|
||||||
|
#include <QImage>
|
||||||
|
|
||||||
class QPainter;
|
class QPainter;
|
||||||
class QOpenGLContext;
|
class QOpenGLContext;
|
||||||
|
@ -168,6 +169,17 @@ private:
|
||||||
QOpenGLFramebufferObject* m_fbo;
|
QOpenGLFramebufferObject* m_fbo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Simple structure for storing rendered page images
|
||||||
|
struct PDFRenderedPageImage
|
||||||
|
{
|
||||||
|
qint64 pageCompileTime = 0;
|
||||||
|
qint64 pageWaitTime = 0;
|
||||||
|
qint64 pageRenderTime = 0;
|
||||||
|
qint64 pageTotalTime = 0;
|
||||||
|
PDFInteger pageIndex;
|
||||||
|
QImage pageImage;
|
||||||
|
};
|
||||||
|
|
||||||
/// Pool of page image renderers. It can use predefined number of renderers to
|
/// Pool of page image renderers. It can use predefined number of renderers to
|
||||||
/// render page images asynchronously. You can use this object in two ways -
|
/// render page images asynchronously. You can use this object in two ways -
|
||||||
/// first one is as standard object pool, second one is to directly render
|
/// first one is as standard object pool, second one is to directly render
|
||||||
|
@ -181,8 +193,9 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
using PageImageSizeGetter = std::function<QSize(const PDFPage*)>;
|
using PageImageSizeGetter = std::function<QSize(const PDFPage*)>;
|
||||||
using ProcessImageMethod = std::function<void(PDFInteger, QImage&&)>;
|
using ProcessImageMethod = std::function<void(PDFRenderedPageImage&)>;
|
||||||
|
|
||||||
/// Creates new rasterizer pool
|
/// Creates new rasterizer pool
|
||||||
/// \param document Document
|
/// \param document Document
|
||||||
|
@ -229,8 +242,15 @@ public:
|
||||||
/// Returns default rasterizer count
|
/// Returns default rasterizer count
|
||||||
static int getDefaultRasterizerCount();
|
static int getDefaultRasterizerCount();
|
||||||
|
|
||||||
|
/// Returns corrected rasterizer count (so, if user
|
||||||
|
/// select too high or too low rasterizer count, this function
|
||||||
|
/// corrects it to acceptable number.
|
||||||
|
/// \param rasterizerCount Requested number of rasterizers
|
||||||
|
/// \returns Corrected number of rasterizers
|
||||||
|
static int getCorrectedRasterizerCount(int rasterizerCount);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void renderError(PDFRenderError error);
|
void renderError(PDFInteger pageIndex, PDFRenderError error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const PDFDocument* m_document;
|
const PDFDocument* m_document;
|
||||||
|
@ -344,7 +364,7 @@ public:
|
||||||
std::vector<PDFInteger> getPages() const;
|
std::vector<PDFInteger> getPages() const;
|
||||||
|
|
||||||
/// Returns output file name for given page
|
/// Returns output file name for given page
|
||||||
QString getOutputFileName(PDFInteger pageIndex, const QByteArray& outputFormat);
|
QString getOutputFileName(PDFInteger pageIndex, const QByteArray& outputFormat) const;
|
||||||
|
|
||||||
static constexpr int getMinDPIResolution() { return 72; }
|
static constexpr int getMinDPIResolution() { return 72; }
|
||||||
static constexpr int getMaxDPIResolution() { return 6000; }
|
static constexpr int getMaxDPIResolution() { return 6000; }
|
||||||
|
|
|
@ -243,9 +243,9 @@ void PDFRenderToImagesDialog::onProgressiveScanWriteChanged(bool value)
|
||||||
m_imageWriterSettings.setProgressiveScanWrite(value);
|
m_imageWriterSettings.setProgressiveScanWrite(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFRenderToImagesDialog::onRenderError(pdf::PDFRenderError error)
|
void PDFRenderToImagesDialog::onRenderError(pdf::PDFInteger pageIndex, pdf::PDFRenderError error)
|
||||||
{
|
{
|
||||||
ui->progressMessagesEdit->setPlainText(QString("%1\n%2").arg(ui->progressMessagesEdit->toPlainText()).arg(error.message));
|
ui->progressMessagesEdit->setPlainText(QString("%1\n%2").arg(ui->progressMessagesEdit->toPlainText()).arg(tr("Page %1: %2").arg(pageIndex + 1).arg(error.message)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFRenderToImagesDialog::onRenderingFinished()
|
void PDFRenderToImagesDialog::onRenderingFinished()
|
||||||
|
@ -319,9 +319,9 @@ void PDFRenderToImagesDialog::on_buttonBox_clicked(QAbstractButton* button)
|
||||||
return QSize();
|
return QSize();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto processImage = [this](const pdf::PDFInteger pageIndex, QImage&& image)
|
auto processImage = [this](pdf::PDFRenderedPageImage& renderedPageImage)
|
||||||
{
|
{
|
||||||
QString fileName = m_imageExportSettings.getOutputFileName(pageIndex, m_imageWriterSettings.getCurrentFormat());
|
QString fileName = m_imageExportSettings.getOutputFileName(renderedPageImage.pageIndex, m_imageWriterSettings.getCurrentFormat());
|
||||||
|
|
||||||
QImageWriter imageWriter(fileName, m_imageWriterSettings.getCurrentFormat());
|
QImageWriter imageWriter(fileName, m_imageWriterSettings.getCurrentFormat());
|
||||||
imageWriter.setSubType(m_imageWriterSettings.getCurrentSubtype());
|
imageWriter.setSubType(m_imageWriterSettings.getCurrentSubtype());
|
||||||
|
@ -331,9 +331,9 @@ void PDFRenderToImagesDialog::on_buttonBox_clicked(QAbstractButton* button)
|
||||||
imageWriter.setOptimizedWrite(m_imageWriterSettings.hasOptimizedWrite());
|
imageWriter.setOptimizedWrite(m_imageWriterSettings.hasOptimizedWrite());
|
||||||
imageWriter.setProgressiveScanWrite(m_imageWriterSettings.hasProgressiveScanWrite());
|
imageWriter.setProgressiveScanWrite(m_imageWriterSettings.hasProgressiveScanWrite());
|
||||||
|
|
||||||
if (!imageWriter.write(image))
|
if (!imageWriter.write(renderedPageImage.pageImage))
|
||||||
{
|
{
|
||||||
emit m_rasterizerPool->renderError(pdf::PDFRenderError(pdf::RenderErrorType::Error, tr("Can't write page image to file '%1', because: %2.").arg(fileName).arg(imageWriter.errorString())));
|
emit m_rasterizerPool->renderError(renderedPageImage.pageIndex, pdf::PDFRenderError(pdf::RenderErrorType::Error, tr("Cannot write page image to file '%1', because: %2.").arg(fileName).arg(imageWriter.errorString())));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ private:
|
||||||
void onGammaChanged(double value);
|
void onGammaChanged(double value);
|
||||||
void onOptimizedWriteChanged(bool value);
|
void onOptimizedWriteChanged(bool value);
|
||||||
void onProgressiveScanWriteChanged(bool value);
|
void onProgressiveScanWriteChanged(bool value);
|
||||||
void onRenderError(pdf::PDFRenderError error);
|
void onRenderError(pdf::PDFInteger pageIndex, pdf::PDFRenderError error);
|
||||||
void onRenderingFinished();
|
void onRenderingFinished();
|
||||||
|
|
||||||
Ui::PDFRenderToImagesDialog* ui;
|
Ui::PDFRenderToImagesDialog* ui;
|
||||||
|
|
|
@ -17,12 +17,13 @@
|
||||||
|
|
||||||
#include "pdftoolabstractapplication.h"
|
#include "pdftoolabstractapplication.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QGuiApplication>
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QCoreApplication a(argc, argv);
|
QGuiApplication a(argc, argv);
|
||||||
|
QGuiApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity, true);
|
||||||
QCoreApplication::setOrganizationName("MelkaJ");
|
QCoreApplication::setOrganizationName("MelkaJ");
|
||||||
QCoreApplication::setApplicationName("PdfTool");
|
QCoreApplication::setApplicationName("PdfTool");
|
||||||
QCoreApplication::setApplicationVersion("1.0.0");
|
QCoreApplication::setApplicationVersion("1.0.0");
|
||||||
|
|
|
@ -286,6 +286,10 @@ void PDFToolAbstractApplication::initializeCommandLineParser(QCommandLineParser*
|
||||||
{
|
{
|
||||||
parser->addOption(QCommandLineOption(info.option, info.description, "bool", defaultFeatures.testFlag(info.feature) ? "1" : "0"));
|
parser->addOption(QCommandLineOption(info.option, info.description, "bool", defaultFeatures.testFlag(info.feature) ? "1" : "0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parser->addOption(QCommandLineOption("render-hw-accel", "Use hardware acceleration (using GPU).", "bool", "1"));
|
||||||
|
parser->addOption(QCommandLineOption("render-msaa-samples", "MSAA sample count for GPU rendering.", "samples", "4"));
|
||||||
|
parser->addOption(QCommandLineOption("render-rasterizers", "Number of rasterizer contexts.", "rasterizers", QString::number(pdf::PDFRasterizerPool::getDefaultRasterizerCount())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,6 +760,40 @@ PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser
|
||||||
PDFConsole::writeError(PDFToolTranslationContext::tr("Uknown bool value '%1'. Default value is used.").arg(textValue), options.outputCodec);
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Uknown bool value '%1'. Default value is used.").arg(textValue), options.outputCodec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString textValue = parser->value("render-hw-accel");
|
||||||
|
bool ok = false;
|
||||||
|
bool value = textValue.toInt(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
options.renderUseHardwareRendering = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Uknown bool value '%1'. GPU rendering is used as default.").arg(textValue), options.outputCodec);
|
||||||
|
}
|
||||||
|
|
||||||
|
textValue = parser->value("render-msaa-samples");
|
||||||
|
options.renderMSAAsamples = textValue.toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Uknown MSAA sample count '%1'. 4 samples are used as default.").arg(textValue), options.outputCodec);
|
||||||
|
options.renderMSAAsamples = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
textValue = parser->value("render-rasterizers");
|
||||||
|
options.renderRasterizerCount = textValue.toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
options.renderRasterizerCount = pdf::PDFRasterizerPool::getDefaultRasterizerCount();
|
||||||
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Uknown rasterizer count '%1'. %2 rasterizers are used as default.").arg(textValue).arg(options.renderRasterizerCount), options.outputCodec);
|
||||||
|
}
|
||||||
|
int correctedRasterizerCount = pdf::PDFRasterizerPool::getCorrectedRasterizerCount(options.renderRasterizerCount);
|
||||||
|
if (correctedRasterizerCount != options.renderRasterizerCount)
|
||||||
|
{
|
||||||
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Invalid raterizer count: %1. Correcting to use %2 rasterizers.").arg(options.renderRasterizerCount).arg(correctedRasterizerCount), options.outputCodec);
|
||||||
|
options.renderRasterizerCount = correctedRasterizerCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
|
|
|
@ -124,6 +124,9 @@ struct PDFToolOptions
|
||||||
|
|
||||||
// For option 'RenderFlags'
|
// For option 'RenderFlags'
|
||||||
pdf::PDFRenderer::Features renderFeatures = pdf::PDFRenderer::getDefaultFeatures();
|
pdf::PDFRenderer::Features renderFeatures = pdf::PDFRenderer::getDefaultFeatures();
|
||||||
|
bool renderUseHardwareRendering = true;
|
||||||
|
int renderMSAAsamples = 4;
|
||||||
|
int renderRasterizerCount = pdf::PDFRasterizerPool::getDefaultRasterizerCount();
|
||||||
|
|
||||||
/// Returns page range. If page range is invalid, then \p errorMessage is empty.
|
/// Returns page range. If page range is invalid, then \p errorMessage is empty.
|
||||||
/// \param pageCount Page count
|
/// \param pageCount Page count
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
|
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "pdftoolrender.h"
|
#include "pdftoolrender.h"
|
||||||
|
#include "pdffont.h"
|
||||||
|
#include "pdfconstants.h"
|
||||||
|
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
namespace pdftool
|
namespace pdftool
|
||||||
{
|
{
|
||||||
|
@ -49,6 +53,43 @@ PDFToolAbstractApplication::Options PDFToolRender::getOptionsFlags() const
|
||||||
return ConsoleFormat | OpenDocument | PageSelector | ImageWriterSettings | ImageExportSettingsFiles | ImageExportSettingsResolution | ColorManagementSystem | RenderFlags;
|
return ConsoleFormat | OpenDocument | PageSelector | ImageWriterSettings | ImageExportSettingsFiles | ImageExportSettingsResolution | ColorManagementSystem | RenderFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFToolRender::finish(const PDFToolOptions& options)
|
||||||
|
{
|
||||||
|
PDFOutputFormatter formatter(options.outputStyle, options.outputCodec);
|
||||||
|
formatter.beginDocument("render", PDFToolTranslationContext::tr("Render document %1").arg(options.document));
|
||||||
|
formatter.endl();
|
||||||
|
|
||||||
|
writeStatistics(formatter);
|
||||||
|
writeErrors(formatter);
|
||||||
|
|
||||||
|
formatter.endDocument();
|
||||||
|
PDFConsole::writeText(formatter.getString(), options.outputCodec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFToolRender::onPageRendered(const PDFToolOptions& options, pdf::PDFRenderedPageImage& renderedPageImage)
|
||||||
|
{
|
||||||
|
writePageInfoStatistics(renderedPageImage);
|
||||||
|
QString fileName = options.imageExportSettings.getOutputFileName(renderedPageImage.pageIndex, options.imageWriterSettings.getCurrentFormat());
|
||||||
|
|
||||||
|
QElapsedTimer imageWriterTimer;
|
||||||
|
imageWriterTimer.start();
|
||||||
|
|
||||||
|
QImageWriter imageWriter(fileName, options.imageWriterSettings.getCurrentFormat());
|
||||||
|
imageWriter.setSubType(options.imageWriterSettings.getCurrentSubtype());
|
||||||
|
imageWriter.setCompression(options.imageWriterSettings.getCompression());
|
||||||
|
imageWriter.setQuality(options.imageWriterSettings.getQuality());
|
||||||
|
imageWriter.setGamma(options.imageWriterSettings.getGamma());
|
||||||
|
imageWriter.setOptimizedWrite(options.imageWriterSettings.hasOptimizedWrite());
|
||||||
|
imageWriter.setProgressiveScanWrite(options.imageWriterSettings.hasProgressiveScanWrite());
|
||||||
|
|
||||||
|
if (!imageWriter.write(renderedPageImage.pageImage))
|
||||||
|
{
|
||||||
|
m_pageInfo[renderedPageImage.pageIndex].errors.emplace_back(pdf::PDFRenderError(pdf::RenderErrorType::Error, PDFToolTranslationContext::tr("Cannot write page image to file '%1', because: %2.").arg(fileName).arg(imageWriter.errorString())));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pageInfo[renderedPageImage.pageIndex].pageWriteTime = imageWriterTimer.elapsed();
|
||||||
|
}
|
||||||
|
|
||||||
QString PDFToolBenchmark::getStandardString(PDFToolAbstractApplication::StandardString standardString) const
|
QString PDFToolBenchmark::getStandardString(PDFToolAbstractApplication::StandardString standardString) const
|
||||||
{
|
{
|
||||||
switch (standardString)
|
switch (standardString)
|
||||||
|
@ -75,6 +116,26 @@ PDFToolAbstractApplication::Options PDFToolBenchmark::getOptionsFlags() const
|
||||||
return ConsoleFormat | OpenDocument | PageSelector | ImageExportSettingsResolution | ColorManagementSystem | RenderFlags;
|
return ConsoleFormat | OpenDocument | PageSelector | ImageExportSettingsResolution | ColorManagementSystem | RenderFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFToolBenchmark::finish(const PDFToolOptions& options)
|
||||||
|
{
|
||||||
|
PDFOutputFormatter formatter(options.outputStyle, options.outputCodec);
|
||||||
|
formatter.beginDocument("benchmark", PDFToolTranslationContext::tr("Benchmark rendering of document %1").arg(options.document));
|
||||||
|
formatter.endl();
|
||||||
|
|
||||||
|
writeStatistics(formatter);
|
||||||
|
writePageStatistics(formatter);
|
||||||
|
writeErrors(formatter);
|
||||||
|
|
||||||
|
formatter.endDocument();
|
||||||
|
PDFConsole::writeText(formatter.getString(), options.outputCodec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFToolBenchmark::onPageRendered(const PDFToolOptions& options, pdf::PDFRenderedPageImage& renderedPageImage)
|
||||||
|
{
|
||||||
|
Q_UNUSED(options);
|
||||||
|
writePageInfoStatistics(renderedPageImage);
|
||||||
|
}
|
||||||
|
|
||||||
int PDFToolRenderBase::execute(const PDFToolOptions& options)
|
int PDFToolRenderBase::execute(const PDFToolOptions& options)
|
||||||
{
|
{
|
||||||
pdf::PDFDocument document;
|
pdf::PDFDocument document;
|
||||||
|
@ -85,7 +146,7 @@ int PDFToolRenderBase::execute(const PDFToolOptions& options)
|
||||||
}
|
}
|
||||||
|
|
||||||
QString parseError;
|
QString parseError;
|
||||||
std::vector<pdf::PDFInteger> pages = options.getPageRange(document.getCatalog()->getPageCount(), parseError, true);
|
std::vector<pdf::PDFInteger> pageIndices = options.getPageRange(document.getCatalog()->getPageCount(), parseError, true);
|
||||||
|
|
||||||
if (!parseError.isEmpty())
|
if (!parseError.isEmpty())
|
||||||
{
|
{
|
||||||
|
@ -103,11 +164,39 @@ int PDFToolRenderBase::execute(const PDFToolOptions& options)
|
||||||
|
|
||||||
// We are ready to render the document
|
// We are ready to render the document
|
||||||
pdf::PDFOptionalContentActivity optionalContentActivity(&document, pdf::OCUsage::Export, nullptr);
|
pdf::PDFOptionalContentActivity optionalContentActivity(&document, pdf::OCUsage::Export, nullptr);
|
||||||
m_cms = m_proxy->getCMSManager()->getCurrentCMS();
|
pdf::PDFCMSManager cmsManager(nullptr);
|
||||||
pdf::PDFRasterizerPool rasterizerPool(&document, m_proxy->getFontCache(), m_proxy->getCMSManager(),
|
cmsManager.setSettings(options.cmsSettings);
|
||||||
&optionalContentActivity, m_proxy->getFeatures(), m_proxy->getMeshQualitySettings(),
|
pdf::PDFMeshQualitySettings meshQualitySettings;
|
||||||
pdf::PDFRasterizerPool::getDefaultRasterizerCount(), m_proxy->isUsingOpenGL(), m_proxy->getSurfaceFormat(), this);
|
pdf::PDFFontCache fontCache(pdf::DEFAULT_FONT_CACHE_LIMIT, pdf::DEFAULT_REALIZED_FONT_CACHE_LIMIT);
|
||||||
connect(&rasterizerPool, &pdf::PDFRasterizerPool::renderError, this, &PDFRenderToImagesDialog::onRenderError);
|
pdf::PDFModifiedDocument md(&document, &optionalContentActivity);
|
||||||
|
fontCache.setDocument(md);
|
||||||
|
fontCache.setCacheShrinkEnabled(nullptr, false);
|
||||||
|
|
||||||
|
QSurfaceFormat surfaceFormat;
|
||||||
|
if (options.renderUseHardwareRendering)
|
||||||
|
{
|
||||||
|
surfaceFormat = QSurfaceFormat::defaultFormat();
|
||||||
|
surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
|
||||||
|
surfaceFormat.setSamples(options.renderMSAAsamples);
|
||||||
|
surfaceFormat.setColorSpace(QSurfaceFormat::sRGBColorSpace);
|
||||||
|
surfaceFormat.setSwapBehavior(QSurfaceFormat::DefaultSwapBehavior);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pageInfo.resize(document.getCatalog()->getPageCount());
|
||||||
|
pdf::PDFRasterizerPool rasterizerPool(&document, &fontCache, &cmsManager,
|
||||||
|
&optionalContentActivity, options.renderFeatures, meshQualitySettings,
|
||||||
|
pdf::PDFRasterizerPool::getCorrectedRasterizerCount(options.renderRasterizerCount),
|
||||||
|
options.renderUseHardwareRendering, surfaceFormat, nullptr);
|
||||||
|
|
||||||
|
auto onRenderError = [this](pdf::PDFInteger pageIndex, pdf::PDFRenderError error)
|
||||||
|
{
|
||||||
|
if (pageIndex != pdf::PDFCatalog::INVALID_PAGE_INDEX)
|
||||||
|
{
|
||||||
|
m_pageInfo[pageIndex].errors.emplace_back(qMove(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
QObject holder;
|
||||||
|
QObject::connect(&rasterizerPool, &pdf::PDFRasterizerPool::renderError, &holder, onRenderError, Qt::DirectConnection);
|
||||||
|
|
||||||
auto imageSizeGetter = [&options](const pdf::PDFPage* page) -> QSize
|
auto imageSizeGetter = [&options](const pdf::PDFPage* page) -> QSize
|
||||||
{
|
{
|
||||||
|
@ -138,27 +227,198 @@ int PDFToolRenderBase::execute(const PDFToolOptions& options)
|
||||||
return QSize();
|
return QSize();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto processImage = [this](const pdf::PDFInteger pageIndex, QImage&& image)
|
QElapsedTimer timer;
|
||||||
{
|
timer.start();
|
||||||
QString fileName = m_imageExportSettings.getOutputFileName(pageIndex, m_imageWriterSettings.getCurrentFormat());
|
|
||||||
|
|
||||||
QImageWriter imageWriter(fileName, m_imageWriterSettings.getCurrentFormat());
|
rasterizerPool.render(pageIndices, imageSizeGetter, std::bind(&PDFToolRenderBase::onPageRendered, this, options, std::placeholders::_1), nullptr);
|
||||||
imageWriter.setSubType(m_imageWriterSettings.getCurrentSubtype());
|
|
||||||
imageWriter.setCompression(m_imageWriterSettings.getCompression());
|
|
||||||
imageWriter.setQuality(m_imageWriterSettings.getQuality());
|
|
||||||
imageWriter.setGamma(m_imageWriterSettings.getGamma());
|
|
||||||
imageWriter.setOptimizedWrite(m_imageWriterSettings.hasOptimizedWrite());
|
|
||||||
imageWriter.setProgressiveScanWrite(m_imageWriterSettings.hasProgressiveScanWrite());
|
|
||||||
|
|
||||||
if (!imageWriter.write(image))
|
m_wallTime = timer.elapsed();
|
||||||
{
|
|
||||||
emit m_rasterizerPool->renderError(pdf::PDFRenderError(pdf::RenderErrorType::Error, tr("Can't write page image to file '%1', because: %2.").arg(fileName).arg(imageWriter.errorString())));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
rasterizerPool.render(pageIndices, imageSizeGetter, processImage, m_progress);
|
fontCache.setCacheShrinkEnabled(nullptr, true);
|
||||||
|
|
||||||
|
finish(options);
|
||||||
return ExitSuccess;
|
return ExitSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFToolRenderBase::writePageInfoStatistics(const pdf::PDFRenderedPageImage& renderedPageImage)
|
||||||
|
{
|
||||||
|
PageInfo& info = m_pageInfo[renderedPageImage.pageIndex];
|
||||||
|
info.isRendered = true;
|
||||||
|
info.pageCompileTime = renderedPageImage.pageCompileTime;
|
||||||
|
info.pageWaitTime = renderedPageImage.pageWaitTime;
|
||||||
|
info.pageRenderTime = renderedPageImage.pageRenderTime;
|
||||||
|
info.pageTotalTime = renderedPageImage.pageTotalTime;
|
||||||
|
info.pageIndex = renderedPageImage.pageIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFToolRenderBase::writeStatistics(PDFOutputFormatter& formatter)
|
||||||
|
{
|
||||||
|
// Jakub Melka: Write overall statistics
|
||||||
|
qint64 pagesRendered = 0;
|
||||||
|
qint64 pageCompileTime = 0;
|
||||||
|
qint64 pageWaitTime = 0;
|
||||||
|
qint64 pageRenderTime = 0;
|
||||||
|
qint64 pageTotalTime = 0;
|
||||||
|
qint64 pageWriteTime = 0;
|
||||||
|
|
||||||
|
for (const PageInfo& info : m_pageInfo)
|
||||||
|
{
|
||||||
|
if (!info.isRendered)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++pagesRendered;
|
||||||
|
pageCompileTime += info.pageCompileTime;
|
||||||
|
pageWaitTime += info.pageWaitTime;
|
||||||
|
pageRenderTime += info.pageRenderTime;
|
||||||
|
pageTotalTime += info.pageTotalTime + info.pageWriteTime;
|
||||||
|
pageWriteTime += info.pageWriteTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pagesRendered > 0 && pageTotalTime > 0 && m_wallTime > 0)
|
||||||
|
{
|
||||||
|
QLocale locale;
|
||||||
|
|
||||||
|
double renderingSpeedPerCore = double(pagesRendered) / (double(pageTotalTime) / 1000.0);
|
||||||
|
double renderingSpeedWallTime = double(pagesRendered) / (double(m_wallTime) / 1000.0);
|
||||||
|
|
||||||
|
double compileRatio = 100.0 * double(pageCompileTime) / double(pageTotalTime);
|
||||||
|
double waitRatio = 100.0 * double(pageWaitTime) / double(pageTotalTime);
|
||||||
|
double renderRatio = 100.0 * double(pageRenderTime) / double(pageTotalTime);
|
||||||
|
double writeRatio = 100.0 * double(pageWriteTime) / double(pageTotalTime);
|
||||||
|
|
||||||
|
formatter.beginTable("statistics", PDFToolTranslationContext::tr("Statistics"));
|
||||||
|
|
||||||
|
formatter.beginTableHeaderRow("header");
|
||||||
|
formatter.writeTableHeaderColumn("description", PDFToolTranslationContext::tr("Description"), Qt::AlignLeft);
|
||||||
|
formatter.writeTableHeaderColumn("value", PDFToolTranslationContext::tr("Value"), Qt::AlignLeft);
|
||||||
|
formatter.writeTableHeaderColumn("unit", PDFToolTranslationContext::tr("Unit"), Qt::AlignLeft);
|
||||||
|
formatter.endTableHeaderRow();
|
||||||
|
|
||||||
|
auto writeValue = [&formatter](QString name, QString description, QString value, QString unit)
|
||||||
|
{
|
||||||
|
formatter.beginTableRow(name);
|
||||||
|
formatter.writeTableColumn("description", description);
|
||||||
|
formatter.writeTableColumn("value", value, Qt::AlignRight);
|
||||||
|
formatter.writeTableColumn("unit", unit);
|
||||||
|
formatter.endTableRow();
|
||||||
|
};
|
||||||
|
|
||||||
|
writeValue("pages-rendered", PDFToolTranslationContext::tr("Pages rendered"), locale.toString(pagesRendered), PDFToolTranslationContext::tr("-"));
|
||||||
|
writeValue("compile-time", PDFToolTranslationContext::tr("Total compile time"), locale.toString(pageCompileTime), PDFToolTranslationContext::tr("msec"));
|
||||||
|
writeValue("render-time", PDFToolTranslationContext::tr("Total render time"), locale.toString(pageRenderTime), PDFToolTranslationContext::tr("msec"));
|
||||||
|
writeValue("wait-time", PDFToolTranslationContext::tr("Total wait time"), locale.toString(pageWaitTime), PDFToolTranslationContext::tr("msec"));
|
||||||
|
writeValue("write-time", PDFToolTranslationContext::tr("Total write time"), locale.toString(pageWriteTime), PDFToolTranslationContext::tr("msec"));
|
||||||
|
writeValue("total-time", PDFToolTranslationContext::tr("Total time"), locale.toString(pageTotalTime), PDFToolTranslationContext::tr("msec"));
|
||||||
|
writeValue("wall-time", PDFToolTranslationContext::tr("Wall time"), locale.toString(m_wallTime), PDFToolTranslationContext::tr("msec"));
|
||||||
|
writeValue("pages-per-second-core", PDFToolTranslationContext::tr("Rendering speed (per core)"), locale.toString(renderingSpeedPerCore, 'f', 3), PDFToolTranslationContext::tr("pages / sec (one core)"));
|
||||||
|
writeValue("pages-per-second-wall", PDFToolTranslationContext::tr("Rendering speed (wall time)"), locale.toString(renderingSpeedWallTime, 'f', 3), PDFToolTranslationContext::tr("pages / sec"));
|
||||||
|
writeValue("compile-time-ratio", PDFToolTranslationContext::tr("Compile time ratio"), locale.toString(compileRatio, 'f', 2), PDFToolTranslationContext::tr("%"));
|
||||||
|
writeValue("render-time-ratio", PDFToolTranslationContext::tr("Render time ratio"), locale.toString(renderRatio, 'f', 2), PDFToolTranslationContext::tr("%"));
|
||||||
|
writeValue("wait-time-ratio", PDFToolTranslationContext::tr("Wait time ratio"), locale.toString(waitRatio, 'f', 2), PDFToolTranslationContext::tr("%"));
|
||||||
|
writeValue("write-time-ratio", PDFToolTranslationContext::tr("Write time ratio"), locale.toString(writeRatio, 'f', 2), PDFToolTranslationContext::tr("%"));
|
||||||
|
|
||||||
|
formatter.endTable();
|
||||||
|
formatter.endl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFToolRenderBase::writePageStatistics(PDFOutputFormatter& formatter)
|
||||||
|
{
|
||||||
|
formatter.beginTable("page-statistics", PDFToolTranslationContext::tr("Page Statistics"));
|
||||||
|
|
||||||
|
formatter.beginTableHeaderRow("header");
|
||||||
|
formatter.writeTableHeaderColumn("page-no", PDFToolTranslationContext::tr("Page No."), Qt::AlignLeft);
|
||||||
|
formatter.writeTableHeaderColumn("compile-time", PDFToolTranslationContext::tr("Compile Time [msec]"), Qt::AlignLeft);
|
||||||
|
formatter.writeTableHeaderColumn("render-time", PDFToolTranslationContext::tr("Render Time [msec]"), Qt::AlignLeft);
|
||||||
|
formatter.writeTableHeaderColumn("wait-time", PDFToolTranslationContext::tr("Wait Time [msec]"), Qt::AlignLeft);
|
||||||
|
formatter.writeTableHeaderColumn("write-time", PDFToolTranslationContext::tr("Write Time [msec]"), Qt::AlignLeft);
|
||||||
|
formatter.writeTableHeaderColumn("total-time", PDFToolTranslationContext::tr("Total Time [msec]"), Qt::AlignLeft);
|
||||||
|
formatter.endTableHeaderRow();
|
||||||
|
|
||||||
|
QLocale locale;
|
||||||
|
|
||||||
|
for (const PageInfo& info : m_pageInfo)
|
||||||
|
{
|
||||||
|
if (!info.isRendered)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
formatter.beginTableRow("page", info.pageIndex + 1);
|
||||||
|
formatter.writeTableColumn("page-no", locale.toString(info.pageIndex + 1), Qt::AlignRight);
|
||||||
|
formatter.writeTableColumn("compile-time", locale.toString(info.pageCompileTime), Qt::AlignRight);
|
||||||
|
formatter.writeTableColumn("render-time", locale.toString(info.pageRenderTime), Qt::AlignRight);
|
||||||
|
formatter.writeTableColumn("wait-time", locale.toString(info.pageWaitTime), Qt::AlignRight);
|
||||||
|
formatter.writeTableColumn("write-time", locale.toString(info.pageWaitTime), Qt::AlignRight);
|
||||||
|
formatter.writeTableColumn("total-time", locale.toString(info.pageTotalTime), Qt::AlignRight);
|
||||||
|
formatter.endTableRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
formatter.endTable();
|
||||||
|
formatter.endl();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFToolRenderBase::writeErrors(PDFOutputFormatter& formatter)
|
||||||
|
{
|
||||||
|
formatter.beginTable("rendering-errors", PDFToolTranslationContext::tr("Rendering Errors"));
|
||||||
|
|
||||||
|
formatter.beginTableHeaderRow("header");
|
||||||
|
formatter.writeTableHeaderColumn("page-no", PDFToolTranslationContext::tr("Page No."), Qt::AlignLeft);
|
||||||
|
formatter.writeTableHeaderColumn("type", PDFToolTranslationContext::tr("Type"), Qt::AlignLeft);
|
||||||
|
formatter.writeTableHeaderColumn("message", PDFToolTranslationContext::tr("Message"), Qt::AlignLeft);
|
||||||
|
formatter.endTableHeaderRow();
|
||||||
|
|
||||||
|
QLocale locale;
|
||||||
|
|
||||||
|
for (const PageInfo& info : m_pageInfo)
|
||||||
|
{
|
||||||
|
if (!info.isRendered)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const pdf::PDFRenderError& error : info.errors)
|
||||||
|
{
|
||||||
|
QString type;
|
||||||
|
switch (error.type)
|
||||||
|
{
|
||||||
|
case pdf::RenderErrorType::Error:
|
||||||
|
type = PDFToolTranslationContext::tr("Error");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case pdf::RenderErrorType::Warning:
|
||||||
|
type = PDFToolTranslationContext::tr("Warning");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case pdf::RenderErrorType::NotImplemented:
|
||||||
|
type = PDFToolTranslationContext::tr("Not implemented");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case pdf::RenderErrorType::NotSupported:
|
||||||
|
type = PDFToolTranslationContext::tr("Not supported");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case pdf::RenderErrorType::Information:
|
||||||
|
type = PDFToolTranslationContext::tr("Information");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
formatter.beginTableRow("page", info.pageIndex + 1);
|
||||||
|
formatter.writeTableColumn("page-no", locale.toString(info.pageIndex + 1), Qt::AlignRight);
|
||||||
|
formatter.writeTableColumn("type", type, Qt::AlignLeft);
|
||||||
|
formatter.writeTableColumn("message", error.message, Qt::AlignLeft);
|
||||||
|
formatter.endTableRow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
formatter.endTable();
|
||||||
|
formatter.endl();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdftool
|
} // namespace pdftool
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#define PDFTOOLRENDER_H
|
#define PDFTOOLRENDER_H
|
||||||
|
|
||||||
#include "pdftoolabstractapplication.h"
|
#include "pdftoolabstractapplication.h"
|
||||||
|
#include "pdfexception.h"
|
||||||
|
|
||||||
namespace pdftool
|
namespace pdftool
|
||||||
{
|
{
|
||||||
|
@ -27,6 +28,31 @@ class PDFToolRenderBase : public PDFToolAbstractApplication
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual int execute(const PDFToolOptions& options) override;
|
virtual int execute(const PDFToolOptions& options) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void finish(const PDFToolOptions& options) = 0;
|
||||||
|
virtual void onPageRendered(const PDFToolOptions& options, pdf::PDFRenderedPageImage& renderedPageImage) = 0;
|
||||||
|
|
||||||
|
void writePageInfoStatistics(const pdf::PDFRenderedPageImage& renderedPageImage);
|
||||||
|
|
||||||
|
void writeStatistics(PDFOutputFormatter& formatter);
|
||||||
|
void writePageStatistics(PDFOutputFormatter& formatter);
|
||||||
|
void writeErrors(PDFOutputFormatter& formatter);
|
||||||
|
|
||||||
|
struct PageInfo
|
||||||
|
{
|
||||||
|
bool isRendered = false;
|
||||||
|
pdf::PDFInteger pageIndex = 0;
|
||||||
|
qint64 pageCompileTime = 0;
|
||||||
|
qint64 pageWaitTime = 0;
|
||||||
|
qint64 pageRenderTime = 0;
|
||||||
|
qint64 pageTotalTime = 0;
|
||||||
|
qint64 pageWriteTime = 0;
|
||||||
|
std::vector<pdf::PDFRenderError> errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<PageInfo> m_pageInfo;
|
||||||
|
qint64 m_wallTime = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PDFToolRender : public PDFToolRenderBase
|
class PDFToolRender : public PDFToolRenderBase
|
||||||
|
@ -34,6 +60,10 @@ class PDFToolRender : public PDFToolRenderBase
|
||||||
public:
|
public:
|
||||||
virtual QString getStandardString(StandardString standardString) const override;
|
virtual QString getStandardString(StandardString standardString) const override;
|
||||||
virtual Options getOptionsFlags() const override;
|
virtual Options getOptionsFlags() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void finish(const PDFToolOptions& options) override;
|
||||||
|
virtual void onPageRendered(const PDFToolOptions& options, pdf::PDFRenderedPageImage& renderedPageImage) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PDFToolBenchmark : public PDFToolRenderBase
|
class PDFToolBenchmark : public PDFToolRenderBase
|
||||||
|
@ -41,6 +71,10 @@ class PDFToolBenchmark : public PDFToolRenderBase
|
||||||
public:
|
public:
|
||||||
virtual QString getStandardString(StandardString standardString) const override;
|
virtual QString getStandardString(StandardString standardString) const override;
|
||||||
virtual Options getOptionsFlags() const override;
|
virtual Options getOptionsFlags() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void finish(const PDFToolOptions& options) override;
|
||||||
|
virtual void onPageRendered(const PDFToolOptions& options, pdf::PDFRenderedPageImage& renderedPageImage) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdftool
|
} // namespace pdftool
|
||||||
|
|
Loading…
Reference in New Issue