Ink annotation graphics

This commit is contained in:
Jakub Melka 2020-04-05 16:01:09 +02:00
parent 992e4b32f3
commit cc11073d70
7 changed files with 839 additions and 159 deletions

View File

@ -148,6 +148,7 @@ public:
_QPolygonF,
_QDateTime,
_QLocale,
_Polygons,
_TextAnnotationIcon,
_LinkHighlightMode,
_TextAlignment,

View File

@ -242,6 +242,37 @@ void PDFExamplesGenerator::generateAnnotationsExample()
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");
pdf::PDFObjectReference page13 = builder.appendPage(QRectF(0, 0, 400, 400));
{
QPolygonF polygon;
polygon << QPointF(50, 50);
polygon << QPointF(50, 100);
polygon << QPointF(100, 50);
builder.createAnnotationInk(page13, polygon, 2.0, Qt::red, "Title", "Subject", "Contents");
}
{
QPolygonF polygon;
polygon << QPointF(50, 50);
polygon << QPointF(50, 100);
polygon << QPointF(100, 50);
polygon.translate(150, 0);
builder.createAnnotationInk(page13, polygon, 2.0, Qt::red, "Title", "Subject", "Contents");
}
{
pdf::Polygons polygons;
QPolygonF polygon;
polygon << QPointF(50, 50);
polygon << QPointF(50, 100);
polygon << QPointF(100, 50);
polygon << QPointF(50, 50);
polygon.translate(0, 150);
polygons.push_back(polygon);
polygon.translate(150, 0);
polygons.push_back(polygon);
builder.createAnnotationInk(page13, polygons, 2.0, Qt::red, "Title", "Subject", "Contents");
}
// Write result to a file
pdf::PDFDocument document = builder.build();
pdf::PDFDocumentWriter writer(nullptr);

View File

@ -430,7 +430,6 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject
annotation->m_inkPath.lineTo(point);
}
}
annotation->m_inkPath.closeSubpath();
}
}
}
@ -1938,4 +1937,78 @@ void PDFCaretAnnotation::draw(AnnotationDrawParameters& parameters) const
painter.fillPath(path, QBrush(getStrokeColor(), Qt::SolidPattern));
}
void PDFInkAnnotation::draw(AnnotationDrawParameters& parameters) const
{
QPainter& painter = *parameters.painter;
QPainterPath path = getInkPath();
painter.setPen(getPen());
painter.setBrush(getBrush());
QPainterPath boundingPath;
QPainterPath currentPath;
const int elementCount = path.elementCount();
for (int i = 0; i < elementCount; ++i)
{
QPainterPath::Element element = path.elementAt(i);
switch (element.type)
{
case QPainterPath::MoveToElement:
{
// Reset the path
if (!currentPath.isEmpty())
{
boundingPath.addPath(currentPath);
painter.drawPath(currentPath);
currentPath.clear();
}
currentPath.moveTo(element.x, element.y);
break;
}
case QPainterPath::LineToElement:
{
const QPointF p0 = currentPath.currentPosition();
const QPointF p1(element.x, element.y);
QLineF line(p0, p1);
QPointF normal = line.normalVector().p2() - p0;
// Jakub Melka: This computation should be clarified. We use second order Bezier curves.
// We must calculate single control point. Let B(t) is bezier curve of second order.
// Then second derivation is B''(t) = 2(p0 - 2*Pc + p1). Second derivation curve is its
// normal. So, we calculate normal vector of the line (which has norm equal to line length),
// then we get following formula:
//
// Pc = (p0 + p1) / 2 - B''(t) / 4
//
// So, for bezier curves of second order, second derivative is constant (which is not surprising,
// because second derivative of polynomial of order 2 is also a constant). Control point is then
// used to paint the path.
QPointF controlPoint = -normal * 0.25 + (p0 + p1) * 0.5;
currentPath.quadTo(controlPoint, p1);
break;
}
case QPainterPath::CurveToElement:
case QPainterPath::CurveToDataElement:
default:
Q_ASSERT(false);
break;
}
}
// Reset the path
if (!currentPath.isEmpty())
{
boundingPath.addPath(currentPath);
painter.drawPath(currentPath);
currentPath.clear();
}
const qreal penWidth = painter.pen().widthF();
parameters.boundingRectangle = boundingPath.boundingRect();
parameters.boundingRectangle.adjust(-penWidth, -penWidth, penWidth, penWidth);
}
} // namespace pdf

View File

@ -35,6 +35,7 @@ class PDFObjectStorage;
class PDFDrawWidgetProxy;
using TextAlignment = Qt::Alignment;
using Polygons = std::vector<QPolygonF>;
enum class AnnotationType
{
@ -971,6 +972,7 @@ public:
inline explicit PDFInkAnnotation() = default;
virtual AnnotationType getType() const override { return AnnotationType::Ink; }
virtual void draw(AnnotationDrawParameters& parameters) const override;
const QPainterPath& getInkPath() const { return m_inkPath; }

View File

@ -897,6 +897,18 @@ void PDFDocumentBuilder::updateDocumentInfo(PDFObject info)
mergeTo(infoReference, info);
}
QRectF PDFDocumentBuilder::getPolygonsBoundingRect(const Polygons& polygons) const
{
QRectF rect;
for (const QPolygonF& polygon : polygons)
{
rect = rect.united(polygon.boundingRect());
}
return rect;
}
std::vector<PDFObject> PDFDocumentBuilder::copyFrom(const std::vector<PDFObject>& objects, const PDFObjectStorage& storage, bool createReferences)
{
// 1) Collect all references, which we must copy. If object is referenced, then
@ -1149,8 +1161,6 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationCaret(PDFObjectReference
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObjectReference annotationObject = addObject(objectBuilder.takeObject());
PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(rectangle), false);
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Annots");
objectBuilder.beginArray();
@ -1573,6 +1583,140 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationHighlight(PDFObjectRefere
}
PDFObjectReference PDFDocumentBuilder::createAnnotationInk(PDFObjectReference page,
QPolygonF inkPoints,
PDFReal borderWidth,
QColor strokeColor,
QString title,
QString subject,
QString contents)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Type");
objectBuilder << WrapName("Annot");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Subtype");
objectBuilder << WrapName("Ink");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Rect");
objectBuilder << inkPoints.boundingRect();
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("F");
objectBuilder << 4;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("P");
objectBuilder << page;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("InkList");
objectBuilder.beginArray();
objectBuilder << inkPoints;
objectBuilder.endArray();
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("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());
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::createAnnotationInk(PDFObjectReference page,
Polygons inkPoints,
PDFReal borderWidth,
QColor strokeColor,
QString title,
QString subject,
QString contents)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Type");
objectBuilder << WrapName("Annot");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Subtype");
objectBuilder << WrapName("Ink");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Rect");
objectBuilder << getPolygonsBoundingRect(inkPoints);
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("F");
objectBuilder << 4;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("P");
objectBuilder << page;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("InkList");
objectBuilder << inkPoints;
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("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());
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::createAnnotationLine(PDFObjectReference page,
QRectF boundingRect,
QPointF startPoint,
@ -1644,8 +1788,6 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationLine(PDFObjectReference p
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObjectReference annotationObject = addObject(objectBuilder.takeObject());
PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(boundingRect), false);
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Annots");
objectBuilder.beginArray();
@ -1751,8 +1893,6 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationLine(PDFObjectReference p
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObjectReference annotationObject = addObject(objectBuilder.takeObject());
PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(boundingRect), false);
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Annots");
objectBuilder.beginArray();
@ -1876,8 +2016,6 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationPolygon(PDFObjectReferenc
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObjectReference annotationObject = addObject(objectBuilder.takeObject());
PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(polygon.boundingRect()), false);
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Annots");
objectBuilder.beginArray();
@ -1956,8 +2094,6 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationPolyline(PDFObjectReferen
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObjectReference annotationObject = addObject(objectBuilder.takeObject());
PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(polyline.boundingRect()), false);
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Annots");
objectBuilder.beginArray();
@ -2380,6 +2516,55 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationText(PDFObjectReference p
}
PDFObjectReference PDFDocumentBuilder::createAnnotationUnderline(PDFObjectReference page,
QRectF rectangle,
QColor color)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Type");
objectBuilder << WrapName("Annot");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Subtype");
objectBuilder << WrapName("Underline");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Rect");
objectBuilder << rectangle;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("P");
objectBuilder << page;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("CreationDate");
objectBuilder << WrapCurrentDateTime();
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("C");
objectBuilder << color;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("QuadPoints");
objectBuilder.beginArray();
objectBuilder << rectangle.bottomLeft();
objectBuilder << rectangle.bottomRight();
objectBuilder << rectangle.topLeft();
objectBuilder << rectangle.topRight();
objectBuilder.endArray();
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObjectReference annotationObject = addObject(objectBuilder.takeObject());
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::createAnnotationUnderline(PDFObjectReference page,
QRectF rectangle,
QColor color,
@ -2444,55 +2629,6 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationUnderline(PDFObjectRefere
}
PDFObjectReference PDFDocumentBuilder::createAnnotationUnderline(PDFObjectReference page,
QRectF rectangle,
QColor color)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Type");
objectBuilder << WrapName("Annot");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Subtype");
objectBuilder << WrapName("Underline");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Rect");
objectBuilder << rectangle;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("P");
objectBuilder << page;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("CreationDate");
objectBuilder << WrapCurrentDateTime();
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("C");
objectBuilder << color;
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("QuadPoints");
objectBuilder.beginArray();
objectBuilder << rectangle.bottomLeft();
objectBuilder << rectangle.bottomRight();
objectBuilder << rectangle.topLeft();
objectBuilder << rectangle.topRight();
objectBuilder.endArray();
objectBuilder.endDictionaryItem();
objectBuilder.endDictionary();
PDFObjectReference annotationObject = addObject(objectBuilder.takeObject());
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::createCatalog()
{
PDFObjectFactory objectBuilder;

View File

@ -437,6 +437,40 @@ public:
QColor color);
/// Ink anotation represents freehand scribble composed from one or more disjoint paths.
/// \param page Page to which is annotation added
/// \param inkPoints Ink points
/// \param borderWidth Border line width
/// \param strokeColor Stroke color
/// \param title Title
/// \param subject Subject
/// \param contents Contents
PDFObjectReference createAnnotationInk(PDFObjectReference page,
QPolygonF inkPoints,
PDFReal borderWidth,
QColor strokeColor,
QString title,
QString subject,
QString contents);
/// Ink anotation represents freehand scribble composed from one or more disjoint paths.
/// \param page Page to which is annotation added
/// \param inkPoints Ink points (vector of polygons)
/// \param borderWidth Border line width
/// \param strokeColor Stroke color
/// \param title Title
/// \param subject Subject
/// \param contents Contents
PDFObjectReference createAnnotationInk(PDFObjectReference page,
Polygons inkPoints,
PDFReal borderWidth,
QColor strokeColor,
QString title,
QString subject,
QString contents);
/// Line annotation represents straight line, or some more advanced graphics, such as dimension with
/// text. Line annotations are markup annotations, so they can have popup window. Line endings can
/// be specified.
@ -692,6 +726,16 @@ public:
bool open);
/// Text markup annotation is used to underline text. It is a markup annotation, so it can contain
/// window to be opened (and commented).
/// \param page Page to which is annotation added
/// \param rectangle Area in which is markup displayed
/// \param color Color
PDFObjectReference createAnnotationUnderline(PDFObjectReference page,
QRectF rectangle,
QColor color);
/// Text markup annotation is used to underline text. It is a markup annotation, so it can contain
/// window to be opened (and commented).
/// \param page Page to which is annotation added
@ -708,16 +752,6 @@ public:
QString contents);
/// Text markup annotation is used to underline text. It is a markup annotation, so it can contain
/// window to be opened (and commented).
/// \param page Page to which is annotation added
/// \param rectangle Area in which is markup displayed
/// \param color Color
PDFObjectReference createAnnotationUnderline(PDFObjectReference page,
QRectF rectangle,
QColor color);
/// Creates empty catalog. This function is used, when a new document is being created. Do not call
/// this function manually.
PDFObjectReference createCatalog();
@ -878,6 +912,7 @@ private:
PDFObjectReference getDocumentInfo() const;
PDFObjectReference getCatalogReference() const;
void updateDocumentInfo(PDFObject info);
QRectF getPolygonsBoundingRect(const Polygons& Polygons) const;
/// Copies objects from another storage. Objects have adjusted references to match
/// this storage references and objects are added after the last objects of active storage.

View File

@ -345,14 +345,6 @@ return pageReference;</property>
<property name="variableType">_PDFObjectReference</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(rectangle), false);</property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
@ -1744,6 +1736,448 @@ return annotationObject;</property>
<property name="functionDescription">Text markup annotation is used to highlight text. It is a markup annotation, so it can contain window to be opened (and commented). This annotation is usually used to highlight text, but can also highlight other things, such as images, or other graphics.</property>
<property name="returnType">_PDFObjectReference</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">page</property>
<property name="parameterType">_PDFObjectReference</property>
<property name="parameterDescription">Page to which is annotation added</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">inkPoints</property>
<property name="parameterType">_QPolygonF</property>
<property name="parameterDescription">Ink points</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">borderWidth</property>
<property name="parameterType">_PDFReal</property>
<property name="parameterDescription">Border line width</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">strokeColor</property>
<property name="parameterType">_QColor</property>
<property name="parameterDescription">Stroke color</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">title</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Title</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">subject</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Subject</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">contents</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Contents</property>
</QObject>
</property>
<property name="actionType">Parameters</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Type</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapName("Annot")</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Subtype</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapName("Ink")</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Rect</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">inkPoints.boundingRect()</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">F</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">4</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">P</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">page</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName"></property>
<property name="objectType">ArraySimple</property>
<property name="value">inkPoints</property>
</QObject>
</property>
<property name="dictionaryItemName">InkList</property>
<property name="objectType">DictionaryItemComplex</property>
<property name="value"></property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">M</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapCurrentDateTime()</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">CreationDate</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapCurrentDateTime()</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Border</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">std::initializer_list&lt;PDFReal>{ 0.0, 0.0, borderWidth }</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">C</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapAnnotationColor(strokeColor)</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">T</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">title</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Contents</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">contents</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Subj</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">subject</property>
</QObject>
</property>
<property name="dictionaryItemName"></property>
<property name="objectType">Dictionary</property>
<property name="value"></property>
</QObject>
</property>
<property name="actionType">CreateObject</property>
<property name="variableName">annotationObject</property>
<property name="variableType">_PDFObjectReference</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName"></property>
<property name="objectType">ArraySimple</property>
<property name="value">annotationObject</property>
</QObject>
</property>
<property name="dictionaryItemName">Annots</property>
<property name="objectType">DictionaryItemComplex</property>
<property name="value"></property>
</QObject>
</property>
<property name="dictionaryItemName"></property>
<property name="objectType">Dictionary</property>
<property name="value"></property>
</QObject>
</property>
<property name="actionType">CreateObject</property>
<property name="variableName">pageAnnots</property>
<property name="variableType">_PDFObject</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">appendTo(page, pageAnnots);
updateAnnotationAppearanceStreams(annotationObject);
return annotationObject;</property>
</QObject>
</property>
<property name="functionType">Annotations</property>
<property name="functionName">createAnnotationInk</property>
<property name="functionDescription">Ink anotation represents freehand scribble composed from one or more disjoint paths.</property>
<property name="returnType">_PDFObjectReference</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">page</property>
<property name="parameterType">_PDFObjectReference</property>
<property name="parameterDescription">Page to which is annotation added</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">inkPoints</property>
<property name="parameterType">_Polygons</property>
<property name="parameterDescription">Ink points (vector of polygons)</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">borderWidth</property>
<property name="parameterType">_PDFReal</property>
<property name="parameterDescription">Border line width</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">strokeColor</property>
<property name="parameterType">_QColor</property>
<property name="parameterDescription">Stroke color</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">title</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Title</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">subject</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Subject</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">contents</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Contents</property>
</QObject>
</property>
<property name="actionType">Parameters</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Type</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapName("Annot")</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Subtype</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapName("Ink")</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Rect</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">getPolygonsBoundingRect(inkPoints)</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">F</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">4</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">P</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">page</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">InkList</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">inkPoints</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">M</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapCurrentDateTime()</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">CreationDate</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapCurrentDateTime()</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Border</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">std::initializer_list&lt;PDFReal>{ 0.0, 0.0, borderWidth }</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">C</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapAnnotationColor(strokeColor)</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">T</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">title</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Contents</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">contents</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Subj</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">subject</property>
</QObject>
</property>
<property name="dictionaryItemName"></property>
<property name="objectType">Dictionary</property>
<property name="value"></property>
</QObject>
</property>
<property name="actionType">CreateObject</property>
<property name="variableName">annotationObject</property>
<property name="variableType">_PDFObjectReference</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName"></property>
<property name="objectType">ArraySimple</property>
<property name="value">annotationObject</property>
</QObject>
</property>
<property name="dictionaryItemName">Annots</property>
<property name="objectType">DictionaryItemComplex</property>
<property name="value"></property>
</QObject>
</property>
<property name="dictionaryItemName"></property>
<property name="objectType">Dictionary</property>
<property name="value"></property>
</QObject>
</property>
<property name="actionType">CreateObject</property>
<property name="variableName">pageAnnots</property>
<property name="variableType">_PDFObject</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">appendTo(page, pageAnnots);
updateAnnotationAppearanceStreams(annotationObject);
return annotationObject;</property>
</QObject>
</property>
<property name="functionType">Annotations</property>
<property name="functionName">createAnnotationInk</property>
<property name="functionDescription">Ink anotation represents freehand scribble composed from one or more disjoint paths.</property>
<property name="returnType">_PDFObjectReference</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">
@ -1978,14 +2412,6 @@ return annotationObject;</property>
<property name="variableType">_PDFObjectReference</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(boundingRect), false);</property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
@ -2338,14 +2764,6 @@ return annotationObject;</property>
<property name="variableType">_PDFObjectReference</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(boundingRect), false);</property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
@ -2778,14 +3196,6 @@ return annotationReference;</property>
<property name="variableType">_PDFObjectReference</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(polygon.boundingRect()), false);</property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
@ -3046,14 +3456,6 @@ return annotationObject;</property>
<property name="variableType">_PDFObjectReference</property>
<property name="code"></property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items"/>
<property name="actionType">Code</property>
<property name="variableName"></property>
<property name="variableType">_void</property>
<property name="code">PDFObjectReference popupAnnotation = createAnnotationPopup(page, annotationObject, getPopupWindowRect(polyline.boundingRect()), false);</property>
</QObject>
<QObject class="codegen::GeneratedAction">
<property name="objectName"></property>
<property name="items">
@ -4461,27 +4863,6 @@ return annotationObject;</property>
<property name="parameterType">_QColor</property>
<property name="parameterDescription">Color</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">title</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Title</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">subject</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Subject</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">contents</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Contents</property>
</QObject>
</property>
<property name="actionType">Parameters</property>
<property name="variableName"></property>
@ -4522,13 +4903,6 @@ return annotationObject;</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">page</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">M</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapCurrentDateTime()</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
@ -4543,27 +4917,6 @@ return annotationObject;</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">color</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">T</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">title</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Contents</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">contents</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Subj</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">subject</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">
@ -4665,6 +5018,27 @@ return annotationObject;</property>
<property name="parameterType">_QColor</property>
<property name="parameterDescription">Color</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">title</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Title</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">subject</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Subject</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">contents</property>
<property name="parameterType">_QString</property>
<property name="parameterDescription">Contents</property>
</QObject>
</property>
<property name="actionType">Parameters</property>
<property name="variableName"></property>
@ -4705,6 +5079,13 @@ return annotationObject;</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">page</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">M</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapCurrentDateTime()</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
@ -4719,6 +5100,27 @@ return annotationObject;</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">color</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">T</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">title</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Contents</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">contents</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">Subj</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">subject</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items">