From 992e4b32f368b9bc15ae841cf366731e91a4f253 Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Sun, 5 Apr 2020 13:56:12 +0200 Subject: [PATCH] Caret annotation graphics --- PdfExampleGenerator/pdfexamplesgenerator.cpp | 5 + PdfForQtLib/sources/pdfannotation.cpp | 27 + PdfForQtLib/sources/pdfannotation.h | 1 + PdfForQtLib/sources/pdfdocumentbuilder.cpp | 65 ++ PdfForQtLib/sources/pdfdocumentbuilder.h | 19 + generated_code_definition.xml | 782 ++++++++++++------- 6 files changed, 617 insertions(+), 282 deletions(-) diff --git a/PdfExampleGenerator/pdfexamplesgenerator.cpp b/PdfExampleGenerator/pdfexamplesgenerator.cpp index 6306da7..2a12715 100644 --- a/PdfExampleGenerator/pdfexamplesgenerator.cpp +++ b/PdfExampleGenerator/pdfexamplesgenerator.cpp @@ -237,6 +237,11 @@ void PDFExamplesGenerator::generateAnnotationsExample() builder.createAnnotationStrikeout(page11, QRectF(50, 150, 50, 50), Qt::green); builder.createAnnotationStrikeout(page11, QRectF(50, 250, 50, 50), Qt::red); + pdf::PDFObjectReference page12 = builder.appendPage(QRectF(0, 0, 400, 400)); + builder.createAnnotationCaret(page12, QRectF(50, 50, 50, 50), 3.0, Qt::blue, "Title1", "Subject1", "Contents - green filling, red boundary"); + builder.createAnnotationCaret(page12, QRectF(50, 150, 50, 50), 3.0, Qt::red, "Title2", "Subject2", "Contents - red boundary"); + builder.createAnnotationCaret(page12, QRectF(50, 250, 50, 50), 3.0, Qt::green, "Title3", "Subject3", "Contents - green filling"); + // Write result to a file pdf::PDFDocument document = builder.build(); pdf::PDFDocumentWriter writer(nullptr); diff --git a/PdfForQtLib/sources/pdfannotation.cpp b/PdfForQtLib/sources/pdfannotation.cpp index c330c02..b0563a7 100644 --- a/PdfForQtLib/sources/pdfannotation.cpp +++ b/PdfForQtLib/sources/pdfannotation.cpp @@ -1911,4 +1911,31 @@ void PDFFreeTextAnnotation::draw(AnnotationDrawParameters& parameters) const painter.drawText(QRectF(QPointF(0, 0), textRect.size()), getContents(), option); } +void PDFCaretAnnotation::draw(AnnotationDrawParameters& parameters) const +{ + QPainter& painter = *parameters.painter; + parameters.boundingRectangle = getRectangle(); + + QRectF caretRect = getCaretRectangle(); + if (caretRect.isEmpty()) + { + caretRect = getRectangle(); + } + + QPointF controlPoint(caretRect.center()); + controlPoint.setY(caretRect.top()); + + QPointF topPoint = controlPoint; + topPoint.setY(caretRect.bottom()); + + QPainterPath path; + path.moveTo(caretRect.topLeft()); + path.quadTo(controlPoint, topPoint); + path.quadTo(controlPoint, caretRect.topRight()); + path.lineTo(caretRect.topLeft()); + path.closeSubpath(); + + painter.fillPath(path, QBrush(getStrokeColor(), Qt::SolidPattern)); +} + } // namespace pdf diff --git a/PdfForQtLib/sources/pdfannotation.h b/PdfForQtLib/sources/pdfannotation.h index 34b1765..d7890af 100644 --- a/PdfForQtLib/sources/pdfannotation.h +++ b/PdfForQtLib/sources/pdfannotation.h @@ -917,6 +917,7 @@ public: }; virtual AnnotationType getType() const override { return AnnotationType::Caret; } + virtual void draw(AnnotationDrawParameters& parameters) const override; const QRectF& getCaretRectangle() const { return m_caretRectangle; } Symbol getSymbol() const { return m_symbol; } diff --git a/PdfForQtLib/sources/pdfdocumentbuilder.cpp b/PdfForQtLib/sources/pdfdocumentbuilder.cpp index f7f4afe..e2ee66f 100644 --- a/PdfForQtLib/sources/pdfdocumentbuilder.cpp +++ b/PdfForQtLib/sources/pdfdocumentbuilder.cpp @@ -1100,6 +1100,71 @@ PDFObjectReference PDFDocumentBuilder::createActionURI(QString URL) } +PDFObjectReference PDFDocumentBuilder::createAnnotationCaret(PDFObjectReference page, + QRectF rectangle, + PDFReal borderWidth, + QColor color, + QString title, + QString subject, + QString contents) +{ + PDFObjectFactory objectBuilder; + + objectBuilder.beginDictionary(); + objectBuilder.beginDictionaryItem("Type"); + objectBuilder << WrapName("Annot"); + objectBuilder.endDictionaryItem(); + objectBuilder.beginDictionaryItem("Subtype"); + objectBuilder << WrapName("Caret"); + objectBuilder.endDictionaryItem(); + objectBuilder.beginDictionaryItem("Rect"); + objectBuilder << rectangle; + objectBuilder.endDictionaryItem(); + objectBuilder.beginDictionaryItem("F"); + objectBuilder << 4; + objectBuilder.endDictionaryItem(); + objectBuilder.beginDictionaryItem("P"); + objectBuilder << page; + objectBuilder.endDictionaryItem(); + objectBuilder.beginDictionaryItem("M"); + objectBuilder << WrapCurrentDateTime(); + objectBuilder.endDictionaryItem(); + objectBuilder.beginDictionaryItem("CreationDate"); + objectBuilder << WrapCurrentDateTime(); + objectBuilder.endDictionaryItem(); + objectBuilder.beginDictionaryItem("Border"); + objectBuilder << std::initializer_list{ 0.0, 0.0, borderWidth }; + objectBuilder.endDictionaryItem(); + objectBuilder.beginDictionaryItem("C"); + objectBuilder << WrapAnnotationColor(color); + objectBuilder.endDictionaryItem(); + objectBuilder.beginDictionaryItem("T"); + objectBuilder << title; + objectBuilder.endDictionaryItem(); + objectBuilder.beginDictionaryItem("Contents"); + objectBuilder << contents; + objectBuilder.endDictionaryItem(); + objectBuilder.beginDictionaryItem("Subj"); + objectBuilder << subject; + objectBuilder.endDictionaryItem(); + objectBuilder.endDictionary(); + PDFObjectReference annotationObject = addObject(objectBuilder.takeObject()); + PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(rectangle), false); + + objectBuilder.beginDictionary(); + objectBuilder.beginDictionaryItem("Annots"); + objectBuilder.beginArray(); + objectBuilder << annotationObject; + objectBuilder.endArray(); + objectBuilder.endDictionaryItem(); + objectBuilder.endDictionary(); + PDFObject pageAnnots = objectBuilder.takeObject(); + appendTo(page, pageAnnots); + updateAnnotationAppearanceStreams(annotationObject); + return annotationObject; +} + + PDFObjectReference PDFDocumentBuilder::createAnnotationCircle(PDFObjectReference page, QRectF rectangle, PDFReal borderWidth, diff --git a/PdfForQtLib/sources/pdfdocumentbuilder.h b/PdfForQtLib/sources/pdfdocumentbuilder.h index 3194f2f..0d39e3d 100644 --- a/PdfForQtLib/sources/pdfdocumentbuilder.h +++ b/PdfForQtLib/sources/pdfdocumentbuilder.h @@ -289,6 +289,25 @@ public: PDFObjectReference createActionURI(QString URL); + /// Caret annotations are used to indicate, where text should be inserted (for example, if reviewer + /// reviews the document, and he wants to mark, that some text should be inserted, he uses this + /// annotation). + /// \param page Page to which is annotation added + /// \param rectangle Area in which is caret displayed + /// \param borderWidth Border width + /// \param color Caret color. If you do not want to have a border, then use invalid QColor. + /// \param title Title + /// \param subject Subject + /// \param contents Contents + PDFObjectReference createAnnotationCaret(PDFObjectReference page, + QRectF rectangle, + PDFReal borderWidth, + QColor color, + QString title, + QString subject, + QString contents); + + /// Circle annotation displays ellipse (or circle). Circle border/fill color can be defined, along with /// border width. Popup annotation can be attached to this annotation. /// \param page Page to which is annotation added diff --git a/generated_code_definition.xml b/generated_code_definition.xml index 0d611c8..c01ed5a 100644 --- a/generated_code_definition.xml +++ b/generated_code_definition.xml @@ -183,6 +183,224 @@ return pageReference; Creates URI action. _PDFObjectReference + + + + + + + + + + page + _PDFObjectReference + Page to which is annotation added + + + + + rectangle + _QRectF + Area in which is caret displayed + + + + + borderWidth + _PDFReal + Border width + + + + + color + _QColor + Caret color. If you do not want to have a border, then use invalid QColor. + + + + + title + _QString + Title + + + + + subject + _QString + Subject + + + + + contents + _QString + Contents + + + Parameters + + _void + + + + + + + + + + + + Type + DictionaryItemSimple + WrapName("Annot") + + + + + Subtype + DictionaryItemSimple + WrapName("Caret") + + + + + Rect + DictionaryItemSimple + rectangle + + + + + F + DictionaryItemSimple + 4 + + + + + P + DictionaryItemSimple + page + + + + + M + DictionaryItemSimple + WrapCurrentDateTime() + + + + + CreationDate + DictionaryItemSimple + WrapCurrentDateTime() + + + + + Border + DictionaryItemSimple + std::initializer_list<PDFReal>{ 0.0, 0.0, borderWidth } + + + + + C + DictionaryItemSimple + WrapAnnotationColor(color) + + + + + T + DictionaryItemSimple + title + + + + + Contents + DictionaryItemSimple + contents + + + + + Subj + DictionaryItemSimple + subject + + + + Dictionary + + + + CreateObject + annotationObject + _PDFObjectReference + + + + + + Code + + _void + PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(rectangle), false); + + + + + + + + + + + + + + + ArraySimple + annotationObject + + + Annots + DictionaryItemComplex + + + + + Dictionary + + + + CreateObject + pageAnnots + _PDFObject + + + + + + Code + + _void + appendTo(page, pageAnnots); +updateAnnotationAppearanceStreams(annotationObject); +return annotationObject; + + + Annotations + createAnnotationCaret + Caret annotations are used to indicate, where text should be inserted (for example, if reviewer reviews the document, and he wants to mark, that some text should be inserted, he uses this annotation). + _PDFObjectReference + @@ -877,6 +1095,288 @@ return annotationObject; _void appendTo(page, pageAnnots); updateAnnotationAppearanceStreams(annotationObject); +return annotationObject; + + + Annotations + createAnnotationFreeText + Free text annotation displays text directly on a page. Text appears directly on the page, in the same way, as standard text in PDF document. Free text annotations are usually used to comment the document. Free text annotation can also have callout line, with, or without a knee. Specify start/end point parameters of this function to get callout line. + _PDFObjectReference + + + + + + + + + + + page + _PDFObjectReference + Page to which is annotation added + + + + + boundingRectangle + _QRectF + Bounding rectangle of free text annotation. It must contain both callout line and text rectangle. + + + + + textRectangle + _QRectF + Rectangle with text, in absolute coordinates. They are then recomputed to match bounding rectangle. + + + + + title + _QString + Title + + + + + subject + _QString + Subject + + + + + contents + _QString + Contents (text displayed) + + + + + textAlignment + _TextAlignment + Text alignment. Only horizontal alignment flags are valid. + + + + + startPoint + _QPointF + Start point of callout line + + + + + kneePoint + _QPointF + Knee point of callout line + + + + + endPoint + _QPointF + End point of callout line + + + + + startLineType + _AnnotationLineEnding + Line ending at the start point + + + + + endLineType + _AnnotationLineEnding + Line ending at the end point + + + Parameters + + _void + + + + + + + + + + + + Type + DictionaryItemSimple + WrapName("Annot") + + + + + Subtype + DictionaryItemSimple + WrapName("FreeText") + + + + + Rect + DictionaryItemSimple + boundingRectangle + + + + + F + DictionaryItemSimple + 4 + + + + + P + DictionaryItemSimple + page + + + + + M + DictionaryItemSimple + WrapCurrentDateTime() + + + + + CreationDate + DictionaryItemSimple + WrapCurrentDateTime() + + + + + T + DictionaryItemSimple + title + + + + + Contents + DictionaryItemSimple + contents + + + + + Subj + DictionaryItemSimple + subject + + + + + Q + DictionaryItemSimple + WrapFreeTextAlignment(textAlignment) + + + + + DA + DictionaryItemSimple + WrapString("/Arial 10 Tf") + + + + + RD + DictionaryItemSimple + getAnnotationReductionRectangle(boundingRectangle, textRectangle) + + + + + + + + + ArraySimple + startPoint;kneePoint;endPoint + + + CL + DictionaryItemComplex + + + + + + + + + + ArraySimple + startLineType;endLineType + + + LE + DictionaryItemComplex + + + + + Dictionary + + + + CreateObject + annotationObject + _PDFObjectReference + + + + + + + + + + + + + + + + ArraySimple + annotationObject + + + Annots + DictionaryItemComplex + + + + + Dictionary + + + + CreateObject + pageAnnots + _PDFObject + + + + + + Code + + _void + appendTo(page, pageAnnots); +updateAnnotationAppearanceStreams(annotationObject); return annotationObject; @@ -5775,287 +6275,5 @@ updateDocumentInfo(qMove(updatedInfoDictionary)); This function is used to update trailer dictionary. Must be called each time the final document is being built. _void - - - - - - - - - - page - _PDFObjectReference - Page to which is annotation added - - - - - boundingRectangle - _QRectF - Bounding rectangle of free text annotation. It must contain both callout line and text rectangle. - - - - - textRectangle - _QRectF - Rectangle with text, in absolute coordinates. They are then recomputed to match bounding rectangle. - - - - - title - _QString - Title - - - - - subject - _QString - Subject - - - - - contents - _QString - Contents (text displayed) - - - - - textAlignment - _TextAlignment - Text alignment. Only horizontal alignment flags are valid. - - - - - startPoint - _QPointF - Start point of callout line - - - - - kneePoint - _QPointF - Knee point of callout line - - - - - endPoint - _QPointF - End point of callout line - - - - - startLineType - _AnnotationLineEnding - Line ending at the start point - - - - - endLineType - _AnnotationLineEnding - Line ending at the end point - - - Parameters - - _void - - - - - - - - - - - - Type - DictionaryItemSimple - WrapName("Annot") - - - - - Subtype - DictionaryItemSimple - WrapName("FreeText") - - - - - Rect - DictionaryItemSimple - boundingRectangle - - - - - F - DictionaryItemSimple - 4 - - - - - P - DictionaryItemSimple - page - - - - - M - DictionaryItemSimple - WrapCurrentDateTime() - - - - - CreationDate - DictionaryItemSimple - WrapCurrentDateTime() - - - - - T - DictionaryItemSimple - title - - - - - Contents - DictionaryItemSimple - contents - - - - - Subj - DictionaryItemSimple - subject - - - - - Q - DictionaryItemSimple - WrapFreeTextAlignment(textAlignment) - - - - - DA - DictionaryItemSimple - WrapString("/Arial 10 Tf") - - - - - RD - DictionaryItemSimple - getAnnotationReductionRectangle(boundingRectangle, textRectangle) - - - - - - - - - ArraySimple - startPoint;kneePoint;endPoint - - - CL - DictionaryItemComplex - - - - - - - - - - ArraySimple - startLineType;endLineType - - - LE - DictionaryItemComplex - - - - - Dictionary - - - - CreateObject - annotationObject - _PDFObjectReference - - - - - - - - - - - - - - - - ArraySimple - annotationObject - - - Annots - DictionaryItemComplex - - - - - Dictionary - - - - CreateObject - pageAnnots - _PDFObject - - - - - - Code - - _void - appendTo(page, pageAnnots); -updateAnnotationAppearanceStreams(annotationObject); -return annotationObject; - - - Annotations - createAnnotationFreeText - Free text annotation displays text directly on a page. Text appears directly on the page, in the same way, as standard text in PDF document. Free text annotations are usually used to comment the document. Free text annotation can also have callout line, with, or without a knee. Specify start/end point parameters of this function to get callout line. - _PDFObjectReference -