diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2022-12-08 10:54:18 +0100 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2022-12-09 16:03:20 +0000 |
commit | 31084ebb59093be7dfe5ab53a20fdb3bcfde34b6 (patch) | |
tree | 5b4708eaca4fe58f585dff29f783287c2e47b197 /sw | |
parent | e5986baa983e1c7b5e07c45299fd84be2c230fbe (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.hxx | 32 | ||||
-rw-r--r-- | sw/qa/extras/globalfilter/data/tdf143311-1.docx | bin | 0 -> 34371 bytes | |||
-rw-r--r-- | sw/qa/extras/globalfilter/globalfilter.cxx | 101 | ||||
-rw-r--r-- | sw/source/core/bastyp/init.cxx | 4 | ||||
-rw-r--r-- | sw/source/core/text/EnhancedPDFExportHelper.cxx | 3 | ||||
-rw-r--r-- | sw/source/core/unocore/unoframe.cxx | 9 | ||||
-rw-r--r-- | sw/source/core/unocore/unomapproperties.hxx | 1 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxattributeoutput.cxx | 15 | ||||
-rw-r--r-- | sw/source/ui/frmdlg/frmpage.cxx | 10 | ||||
-rw-r--r-- | sw/source/uibase/inc/frmpage.hxx | 1 | ||||
-rw-r--r-- | sw/uiconfig/swriter/ui/frmaddpage.ui | 20 |
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 Binary files differnew file mode 100644 index 000000000000..b6b2d089812b --- /dev/null +++ b/sw/qa/extras/globalfilter/data/tdf143311-1.docx 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"> |