mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-02-04 19:27:31 +01:00
Ability to draw on a page trough page content stream builder
This commit is contained in:
parent
cb3a36f891
commit
018c8fae3e
@ -25,4 +25,5 @@ int main(int argc, char *argv[])
|
||||
PDFExamplesGenerator::generateAnnotationsExample();
|
||||
PDFExamplesGenerator::generatePageBoxesExample();
|
||||
PDFExamplesGenerator::generateOutlineExample();
|
||||
PDFExamplesGenerator::generatePageDrawExample();
|
||||
}
|
||||
|
@ -358,3 +358,31 @@ void PDFExamplesGenerator::generateOutlineExample()
|
||||
pdf::PDFDocumentWriter writer(nullptr);
|
||||
writer.write("Ex_Outline.pdf", &document, false);
|
||||
}
|
||||
|
||||
void PDFExamplesGenerator::generatePageDrawExample()
|
||||
{
|
||||
pdf::PDFDocumentBuilder builder;
|
||||
builder.setDocumentTitle("Test document - Page draw");
|
||||
builder.setDocumentAuthor("Jakub Melka");
|
||||
builder.setDocumentCreator(QCoreApplication::applicationName());
|
||||
builder.setDocumentSubject("Testing page draw");
|
||||
builder.setLanguage(QLocale::system());
|
||||
|
||||
QPainter* painter = nullptr;
|
||||
pdf::PDFPageContentStreamBuilder pageContentStreamBuilder(&builder);
|
||||
|
||||
painter = pageContentStreamBuilder.beginNewPage(QRectF(0, 0, 300, 480));
|
||||
painter->drawEllipse(QPointF(150, 240), 65, 25);
|
||||
painter->fillRect(QRectF(0, 0, 50, 50), Qt::green);
|
||||
pageContentStreamBuilder.end(painter);
|
||||
|
||||
painter = pageContentStreamBuilder.beginNewPage(QRectF(0, 0, 300, 480));
|
||||
painter->drawText(QPointF(50, 50), "This is testing text!");
|
||||
pageContentStreamBuilder.end(painter);
|
||||
|
||||
// Write result to a file
|
||||
pdf::PDFDocument document = builder.build();
|
||||
pdf::PDFDocumentWriter writer(nullptr);
|
||||
writer.write("Ex_PageDraw.pdf", &document, false);
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
static void generateAnnotationsExample();
|
||||
static void generatePageBoxesExample();
|
||||
static void generateOutlineExample();
|
||||
static void generatePageDrawExample();
|
||||
};
|
||||
|
||||
#endif // PDFEXAMPLESGENERATOR_H
|
||||
|
@ -666,6 +666,82 @@ std::array<PDFReal, 4> PDFDocumentBuilder::getAnnotationReductionRectangle(const
|
||||
return { qAbs(innerRect.left() - boundingRect.left()), qAbs(boundingRect.bottom() - innerRect.bottom()), qAbs(boundingRect.right() - innerRect.right()), qAbs(boundingRect.top() - innerRect.top()) };
|
||||
}
|
||||
|
||||
PDFPageContentStreamBuilder::PDFPageContentStreamBuilder(PDFDocumentBuilder* builder) :
|
||||
m_documentBuilder(builder),
|
||||
m_contentStreamBuilder(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QPainter* PDFPageContentStreamBuilder::begin(PDFObjectReference page)
|
||||
{
|
||||
if (m_contentStreamBuilder)
|
||||
{
|
||||
// Invalid call to begin function
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const PDFObjectStorage* storage = m_documentBuilder->getStorage();
|
||||
const PDFDictionary* pageDictionary = storage->getDictionaryFromObject(storage->getObject(page));
|
||||
if (!pageDictionary)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PDFDocumentDataLoaderDecorator loader(storage);
|
||||
QRectF mediaBox = loader.readRectangle(pageDictionary->get("MediaBox"), QRectF());
|
||||
if (!mediaBox.isValid())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_pageReference = page;
|
||||
m_contentStreamBuilder = new PDFContentStreamBuilder(mediaBox.size(), PDFContentStreamBuilder::CoordinateSystem::Qt);
|
||||
return m_contentStreamBuilder->begin();
|
||||
}
|
||||
|
||||
QPainter* PDFPageContentStreamBuilder::beginNewPage(QRectF mediaBox)
|
||||
{
|
||||
return begin(m_documentBuilder->appendPage(mediaBox));
|
||||
}
|
||||
|
||||
void PDFPageContentStreamBuilder::end(QPainter* painter)
|
||||
{
|
||||
if (!m_contentStreamBuilder)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PDFContentStreamBuilder::ContentStream contentStream = m_contentStreamBuilder->end(painter);
|
||||
|
||||
delete m_contentStreamBuilder;
|
||||
m_contentStreamBuilder = nullptr;
|
||||
|
||||
// Update page's content stream
|
||||
|
||||
std::vector<PDFObject> copiedObjects = m_documentBuilder->copyFrom({ contentStream.resources, contentStream.contents }, contentStream.document.getStorage(), true);
|
||||
Q_ASSERT(copiedObjects.size() == 2);
|
||||
|
||||
PDFObjectReference resourcesReference = copiedObjects[0].getReference();
|
||||
PDFObjectReference contentsReference = copiedObjects[1].getReference();
|
||||
|
||||
PDFObjectFactory pageUpdateFactory;
|
||||
|
||||
pageUpdateFactory.beginDictionary();
|
||||
|
||||
pageUpdateFactory.beginDictionaryItem("Contents");
|
||||
pageUpdateFactory << contentsReference;
|
||||
pageUpdateFactory.endDictionaryItem();
|
||||
|
||||
pageUpdateFactory.beginDictionaryItem("Resources");
|
||||
pageUpdateFactory << resourcesReference;
|
||||
pageUpdateFactory.endDictionaryItem();
|
||||
|
||||
pageUpdateFactory.endDictionary();
|
||||
|
||||
m_documentBuilder->mergeTo(m_pageReference, pageUpdateFactory.takeObject());
|
||||
}
|
||||
|
||||
void PDFDocumentBuilder::updateAnnotationAppearanceStreams(PDFObjectReference annotationReference)
|
||||
{
|
||||
PDFAnnotationPtr annotation = PDFAnnotation::parse(&m_storage, annotationReference);
|
||||
@ -4436,7 +4512,6 @@ void PDFDocumentBuilder::updateTrailerDictionary(PDFInteger objectCount)
|
||||
updateDocumentInfo(qMove(updatedInfoDictionary));
|
||||
}
|
||||
|
||||
|
||||
/* END GENERATED CODE */
|
||||
|
||||
} // namespace pdf
|
||||
|
@ -246,6 +246,41 @@ private:
|
||||
QPainter* m_painter;
|
||||
};
|
||||
|
||||
/// This class can create page content streams, using the Qt's QPainter
|
||||
/// to draw graphics elements on it. Content stream can have various
|
||||
/// resources, which can, if selected be dereferenced, so content
|
||||
/// stream is encapsulated and doesn't contain references.
|
||||
class PDFFORQTLIBSHARED_EXPORT PDFPageContentStreamBuilder
|
||||
{
|
||||
public:
|
||||
PDFPageContentStreamBuilder(PDFDocumentBuilder* builder);
|
||||
|
||||
/// Starts painting onto the page. Old page content is erased. This
|
||||
/// function returns painter, onto which can be graphics drawn. Painter
|
||||
/// uses Qt's coordinate system. Calling begin multiple times, without
|
||||
/// subsequent calls to end function, is invalid and can result
|
||||
/// in undefined behaviour. This function can return nullptr,
|
||||
/// if error occurs.
|
||||
/// \param page Page, onto which we want to draw
|
||||
QPainter* begin(PDFObjectReference page);
|
||||
|
||||
/// This function is similar to function \p begin(), but it appends
|
||||
/// a new page to the end of the document.
|
||||
/// \param mediaBox Page's media box
|
||||
QPainter* beginNewPage(QRectF mediaBox);
|
||||
|
||||
/// Finishes painting on a page content stream. This function updates
|
||||
/// page content stream, which is associated with this page. This function
|
||||
/// must be called with painter, which has been returned with call to begin function.
|
||||
/// \param painter Painter, which was returned with function begin()
|
||||
void end(QPainter* painter);
|
||||
|
||||
private:
|
||||
PDFDocumentBuilder* m_documentBuilder;
|
||||
PDFContentStreamBuilder* m_contentStreamBuilder;
|
||||
PDFObjectReference m_pageReference;
|
||||
};
|
||||
|
||||
class PDFFORQTLIBSHARED_EXPORT PDFDocumentBuilder
|
||||
{
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user