Kaydet (Commit) 78b11422 authored tarafından Miklos Vajna's avatar Miklos Vajna Kaydeden (comit) Andras Timar

tdf#120028 PPTX import: map shapes with multiple columns to table shapes

This is a combination of 3 commits.

1st commit:

Longer term the core Impress shape has to be improved so that it can have
text in multiple columns.

Shorter term, map text with multiple columns to table shapes, that gives
correct layout in many cases and requires changes to the import filter
only.

(cherry picked from commit aef569ed)

Commit #2:

Related: tdf#120028 PPTX import: fix font size of multi-col shape text

Normal shapes have a TextFitToSize property for this, but table cell
content has to be scaled manually, as the rendering has no automatic
support for them. Luckily the file format has the info we need to scale
at import time.

(cherry picked from commit c8b2849d)

Commit #3:

Related: tdf#120028 PPTX import: fix font color of multi-col shape text

Not just font color, anything defined via list styles were not imported.

(cherry picked from commit 800bf107)

Conflicts:
	oox/inc/drawingml/textbodyproperties.hxx

Reviewed-on: https://gerrit.libreoffice.org/61244
Tested-by: Jenkins
Reviewed-by: 's avatarAndras Timar <andras.timar@collabora.com>
(cherry picked from commit 6f1fb474)

Change-Id: Id7942b16882ab1f083ded2f0e577e8c9e128697c
üst d520cb91
......@@ -60,6 +60,9 @@ public:
const css::uno::Reference < css::beans::XPropertySet > & xPropSet,
const ::oox::drawingml::TextListStylePtr& pMasterTextListStyle );
/// Distributes text body with multiple columns in table cells.
void pullFromTextBody(oox::drawingml::TextBodyPtr pTextBody, sal_Int32 nShapeWidth);
private:
const TableStyle& getUsedTableStyle(const ::oox::core::XmlFilterBase& rFilterBase, TableStyle*& rTableStyleToDelete);
......
......@@ -45,6 +45,8 @@ public:
const TextParagraphVector& getParagraphs() const { return maParagraphs; }
TextParagraph& addParagraph();
/// Appends an existing paragraph to this text body.
void appendParagraph(std::shared_ptr<TextParagraph> pTextParagraph);
const TextListStyle& getTextListStyle() const { return maTextListStyle; }
TextListStyle& getTextListStyle() { return maTextListStyle; }
......
......@@ -42,6 +42,10 @@ struct TextBodyProperties
boost::optional< sal_Int32 > moTextOffRight;
css::drawing::TextVerticalAdjust meVA;
OUString msPrst;
/// Number of requested columns.
sal_Int32 mnNumCol = 1;
/// Normal autofit: font scale (default: 100%).
sal_Int32 mnFontScale = 100000;
explicit TextBodyProperties();
......
......@@ -47,6 +47,8 @@ struct TextCharacterProperties
Color maHighlightColor;
OptValue< OUString > moLang;
OptValue< sal_Int32 > moHeight;
/// If a font scale has to be applied manually to moHeight.
OptValue< double > moFontScale;
OptValue< sal_Int32 > moSpacing;
OptValue< sal_Int32 > moUnderline;
OptValue< sal_Int32 > moBaseline;
......
......@@ -19,6 +19,8 @@
#include <drawingml/table/tableproperties.hxx>
#include <drawingml/table/tablestylelist.hxx>
#include <drawingml/textbody.hxx>
#include <drawingml/textparagraph.hxx>
#include <oox/drawingml/drawingmltypes.hxx>
#include <com/sun/star/table/XTable.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
......@@ -311,6 +313,52 @@ void TableProperties::pushToPropSet( const ::oox::core::XmlFilterBase& rFilterBa
delete pTableStyleToDelete;
}
void TableProperties::pullFromTextBody(oox::drawingml::TextBodyPtr pTextBody, sal_Int32 nShapeWidth)
{
// Create table grid and a single row.
sal_Int32 nNumCol = pTextBody->getTextProperties().mnNumCol;
std::vector<sal_Int32>& rTableGrid(getTableGrid());
sal_Int32 nColWidth = nShapeWidth / nNumCol;
for (sal_Int32 nCol = 0; nCol < nNumCol; ++nCol)
rTableGrid.push_back(nColWidth);
std::vector<drawingml::table::TableRow>& rTableRows(getTableRows());
rTableRows.emplace_back();
oox::drawingml::table::TableRow& rTableRow = rTableRows.back();
std::vector<oox::drawingml::table::TableCell>& rTableCells = rTableRow.getTableCells();
// Create the cells and distribute the paragraphs from pTextBody.
sal_Int32 nNumPara = pTextBody->getParagraphs().size();
sal_Int32 nParaPerCol = std::ceil(double(nNumPara) / nNumCol);
// Font scale of text body will be applied at a text run level.
sal_Int32 nFontScale = pTextBody->getTextProperties().mnFontScale;
size_t nPara = 0;
for (sal_Int32 nCol = 0; nCol < nNumCol; ++nCol)
{
rTableCells.emplace_back();
oox::drawingml::table::TableCell& rTableCell = rTableCells.back();
TextBodyPtr pCellTextBody(new TextBody);
rTableCell.setTextBody(pCellTextBody);
// Copy properties provided by <a:lstStyle>.
pCellTextBody->getTextListStyle() = pTextBody->getTextListStyle();
for (sal_Int32 nParaInCol = 0; nParaInCol < nParaPerCol; ++nParaInCol)
{
if (nPara < pTextBody->getParagraphs().size())
{
std::shared_ptr<oox::drawingml::TextParagraph> pParagraph
= pTextBody->getParagraphs()[nPara];
if (nFontScale != 100000)
{
for (auto& pRun : pParagraph->getRuns())
pRun->getTextCharacterProperties().moFontScale = nFontScale;
}
pCellTextBody->appendParagraph(pParagraph);
}
++nPara;
}
}
}
} } }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -54,6 +54,11 @@ TextParagraph& TextBody::addParagraph()
return *xPara;
}
void TextBody::appendParagraph(std::shared_ptr<TextParagraph> pTextParagraph)
{
maParagraphs.push_back(pTextParagraph);
}
void TextBody::insertAt(
const ::oox::core::XmlFilterBase& rFilterBase,
const Reference < XText > & xText,
......
......@@ -90,7 +90,7 @@ TextBodyPropertiesContext::TextBodyPropertiesContext( ContextHandler2Helper cons
// sal_Int32 nVertOverflow = rAttribs.getToken( XML_vertOverflow, XML_overflow );
// ST_TextColumnCount
// sal_Int32 nNumCol = rAttribs.getInteger( XML_numCol, 1 );
mrTextBodyProp.mnNumCol = rAttribs.getInteger( XML_numCol, 1 );
// ST_Angle
mrTextBodyProp.moRotation = rAttribs.getInteger( XML_rot );
......@@ -155,9 +155,12 @@ ContextHandlerRef TextBodyPropertiesContext::onCreateContext( sal_Int32 aElement
mrTextBodyProp.maPropertyMap.setProperty( PROP_TextAutoGrowHeight, false); // CT_TextNoAutofit
break;
case A_TOKEN( normAutofit ): // CT_TextNormalAutofit
{
mrTextBodyProp.maPropertyMap.setProperty( PROP_TextFitToSize, TextFitToSizeType_AUTOFIT);
mrTextBodyProp.maPropertyMap.setProperty( PROP_TextAutoGrowHeight, false);
mrTextBodyProp.mnFontScale = rAttribs.getInteger(XML_fontScale, 100000);
break;
}
case A_TOKEN( spAutoFit ):
{
const sal_Int32 tVert = mrTextBodyProp.moVert.get( XML_horz );
......
......@@ -52,6 +52,7 @@ void TextCharacterProperties::assignUsed( const TextCharacterProperties& rSource
maHighlightColor.assignIfUsed( rSourceProps.maHighlightColor );
maUnderlineColor.assignIfUsed( rSourceProps.maUnderlineColor );
moHeight.assignIfUsed( rSourceProps.moHeight );
moFontScale.assignIfUsed(rSourceProps.moFontScale);
moSpacing.assignIfUsed( rSourceProps.moSpacing );
moUnderline.assignIfUsed( rSourceProps.moUnderline );
moBaseline.assignIfUsed( rSourceProps.moBaseline );
......@@ -117,6 +118,8 @@ void TextCharacterProperties::pushToPropMap( PropertyMap& rPropMap, const XmlFil
if( moHeight.has() )
{
float fHeight = GetFontHeight( moHeight.get() );
if (moFontScale.has())
fHeight *= (moFontScale.get() / 100000);
rPropMap.setProperty( PROP_CharHeight, fHeight);
rPropMap.setProperty( PROP_CharHeightAsian, fHeight);
rPropMap.setProperty( PROP_CharHeightComplex, fHeight);
......
......@@ -20,6 +20,7 @@
#include <oox/ppt/pptshape.hxx>
#include <oox/core/xmlfilterbase.hxx>
#include <drawingml/textbody.hxx>
#include <drawingml/table/tableproperties.hxx>
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/container/XNamed.hpp>
......@@ -223,6 +224,23 @@ void PPTShape::addShape(
}
}
if (sServiceName != "com.sun.star.drawing.TableShape")
{
if (TextBodyPtr pTextBody = getTextBody())
{
sal_Int32 nNumCol = pTextBody->getTextProperties().mnNumCol;
if (nNumCol > 1)
{
// This shape is not a table, but has multiple columns,
// represent that as a table.
sServiceName = "com.sun.star.drawing.TableShape";
oox::drawingml::table::TablePropertiesPtr pTableProperties = getTableProperties();
pTableProperties->pullFromTextBody(pTextBody, maSize.Width);
setTextBody(nullptr);
}
}
}
SAL_INFO("oox.ppt","shape service: " << sServiceName);
if (mnSubType && getSubTypeIndex().has() && meShapeLocation == Layout)
......
......@@ -178,6 +178,8 @@ public:
bool checkPattern(sd::DrawDocShellRef const & rDocRef, int nShapeNumber, std::vector<sal_uInt8>& rExpected);
void testPatternImport();
void testTdf119015();
void testTdf120028();
void testTdf120028b();
CPPUNIT_TEST_SUITE(SdImportTest);
......@@ -255,6 +257,8 @@ public:
CPPUNIT_TEST(testTdf116266);
CPPUNIT_TEST(testTdf114821);
CPPUNIT_TEST(testTdf119015);
CPPUNIT_TEST(testTdf120028);
CPPUNIT_TEST(testTdf120028b);
CPPUNIT_TEST_SUITE_END();
};
......@@ -2472,6 +2476,79 @@ void SdImportTest::testTdf119015()
xDocShRef->DoClose();
}
void SdImportTest::testTdf120028()
{
// Check that the table shape has 4 columns.
::sd::DrawDocShellRef xDocShRef
= loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/tdf120028.pptx"), PPTX);
uno::Reference<drawing::XDrawPagesSupplier> xDoc(xDocShRef->GetDoc()->getUnoModel(),
uno::UNO_QUERY);
CPPUNIT_ASSERT(xDoc.is());
uno::Reference<drawing::XDrawPage> xPage(xDoc->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
CPPUNIT_ASSERT(xPage.is());
// This failed, shape was not a table, all text was rendered in a single
// column.
uno::Reference<beans::XPropertySet> xShape(getShape(0, xPage));
uno::Reference<table::XColumnRowRange> xModel(xShape->getPropertyValue("Model"),
uno::UNO_QUERY);
CPPUNIT_ASSERT(xModel.is());
uno::Reference<table::XTableColumns> xColumns = xModel->getColumns();
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), xColumns->getCount());
// Check font size in the A1 cell.
uno::Reference<table::XCellRange> xCells(xModel, uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xCell(xCells->getCellByPosition(0, 0), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xParagraph(getParagraphFromShape(0, xCell));
uno::Reference<text::XTextRange> xRun(getRunFromParagraph(0, xParagraph));
uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY);
double fCharHeight = 0;
xPropSet->getPropertyValue("CharHeight") >>= fCharHeight;
// This failed, non-scaled height was 13.5.
CPPUNIT_ASSERT_DOUBLES_EQUAL(11.5, fCharHeight, 1E-12);
xDocShRef->DoClose();
}
void SdImportTest::testTdf120028b()
{
// Check that the table shape has 4 columns.
::sd::DrawDocShellRef xDocShRef
= loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/tdf120028b.pptx"), PPTX);
uno::Reference<drawing::XDrawPagesSupplier> xDoc(xDocShRef->GetDoc()->getUnoModel(),
uno::UNO_QUERY);
CPPUNIT_ASSERT(xDoc.is());
uno::Reference<drawing::XDrawPage> xPage(xDoc->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
CPPUNIT_ASSERT(xPage.is());
uno::Reference<beans::XPropertySet> xShape(getShape(0, xPage));
CPPUNIT_ASSERT(xShape.is());
uno::Reference<table::XColumnRowRange> xModel(xShape->getPropertyValue("Model"),
uno::UNO_QUERY);
CPPUNIT_ASSERT(xModel.is());
uno::Reference<table::XTableColumns> xColumns = xModel->getColumns();
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), xColumns->getCount());
// Check font color in the A1 cell.
uno::Reference<table::XCellRange> xCells(xModel, uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xCell(xCells->getCellByPosition(0, 0), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xParagraph(getParagraphFromShape(0, xCell));
uno::Reference<text::XTextRange> xRun(getRunFromParagraph(0, xParagraph));
uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY);
sal_Int32 nCharColor = 0;
xPropSet->getPropertyValue("CharColor") >>= nCharColor;
// This was 0x1f497d, not white: text list style from placeholder shape
// from slide layout was ignored.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0xffffff), nCharColor);
xDocShRef->DoClose();
}
CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTest);
CPPUNIT_PLUGIN_IMPLEMENT();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment