vcl: migrate AddGradientActions() from OutputDevice to Gradient
Change-Id: I815fb3ce366c93b81f60d19eeed906dc7288708a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127030 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
This commit is contained in:
committed by
Tomaž Vajngerl
parent
88d8c9af71
commit
22f52db0be
@@ -720,9 +720,8 @@ namespace cppcanvas::internal
|
||||
}
|
||||
|
||||
GDIMetaFile aTmpMtf;
|
||||
rParms.mrVDev.AddGradientActions( rPoly.GetBoundRect(),
|
||||
rGradient,
|
||||
aTmpMtf );
|
||||
Gradient aGradient(rGradient);
|
||||
aGradient.AddGradientActions( rPoly.GetBoundRect(), aTmpMtf );
|
||||
|
||||
createActions( aTmpMtf, rParms, bSubsettableActions );
|
||||
|
||||
|
||||
@@ -2255,9 +2255,15 @@ void SVGActionWriter::ImplWritePattern( const tools::PolyPolygon& rPolyPoly,
|
||||
|
||||
GDIMetaFile aTmpMtf;
|
||||
if( pHatch )
|
||||
{
|
||||
mpVDev->AddHatchActions( rPolyPoly, *pHatch, aTmpMtf );
|
||||
}
|
||||
else if ( pGradient )
|
||||
mpVDev->AddGradientActions( rPolyPoly.GetBoundRect(), *pGradient, aTmpMtf );
|
||||
{
|
||||
Gradient aGradient(*pGradient);
|
||||
aGradient.AddGradientActions( rPolyPoly.GetBoundRect(), aTmpMtf );
|
||||
}
|
||||
|
||||
ImplWriteActions( aTmpMtf, nWriteFlags, "" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace tools { class Rectangle; }
|
||||
|
||||
class Point;
|
||||
class SvStream;
|
||||
class GDIMetaFile;
|
||||
|
||||
class VCL_DLLPUBLIC Gradient
|
||||
{
|
||||
@@ -78,11 +79,19 @@ public:
|
||||
|
||||
void GetBoundRect( const tools::Rectangle& rRect, tools::Rectangle &rBoundRect, Point& rCenter ) const;
|
||||
|
||||
void AddGradientActions(tools::Rectangle const& rRect, GDIMetaFile& rMetaFile);
|
||||
|
||||
Gradient& operator=( const Gradient& rGradient );
|
||||
Gradient& operator=( Gradient&& rGradient );
|
||||
bool operator==( const Gradient& rGradient ) const;
|
||||
bool operator!=( const Gradient& rGradient ) const
|
||||
{ return !(Gradient::operator==( rGradient )); }
|
||||
|
||||
private:
|
||||
tools::Long GetMetafileSteps(tools::Rectangle const& rRect) const;
|
||||
|
||||
void DrawComplexGradientToMetafile(tools::Rectangle const& rRect, GDIMetaFile& rMetaFile) const;
|
||||
void DrawLinearGradientToMetafile(tools::Rectangle const& rRect, GDIMetaFile& rMetaFile) const;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_VCL_GRADIENT_HXX
|
||||
|
||||
@@ -795,11 +795,6 @@ public:
|
||||
void DrawGradient( const tools::Rectangle& rRect, const Gradient& rGradient );
|
||||
void DrawGradient( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient );
|
||||
|
||||
void AddGradientActions(
|
||||
const tools::Rectangle& rRect,
|
||||
const Gradient& rGradient,
|
||||
GDIMetaFile& rMtf );
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool UsePolyPolygonForComplexGradient() = 0;
|
||||
@@ -810,13 +805,8 @@ private:
|
||||
|
||||
SAL_DLLPRIVATE void DrawLinearGradient( const tools::Rectangle& rRect, const Gradient& rGradient, const tools::PolyPolygon* pClipPolyPoly );
|
||||
SAL_DLLPRIVATE void DrawComplexGradient( const tools::Rectangle& rRect, const Gradient& rGradient, const tools::PolyPolygon* pClipPolyPoly );
|
||||
|
||||
SAL_DLLPRIVATE void DrawGradientToMetafile( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient );
|
||||
SAL_DLLPRIVATE void DrawLinearGradientToMetafile( const tools::Rectangle& rRect, const Gradient& rGradient );
|
||||
SAL_DLLPRIVATE void DrawComplexGradientToMetafile( const tools::Rectangle& rRect, const Gradient& rGradient );
|
||||
|
||||
SAL_DLLPRIVATE tools::Long GetGradientSteps(Gradient const& rGradient, tools::Rectangle const& rRect);
|
||||
|
||||
SAL_DLLPRIVATE Color GetSingleColorGradientFill();
|
||||
///@}
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
|
||||
#
|
||||
# This file is part of the LibreOffice project.
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
|
||||
$(eval $(call gb_CppunitTest_CppunitTest,vcl_gradient))
|
||||
|
||||
$(eval $(call gb_CppunitTest_set_include,vcl_gradient,\
|
||||
$$(INCLUDE) \
|
||||
-I$(SRCDIR)/vcl/inc \
|
||||
-I$(SRCDIR)/vcl/source/window \
|
||||
))
|
||||
|
||||
$(eval $(call gb_CppunitTest_add_exception_objects,vcl_gradient, \
|
||||
vcl/qa/cppunit/gradient \
|
||||
))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_externals,vcl_gradient,boost_headers))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_libraries,vcl_gradient, \
|
||||
basegfx \
|
||||
comphelper \
|
||||
cppu \
|
||||
cppuhelper \
|
||||
sal \
|
||||
svt \
|
||||
test \
|
||||
tl \
|
||||
unotest \
|
||||
vcl \
|
||||
))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_sdk_api,vcl_gradient))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_ure,vcl_gradient))
|
||||
$(eval $(call gb_CppunitTest_use_vcl,vcl_gradient))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_components,vcl_gradient,\
|
||||
configmgr/source/configmgr \
|
||||
i18npool/util/i18npool \
|
||||
ucb/source/core/ucb1 \
|
||||
))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_configuration,vcl_gradient))
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
||||
@@ -198,6 +198,7 @@ $(eval $(call gb_Module_add_check_targets,vcl,\
|
||||
CppunitTest_vcl_filters_test \
|
||||
CppunitTest_vcl_mnemonic \
|
||||
CppunitTest_vcl_outdev \
|
||||
CppunitTest_vcl_gradient \
|
||||
CppunitTest_vcl_app_test \
|
||||
CppunitTest_vcl_jpeg_read_write_test \
|
||||
CppunitTest_vcl_svm_test \
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <test/bootstrapfixture.hxx>
|
||||
#include <test/outputdevice.hxx>
|
||||
|
||||
#include <sal/log.hxx>
|
||||
#include <basegfx/matrix/b2dhommatrix.hxx>
|
||||
#include <basegfx/numeric/ftools.hxx>
|
||||
#include <basegfx/polygon/b2dpolygon.hxx>
|
||||
#include <basegfx/polygon/b2dpolypolygon.hxx>
|
||||
#include <basegfx/vector/b2enums.hxx>
|
||||
|
||||
#include <vcl/gradient.hxx>
|
||||
#include <vcl/lineinfo.hxx>
|
||||
#include <vcl/print.hxx>
|
||||
#include <vcl/rendercontext/RasterOp.hxx>
|
||||
#include <vcl/virdev.hxx>
|
||||
#include <vcl/window.hxx>
|
||||
#include <vcl/gdimtf.hxx>
|
||||
#include <vcl/metaact.hxx>
|
||||
|
||||
#include <bitmap/BitmapWriteAccess.hxx>
|
||||
#include <bufferdevice.hxx>
|
||||
#include <window.h>
|
||||
|
||||
class VclGradientTest : public test::BootstrapFixture
|
||||
{
|
||||
public:
|
||||
VclGradientTest()
|
||||
: BootstrapFixture(true, false)
|
||||
{
|
||||
}
|
||||
|
||||
void testAddGradientActions_rect_linear();
|
||||
void testAddGradientActions_rect_axial();
|
||||
void testAddGradientActions_rect_complex();
|
||||
|
||||
CPPUNIT_TEST_SUITE(VclGradientTest);
|
||||
CPPUNIT_TEST(testAddGradientActions_rect_linear);
|
||||
CPPUNIT_TEST(testAddGradientActions_rect_axial);
|
||||
CPPUNIT_TEST(testAddGradientActions_rect_complex);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
};
|
||||
|
||||
static size_t TestLinearStripes(GDIMetaFile& rMtf, size_t nTimes, size_t nIndex)
|
||||
{
|
||||
nIndex++;
|
||||
MetaAction* pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action (start)", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action (start)", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
for (size_t i = 0; i < nTimes - 1; i++)
|
||||
{
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
}
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action (end)", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action (end)", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
void VclGradientTest::testAddGradientActions_rect_linear()
|
||||
{
|
||||
GDIMetaFile aMtf;
|
||||
tools::Rectangle aRect(Point(10, 10), Size(40, 40));
|
||||
Gradient aGradient(GradientStyle::Linear, COL_RED, COL_WHITE);
|
||||
aGradient.SetBorder(100);
|
||||
|
||||
aGradient.AddGradientActions(aRect, aMtf);
|
||||
|
||||
size_t nIndex = 0;
|
||||
|
||||
MetaAction* pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a push action", MetaActionType::PUSH, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rectangular intersect clip action",
|
||||
MetaActionType::ISECTRECTCLIPREGION, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action", MetaActionType::LINECOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
TestLinearStripes(aMtf, 3, nIndex);
|
||||
}
|
||||
|
||||
static size_t TestAxialStripes(GDIMetaFile& rMtf, size_t nTimes, size_t nIndex)
|
||||
{
|
||||
nIndex++;
|
||||
MetaAction* pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
for (size_t i = 0; i < nTimes - 1; i++)
|
||||
{
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
}
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
void VclGradientTest::testAddGradientActions_rect_axial()
|
||||
{
|
||||
GDIMetaFile aMtf;
|
||||
tools::Rectangle aRect(Point(10, 10), Size(40, 40));
|
||||
Gradient aGradient(GradientStyle::Axial, COL_RED, COL_WHITE);
|
||||
aGradient.SetBorder(100);
|
||||
|
||||
aGradient.AddGradientActions(aRect, aMtf);
|
||||
|
||||
size_t nIndex = 0;
|
||||
|
||||
MetaAction* pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a push action", MetaActionType::PUSH, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rectangular intersect clip action",
|
||||
MetaActionType::ISECTRECTCLIPREGION, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action", MetaActionType::LINECOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
TestAxialStripes(aMtf, 3, nIndex);
|
||||
}
|
||||
|
||||
static size_t TestComplexStripes(GDIMetaFile& rMtf, size_t nTimes, size_t nIndex)
|
||||
{
|
||||
nIndex++;
|
||||
MetaAction* pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
for (size_t i = 1; i < nTimes; i++)
|
||||
{
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polypolygon action", MetaActionType::POLYPOLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
}
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polypolygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
void VclGradientTest::testAddGradientActions_rect_complex()
|
||||
{
|
||||
GDIMetaFile aMtf;
|
||||
tools::Rectangle aRect(Point(10, 10), Size(40, 40));
|
||||
Gradient aGradient(GradientStyle::Square, COL_RED, COL_WHITE);
|
||||
aGradient.SetBorder(10);
|
||||
|
||||
aGradient.AddGradientActions(aRect, aMtf);
|
||||
|
||||
size_t nIndex = 0;
|
||||
|
||||
MetaAction* pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a push action", MetaActionType::PUSH, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rectangular intersect clip action",
|
||||
MetaActionType::ISECTRECTCLIPREGION, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action", MetaActionType::LINECOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
TestComplexStripes(aMtf, 40, nIndex);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(VclGradientTest);
|
||||
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
@@ -94,12 +94,9 @@ public:
|
||||
void testDrawGradient_drawmode();
|
||||
void testDrawGradient_rect_linear();
|
||||
void testDrawGradient_rect_axial();
|
||||
void testAddGradientActions_rect_linear();
|
||||
void testAddGradientActions_rect_axial();
|
||||
void testDrawGradient_polygon_linear();
|
||||
void testDrawGradient_polygon_axial();
|
||||
void testDrawGradient_rect_complex();
|
||||
void testAddGradientActions_rect_complex();
|
||||
|
||||
CPPUNIT_TEST_SUITE(VclOutdevTest);
|
||||
CPPUNIT_TEST(testVirtualDevice);
|
||||
@@ -156,12 +153,9 @@ public:
|
||||
CPPUNIT_TEST(testDrawGradient_drawmode);
|
||||
CPPUNIT_TEST(testDrawGradient_rect_linear);
|
||||
CPPUNIT_TEST(testDrawGradient_rect_axial);
|
||||
CPPUNIT_TEST(testAddGradientActions_rect_linear);
|
||||
CPPUNIT_TEST(testAddGradientActions_rect_axial);
|
||||
CPPUNIT_TEST(testDrawGradient_polygon_linear);
|
||||
CPPUNIT_TEST(testDrawGradient_polygon_axial);
|
||||
CPPUNIT_TEST(testDrawGradient_rect_complex);
|
||||
CPPUNIT_TEST(testAddGradientActions_rect_complex);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
};
|
||||
|
||||
@@ -2138,92 +2132,6 @@ void VclOutdevTest::testDrawGradient_drawmode()
|
||||
MetaActionType::POP, pAction->GetType());
|
||||
}
|
||||
|
||||
static size_t TestLinearStripes(GDIMetaFile& rMtf, size_t nTimes, size_t nIndex)
|
||||
{
|
||||
nIndex++;
|
||||
MetaAction* pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action (start)", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action (start)", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
for (size_t i = 0; i < nTimes - 1; i++)
|
||||
{
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
}
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action (end)", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action (end)", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
static size_t TestAxialStripes(GDIMetaFile& rMtf, size_t nTimes, size_t nIndex)
|
||||
{
|
||||
nIndex++;
|
||||
MetaAction* pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
for (size_t i = 0; i < nTimes - 1; i++)
|
||||
{
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
}
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
void VclOutdevTest::testDrawGradient_rect_linear()
|
||||
{
|
||||
ScopedVclPtrInstance<VirtualDevice> pVDev;
|
||||
@@ -2245,37 +2153,6 @@ void VclOutdevTest::testDrawGradient_rect_linear()
|
||||
pAction->GetType());
|
||||
}
|
||||
|
||||
void VclOutdevTest::testAddGradientActions_rect_linear()
|
||||
{
|
||||
ScopedVclPtrInstance<VirtualDevice> pVDev;
|
||||
GDIMetaFile aMtf;
|
||||
|
||||
tools::Rectangle aRect(Point(10, 10), Size(40, 40));
|
||||
pVDev->SetOutputSizePixel(Size(100, 100));
|
||||
|
||||
Gradient aGradient(GradientStyle::Linear, COL_RED, COL_WHITE);
|
||||
aGradient.SetBorder(100);
|
||||
|
||||
pVDev->AddGradientActions(aRect, aGradient, aMtf);
|
||||
|
||||
size_t nIndex = 0;
|
||||
|
||||
MetaAction* pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a push action", MetaActionType::PUSH, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rectangular intersect clip action",
|
||||
MetaActionType::ISECTRECTCLIPREGION, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action", MetaActionType::LINECOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
TestLinearStripes(aMtf, 3, nIndex);
|
||||
}
|
||||
|
||||
void VclOutdevTest::testDrawGradient_rect_axial()
|
||||
{
|
||||
ScopedVclPtrInstance<VirtualDevice> pVDev;
|
||||
@@ -2297,37 +2174,6 @@ void VclOutdevTest::testDrawGradient_rect_axial()
|
||||
pAction->GetType());
|
||||
}
|
||||
|
||||
void VclOutdevTest::testAddGradientActions_rect_axial()
|
||||
{
|
||||
ScopedVclPtrInstance<VirtualDevice> pVDev;
|
||||
GDIMetaFile aMtf;
|
||||
|
||||
tools::Rectangle aRect(Point(10, 10), Size(40, 40));
|
||||
pVDev->SetOutputSizePixel(Size(100, 100));
|
||||
|
||||
Gradient aGradient(GradientStyle::Axial, COL_RED, COL_WHITE);
|
||||
aGradient.SetBorder(100);
|
||||
|
||||
pVDev->AddGradientActions(aRect, aGradient, aMtf);
|
||||
|
||||
size_t nIndex = 0;
|
||||
|
||||
MetaAction* pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a push action", MetaActionType::PUSH, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rectangular intersect clip action",
|
||||
MetaActionType::ISECTRECTCLIPREGION, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action", MetaActionType::LINECOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
TestAxialStripes(aMtf, 3, nIndex);
|
||||
}
|
||||
|
||||
void VclOutdevTest::testDrawGradient_polygon_linear()
|
||||
{
|
||||
ScopedVclPtrInstance<VirtualDevice> pVDev;
|
||||
@@ -2364,39 +2210,6 @@ void VclOutdevTest::testDrawGradient_polygon_axial()
|
||||
ClipGradientTest(aMtf, INITIAL_SETUP_ACTION_COUNT);
|
||||
}
|
||||
|
||||
static size_t TestComplexStripes(GDIMetaFile& rMtf, size_t nTimes, size_t nIndex)
|
||||
{
|
||||
nIndex++;
|
||||
MetaAction* pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
for (size_t i = 1; i < nTimes; i++)
|
||||
{
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polypolygon action", MetaActionType::POLYPOLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
}
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a fill color action", MetaActionType::FILLCOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = rMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a polypolygon action", MetaActionType::POLYGON,
|
||||
pAction->GetType());
|
||||
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
void VclOutdevTest::testDrawGradient_rect_complex()
|
||||
{
|
||||
ScopedVclPtrInstance<VirtualDevice> pVDev;
|
||||
@@ -2417,37 +2230,6 @@ void VclOutdevTest::testDrawGradient_rect_complex()
|
||||
pAction->GetType());
|
||||
}
|
||||
|
||||
void VclOutdevTest::testAddGradientActions_rect_complex()
|
||||
{
|
||||
ScopedVclPtrInstance<VirtualDevice> pVDev;
|
||||
GDIMetaFile aMtf;
|
||||
|
||||
tools::Rectangle aRect(Point(10, 10), Size(40, 40));
|
||||
pVDev->SetOutputSizePixel(Size(1000, 1000));
|
||||
|
||||
Gradient aGradient(GradientStyle::Square, COL_RED, COL_WHITE);
|
||||
aGradient.SetBorder(10);
|
||||
|
||||
pVDev->AddGradientActions(aRect, aGradient, aMtf);
|
||||
|
||||
size_t nIndex = 0;
|
||||
|
||||
MetaAction* pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a push action", MetaActionType::PUSH, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a rectangular intersect clip action",
|
||||
MetaActionType::ISECTRECTCLIPREGION, pAction->GetType());
|
||||
|
||||
nIndex++;
|
||||
pAction = aMtf.GetAction(nIndex);
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Not a line color action", MetaActionType::LINECOLOR,
|
||||
pAction->GetType());
|
||||
|
||||
TestComplexStripes(aMtf, 40, nIndex);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(VclOutdevTest);
|
||||
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
@@ -1515,7 +1515,8 @@ void PSWriter::ImplWriteGradient( const tools::PolyPolygon& rPolyPoly, const Gra
|
||||
ScopedVclPtrInstance< VirtualDevice > l_pVDev;
|
||||
GDIMetaFile aTmpMtf;
|
||||
l_pVDev->SetMapMode( rVDev.GetMapMode() );
|
||||
l_pVDev->AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf );
|
||||
Gradient aGradient(rGradient);
|
||||
aGradient.AddGradientActions( rPolyPoly.GetBoundRect(), aTmpMtf );
|
||||
ImplWriteActions( aTmpMtf, rVDev );
|
||||
}
|
||||
|
||||
|
||||
@@ -1170,7 +1170,8 @@ void EMFWriter::ImplWrite( const GDIMetaFile& rMtf )
|
||||
const MetaGradientAction* pA = static_cast<const MetaGradientAction*>(pAction);
|
||||
GDIMetaFile aTmpMtf;
|
||||
|
||||
maVDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
|
||||
Gradient aGradient = pA->GetGradient();
|
||||
aGradient.AddGradientActions( pA->GetRect(), aTmpMtf );
|
||||
ImplWrite( aTmpMtf );
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1302,7 +1302,8 @@ void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
|
||||
const MetaGradientAction* pA = static_cast<const MetaGradientAction*>(pMA);
|
||||
GDIMetaFile aTmpMtf;
|
||||
|
||||
pVirDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
|
||||
Gradient aGradient = pA->GetGradient();
|
||||
aGradient.AddGradientActions( pA->GetRect(), aTmpMtf );
|
||||
WriteRecords( aTmpMtf );
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
*/
|
||||
|
||||
#include <tools/gen.hxx>
|
||||
|
||||
#include <vcl/gradient.hxx>
|
||||
#include <vcl/metaact.hxx>
|
||||
|
||||
class Gradient::Impl
|
||||
{
|
||||
@@ -295,4 +297,384 @@ bool Gradient::operator==( const Gradient& rGradient ) const
|
||||
return mpImplGradient == rGradient.mpImplGradient;
|
||||
}
|
||||
|
||||
const sal_uInt32 GRADIENT_DEFAULT_STEPCOUNT = 0;
|
||||
|
||||
void Gradient::AddGradientActions(tools::Rectangle const& rRect, GDIMetaFile& rMetaFile)
|
||||
{
|
||||
tools::Rectangle aRect(rRect);
|
||||
aRect.Justify();
|
||||
|
||||
// do nothing if the rectangle is empty
|
||||
if (aRect.IsEmpty())
|
||||
return;
|
||||
|
||||
rMetaFile.AddAction(new MetaPushAction(vcl::PushFlags::ALL));
|
||||
rMetaFile.AddAction(new MetaISectRectClipRegionAction( aRect));
|
||||
rMetaFile.AddAction(new MetaLineColorAction(Color(), false));
|
||||
|
||||
// because we draw with no border line, we have to expand gradient
|
||||
// rect to avoid missing lines on the right and bottom edge
|
||||
aRect.AdjustLeft( -1 );
|
||||
aRect.AdjustTop( -1 );
|
||||
aRect.AdjustRight( 1 );
|
||||
aRect.AdjustBottom( 1 );
|
||||
|
||||
// calculate step count if necessary
|
||||
if (!GetSteps())
|
||||
SetSteps(GRADIENT_DEFAULT_STEPCOUNT);
|
||||
|
||||
if (GetStyle() == GradientStyle::Linear || GetStyle() == GradientStyle::Axial)
|
||||
DrawLinearGradientToMetafile(aRect, rMetaFile);
|
||||
else
|
||||
DrawComplexGradientToMetafile(aRect, rMetaFile);
|
||||
|
||||
rMetaFile.AddAction(new MetaPopAction());
|
||||
}
|
||||
|
||||
tools::Long Gradient::GetMetafileSteps(tools::Rectangle const& rRect) const
|
||||
{
|
||||
// calculate step count
|
||||
tools::Long nStepCount = GetSteps();
|
||||
|
||||
if (nStepCount)
|
||||
return nStepCount;
|
||||
|
||||
if (GetStyle() == GradientStyle::Linear || GetStyle() == GradientStyle::Axial)
|
||||
return rRect.GetHeight();
|
||||
else
|
||||
return std::min(rRect.GetWidth(), rRect.GetHeight());
|
||||
}
|
||||
|
||||
|
||||
static sal_uInt8 GetGradientColorValue(tools::Long nValue)
|
||||
{
|
||||
if ( nValue < 0 )
|
||||
return 0;
|
||||
else if ( nValue > 0xFF )
|
||||
return 0xFF;
|
||||
else
|
||||
return static_cast<sal_uInt8>(nValue);
|
||||
}
|
||||
|
||||
void Gradient::DrawLinearGradientToMetafile(tools::Rectangle const& rRect, GDIMetaFile& rMetaFile) const
|
||||
{
|
||||
// get BoundRect of rotated rectangle
|
||||
tools::Rectangle aRect;
|
||||
Point aCenter;
|
||||
Degree10 nAngle = GetAngle() % 3600_deg10;
|
||||
|
||||
GetBoundRect(rRect, aRect, aCenter);
|
||||
|
||||
bool bLinear = (GetStyle() == GradientStyle::Linear);
|
||||
double fBorder = GetBorder() * aRect.GetHeight() / 100.0;
|
||||
if ( !bLinear )
|
||||
{
|
||||
fBorder /= 2.0;
|
||||
}
|
||||
tools::Rectangle aMirrorRect = aRect; // used in style axial
|
||||
aMirrorRect.SetTop( ( aRect.Top() + aRect.Bottom() ) / 2 );
|
||||
if ( !bLinear )
|
||||
{
|
||||
aRect.SetBottom( aMirrorRect.Top() );
|
||||
}
|
||||
|
||||
// colour-intensities of start- and finish; change if needed
|
||||
tools::Long nFactor;
|
||||
Color aStartCol = GetStartColor();
|
||||
Color aEndCol = GetEndColor();
|
||||
tools::Long nStartRed = aStartCol.GetRed();
|
||||
tools::Long nStartGreen = aStartCol.GetGreen();
|
||||
tools::Long nStartBlue = aStartCol.GetBlue();
|
||||
tools::Long nEndRed = aEndCol.GetRed();
|
||||
tools::Long nEndGreen = aEndCol.GetGreen();
|
||||
tools::Long nEndBlue = aEndCol.GetBlue();
|
||||
nFactor = GetStartIntensity();
|
||||
nStartRed = (nStartRed * nFactor) / 100;
|
||||
nStartGreen = (nStartGreen * nFactor) / 100;
|
||||
nStartBlue = (nStartBlue * nFactor) / 100;
|
||||
nFactor = GetEndIntensity();
|
||||
nEndRed = (nEndRed * nFactor) / 100;
|
||||
nEndGreen = (nEndGreen * nFactor) / 100;
|
||||
nEndBlue = (nEndBlue * nFactor) / 100;
|
||||
|
||||
// gradient style axial has exchanged start and end colors
|
||||
if ( !bLinear)
|
||||
{
|
||||
tools::Long nTempColor = nStartRed;
|
||||
nStartRed = nEndRed;
|
||||
nEndRed = nTempColor;
|
||||
nTempColor = nStartGreen;
|
||||
nStartGreen = nEndGreen;
|
||||
nEndGreen = nTempColor;
|
||||
nTempColor = nStartBlue;
|
||||
nStartBlue = nEndBlue;
|
||||
nEndBlue = nTempColor;
|
||||
}
|
||||
|
||||
sal_uInt8 nRed;
|
||||
sal_uInt8 nGreen;
|
||||
sal_uInt8 nBlue;
|
||||
|
||||
// Create border
|
||||
tools::Rectangle aBorderRect = aRect;
|
||||
tools::Polygon aPoly( 4 );
|
||||
if (fBorder > 0.0)
|
||||
{
|
||||
nRed = static_cast<sal_uInt8>(nStartRed);
|
||||
nGreen = static_cast<sal_uInt8>(nStartGreen);
|
||||
nBlue = static_cast<sal_uInt8>(nStartBlue);
|
||||
|
||||
rMetaFile.AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
|
||||
aBorderRect.SetBottom( static_cast<tools::Long>( aBorderRect.Top() + fBorder ) );
|
||||
aRect.SetTop( aBorderRect.Bottom() );
|
||||
aPoly[0] = aBorderRect.TopLeft();
|
||||
aPoly[1] = aBorderRect.TopRight();
|
||||
aPoly[2] = aBorderRect.BottomRight();
|
||||
aPoly[3] = aBorderRect.BottomLeft();
|
||||
aPoly.Rotate( aCenter, nAngle );
|
||||
|
||||
rMetaFile.AddAction( new MetaPolygonAction( aPoly ) );
|
||||
|
||||
if ( !bLinear)
|
||||
{
|
||||
aBorderRect = aMirrorRect;
|
||||
aBorderRect.SetTop( static_cast<tools::Long>( aBorderRect.Bottom() - fBorder ) );
|
||||
aMirrorRect.SetBottom( aBorderRect.Top() );
|
||||
aPoly[0] = aBorderRect.TopLeft();
|
||||
aPoly[1] = aBorderRect.TopRight();
|
||||
aPoly[2] = aBorderRect.BottomRight();
|
||||
aPoly[3] = aBorderRect.BottomLeft();
|
||||
aPoly.Rotate( aCenter, nAngle );
|
||||
|
||||
rMetaFile.AddAction( new MetaPolygonAction( aPoly ) );
|
||||
}
|
||||
}
|
||||
|
||||
tools::Long nStepCount = GetMetafileSteps(aRect);
|
||||
|
||||
// minimal three steps and maximal as max color steps
|
||||
tools::Long nAbsRedSteps = std::abs( nEndRed - nStartRed );
|
||||
tools::Long nAbsGreenSteps = std::abs( nEndGreen - nStartGreen );
|
||||
tools::Long nAbsBlueSteps = std::abs( nEndBlue - nStartBlue );
|
||||
tools::Long nMaxColorSteps = std::max( nAbsRedSteps , nAbsGreenSteps );
|
||||
nMaxColorSteps = std::max( nMaxColorSteps, nAbsBlueSteps );
|
||||
tools::Long nSteps = std::min( nStepCount, nMaxColorSteps );
|
||||
if ( nSteps < 3)
|
||||
{
|
||||
nSteps = 3;
|
||||
}
|
||||
|
||||
double fScanInc = static_cast<double>(aRect.GetHeight()) / static_cast<double>(nSteps);
|
||||
double fGradientLine = static_cast<double>(aRect.Top());
|
||||
double fMirrorGradientLine = static_cast<double>(aMirrorRect.Bottom());
|
||||
|
||||
const double fStepsMinus1 = static_cast<double>(nSteps) - 1.0;
|
||||
if ( !bLinear)
|
||||
{
|
||||
nSteps -= 1; // draw middle polygons as one polygon after loop to avoid gap
|
||||
}
|
||||
for ( tools::Long i = 0; i < nSteps; i++ )
|
||||
{
|
||||
// linear interpolation of color
|
||||
double fAlpha = static_cast<double>(i) / fStepsMinus1;
|
||||
double fTempColor = static_cast<double>(nStartRed) * (1.0-fAlpha) + static_cast<double>(nEndRed) * fAlpha;
|
||||
nRed = GetGradientColorValue(static_cast<tools::Long>(fTempColor));
|
||||
fTempColor = static_cast<double>(nStartGreen) * (1.0-fAlpha) + static_cast<double>(nEndGreen) * fAlpha;
|
||||
nGreen = GetGradientColorValue(static_cast<tools::Long>(fTempColor));
|
||||
fTempColor = static_cast<double>(nStartBlue) * (1.0-fAlpha) + static_cast<double>(nEndBlue) * fAlpha;
|
||||
nBlue = GetGradientColorValue(static_cast<tools::Long>(fTempColor));
|
||||
|
||||
rMetaFile.AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
|
||||
// Polygon for this color step
|
||||
aRect.SetTop( static_cast<tools::Long>( fGradientLine + static_cast<double>(i) * fScanInc ) );
|
||||
aRect.SetBottom( static_cast<tools::Long>( fGradientLine + ( static_cast<double>(i) + 1.0 ) * fScanInc ) );
|
||||
aPoly[0] = aRect.TopLeft();
|
||||
aPoly[1] = aRect.TopRight();
|
||||
aPoly[2] = aRect.BottomRight();
|
||||
aPoly[3] = aRect.BottomLeft();
|
||||
aPoly.Rotate( aCenter, nAngle );
|
||||
|
||||
rMetaFile.AddAction( new MetaPolygonAction( aPoly ) );
|
||||
|
||||
if ( !bLinear )
|
||||
{
|
||||
aMirrorRect.SetBottom( static_cast<tools::Long>( fMirrorGradientLine - static_cast<double>(i) * fScanInc ) );
|
||||
aMirrorRect.SetTop( static_cast<tools::Long>( fMirrorGradientLine - (static_cast<double>(i) + 1.0)* fScanInc ) );
|
||||
aPoly[0] = aMirrorRect.TopLeft();
|
||||
aPoly[1] = aMirrorRect.TopRight();
|
||||
aPoly[2] = aMirrorRect.BottomRight();
|
||||
aPoly[3] = aMirrorRect.BottomLeft();
|
||||
aPoly.Rotate( aCenter, nAngle );
|
||||
|
||||
rMetaFile.AddAction( new MetaPolygonAction( aPoly ) );
|
||||
}
|
||||
}
|
||||
if ( bLinear)
|
||||
return;
|
||||
|
||||
// draw middle polygon with end color
|
||||
nRed = GetGradientColorValue(nEndRed);
|
||||
nGreen = GetGradientColorValue(nEndGreen);
|
||||
nBlue = GetGradientColorValue(nEndBlue);
|
||||
|
||||
rMetaFile.AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
|
||||
aRect.SetTop( static_cast<tools::Long>( fGradientLine + static_cast<double>(nSteps) * fScanInc ) );
|
||||
aRect.SetBottom( static_cast<tools::Long>( fMirrorGradientLine - static_cast<double>(nSteps) * fScanInc ) );
|
||||
aPoly[0] = aRect.TopLeft();
|
||||
aPoly[1] = aRect.TopRight();
|
||||
aPoly[2] = aRect.BottomRight();
|
||||
aPoly[3] = aRect.BottomLeft();
|
||||
aPoly.Rotate( aCenter, nAngle );
|
||||
|
||||
rMetaFile.AddAction( new MetaPolygonAction( aPoly ) );
|
||||
|
||||
}
|
||||
|
||||
void Gradient::DrawComplexGradientToMetafile(tools::Rectangle const& rRect, GDIMetaFile& rMetaFile) const
|
||||
{
|
||||
// Determine if we output via Polygon or PolyPolygon
|
||||
// For all rasteroperations other than Overpaint always use PolyPolygon,
|
||||
// as we will get wrong results if we output multiple times on top of each other.
|
||||
// Also for printers always use PolyPolygon, as not all printers
|
||||
// can print polygons on top of each other.
|
||||
|
||||
tools::Rectangle aRect;
|
||||
Point aCenter;
|
||||
GetBoundRect(rRect, aRect, aCenter);
|
||||
|
||||
std::optional<tools::PolyPolygon> xPolyPoly;
|
||||
xPolyPoly = tools::PolyPolygon( 2 );
|
||||
|
||||
// last parameter - true if complex gradient, false if linear
|
||||
tools::Long nStepCount = GetMetafileSteps(rRect);
|
||||
|
||||
// at least three steps and at most the number of colour differences
|
||||
tools::Long nSteps = std::max(nStepCount, tools::Long(2));
|
||||
|
||||
Color aStartCol(GetStartColor());
|
||||
Color aEndCol(GetEndColor());
|
||||
|
||||
tools::Long nStartRed = (static_cast<tools::Long>(aStartCol.GetRed()) * GetStartIntensity()) / 100;
|
||||
tools::Long nStartGreen = (static_cast<tools::Long>(aStartCol.GetGreen()) * GetStartIntensity()) / 100;
|
||||
tools::Long nStartBlue = (static_cast<tools::Long>(aStartCol.GetBlue()) * GetStartIntensity()) / 100;
|
||||
|
||||
tools::Long nEndRed = (static_cast<tools::Long>(aEndCol.GetRed()) * GetEndIntensity()) / 100;
|
||||
tools::Long nEndGreen = (static_cast<tools::Long>(aEndCol.GetGreen()) * GetEndIntensity()) / 100;
|
||||
tools::Long nEndBlue = (static_cast<tools::Long>(aEndCol.GetBlue()) * GetEndIntensity()) / 100;
|
||||
|
||||
tools::Long nRedSteps = nEndRed - nStartRed;
|
||||
tools::Long nGreenSteps = nEndGreen - nStartGreen;
|
||||
tools::Long nBlueSteps = nEndBlue - nStartBlue;
|
||||
|
||||
tools::Long nCalcSteps = std::abs(nRedSteps);
|
||||
tools::Long nTempSteps = std::abs(nGreenSteps);
|
||||
|
||||
if (nTempSteps > nCalcSteps)
|
||||
nCalcSteps = nTempSteps;
|
||||
|
||||
nTempSteps = std::abs( nBlueSteps );
|
||||
|
||||
if (nTempSteps > nCalcSteps)
|
||||
nCalcSteps = nTempSteps;
|
||||
|
||||
if (nCalcSteps < nSteps)
|
||||
nSteps = nCalcSteps;
|
||||
|
||||
if ( !nSteps )
|
||||
nSteps = 1;
|
||||
|
||||
// determine output limits and stepsizes for all directions
|
||||
tools::Polygon aPoly;
|
||||
double fScanLeft = aRect.Left();
|
||||
double fScanTop = aRect.Top();
|
||||
double fScanRight = aRect.Right();
|
||||
double fScanBottom = aRect.Bottom();
|
||||
double fScanIncX = static_cast<double>(aRect.GetWidth()) / static_cast<double>(nSteps) * 0.5;
|
||||
double fScanIncY = static_cast<double>(aRect.GetHeight()) / static_cast<double>(nSteps) * 0.5;
|
||||
|
||||
// all gradients are rendered as nested rectangles which shrink
|
||||
// equally in each dimension - except for 'square' gradients
|
||||
// which shrink to a central vertex but are not per-se square.
|
||||
if (GetStyle() != GradientStyle::Square)
|
||||
{
|
||||
fScanIncY = std::min( fScanIncY, fScanIncX );
|
||||
fScanIncX = fScanIncY;
|
||||
}
|
||||
sal_uInt8 nRed = static_cast<sal_uInt8>(nStartRed), nGreen = static_cast<sal_uInt8>(nStartGreen), nBlue = static_cast<sal_uInt8>(nStartBlue);
|
||||
bool bPaintLastPolygon( false ); // #107349# Paint last polygon only if loop has generated any output
|
||||
|
||||
rMetaFile.AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
|
||||
aPoly = rRect;
|
||||
xPolyPoly->Insert( aPoly );
|
||||
xPolyPoly->Insert( aPoly );
|
||||
|
||||
// loop to output Polygon/PolyPolygon sequentially
|
||||
for( tools::Long i = 1; i < nSteps; i++ )
|
||||
{
|
||||
// calculate new Polygon
|
||||
fScanLeft += fScanIncX;
|
||||
aRect.SetLeft( static_cast<tools::Long>( fScanLeft ) );
|
||||
fScanTop += fScanIncY;
|
||||
aRect.SetTop( static_cast<tools::Long>( fScanTop ) );
|
||||
fScanRight -= fScanIncX;
|
||||
aRect.SetRight( static_cast<tools::Long>( fScanRight ) );
|
||||
fScanBottom -= fScanIncY;
|
||||
aRect.SetBottom( static_cast<tools::Long>( fScanBottom ) );
|
||||
|
||||
if( ( aRect.GetWidth() < 2 ) || ( aRect.GetHeight() < 2 ) )
|
||||
break;
|
||||
|
||||
if (GetStyle() == GradientStyle::Radial || GetStyle() == GradientStyle::Elliptical)
|
||||
aPoly = tools::Polygon( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
|
||||
else
|
||||
aPoly = tools::Polygon( aRect );
|
||||
|
||||
aPoly.Rotate(aCenter, GetAngle() % 3600_deg10);
|
||||
|
||||
// adapt colour accordingly
|
||||
const tools::Long nStepIndex = ( xPolyPoly ? i : ( i + 1 ) );
|
||||
nRed = GetGradientColorValue( nStartRed + ( ( nRedSteps * nStepIndex ) / nSteps ) );
|
||||
nGreen = GetGradientColorValue( nStartGreen + ( ( nGreenSteps * nStepIndex ) / nSteps ) );
|
||||
nBlue = GetGradientColorValue( nStartBlue + ( ( nBlueSteps * nStepIndex ) / nSteps ) );
|
||||
|
||||
bPaintLastPolygon = true; // #107349# Paint last polygon only if loop has generated any output
|
||||
|
||||
xPolyPoly->Replace( xPolyPoly->GetObject( 1 ), 0 );
|
||||
xPolyPoly->Replace( aPoly, 1 );
|
||||
|
||||
rMetaFile.AddAction( new MetaPolyPolygonAction( *xPolyPoly ) );
|
||||
|
||||
// #107349# Set fill color _after_ geometry painting:
|
||||
// xPolyPoly's geometry is the band from last iteration's
|
||||
// aPoly to current iteration's aPoly. The window outdev
|
||||
// path (see else below), on the other hand, paints the
|
||||
// full aPoly. Thus, here, we're painting the band before
|
||||
// the one painted in the window outdev path below. To get
|
||||
// matching colors, have to delay color setting here.
|
||||
rMetaFile.AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
}
|
||||
|
||||
const tools::Polygon& rPoly = xPolyPoly->GetObject( 1 );
|
||||
|
||||
if( rPoly.GetBoundRect().IsEmpty() )
|
||||
return;
|
||||
|
||||
// #107349# Paint last polygon with end color only if loop
|
||||
// has generated output. Otherwise, the current
|
||||
// (i.e. start) color is taken, to generate _any_ output.
|
||||
if( bPaintLastPolygon )
|
||||
{
|
||||
nRed = GetGradientColorValue( nEndRed );
|
||||
nGreen = GetGradientColorValue( nEndGreen );
|
||||
nBlue = GetGradientColorValue( nEndBlue );
|
||||
}
|
||||
|
||||
rMetaFile.AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
rMetaFile.AddAction( new MetaPolygonAction( rPoly ) );
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -60,8 +60,9 @@ void PDFWriterImpl::implWriteGradient( const tools::PolyPolygon& i_rPolyPoly, co
|
||||
VirtualDevice* i_pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& i_rContext )
|
||||
{
|
||||
GDIMetaFile aTmpMtf;
|
||||
Gradient aGradient(i_rGradient);
|
||||
|
||||
i_pDummyVDev->AddGradientActions( i_rPolyPoly.GetBoundRect(), i_rGradient, aTmpMtf );
|
||||
aGradient.AddGradientActions( i_rPolyPoly.GetBoundRect(), aTmpMtf );
|
||||
|
||||
m_rOuterFace.Push();
|
||||
m_rOuterFace.IntersectClipRegion( i_rPolyPoly.getB2DPolyPolygon() );
|
||||
|
||||
@@ -581,347 +581,6 @@ void OutputDevice::DrawComplexGradient( const tools::Rectangle& rRect,
|
||||
ImplDrawPolygon( rPoly, pClixPolyPoly );
|
||||
}
|
||||
|
||||
static tools::Long GetGradientMetafileSteps(Gradient const& rGradient, tools::Rectangle const& rRect)
|
||||
{
|
||||
// calculate step count
|
||||
tools::Long nStepCount = rGradient.GetSteps();
|
||||
|
||||
if (nStepCount)
|
||||
return nStepCount;
|
||||
|
||||
if (rGradient.GetStyle() == GradientStyle::Linear || rGradient.GetStyle() == GradientStyle::Axial)
|
||||
return rRect.GetHeight();
|
||||
else
|
||||
return std::min(rRect.GetWidth(), rRect.GetHeight());
|
||||
}
|
||||
|
||||
void OutputDevice::DrawLinearGradientToMetafile( const tools::Rectangle& rRect,
|
||||
const Gradient& rGradient )
|
||||
{
|
||||
assert(!is_double_buffered_window());
|
||||
|
||||
// get BoundRect of rotated rectangle
|
||||
tools::Rectangle aRect;
|
||||
Point aCenter;
|
||||
Degree10 nAngle = rGradient.GetAngle() % 3600_deg10;
|
||||
|
||||
rGradient.GetBoundRect( rRect, aRect, aCenter );
|
||||
|
||||
bool bLinear = (rGradient.GetStyle() == GradientStyle::Linear);
|
||||
double fBorder = rGradient.GetBorder() * aRect.GetHeight() / 100.0;
|
||||
if ( !bLinear )
|
||||
{
|
||||
fBorder /= 2.0;
|
||||
}
|
||||
tools::Rectangle aMirrorRect = aRect; // used in style axial
|
||||
aMirrorRect.SetTop( ( aRect.Top() + aRect.Bottom() ) / 2 );
|
||||
if ( !bLinear )
|
||||
{
|
||||
aRect.SetBottom( aMirrorRect.Top() );
|
||||
}
|
||||
|
||||
// colour-intensities of start- and finish; change if needed
|
||||
tools::Long nFactor;
|
||||
Color aStartCol = rGradient.GetStartColor();
|
||||
Color aEndCol = rGradient.GetEndColor();
|
||||
tools::Long nStartRed = aStartCol.GetRed();
|
||||
tools::Long nStartGreen = aStartCol.GetGreen();
|
||||
tools::Long nStartBlue = aStartCol.GetBlue();
|
||||
tools::Long nEndRed = aEndCol.GetRed();
|
||||
tools::Long nEndGreen = aEndCol.GetGreen();
|
||||
tools::Long nEndBlue = aEndCol.GetBlue();
|
||||
nFactor = rGradient.GetStartIntensity();
|
||||
nStartRed = (nStartRed * nFactor) / 100;
|
||||
nStartGreen = (nStartGreen * nFactor) / 100;
|
||||
nStartBlue = (nStartBlue * nFactor) / 100;
|
||||
nFactor = rGradient.GetEndIntensity();
|
||||
nEndRed = (nEndRed * nFactor) / 100;
|
||||
nEndGreen = (nEndGreen * nFactor) / 100;
|
||||
nEndBlue = (nEndBlue * nFactor) / 100;
|
||||
|
||||
// gradient style axial has exchanged start and end colors
|
||||
if ( !bLinear)
|
||||
{
|
||||
tools::Long nTempColor = nStartRed;
|
||||
nStartRed = nEndRed;
|
||||
nEndRed = nTempColor;
|
||||
nTempColor = nStartGreen;
|
||||
nStartGreen = nEndGreen;
|
||||
nEndGreen = nTempColor;
|
||||
nTempColor = nStartBlue;
|
||||
nStartBlue = nEndBlue;
|
||||
nEndBlue = nTempColor;
|
||||
}
|
||||
|
||||
sal_uInt8 nRed;
|
||||
sal_uInt8 nGreen;
|
||||
sal_uInt8 nBlue;
|
||||
|
||||
// Create border
|
||||
tools::Rectangle aBorderRect = aRect;
|
||||
tools::Polygon aPoly( 4 );
|
||||
if (fBorder > 0.0)
|
||||
{
|
||||
nRed = static_cast<sal_uInt8>(nStartRed);
|
||||
nGreen = static_cast<sal_uInt8>(nStartGreen);
|
||||
nBlue = static_cast<sal_uInt8>(nStartBlue);
|
||||
|
||||
mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
|
||||
aBorderRect.SetBottom( static_cast<tools::Long>( aBorderRect.Top() + fBorder ) );
|
||||
aRect.SetTop( aBorderRect.Bottom() );
|
||||
aPoly[0] = aBorderRect.TopLeft();
|
||||
aPoly[1] = aBorderRect.TopRight();
|
||||
aPoly[2] = aBorderRect.BottomRight();
|
||||
aPoly[3] = aBorderRect.BottomLeft();
|
||||
aPoly.Rotate( aCenter, nAngle );
|
||||
|
||||
mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
|
||||
|
||||
if ( !bLinear)
|
||||
{
|
||||
aBorderRect = aMirrorRect;
|
||||
aBorderRect.SetTop( static_cast<tools::Long>( aBorderRect.Bottom() - fBorder ) );
|
||||
aMirrorRect.SetBottom( aBorderRect.Top() );
|
||||
aPoly[0] = aBorderRect.TopLeft();
|
||||
aPoly[1] = aBorderRect.TopRight();
|
||||
aPoly[2] = aBorderRect.BottomRight();
|
||||
aPoly[3] = aBorderRect.BottomLeft();
|
||||
aPoly.Rotate( aCenter, nAngle );
|
||||
|
||||
mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
|
||||
}
|
||||
}
|
||||
|
||||
tools::Long nStepCount = GetGradientMetafileSteps(rGradient, aRect);
|
||||
|
||||
// minimal three steps and maximal as max color steps
|
||||
tools::Long nAbsRedSteps = std::abs( nEndRed - nStartRed );
|
||||
tools::Long nAbsGreenSteps = std::abs( nEndGreen - nStartGreen );
|
||||
tools::Long nAbsBlueSteps = std::abs( nEndBlue - nStartBlue );
|
||||
tools::Long nMaxColorSteps = std::max( nAbsRedSteps , nAbsGreenSteps );
|
||||
nMaxColorSteps = std::max( nMaxColorSteps, nAbsBlueSteps );
|
||||
tools::Long nSteps = std::min( nStepCount, nMaxColorSteps );
|
||||
if ( nSteps < 3)
|
||||
{
|
||||
nSteps = 3;
|
||||
}
|
||||
|
||||
double fScanInc = static_cast<double>(aRect.GetHeight()) / static_cast<double>(nSteps);
|
||||
double fGradientLine = static_cast<double>(aRect.Top());
|
||||
double fMirrorGradientLine = static_cast<double>(aMirrorRect.Bottom());
|
||||
|
||||
const double fStepsMinus1 = static_cast<double>(nSteps) - 1.0;
|
||||
if ( !bLinear)
|
||||
{
|
||||
nSteps -= 1; // draw middle polygons as one polygon after loop to avoid gap
|
||||
}
|
||||
for ( tools::Long i = 0; i < nSteps; i++ )
|
||||
{
|
||||
// linear interpolation of color
|
||||
double fAlpha = static_cast<double>(i) / fStepsMinus1;
|
||||
double fTempColor = static_cast<double>(nStartRed) * (1.0-fAlpha) + static_cast<double>(nEndRed) * fAlpha;
|
||||
nRed = GetGradientColorValue(static_cast<tools::Long>(fTempColor));
|
||||
fTempColor = static_cast<double>(nStartGreen) * (1.0-fAlpha) + static_cast<double>(nEndGreen) * fAlpha;
|
||||
nGreen = GetGradientColorValue(static_cast<tools::Long>(fTempColor));
|
||||
fTempColor = static_cast<double>(nStartBlue) * (1.0-fAlpha) + static_cast<double>(nEndBlue) * fAlpha;
|
||||
nBlue = GetGradientColorValue(static_cast<tools::Long>(fTempColor));
|
||||
|
||||
mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
|
||||
// Polygon for this color step
|
||||
aRect.SetTop( static_cast<tools::Long>( fGradientLine + static_cast<double>(i) * fScanInc ) );
|
||||
aRect.SetBottom( static_cast<tools::Long>( fGradientLine + ( static_cast<double>(i) + 1.0 ) * fScanInc ) );
|
||||
aPoly[0] = aRect.TopLeft();
|
||||
aPoly[1] = aRect.TopRight();
|
||||
aPoly[2] = aRect.BottomRight();
|
||||
aPoly[3] = aRect.BottomLeft();
|
||||
aPoly.Rotate( aCenter, nAngle );
|
||||
|
||||
mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
|
||||
|
||||
if ( !bLinear )
|
||||
{
|
||||
aMirrorRect.SetBottom( static_cast<tools::Long>( fMirrorGradientLine - static_cast<double>(i) * fScanInc ) );
|
||||
aMirrorRect.SetTop( static_cast<tools::Long>( fMirrorGradientLine - (static_cast<double>(i) + 1.0)* fScanInc ) );
|
||||
aPoly[0] = aMirrorRect.TopLeft();
|
||||
aPoly[1] = aMirrorRect.TopRight();
|
||||
aPoly[2] = aMirrorRect.BottomRight();
|
||||
aPoly[3] = aMirrorRect.BottomLeft();
|
||||
aPoly.Rotate( aCenter, nAngle );
|
||||
|
||||
mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
|
||||
}
|
||||
}
|
||||
if ( bLinear)
|
||||
return;
|
||||
|
||||
// draw middle polygon with end color
|
||||
nRed = GetGradientColorValue(nEndRed);
|
||||
nGreen = GetGradientColorValue(nEndGreen);
|
||||
nBlue = GetGradientColorValue(nEndBlue);
|
||||
|
||||
mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
|
||||
aRect.SetTop( static_cast<tools::Long>( fGradientLine + static_cast<double>(nSteps) * fScanInc ) );
|
||||
aRect.SetBottom( static_cast<tools::Long>( fMirrorGradientLine - static_cast<double>(nSteps) * fScanInc ) );
|
||||
aPoly[0] = aRect.TopLeft();
|
||||
aPoly[1] = aRect.TopRight();
|
||||
aPoly[2] = aRect.BottomRight();
|
||||
aPoly[3] = aRect.BottomLeft();
|
||||
aPoly.Rotate( aCenter, nAngle );
|
||||
|
||||
mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
|
||||
|
||||
}
|
||||
|
||||
void OutputDevice::DrawComplexGradientToMetafile( const tools::Rectangle& rRect,
|
||||
const Gradient& rGradient )
|
||||
{
|
||||
assert(!is_double_buffered_window());
|
||||
|
||||
// Determine if we output via Polygon or PolyPolygon
|
||||
// For all rasteroperations other than Overpaint always use PolyPolygon,
|
||||
// as we will get wrong results if we output multiple times on top of each other.
|
||||
// Also for printers always use PolyPolygon, as not all printers
|
||||
// can print polygons on top of each other.
|
||||
|
||||
tools::Rectangle aRect;
|
||||
Point aCenter;
|
||||
rGradient.GetBoundRect(rRect, aRect, aCenter);
|
||||
|
||||
std::optional<tools::PolyPolygon> xPolyPoly;
|
||||
xPolyPoly = tools::PolyPolygon( 2 );
|
||||
|
||||
// last parameter - true if complex gradient, false if linear
|
||||
tools::Long nStepCount = GetGradientMetafileSteps(rGradient, rRect);
|
||||
|
||||
// at least three steps and at most the number of colour differences
|
||||
tools::Long nSteps = std::max(nStepCount, tools::Long(2));
|
||||
|
||||
Color aStartCol(rGradient.GetStartColor());
|
||||
Color aEndCol(rGradient.GetEndColor());
|
||||
|
||||
tools::Long nStartRed = (static_cast<tools::Long>(aStartCol.GetRed()) * rGradient.GetStartIntensity()) / 100;
|
||||
tools::Long nStartGreen = (static_cast<tools::Long>(aStartCol.GetGreen()) * rGradient.GetStartIntensity()) / 100;
|
||||
tools::Long nStartBlue = (static_cast<tools::Long>(aStartCol.GetBlue()) * rGradient.GetStartIntensity()) / 100;
|
||||
|
||||
tools::Long nEndRed = (static_cast<tools::Long>(aEndCol.GetRed()) * rGradient.GetEndIntensity()) / 100;
|
||||
tools::Long nEndGreen = (static_cast<tools::Long>(aEndCol.GetGreen()) * rGradient.GetEndIntensity()) / 100;
|
||||
tools::Long nEndBlue = (static_cast<tools::Long>(aEndCol.GetBlue()) * rGradient.GetEndIntensity()) / 100;
|
||||
|
||||
tools::Long nRedSteps = nEndRed - nStartRed;
|
||||
tools::Long nGreenSteps = nEndGreen - nStartGreen;
|
||||
tools::Long nBlueSteps = nEndBlue - nStartBlue;
|
||||
|
||||
tools::Long nCalcSteps = std::abs(nRedSteps);
|
||||
tools::Long nTempSteps = std::abs(nGreenSteps);
|
||||
|
||||
if (nTempSteps > nCalcSteps)
|
||||
nCalcSteps = nTempSteps;
|
||||
|
||||
nTempSteps = std::abs( nBlueSteps );
|
||||
|
||||
if (nTempSteps > nCalcSteps)
|
||||
nCalcSteps = nTempSteps;
|
||||
|
||||
if (nCalcSteps < nSteps)
|
||||
nSteps = nCalcSteps;
|
||||
|
||||
if ( !nSteps )
|
||||
nSteps = 1;
|
||||
|
||||
// determine output limits and stepsizes for all directions
|
||||
tools::Polygon aPoly;
|
||||
double fScanLeft = aRect.Left();
|
||||
double fScanTop = aRect.Top();
|
||||
double fScanRight = aRect.Right();
|
||||
double fScanBottom = aRect.Bottom();
|
||||
double fScanIncX = static_cast<double>(aRect.GetWidth()) / static_cast<double>(nSteps) * 0.5;
|
||||
double fScanIncY = static_cast<double>(aRect.GetHeight()) / static_cast<double>(nSteps) * 0.5;
|
||||
|
||||
// all gradients are rendered as nested rectangles which shrink
|
||||
// equally in each dimension - except for 'square' gradients
|
||||
// which shrink to a central vertex but are not per-se square.
|
||||
if( rGradient.GetStyle() != GradientStyle::Square )
|
||||
{
|
||||
fScanIncY = std::min( fScanIncY, fScanIncX );
|
||||
fScanIncX = fScanIncY;
|
||||
}
|
||||
sal_uInt8 nRed = static_cast<sal_uInt8>(nStartRed), nGreen = static_cast<sal_uInt8>(nStartGreen), nBlue = static_cast<sal_uInt8>(nStartBlue);
|
||||
bool bPaintLastPolygon( false ); // #107349# Paint last polygon only if loop has generated any output
|
||||
|
||||
mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
|
||||
aPoly = rRect;
|
||||
xPolyPoly->Insert( aPoly );
|
||||
xPolyPoly->Insert( aPoly );
|
||||
|
||||
// loop to output Polygon/PolyPolygon sequentially
|
||||
for( tools::Long i = 1; i < nSteps; i++ )
|
||||
{
|
||||
// calculate new Polygon
|
||||
fScanLeft += fScanIncX;
|
||||
aRect.SetLeft( static_cast<tools::Long>( fScanLeft ) );
|
||||
fScanTop += fScanIncY;
|
||||
aRect.SetTop( static_cast<tools::Long>( fScanTop ) );
|
||||
fScanRight -= fScanIncX;
|
||||
aRect.SetRight( static_cast<tools::Long>( fScanRight ) );
|
||||
fScanBottom -= fScanIncY;
|
||||
aRect.SetBottom( static_cast<tools::Long>( fScanBottom ) );
|
||||
|
||||
if( ( aRect.GetWidth() < 2 ) || ( aRect.GetHeight() < 2 ) )
|
||||
break;
|
||||
|
||||
if( rGradient.GetStyle() == GradientStyle::Radial || rGradient.GetStyle() == GradientStyle::Elliptical )
|
||||
aPoly = tools::Polygon( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
|
||||
else
|
||||
aPoly = tools::Polygon( aRect );
|
||||
|
||||
aPoly.Rotate(aCenter, rGradient.GetAngle() % 3600_deg10);
|
||||
|
||||
// adapt colour accordingly
|
||||
const tools::Long nStepIndex = ( xPolyPoly ? i : ( i + 1 ) );
|
||||
nRed = GetGradientColorValue( nStartRed + ( ( nRedSteps * nStepIndex ) / nSteps ) );
|
||||
nGreen = GetGradientColorValue( nStartGreen + ( ( nGreenSteps * nStepIndex ) / nSteps ) );
|
||||
nBlue = GetGradientColorValue( nStartBlue + ( ( nBlueSteps * nStepIndex ) / nSteps ) );
|
||||
|
||||
bPaintLastPolygon = true; // #107349# Paint last polygon only if loop has generated any output
|
||||
|
||||
xPolyPoly->Replace( xPolyPoly->GetObject( 1 ), 0 );
|
||||
xPolyPoly->Replace( aPoly, 1 );
|
||||
|
||||
mpMetaFile->AddAction( new MetaPolyPolygonAction( *xPolyPoly ) );
|
||||
|
||||
// #107349# Set fill color _after_ geometry painting:
|
||||
// xPolyPoly's geometry is the band from last iteration's
|
||||
// aPoly to current iteration's aPoly. The window outdev
|
||||
// path (see else below), on the other hand, paints the
|
||||
// full aPoly. Thus, here, we're painting the band before
|
||||
// the one painted in the window outdev path below. To get
|
||||
// matching colors, have to delay color setting here.
|
||||
mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
}
|
||||
|
||||
const tools::Polygon& rPoly = xPolyPoly->GetObject( 1 );
|
||||
|
||||
if( rPoly.GetBoundRect().IsEmpty() )
|
||||
return;
|
||||
|
||||
// #107349# Paint last polygon with end color only if loop
|
||||
// has generated output. Otherwise, the current
|
||||
// (i.e. start) color is taken, to generate _any_ output.
|
||||
if( bPaintLastPolygon )
|
||||
{
|
||||
nRed = GetGradientColorValue( nEndRed );
|
||||
nGreen = GetGradientColorValue( nEndGreen );
|
||||
nBlue = GetGradientColorValue( nEndBlue );
|
||||
}
|
||||
|
||||
mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), true ) );
|
||||
mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) );
|
||||
}
|
||||
|
||||
tools::Long OutputDevice::GetGradientStepCount( tools::Long nMinRect )
|
||||
{
|
||||
tools::Long nInc = (nMinRect < 50) ? 2 : 4;
|
||||
@@ -969,45 +628,4 @@ Color OutputDevice::GetSingleColorGradientFill()
|
||||
return aColor;
|
||||
}
|
||||
|
||||
void OutputDevice::AddGradientActions( const tools::Rectangle& rRect, const Gradient& rGradient,
|
||||
GDIMetaFile& rMtf )
|
||||
{
|
||||
|
||||
tools::Rectangle aRect( rRect );
|
||||
|
||||
aRect.Justify();
|
||||
|
||||
// do nothing if the rectangle is empty
|
||||
if ( aRect.IsEmpty() )
|
||||
return;
|
||||
|
||||
Gradient aGradient( rGradient );
|
||||
GDIMetaFile* pOldMtf = mpMetaFile;
|
||||
|
||||
mpMetaFile = &rMtf;
|
||||
mpMetaFile->AddAction( new MetaPushAction( vcl::PushFlags::ALL ) );
|
||||
mpMetaFile->AddAction( new MetaISectRectClipRegionAction( aRect ) );
|
||||
mpMetaFile->AddAction( new MetaLineColorAction( Color(), false ) );
|
||||
|
||||
// because we draw with no border line, we have to expand gradient
|
||||
// rect to avoid missing lines on the right and bottom edge
|
||||
aRect.AdjustLeft( -1 );
|
||||
aRect.AdjustTop( -1 );
|
||||
aRect.AdjustRight( 1 );
|
||||
aRect.AdjustBottom( 1 );
|
||||
|
||||
// calculate step count if necessary
|
||||
if ( !aGradient.GetSteps() )
|
||||
aGradient.SetSteps( GRADIENT_DEFAULT_STEPCOUNT );
|
||||
|
||||
if( aGradient.GetStyle() == GradientStyle::Linear || aGradient.GetStyle() == GradientStyle::Axial )
|
||||
DrawLinearGradientToMetafile( aRect, aGradient );
|
||||
else
|
||||
DrawComplexGradientToMetafile( aRect, aGradient );
|
||||
|
||||
mpMetaFile->AddAction( new MetaPopAction() );
|
||||
mpMetaFile = pOldMtf;
|
||||
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
Reference in New Issue
Block a user