sc/qa/unit/data/ods/tdf129940.ods |binary sc/qa/unit/subsequent_filters-test.cxx | 21 ++++ sc/source/filter/xml/celltextparacontext.cxx | 120 ++++++++++++++++++++++++--- sc/source/filter/xml/celltextparacontext.hxx | 45 ++++++++++ 4 files changed, 177 insertions(+), 9 deletions(-)
New commits: commit e630da1ed8a27c64bc9f22ecb71afd10bf252d93 Author: Mark Hung <mark...@gmail.com> AuthorDate: Thu Jan 28 22:53:49 2021 +0800 Commit: Mark Hung <mark...@gmail.com> CommitDate: Mon Feb 8 14:07:07 2021 +0100 tdf#129940 handle text:ruby element inside text:p Implement ScXMLCellTextRubyContext for text:ruby. It creates two types of child elements: ScXMLCellRubyBaseContext for text:ruby-base, and ScXMLCellRubyTextContext, for text:ruby-text. Ruby text isn't used now, but can serve for future application. Change-Id: I33b778838032458ffbefc6a2835d2ae59dff30cf Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110088 Tested-by: Jenkins Reviewed-by: Mark Hung <mark...@gmail.com> diff --git a/sc/qa/unit/data/ods/tdf129940.ods b/sc/qa/unit/data/ods/tdf129940.ods new file mode 100644 index 000000000000..5cc5369acd49 Binary files /dev/null and b/sc/qa/unit/data/ods/tdf129940.ods differ diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx index d0553d74e3c4..7e7c62500674 100644 --- a/sc/qa/unit/subsequent_filters-test.cxx +++ b/sc/qa/unit/subsequent_filters-test.cxx @@ -304,6 +304,7 @@ public: void testDeleteCircles(); void testDrawCircleInMergeCells(); void testDeleteCirclesInRowAndCol(); + void testTdf129940(); CPPUNIT_TEST_SUITE(ScFiltersTest); CPPUNIT_TEST(testCondFormatFormulaIsXLSX); @@ -491,6 +492,7 @@ public: CPPUNIT_TEST(testDeleteCircles); CPPUNIT_TEST(testDrawCircleInMergeCells); CPPUNIT_TEST(testDeleteCirclesInRowAndCol); + CPPUNIT_TEST(testTdf129940); CPPUNIT_TEST_SUITE_END(); @@ -5434,6 +5436,25 @@ void ScFiltersTest::testDeleteCirclesInRowAndCol() xDocSh->DoClose(); } +void ScFiltersTest::testTdf129940() +{ + // Test pure span elements inside text:ruby-base + ScDocShellRef xDocSh = loadDoc(u"tdf129940.", FORMAT_ODS); + CPPUNIT_ASSERT_MESSAGE("Failed to load tdf129940.ods", xDocSh.is()); + ScDocument& rDoc = xDocSh->GetDocument(); + // Pure text within text:ruby-base + OUString aStr = rDoc.GetString(ScAddress(0,0,0)); + CPPUNIT_ASSERT_EQUAL(OUString(u"小笠原"), aStr); + aStr = rDoc.GetString(ScAddress(1,0,0)); + CPPUNIT_ASSERT_EQUAL(OUString(u"徳彦"), aStr); + + // Multiple text:span within text:ruby-base + aStr = rDoc.GetString(ScAddress(2,0,0)); + CPPUNIT_ASSERT_EQUAL(OUString(u"注音符號"), aStr); + + xDocSh->DoClose(); +} + ScFiltersTest::ScFiltersTest() : ScBootstrapFixture( "sc/qa/unit/data" ) { diff --git a/sc/source/filter/xml/celltextparacontext.cxx b/sc/source/filter/xml/celltextparacontext.cxx index 8a54d38c2b32..ce7f90651645 100644 --- a/sc/source/filter/xml/celltextparacontext.cxx +++ b/sc/source/filter/xml/celltextparacontext.cxx @@ -60,6 +60,8 @@ uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLCellTextParaContex return new ScXMLCellFieldTitleContext(GetScImport(), *this); case XML_ELEMENT( TEXT, XML_A ): return new ScXMLCellFieldURLContext(GetScImport(), *this); + case XML_ELEMENT( TEXT, XML_RUBY ): + return new ScXMLCellTextRubyContext(GetScImport(), *this); default: ; } @@ -118,10 +120,7 @@ void SAL_CALL ScXMLCellTextSpanContext::startFastElement( sal_Int32 /*nElement*/ void SAL_CALL ScXMLCellTextSpanContext::endFastElement( sal_Int32 /*nElement*/ ) { - if (!maContent.isEmpty()) - { - mrParentCxt.PushSpan(maContent, maStyleName); - } + submitContentAndClear(); } void SAL_CALL ScXMLCellTextSpanContext::characters( const OUString& rChars ) @@ -132,11 +131,7 @@ void SAL_CALL ScXMLCellTextSpanContext::characters( const OUString& rChars ) uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLCellTextSpanContext::createFastChildContext( sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) { - if (!maContent.isEmpty()) - { - mrParentCxt.PushSpan(maContent, maStyleName); - maContent.clear(); - } + submitContentAndClear(); switch (nElement) { @@ -177,6 +172,15 @@ uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLCellTextSpanContex return nullptr; } +void ScXMLCellTextSpanContext::submitContentAndClear() +{ + if (!maContent.isEmpty()) + { + mrParentCxt.PushSpan(maContent, maStyleName); + maContent.clear(); + } +} + ScXMLCellFieldSheetNameContext::ScXMLCellFieldSheetNameContext( ScXMLImport& rImport, ScXMLCellTextParaContext& rParent) : ScXMLImportContext(rImport), @@ -337,4 +341,102 @@ void ScXMLCellFieldSContext::PushSpaces() } } +ScXMLCellTextRubyContext::ScXMLCellTextRubyContext( + ScXMLImport& rImport, ScXMLCellTextParaContext& rParent) : + ScXMLImportContext(rImport), + mrParentCxt(rParent) +{ +} + +void SAL_CALL ScXMLCellTextRubyContext::startFastElement( sal_Int32 /*nElement*/, + const uno::Reference< xml::sax::XFastAttributeList >& xAttrList ) +{ + for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList )) + { + switch (aIter.getToken()) + { + case XML_ELEMENT( TEXT, XML_STYLE_NAME ): + // This is ruby style instead of text style. + maRubyStyleName = aIter.toString(); + break; + default: + ; + } + } +} + +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLCellTextRubyContext::createFastChildContext( + sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) +{ + + switch (nElement) + { + case XML_ELEMENT( TEXT, XML_RUBY_BASE ): + { + ScXMLCellRubyBaseContext* p = new ScXMLCellRubyBaseContext(GetScImport(), mrParentCxt); + return p; + } + case XML_ELEMENT( TEXT, XML_RUBY_TEXT ): + { + ScXMLCellRubyTextContext* p = new ScXMLCellRubyTextContext(GetScImport(), maRubyText, maRubyTextStyle); + return p; + } + default: + ; + } + + return nullptr; +} + +ScXMLCellRubyBaseContext::ScXMLCellRubyBaseContext( + ScXMLImport& rImport, ScXMLCellTextParaContext& rParent) : + ScXMLCellTextSpanContext( rImport, rParent), + mrParentCxt(rParent) +{ +} + +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLCellRubyBaseContext::createFastChildContext( + sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) +{ + submitContentAndClear(); + + switch (nElement) + { + case XML_ELEMENT( TEXT, XML_SPAN ): + return new ScXMLCellTextSpanContext(GetScImport(), mrParentCxt); + default: + ; + } + return nullptr; +} + +ScXMLCellRubyTextContext::ScXMLCellRubyTextContext( + ScXMLImport& rImport, OUString& rRubyText, OUString& rRubyTextStyle) : + ScXMLImportContext(rImport), + mrRubyText(rRubyText), + mrRubyTextStyle(rRubyTextStyle) +{ +} + +void SAL_CALL ScXMLCellRubyTextContext::startFastElement( sal_Int32 /*nElement*/, + const uno::Reference< xml::sax::XFastAttributeList >& xAttrList ) +{ + for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList )) + { + switch (aIter.getToken()) + { + case XML_ELEMENT( TEXT, XML_STYLE_NAME ): + mrRubyTextStyle = aIter.toString(); + break; + default: + ; + } + } +} + +void SAL_CALL ScXMLCellRubyTextContext::characters( const OUString& rChars ) +{ + mrRubyText+= rChars; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/xml/celltextparacontext.hxx b/sc/source/filter/xml/celltextparacontext.hxx index 35a553ce7f9c..3758bdba5bba 100644 --- a/sc/source/filter/xml/celltextparacontext.hxx +++ b/sc/source/filter/xml/celltextparacontext.hxx @@ -54,6 +54,7 @@ public: virtual void SAL_CALL characters( const OUString& aChars ) override; virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override; + void submitContentAndClear(); }; /** @@ -144,6 +145,50 @@ public: sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override; }; +/** + * This context handles <text:ruby> element inside <text:p>. + */ +class ScXMLCellTextRubyContext : public ScXMLImportContext +{ + ScXMLCellTextParaContext& mrParentCxt; + OUString maRubyStyleName; + OUString maRubyTextStyle; + OUString maRubyText; +public: + ScXMLCellTextRubyContext(ScXMLImport& rImport, ScXMLCellTextParaContext& rParent); + + virtual void SAL_CALL startFastElement( sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override; + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override; +}; + +/** + * This context handles <text:ruby-base> element inside <text:ruby>. + */ +class ScXMLCellRubyBaseContext : public ScXMLCellTextSpanContext +{ + ScXMLCellTextParaContext& mrParentCxt; +public: + ScXMLCellRubyBaseContext(ScXMLImport& rImport, ScXMLCellTextParaContext& rParent); + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override; +}; + +/** + * This context handles <text:ruby-text> element inside <text:ruby>. + */ +class ScXMLCellRubyTextContext : public ScXMLImportContext +{ + OUString& mrRubyText; + OUString& mrRubyTextStyle; +public: + ScXMLCellRubyTextContext(ScXMLImport& rImport, OUString& rRubyText, OUString& rRubyTextStyle); + + virtual void SAL_CALL startFastElement( sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override; + virtual void SAL_CALL characters( const OUString& aChars ) override; +}; #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits