sw/inc/charatr.hxx | 3 + sw/inc/hintids.hxx | 5 + sw/inc/swatrset.hxx | 2 sw/inc/unoprnms.hxx | 1 sw/qa/extras/htmlexport/htmlexport.cxx | 27 +++++++++ sw/qa/extras/odfexport/odfexport.cxx | 56 ++++++++++++++++++++ sw/qa/uitest/styleInspector/styleInspector.py | 20 +++---- sw/qa/uitest/styleInspector/tdf137513.py | 2 sw/source/core/bastyp/init.cxx | 2 sw/source/core/doc/DocumentStylePoolManager.cxx | 1 sw/source/core/doc/dbgoutsw.cxx | 1 sw/source/core/inc/swfntcch.hxx | 2 sw/source/core/inc/swfont.hxx | 16 +++++ sw/source/core/layout/wsfrm.cxx | 1 sw/source/core/text/atrhndl.hxx | 2 sw/source/core/text/atrstck.cxx | 21 ++++--- sw/source/core/txtnode/swfont.cxx | 3 + sw/source/core/unocore/unomap1.cxx | 2 sw/source/core/unocore/unomapproperties.hxx | 2 sw/source/filter/html/css1atr.cxx | 12 ++++ sw/source/filter/html/css1kywd.hxx | 1 sw/source/filter/html/htmlatr.cxx | 2 sw/source/filter/html/htmlcss1.cxx | 3 + sw/source/filter/html/svxcss1.cxx | 26 +++++++++ sw/source/filter/html/swhtml.hxx | 1 sw/source/filter/ww8/attributeoutputbase.hxx | 4 + sw/source/filter/ww8/docxattributeoutput.cxx | 9 +++ sw/source/filter/ww8/docxattributeoutput.hxx | 3 + sw/source/filter/ww8/rtfattributeoutput.cxx | 14 +++++ sw/source/filter/ww8/rtfattributeoutput.hxx | 5 + sw/source/filter/ww8/ww8atr.cxx | 9 +++ sw/source/filter/ww8/ww8attributeoutput.hxx | 3 + sw/source/uibase/app/docshini.cxx | 4 + vcl/qa/cppunit/pdfexport/data/testOpticalSizing.odt |binary vcl/qa/cppunit/pdfexport/pdfexport.cxx | 38 +++++++++++++ 35 files changed, 281 insertions(+), 22 deletions(-)
New commits: commit 475ec1aa3683cd4a7ff9e5f89d0b3fc858763fa3 Author: Khaled Hosny <[email protected]> AuthorDate: Mon Mar 2 02:02:25 2026 +0200 Commit: Khaled Hosny <[email protected]> CommitDate: Mon Mar 2 21:45:41 2026 +0100 tdf#153368: Support optical size for variable fonts, part 5 Support import/export of font-optical-sizing in HTML filter. Change-Id: Ib45b3152b57e674fc1e0b4b4b2359634909d15a0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200538 Tested-by: Jenkins Reviewed-by: Khaled Hosny <[email protected]> diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx index 20cfe024500f..85fa29ec4c5d 100644 --- a/sw/qa/extras/htmlexport/htmlexport.cxx +++ b/sw/qa/extras/htmlexport/htmlexport.cxx @@ -1651,6 +1651,33 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqifNoTypeInUL) // Without the accompanying fix in place, this test would have failed assertXPathNoAttribute(pXmlDoc, "//reqif-xhtml:ul/reqif-xhtml:li/reqif-xhtml:ul", "type"); } + +CPPUNIT_TEST_FIXTURE(HtmlExportTest, testOpticalSizing) +{ + createSwDoc(); + uno::Reference<text::XTextRange> xRun = getRun(getParagraph(1), 1); + xRun->setString(u"text"_ustr); + uno::Reference<beans::XPropertySet> xCursor(xRun, uno::UNO_QUERY); + + xCursor->setPropertyValue(u"CharOpticalSizing"_ustr, uno::Any(false)); + saveAndReload(TestFilter::HTML_WRITER); + + uno::Reference<beans::XPropertySet> xRetCursor(getRun(getParagraph(1), 1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xRetCursor, u"CharOpticalSizing"_ustr)); + + dispose(); + + createSwDoc(); + uno::Reference<text::XTextRange> xRun2 = getRun(getParagraph(1), 1); + xRun2->setString(u"text"_ustr); + uno::Reference<beans::XPropertySet> xCursor2(xRun2, uno::UNO_QUERY); + + xCursor2->setPropertyValue(u"CharOpticalSizing"_ustr, uno::Any(true)); + saveAndReload(TestFilter::HTML_WRITER); + + uno::Reference<beans::XPropertySet> xRetCursor2(getRun(getParagraph(1), 1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xRetCursor2, u"CharOpticalSizing"_ustr)); +} } // end of anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/filter/html/css1atr.cxx b/sw/source/filter/html/css1atr.cxx index 6f80bb53ff47..12334aaac59d 100644 --- a/sw/source/filter/html/css1atr.cxx +++ b/sw/source/filter/html/css1atr.cxx @@ -48,6 +48,7 @@ #include <editeng/spltitem.hxx> #include <editeng/orphitem.hxx> #include <editeng/charhiddenitem.hxx> +#include <editeng/opticalsizingitem.hxx> #include <svx/xoutbmp.hxx> #include <svx/svdobj.hxx> #include <editeng/langitem.hxx> @@ -2549,6 +2550,16 @@ static SwHTMLWriter& OutCSS1_SvxHidden( SwHTMLWriter& rWrt, const SfxPoolItem& r return rWrt; } +static SwHTMLWriter& OutCSS1_SvxOpticalSizing( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) +{ + if( static_cast<const SvxOpticalSizingItem&>(rHt).GetValue() ) + rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_optical_sizing, sCSS1_PV_auto ); + else + rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_optical_sizing, sCSS1_PV_none ); + + return rWrt; +} + static SwHTMLWriter& OutCSS1_SvxFontWeight( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { sal_uInt16 nScript = CSS1_OUTMODE_WESTERN; @@ -3465,7 +3476,7 @@ SwAttrFnTab const aCSS1AttrFnTab = { /* RES_CHRATR_BIDIRTL */ nullptr, /* RES_CHRATR_UNUSED3 */ nullptr, /* RES_CHRATR_SCRIPT_HINT */ nullptr, -/* RES_CHRATR_OPTICAL_SIZING */ nullptr, +/* RES_CHRATR_OPTICAL_SIZING */ OutCSS1_SvxOpticalSizing, /* RES_TXTATR_REFMARK */ nullptr, /* RES_TXTATR_TOXMARK */ nullptr, diff --git a/sw/source/filter/html/css1kywd.hxx b/sw/source/filter/html/css1kywd.hxx index 2548cd3a9537..8332083ad0f1 100644 --- a/sw/source/filter/html/css1kywd.hxx +++ b/sw/source/filter/html/css1kywd.hxx @@ -65,6 +65,7 @@ constexpr inline std::string_view sCSS1_PV_italic = "italic"; constexpr inline std::string_view sCSS1_PV_oblique = "oblique"; constexpr inline std::string_view sCSS1_P_font_variant = "font-variant"; +constexpr inline std::string_view sCSS1_P_font_optical_sizing = "font-optical-sizing"; //constexpr inline std::string_view sCSS1_PV_normal = "normal"; constexpr inline std::string_view sCSS1_PV_small_caps = "small-caps"; diff --git a/sw/source/filter/html/htmlatr.cxx b/sw/source/filter/html/htmlatr.cxx index d917fea69094..cc33bf540ff4 100644 --- a/sw/source/filter/html/htmlatr.cxx +++ b/sw/source/filter/html/htmlatr.cxx @@ -45,6 +45,7 @@ #include <editeng/lrspitem.hxx> #include <editeng/langitem.hxx> #include <editeng/frmdiritem.hxx> +#include <editeng/opticalsizingitem.hxx> #include <fchrfmt.hxx> #include <fmtautofmt.hxx> #include <fmtfsize.hxx> @@ -3316,7 +3317,7 @@ const SwAttrFnTab aHTMLAttrFnTab = { /* RES_CHRATR_BIDIRTL */ nullptr, /* RES_CHRATR_UNUSED3 */ nullptr, /* RES_CHRATR_SCRIPT_HINT */ nullptr, -/* RES_CHRATR_OPTICAL_SIZING */ nullptr, +/* RES_CHRATR_OPTICAL_SIZING */ OutHTML_CSS1Attr, /* RES_TXTATR_REFMARK */ nullptr, /* RES_TXTATR_TOXMARK */ nullptr, diff --git a/sw/source/filter/html/htmlcss1.cxx b/sw/source/filter/html/htmlcss1.cxx index 5229d3c69eb5..cc0bb8d90cd8 100644 --- a/sw/source/filter/html/htmlcss1.cxx +++ b/sw/source/filter/html/htmlcss1.cxx @@ -1598,6 +1598,9 @@ HTMLAttr **SwHTMLParser::GetAttrTabEntry( sal_uInt16 nWhich ) case RES_CHRATR_BACKGROUND: ppAttr = &m_xAttrTab->pCharBrush; break; + case RES_CHRATR_OPTICAL_SIZING: + ppAttr = &m_xAttrTab->pOpticalSizing; + break; case RES_CHRATR_BOX: ppAttr = &m_xAttrTab->pCharBox; break; diff --git a/sw/source/filter/html/svxcss1.cxx b/sw/source/filter/html/svxcss1.cxx index 69cc2f381cd4..ffd8dd0a7982 100644 --- a/sw/source/filter/html/svxcss1.cxx +++ b/sw/source/filter/html/svxcss1.cxx @@ -52,6 +52,7 @@ #include <editeng/widwitem.hxx> #include <editeng/frmdiritem.hxx> #include <editeng/orphitem.hxx> +#include <editeng/opticalsizingitem.hxx> #include <utility> #include <vcl/metric.hxx> #include <vcl/svapp.hxx> @@ -283,6 +284,7 @@ struct SvxCSS1ItemIds sal_uInt16 nKerning; sal_uInt16 nCaseMap; sal_uInt16 nBlink; + sal_uInt16 nOpticalSizing; sal_uInt16 nLineSpacing; sal_uInt16 nAdjust; @@ -738,6 +740,7 @@ SvxCSS1Parser::SvxCSS1Parser( SfxItemPool& rPool, OUString aBaseURL, aItemIds.nKerning = initTrueWhich( SID_ATTR_CHAR_KERNING ); aItemIds.nCaseMap = initTrueWhich( SID_ATTR_CHAR_CASEMAP ); aItemIds.nBlink = initTrueWhich( SID_ATTR_FLASH ); + aItemIds.nOpticalSizing = initTrueWhich( SID_ATTR_CHAR_OPTICAL_SIZING ); aItemIds.nLineSpacing = initTrueWhich( SID_ATTR_PARA_LINESPACE ); aItemIds.nAdjust = initTrueWhich( SID_ATTR_PARA_ADJUST ); @@ -1247,6 +1250,28 @@ static void ParseCSS1_font_variant( const CSS1Expression *pExpr, } } +static void ParseCSS1_font_optical_sizing( const CSS1Expression *pExpr, + SfxItemSet &rItemSet, + SvxCSS1PropertyInfo& /*rPropInfo*/, + const SvxCSS1Parser& /*rParser*/ ) +{ + assert(pExpr && "no expression"); + + switch( pExpr->GetType() ) + { + case CSS1_IDENT: + { + if( o3tl::equalsIgnoreAsciiCase( pExpr->GetString(), sCSS1_PV_auto ) ) + rItemSet.Put( SvxOpticalSizingItem( true, aItemIds.nOpticalSizing ) ); + else if( o3tl::equalsIgnoreAsciiCase( pExpr->GetString(), sCSS1_PV_none ) ) + rItemSet.Put( SvxOpticalSizingItem( false, aItemIds.nOpticalSizing ) ); + break; + } + default: + break; + } +} + static void ParseCSS1_text_transform( const CSS1Expression *pExpr, SfxItemSet &rItemSet, SvxCSS1PropertyInfo& /*rPropInfo*/, @@ -3099,6 +3124,7 @@ CSS1PropEntry constexpr aCSS1PropFnTab[] = { sCSS1_P_float, ParseCSS1_float }, { sCSS1_P_font, ParseCSS1_font }, { sCSS1_P_font_family, ParseCSS1_font_family }, + { sCSS1_P_font_optical_sizing, ParseCSS1_font_optical_sizing }, { sCSS1_P_font_size, ParseCSS1_font_size }, { sCSS1_P_font_style, ParseCSS1_font_style }, { sCSS1_P_font_variant, ParseCSS1_font_variant }, diff --git a/sw/source/filter/html/swhtml.hxx b/sw/source/filter/html/swhtml.hxx index 151189aa7acf..5147d8e8c6fa 100644 --- a/sw/source/filter/html/swhtml.hxx +++ b/sw/source/filter/html/swhtml.hxx @@ -128,6 +128,7 @@ struct HTMLAttrTable HTMLAttr* pLanguageCJK; HTMLAttr* pLanguageCTL; HTMLAttr* pCharBox; + HTMLAttr* pOpticalSizing; }; class HTMLAttr commit 1802e84d03c3d458edc3e124d2a7839660bc53d0 Author: Khaled Hosny <[email protected]> AuthorDate: Mon Mar 2 02:02:23 2026 +0200 Commit: Khaled Hosny <[email protected]> CommitDate: Mon Mar 2 21:45:29 2026 +0100 tdf#153368: Support optical size for variable fonts, part 4 Support saving/loading font-optical-sizing in Writer. The font-optical-sizing property is enabled on the standard style for new documents, and for old documents it remains unset for backward compatibility. Add no-op stubs to DOCX, RTF, WW8, and HTML filters. Change-Id: I87e3de603785dbd588099bfbd72e13e4538fc420 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200536 Reviewed-by: Khaled Hosny <[email protected]> Tested-by: Jenkins diff --git a/sw/inc/charatr.hxx b/sw/inc/charatr.hxx index 3bea7a6d38e7..677088b44d11 100644 --- a/sw/inc/charatr.hxx +++ b/sw/inc/charatr.hxx @@ -43,6 +43,7 @@ #include <editeng/langitem.hxx> #include <editeng/colritem.hxx> #include <editeng/scripthintitem.hxx> +#include <editeng/opticalsizingitem.hxx> // implementation of the character attribute methods of SwAttrSet @@ -112,6 +113,8 @@ inline const SvxCharReliefItem &SwAttrSet::GetCharRelief( bool bInP ) const { return Get( RES_CHRATR_RELIEF, bInP ); } inline const SvxCharHiddenItem &SwAttrSet::GetCharHidden( bool bInP ) const { return Get( RES_CHRATR_HIDDEN, bInP ); } +inline const SvxOpticalSizingItem&SwAttrSet::GetOpticalSizing(bool bInP) const + { return Get( RES_CHRATR_OPTICAL_SIZING,bInP); } // implementation of the character attribute methods of SwFormat diff --git a/sw/inc/hintids.hxx b/sw/inc/hintids.hxx index 423dafdcea08..59f0c2d51672 100644 --- a/sw/inc/hintids.hxx +++ b/sw/inc/hintids.hxx @@ -76,6 +76,7 @@ class SvxLanguageItem; class SvxLineSpacingItem; class SvxNoHyphenItem; class SvxOpaqueItem; +class SvxOpticalSizingItem; class SvxOrphansItem; class SvxOverlineItem; class SvxPaperBinItem; @@ -244,7 +245,9 @@ inline constexpr TypedWhichId<SfxGrabBagItem> RES_CHRATR_GRABBAG(RES_CHRATR_BEGI inline constexpr TypedWhichId<SfxInt16Item> RES_CHRATR_BIDIRTL(RES_CHRATR_BEGIN + 43); inline constexpr TypedWhichId<SfxInt16Item> RES_CHRATR_UNUSED3(RES_CHRATR_BEGIN + 44); inline constexpr TypedWhichId<SvxScriptHintItem> RES_CHRATR_SCRIPT_HINT(RES_CHRATR_BEGIN + 45); -inline constexpr sal_uInt16 RES_CHRATR_END(RES_CHRATR_BEGIN + 46); +inline constexpr TypedWhichId<SvxOpticalSizingItem> RES_CHRATR_OPTICAL_SIZING(RES_CHRATR_BEGIN + + 46); +inline constexpr sal_uInt16 RES_CHRATR_END(RES_CHRATR_BEGIN + 47); // this Attribute used only in a TextNodes SwpAttr-Array inline constexpr sal_uInt16 RES_TXTATR_BEGIN(RES_CHRATR_END); diff --git a/sw/inc/swatrset.hxx b/sw/inc/swatrset.hxx index 67709a849665..af13c71880ca 100644 --- a/sw/inc/swatrset.hxx +++ b/sw/inc/swatrset.hxx @@ -52,6 +52,7 @@ class SvxCharRotateItem; class SvxCharReliefItem; class SvxCharHiddenItem; class SvxScriptHintItem; +class SvxOpticalSizingItem; // Frame attributes class SwFormatFillOrder; @@ -244,6 +245,7 @@ public: inline const SvxCharRotateItem &GetCharRotate( bool = true ) const; inline const SvxCharReliefItem &GetCharRelief( bool = true ) const; inline const SvxCharHiddenItem &GetCharHidden( bool = true ) const; + inline const SvxOpticalSizingItem &GetOpticalSizing( bool = true ) const; // Frame attributes. Implementation in frmatr.hxx. inline const SwFormatFillOrder &GetFillOrder( bool = true ) const; diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx index 3d9270fdb429..e30a28c26581 100644 --- a/sw/inc/unoprnms.hxx +++ b/sw/inc/unoprnms.hxx @@ -151,6 +151,7 @@ inline constexpr OUString UNO_NAME_CHAR_PROP_HEIGHT_COMPLEX = u"CharPropHeightCo inline constexpr OUString UNO_NAME_CHAR_DIFF_HEIGHT_COMPLEX = u"CharDiffHeightComplex"_ustr; inline constexpr OUString UNO_NAME_CHAR_ESCAPEMENT_HEIGHT = u"CharEscapementHeight"_ustr; inline constexpr OUString UNO_NAME_CHAR_TRANSPARENCE = u"CharTransparence"_ustr; +inline constexpr OUString UNO_NAME_CHAR_OPTICAL_SIZING = u"CharOpticalSizing"_ustr; inline constexpr OUString UNO_NAME_HIDE_TAB_LEADER_AND_PAGE_NUMBERS = u"HideTabLeaderAndPageNumber"_ustr; inline constexpr OUString UNO_NAME_TAB_IN_TOC = u"TabInTOC"_ustr; diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx index 153b1a56197e..a97c68702030 100644 --- a/sw/qa/extras/odfexport/odfexport.cxx +++ b/sw/qa/extras/odfexport/odfexport.cxx @@ -1558,7 +1558,63 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf60700_directories) CPPUNIT_ASSERT_EQUAL(0, nMatches); } +// CharOpticalSizing should be enabled by default for new documents +CPPUNIT_TEST_FIXTURE(Test, testOpticalSizing1) +{ + createSwDoc(); + + { + // It should be true by default for new documents + uno::Reference<beans::XPropertySet> xCursor(getRun(getParagraph(1), 1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xCursor, u"CharOpticalSizing"_ustr)); + + // and it should survive save-and-reload + saveAndReload(TestFilter::ODT); + uno::Reference<beans::XPropertySet> xRun(getRun(getParagraph(1), 1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xRun, u"CharOpticalSizing"_ustr)); + } + + { + // Setting it manually should set it in contents + uno::Reference<beans::XPropertySet> xCursor(getRun(getParagraph(1), 1), uno::UNO_QUERY); + xCursor->setPropertyValue(u"CharOpticalSizing"_ustr, uno::Any(true)); + save(TestFilter::ODT); + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + assertXPath(pXmlDoc, "//style:style/style:text-properties[@loext:font-optical-sizing='auto']", 1); + + // and it should survive save-and-reload + saveAndReload(TestFilter::ODT); + uno::Reference<beans::XPropertySet> xRun(getRun(getParagraph(1), 1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xRun, u"CharOpticalSizing"_ustr)); + pXmlDoc = parseExport(u"content.xml"_ustr); + assertXPath(pXmlDoc, "//style:style/style:text-properties[@loext:font-optical-sizing='auto']", 1); + } + { + // It can also be disabled + uno::Reference<beans::XPropertySet> xCursor(getRun(getParagraph(1), 1), uno::UNO_QUERY); + xCursor->setPropertyValue(u"CharOpticalSizing"_ustr, uno::Any(false)); + save(TestFilter::ODT); + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + assertXPath(pXmlDoc, "//style:style/style:text-properties[@loext:font-optical-sizing='none']", 1); + + // and it should survive save-and-reload + saveAndReload(TestFilter::ODT); + uno::Reference<beans::XPropertySet> xRun3(getRun(getParagraph(1), 1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xRun3, u"CharOpticalSizing"_ustr)); + pXmlDoc = parseExport(u"content.xml"_ustr); + assertXPath(pXmlDoc, "//style:style/style:text-properties[@loext:font-optical-sizing='none']", 1); + } + +} + +// CharOpticalSizing should be disabled by default for old documents +CPPUNIT_TEST_FIXTURE(Test, testOpticalSizing2) +{ + createSwDoc("allow-overlap.odt"); + uno::Reference<beans::XPropertySet> xCursor(getRun(getParagraph(1), 1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xCursor, u"CharOpticalSizing"_ustr)); +} } // end of anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/uitest/styleInspector/styleInspector.py b/sw/qa/uitest/styleInspector/styleInspector.py index 70554e5307c1..fec8f514abc0 100644 --- a/sw/qa/uitest/styleInspector/styleInspector.py +++ b/sw/qa/uitest/styleInspector/styleInspector.py @@ -26,7 +26,7 @@ class styleNavigator(UITestCase): # The cursor is on text without formatting and default style self.assertEqual(1, len(xListBox.getChild('0').getChildren())) self.assertEqual("Default Paragraph Style ", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text']) - self.assertEqual(157, len(xListBox.getChild('0').getChild('0').getChildren())) + self.assertEqual(158, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(0, len(xListBox.getChild('1').getChildren())) self.assertEqual(0, len(xListBox.getChild('2').getChildren())) self.assertEqual(0, len(xListBox.getChild('3').getChildren())) @@ -36,7 +36,7 @@ class styleNavigator(UITestCase): # The cursor is on text with direct formatting self.assertEqual(1, len(xListBox.getChild('0').getChildren())) self.assertEqual("Default Paragraph Style ", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text']) - self.assertEqual(157, len(xListBox.getChild('0').getChild('0').getChildren())) + self.assertEqual(158, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(0, len(xListBox.getChild('1').getChildren())) self.assertEqual(0, len(xListBox.getChild('2').getChildren())) @@ -54,7 +54,7 @@ class styleNavigator(UITestCase): # The cursor is on text with paragraph direct formatting self.assertEqual(1, len(xListBox.getChild('0').getChildren())) self.assertEqual("Default Paragraph Style ", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text']) - self.assertEqual(157, len(xListBox.getChild('0').getChild('0').getChildren())) + self.assertEqual(158, len(xListBox.getChild('0').getChild('0').getChildren())) xParDirFormatting = xListBox.getChild('1') self.assertEqual(7, len(xParDirFormatting.getChildren())) @@ -75,7 +75,7 @@ class styleNavigator(UITestCase): xParStyle = xListBox.getChild('0') self.assertEqual(3, len(xParStyle.getChildren())) self.assertEqual("Default Paragraph Style ", get_state_as_dict(xParStyle.getChild('0'))['Text']) - self.assertEqual(157, len(xParStyle.getChild('0').getChildren())) + self.assertEqual(158, len(xParStyle.getChild('0').getChildren())) self.assertEqual("Heading ", get_state_as_dict(xParStyle.getChild('1'))['Text']) self.assertEqual(28, len(xParStyle.getChild('1').getChildren())) @@ -116,7 +116,7 @@ class styleNavigator(UITestCase): xParStyle = xListBox.getChild('0') self.assertEqual(3, len(xParStyle.getChildren())) self.assertEqual("Default Paragraph Style ", get_state_as_dict(xParStyle.getChild('0'))['Text']) - self.assertEqual(157, len(xParStyle.getChild('0').getChildren())) + self.assertEqual(158, len(xParStyle.getChild('0').getChildren())) self.assertEqual("Body Text ", get_state_as_dict(xParStyle.getChild('1'))['Text']) self.assertEqual(6, len(xParStyle.getChild('1').getChildren())) @@ -151,7 +151,7 @@ class styleNavigator(UITestCase): # The cursor is on text without metadata self.assertEqual(1, len(xListBox.getChild('0').getChildren())) self.assertEqual("Default Paragraph Style ", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text']) - self.assertEqual(157, len(xListBox.getChild('0').getChild('0').getChildren())) + self.assertEqual(158, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(0, len(xListBox.getChild('1').getChildren())) self.assertEqual(0, len(xListBox.getChild('2').getChildren())) self.assertEqual(0, len(xListBox.getChild('3').getChildren())) @@ -161,7 +161,7 @@ class styleNavigator(UITestCase): # The cursor is on text with paragraph metadata showed under direct paragraph formatting self.assertEqual(1, len(xListBox.getChild('0').getChildren())) self.assertEqual("Default Paragraph Style ", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text']) - self.assertEqual(157, len(xListBox.getChild('0').getChild('0').getChildren())) + self.assertEqual(158, len(xListBox.getChild('0').getChild('0').getChildren())) xParDirFormatting = xListBox.getChild('1') self.assertEqual(1, len(xParDirFormatting.getChildren())) @@ -214,7 +214,7 @@ class styleNavigator(UITestCase): # The cursor is on text without metadata self.assertEqual(1, len(xListBox.getChild('0').getChildren())) self.assertEqual("Default Paragraph Style ", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text']) - self.assertEqual(157, len(xListBox.getChild('0').getChild('0').getChildren())) + self.assertEqual(158, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(0, len(xListBox.getChild('1').getChildren())) self.assertEqual(0, len(xListBox.getChild('2').getChildren())) self.assertEqual(0, len(xListBox.getChild('3').getChildren())) @@ -224,7 +224,7 @@ class styleNavigator(UITestCase): # The cursor is on text with paragraph metadata showed under direct paragraph formatting self.assertEqual(1, len(xListBox.getChild('1').getChildren())) self.assertEqual("Default Paragraph Style ", get_state_as_dict(xListBox.getChild('1').getChild('0'))['Text']) - self.assertEqual(157, len(xListBox.getChild('1').getChild('0').getChildren())) + self.assertEqual(158, len(xListBox.getChild('1').getChild('0').getChildren())) # Outer bookmark xBookmarkFormatting = xListBox.getChild('0') @@ -271,7 +271,7 @@ class styleNavigator(UITestCase): # The cursor is on text without metadata self.assertEqual(1, len(xListBox.getChild('0').getChildren())) self.assertEqual("Default Paragraph Style ", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text']) - self.assertEqual(157, len(xListBox.getChild('0').getChild('0').getChildren())) + self.assertEqual(158, len(xListBox.getChild('0').getChild('0').getChildren())) self.assertEqual(0, len(xListBox.getChild('1').getChildren())) self.assertEqual(0, len(xListBox.getChild('2').getChildren())) diff --git a/sw/qa/uitest/styleInspector/tdf137513.py b/sw/qa/uitest/styleInspector/tdf137513.py index de29a3be0588..b499dd5bc5e1 100644 --- a/sw/qa/uitest/styleInspector/tdf137513.py +++ b/sw/qa/uitest/styleInspector/tdf137513.py @@ -35,7 +35,7 @@ class tdf137513(UITestCase): self.assertEqual(2, len(xListBox.getChild('0').getChildren())) self.assertEqual("Default Paragraph Style ", get_state_as_dict(xListBox.getChild('0').getChild('0'))['Text']) self.assertEqual("Table Contents ", get_state_as_dict(xListBox.getChild('0').getChild('1'))['Text']) - self.assertEqual(157, len(xListBox.getChild('0').getChild('0').getChildren())) + self.assertEqual(158, len(xListBox.getChild('0').getChild('0').getChildren())) xTableContent = xListBox.getChild('0').getChild('1') self.assertEqual(5, len(xTableContent.getChildren())) diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx index 9ceb9195a425..c7fd89b47244 100644 --- a/sw/source/core/bastyp/init.cxx +++ b/sw/source/core/bastyp/init.cxx @@ -55,6 +55,7 @@ #include <editeng/lspcitem.hxx> #include <editeng/nhypitem.hxx> #include <editeng/opaqitem.hxx> +#include <editeng/opticalsizingitem.hxx> #include <editeng/orphitem.hxx> #include <editeng/paravertalignitem.hxx> #include <editeng/pbinitem.hxx> @@ -332,6 +333,7 @@ std::unique_ptr<ItemInfoPackage> createItemInfoPackageSwAttributes() { RES_CHRATR_BIDIRTL, new SfxInt16Item( RES_CHRATR_BIDIRTL, sal_Int16(-1) ), 0, SFX_ITEMINFOFLAG_NONE }, { RES_CHRATR_UNUSED3, new SfxVoidItem( RES_CHRATR_UNUSED3 ), 0, SFX_ITEMINFOFLAG_NONE }, { RES_CHRATR_SCRIPT_HINT, new SvxScriptHintItem( RES_CHRATR_SCRIPT_HINT ), SID_ATTR_CHAR_SCRIPT_HINT, SFX_ITEMINFOFLAG_NONE }, + { RES_CHRATR_OPTICAL_SIZING, new SvxOpticalSizingItem( false, RES_CHRATR_OPTICAL_SIZING ), SID_ATTR_CHAR_OPTICAL_SIZING, SFX_ITEMINFOFLAG_NONE }, { RES_TXTATR_REFMARK, new SwFormatRefMark( SwMarkName() ), 0, SFX_ITEMINFOFLAG_NONE }, { RES_TXTATR_TOXMARK, createSwTOXMarkForItemInfoPackage(), 0, SFX_ITEMINFOFLAG_NONE }, diff --git a/sw/source/core/doc/DocumentStylePoolManager.cxx b/sw/source/core/doc/DocumentStylePoolManager.cxx index 4b1667a37f05..17ddfbeb49d3 100644 --- a/sw/source/core/doc/DocumentStylePoolManager.cxx +++ b/sw/source/core/doc/DocumentStylePoolManager.cxx @@ -57,6 +57,7 @@ #include <editeng/charrotateitem.hxx> #include <editeng/emphasismarkitem.hxx> #include <editeng/scriptspaceitem.hxx> +#include <editeng/opticalsizingitem.hxx> #include <o3tl/unit_conversion.hxx> #include <svx/strings.hrc> #include <svx/dialmgr.hxx> diff --git a/sw/source/core/doc/dbgoutsw.cxx b/sw/source/core/doc/dbgoutsw.cxx index 9b739d2575aa..08049eec18b0 100644 --- a/sw/source/core/doc/dbgoutsw.cxx +++ b/sw/source/core/doc/dbgoutsw.cxx @@ -126,6 +126,7 @@ static std::map<sal_uInt16,OUString> & GetItemWhichMap() { RES_CHRATR_HIDDEN , "CHRATR_HIDDEN" }, { RES_CHRATR_BOX , "CHRATR_BOX" }, { RES_CHRATR_SHADOW , "CHRATR_SHADOW" }, + { RES_CHRATR_OPTICAL_SIZING , "CHRATR_OPTICAL_SIZING" }, { RES_TXTATR_AUTOFMT , "TXTATR_AUTOFMT" }, { RES_TXTATR_INETFMT , "TXTATR_INETFMT" }, { RES_TXTATR_REFMARK , "TXTATR_REFMARK" }, diff --git a/sw/source/core/inc/swfntcch.hxx b/sw/source/core/inc/swfntcch.hxx index 43c4c0e43e80..6bb893ca0edb 100644 --- a/sw/source/core/inc/swfntcch.hxx +++ b/sw/source/core/inc/swfntcch.hxx @@ -18,7 +18,7 @@ */ #pragma once -#define NUM_DEFAULT_VALUES 40 +#define NUM_DEFAULT_VALUES 41 #include "swfont.hxx" diff --git a/sw/source/core/inc/swfont.hxx b/sw/source/core/inc/swfont.hxx index a99fdb6fc3a6..afe346863acc 100644 --- a/sw/source/core/inc/swfont.hxx +++ b/sw/source/core/inc/swfont.hxx @@ -103,6 +103,7 @@ class SwSubFont final : public SvxFont inline void SetWordLineMode( const bool bWordLineMode ); inline void SetEmphasisMark( const FontEmphasisMark eValue ); inline void SetRelief( const FontRelief eNew ); + inline void SetOpticalSizing( bool bOpticalSizing ); // methods for sub-/superscript inline void SetEscapement( const short nNewEsc ); @@ -235,6 +236,7 @@ public: inline void SetFixKerning( const short nNewKern ); inline void SetCaseMap( const SvxCaseMap eNew ); inline void SetEmphasisMark( const FontEmphasisMark eValue ); + inline void SetOpticalSizing( bool bOpticalSizing ); // methods for sub-/superscript inline void SetEscapement( const short nNewEsc ); @@ -707,6 +709,20 @@ inline void SwFont::SetEmphasisMark( const FontEmphasisMark eValue ) m_aSub[SwFontScript::CTL].SetEmphasisMark( eValue ); } +inline void SwSubFont::SetOpticalSizing( bool bOpticalSizing ) +{ + m_nFontCacheId = nullptr; + Font::SetOpticalSizing( bOpticalSizing ); +} + +inline void SwFont::SetOpticalSizing( bool bOpticalSizing ) +{ + m_bFontChg = true; + m_aSub[SwFontScript::Latin].SetOpticalSizing( bOpticalSizing ); + m_aSub[SwFontScript::CJK].SetOpticalSizing( bOpticalSizing ); + m_aSub[SwFontScript::CTL].SetOpticalSizing( bOpticalSizing ); +} + inline void SwFont::SetPropWidth( const sal_uInt16 nNew ) { if( nNew != m_aSub[SwFontScript::Latin].GetPropWidth() ) diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index f28276de6c93..b3afcb4999cd 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -2622,6 +2622,7 @@ void SwContentFrame::UpdateAttr_( const SfxPoolItem* pOld, const SfxPoolItem* pN case RES_CHRATR_ESCAPEMENT: case RES_CHRATR_CONTOUR: case RES_CHRATR_NOHYPHEN: + case RES_CHRATR_OPTICAL_SIZING: case RES_PARATR_NUMRULE: rInvFlags |= SwContentFrameInvFlags::SetCompletePaint; break; diff --git a/sw/source/core/text/atrhndl.hxx b/sw/source/core/text/atrhndl.hxx index 979b99800124..f4ebc728ce7d 100644 --- a/sw/source/core/text/atrhndl.hxx +++ b/sw/source/core/text/atrhndl.hxx @@ -18,7 +18,7 @@ */ #pragma once -#define NUM_ATTRIBUTE_STACKS 46 +#define NUM_ATTRIBUTE_STACKS 47 #include <vector> #include <swfntcch.hxx> diff --git a/sw/source/core/text/atrstck.cxx b/sw/source/core/text/atrstck.cxx index 1d8c0ba479f5..caf108486f09 100644 --- a/sw/source/core/text/atrstck.cxx +++ b/sw/source/core/text/atrstck.cxx @@ -44,6 +44,7 @@ #include <editeng/boxitem.hxx> #include <editeng/nhypitem.hxx> #include <editeng/shaditem.hxx> +#include <editeng/opticalsizingitem.hxx> #include <viewopt.hxx> #include <charfmt.hxx> #include <fchrfmt.hxx> @@ -115,18 +116,19 @@ const sal_uInt8 StackPos[ RES_TXTATR_WITHEND_END - RES_CHRATR_BEGIN + 1 ] = 0, // RES_CHRATR_GRABBAG, // 43 0, // RES_CHRATR_BIDIRTL, // 44 0, // RES_CHRATR_UNUSED3, // 45 - 39, // RES_CHRATR_SCRIPT_HINT, // 46 - 40, // RES_TXTATR_REFMARK, // 47 - 41, // RES_TXTATR_TOXMARK, // 48 - 42, // RES_TXTATR_META, // 49 - 42, // RES_TXTATR_METAFIELD, // 50 + 39, // RES_CHRATR_SCRIPT_HINT, // 45 + 40, // RES_CHRATR_OPTICAL_SIZING // 46 + 41, // RES_TXTATR_REFMARK, // 47 + 42, // RES_TXTATR_TOXMARK, // 48 + 43, // RES_TXTATR_META, // 49 + 43, // RES_TXTATR_METAFIELD, // 50 0, // RES_TXTATR_AUTOFMT, // 51 0, // RES_TXTATR_INETFMT // 52 0, // RES_TXTATR_CHARFMT, // 53 - 43, // RES_TXTATR_CJK_RUBY, // 54 + 44, // RES_TXTATR_CJK_RUBY, // 54 0, // RES_TXTATR_UNKNOWN_CONTAINER, // 55 - 44, // RES_TXTATR_INPUTFIELD // 56 - 45, // RES_TXTATR_CONTENTCONTROL // 57 + 45, // RES_TXTATR_INPUTFIELD // 56 + 46, // RES_TXTATR_CONTENTCONTROL // 57 }; namespace CharFormat @@ -831,6 +833,9 @@ void SwAttrHandler::FontChg(const SfxPoolItem& rItem, SwFont& rFnt, bool bPush ) rFnt.SetVertical(m_pDefaultArray[ nRotateStack ]->StaticWhichCast(RES_CHRATR_ROTATE).GetValue(), m_bVertLayout); break; } + case RES_CHRATR_OPTICAL_SIZING : + rFnt.SetOpticalSizing( rItem.StaticWhichCast(RES_CHRATR_OPTICAL_SIZING).GetValue() ); + break; case RES_TXTATR_CJK_RUBY : rFnt.SetVertical( 0_deg10, m_bVertLayout ); break; diff --git a/sw/source/core/txtnode/swfont.cxx b/sw/source/core/txtnode/swfont.cxx index ef33a4e6bae8..e7cc710827af 100644 --- a/sw/source/core/txtnode/swfont.cxx +++ b/sw/source/core/txtnode/swfont.cxx @@ -665,6 +665,8 @@ void SwFont::SetDiffFnt( const SfxItemSet *pAttrSet, const SvxTwoLinesItem* pTwoLinesItem = pAttrSet->GetItemIfSet( RES_CHRATR_TWO_LINES ); if( pTwoLinesItem && pTwoLinesItem->GetValue() ) SetVertical( 0_deg10 ); + if( const SvxOpticalSizingItem* pItem = pAttrSet->GetItemIfSet( RES_CHRATR_OPTICAL_SIZING ) ) + SetOpticalSizing( pItem->GetValue() ); } else { @@ -854,6 +856,7 @@ SwFont::SwFont( const SwAttrSet* pAttrSet, m_aSub[ SwFontScript::CJK ].m_bSmallCapsPercentage66 = true; m_aSub[ SwFontScript::CTL ].m_bSmallCapsPercentage66 = true; } + SetOpticalSizing( pAttrSet->GetOpticalSizing().GetValue() ); } SwFont::~SwFont() diff --git a/sw/source/core/unocore/unomap1.cxx b/sw/source/core/unocore/unomap1.cxx index 184c46aafb98..d73181f1157a 100644 --- a/sw/source/core/unocore/unomap1.cxx +++ b/sw/source/core/unocore/unomap1.cxx @@ -206,6 +206,7 @@ std::span<const SfxItemPropertyMapEntry> SwUnoPropertyMapProvider::GetCharStyleP { UNO_NAME_CHAR_OVERLINE_HAS_COLOR, RES_CHRATR_OVERLINE , cppu::UnoType<bool>::get(), PROPERTY_NONE, MID_TL_HASCOLOR}, { UNO_NAME_CHAR_KERNING, RES_CHRATR_KERNING , cppu::UnoType<sal_Int16>::get() , PROPERTY_NONE, CONVERT_TWIPS}, { UNO_NAME_CHAR_NO_HYPHENATION, RES_CHRATR_NOHYPHEN , cppu::UnoType<bool>::get() , PROPERTY_NONE, 0}, + { UNO_NAME_CHAR_OPTICAL_SIZING, RES_CHRATR_OPTICAL_SIZING , cppu::UnoType<bool>::get() , PROPERTY_NONE, 0}, { UNO_NAME_CHAR_SHADOWED, RES_CHRATR_SHADOWED , cppu::UnoType<bool>::get() , PROPERTY_NONE, 0}, { UNO_NAME_CHAR_CONTOURED, RES_CHRATR_CONTOUR, cppu::UnoType<bool>::get() , PROPERTY_NONE, 0}, { UNO_NAME_CHAR_WORD_MODE, RES_CHRATR_WORDLINEMODE,cppu::UnoType<bool>::get() , PROPERTY_NONE, 0}, @@ -278,6 +279,7 @@ std::span<const SfxItemPropertyMapEntry> SwUnoPropertyMapProvider::GetAutoCharS { UNO_NAME_CHAR_OVERLINE_HAS_COLOR, RES_CHRATR_OVERLINE , cppu::UnoType<bool>::get(), PROPERTY_NONE, MID_TL_HASCOLOR}, { UNO_NAME_CHAR_KERNING, RES_CHRATR_KERNING , cppu::UnoType<sal_Int16>::get() , PROPERTY_NONE, CONVERT_TWIPS}, { UNO_NAME_CHAR_NO_HYPHENATION, RES_CHRATR_NOHYPHEN , cppu::UnoType<bool>::get() , PROPERTY_NONE, 0}, + { UNO_NAME_CHAR_OPTICAL_SIZING, RES_CHRATR_OPTICAL_SIZING , cppu::UnoType<bool>::get() , PROPERTY_NONE, 0}, { UNO_NAME_CHAR_SHADOWED, RES_CHRATR_SHADOWED , cppu::UnoType<bool>::get() , PROPERTY_NONE, 0}, { UNO_NAME_CHAR_CONTOURED, RES_CHRATR_CONTOUR, cppu::UnoType<bool>::get() , PROPERTY_NONE, 0}, { UNO_NAME_CHAR_WORD_MODE, RES_CHRATR_WORDLINEMODE,cppu::UnoType<bool>::get() , PROPERTY_NONE, 0}, diff --git a/sw/source/core/unocore/unomapproperties.hxx b/sw/source/core/unocore/unomapproperties.hxx index 62fa63945d35..015c08af042b 100644 --- a/sw/source/core/unocore/unomapproperties.hxx +++ b/sw/source/core/unocore/unomapproperties.hxx @@ -172,6 +172,7 @@ CTL_FONT_PROPERTIES \ { UNO_NAME_CHAR_KERNING, RES_CHRATR_KERNING, cppu::UnoType<sal_Int16>::get(), PropertyAttribute::MAYBEVOID, CONVERT_TWIPS }, \ { UNO_NAME_CHAR_NO_HYPHENATION, RES_CHRATR_NOHYPHEN, cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID, 0 }, \ + { UNO_NAME_CHAR_OPTICAL_SIZING, RES_CHRATR_OPTICAL_SIZING, cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID, 0 }, \ { UNO_NAME_CHAR_SHADOWED, RES_CHRATR_SHADOWED, cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID, 0 }, \ { UNO_NAME_CHAR_CONTOURED, RES_CHRATR_CONTOUR, cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID, 0 }, \ { UNO_NAME_DROP_CAP_FORMAT, RES_PARATR_DROP, cppu::UnoType<css::style::DropCapFormat>::get(), PropertyAttribute::MAYBEVOID, MID_DROPCAP_FORMAT | CONVERT_TWIPS }, \ @@ -446,6 +447,7 @@ { UNO_NAME_PARA_FIRST_LINE_INDENT_RELATIVE, RES_MARGIN_FIRSTLINE, cppu::UnoType<sal_Int32>::get(), PROPERTY_NONE, MID_FIRST_LINE_REL_INDENT|CONVERT_TWIPS},\ { UNO_NAME_CHAR_KERNING, RES_CHRATR_KERNING , cppu::UnoType<sal_Int16>::get() , PROPERTY_NONE, CONVERT_TWIPS},\ { UNO_NAME_CHAR_NO_HYPHENATION, RES_CHRATR_NOHYPHEN , cppu::UnoType<bool>::get() , PROPERTY_NONE, 0},\ + { UNO_NAME_CHAR_OPTICAL_SIZING, RES_CHRATR_OPTICAL_SIZING , cppu::UnoType<bool>::get() , PROPERTY_NONE, 0},\ { UNO_NAME_CHAR_SHADOWED, RES_CHRATR_SHADOWED , cppu::UnoType<bool>::get() , PROPERTY_NONE, 0},\ { UNO_NAME_CHAR_CONTOURED, RES_CHRATR_CONTOUR, cppu::UnoType<bool>::get() , PROPERTY_NONE, 0},\ { UNO_NAME_DROP_CAP_FORMAT, RES_PARATR_DROP, cppu::UnoType<css::style::DropCapFormat>::get() , PROPERTY_NONE, MID_DROPCAP_FORMAT|CONVERT_TWIPS },\ diff --git a/sw/source/filter/html/css1atr.cxx b/sw/source/filter/html/css1atr.cxx index 42e884c1b2eb..6f80bb53ff47 100644 --- a/sw/source/filter/html/css1atr.cxx +++ b/sw/source/filter/html/css1atr.cxx @@ -3465,6 +3465,7 @@ SwAttrFnTab const aCSS1AttrFnTab = { /* RES_CHRATR_BIDIRTL */ nullptr, /* RES_CHRATR_UNUSED3 */ nullptr, /* RES_CHRATR_SCRIPT_HINT */ nullptr, +/* RES_CHRATR_OPTICAL_SIZING */ nullptr, /* RES_TXTATR_REFMARK */ nullptr, /* RES_TXTATR_TOXMARK */ nullptr, diff --git a/sw/source/filter/html/htmlatr.cxx b/sw/source/filter/html/htmlatr.cxx index 1a5076dc1fa3..d917fea69094 100644 --- a/sw/source/filter/html/htmlatr.cxx +++ b/sw/source/filter/html/htmlatr.cxx @@ -3316,6 +3316,7 @@ const SwAttrFnTab aHTMLAttrFnTab = { /* RES_CHRATR_BIDIRTL */ nullptr, /* RES_CHRATR_UNUSED3 */ nullptr, /* RES_CHRATR_SCRIPT_HINT */ nullptr, +/* RES_CHRATR_OPTICAL_SIZING */ nullptr, /* RES_TXTATR_REFMARK */ nullptr, /* RES_TXTATR_TOXMARK */ nullptr, diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx index 2d46bef3842b..2f4000819959 100644 --- a/sw/source/filter/ww8/attributeoutputbase.hxx +++ b/sw/source/filter/ww8/attributeoutputbase.hxx @@ -48,6 +48,7 @@ class SvxShadowedItem; class SvxUnderlineItem; class SvxWeightItem; class SvxAutoKernItem; +class SvxOpticalSizingItem; class SvxBlinkItem; class SvxBrushItem; class XFillStyleItem; @@ -399,6 +400,9 @@ protected: /// Sfx item RES_CHRATR_AUTOKERN virtual void CharAutoKern( const SvxAutoKernItem& ) = 0; + /// Sfx item RES_CHRATR_OPTICAL_SIZING + virtual void CharOpticalSizing( const SvxOpticalSizingItem& ) = 0; + /// Sfx item RES_CHRATR_BLINK virtual void CharAnimatedText( const SvxBlinkItem& ) = 0; diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 8b6554c83128..2c29bffb408f 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -56,6 +56,7 @@ #include <oox/export/drawingml.hxx> #include <editeng/autokernitem.hxx> +#include <editeng/opticalsizingitem.hxx> #include <editeng/unoprnms.hxx> #include <editeng/fontitem.hxx> #include <editeng/tstpitem.hxx> @@ -5263,6 +5264,9 @@ void DocxAttributeOutput::OutputDefaultItem(const SfxPoolItem& rHt) case RES_CHRATR_AUTOKERN: bMustWrite = rHt.StaticWhichCast(RES_CHRATR_AUTOKERN).GetValue(); break; + case RES_CHRATR_OPTICAL_SIZING: + bMustWrite = rHt.StaticWhichCast(RES_CHRATR_OPTICAL_SIZING).GetValue(); + break; case RES_CHRATR_BLINK: bMustWrite = rHt.StaticWhichCast(RES_CHRATR_BLINK).GetValue(); break; @@ -8400,6 +8404,11 @@ void DocxAttributeOutput::CharAutoKern( const SvxAutoKernItem& rAutoKern ) m_pSerializer->singleElementNS(XML_w, XML_kern, FSNS(XML_w, XML_val), sFontSize); } +void DocxAttributeOutput::CharOpticalSizing( const SvxOpticalSizingItem& ) +{ + // MSOffice has no equivalent for optical sizing, so nothing is exported. +} + void DocxAttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink ) { if ( rBlink.GetValue() ) diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index d23d191b92b0..6156821d47cf 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -586,6 +586,9 @@ protected: /// Sfx item RES_CHRATR_AUTOKERN virtual void CharAutoKern( const SvxAutoKernItem& ) override; + /// Sfx item RES_CHRATR_OPTICAL_SIZING + virtual void CharOpticalSizing( const SvxOpticalSizingItem& ) override; + /// Sfx item RES_CHRATR_BLINK virtual void CharAnimatedText( const SvxBlinkItem& rBlink ) override; diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx index e4051aa159f9..9e1c91879c31 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.cxx +++ b/sw/source/filter/ww8/rtfattributeoutput.cxx @@ -49,6 +49,7 @@ #include <editeng/contouritem.hxx> #include <editeng/shdditem.hxx> #include <editeng/autokernitem.hxx> +#include <editeng/opticalsizingitem.hxx> #include <editeng/emphasismarkitem.hxx> #include <editeng/twolinesitem.hxx> #include <editeng/charscaleitem.hxx> @@ -516,6 +517,9 @@ void RtfAttributeOutput::OutputFormattingItem(const SfxPoolItem& item, OStringBu case RES_CHRATR_AUTOKERN: OutputCharAutoKern(item.StaticWhichCast(RES_CHRATR_AUTOKERN), buf); break; + case RES_CHRATR_OPTICAL_SIZING: + OutputCharOpticalSizing(item.StaticWhichCast(RES_CHRATR_OPTICAL_SIZING), buf); + break; case RES_CHRATR_BLINK: OutputCharAnimatedText(item.StaticWhichCast(RES_CHRATR_BLINK), buf); break; @@ -3205,12 +3209,22 @@ void RtfAttributeOutput::CharAutoKern(const SvxAutoKernItem& rAutoKern) m_aCharFormatting.Put(rAutoKern); } +void RtfAttributeOutput::CharOpticalSizing(const SvxOpticalSizingItem& rOpticalSizing) +{ + m_aCharFormatting.Put(rOpticalSizing); +} + void RtfAttributeOutput::OutputCharAutoKern(const SvxAutoKernItem& rAutoKern, OStringBuffer& buf) { buf.append(OOO_STRING_SVTOOLS_RTF_KERNING); buf.append(static_cast<sal_Int32>(rAutoKern.GetValue() ? 1 : 0)); } +void RtfAttributeOutput::OutputCharOpticalSizing(const SvxOpticalSizingItem&, OStringBuffer&) +{ + // MSOffice has no equivalent for optical sizing, so nothing is exported. +} + void RtfAttributeOutput::CharAnimatedText(const SvxBlinkItem& rBlink) { m_aCharFormatting.Put(rBlink); diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx index 289773a1477d..8d6aeabe2c5c 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.hxx +++ b/sw/source/filter/ww8/rtfattributeoutput.hxx @@ -301,6 +301,9 @@ protected: /// Sfx item RES_CHRATR_AUTOKERN void CharAutoKern(const SvxAutoKernItem& rAutoKern) override; + /// Sfx item RES_CHRATR_OPTICAL_SIZING + void CharOpticalSizing(const SvxOpticalSizingItem& rOpticalSizing) override; + /// Sfx item RES_CHRATR_BLINK void CharAnimatedText(const SvxBlinkItem& rBlink) override; @@ -554,6 +557,8 @@ private: bool assoc) const; static void OutputCharWeightAssoc(const SvxWeightItem& rWeight, OStringBuffer& buf, bool assoc); static void OutputCharAutoKern(const SvxAutoKernItem& rAutoKern, OStringBuffer& buf); + static void OutputCharOpticalSizing(const SvxOpticalSizingItem& rOpticalSizing, + OStringBuffer& buf); static void OutputCharAnimatedText(const SvxBlinkItem& rBlink, OStringBuffer& buf); void OutputCharBackground(const SvxBrushItem& rBrush, OStringBuffer& buf) const; static void OutputCharRotate(const SvxCharRotateItem& rRotate, OStringBuffer& buf); diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx index 8a5878dc49e4..6202a36d15e6 100644 --- a/sw/source/filter/ww8/ww8atr.cxx +++ b/sw/source/filter/ww8/ww8atr.cxx @@ -64,6 +64,7 @@ #include <editeng/contouritem.hxx> #include <editeng/shdditem.hxx> #include <editeng/autokernitem.hxx> +#include <editeng/opticalsizingitem.hxx> #include <editeng/pbinitem.hxx> #include <editeng/emphasismarkitem.hxx> #include <editeng/twolinesitem.hxx> @@ -1316,6 +1317,11 @@ void WW8AttributeOutput::CharAutoKern( const SvxAutoKernItem& rAutoKern ) m_rWW8Export.InsUInt16( rAutoKern.GetValue() ? 2 : 0 ); } +void WW8AttributeOutput::CharOpticalSizing( const SvxOpticalSizingItem& ) +{ + // MSOffice has no equivalent for optical sizing, so nothing is exported. +} + void WW8AttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink ) { m_rWW8Export.InsUInt16( NS_sprm::CSfxText::val ); @@ -5772,6 +5778,9 @@ void AttributeOutputBase::OutputItem( const SfxPoolItem& rHt ) case RES_CHRATR_AUTOKERN: CharAutoKern(rHt.StaticWhichCast(RES_CHRATR_AUTOKERN)); break; + case RES_CHRATR_OPTICAL_SIZING: + CharOpticalSizing(rHt.StaticWhichCast(RES_CHRATR_OPTICAL_SIZING)); + break; case RES_CHRATR_BLINK: CharAnimatedText(rHt.StaticWhichCast(RES_CHRATR_BLINK)); break; diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx b/sw/source/filter/ww8/ww8attributeoutput.hxx index 501959b546d7..7c1ef75cdd06 100644 --- a/sw/source/filter/ww8/ww8attributeoutput.hxx +++ b/sw/source/filter/ww8/ww8attributeoutput.hxx @@ -252,6 +252,9 @@ protected: /// Sfx item RES_CHRATR_AUTOKERN virtual void CharAutoKern( const SvxAutoKernItem& ) override; + /// Sfx item RES_CHRATR_OPTICAL_SIZING + virtual void CharOpticalSizing( const SvxOpticalSizingItem& ) override; + /// Sfx item RES_CHRATR_BLINK virtual void CharAnimatedText( const SvxBlinkItem& ) override; diff --git a/sw/source/uibase/app/docshini.cxx b/sw/source/uibase/app/docshini.cxx index 4c24c8706c9c..f7a19b3e72e5 100644 --- a/sw/source/uibase/app/docshini.cxx +++ b/sw/source/uibase/app/docshini.cxx @@ -47,6 +47,7 @@ #include <editeng/orphitem.hxx> #include <editeng/widwitem.hxx> #include <editeng/hyphenzoneitem.hxx> +#include <editeng/opticalsizingitem.hxx> #include <vcl/metric.hxx> #include <vcl/rendercontext/GetDefaultFontFlags.hxx> #include <vcl/svapp.hxx> @@ -302,6 +303,9 @@ bool SwDocShell::InitNew( const uno::Reference < embed::XStorage >& xStor ) //#i16874# AutoKerning as default for new documents m_xDoc->SetDefault( SvxAutoKernItem( true, RES_CHRATR_AUTOKERN ) ); + // tdf#153368 Optical sizing as default for new documents + m_xDoc->SetDefault( SvxOpticalSizingItem( true, RES_CHRATR_OPTICAL_SIZING ) ); + // #i42080# - Due to the several calls of method <SetDefault(..)> // at the document instance, the document is modified. Thus, reset this // status here. Note: In method <SubInitNew()> this is also done. diff --git a/vcl/qa/cppunit/pdfexport/data/testOpticalSizing.odt b/vcl/qa/cppunit/pdfexport/data/testOpticalSizing.odt new file mode 100644 index 000000000000..cb9130423caa Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/testOpticalSizing.odt differ diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx index cc42c417c5b5..3789f713dc4e 100644 --- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx +++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx @@ -2167,6 +2167,44 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testVariableFontPSName2) #endif } +// This test docuemnt embeds a variable font with opsz axis, and sets the text in the same font but +// different point sizes. The font should be embedded multiple times as different instances +// corresponding to the different opsz values. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testOpticalSizing) +{ +// Embedding variable fonts does not work on Linux, only the default instance is enumerated +// https://bugs.documentfoundation.org/show_bug.cgi?id=155853 +#if defined MACOSX || defined _WIN32 + loadFromFile(u"testOpticalSizing.odt"); + save(TestFilter::PDF_WRITER); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + std::set<OString> aFontNames; + for (const auto& aElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(aElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "Font") + { + auto pName + = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("BaseFont"_ostr)); + aFontNames.insert(pName->GetValue().copy(7)); // skip the subset id + } + } + + std::set<OString> aExpected{ "Fraunces_144opsz_400wght"_ostr, "Fraunces_80opsz_400wght"_ostr, + "Fraunces_60opsz_400wght"_ostr, "Fraunces_40opsz_400wght"_ostr, + "Fraunces_20opsz_400wght"_ostr, "Fraunces-Regular"_ostr }; + + CPPUNIT_ASSERT_EQUAL(aExpected, aFontNames); +#endif +} + CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157679) { // Import the bugdoc and export as PDF.
