diff options
-rw-r--r-- | writerfilter/Library_rtftok.mk | 1 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdocumentimpl.cxx | 334 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdocumentimpl.hxx | 29 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfsdrimport.cxx | 330 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfsdrimport.hxx | 55 |
5 files changed, 451 insertions, 298 deletions
diff --git a/writerfilter/Library_rtftok.mk b/writerfilter/Library_rtftok.mk index b4345454a163..472ed9303168 100644 --- a/writerfilter/Library_rtftok.mk +++ b/writerfilter/Library_rtftok.mk @@ -62,6 +62,7 @@ $(eval $(call gb_Library_add_linked_libs,rtftok,\ $(eval $(call gb_Library_add_exception_objects,rtftok,\ writerfilter/source/rtftok/rtfdocumentfactory \ writerfilter/source/rtftok/rtfdocumentimpl \ + writerfilter/source/rtftok/rtfsdrimport \ writerfilter/source/rtftok/rtfcontrolwords \ writerfilter/source/rtftok/rtfcharsets \ writerfilter/source/rtftok/rtfreferenceproperties \ diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index 8fdabc5e4146..ccb6766e33ee 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -26,6 +26,7 @@ */ #include <rtfdocumentimpl.hxx> +#include <rtfsdrimport.hxx> #include <rtftypes.hxx> #include <rtfcontrolwords.hxx> #include <rtfvalue.hxx> @@ -153,19 +154,6 @@ static void lcl_putBorderProperty(std::stack<RTFParserState>& aStates, Id nId, R } } -static void lcl_Break(Stream& rMapper) -{ - sal_uInt8 sBreak[] = { 0xd }; - rMapper.text(sBreak, 1); -} - -static void lcl_TableBreak(Stream& rMapper) -{ - lcl_Break(rMapper); - rMapper.endParagraphGroup(); - rMapper.startParagraphGroup(); -} - // NEEDSWORK: DocxAttributeOutput's impl_AppendTwoDigits does the same. static void lcl_AppendTwoDigits(OStringBuffer &rBuffer, sal_Int32 nNum) { @@ -263,18 +251,6 @@ static const char* lcl_RtfToString(RTFKeyword nKeyword) return NULL; } -// NEEDSWORK: wwUtility::BGRToRGB does the same. -sal_uInt32 lcl_BGRToRGB(sal_uInt32 nColor) -{ - sal_uInt8 - r(static_cast<sal_uInt8>(nColor&0xFF)), - g(static_cast<sal_uInt8>(((nColor)>>8)&0xFF)), - b(static_cast<sal_uInt8>((nColor>>16)&0xFF)), - t(static_cast<sal_uInt8>((nColor>>24)&0xFF)); - nColor = (t<<24) + (r<<16) + (g<<8) + b; - return nColor; -} - RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& xContext, uno::Reference<io::XInputStream> const& xInputStream, uno::Reference<lang::XComponent> const& xDstDoc, @@ -316,10 +292,13 @@ RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x OSL_ASSERT(xDrawings.is()); m_xDrawPage.set(xDrawings->getDrawPage(), uno::UNO_QUERY); OSL_ASSERT(m_xDrawPage.is()); + + m_pSdrImport = new RTFSdrImport(*this); } RTFDocumentImpl::~RTFDocumentImpl() { + delete m_pSdrImport; } SvStream& RTFDocumentImpl::Strm() @@ -385,12 +364,25 @@ void RTFDocumentImpl::checkFirstRun() } } +void RTFDocumentImpl::runBreak() +{ + sal_uInt8 sBreak[] = { 0xd }; + Mapper().text(sBreak, 1); +} + +void RTFDocumentImpl::tableBreak() +{ + runBreak(); + Mapper().endParagraphGroup(); + Mapper().startParagraphGroup(); +} + void RTFDocumentImpl::parBreak() { checkFirstRun(); // end previous paragraph Mapper().startCharacterGroup(); - lcl_Break(Mapper()); + runBreak(); Mapper().endCharacterGroup(); Mapper().endParagraphGroup(); @@ -746,7 +738,7 @@ void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer) new RTFReferenceProperties(m_aStates.top().aTableCellAttributes, m_aStates.top().aTableCellSprms) ); Mapper().props(pTableCellProperties); - lcl_TableBreak(Mapper()); + tableBreak(); break; } else if (aPair.first == BUFFER_STARTRUN) @@ -1075,7 +1067,7 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword) ); Mapper().props(pTableRowProperties); - lcl_TableBreak(Mapper()); + tableBreak(); m_bNeedPap = true; m_aTableBuffer.clear(); } @@ -2347,7 +2339,7 @@ int RTFDocumentImpl::popState() } else if (m_aStates.top().nDestinationState == DESTINATION_PICPROP || m_aStates.top().nDestinationState == DESTINATION_SHAPEINSTRUCTION) - resolveShapeProperties(m_aStates.top().aShape.aProperties); + m_pSdrImport->resolve(m_aStates.top().aShape); else if (m_aStates.top().nDestinationState == DESTINATION_REVISIONENTRY) m_aAuthors[m_aAuthors.size()] = m_aDestinationText.makeStringAndClear(); else if (m_aStates.top().nDestinationState == DESTINATION_BOOKMARKSTART) @@ -2435,264 +2427,6 @@ int RTFDocumentImpl::popState() return 0; } -void RTFDocumentImpl::createShape(OUString aStr, uno::Reference<drawing::XShape>& xShape, uno::Reference<beans::XPropertySet>& xPropertySet) -{ - xShape.set(m_xModelFactory->createInstance(aStr), uno::UNO_QUERY); - xPropertySet.set(xShape, uno::UNO_QUERY); -} - -void RTFDocumentImpl::resolveShapeProperties(std::vector< std::pair<rtl::OUString, rtl::OUString> >& rShapeProperties) -{ - int nType = -1; - bool bPib = false; - bool bCustom = false; - - uno::Reference<drawing::XShape> xShape; - uno::Reference<beans::XPropertySet> xPropertySet; - // Create this early, as custom shapes may have properties before the type arrives. - createShape(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CustomShape")), xShape, xPropertySet); - uno::Any aAny; - beans::PropertyValue aPropertyValue; - awt::Rectangle aViewBox; - std::vector<beans::PropertyValue> aPathPropVec; - - for (std::vector< std::pair<rtl::OUString, rtl::OUString> >::iterator i = rShapeProperties.begin(); i != rShapeProperties.end(); ++i) - { - if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("shapeType"))) - { - nType = i->second.toInt32(); - switch (nType) - { - case 20: // Line - createShape(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.LineShape")), xShape, xPropertySet); - break; - default: - bCustom = true; - break; - } - - // Defaults - aAny <<= (sal_uInt32)0xffffff; // White in Word, kind of blue in Writer. - xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")), aAny); - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzName"))) - { - RTFValue::Pointer_t pValue(new RTFValue(i->second)); - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_name, pValue)); - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzDescription"))) - { - RTFValue::Pointer_t pValue(new RTFValue(i->second)); - m_aStates.top().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_descr, pValue)); - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pib"))) - { - m_aDestinationText.setLength(0); - m_aDestinationText.append(i->second); - bPib = true; - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fillColor"))) - { - aAny <<= lcl_BGRToRGB(i->second.toInt32()); - xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")), aAny); - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fillBackColor"))) - ; // Ignore: complementer of fillColor - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("lineColor"))) - { - aAny <<= lcl_BGRToRGB(i->second.toInt32()); - xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LineColor")), aAny); - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("lineBackColor"))) - ; // Ignore: complementer of lineColor - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("txflTextFlow"))) - { - if (i->second.toInt32() == 1) - { - aAny <<= text::WritingMode_TB_RL; - xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("TextWritingMode")), aAny); - } - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fLine"))) - { - if (i->second.toInt32() == 0) - { - aAny <<= drawing::LineStyle_NONE; - xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LineStyle")), aAny); - } - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pVerticies"))) - { - uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aCoordinates; - sal_Int32 nSize = 0; // Size of a token (it's value is hardwired in the exporter) - sal_Int32 nCount = 0; // Number of tokens - sal_Int32 nCharIndex = 0; // Character index - sal_Int32 nIndex = 0; // Array index - do - { - OUString aToken = i->second.getToken(0, ';', nCharIndex); - if (!nSize) - nSize = aToken.toInt32(); - else if (!nCount) - { - nCount = aToken.toInt32(); - aCoordinates.realloc(nCount); - } - else - { - // The coordinates are in an (x,y) form. - aToken = aToken.copy(1, aToken.getLength() - 2); - sal_Int32 nI = 0; - sal_Int32 nX = 0; - sal_Int32 nY = 0; - do - { - OUString aPoint = aToken.getToken(0, ',', nI); - if (!nX) - nX = aPoint.toInt32(); - else - nY = aPoint.toInt32(); - } - while (nI >= 0); - aCoordinates[nIndex].First.Value <<= nX; - aCoordinates[nIndex].Second.Value <<= nY; - nIndex++; - } - } - while (nCharIndex >= 0); - aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Coordinates")); - aPropertyValue.Value <<= aCoordinates; - aPathPropVec.push_back(aPropertyValue); - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pSegmentInfo"))) - { - uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments; - sal_Int32 nSize = 0; - sal_Int32 nCount = 0; - sal_Int32 nCharIndex = 0; - sal_Int32 nIndex = 0; - do - { - sal_Int32 nSeg = i->second.getToken(0, ';', nCharIndex).toInt32(); - if (!nSize) - nSize = nSeg; - else if (!nCount) - { - nCount = nSeg; - aSegments.realloc(nCount); - } - else - { - switch (nSeg) - { - case 0x0001: // lineto - aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO; - aSegments[nIndex].Count = sal_Int32(1); - break; - case 0x4000: // moveto - aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::MOVETO; - aSegments[nIndex].Count = sal_Int32(1); - break; - case 0x2001: // curveto - aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::CURVETO; - aSegments[nIndex].Count = sal_Int32(1); - break; - case 0xb300: // arcto - aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ARCTO; - aSegments[nIndex].Count = sal_Int32(0); - break; - case 0xac00: - case 0xaa00: // nofill - case 0xab00: // nostroke - case 0x6001: // close - break; - case 0x8000: // end - aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH; - aSegments[nIndex].Count = sal_Int32(0); - break; - default: - OSL_TRACE("%s: unhandled segment '%x' in the path", OSL_THIS_FUNC, nSeg); - break; - } - nIndex++; - } - } - while (nCharIndex >= 0); - aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Segments")); - aPropertyValue.Value <<= aSegments; - aPathPropVec.push_back(aPropertyValue); - } - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoLeft"))) - aViewBox.X = i->second.toInt32(); - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoTop"))) - aViewBox.Y = i->second.toInt32(); - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoRight"))) - aViewBox.Width = i->second.toInt32(); - else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoBottom"))) - aViewBox.Height = i->second.toInt32(); - else - OSL_TRACE("%s: TODO handle shape property '%s':'%s'", OSL_THIS_FUNC, - OUStringToOString( i->first, RTL_TEXTENCODING_UTF8 ).getStr(), - OUStringToOString( i->second, RTL_TEXTENCODING_UTF8 ).getStr()); - } - - if (nType == 75) // picture frame - { - if (bPib) - resolvePict(false); - return; - } - - m_xDrawPage->add(xShape); - if (bCustom) - { - uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY); - xDefaulter->createCustomShapeDefaults(OUString::valueOf(sal_Int32(nType))); - } - - // Creating Path property - uno::Sequence<beans::PropertyValue> aPathPropSeq(aPathPropVec.size()); - beans::PropertyValue* pPathValues = aPathPropSeq.getArray(); - for (std::vector<beans::PropertyValue>::iterator i = aPathPropVec.begin(); i != aPathPropVec.end(); ++i) - *pPathValues++ = *i; - - // Creating CustomShapeGeometry property - std::vector<beans::PropertyValue> aGeomPropVec; - if (aViewBox.X || aViewBox.Y || aViewBox.Width || aViewBox.Height) - { - aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("ViewBox")); - aPropertyValue.Value <<= aViewBox; - aGeomPropVec.push_back(aPropertyValue); - } - if (aPathPropSeq.getLength()) - { - aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Path")); - aPropertyValue.Value <<= aPathPropSeq; - aGeomPropVec.push_back(aPropertyValue); - } - uno::Sequence<beans::PropertyValue> aGeomPropSeq(aGeomPropVec.size()); - beans::PropertyValue* pGeomValues = aGeomPropSeq.getArray(); - for (std::vector<beans::PropertyValue>::iterator i = aGeomPropVec.begin(); i != aGeomPropVec.end(); ++i) - *pGeomValues++ = *i; - if (aGeomPropSeq.getLength()) - xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("CustomShapeGeometry")), uno::Any(aGeomPropSeq)); - - // Set position and size - xShape->setPosition(awt::Point(m_aStates.top().aShape.nLeft, m_aStates.top().aShape.nTop)); - xShape->setSize(awt::Size(m_aStates.top().aShape.nRight - m_aStates.top().aShape.nLeft, - m_aStates.top().aShape.nBottom - m_aStates.top().aShape.nTop)); - - // Send it to dmapper - Mapper().startShape(xShape); - Mapper().startParagraphGroup(); - replayBuffer(m_aShapetextBuffer); - Mapper().startCharacterGroup(); - lcl_Break(Mapper()); - Mapper().endCharacterGroup(); - Mapper().endParagraphGroup(); - Mapper().endShape(); -} - int RTFDocumentImpl::resolveParse() { OSL_TRACE("%s", OSL_THIS_FUNC); @@ -2772,6 +2506,32 @@ int RTFDocumentImpl::resolveParse() return "RTFDocumentImpl"; } +com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory> RTFDocumentImpl::getModelFactory() +{ + return m_xModelFactory; +} + +RTFParserState& RTFDocumentImpl::getState() +{ + return m_aStates.top(); +} + +void RTFDocumentImpl::setDestinationText(OUString& rString) +{ + m_aDestinationText.setLength(0); + m_aDestinationText.append(rString); +} + +void RTFDocumentImpl::replayShapetext() +{ + replayBuffer(m_aShapetextBuffer); +} + +com::sun::star::uno::Reference<com::sun::star::drawing::XDrawPage> RTFDocumentImpl::getDrawPage() +{ + return m_xDrawPage; +} + RTFParserState::RTFParserState() : nInternalState(INTERNAL_NORMAL), nDestinationState(DESTINATION_NORMAL), diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx index b9133ed80065..2daf9fd2c216 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx @@ -220,6 +220,8 @@ namespace writerfilter { bool bIsCjk; }; + class RTFSdrImport; + /// Implementation of the RTFDocument interface. class RTFDocumentImpl : public RTFDocument @@ -234,25 +236,30 @@ namespace writerfilter { virtual void resolve(Stream & rHandler); virtual std::string getType() const; - SvStream& Strm(); Stream& Mapper(); + void setSubstream(bool bIsSubtream); + void setIgnoreFirst(rtl::OUString& rIgnoreFirst); + void seek(sal_uInt32 nPos); + com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory> getModelFactory(); + RTFParserState& getState(); + void setDestinationText(rtl::OUString& rString); + /// Resolve a picture: If not inline, then anchored. + int resolvePict(bool bInline); + com::sun::star::uno::Reference<com::sun::star::drawing::XDrawPage> getDrawPage(); + void runBreak(); + void replayShapetext(); + private: + SvStream& Strm(); sal_uInt32 getColorTable(sal_uInt32 nIndex); sal_uInt32 getEncodingTable(sal_uInt32 nFontIndex); void skipDestination(bool bParsed); RTFSprms_t mergeSprms(); RTFSprms_t mergeAttributes(); - void setSubstream(bool bIsSubtream); - void setIgnoreFirst(rtl::OUString& rIgnoreFirst); void resolveSubstream(sal_uInt32 nPos, Id nId); void resolveSubstream(sal_uInt32 nPos, Id nId, rtl::OUString& rIgnoreFirst); - void seek(sal_uInt32 nPos); - private: + int resolveParse(); int resolveKeyword(); - void resolveShapeProperties(std::vector< std::pair<rtl::OUString, rtl::OUString> >& rShapeProperties); - void createShape(rtl::OUString aService, - com::sun::star::uno::Reference<drawing::XShape>& xShape, - com::sun::star::uno::Reference<beans::XPropertySet>& xPropertySet); int dispatchKeyword(rtl::OString& rKeyword, bool bParam, int nParam); int dispatchFlag(RTFKeyword nKeyword); @@ -262,12 +269,11 @@ namespace writerfilter { int dispatchValue(RTFKeyword nKeyword, int nParam); int resolveChars(char ch); - /// Resolve a picture: If not inline, then anchored. - int resolvePict(bool bInline); int pushState(); int popState(); void text(rtl::OUString& rString); void parBreak(); + void tableBreak(); /// If this is the first run of the document, starts the initial paragraph. void checkFirstRun(); void sectBreak(bool bFinal); @@ -281,6 +287,7 @@ namespace writerfilter { com::sun::star::uno::Reference<com::sun::star::drawing::XDrawPage> m_xDrawPage; SvStream* m_pInStream; Stream* m_pMapperStream; + RTFSdrImport* m_pSdrImport; /// Same as m_aStates.size(), except that this can be negative for invalid input. int m_nGroup; std::stack<RTFParserState> m_aStates; diff --git a/writerfilter/source/rtftok/rtfsdrimport.cxx b/writerfilter/source/rtftok/rtfsdrimport.cxx new file mode 100644 index 000000000000..ba36fe2a5ee0 --- /dev/null +++ b/writerfilter/source/rtftok/rtfsdrimport.cxx @@ -0,0 +1,330 @@ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Miklos Vajna <vmiklos@frugalware.org> + * Portions created by the Initial Developer are Copyright (C) 2011 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp> +#include <com/sun/star/text/WritingMode.hpp> + +#include <ooxml/resourceids.hxx> // NS_ooxml namespace + +#include <rtfsdrimport.hxx> + +using rtl::OString; +using rtl::OStringBuffer; +using rtl::OUString; +using rtl::OUStringBuffer; +using rtl::OUStringToOString; + +// NEEDSWORK: wwUtility::BGRToRGB does the same. +static sal_uInt32 lcl_BGRToRGB(sal_uInt32 nColor) +{ + sal_uInt8 + r(static_cast<sal_uInt8>(nColor&0xFF)), + g(static_cast<sal_uInt8>(((nColor)>>8)&0xFF)), + b(static_cast<sal_uInt8>((nColor>>16)&0xFF)), + t(static_cast<sal_uInt8>((nColor>>24)&0xFF)); + nColor = (t<<24) + (r<<16) + (g<<8) + b; + return nColor; +} + +namespace writerfilter { +namespace rtftok { + +RTFSdrImport::RTFSdrImport(RTFDocumentImpl& rDocument) + : m_rImport(rDocument) +{ +} + +RTFSdrImport::~RTFSdrImport() +{ +} + +void RTFSdrImport::createShape(OUString aStr, uno::Reference<drawing::XShape>& xShape, uno::Reference<beans::XPropertySet>& xPropertySet) +{ + xShape.set(m_rImport.getModelFactory()->createInstance(aStr), uno::UNO_QUERY); + xPropertySet.set(xShape, uno::UNO_QUERY); +} + +void RTFSdrImport::resolve(RTFShape& rShape) +{ + int nType = -1; + bool bPib = false; + bool bCustom = false; + + uno::Reference<drawing::XShape> xShape; + uno::Reference<beans::XPropertySet> xPropertySet; + // Create this early, as custom shapes may have properties before the type arrives. + createShape(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CustomShape")), xShape, xPropertySet); + uno::Any aAny; + beans::PropertyValue aPropertyValue; + awt::Rectangle aViewBox; + std::vector<beans::PropertyValue> aPathPropVec; + + for (std::vector< std::pair<rtl::OUString, rtl::OUString> >::iterator i = rShape.aProperties.begin(); + i != rShape.aProperties.end(); ++i) + { + if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("shapeType"))) + { + nType = i->second.toInt32(); + switch (nType) + { + case 20: // Line + createShape(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.LineShape")), xShape, xPropertySet); + break; + default: + bCustom = true; + break; + } + + // Defaults + aAny <<= (sal_uInt32)0xffffff; // White in Word, kind of blue in Writer. + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")), aAny); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzName"))) + { + RTFValue::Pointer_t pValue(new RTFValue(i->second)); + m_rImport.getState().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_name, pValue)); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzDescription"))) + { + RTFValue::Pointer_t pValue(new RTFValue(i->second)); + m_rImport.getState().aCharacterAttributes.push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_descr, pValue)); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pib"))) + { + m_rImport.setDestinationText(i->second); + bPib = true; + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fillColor"))) + { + aAny <<= lcl_BGRToRGB(i->second.toInt32()); + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")), aAny); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fillBackColor"))) + ; // Ignore: complementer of fillColor + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("lineColor"))) + { + aAny <<= lcl_BGRToRGB(i->second.toInt32()); + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LineColor")), aAny); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("lineBackColor"))) + ; // Ignore: complementer of lineColor + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("txflTextFlow"))) + { + if (i->second.toInt32() == 1) + { + aAny <<= text::WritingMode_TB_RL; + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("TextWritingMode")), aAny); + } + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fLine"))) + { + if (i->second.toInt32() == 0) + { + aAny <<= drawing::LineStyle_NONE; + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LineStyle")), aAny); + } + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pVerticies"))) + { + uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aCoordinates; + sal_Int32 nSize = 0; // Size of a token (it's value is hardwired in the exporter) + sal_Int32 nCount = 0; // Number of tokens + sal_Int32 nCharIndex = 0; // Character index + sal_Int32 nIndex = 0; // Array index + do + { + OUString aToken = i->second.getToken(0, ';', nCharIndex); + if (!nSize) + nSize = aToken.toInt32(); + else if (!nCount) + { + nCount = aToken.toInt32(); + aCoordinates.realloc(nCount); + } + else + { + // The coordinates are in an (x,y) form. + aToken = aToken.copy(1, aToken.getLength() - 2); + sal_Int32 nI = 0; + sal_Int32 nX = 0; + sal_Int32 nY = 0; + do + { + OUString aPoint = aToken.getToken(0, ',', nI); + if (!nX) + nX = aPoint.toInt32(); + else + nY = aPoint.toInt32(); + } + while (nI >= 0); + aCoordinates[nIndex].First.Value <<= nX; + aCoordinates[nIndex].Second.Value <<= nY; + nIndex++; + } + } + while (nCharIndex >= 0); + aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Coordinates")); + aPropertyValue.Value <<= aCoordinates; + aPathPropVec.push_back(aPropertyValue); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pSegmentInfo"))) + { + uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments; + sal_Int32 nSize = 0; + sal_Int32 nCount = 0; + sal_Int32 nCharIndex = 0; + sal_Int32 nIndex = 0; + do + { + sal_Int32 nSeg = i->second.getToken(0, ';', nCharIndex).toInt32(); + if (!nSize) + nSize = nSeg; + else if (!nCount) + { + nCount = nSeg; + aSegments.realloc(nCount); + } + else + { + switch (nSeg) + { + case 0x0001: // lineto + aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO; + aSegments[nIndex].Count = sal_Int32(1); + break; + case 0x4000: // moveto + aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::MOVETO; + aSegments[nIndex].Count = sal_Int32(1); + break; + case 0x2001: // curveto + aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::CURVETO; + aSegments[nIndex].Count = sal_Int32(1); + break; + case 0xb300: // arcto + aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ARCTO; + aSegments[nIndex].Count = sal_Int32(0); + break; + case 0xac00: + case 0xaa00: // nofill + case 0xab00: // nostroke + case 0x6001: // close + break; + case 0x8000: // end + aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH; + aSegments[nIndex].Count = sal_Int32(0); + break; + default: + OSL_TRACE("%s: unhandled segment '%x' in the path", OSL_THIS_FUNC, nSeg); + break; + } + nIndex++; + } + } + while (nCharIndex >= 0); + aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Segments")); + aPropertyValue.Value <<= aSegments; + aPathPropVec.push_back(aPropertyValue); + } + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoLeft"))) + aViewBox.X = i->second.toInt32(); + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoTop"))) + aViewBox.Y = i->second.toInt32(); + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoRight"))) + aViewBox.Width = i->second.toInt32(); + else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoBottom"))) + aViewBox.Height = i->second.toInt32(); + else + OSL_TRACE("%s: TODO handle shape property '%s':'%s'", OSL_THIS_FUNC, + OUStringToOString( i->first, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( i->second, RTL_TEXTENCODING_UTF8 ).getStr()); + } + + if (nType == 75) // picture frame + { + if (bPib) + m_rImport.resolvePict(false); + return; + } + + m_rImport.getDrawPage()->add(xShape); + if (bCustom) + { + uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY); + xDefaulter->createCustomShapeDefaults(OUString::valueOf(sal_Int32(nType))); + } + + // Creating Path property + uno::Sequence<beans::PropertyValue> aPathPropSeq(aPathPropVec.size()); + beans::PropertyValue* pPathValues = aPathPropSeq.getArray(); + for (std::vector<beans::PropertyValue>::iterator i = aPathPropVec.begin(); i != aPathPropVec.end(); ++i) + *pPathValues++ = *i; + + // Creating CustomShapeGeometry property + std::vector<beans::PropertyValue> aGeomPropVec; + if (aViewBox.X || aViewBox.Y || aViewBox.Width || aViewBox.Height) + { + aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("ViewBox")); + aPropertyValue.Value <<= aViewBox; + aGeomPropVec.push_back(aPropertyValue); + } + if (aPathPropSeq.getLength()) + { + aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Path")); + aPropertyValue.Value <<= aPathPropSeq; + aGeomPropVec.push_back(aPropertyValue); + } + uno::Sequence<beans::PropertyValue> aGeomPropSeq(aGeomPropVec.size()); + beans::PropertyValue* pGeomValues = aGeomPropSeq.getArray(); + for (std::vector<beans::PropertyValue>::iterator i = aGeomPropVec.begin(); i != aGeomPropVec.end(); ++i) + *pGeomValues++ = *i; + if (aGeomPropSeq.getLength()) + xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("CustomShapeGeometry")), uno::Any(aGeomPropSeq)); + + // Set position and size + xShape->setPosition(awt::Point(rShape.nLeft, rShape.nTop)); + xShape->setSize(awt::Size(rShape.nRight - rShape.nLeft, rShape.nBottom - rShape.nTop)); + + // Send it to dmapper + m_rImport.Mapper().startShape(xShape); + m_rImport.Mapper().startParagraphGroup(); + m_rImport.replayShapetext(); + m_rImport.Mapper().startCharacterGroup(); + m_rImport.runBreak(); + m_rImport.Mapper().endCharacterGroup(); + m_rImport.Mapper().endParagraphGroup(); + m_rImport.Mapper().endShape(); +} + +} // namespace rtftok +} // namespace writerfilter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/rtftok/rtfsdrimport.hxx b/writerfilter/source/rtftok/rtfsdrimport.hxx new file mode 100644 index 000000000000..3c45950272de --- /dev/null +++ b/writerfilter/source/rtftok/rtfsdrimport.hxx @@ -0,0 +1,55 @@ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Miklos Vajna <vmiklos@frugalware.org> + * Portions created by the Initial Developer are Copyright (C) 2011 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef _RTFSDRIMPORT_HXX_ +#define _RTFSDRIMPORT_HXX_ + +#include <rtfdocumentimpl.hxx> + +namespace writerfilter { + namespace rtftok { + /// Handles the import of drawings using RTF markup. + class RTFSdrImport + { + public: + RTFSdrImport(RTFDocumentImpl& rDocument); + virtual ~RTFSdrImport(); + + void resolve(RTFShape& rShape); + private: + void createShape(rtl::OUString aService, + com::sun::star::uno::Reference<drawing::XShape>& xShape, + com::sun::star::uno::Reference<beans::XPropertySet>& xPropertySet); + + RTFDocumentImpl& m_rImport; + }; + } // namespace rtftok +} // namespace writerfilter + +#endif // _RTFSDRIPORT_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |