Text annotation

This commit is contained in:
Jakub Melka
2020-03-22 18:19:52 +01:00
parent fcaa288c5b
commit 35ffc256f3
7 changed files with 814 additions and 4 deletions

View File

@@ -508,6 +508,17 @@ private:
PDFObject m_externalData;
};
enum class TextAnnotationIcon
{
Comment,
Help,
Insert,
Key,
NewParagraph,
Note,
Paragraph
};
/// Text annotation represents note attached to a specific point in the PDF
/// document. It appears as icon, and it is not zoomed, or rotated (behaves
/// as if flag NoZoom and NoRotate were set). When this annotation is opened,

View File

@@ -64,6 +64,61 @@ void PDFObjectFactory::endDictionaryItem()
std::get<PDFDictionary>(dictionaryItem.object).addEntry(qMove(topItem.itemName), qMove(std::get<PDFObject>(topItem.object)));
}
PDFObjectFactory& PDFObjectFactory::operator<<(TextAnnotationIcon icon)
{
switch (icon)
{
case TextAnnotationIcon::Comment:
{
*this << WrapName("Comment");
break;
}
case TextAnnotationIcon::Help:
{
*this << WrapName("Help");
break;
}
case TextAnnotationIcon::Insert:
{
*this << WrapName("Insert");
break;
}
case TextAnnotationIcon::Key:
{
*this << WrapName("Key");
break;
}
case TextAnnotationIcon::NewParagraph:
{
*this << WrapName("NewParagraph");
break;
}
case TextAnnotationIcon::Note:
{
*this << WrapName("Note");
break;
}
case TextAnnotationIcon::Paragraph:
{
*this << WrapName("Paragraph");
break;
}
default:
{
Q_ASSERT(false);
}
}
return *this;
}
PDFObjectFactory& PDFObjectFactory::operator<<(WrapEmptyArray)
{
beginArray();
@@ -276,7 +331,9 @@ void PDFDocumentBuilder::appendTo(PDFObjectReference reference, PDFObject object
QRectF PDFDocumentBuilder::getPopupWindowRect(const QRectF& rectangle) const
{
return rectangle.translated(rectangle.width() * 1.25, 0);
QRectF rect = rectangle.translated(rectangle.width() * 1.25, 0);
rect.setSize(QSizeF(100, 100));
return rect;
}
QString PDFDocumentBuilder::getProducerString() const
@@ -375,7 +432,17 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationSquare(PDFObjectReference
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObject updateAnnotationPopup = objectBuilder.takeObject();
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Annots");
objectBuilder.beginArray();
objectBuilder << annotationObject;
objectBuilder << popupAnnotation;
objectBuilder.endArray();
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObject pageAnnots = objectBuilder.takeObject();
mergeTo(annotationObject, updateAnnotationPopup);
appendTo(page, pageAnnots);
return annotationObject;
}
@@ -532,6 +599,148 @@ PDFObjectReference PDFDocumentBuilder::createCatalogPageTreeRoot()
}
PDFObjectReference PDFDocumentBuilder::createAnnotationCircle(PDFObjectReference page,
QRectF rectangle,
PDFReal borderWidth,
QColor fillColor,
QColor strokeColor,
QString title,
QString subject,
QString contents)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Subtype");
objectBuilder << WrapName("Circle");
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<PDFReal>{ 0.0, 0.0, borderWidth };
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("C");
objectBuilder << WrapAnnotationColor(strokeColor);
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("IC");
objectBuilder << WrapAnnotationColor(fillColor);
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("Popup");
objectBuilder << popupAnnotation;
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObject updateAnnotationPopup = objectBuilder.takeObject();
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Annots");
objectBuilder.beginArray();
objectBuilder << annotationObject;
objectBuilder << popupAnnotation;
objectBuilder.endArray();
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObject pageAnnots = objectBuilder.takeObject();
mergeTo(annotationObject, updateAnnotationPopup);
appendTo(page, pageAnnots);
return annotationObject;
}
PDFObjectReference PDFDocumentBuilder::createAnnotationText(PDFObjectReference page,
QRectF rectangle,
TextAnnotationIcon iconType,
QString title,
QString subject,
QString contents,
bool open)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Subtype");
objectBuilder << WrapName("Text");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Rect");
objectBuilder << rectangle;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Name");
objectBuilder << iconType;
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("T");
objectBuilder << title;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Contents");
objectBuilder << contents;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Subj");
objectBuilder << subject;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Open");
objectBuilder << open;
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObjectReference annotationObject = addObject(objectBuilder.takeObject());
PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(rectangle), false);
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Popup");
objectBuilder << popupAnnotation;
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObject updateAnnotationPopup = objectBuilder.takeObject();
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Annots");
objectBuilder.beginArray();
objectBuilder << annotationObject;
objectBuilder << popupAnnotation;
objectBuilder.endArray();
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObject pageAnnots = objectBuilder.takeObject();
mergeTo(annotationObject, updateAnnotationPopup);
appendTo(page, pageAnnots);
return annotationObject;
}
/* END GENERATED CODE */
} // namespace pdf

View File

@@ -20,6 +20,7 @@
#include "pdfobject.h"
#include "pdfdocument.h"
#include "pdfannotation.h"
namespace pdf
{
@@ -77,6 +78,7 @@ public:
PDFObjectFactory& operator<<(WrapAnnotationColor color);
PDFObjectFactory& operator<<(QString textString);
PDFObjectFactory& operator<<(WrapEmptyArray);
PDFObjectFactory& operator<<(TextAnnotationIcon icon);
/// Treat containers - write them as array
template<typename Container, typename ValueType = decltype(*std::begin(std::declval<Container>()))>
@@ -244,6 +246,49 @@ public:
PDFObjectReference createCatalogPageTreeRoot();
/// Circle annotation displays ellipse (or circle). When opened, they display pop-up window containing
/// the text of associated note (and window title). Circle border/fill color can be defined, along with
/// border width.
/// \param page Page to which is annotation added
/// \param rectangle Area in which is circle/ellipse displayed
/// \param borderWidth Width of the border line of circle/ellipse
/// \param fillColor Fill color of rectangle (interior color). If you do not want to have area color filled,
/// then use invalid QColor.
/// \param strokeColor Stroke color (color of the rectangle border). If you do not want to have a
/// border, then use invalid QColor.
/// \param title Title (it is displayed as title of popup window)
/// \param subject Subject (short description of the subject being adressed by the annotation)
/// \param contents Contents (text displayed, for example, in the marked annotation dialog)
PDFObjectReference createAnnotationCircle(PDFObjectReference page,
QRectF rectangle,
PDFReal borderWidth,
QColor fillColor,
QColor strokeColor,
QString title,
QString subject,
QString contents);
/// Creates text annotation. Text annotation is "sticky note" attached to a point in the PDF document.
/// When closed, it is displayed as icon, if opened, widget appears with attached text. Text annotations
/// do not scale or rotate, they appear independent of zoom/rotate. So, they behave as if flags
/// NoZoom or NoRotate to the annotations are being set.
/// \param page Page to which is annotation added
/// \param rectangle Area in which is icon displayed
/// \param iconType Icon type
/// \param title Title (it is displayed as title of popup window)
/// \param subject Subject (short description of the subject being adressed by the annotation)
/// \param contents Contents (text displayed, for example, in the marked annotation dialog)
/// \param open Is annotation initiali displayed as opened?
PDFObjectReference createAnnotationText(PDFObjectReference page,
QRectF rectangle,
TextAnnotationIcon iconType,
QString title,
QString subject,
QString contents,
bool open);
/* END GENERATED CODE */
private: