Text highlight annotations

This commit is contained in:
Jakub Melka 2020-12-12 18:08:37 +01:00
parent dc55950050
commit a6ce36a00c
10 changed files with 1203 additions and 234 deletions

View File

@ -857,12 +857,15 @@ void PDFCreateStampTool::onPointPicked(PDFInteger pageIndex, QPointF pagePoint)
setActive(false);
}
PDFCreateHighlightTextTool::PDFCreateHighlightTextTool(PDFDrawWidgetProxy* proxy, PDFToolManager* toolManager, AnnotationType type, QAction* action, QObject* parent) :
BaseClass(proxy, action, parent),
PDFCreateHighlightTextTool::PDFCreateHighlightTextTool(PDFDrawWidgetProxy* proxy, PDFToolManager* toolManager, QActionGroup* actionGroup, QObject* parent) :
BaseClass(proxy, parent),
m_toolManager(toolManager),
m_type(type),
m_actionGroup(actionGroup),
m_type(AnnotationType::Highlight),
m_isCursorOverText(false)
{
connect(m_actionGroup, &QActionGroup::triggered, this, &PDFCreateHighlightTextTool::onActionTriggered);
updateActions();
}
@ -918,13 +921,55 @@ void PDFCreateHighlightTextTool::mouseReleaseEvent(QWidget* widget, QMouseEvent*
if (m_selectionInfo.pageIndex == pageIndex)
{
// Jakub Melka: handle the selection
PDFTextLayout textLayout = getProxy()->getTextLayoutCompiler()->getTextLayoutLazy(pageIndex);
PDFTextLayoutGetter textLayoutGetter = getProxy()->getTextLayoutCompiler()->getTextLayoutLazy(pageIndex);
PDFTextLayout textLayout = textLayoutGetter;
setSelection(textLayout.createTextSelection(pageIndex, m_selectionInfo.selectionStartPoint, pagePoint));
QPolygonF quadrilaterals;
PDFTextSelectionPainter textSelectionPainter(&m_textSelection);
QPainterPath path = textSelectionPainter.prepareGeometry(pageIndex, textLayoutGetter, QMatrix(), &quadrilaterals);
if (!path.isEmpty())
{
PDFDocumentModifier modifier(getDocument());
PDFObjectReference page = getDocument()->getCatalog()->getPage(pageIndex)->getPageReference();
PDFObjectReference annotationReference;
switch (m_type)
{
case AnnotationType::Highlight:
annotationReference = modifier.getBuilder()->createAnnotationHighlight(page, quadrilaterals, Qt::yellow);
modifier.getBuilder()->setAnnotationOpacity(annotationReference, 0.2);
modifier.getBuilder()->updateAnnotationAppearanceStreams(annotationReference);
break;
case AnnotationType::Underline:
annotationReference = modifier.getBuilder()->createAnnotationUnderline(page, quadrilaterals, Qt::black);
break;
case AnnotationType::Squiggly:
annotationReference = modifier.getBuilder()->createAnnotationSquiggly(page, quadrilaterals, Qt::red);
break;
case AnnotationType::StrikeOut:
annotationReference = modifier.getBuilder()->createAnnotationStrikeout(page, quadrilaterals, Qt::red);
break;
default:
Q_ASSERT(false);
break;
}
modifier.markAnnotationsChanged();
if (modifier.finalize())
{
emit m_toolManager->documentModified(PDFModifiedDocument(modifier.getDocument(), nullptr, modifier.getFlags()));
}
}
}
else
{
setSelection(pdf::PDFTextSelection());
}
setSelection(pdf::PDFTextSelection());
m_selectionInfo = SelectionInfo();
event->accept();
@ -960,6 +1005,22 @@ void PDFCreateHighlightTextTool::mouseMoveEvent(QWidget* widget, QMouseEvent* ev
updateCursor();
}
void PDFCreateHighlightTextTool::updateActions()
{
BaseClass::updateActions();
if (m_actionGroup)
{
const bool isEnabled = getDocument() && getDocument()->getStorage().getSecurityHandler()->isAllowed(PDFSecurityHandler::Permission::ModifyInteractiveItems);
m_actionGroup->setEnabled(isEnabled);
if (!isActive() && m_actionGroup->checkedAction())
{
m_actionGroup->checkedAction()->setChecked(false);
}
}
}
void PDFCreateHighlightTextTool::setActiveImpl(bool active)
{
BaseClass::setActiveImpl(active);
@ -971,6 +1032,16 @@ void PDFCreateHighlightTextTool::setActiveImpl(bool active)
}
}
void PDFCreateHighlightTextTool::onActionTriggered(QAction* action)
{
setActive(action && action->isChecked());
if (action)
{
m_type = static_cast<AnnotationType>(action->data().toInt());
}
}
void PDFCreateHighlightTextTool::updateCursor()
{
if (isActive())

View File

@ -262,21 +262,21 @@ private:
};
/// Tool for highlighting of text in document
class PDFFORQTLIBSHARED_EXPORT PDFCreateHighlightTextTool : public PDFCreateAnnotationTool
class PDFFORQTLIBSHARED_EXPORT PDFCreateHighlightTextTool : public PDFWidgetTool
{
Q_OBJECT
private:
using BaseClass = PDFCreateAnnotationTool;
using BaseClass = PDFWidgetTool;
public:
/// Creates new highlight text tool
/// \param proxy Proxy
/// \param type Annotation type, must be one of: Highlight, Underline, Squiggly, StrikeOut
/// \param action Action
/// \param actionGroup Action group with actions. Each action must define annotation type.
/// \param parent Parent
explicit PDFCreateHighlightTextTool(PDFDrawWidgetProxy* proxy, PDFToolManager* toolManager, AnnotationType type, QAction* action, QObject* parent);
explicit PDFCreateHighlightTextTool(PDFDrawWidgetProxy* proxy, PDFToolManager* toolManager, QActionGroup* actionGroup, QObject* parent);
virtual void drawPage(QPainter* painter,
PDFInteger pageIndex,
@ -290,9 +290,11 @@ public:
virtual void mouseMoveEvent(QWidget* widget, QMouseEvent* event) override;
protected:
virtual void updateActions() override;
virtual void setActiveImpl(bool active) override;
private:
void onActionTriggered(QAction* action);
void updateCursor();
void setSelection(pdf::PDFTextSelection&& textSelection);
@ -303,6 +305,7 @@ private:
};
PDFToolManager* m_toolManager;
QActionGroup* m_actionGroup;
AnnotationType m_type;
pdf::PDFTextSelection m_textSelection;
SelectionInfo m_selectionInfo;

View File

@ -890,7 +890,7 @@ PDFAnnotationQuadrilaterals PDFAnnotation::parseQuadrilaterals(const PDFObjectSt
PDFDocumentDataLoaderDecorator loader(storage);
std::vector<PDFReal> points = loader.readNumberArray(quadrilateralsObject);
const size_t quadrilateralCount = points.size() % 8;
const size_t quadrilateralCount = points.size() / 8;
path.reserve(int(quadrilateralCount) + 5);
quadrilaterals.reserve(quadrilateralCount);
for (size_t i = 0; i < quadrilateralCount; ++i)

View File

@ -2659,6 +2659,47 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationHighlight(PDFObjectRefere
}
PDFObjectReference PDFDocumentBuilder::createAnnotationHighlight(PDFObjectReference page,
QPolygonF quadrilaterals,
QColor color)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Type");
objectBuilder << WrapName("Annot");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Subtype");
objectBuilder << WrapName("Highlight");
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 << quadrilaterals;
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,
QPolygonF inkPoints,
PDFReal borderWidth,
@ -3404,6 +3445,47 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationSquiggly(PDFObjectReferen
}
PDFObjectReference PDFDocumentBuilder::createAnnotationSquiggly(PDFObjectReference page,
QPolygonF quadrilaterals,
QColor color)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Type");
objectBuilder << WrapName("Annot");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Subtype");
objectBuilder << WrapName("Squiggly");
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 << quadrilaterals;
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::createAnnotationStamp(PDFObjectReference page,
QRectF rectangle,
Stamp stampType,
@ -3573,6 +3655,47 @@ PDFObjectReference PDFDocumentBuilder::createAnnotationStrikeout(PDFObjectRefere
}
PDFObjectReference PDFDocumentBuilder::createAnnotationStrikeout(PDFObjectReference page,
QPolygonF quadrilaterals,
QColor color)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Type");
objectBuilder << WrapName("Annot");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Subtype");
objectBuilder << WrapName("StrikeOut");
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 << quadrilaterals;
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::createAnnotationText(PDFObjectReference page,
QRectF rectangle,
TextAnnotationIcon iconType,
@ -3646,6 +3769,96 @@ 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,
QPolygonF quadrilaterals,
QColor color)
{
PDFObjectFactory objectBuilder;
objectBuilder.beginDictionary();
objectBuilder.beginDictionaryItem("Type");
objectBuilder << WrapName("Annot");
objectBuilder.endDictionaryItem();
objectBuilder.beginDictionaryItem("Subtype");
objectBuilder << WrapName("Underline");
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 << quadrilaterals;
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,
@ -3710,55 +3923,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

@ -733,6 +733,17 @@ public:
QColor color);
/// 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.
/// \param page Page to which is annotation added
/// \param quadrilaterals Area in which is highlight displayed
/// \param color Color
PDFObjectReference createAnnotationHighlight(PDFObjectReference page,
QPolygonF quadrilaterals,
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
@ -975,6 +986,16 @@ public:
QString contents);
/// Text markup annotation is used to squiggly 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 quadrilaterals Area in which is markup displayed
/// \param color Color
PDFObjectReference createAnnotationSquiggly(PDFObjectReference page,
QPolygonF quadrilaterals,
QColor color);
/// Stamp annotation
/// \param page Page to which is annotation added
/// \param rectangle Stamp area
@ -1016,6 +1037,16 @@ public:
QColor color);
/// Text markup annotation is used to strikeout 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 quadrilaterals Area in which is markup displayed
/// \param color Color
PDFObjectReference createAnnotationStrikeout(PDFObjectReference page,
QPolygonF quadrilaterals,
QColor color);
/// 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
@ -1037,6 +1068,26 @@ 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
/// \param quadrilaterals Area in which is markup displayed
/// \param color Color
PDFObjectReference createAnnotationUnderline(PDFObjectReference page,
QPolygonF quadrilaterals,
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
@ -1053,16 +1104,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();

View File

@ -1423,6 +1423,122 @@ void PDFTextSelectionPainter::draw(QPainter* painter, PDFInteger pageIndex, PDFT
painter->restore();
}
QPainterPath PDFTextSelectionPainter::prepareGeometry(PDFInteger pageIndex, PDFTextLayoutGetter& textLayoutGetter, const QMatrix& matrix, QPolygonF* quadrilaterals)
{
QPainterPath path;
auto it = m_selection->begin(pageIndex);
auto itEnd = m_selection->end(pageIndex);
if (it == itEnd)
{
// Jakub Melka: no text is selected on current page; do nothing
return path;
}
const PDFTextLayout& layout = textLayoutGetter;
const PDFTextBlocks& blocks = layout.getTextBlocks();
for (; it != itEnd; ++it)
{
const PDFTextSelectionColoredItem& item = *it;
const PDFCharacterPointer& start = item.start;
const PDFCharacterPointer& end = item.end;
Q_ASSERT(start.pageIndex == end.pageIndex);
Q_ASSERT(start.blockIndex == end.blockIndex);
if (start.blockIndex >= blocks.size())
{
// Selection is invalid, do nothing
continue;
}
PDFTextBlock block = blocks[start.blockIndex];
// Fix angle of block, so we will get correct selection rectangles (parallel to lines)
QMatrix angleMatrix;
angleMatrix.rotate(block.getAngle());
block.applyTransform(angleMatrix);
QPainterPath currentPath;
QPolygonF currentPolygon;
const size_t lineStart = start.lineIndex;
const size_t lineEnd = end.lineIndex;
Q_ASSERT(lineEnd >= lineStart);
const PDFTextLines& lines = block.getLines();
for (size_t lineIndex = lineStart; lineIndex <= lineEnd; ++lineIndex)
{
if (lineIndex >= lines.size())
{
// Selection is invalid, do nothing
continue;
}
const PDFTextLine& line = lines[lineIndex];
const TextCharacters& characters = line.getCharacters();
if (characters.empty())
{
// Selection is invalid, do nothing
continue;
}
// First determine, which characters will be selected
size_t characterStart = 0;
size_t characterEnd = characters.size() - 1;
if (lineIndex == lineStart)
{
characterStart = start.characterIndex;
}
if (lineIndex == lineEnd)
{
characterEnd = end.characterIndex;
}
// Validate indices, then calculate bounding box
if (!(characterStart <= characterEnd && characterEnd < characters.size()))
{
continue;
}
QRectF boundingBox;
for (size_t i = characterStart; i <= characterEnd; ++i)
{
boundingBox = boundingBox.united(characters[i].boundingBox.boundingRect());
}
if (boundingBox.isValid())
{
// Enlarge height by some percent
PDFReal heightAdvance = boundingBox.height() * HEIGHT_INCREASE_FACTOR * 0.5;
boundingBox.adjust(0, -heightAdvance, 0, heightAdvance);
currentPath.addRect(boundingBox);
if (quadrilaterals)
{
currentPolygon.append({ boundingBox.topLeft(), boundingBox.topRight(), boundingBox.bottomLeft(), boundingBox.bottomRight() });
}
}
}
QMatrix transformMatrix = angleMatrix.inverted() * matrix;
currentPath = transformMatrix.map(currentPath);
if (quadrilaterals)
{
currentPolygon = transformMatrix.map(currentPolygon);
quadrilaterals->append(currentPolygon);
}
path.addPath(currentPath);
}
return path;
}
PDFTextLayoutCache::PDFTextLayoutCache(std::function<PDFTextLayout (PDFInteger)> textLayoutGetter) :
m_textLayoutGetter(qMove(textLayoutGetter)),
m_pageIndex(-1),

View File

@ -482,6 +482,13 @@ public:
/// \param matrix Matrix which translates from page space to device space
void draw(QPainter* painter, PDFInteger pageIndex, PDFTextLayoutGetter& textLayoutGetter, const QMatrix& matrix);
/// Prepares geometry for text selection drawing, using text layout and matrix. If current text selection
/// doesn't contain items from active page, then text layout is not accessed.
/// \param pageIndex Page index
/// \param textLayoutGetter Text layout getter
/// \param matrix Matrix which translates from page space to device space
QPainterPath prepareGeometry(PDFInteger pageIndex, PDFTextLayoutGetter& textLayoutGetter, const QMatrix& matrix, QPolygonF* quadrilaterals);
private:
static constexpr const PDFReal HEIGHT_INCREASE_FACTOR = 0.40;
static constexpr const PDFReal SELECTION_ALPHA = 0.25;

View File

@ -205,6 +205,18 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
ui->menuStamp->addAction(action);
}
m_insertHighlightGroup = new QActionGroup(this);
m_insertHighlightGroup->setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional);
m_insertHighlightGroup->addAction(ui->actionCreateTextHighlight);
m_insertHighlightGroup->addAction(ui->actionCreateTextUnderline);
m_insertHighlightGroup->addAction(ui->actionCreateTextStrikeout);
m_insertHighlightGroup->addAction(ui->actionCreateTextSquiggly);
ui->actionCreateTextHighlight->setData(int(pdf::AnnotationType::Highlight));
ui->actionCreateTextUnderline->setData(int(pdf::AnnotationType::Underline));
ui->actionCreateTextStrikeout->setData(int(pdf::AnnotationType::StrikeOut));
ui->actionCreateTextSquiggly->setData(int(pdf::AnnotationType::Squiggly));
ui->actionStickyNoteComment->setData(int(pdf::TextAnnotationIcon::Comment));
ui->actionStickyNoteHelp->setData(int(pdf::TextAnnotationIcon::Help));
ui->actionStickyNoteInsert->setData(int(pdf::TextAnnotationIcon::Insert));
@ -369,14 +381,8 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
m_toolManager->addTool(createFreehandCurveTool);
pdf::PDFCreateStampTool* createStampTool = new pdf::PDFCreateStampTool(m_pdfWidget->getDrawWidgetProxy(), m_toolManager, m_insertStampGroup, this);
m_toolManager->addTool(createStampTool);
pdf::PDFCreateHighlightTextTool* createHighlightTextTool = new pdf::PDFCreateHighlightTextTool(m_pdfWidget->getDrawWidgetProxy(), m_toolManager, pdf::AnnotationType::Highlight, ui->actionCreateTextHighlight, this);
pdf::PDFCreateHighlightTextTool* createHighlightTextTool = new pdf::PDFCreateHighlightTextTool(m_pdfWidget->getDrawWidgetProxy(), m_toolManager, m_insertHighlightGroup, this);
m_toolManager->addTool(createHighlightTextTool);
pdf::PDFCreateHighlightTextTool* createUnderlineTextTool = new pdf::PDFCreateHighlightTextTool(m_pdfWidget->getDrawWidgetProxy(), m_toolManager, pdf::AnnotationType::Underline, ui->actionCreateTextUnderline, this);
m_toolManager->addTool(createUnderlineTextTool);
pdf::PDFCreateHighlightTextTool* createStrikeOutTextTool = new pdf::PDFCreateHighlightTextTool(m_pdfWidget->getDrawWidgetProxy(), m_toolManager, pdf::AnnotationType::StrikeOut, ui->actionCreateTextStrikeout, this);
m_toolManager->addTool(createStrikeOutTextTool);
pdf::PDFCreateHighlightTextTool* createSquigglyTextTool = new pdf::PDFCreateHighlightTextTool(m_pdfWidget->getDrawWidgetProxy(), m_toolManager, pdf::AnnotationType::Squiggly, ui->actionCreateTextSquiggly, this);
m_toolManager->addTool(createSquigglyTextTool);
m_annotationManager = new pdf::PDFWidgetAnnotationManager(m_pdfWidget->getDrawWidgetProxy(), this);
connect(m_annotationManager, &pdf::PDFWidgetAnnotationManager::actionTriggered, this, &PDFViewerMainWindow::onActionTriggered);

View File

@ -192,6 +192,7 @@ private:
std::vector<pdf::PDFSignatureVerificationResult> m_signatures;
QActionGroup* m_insertStickyNoteGroup;
QActionGroup* m_insertStampGroup;
QActionGroup* m_insertHighlightGroup;
QFuture<AsyncReadingResult> m_future;
QFutureWatcher<AsyncReadingResult>* m_futureWatcher;

View File

@ -3827,6 +3827,146 @@ return annotationObject;</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">createAnnotationHighlight</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">quadrilaterals</property>
<property name="parameterType">_QPolygonF</property>
<property name="parameterDescription">Area in which is highlight displayed</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">color</property>
<property name="parameterType">_QColor</property>
<property name="parameterDescription">Color</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("Highlight")</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">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">C</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">QuadPoints</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">quadrilaterals</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>
@ -6317,6 +6457,146 @@ return annotationObject;</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">createAnnotationSquiggly</property>
<property name="functionDescription">Text markup annotation is used to squiggly underline text. It is a markup annotation, so it can contain window to be opened (and commented).</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">quadrilaterals</property>
<property name="parameterType">_QPolygonF</property>
<property name="parameterDescription">Area in which is markup displayed</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">color</property>
<property name="parameterType">_QColor</property>
<property name="parameterDescription">Color</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("Squiggly")</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">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">C</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">QuadPoints</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">quadrilaterals</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>
@ -6865,6 +7145,146 @@ return annotationObject;</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">createAnnotationStrikeout</property>
<property name="functionDescription">Text markup annotation is used to strikeout text. It is a markup annotation, so it can contain window to be opened (and commented).</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">quadrilaterals</property>
<property name="parameterType">_QPolygonF</property>
<property name="parameterDescription">Area in which is markup displayed</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">color</property>
<property name="parameterType">_QColor</property>
<property name="parameterDescription">Color</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("StrikeOut")</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">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">C</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">QuadPoints</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">quadrilaterals</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>
@ -7116,6 +7536,301 @@ return annotationObject;</property>
<property name="functionDescription">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. Popup annotation is automatically created for this annotation.</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">rectangle</property>
<property name="parameterType">_QRectF</property>
<property name="parameterDescription">Area in which is markup displayed</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">color</property>
<property name="parameterType">_QColor</property>
<property name="parameterDescription">Color</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("Underline")</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">rectangle</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">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">C</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">color</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">rectangle.bottomLeft();rectangle.bottomRight();rectangle.topLeft();rectangle.topRight()</property>
</QObject>
</property>
<property name="dictionaryItemName">QuadPoints</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">createAnnotationUnderline</property>
<property name="functionDescription">Text markup annotation is used to underline text. It is a markup annotation, so it can contain window to be opened (and commented).</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">quadrilaterals</property>
<property name="parameterType">_QPolygonF</property>
<property name="parameterDescription">Area in which is markup displayed</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">color</property>
<property name="parameterType">_QColor</property>
<property name="parameterDescription">Color</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("Underline")</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">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">C</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">QuadPoints</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">quadrilaterals</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">createAnnotationUnderline</property>
<property name="functionDescription">Text markup annotation is used to underline text. It is a markup annotation, so it can contain window to be opened (and commented).</property>
<property name="returnType">_PDFObjectReference</property>
</QObject>
<QObject class="codegen::GeneratedFunction">
<property name="objectName"></property>
<property name="items">
@ -7312,161 +8027,6 @@ return annotationObject;</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">createAnnotationUnderline</property>
<property name="functionDescription">Text markup annotation is used to underline text. It is a markup annotation, so it can contain window to be opened (and commented).</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">rectangle</property>
<property name="parameterType">_QRectF</property>
<property name="parameterDescription">Area in which is markup displayed</property>
</QObject>
<QObject class="codegen::GeneratedParameter">
<property name="objectName"></property>
<property name="items"/>
<property name="parameterName">color</property>
<property name="parameterType">_QColor</property>
<property name="parameterDescription">Color</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("Underline")</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">rectangle</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">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">C</property>
<property name="objectType">DictionaryItemSimple</property>
<property name="value">color</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">rectangle.bottomLeft();rectangle.bottomRight();rectangle.topLeft();rectangle.topRight()</property>
</QObject>
</property>
<property name="dictionaryItemName">QuadPoints</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>