summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--oox/qa/unit/data/tdf151008_eaVertAnchor.pptxbin0 -> 19773 bytes
-rw-r--r--oox/qa/unit/export.cxx30
-rw-r--r--oox/qa/unit/shape.cxx58
-rw-r--r--oox/source/drawingml/textbodypropertiescontext.cxx46
-rw-r--r--oox/source/export/drawingml.cxx78
5 files changed, 165 insertions, 47 deletions
diff --git a/oox/qa/unit/data/tdf151008_eaVertAnchor.pptx b/oox/qa/unit/data/tdf151008_eaVertAnchor.pptx
new file mode 100644
index 000000000000..999cd220408c
--- /dev/null
+++ b/oox/qa/unit/data/tdf151008_eaVertAnchor.pptx
Binary files differ
diff --git a/oox/qa/unit/export.cxx b/oox/qa/unit/export.cxx
index 09cf5cb5ef48..64e1cfaa47e7 100644
--- a/oox/qa/unit/export.cxx
+++ b/oox/qa/unit/export.cxx
@@ -808,6 +808,36 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf149538upright)
assertXPath(pXmlDoc, "//p:spTree/p:sp/p:txBody/a:bodyPr", "upright", "1");
assertXPathNoAttribute(pXmlDoc, "//p:spTree/p:sp/p:txBody/a:bodyPr", "rot");
}
+
+CPPUNIT_TEST_FIXTURE(Test, testTdf151008VertAnchor)
+{
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf151008_eaVertAnchor.pptx";
+ loadAndSave(aURL, "Impress Office Open XML");
+ std::unique_ptr<SvStream> pStream = parseExportStream(getTempFile(), "ppt/slides/slide1.xml");
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get());
+ // The order of the shapes in the file is by name "Right", "Center", "Left", "RightMiddle",
+ // "CenterMiddle" and "LeftMiddle". I access the shapes here by index, because the XPath is
+ // easier then.
+ // As of Sep 2022 LibreOffice does not write the default anchorCtr="0"
+ // Right
+ assertXPath(pXmlDoc, "//p:spTree/p:sp[1]/p:txBody/a:bodyPr", "anchor", "t");
+ assertXPathNoAttribute(pXmlDoc, "//p:spTree/p:sp[1]/p:txBody/a:bodyPr", "anchorCtr");
+ // Center
+ assertXPath(pXmlDoc, "//p:spTree/p:sp[2]/p:txBody/a:bodyPr", "anchor", "ctr");
+ assertXPathNoAttribute(pXmlDoc, "//p:spTree/p:sp[2]/p:txBody/a:bodyPr", "anchorCtr");
+ // Left
+ assertXPath(pXmlDoc, "//p:spTree/p:sp[3]/p:txBody/a:bodyPr", "anchor", "b");
+ assertXPathNoAttribute(pXmlDoc, "//p:spTree/p:sp[3]/p:txBody/a:bodyPr", "anchorCtr");
+ // RightMiddle
+ assertXPath(pXmlDoc, "//p:spTree/p:sp[4]/p:txBody/a:bodyPr", "anchor", "t");
+ assertXPath(pXmlDoc, "//p:spTree/p:sp[4]/p:txBody/a:bodyPr", "anchorCtr", "1");
+ // CenterMiddle
+ assertXPath(pXmlDoc, "//p:spTree/p:sp[5]/p:txBody/a:bodyPr", "anchor", "ctr");
+ assertXPath(pXmlDoc, "//p:spTree/p:sp[5]/p:txBody/a:bodyPr", "anchorCtr", "1");
+ // LeftMiddle
+ assertXPath(pXmlDoc, "//p:spTree/p:sp[6]/p:txBody/a:bodyPr", "anchor", "b");
+ assertXPath(pXmlDoc, "//p:spTree/p:sp[6]/p:txBody/a:bodyPr", "anchorCtr", "1");
+}
}
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/oox/qa/unit/shape.cxx b/oox/qa/unit/shape.cxx
index 345ebb215ad6..c741ff84d4da 100644
--- a/oox/qa/unit/shape.cxx
+++ b/oox/qa/unit/shape.cxx
@@ -15,6 +15,7 @@
#include <unotest/macros_test.hxx>
#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
#include <com/sun/star/frame/Desktop.hpp>
@@ -55,6 +56,7 @@ public:
void tearDown() override;
uno::Reference<lang::XComponent>& getComponent() { return mxComponent; }
void load(std::u16string_view rURL);
+ uno::Reference<drawing::XShape> getShapeByName(std::u16string_view aName);
};
void OoxShapeTest::setUp()
@@ -78,6 +80,26 @@ void OoxShapeTest::load(std::u16string_view rFileName)
mxComponent = loadFromDesktop(aURL);
}
+uno::Reference<drawing::XShape> OoxShapeTest::getShapeByName(std::u16string_view aName)
+{
+ uno::Reference<drawing::XShape> xRet;
+
+ uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
+ uno::UNO_QUERY);
+ for (sal_Int32 i = 0; i < xDrawPage->getCount(); ++i)
+ {
+ uno::Reference<container::XNamed> xShape(xDrawPage->getByIndex(i), uno::UNO_QUERY);
+ if (xShape->getName() == aName)
+ {
+ xRet.set(xShape, uno::UNO_QUERY);
+ break;
+ }
+ }
+
+ return xRet;
+}
+
CPPUNIT_TEST_FIXTURE(OoxShapeTest, testGroupTransform)
{
load(u"tdf141463_GroupTransform.pptx");
@@ -175,6 +197,42 @@ CPPUNIT_TEST_FIXTURE(OoxShapeTest, testTdf125582_TextOnCircle)
CPPUNIT_ASSERT_EQUAL_MESSAGE("TextVerticalAdjust", drawing::TextVerticalAdjust_BOTTOM, eAdjust);
}
+CPPUNIT_TEST_FIXTURE(OoxShapeTest, testTdf151008VertAnchor)
+{
+ // The document contains shapes with all six kind of anchor positions in pptx. The text in the
+ // shapes is larger than the shape and has no word wrap. That way anchor position is visible
+ // in case you inspect the file manually.
+ load(u"tdf151008_eaVertAnchor.pptx");
+
+ struct anchorDesc
+ {
+ OUString sShapeName;
+ drawing::TextHorizontalAdjust eAnchorHori;
+ drawing::TextVerticalAdjust eAnchorVert;
+ };
+ anchorDesc aExpected[6] = {
+ { u"Right", drawing::TextHorizontalAdjust_RIGHT, drawing::TextVerticalAdjust_TOP },
+ { u"Center", drawing::TextHorizontalAdjust_CENTER, drawing::TextVerticalAdjust_TOP },
+ { u"Left", drawing::TextHorizontalAdjust_LEFT, drawing::TextVerticalAdjust_TOP },
+ { u"RightMiddle", drawing::TextHorizontalAdjust_RIGHT, drawing::TextVerticalAdjust_CENTER },
+ { u"CenterMiddle", drawing::TextHorizontalAdjust_CENTER,
+ drawing::TextVerticalAdjust_CENTER },
+ { u"LeftMiddle", drawing::TextHorizontalAdjust_LEFT, drawing::TextVerticalAdjust_CENTER }
+ };
+ // without the fix horizontal and vertical anchor positions were exchanged
+ for (size_t i = 0; i < 6; ++i)
+ {
+ uno::Reference<beans::XPropertySet> xShape(getShapeByName(aExpected[i].sShapeName),
+ uno::UNO_QUERY);
+ drawing::TextHorizontalAdjust eHori;
+ CPPUNIT_ASSERT(xShape->getPropertyValue("TextHorizontalAdjust") >>= eHori);
+ drawing::TextVerticalAdjust eVert;
+ CPPUNIT_ASSERT(xShape->getPropertyValue("TextVerticalAdjust") >>= eVert);
+ CPPUNIT_ASSERT_EQUAL(aExpected[i].eAnchorHori, eHori);
+ CPPUNIT_ASSERT_EQUAL(aExpected[i].eAnchorVert, eVert);
+ }
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/textbodypropertiescontext.cxx b/oox/source/drawingml/textbodypropertiescontext.cxx
index 9d221a18ffbe..47ef04797c93 100644
--- a/oox/source/drawingml/textbodypropertiescontext.cxx
+++ b/oox/source/drawingml/textbodypropertiescontext.cxx
@@ -75,10 +75,6 @@ TextBodyPropertiesContext::TextBodyPropertiesContext( ContextHandler2Helper cons
mrTextBodyProp.moInsets[i] = GetCoordinate( sValue );
}
- mrTextBodyProp.mbAnchorCtr = rAttribs.getBool( XML_anchorCtr, false );
- if( mrTextBodyProp.mbAnchorCtr )
- mrTextBodyProp.maPropertyMap.setProperty( PROP_TextHorizontalAdjust, TextHorizontalAdjust_CENTER );
-
// bool bCompatLineSpacing = rAttribs.getBool( XML_compatLnSpc, false );
// bool bForceAA = rAttribs.getBool( XML_forceAA, false );
bool bFromWordArt = rAttribs.getBool(XML_fromWordArt, false);
@@ -148,10 +144,46 @@ TextBodyPropertiesContext::TextBodyPropertiesContext( ContextHandler2Helper cons
}
// ST_TextAnchoringType
- if( rAttribs.hasAttribute( XML_anchor ) )
+ mrTextBodyProp.mbAnchorCtr = rAttribs.getBool(XML_anchorCtr, false );
+ if (rAttribs.hasAttribute(XML_anchor))
+ mrTextBodyProp.meVA = GetTextVerticalAdjust( rAttribs.getToken(XML_anchor, XML_t));
+ // else meVA is initialized to TextVerticalAdjust_TOP
+
+ sal_Int32 tVert = mrTextBodyProp.moVert.value_or(XML_horz);
+ if (tVert == XML_eaVert || tVert == XML_mongolianVert)
+ {
+ if (mrTextBodyProp.mbAnchorCtr)
+ mrTextBodyProp.maPropertyMap.setProperty(PROP_TextVerticalAdjust,
+ TextVerticalAdjust_CENTER);
+ else
+ mrTextBodyProp.maPropertyMap.setProperty(PROP_TextVerticalAdjust,
+ TextVerticalAdjust_TOP);
+
+ if (mrTextBodyProp.meVA == TextVerticalAdjust_CENTER)
+ mrTextBodyProp.maPropertyMap.setProperty(PROP_TextHorizontalAdjust,
+ TextHorizontalAdjust_CENTER);
+ else if (mrTextBodyProp.meVA == TextVerticalAdjust_TOP)
+ {
+ mrTextBodyProp.maPropertyMap.setProperty(
+ PROP_TextHorizontalAdjust,
+ tVert == XML_eaVert ? TextHorizontalAdjust_RIGHT : TextHorizontalAdjust_LEFT);
+ }
+ else // meVA == TextVerticalAdjust_BOTTOM
+ {
+ mrTextBodyProp.maPropertyMap.setProperty(
+ PROP_TextHorizontalAdjust,
+ tVert == XML_eaVert ? TextHorizontalAdjust_LEFT : TextHorizontalAdjust_RIGHT);
+ }
+ }
+ else
{
- mrTextBodyProp.meVA = GetTextVerticalAdjust( rAttribs.getToken( XML_anchor, XML_t ) );
- mrTextBodyProp.maPropertyMap.setProperty( PROP_TextVerticalAdjust, mrTextBodyProp.meVA);
+ if (mrTextBodyProp.mbAnchorCtr)
+ mrTextBodyProp.maPropertyMap.setProperty(PROP_TextHorizontalAdjust,
+ TextHorizontalAdjust_CENTER);
+ else // BLOCK is nearer to rendering in MS Office than LEFT, see tdf#137023
+ mrTextBodyProp.maPropertyMap.setProperty(PROP_TextHorizontalAdjust,
+ TextHorizontalAdjust_BLOCK);
+ mrTextBodyProp.maPropertyMap.setProperty(PROP_TextVerticalAdjust, mrTextBodyProp.meVA);
}
// Push defaults
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 47c8903093b1..85e73eb35c85 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -3318,22 +3318,12 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
}
}
- TextVerticalAdjust eVerticalAlignment( TextVerticalAdjust_TOP );
- const char* sVerticalAlignment = nullptr;
- if (GetProperty(rXPropSet, "TextVerticalAdjust"))
- mAny >>= eVerticalAlignment;
- sVerticalAlignment = GetTextVerticalAdjust(eVerticalAlignment);
-
std::optional<OString> sWritingMode;
- bool bVertical = false;
if (GetProperty(rXPropSet, "TextWritingMode"))
{
WritingMode eMode;
if( ( mAny >>= eMode ) && eMode == WritingMode_TB_RL )
- {
sWritingMode = "eaVert";
- bVertical = true;
- }
}
if (GetProperty(rXPropSet, "WritingMode"))
{
@@ -3341,25 +3331,13 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
if (mAny >>= nWritingMode)
{
if (nWritingMode == text::WritingMode2::TB_RL)
- {
sWritingMode = "eaVert";
- bVertical = true;
- }
else if (nWritingMode == text::WritingMode2::BT_LR)
- {
sWritingMode = "vert270";
- bVertical = true;
- }
else if (nWritingMode == text::WritingMode2::TB_RL90)
- {
sWritingMode = "vert";
- bVertical = true;
- }
else if (nWritingMode == text::WritingMode2::TB_LR)
- {
sWritingMode = "mongolianVert";
- bVertical = true;
- }
}
}
@@ -3423,19 +3401,15 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
{
case WritingMode2::TB_RL:
sWritingMode = "eaVert";
- bVertical = true;
break;
case WritingMode2::BT_LR:
sWritingMode = "vert270";
- bVertical = true;
break;
case WritingMode2::TB_RL90:
sWritingMode = "vert";
- bVertical = true;
break;
case WritingMode2::TB_LR:
sWritingMode = "mongolianVert";
- bVertical = true;
break;
default:
break;
@@ -3529,15 +3503,9 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
if (nTextPreRotateAngle != 0 && !sWritingMode)
{
if (nTextPreRotateAngle == -90 || nTextPreRotateAngle == 270)
- {
sWritingMode = "vert";
- bVertical = true;
- }
else if (nTextPreRotateAngle == -270 || nTextPreRotateAngle == 90)
- {
sWritingMode = "vert270";
- bVertical = true;
- }
else if (nTextPreRotateAngle == -180 || nTextPreRotateAngle == 180)
{
#if defined __GNUC__ && !defined __clang__ && __GNUC__ == 12
@@ -3600,14 +3568,44 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
#pragma GCC diagnostic pop
#endif
- TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER );
- bool bHorizontalCenter = false;
+ // Prepare attributes 'anchor' and 'anchorCtr'
+ // LibreOffice has 12 value sets, MS Office only 6. We map them so, that it reverses the
+ // 6 mappings from import, and we assign the others approximately.
+ TextVerticalAdjust eVerticalAlignment(TextVerticalAdjust_TOP);
+ if (GetProperty(rXPropSet, "TextVerticalAdjust"))
+ mAny >>= eVerticalAlignment;
+ TextHorizontalAdjust eHorizontalAlignment(TextHorizontalAdjust_CENTER);
if (GetProperty(rXPropSet, "TextHorizontalAdjust"))
mAny >>= eHorizontalAlignment;
- if( eHorizontalAlignment == TextHorizontalAdjust_CENTER )
- bHorizontalCenter = true;
- else if( bVertical && eHorizontalAlignment == TextHorizontalAdjust_LEFT )
- sVerticalAlignment = "b";
+
+ const char* sAnchor = nullptr;
+ bool bAnchorCtr = false;
+ if (sWritingMode.has_value()
+ && (sWritingMode.value() == "eaVert" || sWritingMode.value() == "mongolianVert"))
+ {
+ bAnchorCtr = eVerticalAlignment == TextVerticalAdjust_CENTER
+ || eVerticalAlignment == TextVerticalAdjust_BOTTOM
+ || eVerticalAlignment == TextVerticalAdjust_BLOCK;
+ switch (eHorizontalAlignment)
+ {
+ case TextHorizontalAdjust_CENTER:
+ sAnchor = "ctr";
+ break;
+ case TextHorizontalAdjust_LEFT:
+ sAnchor = sWritingMode.value() == "eaVert" ? "b" : "t";
+ break;
+ case TextHorizontalAdjust_RIGHT:
+ default: // TextHorizontalAdjust_BLOCK, should not happen
+ sAnchor = sWritingMode.value() == "eaVert" ? "t" : "b";
+ break;
+ }
+ }
+ else
+ {
+ bAnchorCtr = eHorizontalAlignment == TextHorizontalAdjust_CENTER
+ || eHorizontalAlignment == TextHorizontalAdjust_RIGHT;
+ sAnchor = GetTextVerticalAdjust(eVerticalAlignment);
+ }
bool bHasWrap = false;
bool bWrap = false;
@@ -3658,8 +3656,8 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
XML_rIns, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nRight)), nRight != constDefaultLeftRightInset),
XML_tIns, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nTop)), nTop != constDefaultTopBottomInset),
XML_bIns, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nBottom)), nBottom != constDefaultTopBottomInset),
- XML_anchor, sVerticalAlignment,
- XML_anchorCtr, sax_fastparser::UseIf("1", bHorizontalCenter),
+ XML_anchor, sAnchor,
+ XML_anchorCtr, sax_fastparser::UseIf("1", bAnchorCtr),
XML_vert, sWritingMode,
XML_upright, isUpright,
XML_rot, sTextRotateAngleMSUnit);