mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Issue #123: Alternative software rendering backend
This commit is contained in:
@ -24,6 +24,7 @@
|
||||
#include "pdfannotation.h"
|
||||
#include "pdfdrawwidget.h"
|
||||
#include "pdfwidgetannotation.h"
|
||||
#include "pdfpainterutils.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QPainter>
|
||||
@ -31,6 +32,8 @@
|
||||
#include <QScreen>
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include <Blend2d.h>
|
||||
|
||||
#include "pdfdbgheap.h"
|
||||
|
||||
namespace pdf
|
||||
@ -469,7 +472,7 @@ PDFDrawWidgetProxy::PDFDrawWidgetProxy(QObject* parent) :
|
||||
m_rasterizer(new PDFRasterizer(this)),
|
||||
m_progress(nullptr),
|
||||
m_cacheClearTimer(new QTimer(this)),
|
||||
m_useOpenGL(false)
|
||||
m_rendererEngine(RendererEngine::Blend2D)
|
||||
{
|
||||
m_controller = new PDFDrawSpaceController(this);
|
||||
connect(m_controller, &PDFDrawSpaceController::drawSpaceChanged, this, &PDFDrawWidgetProxy::update);
|
||||
@ -765,6 +768,18 @@ void PDFDrawWidgetProxy::draw(QPainter* painter, QRect rect)
|
||||
}
|
||||
}
|
||||
|
||||
void PDFDrawWidgetProxy::draw(BLContext& context, QRect rect)
|
||||
{
|
||||
drawPages(context, rect, m_features);
|
||||
|
||||
for (IDocumentDrawInterface* drawInterface : m_drawInterfaces)
|
||||
{
|
||||
context.save();
|
||||
drawInterface->drawPostRendering(context, rect);
|
||||
context.restore();
|
||||
}
|
||||
}
|
||||
|
||||
QColor PDFDrawWidgetProxy::getPaperColor()
|
||||
{
|
||||
QColor paperColor = getCMSManager()->getCurrentCMS()->getPaperColor();
|
||||
@ -920,6 +935,153 @@ void PDFDrawWidgetProxy::drawPages(QPainter* painter, QRect rect, PDFRenderer::F
|
||||
}
|
||||
}
|
||||
|
||||
void PDFDrawWidgetProxy::drawPages(BLContext& context, QRect rect, PDFRenderer::Features features)
|
||||
{
|
||||
PDFPainterHelper::setBLBrush(context, QBrush(Qt::lightGray));
|
||||
context.fillRect(rect);
|
||||
BLMatrix2D baseMatrix = context.userMatrix();
|
||||
|
||||
// Use current paper color (it can be a bit different from white)
|
||||
QColor paperColor = getPaperColor();
|
||||
|
||||
// Iterate trough pages and display them on the painter device
|
||||
for (const LayoutItem& item : m_layout.items)
|
||||
{
|
||||
// The offsets m_horizontalOffset and m_verticalOffset are offsets to the
|
||||
// topleft point of the block. But block maybe doesn't start at (0, 0),
|
||||
// so we must also use translation from the block beginning.
|
||||
QRect placedRect = item.pageRect.translated(m_horizontalOffset - m_layout.blockRect.left(), m_verticalOffset - m_layout.blockRect.top());
|
||||
if (placedRect.intersects(rect))
|
||||
{
|
||||
GroupInfo groupInfo = getGroupInfo(item.groupIndex);
|
||||
|
||||
// Clear the page space by paper color
|
||||
if (groupInfo.drawPaper)
|
||||
{
|
||||
PDFPainterHelper::setBLBrush(context, paperColor);
|
||||
context.fillRect(placedRect);
|
||||
}
|
||||
|
||||
const PDFPrecompiledPage* compiledPage = m_compiler->getCompiledPage(item.pageIndex, true);
|
||||
if (compiledPage && compiledPage->isValid())
|
||||
{
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
const PDFPage* page = m_controller->getDocument()->getCatalog()->getPage(item.pageIndex);
|
||||
QTransform matrix = QTransform(createPagePointToDevicePointMatrix(page, placedRect)) * baseMatrix;
|
||||
compiledPage->draw(context, page->getCropBox(), matrix, features, groupInfo.transparency);
|
||||
PDFTextLayoutGetter layoutGetter = m_textLayoutCompiler->getTextLayoutLazy(item.pageIndex);
|
||||
|
||||
// Draw text blocks/text lines, if it is enabled
|
||||
if (features.testFlag(PDFRenderer::DebugTextBlocks))
|
||||
{
|
||||
m_textLayoutCompiler->makeTextLayout();
|
||||
const PDFTextLayout& layout = layoutGetter;
|
||||
const PDFTextBlocks& textBlocks = layout.getTextBlocks();
|
||||
|
||||
context.save();
|
||||
painter->setFont(m_widget->font());
|
||||
painter->setPen(Qt::red);
|
||||
painter->setBrush(QColor(255, 0, 0, 128));
|
||||
|
||||
QFontMetricsF fontMetrics(painter->font(), painter->device());
|
||||
int blockIndex = 1;
|
||||
for (const PDFTextBlock& block : textBlocks)
|
||||
{
|
||||
QString blockNumber = QString::number(blockIndex++);
|
||||
|
||||
painter->drawPath(matrix.map(block.getBoundingBox()));
|
||||
painter->drawText(matrix.map(block.getTopLeft()) - QPointF(fontMetrics.horizontalAdvance(blockNumber), 0), blockNumber, Qt::TextSingleLine, 0);
|
||||
}
|
||||
|
||||
context.restore();
|
||||
}
|
||||
if (features.testFlag(PDFRenderer::DebugTextLines))
|
||||
{
|
||||
m_textLayoutCompiler->makeTextLayout();
|
||||
const PDFTextLayout& layout = layoutGetter;
|
||||
const PDFTextBlocks& textBlocks = layout.getTextBlocks();
|
||||
|
||||
context.save();
|
||||
painter->setFont(m_widget->font());
|
||||
painter->setPen(Qt::green);
|
||||
painter->setBrush(QColor(0, 255, 0, 128));
|
||||
|
||||
QFontMetricsF fontMetrics(painter->font(), painter->device());
|
||||
int lineIndex = 1;
|
||||
for (const PDFTextBlock& block : textBlocks)
|
||||
{
|
||||
for (const PDFTextLine& line : block.getLines())
|
||||
{
|
||||
QString lineNumber = QString::number(lineIndex++);
|
||||
|
||||
painter->drawPath(matrix.map(line.getBoundingBox()));
|
||||
painter->drawText(matrix.map(line.getTopLeft()) - QPointF(fontMetrics.horizontalAdvance(lineNumber), 0), lineNumber, Qt::TextSingleLine, 0);
|
||||
}
|
||||
}
|
||||
|
||||
context.restore();
|
||||
}
|
||||
|
||||
QList<PDFRenderError> drawInterfaceErrors;
|
||||
if (!features.testFlag(PDFRenderer::DenyExtraGraphics))
|
||||
{
|
||||
for (IDocumentDrawInterface* drawInterface : m_drawInterfaces)
|
||||
{
|
||||
context.save();
|
||||
drawInterface->drawPage(context, item.pageIndex, compiledPage, layoutGetter, matrix, drawInterfaceErrors);
|
||||
context.restore();
|
||||
}
|
||||
}
|
||||
|
||||
const qint64 drawTimeNS = timer.nsecsElapsed();
|
||||
|
||||
// Draw rendering times
|
||||
if (features.testFlag(PDFRenderer::DisplayTimes))
|
||||
{
|
||||
QFont font = m_widget->font();
|
||||
font.setPointSize(12);
|
||||
|
||||
auto formatDrawTime = [](qint64 nanoseconds)
|
||||
{
|
||||
PDFReal miliseconds = nanoseconds / 1000000.0;
|
||||
return QString::number(miliseconds, 'f', 3);
|
||||
};
|
||||
|
||||
QFontMetrics fontMetrics(font);
|
||||
const int lineSpacing = fontMetrics.lineSpacing();
|
||||
|
||||
context.save();
|
||||
painter->setPen(Qt::red);
|
||||
painter->setFont(font);
|
||||
context.translate(placedRect.topLeft());
|
||||
context.translate(placedRect.width() / 20.0, placedRect.height() / 20.0); // Offset
|
||||
|
||||
painter->setBackground(QBrush(Qt::white));
|
||||
painter->setBackgroundMode(Qt::OpaqueMode);
|
||||
painter->drawText(0, 0, PDFTranslationContext::tr("Compile time: %1 [ms]").arg(formatDrawTime(compiledPage->getCompilingTimeNS())));
|
||||
painter->translate(0, lineSpacing);
|
||||
painter->drawText(0, 0, PDFTranslationContext::tr("Draw time: %1 [ms]").arg(formatDrawTime(drawTimeNS)));
|
||||
|
||||
context.restore();
|
||||
}
|
||||
|
||||
const QList<PDFRenderError>& pageErrors = compiledPage->getErrors();
|
||||
if (!pageErrors.empty() || !drawInterfaceErrors.empty())
|
||||
{
|
||||
QList<PDFRenderError> errors = pageErrors;
|
||||
if (!drawInterfaceErrors.isEmpty())
|
||||
{
|
||||
errors.append(drawInterfaceErrors);
|
||||
}
|
||||
Q_EMIT renderingError(item.pageIndex, qMove(errors));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QImage PDFDrawWidgetProxy::drawThumbnailImage(PDFInteger pageIndex, int pixelSize) const
|
||||
{
|
||||
QImage image;
|
||||
@ -1403,11 +1565,10 @@ bool PDFDrawWidgetProxy::isBlockMode() const
|
||||
return false;
|
||||
}
|
||||
|
||||
void PDFDrawWidgetProxy::updateRenderer(bool useOpenGL, const QSurfaceFormat& surfaceFormat)
|
||||
void PDFDrawWidgetProxy::updateRenderer(RendererEngine rendererEngine)
|
||||
{
|
||||
m_useOpenGL = useOpenGL;
|
||||
m_surfaceFormat = surfaceFormat;
|
||||
m_rasterizer->reset(useOpenGL && ENABLE_OPENGL_FOR_THUMBNAILS, surfaceFormat);
|
||||
m_rendererEngine = rendererEngine;
|
||||
m_rasterizer->reset(m_rendererEngine);
|
||||
}
|
||||
|
||||
void PDFDrawWidgetProxy::prefetchPages(PDFInteger pageIndex)
|
||||
|
Reference in New Issue
Block a user