summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@suse.cz>2013-07-01 12:05:23 +0200
committerFridrich Strba <fridrich@documentfoundation.org>2013-07-02 14:15:30 +0000
commit2b4d78598c55389b24b4a5016279aed26ac0fb2e (patch)
tree14238365c69950ecdd159566c566002e4e8b4141
parent3820420edfb828e49735becf796803f0558ef844 (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.hxx1
-rw-r--r--include/oox/vml/vmltextbox.hxx11
-rw-r--r--include/oox/vml/vmltextboxcontext.hxx5
-rw-r--r--oox/source/vml/vmlshape.cxx9
-rw-r--r--oox/source/vml/vmlshapecontext.cxx1
-rw-r--r--oox/source/vml/vmltextbox.cxx34
-rw-r--r--oox/source/vml/vmltextboxcontext.cxx46
-rw-r--r--sw/qa/extras/ooxmlimport/data/fdo46361.docxbin0 -> 13791 bytes
-rw-r--r--sw/qa/extras/ooxmlimport/ooxmlimport.cxx25
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
new file mode 100644
index 000000000000..2f894e4b3ccd
--- /dev/null
+++ b/sw/qa/extras/ooxmlimport/data/fdo46361.docx
Binary files differ
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();