Form field manager (beginnings)

This commit is contained in:
Jakub Melka
2020-04-22 20:00:44 +02:00
parent b654ce463a
commit d16e2a2c02
15 changed files with 499 additions and 3 deletions

View File

@ -25,6 +25,7 @@
#include "pdfpagecontentprocessor.h"
#include "pdfparser.h"
#include "pdfdrawwidget.h"
#include "pdfform.h"
#include <QDialog>
#include <QApplication>
@ -897,6 +898,7 @@ PDFAnnotationManager::PDFAnnotationManager(PDFFontCache* fontCache,
m_fontCache(fontCache),
m_cmsManager(cmsManager),
m_optionalActivity(optionalActivity),
m_formManager(nullptr),
m_meshQualitySettings(meshQualitySettings),
m_features(features),
m_target(target)
@ -1081,6 +1083,22 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
if (!oc.isValid() || !pdfPainter.isContentSuppressedByOC(oc))
{
pdfPainter.processForm(AA, formBoundingBox, resources, transparencyGroup, content);
// Is it a form field?
if (m_formManager && annotation.annotation->getType() == AnnotationType::Widget)
{
const PDFFormManager::FormAppearanceFlags flags = m_formManager->getAppearanceFlags();
if (flags.testFlag(PDFFormManager::HighlightFields) || flags.testFlag(PDFFormManager::HighlightRequiredFields))
{
const PDFFormField* formField = m_formManager->getFormFieldForWidget(annotation.annotation->getSelfReference());
if (!formField)
{
continue;
}
s
}
}
}
}
catch (PDFException exception)
@ -1168,6 +1186,16 @@ bool PDFAnnotationManager::hasAnyPageAnnotation(const std::vector<PDFInteger>& p
return std::any_of(pageIndices.cbegin(), pageIndices.cend(), std::bind(&PDFAnnotationManager::hasAnnotation, this, std::placeholders::_1));
}
PDFFormManager* PDFAnnotationManager::getFormManager() const
{
return m_formManager;
}
void PDFAnnotationManager::setFormManager(PDFFormManager* formManager)
{
m_formManager = formManager;
}
PDFRenderer::Features PDFAnnotationManager::getFeatures() const
{
return m_features;
@ -1336,7 +1364,8 @@ void PDFWidgetAnnotationManager::updateFromMouseEvent(QMouseEvent* event)
}
const PDFAction* linkAction = nullptr;
if (pageAnnotation.annotation->getType() == AnnotationType::Link)
const AnnotationType annotationType = pageAnnotation.annotation->getType();
if (annotationType == AnnotationType::Link)
{
const PDFLinkAnnotation* linkAnnotation = dynamic_cast<const PDFLinkAnnotation*>(pageAnnotation.annotation.data());
Q_ASSERT(linkAnnotation);
@ -1350,6 +1379,10 @@ void PDFWidgetAnnotationManager::updateFromMouseEvent(QMouseEvent* event)
linkAction = linkAnnotation->getAction();
}
}
if (annotationType == AnnotationType::Widget)
{
m_cursor = QCursor(Qt::ArrowCursor);
}
// Generate popup window
if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton)

View File

@ -43,6 +43,7 @@ class PDFWidget;
class PDFObjectStorage;
class PDFDrawWidgetProxy;
class PDFFontCache;
class PDFFormManager;
class PDFOptionalContentActivity;
using TextAlignment = Qt::Alignment;
@ -1301,6 +1302,9 @@ public:
PDFRenderer::Features getFeatures() const;
void setFeatures(PDFRenderer::Features features);
PDFFormManager* getFormManager() const;
void setFormManager(PDFFormManager* formManager);
protected:
struct PageAnnotation
{
@ -1368,6 +1372,7 @@ protected:
PDFFontCache* m_fontCache;
const PDFCMSManager* m_cmsManager;
const PDFOptionalContentActivity* m_optionalActivity;
PDFFormManager* m_formManager;
PDFMeshQualitySettings m_meshQualitySettings;
PDFRenderer::Features m_features;

View File

@ -168,6 +168,8 @@ PDFCatalog PDFCatalog::parse(const PDFObject& catalog, const PDFDocument* docume
catalogObject.m_baseURI = loader.readStringFromDictionary(URIDictionary, "Base");
}
catalogObject.m_formObject = catalogDictionary->get("AcroForm");
return catalogObject;
}

View File

@ -235,6 +235,7 @@ public:
PageMode getPageMode() const { return m_pageMode; }
const QByteArray& getBaseURI() const { return m_baseURI; }
const std::map<QByteArray, PDFFileSpecification>& getEmbeddedFiles() const { return m_embeddedFiles; }
const PDFObject& getFormObject() const { return m_formObject; }
/// Returns destination using the key. If destination with the key is not found,
/// then nullptr is returned.
@ -257,6 +258,7 @@ private:
PageLayout m_pageLayout = PageLayout::SinglePage;
PageMode m_pageMode = PageMode::UseNone;
QByteArray m_baseURI;
PDFObject m_formObject;
// Maps from Names dictionary
std::map<QByteArray, PDFDestination> m_destinations;

View File

@ -17,6 +17,7 @@
#include "pdfform.h"
#include "pdfdocument.h"
#include "pdfdrawspacecontroller.h"
namespace pdf
{
@ -55,6 +56,19 @@ PDFForm PDFForm::parse(const PDFObjectStorage* storage, PDFObject object)
return form;
}
void PDFFormField::fillWidgetToFormFieldMapping(PDFWidgetToFormFieldMapping& mapping)
{
for (const auto& childField : m_childFields)
{
childField->fillWidgetToFormFieldMapping(mapping);
}
for (const PDFFormWidget& formWidget : m_widgets)
{
mapping[formWidget.getWidget()] = formWidget.getParent();
}
}
PDFFormFieldPointer PDFFormField::parse(const PDFObjectStorage* storage, PDFObjectReference reference, PDFFormField* parentField)
{
PDFFormFieldPointer result;
@ -253,4 +267,77 @@ PDFFormFieldButton::ButtonType PDFFormFieldButton::getButtonType() const
return ButtonType::CheckBox;
}
PDFFormManager::PDFFormManager(PDFDrawWidgetProxy* proxy, QObject* parent) :
BaseClass(parent),
m_proxy(proxy),
m_annotationManager(nullptr),
m_document(nullptr),
m_flags(getDefaultApperanceFlags())
{
Q_ASSERT(proxy);
}
PDFFormManager::~PDFFormManager()
{
}
PDFAnnotationManager* PDFFormManager::getAnnotationManager() const
{
return m_annotationManager;
}
void PDFFormManager::setAnnotationManager(PDFAnnotationManager* annotationManager)
{
m_annotationManager = annotationManager;
}
const PDFDocument* PDFFormManager::getDocument() const
{
return m_document;
}
void PDFFormManager::setDocument(const PDFDocument* document)
{
if (m_document != document)
{
m_document = document;
if (m_document)
{
m_form = PDFForm::parse(&m_document->getStorage(), m_document->getCatalog()->getFormObject());
}
else
{
// Clean the form
m_form = PDFForm();
}
updateWidgetToFormFieldMapping();
}
}
PDFFormManager::FormAppearanceFlags PDFFormManager::getAppearanceFlags() const
{
return m_flags;
}
void PDFFormManager::setAppearanceFlags(FormAppearanceFlags flags)
{
m_flags = flags;
}
void PDFFormManager::updateWidgetToFormFieldMapping()
{
m_widgetToFormField.clear();
if (hasAcroForm())
{
for (const PDFFormFieldPointer& formFieldPtr : m_form.getFormFields())
{
formFieldPtr->fillWidgetToFormFieldMapping(m_widgetToFormField);
}
}
}
} // namespace pdf

View File

@ -31,6 +31,7 @@ class PDFFormField;
using PDFFormFieldPointer = QSharedPointer<PDFFormField>;
using PDFFormFields = std::vector<PDFFormFieldPointer>;
using PDFWidgetToFormFieldMapping = std::map<PDFObjectReference, PDFFormField*>;
/// A simple proxy to the widget annotation
class PDFFormWidget
@ -182,6 +183,10 @@ public:
const PDFObject& getValue() const { return m_value; }
const PDFObject& getDefaultValue() const { return m_defaultValue; }
/// Fills widget to form field mapping
/// \param mapping Form field mapping
void fillWidgetToFormFieldMapping(PDFWidgetToFormFieldMapping& mapping);
/// Parses form field from the object reference. If some error occurs
/// then null pointer is returned, no exception is thrown.
/// \param storage Storage
@ -311,6 +316,7 @@ public:
};
Q_DECLARE_FLAGS(SignatureFlags, SignatureFlag)
FormType getFormType() const { return m_formType; }
const PDFFormFields& getFormFields() const { return m_formFields; }
bool isAppearanceUpdateNeeded() const { return m_needAppearances; }
SignatureFlags getSignatureFlags() const { return m_signatureFlags; }
@ -338,6 +344,58 @@ private:
PDFObject m_xfa;
};
/// Form manager. Manages all form widgets functionality - triggers actions,
/// edits fields, updates annotation appearances, etc. Valid pointer to annotation
/// manager is requirement.
class PDFFORQTLIBSHARED_EXPORT PDFFormManager : public QObject
{
Q_OBJECT
private:
using BaseClass = QObject;
public:
explicit PDFFormManager(PDFDrawWidgetProxy* proxy, QObject* parent);
virtual ~PDFFormManager() override;
enum FormAppearanceFlag
{
None = 0x0000,
HighlightFields = 0x0001,
HighlightRequiredFields = 0x0002,
};
Q_DECLARE_FLAGS(FormAppearanceFlags, FormAppearanceFlag)
bool hasAcroForm() const { return m_form.getFormType() == PDFForm::FormType::AcroForm; }
/// Returns form field for widget. If widget doesn't have attached form field,
/// then nullptr is returned.
/// \param widget Widget annotation
const PDFFormField* getFormFieldForWidget(PDFObjectReference widget) const;
PDFAnnotationManager* getAnnotationManager() const;
void setAnnotationManager(PDFAnnotationManager* annotationManager);
const PDFDocument* getDocument() const;
void setDocument(const PDFDocument* document);
/// Returns default form apperance flags
static constexpr FormAppearanceFlags getDefaultApperanceFlags() { return HighlightFields | HighlightRequiredFields; }
FormAppearanceFlags getAppearanceFlags() const;
void setAppearanceFlags(FormAppearanceFlags flags);
private:
void updateWidgetToFormFieldMapping();
PDFDrawWidgetProxy* m_proxy;
PDFAnnotationManager* m_annotationManager;
const PDFDocument* m_document;
FormAppearanceFlags m_flags;
PDFForm m_form;
PDFWidgetToFormFieldMapping m_widgetToFormField;
};
} // namespace pdf
#endif // PDFFORM_H

View File

@ -43,5 +43,6 @@
<file>resources/magnifier.svg</file>
<file>resources/screenshot-tool.svg</file>
<file>resources/extract-image.svg</file>
<file>resources/form-settings.svg</file>
</qresource>
</RCC>

View File

@ -90,6 +90,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
m_isChangingProgressStep(false),
m_toolManager(nullptr),
m_annotationManager(nullptr),
m_formManager(nullptr),
m_textToSpeech(new PDFTextToSpeech(this))
{
ui->setupUi(this);
@ -268,6 +269,11 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
connect(m_annotationManager, &pdf::PDFWidgetAnnotationManager::actionTriggered, this, &PDFViewerMainWindow::onActionTriggered);
m_pdfWidget->setAnnotationManager(m_annotationManager);
m_formManager = new pdf::PDFFormManager(m_pdfWidget->getDrawWidgetProxy(), this);
m_formManager->setAnnotationManager(m_annotationManager);
m_formManager->setAppearanceFlags(m_settings->getSettings().m_formAppearanceFlags);
m_annotationManager->setFormManager(m_formManager);
connect(m_pdfWidget->getDrawWidgetProxy(), &pdf::PDFDrawWidgetProxy::drawSpaceChanged, this, &PDFViewerMainWindow::onDrawSpaceChanged);
connect(m_pdfWidget->getDrawWidgetProxy(), &pdf::PDFDrawWidgetProxy::pageLayoutChanged, this, &PDFViewerMainWindow::onPageLayoutChanged);
connect(m_pdfWidget, &pdf::PDFWidget::pageRenderingErrorsChanged, this, &PDFViewerMainWindow::onPageRenderingErrorsChanged, Qt::QueuedConnection);
@ -288,6 +294,9 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
PDFViewerMainWindow::~PDFViewerMainWindow()
{
delete m_formManager;
m_formManager = nullptr;
delete m_annotationManager;
m_annotationManager = nullptr;
@ -669,6 +678,11 @@ void PDFViewerMainWindow::readSettings()
m_settings->readSettings(settings, m_CMSManager->getDefaultSettings());
m_CMSManager->setSettings(m_settings->getColorManagementSystemSettings());
m_textToSpeech->setSettings(m_settings);
if (m_formManager)
{
m_formManager->setAppearanceFlags(m_settings->getSettings().m_formAppearanceFlags);
}
}
void PDFViewerMainWindow::readActionSettings()
@ -979,6 +993,7 @@ void PDFViewerMainWindow::setDocument(const pdf::PDFDocument* document)
}
m_annotationManager->setDocument(document, m_optionalContentActivity);
m_formManager->setDocument(document);
m_toolManager->setDocument(document);
m_textToSpeech->setDocument(document);
m_pdfWidget->setDocument(document, m_optionalContentActivity);
@ -1164,6 +1179,7 @@ void PDFViewerMainWindow::on_actionOptions_triggered()
m_CMSManager->setSettings(m_settings->getColorManagementSystemSettings());
m_recentFileManager->setRecentFilesLimit(dialog.getOtherSettings().maximumRecentFileCount);
m_textToSpeech->setSettings(m_settings);
m_formManager->setAppearanceFlags(m_settings->getSettings().m_formAppearanceFlags);
updateMagnifierToolSettings();
}
}

View File

@ -29,6 +29,7 @@
#include "pdfrecentfilemanager.h"
#include "pdftexttospeech.h"
#include "pdfannotation.h"
#include "pdfform.h"
#include <QFuture>
#include <QTreeView>
@ -181,6 +182,7 @@ private:
pdf::PDFToolManager* m_toolManager;
pdf::PDFWidgetAnnotationManager* m_annotationManager;
pdf::PDFFormManager* m_formManager;
PDFTextToSpeech* m_textToSpeech;
};

View File

@ -80,6 +80,10 @@ void PDFViewerSettings::readSettings(QSettings& settings, const pdf::PDFCMSSetti
m_settings.m_speechVolume = settings.value("speechVolume", defaultSettings.m_speechVolume).toDouble();
settings.endGroup();
settings.beginGroup("Forms");
m_settings.m_formAppearanceFlags = static_cast<pdf::PDFFormManager::FormAppearanceFlags>(settings.value("formAppearance", int(pdf::PDFFormManager::getDefaultApperanceFlags())).toInt());
settings.endGroup();
emit settingsChanged();
}
@ -127,6 +131,10 @@ void PDFViewerSettings::writeSettings(QSettings& settings)
settings.setValue("speechPitch", m_settings.m_speechPitch);
settings.setValue("speechVolume", m_settings.m_speechVolume);
settings.endGroup();
settings.beginGroup("Forms");
settings.setValue("formAppearance", int(m_settings.m_formAppearanceFlags));
settings.endGroup();
}
QString PDFViewerSettings::getDirectory() const
@ -232,7 +240,8 @@ PDFViewerSettings::Settings::Settings() :
m_speechPitch(0.0),
m_speechVolume(1.0),
m_magnifierSize(100),
m_magnifierZoom(2.0)
m_magnifierZoom(2.0),
m_formAppearanceFlags(pdf::PDFFormManager::getDefaultApperanceFlags())
{
}

View File

@ -21,6 +21,7 @@
#include "pdfrenderer.h"
#include "pdfcms.h"
#include "pdfexecutionpolicy.h"
#include "pdfform.h"
#include <QObject>
@ -75,6 +76,9 @@ public:
// Magnifier tool settings
int m_magnifierSize;
double m_magnifierZoom;
// Form settings
pdf::PDFFormManager::FormAppearanceFlags m_formAppearanceFlags;
};
const Settings& getSettings() const { return m_settings; }

View File

@ -58,6 +58,7 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin
new QListWidgetItem(QIcon(":/resources/security.svg"), tr("Security"), ui->optionsPagesWidget, SecuritySettings);
new QListWidgetItem(QIcon(":/resources/ui.svg"), tr("UI"), ui->optionsPagesWidget, UISettings);
new QListWidgetItem(QIcon(":/resources/speech.svg"), tr("Speech"), ui->optionsPagesWidget, SpeechSettings);
new QListWidgetItem(QIcon(":/resources/form-settings.svg"), tr("Forms"), ui->optionsPagesWidget, FormSettings);
ui->renderingEngineComboBox->addItem(tr("Software"), static_cast<int>(pdf::RendererEngine::Software));
ui->renderingEngineComboBox->addItem(tr("Hardware accelerated (OpenGL)"), static_cast<int>(pdf::RendererEngine::OpenGL));
@ -193,6 +194,10 @@ void PDFViewerSettingsDialog::on_optionsPagesWidget_currentItemChanged(QListWidg
ui->stackedWidget->setCurrentWidget(ui->speechPage);
break;
case FormSettings:
ui->stackedWidget->setCurrentWidget(ui->formPage);
break;
default:
Q_ASSERT(false);
break;
@ -316,6 +321,10 @@ void PDFViewerSettingsDialog::loadData()
ui->speechRateEdit->setValue(m_settings.m_speechRate);
ui->speechPitchEdit->setValue(m_settings.m_speechPitch);
ui->speechVolumeEdit->setValue(m_settings.m_speechVolume);
// Form Settings
ui->formHighlightFieldsCheckBox->setChecked(m_settings.m_formAppearanceFlags.testFlag(pdf::PDFFormManager::HighlightFields));
ui->formHighlightRequiredFieldsCheckBox->setChecked(m_settings.m_formAppearanceFlags.testFlag(pdf::PDFFormManager::HighlightRequiredFields));
}
void PDFViewerSettingsDialog::saveData()
@ -487,6 +496,14 @@ void PDFViewerSettingsDialog::saveData()
{
m_settings.m_magnifierZoom = ui->magnifierZoomEdit->value();
}
else if (sender == ui->formHighlightFieldsCheckBox)
{
m_settings.m_formAppearanceFlags.setFlag(pdf::PDFFormManager::HighlightFields, ui->formHighlightFieldsCheckBox->isChecked());
}
else if (sender == ui->formHighlightRequiredFieldsCheckBox)
{
m_settings.m_formAppearanceFlags.setFlag(pdf::PDFFormManager::HighlightRequiredFields, ui->formHighlightRequiredFieldsCheckBox->isChecked());
}
const bool loadData = !qobject_cast<const QDoubleSpinBox*>(sender) && !qobject_cast<const QSpinBox*>(sender);
if (loadData)

View File

@ -70,7 +70,8 @@ public:
ColorManagementSystemSettings,
SecuritySettings,
UISettings,
SpeechSettings
SpeechSettings,
FormSettings
};
const PDFViewerSettings::Settings& getSettings() const { return m_settings; }

View File

@ -1068,6 +1068,86 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="formPage">
<layout class="QVBoxLayout" name="formPageLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="formGroupBox">
<property name="title">
<string>Form Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QGridLayout" name="formWidgetsLayout">
<item row="0" column="0">
<widget class="QLabel" name="formHighlightFieldsLabel">
<property name="text">
<string>Highlight form fields</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="formHighlightRequiredFieldsLabel">
<property name="text">
<string>Highlight required form fields</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="formHighlightFieldsCheckBox">
<property name="text">
<string>Enable</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="formHighlightRequiredFieldsCheckBox">
<property name="text">
<string>Enable</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="formInfoLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Form field appearance settings can be used to set highlighting of editable form fields. Required form fields can be highlighted separately by red color, other fields can be highlighted by blue color.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="formGroupBoxSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>393</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>

View File

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="30mm"
height="30mm"
viewBox="0 0 30 30"
version="1.1"
id="svg5291"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="form-settings.svg">
<defs
id="defs5285">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 15 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="30 : 15 : 1"
inkscape:persp3d-origin="15 : 10 : 1"
id="perspective5921" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35355338"
inkscape:cx="-1690.1311"
inkscape:cy="379.57968"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="3840"
inkscape:window-height="2035"
inkscape:window-x="-13"
inkscape:window-y="-13"
inkscape:window-maximized="1" />
<metadata
id="metadata5288">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Jakub Melka</dc:title>
</cc:Agent>
</dc:creator>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Vrstva 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-267)">
<flowRoot
xml:space="preserve"
id="flowRoot5913"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"><flowRegion
id="flowRegion5915"><rect
id="rect5917"
width="129.22377"
height="91.747108"
x="-13.788582"
y="-33.515606" /></flowRegion><flowPara
id="flowPara5919" /></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot843"
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"><flowRegion
id="flowRegion845"><rect
id="rect847"
width="159.09903"
height="129.04698"
x="-37.123108"
y="-35.460152" /></flowRegion><flowPara
id="flowPara849" /></flowRoot> <rect
style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect4554"
width="27.455263"
height="25.116655"
x="1.4499372"
y="269.49796" />
<rect
style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect4556"
width="12.160765"
height="4.0457926"
x="14.686461"
y="271.22855" />
<rect
style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect4558"
width="12.230922"
height="3.3675961"
x="14.639688"
y="277.92294" />
<rect
style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="rect4560"
width="12.511556"
height="8.5827026"
x="14.546144"
y="284.09088" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="2.8998747"
y="273.9881"
id="text4568"><tspan
sodipodi:role="line"
id="tspan4566"
x="2.8998747"
y="273.9881"
style="stroke-width:0.26458332">lorem i</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="2.9466467"
y="278.38467"
id="text4572"><tspan
sodipodi:role="line"
id="tspan4570"
x="2.9466467"
y="278.38467"
style="stroke-width:0.26458332">dolor</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="3.0427084"
y="282.5802"
id="text4576"><tspan
sodipodi:role="line"
id="tspan4574"
x="3.0427084"
y="282.5802"
style="stroke-width:0.26458332">sil </tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
x="6.5153646"
y="282.44794"
id="text4580"><tspan
sodipodi:role="line"
id="tspan4578"
x="6.5153646"
y="282.44794"
style="stroke-width:0.26458332">amet</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB