mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-02-22 22:47:50 +01:00
Editor plugin: Building stream
This commit is contained in:
parent
75db2de2a0
commit
a40faf855d
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2023 Jakub Melka
|
||||
// Copyright (C) 2023-2024 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
@ -41,7 +41,7 @@ EditorPlugin::EditorPlugin() :
|
||||
m_scene(nullptr),
|
||||
m_sceneSelectionChangeEnabled(true)
|
||||
{
|
||||
|
||||
m_scene.setIsPageContentDrawSuppressed(true);
|
||||
}
|
||||
|
||||
void EditorPlugin::setWidget(pdf::PDFWidget* widget)
|
||||
|
@ -32,6 +32,9 @@ PDFPageContentEditorProcessor::PDFPageContentEditorProcessor(const PDFPage* page
|
||||
BaseClass(page, document, fontCache, CMS, optionalContentActivity, pagePointToDevicePointMatrix, meshQualitySettings)
|
||||
{
|
||||
m_clippingPaths.push(QPainterPath());
|
||||
|
||||
m_content.setFontDictionary(*getFontDictionary());
|
||||
m_content.setXObjectDictionary(*getXObjectDictionary());
|
||||
}
|
||||
|
||||
const PDFEditedPageContent& PDFPageContentEditorProcessor::getEditedPageContent() const
|
||||
@ -451,6 +454,26 @@ PDFEditedPageContentElement* PDFEditedPageContent::getBackElement() const
|
||||
return m_contentElements.back().get();
|
||||
}
|
||||
|
||||
PDFDictionary PDFEditedPageContent::getFontDictionary() const
|
||||
{
|
||||
return m_fontDictionary;
|
||||
}
|
||||
|
||||
void PDFEditedPageContent::setFontDictionary(const PDFDictionary& newFontDictionary)
|
||||
{
|
||||
m_fontDictionary = newFontDictionary;
|
||||
}
|
||||
|
||||
PDFDictionary PDFEditedPageContent::getXObjectDictionary() const
|
||||
{
|
||||
return m_xobjectDictionary;
|
||||
}
|
||||
|
||||
void PDFEditedPageContent::setXObjectDictionary(const PDFDictionary& newXobjectDictionary)
|
||||
{
|
||||
m_xobjectDictionary = newXobjectDictionary;
|
||||
}
|
||||
|
||||
PDFEditedPageContentElement::PDFEditedPageContentElement(PDFPageContentProcessorState state, QTransform transform) :
|
||||
m_state(std::move(state)),
|
||||
m_transform(transform)
|
||||
@ -737,4 +760,102 @@ QString PDFEditedPageContentElementText::getItemsAsText() const
|
||||
return text;
|
||||
}
|
||||
|
||||
void PDFPageContentEditorContentStreamBuilder::writeStateDifference(const PDFPageContentProcessorState& state)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PDFPageContentEditorContentStreamBuilder::writeElement(const PDFEditedPageContentElement* element)
|
||||
{
|
||||
PDFPageContentProcessorState state = element->getState();
|
||||
state.setCurrentTransformationMatrix(element->getTransform());
|
||||
writeStateDifference(state);
|
||||
|
||||
QDataStream stream(&m_outputContent, QDataStream::WriteOnly);
|
||||
|
||||
if (const PDFEditedPageContentElementImage* imageElement = element->asImage())
|
||||
{
|
||||
QImage image = imageElement->getImage();
|
||||
PDFObject imageObject = imageElement->getImageObject();
|
||||
}
|
||||
|
||||
if (const PDFEditedPageContentElementPath* pathElement = element->asPath())
|
||||
{
|
||||
const bool isStroking = pathElement->getStrokePath();
|
||||
const bool isFilling = pathElement->getFillPath();
|
||||
|
||||
writePainterPath(stream, pathElement->getPath(), isStroking, isFilling);
|
||||
}
|
||||
|
||||
stream << Qt::endl;
|
||||
}
|
||||
|
||||
void PDFPageContentEditorContentStreamBuilder::writePainterPath(QDataStream& stream,
|
||||
const QPainterPath& path,
|
||||
bool isStroking,
|
||||
bool isFilling)
|
||||
{
|
||||
const int elementCount = path.elementCount();
|
||||
|
||||
for (int i = 0; i < elementCount; ++i)
|
||||
{
|
||||
QPainterPath::Element element = path.elementAt(i);
|
||||
|
||||
switch (element.type)
|
||||
{
|
||||
case QPainterPath::MoveToElement:
|
||||
stream << element.x << " " << element.y << " m" << Qt::endl;
|
||||
break;
|
||||
case QPainterPath::LineToElement:
|
||||
stream << element.x << " " << element.y << " l" << Qt::endl;
|
||||
break;
|
||||
case QPainterPath::CurveToElement:
|
||||
stream << element.x << " " << element.y << " c" << Qt::endl;
|
||||
break;
|
||||
case QPainterPath::CurveToDataElement:
|
||||
stream << element.x << " " << element.y << " ";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isStroking && !isFilling)
|
||||
{
|
||||
stream << "S" << Qt::endl;
|
||||
}
|
||||
else if (isStroking || isFilling)
|
||||
{
|
||||
switch (path.fillRule())
|
||||
{
|
||||
case Qt::OddEvenFill:
|
||||
if (isFilling && isStroking)
|
||||
{
|
||||
stream << "B*" << Qt::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << "f*" << Qt::endl;
|
||||
}
|
||||
break;
|
||||
case Qt::WindingFill:
|
||||
if (isFilling && isStroking)
|
||||
{
|
||||
stream << "B" << Qt::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << "f" << Qt::endl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << "n" << Qt::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -190,8 +190,38 @@ public:
|
||||
|
||||
PDFEditedPageContentElement* getBackElement() const;
|
||||
|
||||
PDFDictionary getFontDictionary() const;
|
||||
void setFontDictionary(const PDFDictionary& newFontDictionary);
|
||||
|
||||
PDFDictionary getXObjectDictionary() const;
|
||||
void setXObjectDictionary(const PDFDictionary& newXobjectDictionary);
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<PDFEditedPageContentElement>> m_contentElements;
|
||||
PDFDictionary m_fontDictionary;
|
||||
PDFDictionary m_xobjectDictionary;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentEditorContentStreamBuilder
|
||||
{
|
||||
public:
|
||||
PDFPageContentEditorContentStreamBuilder();
|
||||
|
||||
void writeStateDifference(const PDFPageContentProcessorState& state);
|
||||
void writeElement(const PDFEditedPageContentElement* element);
|
||||
|
||||
const QByteArray& getOutputContent() const;
|
||||
|
||||
private:
|
||||
void writePainterPath(QDataStream& stream,
|
||||
const QPainterPath& path,
|
||||
bool isStroking,
|
||||
bool isFilling);
|
||||
|
||||
PDFDictionary m_fontDictionary;
|
||||
PDFDictionary m_xobjectDictionary;
|
||||
QByteArray m_outputContent;
|
||||
PDFPageContentProcessorState m_currentState;
|
||||
};
|
||||
|
||||
class PDF4QTLIBCORESHARED_EXPORT PDFPageContentEditorProcessor : public PDFPageContentProcessor
|
||||
|
@ -742,6 +742,14 @@ protected:
|
||||
/// Process form using form stream
|
||||
void processForm(const PDFStream* stream);
|
||||
|
||||
const PDFDictionary* getColorSpaceDictionary() const { return m_colorSpaceDictionary; }
|
||||
const PDFDictionary* getFontDictionary() const { return m_fontDictionary; }
|
||||
const PDFDictionary* getXObjectDictionary() const { return m_xobjectDictionary; }
|
||||
const PDFDictionary* getExtendedGraphicStateDictionary() const { return m_extendedGraphicStateDictionary; }
|
||||
const PDFDictionary* getPropertiesDictionary() const { return m_propertiesDictionary; }
|
||||
const PDFDictionary* getShadingDictionary() const { return m_shadingDictionary; }
|
||||
const PDFDictionary* getPatternDictionary() const { return m_patternDictionary; }
|
||||
|
||||
private:
|
||||
/// Initializes the resources dictionaries
|
||||
void initDictionaries(const PDFObject& resourcesObject);
|
||||
|
@ -59,6 +59,10 @@ public:
|
||||
/// \param painter Painter
|
||||
/// \param rect Draw rectangle (usually viewport rectangle of the pdf widget)
|
||||
virtual void drawPostRendering(QPainter* painter, QRect rect) const;
|
||||
|
||||
/// Returns true if drawing of the page content should be suppressed.
|
||||
/// This is used for special purposes, such as rendering edited page content.
|
||||
virtual bool isPageContentDrawSuppressed() const;
|
||||
};
|
||||
|
||||
/// Input interface for handling events. Implementations should react on these events,
|
||||
|
@ -809,9 +809,19 @@ void PDFDrawWidgetProxy::drawPages(QPainter* painter, QRect rect, PDFRenderer::F
|
||||
|
||||
const PDFPage* page = m_controller->getDocument()->getCatalog()->getPage(item.pageIndex);
|
||||
QTransform matrix = QTransform(createPagePointToDevicePointMatrix(page, placedRect)) * baseMatrix;
|
||||
compiledPage->draw(painter, page->getCropBox(), matrix, features, groupInfo.transparency);
|
||||
PDFTextLayoutGetter layoutGetter = m_textLayoutCompiler->getTextLayoutLazy(item.pageIndex);
|
||||
|
||||
bool isPageContentDrawSuppressed = false;
|
||||
for (IDocumentDrawInterface* drawInterface : m_drawInterfaces)
|
||||
{
|
||||
isPageContentDrawSuppressed = isPageContentDrawSuppressed || drawInterface->isPageContentDrawSuppressed();
|
||||
}
|
||||
|
||||
if (!isPageContentDrawSuppressed)
|
||||
{
|
||||
compiledPage->draw(painter, page->getCropBox(), matrix, features, groupInfo.transparency);
|
||||
}
|
||||
|
||||
// Draw text blocks/text lines, if it is enabled
|
||||
if (features.testFlag(PDFRenderer::DebugTextBlocks))
|
||||
{
|
||||
@ -1629,4 +1639,9 @@ void IDocumentDrawInterface::drawPostRendering(QPainter* painter, QRect rect) co
|
||||
Q_UNUSED(rect);
|
||||
}
|
||||
|
||||
bool IDocumentDrawInterface::isPageContentDrawSuppressed() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -333,6 +333,7 @@ PDFPageContentScene::PDFPageContentScene(QObject* parent) :
|
||||
QObject(parent),
|
||||
m_firstFreeId(1),
|
||||
m_isActive(false),
|
||||
m_isPageContentDrawSuppressed(false),
|
||||
m_widget(nullptr),
|
||||
m_manipulator(this, nullptr)
|
||||
{
|
||||
@ -642,6 +643,11 @@ int PDFPageContentScene::getInputPriority() const
|
||||
return ToolPriority + 1;
|
||||
}
|
||||
|
||||
bool PDFPageContentScene::isPageContentDrawSuppressed() const
|
||||
{
|
||||
return isActive() && m_isPageContentDrawSuppressed;
|
||||
}
|
||||
|
||||
void PDFPageContentScene::drawElements(QPainter* painter,
|
||||
PDFInteger pageIndex,
|
||||
PDFTextLayoutGetter& layoutGetter,
|
||||
@ -823,6 +829,11 @@ void PDFPageContentScene::onSelectionChanged()
|
||||
Q_EMIT selectionChanged();
|
||||
}
|
||||
|
||||
void PDFPageContentScene::setIsPageContentDrawSuppressed(bool newIsPageContentDrawSuppressed)
|
||||
{
|
||||
m_isPageContentDrawSuppressed = newIsPageContentDrawSuppressed;
|
||||
}
|
||||
|
||||
PDFWidget* PDFPageContentScene::widget() const
|
||||
{
|
||||
return m_widget;
|
||||
|
@ -561,6 +561,7 @@ public:
|
||||
virtual QString getTooltip() const override;
|
||||
virtual const std::optional<QCursor>& getCursor() const override;
|
||||
virtual int getInputPriority() const override;
|
||||
virtual bool isPageContentDrawSuppressed() const;
|
||||
|
||||
virtual void drawPage(QPainter* painter,
|
||||
PDFInteger pageIndex,
|
||||
@ -579,6 +580,8 @@ public:
|
||||
const PDFPrecompiledPage* compiledPage,
|
||||
QList<PDFRenderError>& errors) const;
|
||||
|
||||
void setIsPageContentDrawSuppressed(bool newIsPageContentDrawSuppressed);
|
||||
|
||||
signals:
|
||||
/// This signal is emitted when scene has changed (including graphics)
|
||||
void sceneChanged(bool graphicsOnly);
|
||||
@ -637,6 +640,7 @@ private:
|
||||
|
||||
PDFInteger m_firstFreeId;
|
||||
bool m_isActive;
|
||||
bool m_isPageContentDrawSuppressed;
|
||||
PDFWidget* m_widget;
|
||||
std::vector<std::unique_ptr<PDFPageContentElement>> m_elements;
|
||||
std::optional<QCursor> m_cursor;
|
||||
|
Loading…
x
Reference in New Issue
Block a user