Refactoring, element rendering

This commit is contained in:
Jakub Melka
2024-04-01 16:38:02 +02:00
parent 379fddcc83
commit 34f64c3a85
8 changed files with 216 additions and 98 deletions

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2023 Jakub Melka
// Copyright (C) 2023-2024 Jakub Melka
//
// This file is part of PDF4QT.
//
@@ -61,11 +61,14 @@ void PDFPageContentEditorProcessor::performInterceptInstruction(Operator current
{
if (m_contentElementText && !m_contentElementText->isEmpty())
{
m_contentElementText->setTextPath(std::move(m_textPath));
m_contentElementText->setBoundingBox(m_textBoundingRect);
m_content.addContentElement(std::move(m_contentElementText));
}
m_contentElementText.reset();
m_textBoundingRect = QRectF();
m_textPath = QPainterPath();
}
}
}
@@ -87,6 +90,7 @@ void PDFPageContentEditorProcessor::performPathPainting(const QPainterPath& path
QPainterPath mappedPath = getCurrentWorldMatrix().map(path);
QRectF boundingRect = mappedPath.boundingRect();
m_textBoundingRect = m_textBoundingRect.united(boundingRect);
m_textPath.addPath(mappedPath);
}
else
{
@@ -122,8 +126,9 @@ bool PDFPageContentEditorProcessor::performOriginalImagePainting(const PDFImage&
{
Q_UNUSED(image);
QRectF boundingBox = getCurrentWorldMatrix().mapRect(QRectF(0.0, 0.0, 1.0, 1.0));
PDFObject imageObject = PDFObject::createStream(std::make_shared<PDFStream>(*stream));
m_content.addContentImage(*getGraphicState(), std::move(imageObject), QImage());
m_content.addContentImage(*getGraphicState(), std::move(imageObject), QImage(), boundingBox);
return false;
}
@@ -419,9 +424,9 @@ void PDFEditedPageContent::addContentPath(PDFPageContentProcessorState state, QP
m_contentElements.emplace_back(new PDFEditedPageContentElementPath(std::move(state), std::move(path), strokePath, fillPath));
}
void PDFEditedPageContent::addContentImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image)
void PDFEditedPageContent::addContentImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image, QRectF boundingBox)
{
m_contentElements.emplace_back(new PDFEditedPageContentElementImage(std::move(state), std::move(imageObject), std::move(image)));
m_contentElements.emplace_back(new PDFEditedPageContentElementImage(std::move(state), std::move(imageObject), std::move(image), boundingBox));
}
void PDFEditedPageContent::addContentElement(std::unique_ptr<PDFEditedPageContentElement> element)
@@ -510,10 +515,11 @@ void PDFEditedPageContentElementPath::setFillPath(bool newFillPath)
m_fillPath = newFillPath;
}
PDFEditedPageContentElementImage::PDFEditedPageContentElementImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image) :
PDFEditedPageContentElementImage::PDFEditedPageContentElementImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image, QRectF boundingBox) :
PDFEditedPageContentElement(std::move(state)),
m_imageObject(std::move(imageObject)),
m_image(std::move(image))
m_image(std::move(image)),
m_boundingBox(boundingBox)
{
}
@@ -525,7 +531,12 @@ PDFEditedPageContentElement::Type PDFEditedPageContentElementImage::getType() co
PDFEditedPageContentElementImage* PDFEditedPageContentElementImage::clone() const
{
return new PDFEditedPageContentElementImage(getState(), getImageObject(), getImage());
return new PDFEditedPageContentElementImage(getState(), getImageObject(), getImage(), getBoundingBox());
}
QRectF PDFEditedPageContentElementImage::getBoundingBox() const
{
return m_boundingBox;
}
PDFObject PDFEditedPageContentElementImage::getImageObject() const
@@ -554,9 +565,14 @@ PDFEditedPageContentElementText::PDFEditedPageContentElementText(PDFPageContentP
}
PDFEditedPageContentElementText::PDFEditedPageContentElementText(PDFPageContentProcessorState state, std::vector<Item> items) :
PDFEditedPageContentElementText::PDFEditedPageContentElementText(PDFPageContentProcessorState state,
std::vector<Item> items,
QPainterPath textPath,
QRectF boundingBox) :
PDFEditedPageContentElement(state),
m_items(std::move(items))
m_items(std::move(items)),
m_boundingBox(boundingBox),
m_textPath(std::move(textPath))
{
}
@@ -568,7 +584,7 @@ PDFEditedPageContentElement::Type PDFEditedPageContentElementText::getType() con
PDFEditedPageContentElementText* PDFEditedPageContentElementText::clone() const
{
return new PDFEditedPageContentElementText(getState(), getItems());
return new PDFEditedPageContentElementText(getState(), getItems(), getTextPath(), getBoundingBox());
}
void PDFEditedPageContentElementText::addItem(Item item)
@@ -586,4 +602,24 @@ void PDFEditedPageContentElementText::setItems(const std::vector<Item>& newItems
m_items = newItems;
}
QRectF PDFEditedPageContentElementText::getBoundingBox() const
{
return m_boundingBox;
}
void PDFEditedPageContentElementText::setBoundingBox(const QRectF& newBoundingBox)
{
m_boundingBox = newBoundingBox;
}
QPainterPath PDFEditedPageContentElementText::getTextPath() const
{
return m_textPath;
}
void PDFEditedPageContentElementText::setTextPath(QPainterPath newTextPath)
{
m_textPath = newTextPath;
}
} // namespace pdf

View File

@@ -29,7 +29,7 @@ class PDFEditedPageContentElementPath;
class PDFEditedPageContentElementText;
class PDFEditedPageContentElementImage;
class PDFEditedPageContentElement
class PDF4QTLIBCORESHARED_EXPORT PDFEditedPageContentElement
{
public:
PDFEditedPageContentElement() = default;
@@ -64,7 +64,7 @@ protected:
PDFPageContentProcessorState m_state;
};
class PDFEditedPageContentElementPath : public PDFEditedPageContentElement
class PDF4QTLIBCORESHARED_EXPORT PDFEditedPageContentElementPath : public PDFEditedPageContentElement
{
public:
PDFEditedPageContentElementPath(PDFPageContentProcessorState state, QPainterPath path, bool strokePath, bool fillPath);
@@ -91,16 +91,17 @@ private:
bool m_fillPath;
};
class PDFEditedPageContentElementImage : public PDFEditedPageContentElement
class PDF4QTLIBCORESHARED_EXPORT PDFEditedPageContentElementImage : public PDFEditedPageContentElement
{
public:
PDFEditedPageContentElementImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image);
PDFEditedPageContentElementImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image, QRectF boundingBox);
virtual ~PDFEditedPageContentElementImage() = default;
virtual Type getType() const override;
virtual PDFEditedPageContentElementImage* clone() const override;
virtual PDFEditedPageContentElementImage* asImage() override { return this; }
virtual const PDFEditedPageContentElementImage* asImage() const override { return this; }
virtual QRectF getBoundingBox() const override;
PDFObject getImageObject() const;
void setImageObject(const PDFObject& newImageObject);
@@ -111,9 +112,10 @@ public:
private:
PDFObject m_imageObject;
QImage m_image;
QRectF m_boundingBox;
};
class PDFEditedPageContentElementText : public PDFEditedPageContentElement
class PDF4QTLIBCORESHARED_EXPORT PDFEditedPageContentElementText : public PDFEditedPageContentElement
{
public:
@@ -127,13 +129,17 @@ public:
};
PDFEditedPageContentElementText(PDFPageContentProcessorState state);
PDFEditedPageContentElementText(PDFPageContentProcessorState state, std::vector<Item> items);
PDFEditedPageContentElementText(PDFPageContentProcessorState state,
std::vector<Item> items,
QPainterPath textPath,
QRectF boundingBox);
virtual ~PDFEditedPageContentElementText() = default;
virtual Type getType() const override;
virtual PDFEditedPageContentElementText* clone() const override;
virtual PDFEditedPageContentElementText* asText() override { return this; }
virtual const PDFEditedPageContentElementText* asText() const override { return this; }
virtual QRectF getBoundingBox() const override;
void addItem(Item item);
const std::vector<Item>& getItems() const;
@@ -141,11 +147,18 @@ public:
bool isEmpty() const { return m_items.empty(); }
void setBoundingBox(const QRectF& newBoundingBox);
QPainterPath getTextPath() const;
void setTextPath(QPainterPath newTextPath);
private:
std::vector<Item> m_items;
QRectF m_boundingBox;
QPainterPath m_textPath;
};
class PDFEditedPageContent
class PDF4QTLIBCORESHARED_EXPORT PDFEditedPageContent
{
public:
PDFEditedPageContent() = default;
@@ -159,7 +172,7 @@ public:
static QString getOperandName(PDFPageContentProcessor::Operator operatorValue, int operandIndex);
void addContentPath(PDFPageContentProcessorState state, QPainterPath path, bool strokePath, bool fillPath);
void addContentImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image);
void addContentImage(PDFPageContentProcessorState state, PDFObject imageObject, QImage image, QRectF boundingBox);
void addContentClipping(PDFPageContentProcessorState state, QPainterPath path);
void addContentElement(std::unique_ptr<PDFEditedPageContentElement> element);
@@ -205,6 +218,7 @@ private:
QRectF m_textBoundingRect;
std::stack<QPainterPath> m_clippingPaths;
std::unique_ptr<PDFEditedPageContentElementText> m_contentElementText;
QPainterPath m_textPath;
};
} // namespace pdf

View File

@@ -114,56 +114,12 @@ bool PDFPainterBase::isContentSuppressedByOC(PDFObjectReference ocgOrOcmd)
QPen PDFPainterBase::getCurrentPenImpl() const
{
const PDFPageContentProcessorState* graphicState = getGraphicState();
QColor color = graphicState->getStrokeColor();
if (color.isValid())
{
color.setAlphaF(getEffectiveStrokingAlpha());
const PDFReal lineWidth = graphicState->getLineWidth();
Qt::PenCapStyle penCapStyle = graphicState->getLineCapStyle();
Qt::PenJoinStyle penJoinStyle = graphicState->getLineJoinStyle();
const PDFLineDashPattern& lineDashPattern = graphicState->getLineDashPattern();
const PDFReal mitterLimit = graphicState->getMitterLimit();
QPen pen(color);
pen.setWidthF(lineWidth);
pen.setCapStyle(penCapStyle);
pen.setJoinStyle(penJoinStyle);
pen.setMiterLimit(mitterLimit);
if (lineDashPattern.isSolid())
{
pen.setStyle(Qt::SolidLine);
}
else
{
pen.setStyle(Qt::CustomDashLine);
pen.setDashPattern(lineDashPattern.createForQPen(pen.widthF()));
pen.setDashOffset(lineDashPattern.getDashOffset());
}
return pen;
}
else
{
return QPen(Qt::NoPen);
}
return PDFPainterHelper::createPenFromState(getGraphicState(), getEffectiveStrokingAlpha());
}
QBrush PDFPainterBase::getCurrentBrushImpl() const
{
const PDFPageContentProcessorState* graphicState = getGraphicState();
QColor color = graphicState->getFillColor();
if (color.isValid())
{
color.setAlphaF(getEffectiveFillingAlpha());
return QBrush(color, Qt::SolidPattern);
}
else
{
return QBrush(Qt::NoBrush);
}
return PDFPainterHelper::createBrushFromState(getGraphicState(), getEffectiveFillingAlpha());
}
PDFReal PDFPainterBase::getEffectiveStrokingAlpha() const

View File

@@ -16,6 +16,7 @@
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
#include "pdfpainterutils.h"
#include "pdfpagecontentprocessor.h"
#include <QPainterPath>
#include <QFontMetrics>
@@ -64,5 +65,56 @@ QRect PDFPainterHelper::drawBubble(QPainter* painter, QPoint point, QColor color
return rectangle;
}
QPen PDFPainterHelper::createPenFromState(const PDFPageContentProcessorState* graphicState, double alpha)
{
QColor color = graphicState->getStrokeColor();
if (color.isValid())
{
color.setAlphaF(alpha);
const PDFReal lineWidth = graphicState->getLineWidth();
Qt::PenCapStyle penCapStyle = graphicState->getLineCapStyle();
Qt::PenJoinStyle penJoinStyle = graphicState->getLineJoinStyle();
const PDFLineDashPattern& lineDashPattern = graphicState->getLineDashPattern();
const PDFReal mitterLimit = graphicState->getMitterLimit();
QPen pen(color);
pen.setWidthF(lineWidth);
pen.setCapStyle(penCapStyle);
pen.setJoinStyle(penJoinStyle);
pen.setMiterLimit(mitterLimit);
if (lineDashPattern.isSolid())
{
pen.setStyle(Qt::SolidLine);
}
else
{
pen.setStyle(Qt::CustomDashLine);
pen.setDashPattern(lineDashPattern.createForQPen(pen.widthF()));
pen.setDashOffset(lineDashPattern.getDashOffset());
}
return pen;
}
else
{
return QPen(Qt::NoPen);
}
}
QBrush PDFPainterHelper::createBrushFromState(const PDFPageContentProcessorState* graphicState, double alpha)
{
QColor color = graphicState->getFillColor();
if (color.isValid())
{
color.setAlphaF(alpha);
return QBrush(color, Qt::SolidPattern);
}
else
{
return QBrush(Qt::NoBrush);
}
}
} // namespace pdf

View File

@@ -24,6 +24,7 @@
namespace pdf
{
class PDFPageContentProcessorState;
/// RAII wrapper for painter save/restore
class PDFPainterStateGuard
@@ -55,6 +56,12 @@ public:
/// \param text Text inside the bubble
/// \param alignment Bubble alignment relative to the bubble position point
static QRect drawBubble(QPainter* painter, QPoint point, QColor color, QString text, Qt::Alignment alignment);
/// Creates pen from painter graphicState
static QPen createPenFromState(const PDFPageContentProcessorState* graphicState, double alpha);
/// Creates brush from painter graphicState
static QBrush createBrushFromState(const PDFPageContentProcessorState* graphicState, double alpha);
};
} // namespace pdf