mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Draw buffer commiting
This commit is contained in:
@ -149,7 +149,8 @@ void PDFFloatBitmap::blend(const PDFFloatBitmap& source,
|
|||||||
BlendMode mode,
|
BlendMode mode,
|
||||||
bool knockoutGroup,
|
bool knockoutGroup,
|
||||||
uint32_t activeColorChannels,
|
uint32_t activeColorChannels,
|
||||||
OverprintMode overprintMode)
|
OverprintMode overprintMode,
|
||||||
|
QRect blendRegion)
|
||||||
{
|
{
|
||||||
Q_ASSERT(source.getWidth() == target.getWidth());
|
Q_ASSERT(source.getWidth() == target.getWidth());
|
||||||
Q_ASSERT(source.getHeight() == target.getHeight());
|
Q_ASSERT(source.getHeight() == target.getHeight());
|
||||||
@ -158,8 +159,11 @@ void PDFFloatBitmap::blend(const PDFFloatBitmap& source,
|
|||||||
Q_ASSERT(source.getHeight() == softMask.getHeight());
|
Q_ASSERT(source.getHeight() == softMask.getHeight());
|
||||||
Q_ASSERT(softMask.getPixelFormat() == PDFPixelFormat::createOpacityMask());
|
Q_ASSERT(softMask.getPixelFormat() == PDFPixelFormat::createOpacityMask());
|
||||||
|
|
||||||
const size_t width = source.getWidth();
|
Q_ASSERT(blendRegion.left() >= 0);
|
||||||
const size_t height = source.getHeight();
|
Q_ASSERT(blendRegion.top() >= 0);
|
||||||
|
Q_ASSERT(blendRegion.right() < source.getWidth());
|
||||||
|
Q_ASSERT(blendRegion.bottom() < source.getHeight());
|
||||||
|
|
||||||
const PDFPixelFormat pixelFormat = source.getPixelFormat();
|
const PDFPixelFormat pixelFormat = source.getPixelFormat();
|
||||||
const uint8_t shapeChannel = pixelFormat.getShapeChannelIndex();
|
const uint8_t shapeChannel = pixelFormat.getShapeChannelIndex();
|
||||||
const uint8_t opacityChannel = pixelFormat.getOpacityChannelIndex();
|
const uint8_t opacityChannel = pixelFormat.getOpacityChannelIndex();
|
||||||
@ -256,9 +260,9 @@ void PDFFloatBitmap::blend(const PDFFloatBitmap& source,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t x = 0; x < width; ++x)
|
for (size_t x = blendRegion.left(); x <= blendRegion.right(); ++x)
|
||||||
{
|
{
|
||||||
for (size_t y = 0; y < height; ++y)
|
for (size_t y = blendRegion.top(); y <= blendRegion.bottom(); ++y)
|
||||||
{
|
{
|
||||||
PDFConstColorBuffer sourceColor = source.getPixel(x, y);
|
PDFConstColorBuffer sourceColor = source.getPixel(x, y);
|
||||||
PDFColorBuffer targetColor = target.getPixel(x, y);
|
PDFColorBuffer targetColor = target.getPixel(x, y);
|
||||||
@ -600,6 +604,8 @@ void PDFTransparencyRenderer::beginPaint(QSize pixelSize)
|
|||||||
|
|
||||||
m_transparencyGroupDataStack.clear();
|
m_transparencyGroupDataStack.clear();
|
||||||
m_painterStateStack.push(PDFTransparencyPainterState());
|
m_painterStateStack.push(PDFTransparencyPainterState());
|
||||||
|
m_painterStateStack.top().softMask = PDFFloatBitmap(pixelSize.width(), pixelSize.height(), PDFPixelFormat::createOpacityMask());
|
||||||
|
m_painterStateStack.top().softMask.makeOpaque();
|
||||||
|
|
||||||
PDFPixelFormat pixelFormat = PDFPixelFormat::createFormat(uint8_t(m_deviceColorSpace->getColorComponentCount()),
|
PDFPixelFormat pixelFormat = PDFPixelFormat::createFormat(uint8_t(m_deviceColorSpace->getColorComponentCount()),
|
||||||
uint8_t(m_inkMapper->getActiveSpotColorCount()),
|
uint8_t(m_inkMapper->getActiveSpotColorCount()),
|
||||||
@ -719,6 +725,8 @@ QImage PDFTransparencyRenderer::toImage(bool use16Bit) const
|
|||||||
|
|
||||||
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);
|
||||||
|
|
||||||
PDFPainterPathSampler clipSampler(m_painterStateStack.top().clipPath, m_settings.samplesCount, 1.0f);
|
PDFPainterPathSampler clipSampler(m_painterStateStack.top().clipPath, m_settings.samplesCount, 1.0f);
|
||||||
|
|
||||||
QMatrix worldMatrix = getCurrentWorldMatrix();
|
QMatrix worldMatrix = getCurrentWorldMatrix();
|
||||||
@ -776,7 +784,7 @@ void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_drawBuffer.markActiveColors(fillColor.activeChannels);
|
m_drawBuffer.markActiveColors(fillColor.activeChannels);
|
||||||
m_drawBuffer.modify(fillRect);
|
m_drawBuffer.modify(fillRect, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,12 +792,12 @@ void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool
|
|||||||
{
|
{
|
||||||
// We must stroke the path.
|
// We must stroke the path.
|
||||||
QPainterPathStroker stroker;
|
QPainterPathStroker stroker;
|
||||||
stroker.setCapStyle(m_graphicState.getLineCapStyle());
|
stroker.setCapStyle(getGraphicState()->getLineCapStyle());
|
||||||
stroker.setWidth(m_graphicState.getLineWidth());
|
stroker.setWidth(getGraphicState()->getLineWidth());
|
||||||
stroker.setMiterLimit(m_graphicState.getMitterLimit());
|
stroker.setMiterLimit(getGraphicState()->getMitterLimit());
|
||||||
stroker.setJoinStyle(m_graphicState.getLineJoinStyle());
|
stroker.setJoinStyle(getGraphicState()->getLineJoinStyle());
|
||||||
|
|
||||||
const PDFLineDashPattern& lineDashPattern = m_graphicState.getLineDashPattern();
|
const PDFLineDashPattern& lineDashPattern = getGraphicState()->getLineDashPattern();
|
||||||
if (!lineDashPattern.isSolid())
|
if (!lineDashPattern.isSolid())
|
||||||
{
|
{
|
||||||
stroker.setDashPattern(QVector<PDFReal>::fromStdVector(lineDashPattern.getDashArray()));
|
stroker.setDashPattern(QVector<PDFReal>::fromStdVector(lineDashPattern.getDashArray()));
|
||||||
@ -834,7 +842,7 @@ void PDFTransparencyRenderer::performPathPainting(const QPainterPath& path, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_drawBuffer.markActiveColors(strokeColor.activeChannels);
|
m_drawBuffer.markActiveColors(strokeColor.activeChannels);
|
||||||
m_drawBuffer.modify(strokeRect);
|
m_drawBuffer.modify(strokeRect, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,7 +991,8 @@ void PDFTransparencyRenderer::performEndTransparencyGroup(ProcessOrder order, co
|
|||||||
sourceData.immediateBackdrop.convertToColorSpace(getCMS(), targetData.renderingIntent, targetData.blendColorSpace, this);
|
sourceData.immediateBackdrop.convertToColorSpace(getCMS(), targetData.renderingIntent, targetData.blendColorSpace, this);
|
||||||
|
|
||||||
PDFFloatBitmap::blend(sourceData.immediateBackdrop, targetData.immediateBackdrop, *getBackdrop(), *getInitialBackdrop(), sourceData.softMask,
|
PDFFloatBitmap::blend(sourceData.immediateBackdrop, targetData.immediateBackdrop, *getBackdrop(), *getInitialBackdrop(), sourceData.softMask,
|
||||||
sourceData.alphaIsShape, sourceData.alphaFill, BlendMode::Normal, targetData.group.knockout, 0xFFFF, PDFFloatBitmap::OverprintMode::NoOveprint);
|
sourceData.alphaIsShape, sourceData.alphaFill, BlendMode::Normal, targetData.group.knockout, 0xFFFF,
|
||||||
|
PDFFloatBitmap::OverprintMode::NoOveprint, getPaintRect());
|
||||||
|
|
||||||
// Create draw buffer
|
// Create draw buffer
|
||||||
PDFFloatBitmapWithColorSpace* backdrop = getImmediateBackdrop();
|
PDFFloatBitmapWithColorSpace* backdrop = getImmediateBackdrop();
|
||||||
@ -1088,6 +1097,28 @@ PDFFloatBitmapWithColorSpace* PDFTransparencyRenderer::getBackdrop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PDFFloatBitmapWithColorSpace* PDFTransparencyRenderer::getInitialBackdrop() const
|
||||||
|
{
|
||||||
|
return &m_transparencyGroupDataStack.back().initialBackdrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PDFFloatBitmapWithColorSpace* PDFTransparencyRenderer::getImmediateBackdrop() const
|
||||||
|
{
|
||||||
|
return &m_transparencyGroupDataStack.back().immediateBackdrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PDFFloatBitmapWithColorSpace* PDFTransparencyRenderer::getBackdrop() const
|
||||||
|
{
|
||||||
|
if (isTransparencyGroupKnockout())
|
||||||
|
{
|
||||||
|
return getInitialBackdrop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return getImmediateBackdrop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const PDFColorSpacePointer& PDFTransparencyRenderer::getBlendColorSpace() const
|
const PDFColorSpacePointer& PDFTransparencyRenderer::getBlendColorSpace() const
|
||||||
{
|
{
|
||||||
return m_transparencyGroupDataStack.back().blendColorSpace;
|
return m_transparencyGroupDataStack.back().blendColorSpace;
|
||||||
@ -1224,10 +1255,10 @@ PDFTransparencyRenderer::PDFMappedColor PDFTransparencyRenderer::getMappedFillCo
|
|||||||
|
|
||||||
QRect PDFTransparencyRenderer::getPaintRect() const
|
QRect PDFTransparencyRenderer::getPaintRect() const
|
||||||
{
|
{
|
||||||
return QRect(0, 0, getBackdrop()->getWidth(), getBackdrop()->getHeight());
|
return QRect(0, 0, int(getBackdrop()->getWidth()), int(getBackdrop()->getHeight()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect PDFTransparencyRenderer::getActualFillRect(QRectF& fillRect) const
|
QRect PDFTransparencyRenderer::getActualFillRect(const QRectF& fillRect) const
|
||||||
{
|
{
|
||||||
int xLeft = qFloor(fillRect.left()) - 1;
|
int xLeft = qFloor(fillRect.left()) - 1;
|
||||||
int xRight = qCeil(fillRect.right()) + 1;
|
int xRight = qCeil(fillRect.right()) + 1;
|
||||||
@ -1242,6 +1273,22 @@ void PDFTransparencyRenderer::flushDrawBuffer()
|
|||||||
{
|
{
|
||||||
if (m_drawBuffer.isModified())
|
if (m_drawBuffer.isModified())
|
||||||
{
|
{
|
||||||
|
PDFOverprintMode overprintMode = getGraphicState()->getOverprintMode();
|
||||||
|
const bool useOverprint = (overprintMode.overprintFilling && m_drawBuffer.isContainsFilling()) ||
|
||||||
|
(overprintMode.overprintStroking && m_drawBuffer.isContainsStroking());
|
||||||
|
|
||||||
|
PDFFloatBitmap::OverprintMode selectedOverprintMode = PDFFloatBitmap::OverprintMode::NoOveprint;
|
||||||
|
if (useOverprint)
|
||||||
|
{
|
||||||
|
selectedOverprintMode = overprintMode.overprintMode == 0 ? PDFFloatBitmap::OverprintMode::Overprint_Mode_0
|
||||||
|
: PDFFloatBitmap::OverprintMode::Overprint_Mode_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFFloatBitmap::blend(m_drawBuffer, *getImmediateBackdrop(), *getBackdrop(), *getInitialBackdrop(), m_painterStateStack.top().softMask,
|
||||||
|
getGraphicState()->getAlphaIsShape(), 1.0f, getGraphicState()->getBlendMode(), isTransparencyGroupKnockout(),
|
||||||
|
m_drawBuffer.getActiveColors(), selectedOverprintMode, m_drawBuffer.getModifiedRect());
|
||||||
|
|
||||||
|
|
||||||
m_drawBuffer.clear();
|
m_drawBuffer.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1547,12 +1594,16 @@ void PDFDrawBuffer::clear()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_activeColors = 0;
|
m_activeColors = 0;
|
||||||
|
m_containsFilling = false;
|
||||||
|
m_containsStroking = false;
|
||||||
m_modifiedRect = QRect();
|
m_modifiedRect = QRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFDrawBuffer::modify(QRect rect)
|
void PDFDrawBuffer::modify(QRect rect, bool containsFilling, bool containsStroking)
|
||||||
{
|
{
|
||||||
m_modifiedRect = m_modifiedRect.united(rect);
|
m_modifiedRect = m_modifiedRect.united(rect);
|
||||||
|
m_containsFilling |= containsFilling;
|
||||||
|
m_containsStroking |= containsStroking;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -200,6 +200,7 @@ public:
|
|||||||
/// \param mode Blend mode
|
/// \param mode Blend mode
|
||||||
/// \param activeColorChannels Active color channels
|
/// \param activeColorChannels Active color channels
|
||||||
/// \param overprintMode Overprint mode
|
/// \param overprintMode Overprint mode
|
||||||
|
/// \param blendRegion Blend region
|
||||||
static void blend(const PDFFloatBitmap& source,
|
static void blend(const PDFFloatBitmap& source,
|
||||||
PDFFloatBitmap& target,
|
PDFFloatBitmap& target,
|
||||||
const PDFFloatBitmap& backdrop,
|
const PDFFloatBitmap& backdrop,
|
||||||
@ -210,7 +211,8 @@ public:
|
|||||||
BlendMode mode,
|
BlendMode mode,
|
||||||
bool knockoutGroup,
|
bool knockoutGroup,
|
||||||
uint32_t activeColorChannels,
|
uint32_t activeColorChannels,
|
||||||
OverprintMode overprintMode);
|
OverprintMode overprintMode,
|
||||||
|
QRect blendRegion);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void fillProcessColorChannels(PDFColorComponent value);
|
void fillProcessColorChannels(PDFColorComponent value);
|
||||||
@ -354,13 +356,24 @@ public:
|
|||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
/// Marks given area as modified
|
/// Marks given area as modified
|
||||||
void modify(QRect rect);
|
void modify(QRect rect, bool containsFilling, bool containsStroking);
|
||||||
|
|
||||||
/// Returns true, if draw buffer is modified and needs to be flushed
|
/// Returns true, if draw buffer is modified and needs to be flushed
|
||||||
bool isModified() const { return m_modifiedRect.isValid(); }
|
bool isModified() const { return m_modifiedRect.isValid(); }
|
||||||
|
|
||||||
|
/// Returns active colors
|
||||||
|
uint32_t getActiveColors() const { return m_activeColors; }
|
||||||
|
|
||||||
|
/// Returns modified rectangle
|
||||||
|
QRect getModifiedRect() const { return m_modifiedRect; }
|
||||||
|
|
||||||
|
bool isContainsFilling() const { return m_containsFilling; }
|
||||||
|
bool isContainsStroking() const { return m_containsStroking; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t m_activeColors = 0;
|
uint32_t m_activeColors = 0;
|
||||||
|
bool m_containsFilling = false;
|
||||||
|
bool m_containsStroking = false;
|
||||||
QRect m_modifiedRect;
|
QRect m_modifiedRect;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -451,6 +464,7 @@ private:
|
|||||||
struct PDFTransparencyPainterState
|
struct PDFTransparencyPainterState
|
||||||
{
|
{
|
||||||
QPainterPath clipPath; ///< Clipping path in device state coordinates
|
QPainterPath clipPath; ///< Clipping path in device state coordinates
|
||||||
|
PDFFloatBitmap softMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PDFMappedColor
|
struct PDFMappedColor
|
||||||
@ -473,6 +487,9 @@ private:
|
|||||||
PDFFloatBitmapWithColorSpace* getInitialBackdrop();
|
PDFFloatBitmapWithColorSpace* getInitialBackdrop();
|
||||||
PDFFloatBitmapWithColorSpace* getImmediateBackdrop();
|
PDFFloatBitmapWithColorSpace* getImmediateBackdrop();
|
||||||
PDFFloatBitmapWithColorSpace* getBackdrop();
|
PDFFloatBitmapWithColorSpace* getBackdrop();
|
||||||
|
const PDFFloatBitmapWithColorSpace* getInitialBackdrop() const;
|
||||||
|
const PDFFloatBitmapWithColorSpace* getImmediateBackdrop() const;
|
||||||
|
const PDFFloatBitmapWithColorSpace* getBackdrop() const;
|
||||||
const PDFColorSpacePointer& getBlendColorSpace() const;
|
const PDFColorSpacePointer& getBlendColorSpace() const;
|
||||||
|
|
||||||
PDFTransparencyPainterState* getPainterState() { return &m_painterStateStack.top(); }
|
PDFTransparencyPainterState* getPainterState() { return &m_painterStateStack.top(); }
|
||||||
@ -492,7 +509,7 @@ private:
|
|||||||
|
|
||||||
/// Returns fill area from fill rectangle
|
/// Returns fill area from fill rectangle
|
||||||
/// \param fillRect Fill rectangle
|
/// \param fillRect Fill rectangle
|
||||||
QRect getActualFillRect(QRectF& fillRect) const;
|
QRect getActualFillRect(const QRectF& fillRect) const;
|
||||||
|
|
||||||
/// Flushes draw buffer
|
/// Flushes draw buffer
|
||||||
void flushDrawBuffer();
|
void flushDrawBuffer();
|
||||||
|
@ -47,6 +47,12 @@ OutputPreviewDialog::~OutputPreviewDialog()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OutputPreviewDialog::resizeEvent(QResizeEvent* event)
|
||||||
|
{
|
||||||
|
QDialog::resizeEvent(event);
|
||||||
|
updateImage();
|
||||||
|
}
|
||||||
|
|
||||||
void OutputPreviewDialog::updateImage()
|
void OutputPreviewDialog::updateImage()
|
||||||
{
|
{
|
||||||
const pdf::PDFPage* page = m_document->getCatalog()->getPage(ui->pageIndexScrollBar->value() - 1);
|
const pdf::PDFPage* page = m_document->getCatalog()->getPage(ui->pageIndexScrollBar->value() - 1);
|
||||||
|
@ -40,6 +40,8 @@ public:
|
|||||||
explicit OutputPreviewDialog(const pdf::PDFDocument* document, pdf::PDFWidget* widget, QWidget* parent);
|
explicit OutputPreviewDialog(const pdf::PDFDocument* document, pdf::PDFWidget* widget, QWidget* parent);
|
||||||
virtual ~OutputPreviewDialog() override;
|
virtual ~OutputPreviewDialog() override;
|
||||||
|
|
||||||
|
virtual void resizeEvent(QResizeEvent* event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateImage();
|
void updateImage();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user