summaryrefslogtreecommitdiff
path: root/writerfilter/source/dmapper
diff options
context:
space:
mode:
authorLászló Németh <nemeth@numbertext.org>2020-02-17 14:34:11 +0100
committerLászló Németh <nemeth@numbertext.org>2020-02-19 16:46:18 +0100
commit4d5c0eaf3e0d3d3bcd9e691fffee19b75f3d6631 (patch)
tree6ed8e4a013884c28db01b9175dfc933141b7c395 /writerfilter/source/dmapper
parentfaa2e7b7227b6b87379e7e136ea9ab63f37c3fc4 (diff)
tdf#118812 DOCX import: fix table style preference – part 2
Apply table styles according to OOXML and – in the case of font sizes – MSO exception "overrideTableStyleFontSizeAndJustification". Fix temporary regression in styles of paragraph portions, table cell regions and nested tables from commit f15d67442972c5f69c71925a6bfa5aa1a39d54eb (tdf#129575 DOCX import: fix table style preference). Unit test document was created by Justin Luth. Change-Id: I7b076ac27f5b44d44934b7efb18ac4a878f8b596 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88869 Tested-by: Jenkins Reviewed-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'writerfilter/source/dmapper')
-rw-r--r--writerfilter/source/dmapper/DomainMapperTableHandler.cxx150
-rw-r--r--writerfilter/source/dmapper/DomainMapperTableHandler.hxx11
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx8
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx7
4 files changed, 123 insertions, 53 deletions
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index ab51d4fdd48d..d02e26abf96e 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -28,6 +28,10 @@
#include <com/sun/star/text/RelOrientation.hpp>
#include <com/sun/star/text/SizeType.hpp>
#include <com/sun/star/text/XTextRangeCompare.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
#include "TablePositionHandler.hxx"
#include "ConversionHelper.hxx"
#include "util.hxx"
@@ -1066,59 +1070,65 @@ css::uno::Sequence<css::beans::PropertyValues> DomainMapperTableHandler::endTabl
// table style has got bigger precedence than docDefault style,
// but lower precedence than the paragraph styles and direct paragraph formatting
-void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableInfo & rInfo)
+void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableParagraph rParaProp, std::vector< PropertyIds > aAllTableParaProperties, css::beans::PropertyValues rCellProperties)
{
- for( auto const& eId : rInfo.aTablePropertyIds )
+ for( auto const& eId : aAllTableParaProperties )
{
// apply paragraph and character properties of the table style on table paragraphs
- if ( isParagraphProperty(eId) || isCharacterProperty(eId) )
+ // if there is no direct paragraph formatting
+ if ( !rParaProp.m_pPropertyMap->isSet(eId) )
{
- // check all paragraphs of the table
- for (const auto& rParaProp : m_rDMapper_Impl.m_aParagraphsToEndTable)
+ OUString sPropertyName = getPropertyName(eId);
+ auto pCellProp = std::find_if(rCellProperties.begin(), rCellProperties.end(),
+ [&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; });
+ // this cell applies the table style property
+ if (pCellProp != rCellProperties.end())
{
- // there is no direct paragraph formatting
- if (!rParaProp.m_pPropertyMap->isSet(eId))
+ bool bDocDefault;
+ OUString sParaStyleName;
+ rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName;
+ StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName);
+ uno::Any aParaStyle = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true, &bDocDefault);
+ // use table style when no paragraph style setting or a docDefault value is applied instead of it
+ if ( aParaStyle == uno::Any() || bDocDefault ||
+ // set default behaviour of MSO ("overrideTableStyleFontSizeAndJustification" exception):
+ // if Normal style defines 11 pt or 12 pt font heights, table style overrides its font size
+ (eId == PROP_CHAR_HEIGHT && sParaStyleName == "Standard" && (aParaStyle == uno::Any(double(11)) || aParaStyle == uno::Any(double(12))))) try
{
- bool bDocDefault;
- OUString sParaStyleName;
- rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName;
- StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName);
- uno::Any aParaStyle = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true, &bDocDefault);
- // use table style when a docDefault value is applied instead of it,
- // and there is no associated TableStyleSheetEntry
- // TODO: replace CNF_ALL with the actual mask
- if ( (aParaStyle == uno::Any() || bDocDefault) && !rInfo.pTableStyle->GetProperties(CNF_ALL)->getProperty(eId) )
+ // check property state of paragraph
+ uno::Reference<text::XParagraphCursor> xParagraph(
+ rParaProp.m_rEndParagraph->getText()->createTextCursorByRange(rParaProp.m_rEndParagraph), uno::UNO_QUERY_THROW );
+ // select paragraph
+ xParagraph->gotoStartOfParagraph( true );
+ uno::Reference< beans::XPropertyState > xParaProperties( xParagraph, uno::UNO_QUERY_THROW );
+ if ( xParaProperties->getPropertyState(sPropertyName) == css::beans::PropertyState_DEFAULT_VALUE )
{
- OUString sPropertyName = getPropertyName(eId);
- auto pTableProp = std::find_if(rInfo.aTableProperties.begin(), rInfo.aTableProperties.end(),
- [&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; });
- if (pTableProp != rInfo.aTableProperties.end())
- {
- try
- {
- rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, pTableProp->Value );
- }
- catch ( const uno::Exception & )
- {
- TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction");
- }
- }
+ // apply style setting when the paragraph doesn't modify it
+ rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, pCellProp->Value );
}
- // table style can overwrite paragraph style, when the paragraph style property has a default value, restore it
- // TODO remove the associated TableStyleSheetEntry styles, if needed
- else if ( aParaStyle != uno::Any() && !bDocDefault )
+ else
{
- OUString sPropertyName = getPropertyName(eId);
- try
- {
- rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, aParaStyle );
- }
- catch ( const uno::Exception & )
+ // apply style setting only on text portions without direct modification of it
+ uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xParagraph, uno::UNO_QUERY);
+ uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
+ uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY);
+ uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
+ while ( xRunEnum->hasMoreElements() )
{
- TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction");
+ uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY);
+ uno::Reference< beans::XPropertyState > xRunProperties( xRun, uno::UNO_QUERY_THROW );
+ if ( xRunProperties->getPropertyState(sPropertyName) == css::beans::PropertyState_DEFAULT_VALUE )
+ {
+ uno::Reference< beans::XPropertySet > xRunPropertySet( xRun, uno::UNO_QUERY_THROW );
+ xRunPropertySet->setPropertyValue( sPropertyName, pCellProp->Value );
+ }
}
}
}
+ catch ( const uno::Exception & )
+ {
+ TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction");
+ }
}
}
}
@@ -1153,6 +1163,60 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
uno::Reference<text::XTextRange> xEnd;
bool bFloating = !aFrameProperties.empty();
+
+ // OOXML table style may contain paragraph properties, apply these on cell paragraphs
+ if ( m_aTableRanges[0].hasElements() && m_aTableRanges[0][0].hasElements() )
+ {
+ // collect all paragraph properties used in table styles
+ PropertyMapPtr pAllTableProps( new PropertyMap );
+ pAllTableProps->InsertProps(aTableInfo.pTableDefaults);
+ if ( aTableInfo.pTableStyle )
+ pAllTableProps->InsertProps(aTableInfo.pTableStyle->GetProperties( CNF_ALL ));
+ for (const auto& eId : pAllTableProps->GetPropertyIds())
+ {
+ if ( !isParagraphProperty(eId) && !isCharacterProperty(eId) )
+ pAllTableProps->Erase(eId);
+ }
+ std::vector< PropertyIds > aAllTableParaProperties = pAllTableProps->GetPropertyIds();
+
+ if ( !aAllTableParaProperties.empty() )
+ {
+ for (size_t nRow = 0; nRow < m_aTableRanges.size(); ++nRow)
+ {
+ for (size_t nCell = 0; nCell < m_aTableRanges[nRow].size(); ++nCell)
+ {
+ auto rStartPara = m_aTableRanges[nRow][nCell][0];
+ auto rEndPara = m_aTableRanges[nRow][nCell][1];
+ uno::Reference<text::XTextRangeCompare> xTextRangeCompare(rStartPara->getText(), uno::UNO_QUERY);
+ bool bApply = false;
+ // search paragraphs of the cell
+ std::vector<TableParagraph>::iterator aIt = m_rDMapper_Impl.m_aParagraphsToEndTable.begin();
+ while ( aIt != m_rDMapper_Impl.m_aParagraphsToEndTable.end() ) try
+ {
+ if (!bApply && xTextRangeCompare->compareRegionStarts(rStartPara, aIt->m_rStartParagraph) == 0)
+ bApply = true;
+ if (bApply)
+ {
+ bool bEndOfApply = (xTextRangeCompare->compareRegionEnds(rEndPara, aIt->m_rEndParagraph) == 0);
+ ApplyParagraphPropertiesFromTableStyle(*aIt, aAllTableParaProperties, aCellProperties[nRow][nCell]);
+ // erase processed paragraph from list of pending paragraphs
+ aIt = m_rDMapper_Impl.m_aParagraphsToEndTable.erase(aIt);
+ if (bEndOfApply)
+ break;
+ }
+ else
+ ++aIt;
+ }
+ catch( const lang::IllegalArgumentException & )
+ {
+ // skip compareRegion with nested tables
+ ++aIt;
+ }
+ }
+ }
+ }
+ }
+
// Additional checks: if we can do this.
if (bFloating && m_aTableRanges[0].hasElements() && m_aTableRanges[0][0].hasElements())
{
@@ -1221,9 +1285,6 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
}
}
}
-
- // OOXML table style may contain paragraph properties, apply these now.
- ApplyParagraphPropertiesFromTableStyle(aTableInfo);
}
}
catch ( const lang::IllegalArgumentException & )
@@ -1301,7 +1362,8 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
m_aCellProperties.clear();
m_aRowProperties.clear();
m_bHadFootOrEndnote = false;
- m_rDMapper_Impl.m_aParagraphsToEndTable.clear();
+ if (nestedTableLevel <= 1)
+ m_rDMapper_Impl.m_aParagraphsToEndTable.clear();
#ifdef DBG_UTIL
TagLogger::getInstance().endElement();
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
index b454be94f563..bb0ea2e01804 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
@@ -56,6 +56,15 @@ struct HorizontallyMergedCell
}
};
+/// Information about a paragraph to be finished after a table end.
+struct TableParagraph
+{
+ css::uno::Reference<css::text::XTextRange> m_rStartParagraph;
+ css::uno::Reference<css::text::XTextRange> m_rEndParagraph;
+ PropertyMapPtr m_pPropertyMap;
+ css::uno::Reference<css::beans::XPropertySet> m_rPropertySet;
+};
+
/// Class to handle events generated by TableManager::resolveCurrentTable().
class DomainMapperTableHandler final : public virtual SvRefBase
{
@@ -91,7 +100,7 @@ public:
*/
void startTable(const TablePropertyMapPtr& pProps);
- void ApplyParagraphPropertiesFromTableStyle(TableInfo & rInfo);
+ void ApplyParagraphPropertiesFromTableStyle(TableParagraph rParaProp, std::vector< PropertyIds > aAllTableProperties, css::beans::PropertyValues rCellProperties);
/// Handle end of table.
void endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart);
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 259e1ebbf678..0ee4c6d1989d 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1759,7 +1759,13 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
// collect these pending paragraph properties to process in endTable()
if (xParaProps && m_nTableDepth > 0)
{
- TableParagraph aPending{pParaContext, xParaProps};
+ uno::Reference<text::XTextCursor> xCur = xTextRange->getText( )->createTextCursor( );
+ xCur->gotoEnd(false);
+ xCur->goLeft(1, false);
+ uno::Reference<text::XTextCursor> xCur2 = xTextRange->getText()->createTextCursorByRange(xCur);
+ uno::Reference<text::XParagraphCursor> xParaCursor(xCur2, uno::UNO_QUERY_THROW);
+ xParaCursor->gotoStartOfParagraph(false);
+ TableParagraph aPending{xParaCursor, xCur, pParaContext, xParaProps};
m_aParagraphsToEndTable.push_back(aPending);
}
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 0fd51ab2298e..6138bb738e56 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -430,13 +430,6 @@ struct SymbolData
{ }
};
-/// Information about a paragraph to be finished after a table end.
-struct TableParagraph
-{
- PropertyMapPtr m_pPropertyMap;
- css::uno::Reference<css::beans::XPropertySet> m_rPropertySet;
-};
-
class DomainMapper;
class DomainMapper_Impl final
{