Kaydet (Commit) fa6d726a authored tarafından Miklos Vajna's avatar Miklos Vajna

Related: tdf#94238 PPTX import: handle subset of radial gradient fill

Handle the case when the horizontal center is at 50%. Other cases are
still unhandled, those are more complex.

After fixing the style, center and border, the gradient fill looks
similar to how PowerPoint renders it.

Change-Id: I419da70482de37031aa2c7fc735692019d7665f5
Reviewed-on: https://gerrit.libreoffice.org/67168Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
üst 92cea90e
......@@ -103,6 +103,9 @@ public:
/** Translates between color transformation token names and the corresponding token */
static sal_Int32 getColorTransformationToken( const OUString& sName );
/// Compares this color with rOther.
bool equals(const Color& rOther, const GraphicHelper& rGraphicHelper, ::Color nPhClr) const;
private:
/** Internal helper for getColor(). */
void setResolvedRgb( ::Color nRgb ) const;
......
......@@ -431,6 +431,14 @@ sal_Int32 Color::getColorTransformationToken( const OUString& sName )
return XML_TOKEN_INVALID;
}
bool Color::equals(const Color& rOther, const GraphicHelper& rGraphicHelper, ::Color nPhClr) const
{
if (getColor(rGraphicHelper, nPhClr) != rOther.getColor(rGraphicHelper, nPhClr))
return false;
return getTransparency() == rOther.getTransparency();
}
void Color::clearTransparence()
{
mnAlpha = MAX_PERCENT;
......
......@@ -154,6 +154,30 @@ const awt::Size lclGetOriginalSize( const GraphicHelper& rGraphicHelper, const R
return aSizeHmm;
}
/**
* Looks for a last gradient transition and possibly sets a gradient border
* based on that.
*/
void extractGradientBorderFromStops(const GradientFillProperties& rGradientProps,
const GraphicHelper& rGraphicHelper, ::Color nPhClr,
awt::Gradient& rGradient)
{
if (rGradientProps.maGradientStops.size() <= 1)
return;
auto it = rGradientProps.maGradientStops.rbegin();
double fLastPos = it->first;
Color aLastColor = it->second;
++it;
double fLastButOnePos = it->first;
Color aLastButOneColor = it->second;
if (!aLastColor.equals(aLastButOneColor, rGraphicHelper, nPhClr))
return;
// Last transition has the same color, we can map that to a border.
rGradient.Border = rtl::math::round((fLastPos - fLastButOnePos) * 100);
}
} // namespace
void GradientFillProperties::assignUsed( const GradientFillProperties& rSourceProps )
......@@ -354,15 +378,28 @@ void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap,
if( maGradientProps.moGradientPath.has() )
{
aGradient.Style = (maGradientProps.moGradientPath.get() == XML_circle) ? awt::GradientStyle_ELLIPTICAL : awt::GradientStyle_RECT;
// position of gradient center (limited to [30%;70%], otherwise gradient is too hidden)
// position of gradient center (limited to [30%;100%], otherwise gradient is too hidden)
IntegerRectangle2D aFillToRect = maGradientProps.moFillToRect.get( IntegerRectangle2D( 0, 0, MAX_PERCENT, MAX_PERCENT ) );
sal_Int32 nCenterX = (MAX_PERCENT + aFillToRect.X1 - aFillToRect.X2) / 2;
aGradient.XOffset = getLimitedValue< sal_Int16, sal_Int32 >( nCenterX / PER_PERCENT, 30, 70 );
aGradient.XOffset = getLimitedValue<sal_Int16, sal_Int32>(
nCenterX / PER_PERCENT, 30, 100);
// Style should be radial at least when the horizontal center is at 50%.
awt::GradientStyle eCircle = aGradient.XOffset == 50
? awt::GradientStyle_RADIAL
: awt::GradientStyle_ELLIPTICAL;
aGradient.Style = (maGradientProps.moGradientPath.get() == XML_circle)
? eCircle
: awt::GradientStyle_RECT;
sal_Int32 nCenterY = (MAX_PERCENT + aFillToRect.Y1 - aFillToRect.Y2) / 2;
aGradient.YOffset = getLimitedValue< sal_Int16, sal_Int32 >( nCenterY / PER_PERCENT, 30, 70 );
aGradient.YOffset = getLimitedValue<sal_Int16, sal_Int32>(
nCenterY / PER_PERCENT, 30, 100);
::std::swap( aGradient.StartColor, aGradient.EndColor );
::std::swap( nStartTrans, nEndTrans );
extractGradientBorderFromStops(maGradientProps, rGraphicHelper, nPhClr,
aGradient);
}
else if (!maGradientProps.maGradientStops.empty())
{
......@@ -394,8 +431,7 @@ void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap,
GradientFillProperties::GradientStopMap::const_iterator aItZ(std::prev(aGradientStops.end()));
while( bSymmetric && aItA->first < aItZ->first )
{
if( aItA->second.getColor( rGraphicHelper, nPhClr ) != aItZ->second.getColor( rGraphicHelper, nPhClr ) ||
aItA->second.getTransparency() != aItZ->second.getTransparency() )
if (!aItA->second.equals(aItZ->second, rGraphicHelper, nPhClr))
bSymmetric = false;
else
{
......
......@@ -190,6 +190,7 @@ public:
void testTdf119015();
void testTdf120028();
void testTdf120028b();
void testTdf94238();
CPPUNIT_TEST_SUITE(SdImportTest);
......@@ -273,6 +274,7 @@ public:
CPPUNIT_TEST(testTdf119015);
CPPUNIT_TEST(testTdf120028);
CPPUNIT_TEST(testTdf120028b);
CPPUNIT_TEST(testTdf94238);
CPPUNIT_TEST_SUITE_END();
};
......@@ -2592,6 +2594,37 @@ void SdImportTest::testTdf120028b()
xDocShRef->DoClose();
}
void SdImportTest::testTdf94238()
{
// Assert how the gradient fill of the only shape in the document is
// imported.
::sd::DrawDocShellRef xDocShRef
= loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/tdf94238.pptx"), PPTX);
uno::Reference<drawing::XDrawPagesSupplier> xDoc(xDocShRef->GetDoc()->getUnoModel(),
uno::UNO_QUERY);
CPPUNIT_ASSERT(xDoc.is());
uno::Reference<drawing::XDrawPage> xPage(xDoc->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
CPPUNIT_ASSERT(xPage.is());
uno::Reference<beans::XPropertySet> xShape(getShape(0, xPage));
CPPUNIT_ASSERT(xShape.is());
awt::Gradient aGradient;
CPPUNIT_ASSERT(xShape->getPropertyValue("FillGradient") >>= aGradient);
// Without the accompanying fix in place, this test would have failed with
// the following details:
// - aGradient.Style was awt::GradientStyle_ELLIPTICAL
// - aGradient.YOffset was 70
// - aGradient.Border was 0
CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RADIAL, aGradient.Style);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(100), aGradient.YOffset);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(39), aGradient.Border);
xDocShRef->DoClose();
}
CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTest);
CPPUNIT_PLUGIN_IMPLEMENT();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment