tdf#99497 CircleKind ARC, CUT, SECTION to OOXML arc, chord, pie
Before this patch, a classical ellipse or circle was exported as OOXML preset type 'ellipse', regardless of the value of property CircleKind. Now the property is evaluated and the corresponding preset type is used. Change-Id: I49ff43cf7e2ce02654979e82f7d83d60ace39e23 Reviewed-on: https://gerrit.libreoffice.org/77785 Tested-by: Jenkins Reviewed-by: Regina Henschel <rb.henschel@t-online.de>
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
#include <com/sun/star/container/XEnumerationAccess.hpp>
|
||||
#include <com/sun/star/document/XExporter.hpp>
|
||||
#include <com/sun/star/document/XStorageBasedDocument.hpp>
|
||||
#include <com/sun/star/drawing/CircleKind.hpp>
|
||||
#include <com/sun/star/drawing/FillStyle.hpp>
|
||||
#include <com/sun/star/drawing/BitmapMode.hpp>
|
||||
#include <com/sun/star/drawing/ConnectorType.hpp>
|
||||
@@ -102,6 +103,7 @@
|
||||
#include <oox/export/chartexport.hxx>
|
||||
#include <oox/mathml/export.hxx>
|
||||
#include <drawingml/presetgeometrynames.hxx>
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
|
||||
using namespace ::css;
|
||||
using namespace ::css::beans;
|
||||
@@ -697,6 +699,21 @@ static sal_Int32 lcl_NormalizeAngle( sal_Int32 nAngle )
|
||||
return nAngle < 0 ? ( nAngle + 360 ) : nAngle ;
|
||||
}
|
||||
|
||||
static sal_Int32 lcl_CircleAngle2CustomShapeEllipseAngleOOX(const sal_Int32 nInternAngle, const sal_Int32 nWidth, const sal_Int32 nHeight)
|
||||
{
|
||||
if (nWidth != 0 || nHeight != 0)
|
||||
{
|
||||
double fAngle = basegfx::deg2rad(nInternAngle / 100.0); // intern 1/100 deg to degree to rad
|
||||
fAngle = atan2(nHeight * sin(fAngle), nWidth * cos(fAngle)); // circle to ellipse
|
||||
fAngle = basegfx::rad2deg(fAngle) * 60000.0; // rad to degree to OOXML angle unit
|
||||
sal_Int32 nAngle = basegfx::fround(fAngle); // normalize
|
||||
nAngle = nAngle % 21600000;
|
||||
return nAngle < 0 ? (nAngle + 21600000) : nAngle;
|
||||
}
|
||||
else // should be handled by caller, dummy value
|
||||
return 0;
|
||||
}
|
||||
|
||||
ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape )
|
||||
{
|
||||
// First check, if this is a Fontwork-shape. For DrawingML, such a shape is a
|
||||
@@ -1055,7 +1072,7 @@ ShapeExport& ShapeExport::WriteEllipseShape( const Reference< XShape >& xShape )
|
||||
|
||||
pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp));
|
||||
|
||||
// TODO: arc, section, cut, connector
|
||||
// TODO: connector ?
|
||||
|
||||
// non visual shape properties
|
||||
if (GetDocumentType() != DOCUMENT_DOCX)
|
||||
@@ -1071,13 +1088,64 @@ ShapeExport& ShapeExport::WriteEllipseShape( const Reference< XShape >& xShape )
|
||||
else
|
||||
pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
|
||||
|
||||
Reference< XPropertySet > xProps( xShape, UNO_QUERY );
|
||||
CircleKind eCircleKind(CircleKind_FULL);
|
||||
if (xProps.is())
|
||||
xProps->getPropertyValue("CircleKind" ) >>= eCircleKind;
|
||||
|
||||
// visual shape properties
|
||||
pFS->startElementNS( mnXmlNamespace, XML_spPr );
|
||||
WriteShapeTransformation( xShape, XML_a );
|
||||
WritePresetShape( "ellipse" );
|
||||
Reference< XPropertySet > xProps( xShape, UNO_QUERY );
|
||||
|
||||
if (CircleKind_FULL == eCircleKind)
|
||||
WritePresetShape("ellipse");
|
||||
else
|
||||
{
|
||||
sal_Int32 nStartAngleIntern(9000);
|
||||
sal_Int32 nEndAngleIntern(0);
|
||||
if (xProps.is())
|
||||
{
|
||||
xProps->getPropertyValue("CircleStartAngle" ) >>= nStartAngleIntern;
|
||||
xProps->getPropertyValue("CircleEndAngle") >>= nEndAngleIntern;
|
||||
}
|
||||
std::vector< std::pair<sal_Int32,sal_Int32>> aAvList;
|
||||
awt::Size aSize = xShape->getSize();
|
||||
if (aSize.Width != 0 || aSize.Height != 0)
|
||||
{
|
||||
// Our arc has 90° up, OOXML has 90° down, so mirror it.
|
||||
// API angles are 1/100 degree.
|
||||
sal_Int32 nStartAngleOOXML(lcl_CircleAngle2CustomShapeEllipseAngleOOX(36000 - nEndAngleIntern, aSize.Width, aSize.Height));
|
||||
sal_Int32 nEndAngleOOXML(lcl_CircleAngle2CustomShapeEllipseAngleOOX(36000 - nStartAngleIntern, aSize.Width, aSize.Height));
|
||||
lcl_AppendAdjustmentValue( aAvList, 1, nStartAngleOOXML);
|
||||
lcl_AppendAdjustmentValue( aAvList, 2, nEndAngleOOXML);
|
||||
}
|
||||
switch (eCircleKind)
|
||||
{
|
||||
case CircleKind_ARC :
|
||||
WritePresetShape("arc", aAvList);
|
||||
break;
|
||||
case CircleKind_SECTION :
|
||||
WritePresetShape("pie", aAvList);
|
||||
break;
|
||||
case CircleKind_CUT :
|
||||
WritePresetShape("chord", aAvList);
|
||||
break;
|
||||
default :
|
||||
WritePresetShape("ellipse");
|
||||
}
|
||||
}
|
||||
if( xProps.is() )
|
||||
{
|
||||
if (CircleKind_ARC == eCircleKind)
|
||||
{
|
||||
// An arc in ODF is never filled, even if a fill style other than
|
||||
// "none" is set. OOXML arc can be filled, so set fill explicit to
|
||||
// NONE, otherwise some hidden or inherited filling is shown.
|
||||
FillStyle eFillStyle(FillStyle_NONE);
|
||||
uno::Any aNewValue;
|
||||
aNewValue <<= eFillStyle;
|
||||
xProps->setPropertyValue("FillStyle", aNewValue);
|
||||
}
|
||||
WriteFill( xProps );
|
||||
WriteOutline( xProps );
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -193,6 +193,7 @@ public:
|
||||
void testTdf111789();
|
||||
void testTdf100348_convert_Fontwork2TextWarp();
|
||||
void testTdf1225573_FontWorkScaleX();
|
||||
void testTdf99497_keepAppearanceOfCircleKind();
|
||||
/// SmartArt animated elements
|
||||
void testTdf104792();
|
||||
void testTdf90627();
|
||||
@@ -288,6 +289,7 @@ public:
|
||||
CPPUNIT_TEST(testTdf111789);
|
||||
CPPUNIT_TEST(testTdf100348_convert_Fontwork2TextWarp);
|
||||
CPPUNIT_TEST(testTdf1225573_FontWorkScaleX);
|
||||
CPPUNIT_TEST(testTdf99497_keepAppearanceOfCircleKind);
|
||||
CPPUNIT_TEST(testTdf104792);
|
||||
CPPUNIT_TEST(testTdf90627);
|
||||
CPPUNIT_TEST(testTdf104786);
|
||||
@@ -2538,6 +2540,46 @@ void SdOOXMLExportTest2::testTdf126741()
|
||||
xDocShRef->DoClose();
|
||||
}
|
||||
|
||||
void SdOOXMLExportTest2::testTdf99497_keepAppearanceOfCircleKind()
|
||||
{
|
||||
// Error was, that all CircleKind were exported to 'ellipse'.
|
||||
// Resulting pptx has to contain the customshapes of the corresponding kind
|
||||
// slide 1 ARC -> arc, slide 2 CUT -> chord, slide 3 SECTION -> pie
|
||||
// Adjustment values need to exist and their values need to correspond to the
|
||||
// orignal angles. Shape 'arc' needs to be unfilled.
|
||||
const OUString sPath("/sd/qa/unit/data/odp/tdf99497_CircleKind.odp");
|
||||
::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc(sPath), ODP);
|
||||
utl::TempFile tempFile;
|
||||
xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
|
||||
|
||||
// slide 1 45° -> adj1 = 20493903, 270° -> adj2 = 5400000, <a:noFill/> exists
|
||||
xmlDocPtr pXmlDocContent1 = parseExport(tempFile, "ppt/slides/slide1.xml");
|
||||
const OString sPathStart1("/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:prstGeom");
|
||||
assertXPath(pXmlDocContent1, sPathStart1 + "[@prst='arc']");
|
||||
const OString sPathAdj1(sPathStart1 + "/a:avLst/a:gd");
|
||||
assertXPath(pXmlDocContent1, sPathAdj1 + "[@name='adj1' and @fmla='val 20493903']");
|
||||
assertXPath(pXmlDocContent1, sPathAdj1 + "[@name='adj2' and @fmla='val 5400000']");
|
||||
assertXPath(pXmlDocContent1, "/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:noFill");
|
||||
|
||||
// slide 2 270° -> adj1 = 5400000, 180° -> adj2 = 10800000
|
||||
xmlDocPtr pXmlDocContent2 = parseExport(tempFile, "ppt/slides/slide2.xml");
|
||||
const OString sPathStart2("/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:prstGeom");
|
||||
assertXPath(pXmlDocContent2, sPathStart2 + "[@prst='chord']");
|
||||
const OString sPathAdj2(sPathStart2 + "/a:avLst/a:gd");
|
||||
assertXPath(pXmlDocContent2, sPathAdj2 + "[@name='adj1' and @fmla='val 5400000']");
|
||||
assertXPath(pXmlDocContent2, sPathAdj2 + "[@name='adj2' and @fmla='val 10800000']");
|
||||
|
||||
// slide 3 120° -> adj1 = 12600000, 30° -> adj2 = 20946396
|
||||
xmlDocPtr pXmlDocContent3 = parseExport(tempFile, "ppt/slides/slide3.xml");
|
||||
const OString sPathStart3("/p:sld/p:cSld/p:spTree/p:sp/p:spPr/a:prstGeom");
|
||||
assertXPath(pXmlDocContent3, sPathStart3 + "[@prst='pie']");
|
||||
const OString sPathAdj3(sPathStart3 + "/a:avLst/a:gd");
|
||||
assertXPath(pXmlDocContent3, sPathAdj3 + "[@name='adj1' and @fmla='val 12600000']");
|
||||
assertXPath(pXmlDocContent3, sPathAdj3 + "[@name='adj2' and @fmla='val 20946396']");
|
||||
|
||||
xDocShRef->DoClose();
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
|
||||
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
Reference in New Issue
Block a user