Free text annotation graphics

This commit is contained in:
Jakub Melka 2020-04-05 12:34:29 +02:00
parent 5dd9888906
commit a3ce271349
6 changed files with 621 additions and 19 deletions

View File

@ -54,12 +54,12 @@ void PDFExamplesGenerator::generateAnnotationsExample()
builder.createAnnotationLink(page2, QRectF(50, 350, 200, 50), "www.seznam.cz", pdf::LinkHighlightMode::Push);
pdf::PDFObjectReference page3 = builder.appendPage(QRectF(0, 0, 400, 400));
builder.createAnnotationFreeText(page3, QRectF(50, 50, 100, 50), "Title", "Subject", "Toto je dolni text", Qt::AlignLeft);
builder.createAnnotationFreeText(page3, QRectF(50, 150, 100, 50), "Title", "Subject", "Toto je stredni text", Qt::AlignCenter);
builder.createAnnotationFreeText(page3, QRectF(50, 250, 100, 50), "Title", "Subject", "Toto je horni text", Qt::AlignRight);
builder.createAnnotationFreeText(page3, QRectF(250, 50, 100, 50), QRectF(300, 50, 50, 50), "Title", "Subject", "Toto je dolni text", Qt::AlignLeft, QPointF(250, 50), QPointF(300, 100), pdf::AnnotationLineEnding::OpenArrow, pdf::AnnotationLineEnding::ClosedArrow);
builder.createAnnotationFreeText(page3, QRectF(250, 150, 100, 50), QRectF(50, 50, 50, 50), "Title", "Subject", "Toto je stredni text", Qt::AlignCenter, QPointF(250, 150), QPointF(300, 200), pdf::AnnotationLineEnding::OpenArrow, pdf::AnnotationLineEnding::ClosedArrow);
pdf::PDFObjectReference ref = builder.createAnnotationFreeText(page3, QRectF(250, 250, 100, 50), QRectF(0, 50, 50, 50), "Title", "Subject", "Toto je horni text", Qt::AlignRight, QPointF(250, 250), QPointF(300, 300), pdf::AnnotationLineEnding::OpenArrow, pdf::AnnotationLineEnding::ClosedArrow);
builder.createAnnotationFreeText(page3, QRectF(50, 50, 100, 50), "Title", "Subject", "Toto je dolni text, желтая лошадь", Qt::AlignLeft);
builder.createAnnotationFreeText(page3, QRectF(50, 150, 100, 50), "Title", "Subject", "Toto je stredni text, желтая лошадь", Qt::AlignCenter);
builder.createAnnotationFreeText(page3, QRectF(50, 250, 100, 50), "Title", "Subject", "Toto je horni text, желтая лошадь", Qt::AlignRight);
builder.createAnnotationFreeText(page3, QRectF(250, 50, 100, 50), QRectF(300, 50, 50, 50), "Title", "Subject", "Toto je dolni text, желтая лошадь", Qt::AlignLeft, QPointF(250, 50), QPointF(300, 100), pdf::AnnotationLineEnding::OpenArrow, pdf::AnnotationLineEnding::ClosedArrow);
builder.createAnnotationFreeText(page3, QRectF(250, 150, 100, 50), QRectF(300, 150, 50, 50), "Title", "Subject", "Toto je stredni text, желтая лошадь", Qt::AlignCenter, QPointF(250, 150), QPointF(300, 200), pdf::AnnotationLineEnding::OpenArrow, pdf::AnnotationLineEnding::ClosedArrow);
pdf::PDFObjectReference ref = builder.createAnnotationFreeText(page3, QRectF(250, 250, 100, 50), QRectF(300, 250, 50, 50), "Title", "Subject", "Toto je horni text, желтая лошадь", Qt::AlignRight, QPointF(260, 250), QPointF(260, 290), QPointF(300, 290), pdf::AnnotationLineEnding::OpenArrow, pdf::AnnotationLineEnding::ClosedArrow);
builder.setAnnotationContents(ref, "UPDATED: Horni text");
builder.setAnnotationTitle(ref, "Updated title");
builder.setAnnotationSubject(ref, "Updated subject");

View File

@ -23,6 +23,7 @@
#include "pdfcms.h"
#include "pdfwidgetutils.h"
#include "pdfpagecontentprocessor.h"
#include "pdfparser.h"
#include <QApplication>
@ -661,7 +662,7 @@ QColor PDFAnnotation::getFillColor() const
return QColor();
}
QColor PDFAnnotation::getDrawColorFromAnnotationColor(const std::vector<PDFReal>& color) const
QColor PDFAnnotation::getDrawColorFromAnnotationColor(const std::vector<PDFReal>& color)
{
switch (color.size())
{
@ -1747,4 +1748,167 @@ void PDFLinkAnnotation::draw(AnnotationDrawParameters& parameters) const
}
}
PDFAnnotationDefaultAppearance PDFAnnotationDefaultAppearance::parse(const QByteArray& string)
{
PDFAnnotationDefaultAppearance result;
PDFLexicalAnalyzer analyzer(string.constData(), string.constData() + string.size());
std::vector<PDFLexicalAnalyzer::Token> tokens;
for (PDFLexicalAnalyzer::Token token = analyzer.fetch(); token.type != PDFLexicalAnalyzer::TokenType::EndOfFile; token = analyzer.fetch())
{
tokens.push_back(qMove(token));
}
auto readNumber = [&tokens](size_t index) -> PDFReal
{
Q_ASSERT(index >= 0 && index < tokens.size());
const PDFLexicalAnalyzer::Token& token = tokens[index];
if (token.type == PDFLexicalAnalyzer::TokenType::Real ||
token.type == PDFLexicalAnalyzer::TokenType::Integer)
{
return token.data.toDouble();
}
return 0.0;
};
for (size_t i = 0; i < tokens.size(); ++i)
{
const PDFLexicalAnalyzer::Token& token = tokens[i];
if (token.type == PDFLexicalAnalyzer::TokenType::Command)
{
QByteArray command = token.data.toByteArray();
if (command == "Tf")
{
if (i >= 1)
{
result.m_fontSize = readNumber(i - 1);
}
if (i >= 2)
{
result.m_fontName = tokens[i - 2].data.toByteArray();
}
}
else if (command == "g" && i >= 1)
{
result.m_fontColor = PDFAnnotation::getDrawColorFromAnnotationColor({ readNumber(i - 1) });
}
else if (command == "rg" && i >= 3)
{
result.m_fontColor = PDFAnnotation::getDrawColorFromAnnotationColor({ readNumber(i - 3), readNumber(i - 2), readNumber(i - 1) });
}
else if (command == "k" && i >= 4)
{
result.m_fontColor = PDFAnnotation::getDrawColorFromAnnotationColor({ readNumber(i - 4), readNumber(i - 3), readNumber(i - 2), readNumber(i - 1) });
}
}
}
return result;
}
void PDFFreeTextAnnotation::draw(AnnotationDrawParameters& parameters) const
{
QPainter& painter = *parameters.painter;
parameters.boundingRectangle = getRectangle();
painter.setPen(getPen());
painter.setBrush(getBrush());
// Draw callout line
const PDFAnnotationCalloutLine& calloutLine = getCalloutLine();
switch (calloutLine.getType())
{
case PDFAnnotationCalloutLine::Type::Invalid:
{
// Annotation doesn't have callout line
break;
}
case PDFAnnotationCalloutLine::Type::StartEnd:
{
QPainterPath boundingPath;
QLineF line(calloutLine.getPoint(0), calloutLine.getPoint(1));
const PDFReal lineEndingSize = qMin(painter.pen().widthF() * 5.0, line.length() * 0.5);
drawLine(LineGeometryInfo::create(line), painter, lineEndingSize,
getStartLineEnding(), getEndLineEnding(), boundingPath,
QPointF(), QString(), true);
break;
}
case PDFAnnotationCalloutLine::Type::StartKneeEnd:
{
QPainterPath boundingPath;
QLineF lineStart(calloutLine.getPoint(0), calloutLine.getPoint(1));
QLineF lineEnd(calloutLine.getPoint(1), calloutLine.getPoint(2));
PDFReal preferredLineEndingSize = painter.pen().widthF() * 5.0;
PDFReal lineStartEndingSize = qMin(preferredLineEndingSize, lineStart.length() * 0.5);
drawLine(LineGeometryInfo::create(lineStart), painter, lineStartEndingSize,
getStartLineEnding(), AnnotationLineEnding::None, boundingPath,
QPointF(), QString(), true);
PDFReal lineEndEndingSize = qMin(preferredLineEndingSize, lineEnd.length() * 0.5);
drawLine(LineGeometryInfo::create(lineEnd), painter, lineEndEndingSize,
AnnotationLineEnding::None, getEndLineEnding() , boundingPath,
QPointF(), QString(), true);
break;
}
default:
{
Q_ASSERT(false);
break;
}
}
QRectF textRect = getTextRectangle();
if (!textRect.isValid())
{
textRect = getRectangle();
}
painter.drawRect(textRect);
// Draw text
PDFAnnotationDefaultAppearance defaultAppearance = PDFAnnotationDefaultAppearance::parse(getDefaultAppearance());
QFont font(defaultAppearance.getFontName());
font.setPixelSize(defaultAppearance.getFontSize());
painter.setPen(defaultAppearance.getFontColor());
Qt::Alignment alignment = Qt::AlignTop;
switch (getJustification())
{
case PDFFreeTextAnnotation::Justification::Left:
alignment |= Qt::AlignLeft;
break;
case PDFFreeTextAnnotation::Justification::Centered:
alignment |= Qt::AlignHCenter;
break;
case PDFFreeTextAnnotation::Justification::Right:
alignment |= Qt::AlignRight;
break;
default:
alignment |= Qt::AlignLeft;
Q_ASSERT(false);
break;
}
QTextOption option(alignment);
option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
option.setUseDesignMetrics(true);
painter.translate(textRect.left(), textRect.bottom());
painter.scale(1.0, -1.0);
painter.drawText(QRectF(QPointF(0, 0), textRect.size()), getContents(), option);
}
} // namespace pdf

View File

@ -388,6 +388,26 @@ private:
std::array<PDFActionPtr, End> m_actions;
};
/// Annotation default appearance
class PDFAnnotationDefaultAppearance
{
public:
explicit inline PDFAnnotationDefaultAppearance() = default;
/// Parses appearance string. If error occurs, then default appearance
/// string is constructed.
static PDFAnnotationDefaultAppearance parse(const QByteArray& string);
const QByteArray& getFontName() const { return m_fontName; }
PDFReal getFontSize() const { return m_fontSize; }
QColor getFontColor() const { return m_fontColor; }
private:
QByteArray m_fontName;
PDFReal m_fontSize = 8.0;
QColor m_fontColor = Qt::black;
};
class PDFAnnotation;
class PDFMarkupAnnotation;
class PDFTextAnnotation;
@ -484,6 +504,9 @@ public:
/// \param name Name of the line ending
static AnnotationLineEnding convertNameToLineEnding(const QByteArray& name);
/// Returns draw color from defined annotation color
static QColor getDrawColorFromAnnotationColor(const std::vector<PDFReal>& color);
protected:
virtual QColor getStrokeColor() const;
virtual QColor getFillColor() const;
@ -508,9 +531,6 @@ protected:
static LineGeometryInfo create(QLineF line);
};
/// Returns draw color from defined annotation color
QColor getDrawColorFromAnnotationColor(const std::vector<PDFReal>& color) const;
/// Returns pen from border settings and annotation color
QPen getPen() const;
@ -686,6 +706,7 @@ public:
inline explicit PDFFreeTextAnnotation() = default;
virtual AnnotationType getType() const override { return AnnotationType::FreeText; }
virtual void draw(AnnotationDrawParameters& parameters) const override;
enum class Justification
{

View File

@ -899,12 +899,33 @@ void PDFDocumentBuilder::updateDocumentInfo(PDFObject info)
std::vector<PDFObject> PDFDocumentBuilder::copyFrom(const std::vector<PDFObject>& objects, const PDFObjectStorage& storage, bool createReferences)
{
// 1) Collect all references, which we must copy
// 1) Collect all references, which we must copy. If object is referenced, then
// we must also collect references of referenced object.
std::set<PDFObjectReference> references;
PDFCollectReferencesVisitor collectReferencesVisitor(references);
for (const PDFObject& object : objects)
{
object.accept(&collectReferencesVisitor);
PDFCollectReferencesVisitor collectReferencesVisitor(references);
for (const PDFObject& object : objects)
{
object.accept(&collectReferencesVisitor);
}
}
// Iterative algorihm, which adds additional references from referenced objects.
// If new reference is added, then we must also check, that all referenced objects
// from this object are added.
std::set<PDFObjectReference> workSet = references;
while (!workSet.empty())
{
std::set<PDFObjectReference> addedReferences;
PDFCollectReferencesVisitor collectReferencesVisitor(addedReferences);
for (const PDFObjectReference& objectReference : workSet)
{
storage.getObject(objectReference).accept(&collectReferencesVisitor);
}
workSet.clear();
std::set_difference(addedReferences.cbegin(), addedReferences.cend(), references.cbegin(), references.cend(), std::inserter(workSet, workSet.cend()));
references.merge(addedReferences);
}
// 2) Make room for new objects, together with mapping
@ -1264,10 +1285,92 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationFreeText(PDFObjectReferen
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("CL");
objectBuilder.beginArray();
objectBuilder << startPoint.x();
objectBuilder << startPoint.y();
objectBuilder << endPoint.x();
objectBuilder << endPoint.y();
objectBuilder << startPoint;
objectBuilder << endPoint;
objectBuilder.endArray();
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("LE");
objectBuilder.beginArray();
objectBuilder << startLineType;
objectBuilder << endLineType;
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::createAnnotationFreeText(PDFObjectReference page,
QRectF boundingRectangle,
QRectF textRectangle,
QString title,
QString subject,
QString contents,
TextAlignment textAlignment,
QPointF startPoint,
QPointF kneePoint,
QPointF endPoint,
AnnotationLineEnding startLineType,
AnnotationLineEnding endLineType)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Type");
objectBuilder << WrapName("Annot");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Subtype");
objectBuilder << WrapName("FreeText");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Rect");
objectBuilder << boundingRectangle;
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("Q");
objectBuilder << WrapFreeTextAlignment(textAlignment);
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("DA");
objectBuilder << WrapString("/Arial 10 Tf");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("RD");
objectBuilder << getAnnotationReductionRectangle(boundingRectangle, textRectangle);
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("CL");
objectBuilder.beginArray();
objectBuilder << startPoint;
objectBuilder << kneePoint;
objectBuilder << endPoint;
objectBuilder.endArray();
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("LE");

View File

@ -358,6 +358,38 @@ public:
AnnotationLineEnding endLineType);
/// 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.
/// \param page Page to which is annotation added
/// \param boundingRectangle Bounding rectangle of free text annotation. It must contain both
/// callout line and text rectangle.
/// \param textRectangle Rectangle with text, in absolute coordinates. They are then recomputed to
/// match bounding rectangle.
/// \param title Title
/// \param subject Subject
/// \param contents Contents (text displayed)
/// \param textAlignment Text alignment. Only horizontal alignment flags are valid.
/// \param startPoint Start point of callout line
/// \param kneePoint Knee point of callout line
/// \param endPoint End point of callout line
/// \param startLineType Line ending at the start point
/// \param endLineType Line ending at the end point
PDFObjectReference createAnnotationFreeText(PDFObjectReference page,
QRectF boundingRectangle,
QRectF textRectangle,
QString title,
QString subject,
QString contents,
TextAlignment textAlignment,
QPointF startPoint,
QPointF kneePoint,
QPointF endPoint,
AnnotationLineEnding startLineType,
AnnotationLineEnding endLineType);
/// 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.

View File

@ -804,7 +804,7 @@ return annotationObject;</property>
<property name="items"/>
<property name="dictionaryItemName"></property>
<property name="objectType">ArraySimple</property>
<property name="value">startPoint.x();startPoint.y();endPoint.x();endPoint.y()</property>
<property name="value">startPoint;endPoint</property>
</QObject>
</property>
<property name="dictionaryItemName">CL</property>
@ -5775,5 +5775,287 @@ updateDocumentInfo(qMove(updatedInfoDictionary));</property>
<property name="functionDescription">This function is used to update trailer dictionary. Must be called each time the final document is being built.</property>
<property name="returnType">_void</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">boundingRectangle</property>
<property name="parameterType">_QRectF</property>
<property name="parameterDescription">Bounding rectangle of free text annotation. It must contain both callout line and text rectangle.</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">textRectangle</property>
<property name="parameterType">_QRectF</property>
<property name="parameterDescription">Rectangle with text, in absolute coordinates. They are then recomputed to match bounding rectangle.</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 (text displayed)</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">textAlignment</property>
<property name="parameterType">_TextAlignment</property>
<property name="parameterDescription">Text alignment. Only horizontal alignment flags are valid.</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">startPoint</property>
<property name="parameterType">_QPointF</property>
<property name="parameterDescription">Start point of callout line</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">kneePoint</property>
<property name="parameterType">_QPointF</property>
<property name="parameterDescription">Knee point of callout line</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">endPoint</property>
<property name="parameterType">_QPointF</property>
<property name="parameterDescription">End point of callout line</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">startLineType</property>
<property name="parameterType">_AnnotationLineEnding</property>
<property name="parameterDescription">Line ending at the start point</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">endLineType</property>
<property name="parameterType">_AnnotationLineEnding</property>
<property name="parameterDescription">Line ending at the end point</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("FreeText")</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">boundingRectangle</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">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">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"/>
<property name="dictionaryItemName">Q</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapFreeTextAlignment(textAlignment)</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">DA</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">WrapString("/Arial 10 Tf")</property>
</QObject>
<QObject class="codegen::GeneratedPDFObject">
<property name="objectName"></property>
<property name="items"/>
<property name="dictionaryItemName">RD</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">getAnnotationReductionRectangle(boundingRectangle, textRectangle)</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">startPoint;kneePoint;endPoint</property>
</QObject>
</property>
<property name="dictionaryItemName">CL</property>
<property name="objectType">DictionaryItemComplex</property>
<property name="value"></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">startLineType;endLineType</property>
</QObject>
</property>
<property name="dictionaryItemName">LE</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">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">createAnnotationFreeText</property>
<property name="functionDescription">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.</property>
<property name="returnType">_PDFObjectReference</property>
</QObject>
</property>
</root>