diff --git a/bsc1110348.patch b/bsc1110348.patch new file mode 100644 index 0000000..f679997 --- /dev/null +++ b/bsc1110348.patch @@ -0,0 +1,275 @@ +From b77f4f69bb2f1d3ab740446799da2fd3db9094da Mon Sep 17 00:00:00 2001 +From: Balazs Varga +Date: Wed, 31 Oct 2018 08:43:47 +0100 +Subject: [PATCH] tdf#108104 OOXML Import: Fix Hatch fill in Charts + +Sets an explicit fill hatch, or creates a named fill hatch +and stored in a global container. With this patch the +SUPPORTED MS Office hatch styles by LibreOffice, or the custom +LibreOffice hatches will be appeared correctly instead of the +previous display as horizontal lines in LibreOffice. +(The background color of the hatch styles are not imported correcty, +but that is another BUG.) + +Change-Id: Ifda9dc805dd08f58db10b35f40d7f511a8614f77 +Reviewed-on: https://gerrit.libreoffice.org/62681 +Tested-by: Jenkins +Reviewed-by: Miklos Vajna +Reviewed-on: https://gerrit.libreoffice.org/62891 +Reviewed-by: Andras Timar +--- + +diff --git a/include/oox/drawingml/shapepropertymap.hxx b/include/oox/drawingml/shapepropertymap.hxx +index 2fb237c..dd2d0d4 100644 +--- a/include/oox/drawingml/shapepropertymap.hxx ++++ b/include/oox/drawingml/shapepropertymap.hxx +@@ -71,7 +71,7 @@ + FillBitmapOffsetX, + FillBitmapOffsetY, + FillBitmapRectanglePoint, +- FillHatch, ++ FillHatch, /// Explicit fill hatch or name of a fill hatch stored in a global container. + ShadowXDistance, + FillBitmapName, + FillBackground, +@@ -87,12 +87,13 @@ + bool mbNamedLineDash; /// True = use named line dash instead of explicit line dash. + bool mbNamedFillGradient; /// True = use named fill gradient instead of explicit fill gradient. + bool mbNamedFillBitmap; /// True = use named fill bitmap instead of explicit fill bitmap. ++ bool mbNamedFillHatch; /// True = use named fill hatch instead of explicit fill hatch. + + static ShapePropertyInfo DEFAULT; /// Default property info (used as default parameter of other methods). + + explicit ShapePropertyInfo(const ShapePropertyIds& rnPropertyIds, + bool bNamedLineMarker, bool bNamedLineDash, +- bool bNamedFillGradient, bool bNamedFillBitmap); ++ bool bNamedFillGradient, bool bNamedFillBitmap, bool bNamedFillHatch); + + bool has(ShapeProperty ePropId) const + { +@@ -147,6 +148,8 @@ + bool setFillBitmap( sal_Int32 nPropId, const css::uno::Any& rValue ); + /** Sets an explicit fill bitmap and pushes the name to FillBitmapName */ + bool setFillBitmapName( const css::uno::Any& rValue ); ++ /** Sets an explicit fill hatch, or creates a named fill hatch. */ ++ bool setFillHatch( sal_Int32 nPropId, const css::uno::Any& rValue ); + + // not implemented, to prevent implicit conversion from enum to int + css::uno::Any& operator[]( ShapeProperty ePropId ) = delete; +diff --git a/include/oox/helper/modelobjecthelper.hxx b/include/oox/helper/modelobjecthelper.hxx +index eb9c7ba..016b963 100644 +--- a/include/oox/helper/modelobjecthelper.hxx ++++ b/include/oox/helper/modelobjecthelper.hxx +@@ -32,6 +32,7 @@ + namespace graphic { class XGraphic; } + namespace container { class XNameContainer; } + namespace drawing { struct LineDash; } ++ namespace drawing { struct Hatch; } + namespace drawing { struct PolyPolygonBezierCoords; } + namespace lang { class XMultiServiceFactory; } + } } } +@@ -105,6 +106,8 @@ + + OUString insertTransGrandient( const css::awt::Gradient& rGradient ); + ++ OUString insertFillHatch( const css::drawing::Hatch& rHatch ); ++ + /** Inserts a new named fill graphic, returns the bitmap name, based on + an internal constant name with a new unused index appended. */ + OUString insertFillBitmapXGraphic(css::uno::Reference const & rxGraphic); +@@ -117,10 +120,12 @@ + ObjectContainer maGradientContainer; ///< Contains all named fill gradients. + ObjectContainer maTransGradContainer; ///< Contains all named transparency Gradients. + ObjectContainer maBitmapUrlContainer; ///< Contains all named fill bitmap URLs. ++ ObjectContainer maHatchContainer; ///< Contains all named fill hatches. + const OUString maDashNameBase; ///< Base name for all named line dashes. + const OUString maGradientNameBase; ///< Base name for all named fill gradients. + const OUString maTransGradNameBase; ///< Base name for all named fill gradients. + const OUString maBitmapUrlNameBase; ///< Base name for all named fill bitmap URLs. ++ const OUString maHatchNameBase; ///< Base name for all named fill hatch URLs. + }; + + +diff --git a/oox/source/drawingml/chart/objectformatter.cxx b/oox/source/drawingml/chart/objectformatter.cxx +index 5b5f67b..2eaad42 100644 +--- a/oox/source/drawingml/chart/objectformatter.cxx ++++ b/oox/source/drawingml/chart/objectformatter.cxx +@@ -449,7 +449,8 @@ + PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, + PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_INVALID, PROP_FillGradientName, + PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY, +- PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint ++ PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint, ++ PROP_FillHatchName + }; + + static const ShapePropertyIds spnLinearPropIds = +@@ -458,7 +459,8 @@ + PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, + PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, + PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, +- PROP_INVALID, PROP_INVALID, PROP_INVALID ++ PROP_INVALID, PROP_INVALID, PROP_INVALID, ++ PROP_INVALID + }; + + static const ShapePropertyIds spnFilledPropIds = +@@ -487,15 +489,15 @@ + PROP_FillBitmapPositionOffsetX, + PROP_FillBitmapPositionOffsetY, + PROP_FillBitmapRectanglePoint, +- PROP_FillHatch ++ PROP_HatchName + }; + + /** Property info for common chart objects, to be used in ShapePropertyMap. */ +-static const ShapePropertyInfo saCommonPropInfo( spnCommonPropIds, false, true, true, true ); ++static const ShapePropertyInfo saCommonPropInfo( spnCommonPropIds, false, true, true, true, true ); + /** Property info for linear data series, to be used in ShapePropertyMap. */ +-static const ShapePropertyInfo saLinearPropInfo( spnLinearPropIds, false, true, true, true ); ++static const ShapePropertyInfo saLinearPropInfo( spnLinearPropIds, false, true, true, true, true ); + /** Property info for filled data series, to be used in ShapePropertyMap. */ +-static const ShapePropertyInfo saFilledPropInfo( spnFilledPropIds, false, true, true, true ); ++static const ShapePropertyInfo saFilledPropInfo( spnFilledPropIds, false, true, true, true, true ); + + /** Contains information about formatting of a specific chart object type. */ + struct ObjectTypeFormatEntry +diff --git a/oox/source/drawingml/shapepropertymap.cxx b/oox/source/drawingml/shapepropertymap.cxx +index fcb1549..b072403 100644 +--- a/oox/source/drawingml/shapepropertymap.cxx ++++ b/oox/source/drawingml/shapepropertymap.cxx +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -53,15 +54,16 @@ + + } // namespace + +-ShapePropertyInfo ShapePropertyInfo::DEFAULT( spnDefaultShapeIds, true, false, false, false ); ++ShapePropertyInfo ShapePropertyInfo::DEFAULT( spnDefaultShapeIds, true, false, false, false, false ); + + ShapePropertyInfo::ShapePropertyInfo( const ShapePropertyIds& rnPropertyIds, +- bool bNamedLineMarker, bool bNamedLineDash, bool bNamedFillGradient, bool bNamedFillBitmap ) : ++ bool bNamedLineMarker, bool bNamedLineDash, bool bNamedFillGradient, bool bNamedFillBitmap, bool bNamedFillHatch ) : + mrPropertyIds(rnPropertyIds), + mbNamedLineMarker( bNamedLineMarker ), + mbNamedLineDash( bNamedLineDash ), + mbNamedFillGradient( bNamedFillGradient ), +- mbNamedFillBitmap( bNamedFillBitmap ) ++ mbNamedFillBitmap( bNamedFillBitmap ), ++ mbNamedFillHatch( bNamedFillHatch ) + { + } + +@@ -108,6 +110,9 @@ + + case ShapeProperty::FillBitmapName: + return setFillBitmapName(rValue); ++ ++ case ShapeProperty::FillHatch: ++ return setFillHatch( nPropId, rValue ); + + default:; // suppress compiler warnings + } +@@ -168,6 +173,22 @@ + return false; + } + ++bool ShapePropertyMap::setFillHatch( sal_Int32 nPropId, const Any& rValue ) ++{ ++ // push hatch explicitly ++ if( !maShapePropInfo.mbNamedFillHatch ) ++ return setAnyProperty( nPropId, rValue ); ++ ++ // create named hatch and push its name ++ if( rValue.has< Hatch >() ) ++ { ++ OUString aHatchName = mrModelObjHelper.insertFillHatch( rValue.get< Hatch >() ); ++ return !aHatchName.isEmpty() && setProperty( nPropId, aHatchName ); ++ } ++ ++ return false; ++} ++ + bool ShapePropertyMap::setGradientTrans( sal_Int32 nPropId, const Any& rValue ) + { + // create named gradient and push its name +diff --git a/oox/source/helper/modelobjecthelper.cxx b/oox/source/helper/modelobjecthelper.cxx +index 4929dc2..02481e2 100644 +--- a/oox/source/helper/modelobjecthelper.cxx ++++ b/oox/source/helper/modelobjecthelper.cxx +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -92,12 +93,14 @@ + maMarkerContainer( rxModelFactory, "com.sun.star.drawing.MarkerTable" ), + maDashContainer( rxModelFactory, "com.sun.star.drawing.DashTable" ), + maGradientContainer( rxModelFactory, "com.sun.star.drawing.GradientTable" ), +- maTransGradContainer( rxModelFactory, "com.sun.star.drawing.TransparencyGradientTable" ), ++ maTransGradContainer( rxModelFactory, "com.sun.star.drawing.TransparencyGradientTable" ), + maBitmapUrlContainer( rxModelFactory, "com.sun.star.drawing.BitmapTable" ), ++ maHatchContainer( rxModelFactory, "com.sun.star.drawing.HatchTable" ), + maDashNameBase( "msLineDash " ), + maGradientNameBase( "msFillGradient " ), + maTransGradNameBase( "msTransGradient " ), +- maBitmapUrlNameBase( "msFillBitmap " ) ++ maBitmapUrlNameBase( "msFillBitmap " ), ++ maHatchNameBase( "msFillHatch " ) + { + } + +@@ -137,6 +140,11 @@ + return OUString(); + } + ++OUString ModelObjectHelper::insertFillHatch( const Hatch& rHatch ) ++{ ++ return maHatchContainer.insertObject( maHatchNameBase, Any( rHatch ), true ); ++} ++ + uno::Reference ModelObjectHelper::getFillBitmap(OUString const & rGraphicName) + { + uno::Reference xBitmap; +diff --git a/oox/source/ppt/slidepersist.cxx b/oox/source/ppt/slidepersist.cxx +index 8d6abaa..2704a24 100644 +--- a/oox/source/ppt/slidepersist.cxx ++++ b/oox/source/ppt/slidepersist.cxx +@@ -171,7 +171,7 @@ + + oox::drawingml::ShapePropertyIds aPropertyIds = oox::drawingml::ShapePropertyInfo::DEFAULT.mrPropertyIds; + aPropertyIds[oox::drawingml::ShapeProperty::FillGradient] = PROP_FillGradientName; +- oox::drawingml::ShapePropertyInfo aPropInfo( aPropertyIds, true, false, true, false ); ++ oox::drawingml::ShapePropertyInfo aPropInfo( aPropertyIds, true, false, true, false, false ); + oox::drawingml::ShapePropertyMap aPropMap( rFilterBase.getModelObjectHelper(), aPropInfo ); + mpBackgroundPropertiesPtr->pushToPropMap( aPropMap, rFilterBase.getGraphicHelper(), 0, nPhClr ); + PropertySet( mxPage ).setProperty( PROP_Background, aPropMap.makePropertySet() ); +diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt +index 86dd843..1b06aa7 100644 +--- a/oox/source/token/properties.txt ++++ b/oox/source/token/properties.txt +@@ -171,6 +171,7 @@ + FillGradient + FillGradientName + FillHatch ++FillHatchName + FillStyle + FillTransparence + FillTransparenceGradient +@@ -202,6 +203,7 @@ + GenerateVbaEvents + Geometry3D + GradientName ++HatchName + Graphic + GraphicBitmap + GraphicColorMode diff --git a/bsc1112112.patch b/bsc1112112.patch new file mode 100644 index 0000000..ab42331 --- /dev/null +++ b/bsc1112112.patch @@ -0,0 +1,669 @@ +diff --git a/oox/inc/drawingml/diagram/diagram.hxx b/oox/inc/drawingml/diagram/diagram.hxx +index 5277d98d2dee..a528668c08b4 100644 +--- a/oox/inc/drawingml/diagram/diagram.hxx ++++ b/oox/inc/drawingml/diagram/diagram.hxx +@@ -39,7 +39,8 @@ void loadDiagram( ShapePtr const & pShape, + const OUString& rDataModelPath, + const OUString& rLayoutPath, + const OUString& rQStylePath, +- const OUString& rColorStylePath ); ++ const OUString& rColorStylePath, ++ const oox::core::Relations& rRelations ); + + void loadDiagram( const ShapePtr& pShape, + core::XmlFilterBase& rFilter, +diff --git a/oox/source/drawingml/diagram/constraintlistcontext.cxx b/oox/source/drawingml/diagram/constraintlistcontext.cxx +index 99e3f3d10e72..cc71c89b226a 100644 +--- a/oox/source/drawingml/diagram/constraintlistcontext.cxx ++++ b/oox/source/drawingml/diagram/constraintlistcontext.cxx +@@ -50,7 +50,7 @@ ConstraintListContext::onCreateContext( ::sal_Int32 aElement, + case DGM_TOKEN( constr ): + { + std::shared_ptr< ConstraintAtom > pNode( new ConstraintAtom(mpNode->getLayoutNode()) ); +- mpNode->addChild( pNode ); ++ LayoutAtom::connect(mpNode, pNode); + + Constraint& rConstraint = pNode->getConstraint(); + rConstraint.mnFor = rAttribs.getToken( XML_for, XML_none ); +diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx +index e7a2df78bd5e..4664a55e594c 100644 +--- a/oox/source/drawingml/diagram/diagram.cxx ++++ b/oox/source/drawingml/diagram/diagram.cxx +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + #include "diagramlayoutatoms.hxx" + #include "layoutatomvisitors.hxx" +@@ -375,12 +376,57 @@ void importFragment( core::XmlFilterBase& rFilter, + rFilter.importFragment( rxHandler, xSerializer ); + } + ++namespace ++{ ++/** ++ * A fragment handler that just counts the number of elements in a ++ * fragment. ++ */ ++class DiagramShapeCounter : public oox::core::FragmentHandler2 ++{ ++public: ++ DiagramShapeCounter(oox::core::XmlFilterBase& rFilter, const OUString& rFragmentPath, ++ sal_Int32& nCounter); ++ oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, ++ const AttributeList& rAttribs) override; ++ ++private: ++ sal_Int32& m_nCounter; ++}; ++ ++DiagramShapeCounter::DiagramShapeCounter(oox::core::XmlFilterBase& rFilter, ++ const OUString& rFragmentPath, sal_Int32& nCounter) ++ : FragmentHandler2(rFilter, rFragmentPath) ++ , m_nCounter(nCounter) ++{ ++} ++ ++oox::core::ContextHandlerRef DiagramShapeCounter::onCreateContext(sal_Int32 nElement, ++ const AttributeList& /*rAttribs*/) ++{ ++ switch (nElement) ++ { ++ case DSP_TOKEN(drawing): ++ case DSP_TOKEN(spTree): ++ return this; ++ case DSP_TOKEN(sp): ++ ++m_nCounter; ++ break; ++ default: ++ break; ++ } ++ ++ return nullptr; ++} ++} ++ + void loadDiagram( ShapePtr const & pShape, + core::XmlFilterBase& rFilter, + const OUString& rDataModelPath, + const OUString& rLayoutPath, + const OUString& rQStylePath, +- const OUString& rColorStylePath ) ++ const OUString& rColorStylePath, ++ const oox::core::Relations& rRelations ) + { + DiagramPtr pDiagram( new Diagram ); + +@@ -407,11 +453,26 @@ void loadDiagram( ShapePtr const & pShape, + + // Pass the info to pShape + for (auto const& extDrawing : pData->getExtDrawings()) +- pShape->addExtDrawingRelId(extDrawing); ++ { ++ OUString aFragmentPath = rRelations.getFragmentPathFromRelId(extDrawing); ++ // Ignore RelIds which don't resolve to a fragment path. ++ if (aFragmentPath.isEmpty()) ++ continue; ++ ++ sal_Int32 nCounter = 0; ++ rtl::Reference xCounter( ++ new DiagramShapeCounter(rFilter, aFragmentPath, nCounter)); ++ rFilter.importFragment(xCounter); ++ // Ignore ext drawings which don't actually have any shapes. ++ if (nCounter == 0) ++ continue; ++ ++ pShape->addExtDrawingRelId(extDrawing); ++ } + } + + // extLst is present, lets bet on that and ignore the rest of the data from here +- if( pData->getExtDrawings().empty() ) ++ if( pShape->getExtDrawings().empty() ) + { + // layout + if( !rLayoutPath.isEmpty() ) +diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +index 3c8993bd687d..c1aaf6e07025 100644 +--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx ++++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx +@@ -35,6 +35,27 @@ using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::xml::sax; + using namespace ::oox::core; + ++namespace ++{ ++/// Looks up the value of the rInternalName -> nProperty key in rProperties. ++oox::OptValue findProperty(const oox::drawingml::LayoutPropertyMap& rProperties, ++ const OUString& rInternalName, sal_Int32 nProperty) ++{ ++ oox::OptValue oRet; ++ ++ auto it = rProperties.find(rInternalName); ++ if (it != rProperties.end()) ++ { ++ const oox::drawingml::LayoutProperty& rProperty = it->second; ++ auto itProperty = rProperty.find(nProperty); ++ if (itProperty != rProperty.end()) ++ oRet = itProperty->second; ++ } ++ ++ return oRet; ++} ++} ++ + namespace oox { namespace drawingml { + + IteratorAttr::IteratorAttr( ) +@@ -145,6 +166,36 @@ const dgm::Point* ConditionAtom::getPresNode() const + return nullptr; + } + ++namespace ++{ ++/** ++ * Takes the connection list from rLayoutNode, navigates from rFrom on an edge ++ * of type nType, using a direction determined by bSourceToDestination. ++ */ ++OUString navigate(const LayoutNode& rLayoutNode, sal_Int32 nType, const OUString& rFrom, ++ bool bSourceToDestination) ++{ ++ for (const auto& rConnection : rLayoutNode.getDiagram().getData()->getConnections()) ++ { ++ if (rConnection.mnType != nType) ++ continue; ++ ++ if (bSourceToDestination) ++ { ++ if (rConnection.msSourceId == rFrom) ++ return rConnection.msDestId; ++ } ++ else ++ { ++ if (rConnection.msDestId == rFrom) ++ return rConnection.msSourceId; ++ } ++ } ++ ++ return OUString(); ++} ++} ++ + sal_Int32 ConditionAtom::getNodeCount() const + { + sal_Int32 nCount = 0; +@@ -153,9 +204,21 @@ sal_Int32 ConditionAtom::getNodeCount() const + { + OUString sNodeId = ""; + +- for (const auto& aCxn : mrLayoutNode.getDiagram().getData()->getConnections()) +- if (aCxn.mnType == XML_presOf && aCxn.msDestId == pPoint->msModelId) +- sNodeId = aCxn.msSourceId; ++ sNodeId ++ = navigate(mrLayoutNode, XML_presOf, pPoint->msModelId, /*bSourceToDestination*/ false); ++ ++ if (sNodeId.isEmpty()) ++ { ++ // The current layout node is not a presentation of anything. Look ++ // up the first presentation child of the layout node. ++ OUString sFirstPresChildId = navigate(mrLayoutNode, XML_presParOf, pPoint->msModelId, ++ /*bSourceToDestination*/ true); ++ if (!sFirstPresChildId.isEmpty()) ++ // It has a presentation child: is that a presentation of a ++ // model node? ++ sNodeId = navigate(mrLayoutNode, XML_presOf, sFirstPresChildId, ++ /*bSourceToDestination*/ false); ++ } + + if (!sNodeId.isEmpty()) + { +@@ -224,8 +287,22 @@ void AlgAtom::accept( LayoutAtomVisitor& rVisitor ) + } + + void AlgAtom::layoutShape( const ShapePtr& rShape, +- const std::vector& rConstraints ) const ++ const std::vector& rOwnConstraints ) const + { ++ // Algorithm result may depend on the parent constraints as well. ++ std::vector aParentConstraints; ++ const LayoutNode* pParent = getLayoutNode().getParentLayoutNode(); ++ if (pParent) ++ { ++ for (const auto& pChild : pParent->getChildren()) ++ { ++ auto pConstraintAtom = dynamic_cast(pChild.get()); ++ if (pConstraintAtom) ++ pConstraintAtom->parseConstraint(aParentConstraints); ++ } ++ } ++ const std::vector& rConstraints = rOwnConstraints.empty() ? aParentConstraints : rOwnConstraints; ++ + switch(mnType) + { + case XML_composite: +@@ -356,9 +433,9 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, + double fSpace = 0.3; + + awt::Size aChildSize = rShape->getSize(); +- if (nIncX) ++ if (nDir == XML_fromL || nDir == XML_fromR) + aChildSize.Width /= (nCount + (nCount-1)*fSpace); +- if (nIncY) ++ else if (nDir == XML_fromT || nDir == XML_fromB) + aChildSize.Height /= (nCount + (nCount-1)*fSpace); + + awt::Point aCurrPos(0, 0); +@@ -367,12 +444,64 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, + if (nIncY == -1) + aCurrPos.Y = rShape->getSize().Height - aChildSize.Height; + ++ // Find out which contraint is relevant for which (internal) name. ++ LayoutPropertyMap aProperties; ++ for (const auto& rConstraint : rConstraints) ++ { ++ if (rConstraint.msForName.isEmpty()) ++ continue; ++ ++ LayoutProperty& rProperty = aProperties[rConstraint.msForName]; ++ if (rConstraint.mnType == XML_w) ++ rProperty[XML_w] = rShape->getSize().Width * rConstraint.mfFactor; ++ } ++ ++ // See if children requested more than 100% space in total: scale ++ // down in that case. ++ sal_Int32 nTotalWidth = 0; ++ bool bSpaceFromConstraints = false; + for (auto & aCurrShape : rShape->getChildren()) + { ++ oox::OptValue oWidth ++ = findProperty(aProperties, aCurrShape->getInternalName(), XML_w); ++ ++ awt::Size aSize = aChildSize; ++ if (oWidth.has()) ++ { ++ aSize.Width = oWidth.get(); ++ bSpaceFromConstraints = true; ++ } ++ if (nDir == XML_fromL || nDir == XML_fromR) ++ nTotalWidth += aSize.Width; ++ } ++ ++ double fWidthScale = 1.0; ++ if (nTotalWidth > rShape->getSize().Width && nTotalWidth) ++ { ++ fWidthScale = rShape->getSize().Width; ++ fWidthScale /= nTotalWidth; ++ } ++ ++ // Don't add automatic space if we take space from constraints. ++ if (bSpaceFromConstraints) ++ fSpace = 0; ++ ++ for (auto& aCurrShape : rShape->getChildren()) ++ { ++ // Extract properties relevant for this shape from constraints. ++ oox::OptValue oWidth ++ = findProperty(aProperties, aCurrShape->getInternalName(), XML_w); ++ + aCurrShape->setPosition(aCurrPos); +- aCurrShape->setSize(aChildSize); ++ ++ awt::Size aSize = aChildSize; ++ if (oWidth.has()) ++ aSize.Width = oWidth.get(); ++ aSize.Width *= fWidthScale; ++ aCurrShape->setSize(aSize); ++ + aCurrShape->setChildSize(aChildSize); +- aCurrPos.X += nIncX * (aChildSize.Width + fSpace*aChildSize.Width); ++ aCurrPos.X += nIncX * (aSize.Width + fSpace*aSize.Width); + aCurrPos.Y += nIncY * (aChildSize.Height + fSpace*aChildSize.Height); + } + break; +@@ -402,18 +531,19 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, + // TODO: get values from constraints + sal_Int32 nCount = rShape->getChildren().size(); + double fSpace = 0.3; +- double fAspectRatio = 0.6; ++ double fAspectRatio = 0.54; // diagram should not spill outside, earlier it was 0.6 + + sal_Int32 nCol = 1; + sal_Int32 nRow = 1; +- for ( ; nColgetSize().Height; + const double fShapeWidth = rShape->getSize().Width; +- if ((fShapeHeight / nRow) / (fShapeWidth / nCol) >= fAspectRatio) ++ if ((fShapeHeight / nCol) / (fShapeWidth / nRow) >= fAspectRatio) + break; + } ++ + SAL_INFO("oox.drawingml", "Snake layout grid: " << nCol << "x" << nRow); + + sal_Int32 nWidth = rShape->getSize().Width / (nCol + (nCol-1)*fSpace); +@@ -426,20 +556,89 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, + aCurrPos.Y = rShape->getSize().Height - aChildSize.Height; + + sal_Int32 nStartX = aCurrPos.X; +- sal_Int32 nColIdx = 0; ++ sal_Int32 nColIdx = 0,index = 0; + +- for (auto & aCurrShape : rShape->getChildren()) ++ sal_Int32 num = rShape->getChildren().size(); ++ ++ const sal_Int32 aContDir = maMap.count(XML_contDir) ? maMap.find(XML_contDir)->second : XML_sameDir; ++ ++ switch(aContDir) + { +- aCurrShape->setPosition(aCurrPos); +- aCurrShape->setSize(aChildSize); +- aCurrShape->setChildSize(aChildSize); +- aCurrPos.X += nIncX * (aChildSize.Width + fSpace*aChildSize.Width); +- if (++nColIdx == nCol) ++ case XML_sameDir: ++ for (auto & aCurrShape : rShape->getChildren()) + { +- aCurrPos.X = nStartX; +- aCurrPos.Y += nIncY * (aChildSize.Height + fSpace*aChildSize.Height); +- nColIdx = 0; ++ aCurrShape->setPosition(aCurrPos); ++ aCurrShape->setSize(aChildSize); ++ aCurrShape->setChildSize(aChildSize); ++ ++ index++; // counts index of child, helpful for positioning. ++ ++ if(index%nCol==0 || ((index/nCol)+1)!=nRow) ++ aCurrPos.X += nIncX * (aChildSize.Width + fSpace*aChildSize.Width); ++ ++ if(++nColIdx == nCol) // condition for next row ++ { ++ // if last row, then position children according to number of shapes. ++ if((index+1)%nCol!=0 && (index+1)>=3 && ((index+1)/nCol+1)==nRow && num!=nRow*nCol) ++ // position first child of last row ++ aCurrPos.X = nStartX + (nIncX * (aChildSize.Width + fSpace*aChildSize.Width))/2; ++ else ++ // if not last row, positions first child of that row ++ aCurrPos.X = nStartX; ++ aCurrPos.Y += nIncY * (aChildSize.Height + fSpace*aChildSize.Height); ++ nColIdx = 0; ++ } ++ ++ // positions children in the last row. ++ if(index%nCol!=0 && index>=3 && ((index/nCol)+1)==nRow) ++ aCurrPos.X += (nIncX * (aChildSize.Width + fSpace*aChildSize.Width)); + } ++ break; ++ case XML_revDir: ++ for (auto & aCurrShape : rShape->getChildren()) ++ { ++ aCurrShape->setPosition(aCurrPos); ++ aCurrShape->setSize(aChildSize); ++ aCurrShape->setChildSize(aChildSize); ++ ++ index++; // counts index of child, helpful for positioning. ++ ++ /* ++ index%col -> tests node is at last column ++ ((index/nCol)+1)!=nRow) -> tests node is at last row or not ++ ((index/nCol)+1)%2!=0 -> tests node is at row which is multiple of 2, important for revDir ++ num!=nRow*nCol -> tests how last row nodes should be spread. ++ */ ++ ++ if((index%nCol==0 || ((index/nCol)+1)!=nRow) && ((index/nCol)+1)%2!=0) ++ aCurrPos.X += (aChildSize.Width + fSpace*aChildSize.Width); ++ else if( index%nCol!=0 && ((index/nCol)+1)!=nRow) // child other than placed at last column ++ aCurrPos.X -= (aChildSize.Width + fSpace*aChildSize.Width); ++ ++ if(++nColIdx == nCol) // condition for next row ++ { ++ // if last row, then position children according to number of shapes. ++ if((index+1)%nCol!=0 && (index+1)>=4 && ((index+1)/nCol+1)==nRow && num!=nRow*nCol && ((index/nCol)+1)%2==0) ++ // position first child of last row ++ aCurrPos.X -= aChildSize.Width*3/2; ++ else if((index+1)%nCol!=0 && (index+1)>=4 && ((index+1)/nCol+1)==nRow && num!=nRow*nCol && ((index/nCol)+1)%2!=0) ++ aCurrPos.X = nStartX + (nIncX * (aChildSize.Width + fSpace*aChildSize.Width))/2; ++ else if(((index/nCol)+1)%2!=0) ++ aCurrPos.X = nStartX; ++ ++ aCurrPos.Y += nIncY * (aChildSize.Height + fSpace*aChildSize.Height); ++ nColIdx = 0; ++ } ++ ++ // positions children in the last row. ++ if(index%nCol!=0 && index>=3 && ((index/nCol)+1)==nRow && ((index/nCol)+1)%2==0) ++ //if row%2=0 then start from left else ++ aCurrPos.X -= (nIncX * (aChildSize.Width + fSpace*aChildSize.Width)); ++ else if(index%nCol!=0 && index>=3 && ((index/nCol)+1)==nRow && ((index/nCol)+1)%2!=0) ++ // start from right ++ aCurrPos.X += (nIncX * (aChildSize.Width + fSpace*aChildSize.Width)); ++ } ++ break; + } + break; + } +@@ -456,7 +655,6 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, + { + // adjust text alignment + // TODO: adjust text size to fit shape +- + TextBodyPtr pTextBody = rShape->getTextBody(); + if (!pTextBody || + pTextBody->getParagraphs().empty() || +@@ -465,12 +663,44 @@ void AlgAtom::layoutShape( const ShapePtr& rShape, + break; + } + +- if (rShape->getRotation()) +- pTextBody->getTextProperties().moRotation = -rShape->getRotation(); ++ const sal_Int32 nautoTxRot = maMap.count(XML_autoTxRot) ? maMap.find(XML_autoTxRot)->second : XML_upr; ++ ++ switch(nautoTxRot) ++ { ++ case XML_upr: ++ { ++ if (rShape->getRotation()) ++ pTextBody->getTextProperties().moRotation = -F_PI180*90*rShape->getRotation(); ++ } ++ break; ++ case XML_grav: ++ { ++ if (rShape->getRotation()==90*F_PI180 || rShape->getRotation()==180*F_PI180) ++ pTextBody->getTextProperties().moRotation = 180*F_PI180; ++ } ++ break; ++ case XML_none: ++ break; ++ } ++ ++ const sal_Int32 atxAnchorVert = maMap.count(XML_txAnchorVert) ? maMap.find(XML_txAnchorVert)->second : XML_mid; ++ ++ switch(atxAnchorVert) ++ { ++ case XML_t: ++ pTextBody->getTextProperties().meVA = css::drawing::TextVerticalAdjust_TOP; ++ break; ++ case XML_b: ++ pTextBody->getTextProperties().meVA = css::drawing::TextVerticalAdjust_BOTTOM; ++ break; ++ case XML_mid: ++ // text centered vertically by default ++ default: ++ pTextBody->getTextProperties().meVA = css::drawing::TextVerticalAdjust_CENTER; ++ break; ++ } + +- // text centered vertically by default +- pTextBody->getTextProperties().meVA = css::drawing::TextVerticalAdjust_CENTER; +- pTextBody->getTextProperties().maPropertyMap.setProperty(PROP_TextVerticalAdjust, css::drawing::TextVerticalAdjust_CENTER); ++ pTextBody->getTextProperties().maPropertyMap.setProperty(PROP_TextVerticalAdjust, pTextBody->getTextProperties().meVA); + + // normalize list level + sal_Int32 nBaseLevel = pTextBody->getParagraphs().front()->getProperties().getLevel(); +@@ -653,6 +883,18 @@ bool LayoutNode::setupShape( const ShapePtr& rShape, const dgm::Point* pPresNode + return true; + } + ++const LayoutNode* LayoutNode::getParentLayoutNode() const ++{ ++ for (LayoutAtomPtr pAtom = getParent(); pAtom; pAtom = pAtom->getParent()) ++ { ++ auto pLayoutNode = dynamic_cast(pAtom.get()); ++ if (pLayoutNode) ++ return pLayoutNode; ++ } ++ ++ return nullptr; ++} ++ + void ShapeAtom::accept( LayoutAtomVisitor& rVisitor ) + { + rVisitor.visit(*this); +diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx +index 5ab34b042c86..3d4d9c05aae2 100644 +--- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx ++++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx +@@ -106,17 +106,30 @@ public: + const OUString& getName() const + { return msName; } + ++private: + void addChild( const LayoutAtomPtr & pNode ) + { mpChildNodes.push_back( pNode ); } ++ void setParent(const LayoutAtomPtr& pParent) { mpParent = pParent; } ++ ++public: + virtual const std::vector& getChildren() const + { return mpChildNodes; } + ++ LayoutAtomPtr getParent() const { return mpParent.lock(); } ++ ++ static void connect(const LayoutAtomPtr& pParent, const LayoutAtomPtr& pChild) ++ { ++ pParent->addChild(pChild); ++ pChild->setParent(pParent); ++ } ++ + // dump for debug + void dump(int level = 0); + + protected: + const LayoutNode& mrLayoutNode; + std::vector< LayoutAtomPtr > mpChildNodes; ++ std::weak_ptr mpParent; + OUString msName; + }; + +@@ -238,6 +251,8 @@ public: + bool setupShape( const ShapePtr& rShape, + const dgm::Point* pPresNode ) const; + ++ const LayoutNode* getParentLayoutNode() const; ++ + private: + const Diagram& mrDgm; + VarMap mVariables; +diff --git a/oox/source/drawingml/diagram/layoutnodecontext.cxx b/oox/source/drawingml/diagram/layoutnodecontext.cxx +index 9bbe8b31421c..257f490f7c7c 100644 +--- a/oox/source/drawingml/diagram/layoutnodecontext.cxx ++++ b/oox/source/drawingml/diagram/layoutnodecontext.cxx +@@ -105,14 +105,14 @@ public: + { + // CT_When + ConditionAtomPtr pNode( new ConditionAtom(mpNode->getLayoutNode(), false, rAttribs.getFastAttributeList()) ); +- mpNode->addChild( pNode ); ++ LayoutAtom::connect(mpNode, pNode); + return new IfContext( *this, rAttribs, pNode ); + } + case DGM_TOKEN( else ): + { + // CT_Otherwise + ConditionAtomPtr pNode( new ConditionAtom(mpNode->getLayoutNode(), true, rAttribs.getFastAttributeList()) ); +- mpNode->addChild( pNode ); ++ LayoutAtom::connect(mpNode, pNode); + return new IfContext( *this, rAttribs, pNode ); + } + default: +@@ -182,7 +182,7 @@ LayoutNodeContext::onCreateContext( ::sal_Int32 aElement, + case DGM_TOKEN( layoutNode ): + { + LayoutNodePtr pNode( new LayoutNode(mpNode->getLayoutNode().getDiagram()) ); +- mpNode->addChild( pNode ); ++ LayoutAtom::connect(mpNode, pNode); + pNode->setChildOrder( rAttribs.getToken( XML_chOrder, XML_b ) ); + pNode->setMoveWith( rAttribs.getString( XML_moveWith ).get() ); + pNode->setStyleLabel( rAttribs.getString( XML_styleLbl ).get() ); +@@ -210,7 +210,7 @@ LayoutNodeContext::onCreateContext( ::sal_Int32 aElement, + pShape->setDiagramRotation(rAttribs.getInteger(XML_rot, 0) * PER_DEGREE); + + ShapeAtomPtr pAtom( new ShapeAtom(mpNode->getLayoutNode(), pShape) ); +- mpNode->addChild( pAtom ); ++ LayoutAtom::connect(mpNode, pAtom); + return new ShapeContext( *this, ShapePtr(), pShape ); + } + case DGM_TOKEN( extLst ): +@@ -219,21 +219,21 @@ LayoutNodeContext::onCreateContext( ::sal_Int32 aElement, + { + // CT_Algorithm + AlgAtomPtr pAtom( new AlgAtom(mpNode->getLayoutNode()) ); +- mpNode->addChild( pAtom ); ++ LayoutAtom::connect(mpNode, pAtom); + return new AlgorithmContext( *this, rAttribs, pAtom ); + } + case DGM_TOKEN( choose ): + { + // CT_Choose + LayoutAtomPtr pAtom( new ChooseAtom(mpNode->getLayoutNode()) ); +- mpNode->addChild( pAtom ); ++ LayoutAtom::connect(mpNode, pAtom); + return new ChooseContext( *this, rAttribs, pAtom ); + } + case DGM_TOKEN( forEach ): + { + // CT_ForEach + ForEachAtomPtr pAtom( new ForEachAtom(mpNode->getLayoutNode(), rAttribs.getFastAttributeList()) ); +- mpNode->addChild( pAtom ); ++ LayoutAtom::connect(mpNode, pAtom); + return new ForEachContext( *this, rAttribs, pAtom ); + } + case DGM_TOKEN( constrLst ): +diff --git a/oox/source/drawingml/graphicshapecontext.cxx b/oox/source/drawingml/graphicshapecontext.cxx +index f8cfc0d40b0a..135966eee9b9 100644 +--- a/oox/source/drawingml/graphicshapecontext.cxx ++++ b/oox/source/drawingml/graphicshapecontext.cxx +@@ -262,7 +262,8 @@ ContextHandlerRef DiagramGraphicDataContext::onCreateContext( ::sal_Int32 aEleme + getFragmentPathFromRelId( msDm ), + getFragmentPathFromRelId( msLo ), + getFragmentPathFromRelId( msQs ), +- getFragmentPathFromRelId( msCs )); ++ getFragmentPathFromRelId( msCs ), ++ getRelations()); + SAL_INFO("oox.drawingml", "DiagramGraphicDataContext::onCreateContext: added shape " << mpShapePtr->getName() + << " of type " << mpShapePtr->getServiceName() + << ", position: " << mpShapePtr->getPosition().X +diff --git a/oox/source/ppt/dgmimport.cxx b/oox/source/ppt/dgmimport.cxx +index c10dc48a72ef..191ec1771028 100644 +--- a/oox/source/ppt/dgmimport.cxx ++++ b/oox/source/ppt/dgmimport.cxx +@@ -68,6 +68,7 @@ bool QuickDiagrammingImport::importDocument() + + Reference xParentShape(getParentShape(), + UNO_QUERY_THROW); ++ oox::core::Relations aRelations(""); + oox::drawingml::ShapePtr pShape( + new oox::drawingml::Shape( "com.sun.star.drawing.DiagramShape" ) ); + drawingml::loadDiagram(pShape, +@@ -75,7 +76,8 @@ bool QuickDiagrammingImport::importDocument() + "", + aFragmentPath, + "", +- ""); ++ "", ++ aRelations); + oox::drawingml::ThemePtr pTheme( + new oox::drawingml::Theme()); + basegfx::B2DHomMatrix aMatrix; diff --git a/libreoffice.changes b/libreoffice.changes index fd79d5a..af2bf6c 100644 --- a/libreoffice.changes +++ b/libreoffice.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Mon Nov 12 08:50:57 UTC 2018 - andras.timar@collabora.com + +- bsc#1112112 - LO-L3: [PPTX] SmartArt: Basic rendering of several list types + * bsc1112112.patch + +------------------------------------------------------------------- +Mon Nov 5 19:57:23 UTC 2018 - andras.timar@collabora.com + +- bsc#1110348 LO-L3: [PPTX] Charts having weird/darker/ugly background versus Office 365 and strange artefacts where overlapping + * bsc1110348.patch + ------------------------------------------------------------------- Wed Oct 31 11:08:05 UTC 2018 - Tomáš Chvátal @@ -209,7 +221,7 @@ Sun Jun 17 07:56:09 UTC 2018 - tchvatal@suse.com * Tajik * Uyghur * Vietnamese - * Kurdish + * Kurdish ------------------------------------------------------------------- Sat Jun 16 12:08:53 UTC 2018 - tchvatal@suse.com diff --git a/libreoffice.spec b/libreoffice.spec index e4740a2..91767e3 100644 --- a/libreoffice.spec +++ b/libreoffice.spec @@ -12,7 +12,7 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# Please submit bugfixes or comments via http://bugs.opensuse.org/ # @@ -104,6 +104,10 @@ Patch3: mediawiki-no-broken-help.diff Patch4: libreoffice-java-sched.patch Patch5: old-boost.patch Patch6: 0001-call-System.runFinalizersOnExit-by-reflection-since-.patch +# Bug 1110348 - LO-L3: [PPTX] Charts having weird/darker/ugly background versus Office 365 and strange artefacts where overlapping +Patch7: bsc1110348.patch +# Bug 1112112 - LO-L3: [PPTX] SmartArt: Basic rendering of several list types +Patch8: bsc1112112.patch # try to save space by using hardlinks Patch990: install-with-hardlinks.diff BuildRequires: %{name}-share-linker @@ -827,7 +831,7 @@ Provides %{langname} translations and additional resources (help files, etc.) fo %langpack -l am -n Amharic -T %langpack -l ar -n Arabic -s ctl -m ar -T %langpack -l as -n Assamese -%langpack -l ast -n Asturian -T +%langpack -l ast -n Asturian -T %langpack -l be -n Belarusian -m be_BY %langpack -l bg -n Bulgarian -X -m bg_BG -T %langpack -l bn -n Bengali -m bn_BD -T @@ -950,6 +954,8 @@ Provides %{langname} translations and additional resources (help files, etc.) fo %patch3 %patch4 -p1 %patch6 -p1 +%patch7 -p1 +%patch8 -p1 %patch990 -p1 # Disable some of the failing tests (some are random)