summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2022-12-08 10:54:18 +0100
committerMichael Stahl <michael.stahl@allotropia.de>2022-12-09 16:03:20 +0000
commit31084ebb59093be7dfe5ab53a20fdb3bcfde34b6 (patch)
tree5b4708eaca4fe58f585dff29f783287c2e47b197 /sw
parente5986baa983e1c7b5e07c45299fd84be2c230fbe (diff)
tdf#143311 offapi,oox,writerfilter,xmloff,sw: decorative flag on flys
* sw core RES_DECORATIVE as a FRMATR * sw API SwXFrame property "Decorative" * UI checkbox "Decorative" * ODF import/export as loext:decorative on draw:frame * DOCX export * DOCX import - very non-obvious how to get it from model.xml to dmapper * PDF/UA export: tag flys with this flag as Artifact * test for DOCX filters, ODF filters, PDF export Change-Id: I1ceb67fdd4e1cfa212aafdeb1c5f4ccd873d433e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143815 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Diffstat (limited to 'sw')
-rw-r--r--sw/inc/hintids.hxx32
-rw-r--r--sw/qa/extras/globalfilter/data/tdf143311-1.docxbin0 -> 34371 bytes
-rw-r--r--sw/qa/extras/globalfilter/globalfilter.cxx101
-rw-r--r--sw/source/core/bastyp/init.cxx4
-rw-r--r--sw/source/core/text/EnhancedPDFExportHelper.cxx3
-rw-r--r--sw/source/core/unocore/unoframe.cxx9
-rw-r--r--sw/source/core/unocore/unomapproperties.hxx1
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx15
-rw-r--r--sw/source/ui/frmdlg/frmpage.cxx10
-rw-r--r--sw/source/uibase/inc/frmpage.hxx1
-rw-r--r--sw/uiconfig/swriter/ui/frmaddpage.ui20
11 files changed, 177 insertions, 19 deletions
diff --git a/sw/inc/hintids.hxx b/sw/inc/hintids.hxx
index 22dba273ec1b..e2392cf0007e 100644
--- a/sw/inc/hintids.hxx
+++ b/sw/inc/hintids.hxx
@@ -368,24 +368,24 @@ constexpr TypedWhichId<SfxGrabBagItem> RES_FRMATR_GRABBAG(129);
constexpr TypedWhichId<SdrTextVertAdjustItem> RES_TEXT_VERT_ADJUST(130);
constexpr TypedWhichId<SfxBoolItem> RES_BACKGROUND_FULL_SIZE(131);
constexpr TypedWhichId<SfxBoolItem> RES_RTL_GUTTER(132);
-constexpr sal_uInt16 RES_FRMATR_END(133);
+constexpr TypedWhichId<SfxBoolItem> RES_DECORATIVE(133);
+constexpr sal_uInt16 RES_FRMATR_END(134);
constexpr sal_uInt16 RES_GRFATR_BEGIN(RES_FRMATR_END);
-constexpr TypedWhichId<SwMirrorGrf> RES_GRFATR_MIRRORGRF(RES_GRFATR_BEGIN); // 133
-constexpr TypedWhichId<SwCropGrf> RES_GRFATR_CROPGRF(134);
-
-constexpr TypedWhichId<SwRotationGrf> RES_GRFATR_ROTATION(135);
-constexpr TypedWhichId<SwLuminanceGrf> RES_GRFATR_LUMINANCE(136);
-constexpr TypedWhichId<SwContrastGrf> RES_GRFATR_CONTRAST(137);
-constexpr TypedWhichId<SwChannelRGrf> RES_GRFATR_CHANNELR(138);
-constexpr TypedWhichId<SwChannelGGrf> RES_GRFATR_CHANNELG(139);
-constexpr TypedWhichId<SwChannelBGrf> RES_GRFATR_CHANNELB(140);
-constexpr TypedWhichId<SwGammaGrf> RES_GRFATR_GAMMA(141);
-constexpr TypedWhichId<SwInvertGrf> RES_GRFATR_INVERT(142);
-constexpr TypedWhichId<SwTransparencyGrf> RES_GRFATR_TRANSPARENCY(143);
-constexpr TypedWhichId<SwDrawModeGrf> RES_GRFATR_DRAWMODE(144);
-
-constexpr TypedWhichId<SfxBoolItem> RES_GRFATR_DUMMY1(145);
+constexpr TypedWhichId<SwMirrorGrf> RES_GRFATR_MIRRORGRF(RES_GRFATR_BEGIN);
+constexpr TypedWhichId<SwCropGrf> RES_GRFATR_CROPGRF(135);
+
+constexpr TypedWhichId<SwRotationGrf> RES_GRFATR_ROTATION(136);
+constexpr TypedWhichId<SwLuminanceGrf> RES_GRFATR_LUMINANCE(137);
+constexpr TypedWhichId<SwContrastGrf> RES_GRFATR_CONTRAST(138);
+constexpr TypedWhichId<SwChannelRGrf> RES_GRFATR_CHANNELR(139);
+constexpr TypedWhichId<SwChannelGGrf> RES_GRFATR_CHANNELG(140);
+constexpr TypedWhichId<SwChannelBGrf> RES_GRFATR_CHANNELB(141);
+constexpr TypedWhichId<SwGammaGrf> RES_GRFATR_GAMMA(142);
+constexpr TypedWhichId<SwInvertGrf> RES_GRFATR_INVERT(143);
+constexpr TypedWhichId<SwTransparencyGrf> RES_GRFATR_TRANSPARENCY(144);
+constexpr TypedWhichId<SwDrawModeGrf> RES_GRFATR_DRAWMODE(145);
+
constexpr TypedWhichId<SfxBoolItem> RES_GRFATR_DUMMY2(146);
constexpr TypedWhichId<SfxBoolItem> RES_GRFATR_DUMMY3(147);
constexpr TypedWhichId<SfxBoolItem> RES_GRFATR_DUMMY4(148);
diff --git a/sw/qa/extras/globalfilter/data/tdf143311-1.docx b/sw/qa/extras/globalfilter/data/tdf143311-1.docx
new file mode 100644
index 000000000000..b6b2d089812b
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/tdf143311-1.docx
Binary files differ
diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx
index 188340354a88..7beb928dd344 100644
--- a/sw/qa/extras/globalfilter/globalfilter.cxx
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -15,7 +15,10 @@
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/text/XDocumentIndex.hpp>
#include <o3tl/safeint.hxx>
+#include <o3tl/string_view.hxx>
#include <officecfg/Office/Common.hxx>
+#include <tools/zcodec.hxx>
+#include <vcl/filter/pdfdocument.hxx>
#include <sfx2/linkmgr.hxx>
#include <comphelper/propertysequence.hxx>
#include <unotxdoc.hxx>
@@ -1227,6 +1230,104 @@ void Test::testBulletAsImage()
}
}
+CPPUNIT_TEST_FIXTURE(Test, testTdf143311)
+{
+ createSwDoc("tdf143311-1.docx");
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(1), "Decorative"));
+ // check DOCX filters
+ saveAndReload("Office Open XML Text");
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(1), "Decorative"));
+ // check ODF filters
+ saveAndReload("writer8");
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(1), "Decorative"));
+
+ // check PDF export
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ // Enable PDF/UA
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ css::uno::Reference<frame::XStorable> xStorable(mxComponent, css::uno::UNO_QUERY_THROW);
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ vcl::filter::PDFDocument aDocument;
+ SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+ CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+ // The document has one page.
+ std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+ vcl::filter::PDFObjectElement* pContents = aPages[0]->LookupObject("Contents");
+ CPPUNIT_ASSERT(pContents);
+ vcl::filter::PDFStreamElement* pStream = pContents->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ // Uncompress it.
+ SvMemoryStream aUncompressed;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ rObjectStream.Seek(0);
+ aZCodec.Decompress(rObjectStream, aUncompressed);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+ auto pStart = static_cast<const char*>(aUncompressed.GetData());
+ const char* const pEnd = pStart + aUncompressed.GetSize();
+
+ enum
+ {
+ Default,
+ Artifact,
+ Tagged
+ } state
+ = Default;
+
+ auto nLine(0);
+ auto nTagged(0);
+ auto nArtifacts(0);
+ while (true)
+ {
+ ++nLine;
+ auto const pLine = ::std::find(pStart, pEnd, '\n');
+ if (pLine == pEnd)
+ {
+ break;
+ }
+ std::string_view const line(pStart, pLine - pStart);
+ pStart = pLine + 1;
+ if (!line.empty() && line[0] != '%')
+ {
+ ::std::cerr << nLine << ": " << line << "\n";
+ if (line == "/Artifact BMC")
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, state);
+ state = Artifact;
+ ++nArtifacts;
+ }
+ else if (o3tl::starts_with(line, "/Standard<</MCID") && o3tl::ends_with(line, ">>BDC"))
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, state);
+ state = Tagged;
+ ++nTagged;
+ }
+ else if (line == "EMC")
+ {
+ CPPUNIT_ASSERT_MESSAGE("unexpected end", state != Default);
+ state = Default;
+ }
+ else if (nLine > 1) // first line is expected "0.1 w"
+ {
+ CPPUNIT_ASSERT_MESSAGE("unexpected content outside MCS", state != Default);
+ }
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("unclosed MCS", Default, state);
+ CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nTagged)>(25), nTagged); // text in body
+ // 1 decorative image + 1 pre-existing rectangle border or something
+ CPPUNIT_ASSERT(nArtifacts >= 2);
+}
+
void Test::testTextFormField()
{
const OUString aFilterNames[] = {
diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx
index 461d7bc2da6e..a7e1a41db639 100644
--- a/sw/source/core/bastyp/init.cxx
+++ b/sw/source/core/bastyp/init.cxx
@@ -404,6 +404,7 @@ SfxItemInfo aSlotTab[] =
{ 0, true }, // RES_TEXT_VERT_ADJUST
{ 0, true }, // RES_BACKGROUND_FULL_SIZE
{ 0, true }, // RES_RTL_GUTTER
+ { 0, true }, // RES_DECORATIVE
{ 0, true }, // RES_GRFATR_MIRRORGRF
{ SID_ATTR_GRAF_CROP, true }, // RES_GRFATR_CROPGRF
@@ -416,7 +417,6 @@ SfxItemInfo aSlotTab[] =
{ 0, true }, // RES_GRFATR_GAMMA,
{ 0, true }, // RES_GRFATR_INVERT,
{ 0, true }, // RES_GRFATR_TRANSPARENCY,
- { 0, true }, // RES_GRFATR_DUMMY1,
{ 0, true }, // RES_GRFATR_DUMMY2,
{ 0, true }, // RES_GRFATR_DUMMY3,
{ 0, true }, // RES_GRFATR_DUMMY4,
@@ -609,6 +609,7 @@ void InitCore()
aAttrTab[ RES_TEXT_VERT_ADJUST - POOLATTR_BEGIN ] = new SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP,RES_TEXT_VERT_ADJUST);
aAttrTab[ RES_BACKGROUND_FULL_SIZE - POOLATTR_BEGIN ] = new SfxBoolItem(RES_BACKGROUND_FULL_SIZE, true);
aAttrTab[ RES_RTL_GUTTER - POOLATTR_BEGIN ] = new SfxBoolItem(RES_RTL_GUTTER, false);
+ aAttrTab[ RES_DECORATIVE - POOLATTR_BEGIN ] = new SfxBoolItem(RES_DECORATIVE, false);
aAttrTab[ RES_GRFATR_MIRRORGRF- POOLATTR_BEGIN ] = new SwMirrorGrf;
aAttrTab[ RES_GRFATR_CROPGRF- POOLATTR_BEGIN ] = new SwCropGrf;
@@ -624,7 +625,6 @@ void InitCore()
aAttrTab[ RES_GRFATR_DRAWMODE - POOLATTR_BEGIN ] = new SwDrawModeGrf;
// GraphicAttr - Dummies
- aAttrTab[ RES_GRFATR_DUMMY1 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_GRFATR_DUMMY1 );
aAttrTab[ RES_GRFATR_DUMMY2 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_GRFATR_DUMMY2 );
aAttrTab[ RES_GRFATR_DUMMY3 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_GRFATR_DUMMY3 );
aAttrTab[ RES_GRFATR_DUMMY4 - POOLATTR_BEGIN ] = new SfxBoolItem( RES_GRFATR_DUMMY4 );
diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx b/sw/source/core/text/EnhancedPDFExportHelper.cxx
index e8221d4ebf12..42141b4013f9 100644
--- a/sw/source/core/text/EnhancedPDFExportHelper.cxx
+++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx
@@ -1302,7 +1302,8 @@ void SwTaggedPDFHelper::BeginBlockStructureElements()
// fly in content or fly at page
{
const SwFlyFrame* pFly = static_cast<const SwFlyFrame*>(pFrame);
- if (pFly->GetAnchorFrame()->FindFooterOrHeader() != nullptr)
+ if (pFly->GetAnchorFrame()->FindFooterOrHeader() != nullptr
+ || pFly->GetFrameFormat().GetAttrSet().Get(RES_DECORATIVE).GetValue())
{
nPDFType = vcl::PDFWriter::NonStructElement;
}
diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx
index 95b8956ea0a9..71e69a95192d 100644
--- a/sw/source/core/unocore/unoframe.cxx
+++ b/sw/source/core/unocore/unoframe.cxx
@@ -949,6 +949,15 @@ bool BaseFrameProperties_Impl::FillBaseProperties(SfxItemSet& rToSet, const SfxI
}
}
+ const ::uno::Any* pDecorative = nullptr;
+ GetProperty(RES_DECORATIVE, 0, pDecorative);
+ if (pDecorative)
+ {
+ SfxBoolItem item(RES_DECORATIVE);
+ bRet &= item.PutValue(*pDecorative, 0);
+ rToSet.Put(item);
+ }
+
return bRet;
}
diff --git a/sw/source/core/unocore/unomapproperties.hxx b/sw/source/core/unocore/unomapproperties.hxx
index c1e3f2fc20af..11a326d185c5 100644
--- a/sw/source/core/unocore/unomapproperties.hxx
+++ b/sw/source/core/unocore/unomapproperties.hxx
@@ -337,6 +337,7 @@
{ UNO_NAME_LAYOUT_SIZE, WID_LAYOUT_SIZE, cppu::UnoType<css::awt::Size>::get(), PropertyAttribute::MAYBEVOID | PropertyAttribute::READONLY, 0 }, \
{ UNO_NAME_LINE_STYLE, RES_BOX, cppu::UnoType<css::drawing::LineStyle>::get(), 0, LINE_STYLE }, \
{ UNO_NAME_LINE_WIDTH, RES_BOX, cppu::UnoType<sal_Int32>::get(), 0, LINE_WIDTH |CONVERT_TWIPS }, \
+ { u"Decorative", RES_DECORATIVE, cppu::UnoType<bool>::get(), PROPERTY_NONE, 0 }, \
{ UNO_NAME_TEXT_VERT_ADJUST, RES_TEXT_VERT_ADJUST, cppu::UnoType<css::drawing::TextVerticalAdjust>::get(), PROPERTY_NONE ,0},
#define COMMON_TEXT_CONTENT_PROPERTIES \
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 95f137ec771f..76d608ddc01e 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -5693,6 +5693,21 @@ void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size
FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
FSNS( XML_r, XML_id ), sRelId);
}
+
+ if (xShapePropSet->getPropertyValue("Decorative").get<bool>())
+ {
+ m_pSerializer->startElementNS(XML_a, XML_extLst,
+ FSNS(XML_xmlns, XML_a), GetExport().GetFilter().getNamespaceURL(OOX_NS(dml)));
+ m_pSerializer->startElementNS(XML_a, XML_ext,
+ // Word uses this "URI" which is obviously not a URI
+ XML_uri, "{C183D7F6-B498-43B3-948B-1728B52AA6E4}");
+ rtl::Reference<::sax_fastparser::FastAttributeList> pAttrs(FastSerializerHelper::createAttrList());
+ m_pSerializer->singleElementNS(XML_adec, XML_decorative,
+ FSNS(XML_xmlns, XML_adec), "http://schemas.microsoft.com/office/drawing/2017/decorative",
+ XML_val, "1");
+ m_pSerializer->endElementNS(XML_a, XML_ext);
+ m_pSerializer->endElementNS(XML_a, XML_extLst);
+ }
}
m_pSerializer->endElementNS( XML_wp, XML_docPr );
diff --git a/sw/source/ui/frmdlg/frmpage.cxx b/sw/source/ui/frmdlg/frmpage.cxx
index f1c20e73fa0b..2b8b9105caab 100644
--- a/sw/source/ui/frmdlg/frmpage.cxx
+++ b/sw/source/ui/frmdlg/frmpage.cxx
@@ -2792,6 +2792,7 @@ SwFrameAddPage::SwFrameAddPage(weld::Container* pPage, weld::DialogController* p
, m_xAltNameFT(m_xBuilder->weld_label("altname_label"))
, m_xAltNameED(m_xBuilder->weld_entry("altname"))
, m_xDescriptionED(m_xBuilder->weld_text_view("description"))
+ , m_xDecorativeCB(m_xBuilder->weld_check_button("decorative"))
, m_xSequenceFrame(m_xBuilder->weld_widget("frmSequence"))
, m_xPrevLB(m_xBuilder->weld_combo_box("prev"))
, m_xNextLB(m_xBuilder->weld_combo_box("next"))
@@ -2978,6 +2979,10 @@ void SwFrameAddPage::Reset(const SfxItemSet *rSet )
m_xPrintFrameCB->set_active(rPrt.GetValue());
m_xPrintFrameCB->save_state();
+ SfxBoolItem const& rDecorative = rSet->Get(RES_DECORATIVE);
+ m_xDecorativeCB->set_active(rDecorative.GetValue());
+ m_xDecorativeCB->save_state();
+
// textflow
if( (!m_bHtmlMode || (0 != (nHtmlMode&HTMLMODE_SOME_STYLES)))
&& m_sDlgType != "PictureDialog" && m_sDlgType != "ObjectDialog"
@@ -3043,6 +3048,11 @@ bool SwFrameAddPage::FillItemSet(SfxItemSet *rSet)
if ( m_xPrintFrameCB->get_state_changed_from_saved() )
bRet |= nullptr != rSet->Put( SvxPrintItem( RES_PRINT, m_xPrintFrameCB->get_active()));
+ if (m_xDecorativeCB->get_state_changed_from_saved())
+ {
+ bRet |= nullptr != rSet->Put(SfxBoolItem(RES_DECORATIVE, m_xDecorativeCB->get_active()));
+ }
+
// textflow
if (m_xTextFlowLB->get_visible() && m_xTextFlowLB->get_value_changed_from_saved())
{
diff --git a/sw/source/uibase/inc/frmpage.hxx b/sw/source/uibase/inc/frmpage.hxx
index 2a6b280c68c6..db74d967ae3e 100644
--- a/sw/source/uibase/inc/frmpage.hxx
+++ b/sw/source/uibase/inc/frmpage.hxx
@@ -279,6 +279,7 @@ class SwFrameAddPage final : public SfxTabPage
std::unique_ptr<weld::Label> m_xAltNameFT;
std::unique_ptr<weld::Entry> m_xAltNameED;
std::unique_ptr<weld::TextView> m_xDescriptionED;
+ std::unique_ptr<weld::CheckButton> m_xDecorativeCB;
std::unique_ptr<weld::Widget> m_xSequenceFrame;
std::unique_ptr<weld::ComboBox> m_xPrevLB;
std::unique_ptr<weld::ComboBox> m_xNextLB;
diff --git a/sw/uiconfig/swriter/ui/frmaddpage.ui b/sw/uiconfig/swriter/ui/frmaddpage.ui
index dd949a5b69cf..51431a1ff493 100644
--- a/sw/uiconfig/swriter/ui/frmaddpage.ui
+++ b/sw/uiconfig/swriter/ui/frmaddpage.ui
@@ -146,6 +146,26 @@
<property name="top-attach">2</property>
</packing>
</child>
+ <child>
+ <object class="GtkCheckButton" id="decorative">
+ <property name="label" translatable="yes" context="frmaddpage|decorative">Decorative</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="decorative-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="frmaddpage|extended_tip|decorative">The item is purely decorative, not part of the document content, and may be ignored by assistive technologies.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
</object>
</child>
<child type="label">