diff options
author | Miklos Vajna <vmiklos@suse.cz> | 2013-07-01 12:05:23 +0200 |
---|---|---|
committer | Fridrich Strba <fridrich@documentfoundation.org> | 2013-07-02 14:15:30 +0000 |
commit | 2b4d78598c55389b24b4a5016279aed26ac0fb2e (patch) | |
tree | 14238365c69950ecdd159566c566002e4e8b4141 | |
parent | 3820420edfb828e49735becf796803f0558ef844 (diff) |
fdo#46361 oox: fixes for the VML import of groupshape textboxes
(cherry picked from commits b1f78c44c1acc246f06a963383232c9bf649a06b,
f24e4c74d7d6a7d95090c6fa6a584fed7787706c,
6bf79576aeca243db553ed3b5eade492dc35337b,
5a737fca37cd5a5f90aa03a30688d447677d3b8a,
ef53d4aec2a3d690de2c7cdaf73ca95bbe29a433 and
2a2105b002c482e6536d5c3046c9e7783c0cdca3)
Conflicts:
sw/qa/extras/ooxmlimport/ooxmlimport.cxx
Change-Id: Ie7ce4fb5c32ff4b3c1f3d7ee92d8358ae67fc6c1
Reviewed-on: https://gerrit.libreoffice.org/4675
Reviewed-by: Fridrich Strba <fridrich@documentfoundation.org>
Tested-by: Fridrich Strba <fridrich@documentfoundation.org>
-rw-r--r-- | include/oox/vml/vmlshape.hxx | 1 | ||||
-rw-r--r-- | include/oox/vml/vmltextbox.hxx | 11 | ||||
-rw-r--r-- | include/oox/vml/vmltextboxcontext.hxx | 5 | ||||
-rw-r--r-- | oox/source/vml/vmlshape.cxx | 9 | ||||
-rw-r--r-- | oox/source/vml/vmlshapecontext.cxx | 1 | ||||
-rw-r--r-- | oox/source/vml/vmltextbox.cxx | 34 | ||||
-rw-r--r-- | oox/source/vml/vmltextboxcontext.cxx | 46 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlimport/data/fdo46361.docx | bin | 0 -> 13791 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlimport/ooxmlimport.cxx | 25 |
9 files changed, 119 insertions, 13 deletions
diff --git a/include/oox/vml/vmlshape.hxx b/include/oox/vml/vmlshape.hxx index ca815ec8ef8e..0312ec1a17c9 100644 --- a/include/oox/vml/vmlshape.hxx +++ b/include/oox/vml/vmlshape.hxx @@ -96,6 +96,7 @@ struct OOX_DLLPUBLIC ShapeTypeModel OptValue< OUString > moWrapAnchorY; ///< The base object from which our vertical positioning should be calculated. OptValue< ::rtl::OUString > moWrapType; ///< How to wrap the text around the object OptValue< ::rtl::OUString > moWrapSide; ///< On which side to wrap the text around the object + OUString maVTextAnchor; ///< How the text inside the shape is anchored vertically. explicit ShapeTypeModel(); diff --git a/include/oox/vml/vmltextbox.hxx b/include/oox/vml/vmltextbox.hxx index 4975e6bb26b6..fc97dc78413b 100644 --- a/include/oox/vml/vmltextbox.hxx +++ b/include/oox/vml/vmltextbox.hxx @@ -37,6 +37,12 @@ struct ShapeTypeModel; // ============================================================================ +/// A text paragraph in a textbox. +struct TextParagraphModel +{ + OptValue<OUString> moParaAdjust; ///< Paragraph adjust (left, center, right, etc.) +}; + /** Font settings for a text portion in a textbox. */ struct OOX_DLLPUBLIC TextFontModel { @@ -57,10 +63,11 @@ struct OOX_DLLPUBLIC TextFontModel /** A text portion in a textbox with the same formatting for all characters. */ struct TextPortionModel { + TextParagraphModel maParagraph; TextFontModel maFont; OUString maText; - explicit TextPortionModel( const TextFontModel& rFont, const OUString& rText ); + explicit TextPortionModel( const TextParagraphModel& rParagraph, const TextFontModel& rFont, const OUString& rText ); }; // ============================================================================ @@ -72,7 +79,7 @@ public: explicit TextBox(ShapeTypeModel& rTypeModel); /** Appends a new text portion to the textbox. */ - void appendPortion( const TextFontModel& rFont, const OUString& rText ); + void appendPortion( const TextParagraphModel& rParagraph, const TextFontModel& rFont, const OUString& rText ); /** Returns the current number of text portions. */ inline size_t getPortionCount() const { return maPortions.size(); } diff --git a/include/oox/vml/vmltextboxcontext.hxx b/include/oox/vml/vmltextboxcontext.hxx index 47d71ac41b41..b5502445cdd7 100644 --- a/include/oox/vml/vmltextboxcontext.hxx +++ b/include/oox/vml/vmltextboxcontext.hxx @@ -34,6 +34,7 @@ public: explicit TextPortionContext( ::oox::core::ContextHandler2Helper& rParent, TextBox& rTextBox, + TextParagraphModel& rParagraph, const TextFontModel& rParentFont, sal_Int32 nElement, const AttributeList& rAttribs ); @@ -46,6 +47,7 @@ public: private: TextBox& mrTextBox; + TextParagraphModel maParagraph; TextFontModel maFont; size_t mnInitialPortions; }; @@ -63,9 +65,12 @@ public: virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ); + virtual void onStartElement(const AttributeList& rAttribs) SAL_OVERRIDE; + virtual void onEndElement(); private: TextBox& mrTextBox; + TextParagraphModel maParagraph; }; // ============================================================================ diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx index 0d0f80f0a73c..872ccace661a 100644 --- a/oox/source/vml/vmlshape.cxx +++ b/oox/source/vml/vmlshape.cxx @@ -27,6 +27,7 @@ #include <com/sun/star/awt/XControlModel.hpp> #include <com/sun/star/drawing/PointSequenceSequence.hpp> #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> #include <com/sun/star/drawing/XShapes.hpp> #include <com/sun/star/drawing/XControlShape.hpp> @@ -545,6 +546,14 @@ Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes } } + // drawinglayer default is center, MSO default is top. + drawing::TextVerticalAdjust eTextVerticalAdjust = drawing::TextVerticalAdjust_TOP; + if (maTypeModel.maVTextAnchor == "middle") + eTextVerticalAdjust = drawing::TextVerticalAdjust_CENTER; + else if (maTypeModel.maVTextAnchor == "bottom") + eTextVerticalAdjust = drawing::TextVerticalAdjust_BOTTOM; + PropertySet(xShape).setAnyProperty(PROP_TextVerticalAdjust, makeAny(eTextVerticalAdjust)); + if (getTextBox()) getTextBox()->convert(xShape); } diff --git a/oox/source/vml/vmlshapecontext.cxx b/oox/source/vml/vmlshapecontext.cxx index efa6e3888cbe..3c47c668cd39 100644 --- a/oox/source/vml/vmlshapecontext.cxx +++ b/oox/source/vml/vmlshapecontext.cxx @@ -417,6 +417,7 @@ void ShapeTypeContext::setStyle( const OUString& rStyle ) else if( aName.equalsAscii( "visibility" ) ) mrTypeModel.mbVisible = !aValue.equalsAscii( "hidden" ); else if( aName == "mso-wrap-style" ) mrTypeModel.maWrapStyle = aValue; + else if ( aName == "v-text-anchor" ) mrTypeModel.maVTextAnchor = aValue; } } } diff --git a/oox/source/vml/vmltextbox.cxx b/oox/source/vml/vmltextbox.cxx index 1499091a8cfd..6fe51b147f0d 100644 --- a/oox/source/vml/vmltextbox.cxx +++ b/oox/source/vml/vmltextbox.cxx @@ -24,6 +24,7 @@ #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/text/XTextAppend.hpp> #include <com/sun/star/text/WritingMode.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> namespace oox { namespace vml { @@ -34,7 +35,8 @@ TextFontModel::TextFontModel() { } -TextPortionModel::TextPortionModel( const TextFontModel& rFont, const OUString& rText ) : +TextPortionModel::TextPortionModel( const TextParagraphModel& rParagraph, const TextFontModel& rFont, const OUString& rText ) : + maParagraph( rParagraph ), maFont( rFont ), maText( rText ) { @@ -50,9 +52,9 @@ TextBox::TextBox(ShapeTypeModel& rTypeModel) { } -void TextBox::appendPortion( const TextFontModel& rFont, const OUString& rText ) +void TextBox::appendPortion( const TextParagraphModel& rParagraph, const TextFontModel& rFont, const OUString& rText ) { - maPortions.push_back( TextPortionModel( rFont, rText ) ); + maPortions.push_back( TextPortionModel( rParagraph, rFont, rText ) ); } const TextFontModel* TextBox::getFirstFont() const @@ -75,6 +77,7 @@ void TextBox::convert(uno::Reference<drawing::XShape> xShape) const { beans::PropertyValue aPropertyValue; std::vector<beans::PropertyValue> aPropVec; + const TextParagraphModel& rParagraph = aIt->maParagraph; const TextFontModel& rFont = aIt->maFont; if (rFont.mobBold.has()) { @@ -88,6 +91,24 @@ void TextBox::convert(uno::Reference<drawing::XShape> xShape) const aPropertyValue.Value = uno::makeAny(double(rFont.monSize.get()) / 2.); aPropVec.push_back(aPropertyValue); } + if (rParagraph.moParaAdjust.has()) + { + style::ParagraphAdjust eAdjust = style::ParagraphAdjust_LEFT; + if (rParagraph.moParaAdjust.get() == "center") + eAdjust = style::ParagraphAdjust_CENTER; + else if (rParagraph.moParaAdjust.get() == "right") + eAdjust = style::ParagraphAdjust_RIGHT; + + aPropertyValue.Name = "ParaAdjust"; + aPropertyValue.Value = uno::makeAny(eAdjust); + aPropVec.push_back(aPropertyValue); + } + if (rFont.moColor.has()) + { + aPropertyValue.Name = "CharColor"; + aPropertyValue.Value = uno::makeAny(rFont.moColor.get().toInt32(16)); + aPropVec.push_back(aPropertyValue); + } uno::Sequence<beans::PropertyValue> aPropSeq(aPropVec.size()); beans::PropertyValue* pValues = aPropSeq.getArray(); for (std::vector<beans::PropertyValue>::iterator i = aPropVec.begin(); i != aPropVec.end(); ++i) @@ -95,6 +116,13 @@ void TextBox::convert(uno::Reference<drawing::XShape> xShape) const xTextAppend->appendTextPortion(aIt->maText, aPropSeq); } + // Remove the last character of the shape text, if it would be a newline. + uno::Reference< text::XTextCursor > xCursor = xTextAppend->createTextCursor(); + xCursor->gotoEnd(false); + xCursor->goLeft(1, true); + if (xCursor->getString() == "\n") + xCursor->setString(""); + if ( maLayoutFlow == "vertical" ) { uno::Reference<beans::XPropertySet> xProperties(xShape, uno::UNO_QUERY); diff --git a/oox/source/vml/vmltextboxcontext.cxx b/oox/source/vml/vmltextboxcontext.cxx index 0adf9431ff03..d91c66ade821 100644 --- a/oox/source/vml/vmltextboxcontext.cxx +++ b/oox/source/vml/vmltextboxcontext.cxx @@ -34,10 +34,11 @@ using ::oox::core::ContextHandlerRef; // ============================================================================ TextPortionContext::TextPortionContext( ContextHandler2Helper& rParent, - TextBox& rTextBox, const TextFontModel& rParentFont, + TextBox& rTextBox, TextParagraphModel& rParagraph, const TextFontModel& rParentFont, sal_Int32 nElement, const AttributeList& rAttribs ) : ContextHandler2( rParent ), mrTextBox( rTextBox ), + maParagraph( rParagraph ), maFont( rParentFont ), mnInitialPortions( rTextBox.getPortionCount() ) { @@ -96,7 +97,7 @@ ContextHandlerRef TextPortionContext::onCreateContext( sal_Int32 nElement, const OSL_ENSURE( nElement != XML_font, "TextPortionContext::onCreateContext - nested <font> elements" ); if (getNamespace(getCurrentElement()) == NMSP_doc) return this; - return new TextPortionContext( *this, mrTextBox, maFont, nElement, rAttribs ); + return new TextPortionContext( *this, mrTextBox, maParagraph, maFont, nElement, rAttribs ); } void TextPortionContext::onCharacters( const OUString& rChars ) @@ -108,10 +109,10 @@ void TextPortionContext::onCharacters( const OUString& rChars ) { case XML_span: // replace all NBSP characters with SP - mrTextBox.appendPortion( maFont, rChars.replace( 0xA0, ' ' ) ); + mrTextBox.appendPortion( maParagraph, maFont, rChars.replace( 0xA0, ' ' ) ); break; default: - mrTextBox.appendPortion( maFont, rChars ); + mrTextBox.appendPortion( maParagraph, maFont, rChars ); } } @@ -125,6 +126,12 @@ void TextPortionContext::onStartElement(const AttributeList& rAttribs) case OOX_TOKEN(doc, sz): maFont.monSize = rAttribs.getInteger( OOX_TOKEN(doc, val) ); break; + case OOX_TOKEN(doc, br): + mrTextBox.appendPortion( maParagraph, maFont, "\n" ); + break; + case OOX_TOKEN(doc, color): + maFont.moColor = rAttribs.getString( OOX_TOKEN(doc, val) ); + break; } } @@ -150,7 +157,7 @@ void TextPortionContext::onEndElement() meantime, the space character has to be added manually. */ if( mrTextBox.getPortionCount() == mnInitialPortions ) - mrTextBox.appendPortion( maFont, OUString( sal_Unicode( ' ' ) ) ); + mrTextBox.appendPortion( maParagraph, maFont, OUString( sal_Unicode( ' ' ) ) ); } // ============================================================================ @@ -204,18 +211,43 @@ ContextHandlerRef TextBoxContext::onCreateContext( sal_Int32 nElement, const Att else if (nElement == OOX_TOKEN(doc, txbxContent)) return this; break; case XML_div: - if( nElement == XML_font ) return new TextPortionContext( *this, mrTextBox, TextFontModel(), nElement, rAttribs ); + if( nElement == XML_font ) return new TextPortionContext( *this, mrTextBox, maParagraph, TextFontModel(), nElement, rAttribs ); break; case OOX_TOKEN(doc, txbxContent): if (nElement == OOX_TOKEN(doc, p)) return this; break; case OOX_TOKEN(doc, p): - if (nElement == OOX_TOKEN(doc, r)) return new TextPortionContext( *this, mrTextBox, TextFontModel(), nElement, rAttribs ); + if (nElement == OOX_TOKEN(doc, r)) + return new TextPortionContext( *this, mrTextBox, maParagraph, TextFontModel(), nElement, rAttribs ); + else + return this; + break; + case OOX_TOKEN(doc, pPr): + return this; break; } return 0; } +void TextBoxContext::onStartElement(const AttributeList& rAttribs) +{ + switch (getCurrentElement()) + { + case OOX_TOKEN(doc, jc): + maParagraph.moParaAdjust = rAttribs.getString( OOX_TOKEN(doc, val) ); + break; + } +} + +void TextBoxContext::onEndElement() +{ + if (getCurrentElement() == OOX_TOKEN(doc, p)) + { + mrTextBox.appendPortion( maParagraph, TextFontModel(), "\n" ); + maParagraph = TextParagraphModel(); + } +} + // ============================================================================ } // namespace vml diff --git a/sw/qa/extras/ooxmlimport/data/fdo46361.docx b/sw/qa/extras/ooxmlimport/data/fdo46361.docx Binary files differnew file mode 100644 index 000000000000..2f894e4b3ccd --- /dev/null +++ b/sw/qa/extras/ooxmlimport/data/fdo46361.docx diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx index a398d91b8714..6ff2400b7478 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx @@ -11,6 +11,7 @@ #include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp> #include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include <com/sun/star/drawing/XControlShape.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> #include <com/sun/star/text/HoriOrientation.hpp> @@ -122,6 +123,7 @@ public: void testN820788(); void testN820504(); void testFdo43641(); + void testFdo46361(); CPPUNIT_TEST_SUITE(Test); #if !defined(MACOSX) && !defined(WNT) @@ -210,6 +212,7 @@ void Test::run() {"n820788.docx", &Test::testN820788}, {"n820504.docx", &Test::testN820504}, {"fdo43641.docx", &Test::testFdo43641}, + {"fdo46361.docx", &Test::testFdo46361}, }; header(); for (unsigned int i = 0; i < SAL_N_ELEMENTS(aMethods); ++i) @@ -365,7 +368,7 @@ xray ThisComponent.DrawPage(1).getByIndex(0).Anchor.PageStyleName uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(1), uno::UNO_QUERY); uno::Reference<text::XTextRange> xShape(xShapes->getByIndex(0), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(OUString("TEXT1"), xShape->getString()); + CPPUNIT_ASSERT_EQUAL(OUString("TEXT1\n"), xShape->getString()); // we want to test the textbox is on the first page (it was put onto another page without the fix), // use a small trick and instead of checking the page layout, check the page style uno::Reference<text::XTextContent> xTextContent(xShape, uno::UNO_QUERY); @@ -1482,6 +1485,26 @@ void Test::testFdo43641() CPPUNIT_ASSERT_EQUAL(sal_Int32(EMU_TO_MM100(928694)), xLine->getSize().Width); } +void Test::testFdo46361() +{ + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xGroupShape(xDraws->getByIndex(0), uno::UNO_QUERY); + uno::Reference<drawing::XShape> xShape(xGroupShape->getByIndex(0), uno::UNO_QUERY); + // This was CENTER. + CPPUNIT_ASSERT_EQUAL(drawing::TextVerticalAdjust_TOP, getProperty<drawing::TextVerticalAdjust>(xShape, "TextVerticalAdjust")); + uno::Reference<text::XText> xText = uno::Reference<text::XTextRange>(xShape, uno::UNO_QUERY)->getText(); + uno::Reference<text::XTextRange> xParagraph = getParagraphOfText(1, xText); + // This was LEFT. + CPPUNIT_ASSERT_EQUAL(style::ParagraphAdjust_CENTER, static_cast<style::ParagraphAdjust>(getProperty<sal_Int16>(xParagraph, "ParaAdjust"))); + // This was black, not green. + CPPUNIT_ASSERT_EQUAL(sal_Int32(0x008000), getProperty<sal_Int32>(getRun(xParagraph, 1), "CharColor")); + // \n char was missing due to unhandled w:br. + CPPUNIT_ASSERT_EQUAL(OUString("text\ntext"), uno::Reference<text::XTextRange>(xGroupShape->getByIndex(1), uno::UNO_QUERY)->getString()); + // \n chars were missing, due to unhandled multiple w:p tags. + CPPUNIT_ASSERT_EQUAL(OUString("text\ntext\n"), uno::Reference<text::XTextRange>(xGroupShape->getByIndex(2), uno::UNO_QUERY)->getString()); +} + CPPUNIT_TEST_SUITE_REGISTRATION(Test); CPPUNIT_PLUGIN_IMPLEMENT(); |