mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Optimization (multithreading)
This commit is contained in:
@ -16,6 +16,7 @@
|
|||||||
// along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
|
// along with Pdf4Qt. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "pdfcms.h"
|
#include "pdfcms.h"
|
||||||
|
#include "pdfexecutionpolicy.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QReadWriteLock>
|
#include <QReadWriteLock>
|
||||||
@ -329,7 +330,52 @@ bool PDFLittleCMS::transformColorSpace(const PDFCMS::ColorSpaceTransformParams&
|
|||||||
inputPixelCount == outputPixelCount)
|
inputPixelCount == outputPixelCount)
|
||||||
{
|
{
|
||||||
PDFColorBuffer outputBuffer = params.output;
|
PDFColorBuffer outputBuffer = params.output;
|
||||||
cmsDoTransform(transform, inputColors, outputBuffer.begin(), inputPixelCount);
|
|
||||||
|
if (inputPixelCount > params.multithreadingThreshold)
|
||||||
|
{
|
||||||
|
struct TransformInfo
|
||||||
|
{
|
||||||
|
inline TransformInfo(const float* source, float* target, cmsUInt32Number pixelCount) :
|
||||||
|
source(source),
|
||||||
|
target(target),
|
||||||
|
pixelCount(pixelCount)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const float* source = nullptr;
|
||||||
|
float* target = nullptr;
|
||||||
|
cmsUInt32Number pixelCount = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cmsUInt32Number blockSize = 4096;
|
||||||
|
std::vector<TransformInfo> infos;
|
||||||
|
infos.reserve(inputPixelCount / blockSize + 1);
|
||||||
|
|
||||||
|
const float* sourcePointer = inputColors;
|
||||||
|
float* targetPointer = outputBuffer.begin();
|
||||||
|
|
||||||
|
cmsUInt32Number remainingPixelCount = inputPixelCount;
|
||||||
|
while (remainingPixelCount > 0)
|
||||||
|
{
|
||||||
|
const cmsUInt32Number currentPixelCount = qMin(blockSize, remainingPixelCount);
|
||||||
|
infos.emplace_back(sourcePointer, targetPointer, currentPixelCount);
|
||||||
|
sourcePointer += currentPixelCount * inputChannels;
|
||||||
|
targetPointer += currentPixelCount * outputChannels;
|
||||||
|
remainingPixelCount -= currentPixelCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto processEntry = [transform](const TransformInfo& info)
|
||||||
|
{
|
||||||
|
cmsDoTransform(transform, info.source, info.target, info.pixelCount);
|
||||||
|
};
|
||||||
|
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, infos.begin(), infos.end(), processEntry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Single-threaded transform
|
||||||
|
cmsDoTransform(transform, inputColors, outputBuffer.begin(), inputPixelCount);
|
||||||
|
}
|
||||||
|
|
||||||
if (isOutputCMYK)
|
if (isOutputCMYK)
|
||||||
{
|
{
|
||||||
|
@ -225,6 +225,8 @@ public:
|
|||||||
PDFColorBuffer output;
|
PDFColorBuffer output;
|
||||||
|
|
||||||
RenderingIntent intent = RenderingIntent::Unknown;
|
RenderingIntent intent = RenderingIntent::Unknown;
|
||||||
|
|
||||||
|
PDFInteger multithreadingThreshold = 4096;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Transforms color between two color spaces. Doesn't do soft-proofing,
|
/// Transforms color between two color spaces. Doesn't do soft-proofing,
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "pdftransparencyrenderer.h"
|
#include "pdftransparencyrenderer.h"
|
||||||
#include "pdfdocument.h"
|
#include "pdfdocument.h"
|
||||||
#include "pdfcms.h"
|
#include "pdfcms.h"
|
||||||
|
#include "pdfexecutionpolicy.h"
|
||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
@ -566,10 +567,12 @@ PDFTransparencyRenderer::PDFTransparencyRenderer(const PDFPage* page,
|
|||||||
const PDFCMS* cms,
|
const PDFCMS* cms,
|
||||||
const PDFOptionalContentActivity* optionalContentActivity,
|
const PDFOptionalContentActivity* optionalContentActivity,
|
||||||
const PDFInkMapper* inkMapper,
|
const PDFInkMapper* inkMapper,
|
||||||
|
PDFTransparencyRendererSettings settings,
|
||||||
QMatrix pagePointToDevicePointMatrix) :
|
QMatrix pagePointToDevicePointMatrix) :
|
||||||
BaseClass(page, document, fontCache, cms, optionalContentActivity, pagePointToDevicePointMatrix, PDFMeshQualitySettings()),
|
BaseClass(page, document, fontCache, cms, optionalContentActivity, pagePointToDevicePointMatrix, PDFMeshQualitySettings()),
|
||||||
m_inkMapper(inkMapper),
|
m_inkMapper(inkMapper),
|
||||||
m_active(false)
|
m_active(false),
|
||||||
|
m_settings(settings)
|
||||||
{
|
{
|
||||||
m_deviceColorSpace.reset(new PDFDeviceRGBColorSpace());
|
m_deviceColorSpace.reset(new PDFDeviceRGBColorSpace());
|
||||||
m_processColorSpace.reset(new PDFDeviceCMYKColorSpace());
|
m_processColorSpace.reset(new PDFDeviceCMYKColorSpace());
|
||||||
@ -751,6 +754,39 @@ QImage PDFTransparencyRenderer::toImage(bool use16Bit, bool usePaper, PDFRGB pap
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFTransparencyRenderer::performPixelSampling(const PDFReal shape,
|
||||||
|
const PDFReal opacity,
|
||||||
|
const uint8_t shapeChannel,
|
||||||
|
const uint8_t opacityChannel,
|
||||||
|
const uint8_t colorChannelStart,
|
||||||
|
const uint8_t colorChannelEnd,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
const PDFMappedColor& fillColor,
|
||||||
|
const PDFPainterPathSampler& clipSampler,
|
||||||
|
const PDFPainterPathSampler& pathSampler)
|
||||||
|
{
|
||||||
|
const PDFColorComponent clipValue = clipSampler.sample(QPoint(x, y));
|
||||||
|
const PDFColorComponent objectShapeValue = pathSampler.sample(QPoint(x, y));
|
||||||
|
const PDFColorComponent shapeValue = objectShapeValue * clipValue * shape;
|
||||||
|
|
||||||
|
if (shapeValue > 0.0f)
|
||||||
|
{
|
||||||
|
// We consider old object shape - we use Union function to
|
||||||
|
// set shape channel value.
|
||||||
|
|
||||||
|
PDFColorBuffer pixel = m_drawBuffer.getPixel(x, y);
|
||||||
|
pixel[shapeChannel] = PDFBlendFunction::blend_Union(shapeValue, pixel[shapeChannel]);
|
||||||
|
pixel[opacityChannel] = pixel[shapeChannel] * opacity;
|
||||||
|
|
||||||
|
// Copy color
|
||||||
|
for (uint8_t colorChannelIndex = colorChannelStart; colorChannelIndex < colorChannelEnd; ++colorChannelIndex)
|
||||||
|
{
|
||||||
|
pixel[colorChannelIndex] = fillColor.mappedColor[colorChannelIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule)
|
void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool stroke, bool fill, bool text, Qt::FillRule fillRule)
|
||||||
{
|
{
|
||||||
Q_UNUSED(fillRule);
|
Q_UNUSED(fillRule);
|
||||||
@ -784,28 +820,42 @@ void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool
|
|||||||
PDFPainterPathSampler pathSampler(worldPath, m_settings.samplesCount, 0.0f, fillRect, m_settings.flags.testFlag(PDFTransparencyRendererSettings::PrecisePathSampler));
|
PDFPainterPathSampler pathSampler(worldPath, m_settings.samplesCount, 0.0f, fillRect, m_settings.flags.testFlag(PDFTransparencyRendererSettings::PrecisePathSampler));
|
||||||
const PDFMappedColor& fillColor = getMappedFillColor();
|
const PDFMappedColor& fillColor = getMappedFillColor();
|
||||||
|
|
||||||
for (int x = fillRect.left(); x < fillRect.right(); ++x)
|
if (isMultithreadedPathSamplingUsed(fillRect))
|
||||||
{
|
{
|
||||||
for (int y = fillRect.top(); y < fillRect.bottom(); ++y)
|
if (fillRect.width() > fillRect.height())
|
||||||
{
|
{
|
||||||
const PDFColorComponent clipValue = clipSampler.sample(QPoint(x, y));
|
// Columns
|
||||||
const PDFColorComponent objectShapeValue = pathSampler.sample(QPoint(x, y));
|
PDFIntegerRange<int> range(fillRect.left(), fillRect.right() + 1);
|
||||||
const PDFColorComponent shapeValue = objectShapeValue * clipValue * shapeFilling;
|
auto processEntry = [&, this](int x)
|
||||||
|
|
||||||
if (shapeValue > 0.0f)
|
|
||||||
{
|
{
|
||||||
// We consider old object shape - we use Union function to
|
for (int y = fillRect.top(); y <= fillRect.bottom(); ++y)
|
||||||
// set shape channel value.
|
|
||||||
|
|
||||||
PDFColorBuffer pixel = m_drawBuffer.getPixel(x, y);
|
|
||||||
pixel[shapeChannel] = PDFBlendFunction::blend_Union(shapeValue, pixel[shapeChannel]);
|
|
||||||
pixel[opacityChannel] = pixel[shapeChannel] * opacityFilling;
|
|
||||||
|
|
||||||
// Copy color
|
|
||||||
for (uint8_t colorChannelIndex = colorChannelStart; colorChannelIndex < colorChannelEnd; ++colorChannelIndex)
|
|
||||||
{
|
{
|
||||||
pixel[colorChannelIndex] = fillColor.mappedColor[colorChannelIndex];
|
performPixelSampling(shapeFilling, opacityFilling, shapeChannel, opacityChannel, colorChannelStart, colorChannelEnd, x, y, fillColor, clipSampler, pathSampler);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, range.begin(), range.end(), processEntry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Rows
|
||||||
|
PDFIntegerRange<int> range(fillRect.top(), fillRect.bottom() + 1);
|
||||||
|
auto processEntry = [&, this](int y)
|
||||||
|
{
|
||||||
|
for (int x = fillRect.left(); x <= fillRect.right(); ++x)
|
||||||
|
{
|
||||||
|
performPixelSampling(shapeFilling, opacityFilling, shapeChannel, opacityChannel, colorChannelStart, colorChannelEnd, x, y, fillColor, clipSampler, pathSampler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, range.begin(), range.end(), processEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int x = fillRect.left(); x <= fillRect.right(); ++x)
|
||||||
|
{
|
||||||
|
for (int y = fillRect.top(); y <= fillRect.bottom(); ++y)
|
||||||
|
{
|
||||||
|
performPixelSampling(shapeFilling, opacityFilling, shapeChannel, opacityChannel, colorChannelStart, colorChannelEnd, x, y, fillColor, clipSampler, pathSampler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -843,28 +893,42 @@ void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool
|
|||||||
PDFPainterPathSampler pathSampler(worldPath, m_settings.samplesCount, 0.0f, strokeRect, m_settings.flags.testFlag(PDFTransparencyRendererSettings::PrecisePathSampler));
|
PDFPainterPathSampler pathSampler(worldPath, m_settings.samplesCount, 0.0f, strokeRect, m_settings.flags.testFlag(PDFTransparencyRendererSettings::PrecisePathSampler));
|
||||||
const PDFMappedColor& strokeColor = getMappedStrokeColor();
|
const PDFMappedColor& strokeColor = getMappedStrokeColor();
|
||||||
|
|
||||||
for (int x = strokeRect.left(); x < strokeRect.right(); ++x)
|
if (isMultithreadedPathSamplingUsed(strokeRect))
|
||||||
{
|
{
|
||||||
for (int y = strokeRect.top(); y < strokeRect.bottom(); ++y)
|
if (strokeRect.width() > strokeRect.height())
|
||||||
{
|
{
|
||||||
const PDFColorComponent clipValue = clipSampler.sample(QPoint(x, y));
|
// Columns
|
||||||
const PDFColorComponent objectShapeValue = pathSampler.sample(QPoint(x, y));
|
PDFIntegerRange<int> range(strokeRect.left(), strokeRect.right() + 1);
|
||||||
const PDFColorComponent shapeValue = objectShapeValue * clipValue * shapeStroking;
|
auto processEntry = [&, this](int x)
|
||||||
|
|
||||||
if (shapeValue > 0.0f)
|
|
||||||
{
|
{
|
||||||
// We consider old object shape - we use Union function to
|
for (int y = strokeRect.top(); y <= strokeRect.bottom(); ++y)
|
||||||
// set shape channel value.
|
|
||||||
|
|
||||||
PDFColorBuffer pixel = m_drawBuffer.getPixel(x, y);
|
|
||||||
pixel[shapeChannel] = PDFBlendFunction::blend_Union(shapeValue, pixel[shapeChannel]);
|
|
||||||
pixel[opacityChannel] = pixel[shapeChannel] * opacityStroking;
|
|
||||||
|
|
||||||
// Copy color
|
|
||||||
for (uint8_t colorChannelIndex = colorChannelStart; colorChannelIndex < colorChannelEnd; ++colorChannelIndex)
|
|
||||||
{
|
{
|
||||||
pixel[colorChannelIndex] = strokeColor.mappedColor[colorChannelIndex];
|
performPixelSampling(shapeStroking, opacityStroking, shapeChannel, opacityChannel, colorChannelStart, colorChannelEnd, x, y, strokeColor, clipSampler, pathSampler);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, range.begin(), range.end(), processEntry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Rows
|
||||||
|
PDFIntegerRange<int> range(strokeRect.top(), strokeRect.bottom() + 1);
|
||||||
|
auto processEntry = [&, this](int y)
|
||||||
|
{
|
||||||
|
for (int x = strokeRect.left(); x <= strokeRect.right(); ++x)
|
||||||
|
{
|
||||||
|
performPixelSampling(shapeStroking, opacityStroking, shapeChannel, opacityChannel, colorChannelStart, colorChannelEnd, x, y, strokeColor, clipSampler, pathSampler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, range.begin(), range.end(), processEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int x = strokeRect.left(); x <= strokeRect.right(); ++x)
|
||||||
|
{
|
||||||
|
for (int y = strokeRect.top(); y <= strokeRect.bottom(); ++y)
|
||||||
|
{
|
||||||
|
performPixelSampling(shapeStroking, opacityStroking, shapeChannel, opacityChannel, colorChannelStart, colorChannelEnd, x, y, strokeColor, clipSampler, pathSampler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1349,6 +1413,16 @@ void PDFTransparencyRenderer::flushDrawBuffer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PDFTransparencyRenderer::isMultithreadedPathSamplingUsed(QRect fillRect) const
|
||||||
|
{
|
||||||
|
if (!m_settings.flags.testFlag(PDFTransparencyRendererSettings::MultithreadedPathSampler))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fillRect.width() * fillRect.height() > m_settings.multithreadingPathSampleThreshold && fillRect.width() > 1;
|
||||||
|
}
|
||||||
|
|
||||||
PDFInkMapper::PDFInkMapper(const PDFDocument* document) :
|
PDFInkMapper::PDFInkMapper(const PDFDocument* document) :
|
||||||
m_document(document)
|
m_document(document)
|
||||||
{
|
{
|
||||||
@ -1746,7 +1820,7 @@ void PDFPainterPathSampler::prepareScanLines()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int yOffset = m_fillRect.top(); yOffset < m_fillRect.bottom(); ++yOffset)
|
for (int yOffset = m_fillRect.top(); yOffset <= m_fillRect.bottom(); ++yOffset)
|
||||||
{
|
{
|
||||||
const qreal coordY1 = yOffset;
|
const qreal coordY1 = yOffset;
|
||||||
const qreal coordY2 = coordY1 + 1.0;
|
const qreal coordY2 = coordY1 + 1.0;
|
||||||
|
@ -439,13 +439,24 @@ struct PDFTransparencyRendererSettings
|
|||||||
/// Sample count for MSAA antialiasing
|
/// Sample count for MSAA antialiasing
|
||||||
int samplesCount = 16;
|
int samplesCount = 16;
|
||||||
|
|
||||||
|
/// Threshold for turning on painter path
|
||||||
|
/// multithreaded painting. When number of potential
|
||||||
|
/// pixels of painter path is greater than this constant,
|
||||||
|
/// and MultithreadedPathSampler flag is turned on,
|
||||||
|
/// multithreaded painting is performed.
|
||||||
|
int multithreadingPathSampleThreshold = 128;
|
||||||
|
|
||||||
enum Flag
|
enum Flag
|
||||||
{
|
{
|
||||||
None = 0x0000,
|
None = 0x0000,
|
||||||
|
|
||||||
/// Use precise path sampler, which uses paths instead
|
/// Use precise path sampler, which uses paths instead
|
||||||
/// of filling polygon.
|
/// of filling polygon.
|
||||||
PrecisePathSampler = 0x0001
|
PrecisePathSampler = 0x0001,
|
||||||
|
|
||||||
|
/// Use multithreading when painter paths are painted?
|
||||||
|
/// Multithreading is used to
|
||||||
|
MultithreadedPathSampler = 0x0002
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_FLAGS(Flags, Flag)
|
Q_DECLARE_FLAGS(Flags, Flag)
|
||||||
@ -471,6 +482,7 @@ public:
|
|||||||
const PDFCMS* cms,
|
const PDFCMS* cms,
|
||||||
const PDFOptionalContentActivity* optionalContentActivity,
|
const PDFOptionalContentActivity* optionalContentActivity,
|
||||||
const PDFInkMapper* inkMapper,
|
const PDFInkMapper* inkMapper,
|
||||||
|
PDFTransparencyRendererSettings settings,
|
||||||
QMatrix pagePointToDevicePointMatrix);
|
QMatrix pagePointToDevicePointMatrix);
|
||||||
|
|
||||||
/// Sets device color space. This is final color space, to which
|
/// Sets device color space. This is final color space, to which
|
||||||
@ -596,6 +608,37 @@ private:
|
|||||||
/// Flushes draw buffer
|
/// Flushes draw buffer
|
||||||
void flushDrawBuffer();
|
void flushDrawBuffer();
|
||||||
|
|
||||||
|
/// Returns true, if multithreaded painter path sampling should be used
|
||||||
|
/// for a given fill rectangle.
|
||||||
|
/// \param fillRect Fill rectangle
|
||||||
|
/// \returns true, if multithreading should be used
|
||||||
|
bool isMultithreadedPathSamplingUsed(QRect fillRect) const;
|
||||||
|
|
||||||
|
/// Performs sampling of single pixel. Sampled pixel is painted
|
||||||
|
/// into the draw buffer.
|
||||||
|
/// \param shape Constant shape value
|
||||||
|
/// \param opacity Constant opacity value
|
||||||
|
/// \param x Horizontal coordinate of the pixel
|
||||||
|
/// \param y Vertical coordinate of the pixel
|
||||||
|
/// \param shapeChannel Shape channel (draw buffer)
|
||||||
|
/// \param opacityChannel Opacity channel (draw buffer)
|
||||||
|
/// \param colorChannelStart Color channel start (draw buffer)
|
||||||
|
/// \param colorChannelEnd Color channel end (draw buffer)
|
||||||
|
/// \param fillColor Fill color
|
||||||
|
/// \param clipSample Clipping sampler
|
||||||
|
/// \param pathSampler Path sampler
|
||||||
|
void performPixelSampling(const PDFReal shape,
|
||||||
|
const PDFReal opacity,
|
||||||
|
const uint8_t shapeChannel,
|
||||||
|
const uint8_t opacityChannel,
|
||||||
|
const uint8_t colorChannelStart,
|
||||||
|
const uint8_t colorChannelEnd,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
const PDFMappedColor& fillColor,
|
||||||
|
const PDFPainterPathSampler& clipSampler,
|
||||||
|
const PDFPainterPathSampler& pathSampler);
|
||||||
|
|
||||||
PDFColorSpacePointer m_deviceColorSpace; ///< Device color space (color space for final result)
|
PDFColorSpacePointer m_deviceColorSpace; ///< Device color space (color space for final result)
|
||||||
PDFColorSpacePointer m_processColorSpace; ///< Process color space (color space, in which is page graphic's blended)
|
PDFColorSpacePointer m_processColorSpace; ///< Process color space (color space, in which is page graphic's blended)
|
||||||
std::unique_ptr<PDFTransparencyGroupGuard> m_pageTransparencyGroupGuard;
|
std::unique_ptr<PDFTransparencyGroupGuard> m_pageTransparencyGroupGuard;
|
||||||
|
@ -71,10 +71,17 @@ void OutputPreviewDialog::updateImage()
|
|||||||
ui->imageLabel->setPixmap(QPixmap());
|
ui->imageLabel->setPixmap(QPixmap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pdf::PDFTransparencyRendererSettings settings;
|
||||||
|
|
||||||
|
// Jakub Melka: debug is very slow, use multithreading
|
||||||
|
#ifdef QT_DEBUG
|
||||||
|
settings.flags.setFlag(pdf::PDFTransparencyRendererSettings::MultithreadedPathSampler, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
QMatrix pagePointToDevicePoint = pdf::PDFRenderer::createPagePointToDevicePointMatrix(page, QRect(QPoint(0, 0), imageSize));
|
QMatrix pagePointToDevicePoint = pdf::PDFRenderer::createPagePointToDevicePointMatrix(page, QRect(QPoint(0, 0), imageSize));
|
||||||
pdf::PDFDrawWidgetProxy* proxy = m_widget->getDrawWidgetProxy();
|
pdf::PDFDrawWidgetProxy* proxy = m_widget->getDrawWidgetProxy();
|
||||||
pdf::PDFCMSPointer cms = proxy->getCMSManager()->getCurrentCMS();
|
pdf::PDFCMSPointer cms = proxy->getCMSManager()->getCurrentCMS();
|
||||||
pdf::PDFTransparencyRenderer renderer(page, m_document, proxy->getFontCache(), cms.data(), proxy->getOptionalContentActivity(), &m_inkMapper, pagePointToDevicePoint);
|
pdf::PDFTransparencyRenderer renderer(page, m_document, proxy->getFontCache(), cms.data(), proxy->getOptionalContentActivity(), &m_inkMapper, settings, pagePointToDevicePoint);
|
||||||
|
|
||||||
renderer.beginPaint(imageSize);
|
renderer.beginPaint(imageSize);
|
||||||
renderer.processContents();
|
renderer.processContents();
|
||||||
|
Reference in New Issue
Block a user