summaryrefslogtreecommitdiff
path: root/canvas/source
diff options
context:
space:
mode:
authorthb <thb@openoffice.org>2009-10-16 00:43:16 +0200
committerthb <thb@openoffice.org>2009-10-16 00:43:16 +0200
commit1837a267a2cf82b0152631e416d8be66c2adef25 (patch)
treee9df5704754fc1ed559cdc01d7d5c41207af5374 /canvas/source
parent9b9d44ee50a38180c2451ca527bf7b9f6f46f0fe (diff)
#i105937# Much improved gradient support for canvas/basegfx/drawinglayer.
See http://blog.thebehrens.net/2009/07/28/hackweek-iv-canvas-convwatch/ for more background information
Diffstat (limited to 'canvas/source')
-rw-r--r--canvas/source/cairo/cairo_canvas.hxx3
-rw-r--r--canvas/source/cairo/cairo_canvashelper.cxx268
-rw-r--r--canvas/source/cairo/cairo_spritecanvas.hxx3
-rw-r--r--canvas/source/null/null_spritecanvas.hxx4
-rw-r--r--canvas/source/tools/parametricpolypolygon.cxx114
-rw-r--r--canvas/source/vcl/canvas.hxx3
-rw-r--r--canvas/source/vcl/canvashelper_texturefill.cxx286
-rw-r--r--canvas/source/vcl/spritecanvas.hxx3
8 files changed, 391 insertions, 293 deletions
diff --git a/canvas/source/cairo/cairo_canvas.hxx b/canvas/source/cairo/cairo_canvas.hxx
index de2b9f8693a1..8fa56b5f4187 100644
--- a/canvas/source/cairo/cairo_canvas.hxx
+++ b/canvas/source/cairo/cairo_canvas.hxx
@@ -44,7 +44,6 @@
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
#include <com/sun/star/rendering/XGraphicDevice.hpp>
#include <com/sun/star/rendering/XBufferController.hpp>
-#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
#include <cppuhelper/compbase7.hxx>
#include <comphelper/uno3.hxx>
@@ -68,7 +67,7 @@ namespace cairocanvas
typedef ::cppu::WeakComponentImplHelper7< ::com::sun::star::rendering::XBitmapCanvas,
::com::sun::star::rendering::XIntegerBitmap,
::com::sun::star::rendering::XGraphicDevice,
- ::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
+ ::com::sun::star::lang::XMultiServiceFactory,
::com::sun::star::util::XUpdatable,
::com::sun::star::beans::XPropertySet,
::com::sun::star::lang::XServiceName > GraphicDeviceBase_Base;
diff --git a/canvas/source/cairo/cairo_canvashelper.cxx b/canvas/source/cairo/cairo_canvashelper.cxx
index 9cf2dd978759..942e5edb06a6 100644
--- a/canvas/source/cairo/cairo_canvashelper.cxx
+++ b/canvas/source/cairo/cairo_canvashelper.cxx
@@ -56,6 +56,8 @@
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/tools/keystoplerp.hxx>
+#include <basegfx/tools/lerp.hxx>
#include <comphelper/sequence.hxx>
#include <cppuhelper/compbase1.hxx>
@@ -73,6 +75,7 @@
#include "cairo_canvashelper.hxx"
#include "cairo_canvasbitmap.hxx"
+#include <boost/tuple/tuple.hpp>
#include <algorithm>
using namespace ::cairo;
@@ -122,9 +125,29 @@ namespace cairocanvas
mpCairo = pSurface->getCairo();
}
+ static void setColor( Cairo* pCairo,
+ const uno::Sequence<double>& rColor )
+ {
+ if( rColor.getLength() > 3 )
+ {
+ const double alpha = rColor[3];
+
+ cairo_set_source_rgba( pCairo,
+ alpha*rColor[0],
+ alpha*rColor[1],
+ alpha*rColor[2],
+ alpha );
+ }
+ else if( rColor.getLength() == 3 )
+ cairo_set_source_rgb( pCairo,
+ rColor[0],
+ rColor[1],
+ rColor[2] );
+ }
+
void CanvasHelper::useStates( const rendering::ViewState& viewState,
const rendering::RenderState& renderState,
- bool setColor )
+ bool bSetColor )
{
Matrix aViewMatrix;
Matrix aRenderMatrix;
@@ -158,19 +181,8 @@ namespace cairocanvas
OSL_TRACE ("render clip END");
}
- if( setColor ) {
- if( renderState.DeviceColor.getLength() > 3 )
- cairo_set_source_rgba( mpCairo.get(),
- renderState.DeviceColor [0],
- renderState.DeviceColor [1],
- renderState.DeviceColor [2],
- renderState.DeviceColor [3] );
- else if (renderState.DeviceColor.getLength() == 3)
- cairo_set_source_rgb( mpCairo.get(),
- renderState.DeviceColor [0],
- renderState.DeviceColor [1],
- renderState.DeviceColor [2] );
- }
+ if( bSetColor )
+ setColor(mpCairo.get(),renderState.DeviceColor);
cairo_operator_t compositingMode( CAIRO_OPERATOR_OVER );
switch( renderState.CompositeOperation )
@@ -665,11 +677,33 @@ namespace cairocanvas
double alpha = rColor[3];
// cairo expects premultiplied alpha
cairo_pattern_add_color_stop_rgba( pPattern, stop, rColor[0]*alpha, rColor[1]*alpha, rColor[2]*alpha, alpha );
- //cairo_pattern_add_color_stop_rgba( pPattern, stop, rColor[0], rColor[1], rColor[2], alpha );
}
}
}
+ static uno::Sequence<double> lerp(const uno::Sequence<double>& rLeft, const uno::Sequence<double>& rRight, double fAlpha)
+ {
+ if( rLeft.getLength() == 3 )
+ {
+ uno::Sequence<double> aRes(3);
+ aRes[0] = basegfx::tools::lerp(rLeft[0],rRight[0],fAlpha);
+ aRes[1] = basegfx::tools::lerp(rLeft[1],rRight[1],fAlpha);
+ aRes[2] = basegfx::tools::lerp(rLeft[2],rRight[2],fAlpha);
+ return aRes;
+ }
+ else if( rLeft.getLength() == 4 )
+ {
+ uno::Sequence<double> aRes(4);
+ aRes[0] = basegfx::tools::lerp(rLeft[0],rRight[0],fAlpha);
+ aRes[1] = basegfx::tools::lerp(rLeft[1],rRight[1],fAlpha);
+ aRes[2] = basegfx::tools::lerp(rLeft[2],rRight[2],fAlpha);
+ aRes[3] = basegfx::tools::lerp(rLeft[3],rRight[3],fAlpha);
+ return aRes;
+ }
+
+ return uno::Sequence<double>();
+ }
+
static Pattern* patternFromParametricPolyPolygon( ::canvas::ParametricPolyPolygon& rPolygon )
{
Pattern* pPattern = NULL;
@@ -678,7 +712,6 @@ namespace cairocanvas
// undef macros from vclenum.hxx which conflicts with GradientType enum values
#undef GRADIENT_LINEAR
-#undef GRADIENT_AXIAL
#undef GRADIENT_ELLIPTICAL
switch( aValues.meType ) {
@@ -691,26 +724,17 @@ namespace cairocanvas
addColorStops( pPattern, aValues.maColors, aValues.maStops );
break;
- // FIXME: NYI
- case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR:
- case ::canvas::ParametricPolyPolygon::GRADIENT_AXIAL:
- x0 = 0;
- y0 = 0;
- x1 = 1;
- y1 = 0;
- pPattern = cairo_pattern_create_linear( x0, y0, x1, y1 );
- addColorStops( pPattern, aValues.maColors, aValues.maStops );
- break;
-
case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
- cx = 0.5;
- cy = 0.5;
+ cx = 0;
+ cy = 0;
r0 = 0;
- r1 = 0.5;
+ r1 = 1;
- pPattern = cairo_pattern_create_radial( cx, cy, r0, cx, cy, r1 );
+ pPattern = cairo_pattern_create_radial( cx, cy, r0, cy, cy, r1 );
addColorStops( pPattern, aValues.maColors, aValues.maStops, true );
break;
+ default:
+ break;
}
return pPattern;
@@ -719,7 +743,8 @@ namespace cairocanvas
static void doOperation( Operation aOperation,
Cairo* pCairo,
const uno::Sequence< rendering::Texture >* pTextures,
- const SurfaceProviderRef& pDevice )
+ const SurfaceProviderRef& pDevice,
+ const basegfx::B2DRange& rBounds )
{
switch( aOperation ) {
case Fill:
@@ -790,19 +815,70 @@ namespace cairocanvas
cairo_matrix_init( &aTextureMatrix,
aTransform.m00, aTransform.m10, aTransform.m01,
aTransform.m11, aTransform.m02, aTransform.m12);
- Pattern* pPattern = patternFromParametricPolyPolygon( *pPolyImpl );
+ if( pPolyImpl->getValues().meType == canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR )
+ {
+ // no general path gradient yet in cairo; emulate then
+ cairo_save( pCairo );
+ cairo_clip( pCairo );
+
+ // fill bound rect with start color
+ cairo_rectangle( pCairo, rBounds.getMinX(), rBounds.getMinY(),
+ rBounds.getWidth(), rBounds.getHeight() );
+ setColor(pCairo,pPolyImpl->getValues().maColors[0]);
+ cairo_fill(pCairo);
+
+ cairo_transform( pCairo, &aTextureMatrix );
+
+ // longest line in gradient bound rect
+ const unsigned int nGradientSize(
+ static_cast<unsigned int>(
+ ::basegfx::B2DVector(rBounds.getMinimum() - rBounds.getMaximum()).getLength() + 1.0 ) );
+
+ // typical number for pixel of the same color (strip size)
+ const unsigned int nStripSize( nGradientSize < 50 ? 2 : 4 );
+
+ // use at least three steps, and at utmost the number of color
+ // steps
+ const unsigned int nStepCount(
+ ::std::max(
+ 3U,
+ ::std::min(
+ nGradientSize / nStripSize,
+ 128U )) + 1 );
+
+ const uno::Sequence<double>* pColors=&pPolyImpl->getValues().maColors[0];
+ basegfx::tools::KeyStopLerp aLerper(pPolyImpl->getValues().maStops);
+ for( unsigned int i=1; i<nStepCount; ++i )
+ {
+ const double fT( i/double(nStepCount) );
- if( pPattern ) {
- OSL_TRACE( "filling with pattern" );
+ std::ptrdiff_t nIndex;
+ double fAlpha;
+ boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(fT);
- cairo_save( pCairo );
+ setColor(pCairo, lerp(pColors[nIndex], pColors[nIndex+1], fAlpha));
+ cairo_rectangle( pCairo, -1+fT, -1+fT, 2-2*fT, 2-2*fT );
+ cairo_fill(pCairo);
+ }
- cairo_transform( pCairo, &aTextureMatrix );
- cairo_set_source( pCairo, pPattern );
- cairo_fill( pCairo );
cairo_restore( pCairo );
+ }
+ else
+ {
+ Pattern* pPattern = patternFromParametricPolyPolygon( *pPolyImpl );
+
+ if( pPattern ) {
+ OSL_TRACE( "filling with pattern" );
+
+ cairo_save( pCairo );
+
+ cairo_transform( pCairo, &aTextureMatrix );
+ cairo_set_source( pCairo, pPattern );
+ cairo_fill( pCairo );
+ cairo_restore( pCairo );
- cairo_pattern_destroy( pPattern );
+ cairo_pattern_destroy( pPattern );
+ }
}
}
}
@@ -935,7 +1011,7 @@ namespace cairocanvas
if( aOperation == Fill && pTextures ) {
cairo_set_matrix( pCairo, &aOrigMatrix );
- doOperation( aOperation, pCairo, pTextures, pDevice );
+ doOperation( aOperation, pCairo, pTextures, pDevice, aPolyPolygon.getB2DRange() );
cairo_set_matrix( pCairo, &aIdentityMatrix );
}
} else {
@@ -948,7 +1024,7 @@ namespace cairocanvas
}
}
if( bOpToDo && ( aOperation != Fill || !pTextures ) )
- doOperation( aOperation, pCairo, pTextures, pDevice );
+ doOperation( aOperation, pCairo, pTextures, pDevice, aPolyPolygon.getB2DRange() );
cairo_set_matrix( pCairo, &aOrigMatrix );
@@ -1171,12 +1247,12 @@ namespace cairocanvas
const rendering::ViewState& viewState,
const rendering::RenderState& renderState,
const geometry::IntegerSize2D& rSize,
- bool /*bModulateColors*/,
+ bool bModulateColors,
bool bHasAlpha )
{
SurfaceSharedPtr pSurface=pInputSurface;
uno::Reference< rendering::XCachedPrimitive > rv = uno::Reference< rendering::XCachedPrimitive >(NULL);
- geometry::IntegerSize2D aBitmapSize = rSize;
+ geometry::IntegerSize2D aBitmapSize = rSize;
if( mpCairo ) {
cairo_save( mpCairo.get() );
@@ -1198,38 +1274,38 @@ namespace cairocanvas
::rtl::math::approxEqual( aMatrix.y0, 0 ) &&
basegfx::fround( rSize.Width * aMatrix.xx ) > 8 &&
basegfx::fround( rSize.Height* aMatrix.yy ) > 8 )
- {
- double dWidth, dHeight;
-
- dWidth = basegfx::fround( rSize.Width * aMatrix.xx );
- dHeight = basegfx::fround( rSize.Height* aMatrix.yy );
- aBitmapSize.Width = static_cast<sal_Int32>( dWidth );
- aBitmapSize.Height = static_cast<sal_Int32>( dHeight );
-
- SurfaceSharedPtr pScaledSurface = mpSurfaceProvider->createSurface(
- ::basegfx::B2ISize( aBitmapSize.Width, aBitmapSize.Height ),
- bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
- CairoSharedPtr pCairo = pScaledSurface->getCairo();
-
- cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
- // add 0.5px to size to avoid rounding errors in cairo, leading sometimes to random data on the image right/bottom borders
- cairo_scale( pCairo.get(), (dWidth+0.5)/rSize.Width, (dHeight+0.5)/rSize.Height );
- cairo_set_source_surface( pCairo.get(), pSurface->getCairoSurface().get(), 0, 0 );
- cairo_paint( pCairo.get() );
-
- pSurface = pScaledSurface;
-
- aMatrix.xx = aMatrix.yy = 1;
- cairo_set_matrix( mpCairo.get(), &aMatrix );
-
- rv = uno::Reference< rendering::XCachedPrimitive >(
- new CachedBitmap( pSurface, viewState, renderState,
- // cast away const, need to
- // change refcount (as this is
- // ~invisible to client code,
- // still logically const)
- const_cast< rendering::XCanvas* >(pCanvas)) );
- }
+ {
+ double dWidth, dHeight;
+
+ dWidth = basegfx::fround( rSize.Width * aMatrix.xx );
+ dHeight = basegfx::fround( rSize.Height* aMatrix.yy );
+ aBitmapSize.Width = static_cast<sal_Int32>( dWidth );
+ aBitmapSize.Height = static_cast<sal_Int32>( dHeight );
+
+ SurfaceSharedPtr pScaledSurface = mpSurfaceProvider->createSurface(
+ ::basegfx::B2ISize( aBitmapSize.Width, aBitmapSize.Height ),
+ bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
+ CairoSharedPtr pCairo = pScaledSurface->getCairo();
+
+ cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
+ // add 0.5px to size to avoid rounding errors in cairo, leading sometimes to random data on the image right/bottom borders
+ cairo_scale( pCairo.get(), (dWidth+0.5)/rSize.Width, (dHeight+0.5)/rSize.Height );
+ cairo_set_source_surface( pCairo.get(), pSurface->getCairoSurface().get(), 0, 0 );
+ cairo_paint( pCairo.get() );
+
+ pSurface = pScaledSurface;
+
+ aMatrix.xx = aMatrix.yy = 1;
+ cairo_set_matrix( mpCairo.get(), &aMatrix );
+
+ rv = uno::Reference< rendering::XCachedPrimitive >(
+ new CachedBitmap( pSurface, viewState, renderState,
+ // cast away const, need to
+ // change refcount (as this is
+ // ~invisible to client code,
+ // still logically const)
+ const_cast< rendering::XCanvas* >(pCanvas)) );
+ }
if( !bHasAlpha && mbHaveAlpha )
{
@@ -1270,7 +1346,11 @@ namespace cairocanvas
cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
cairo_rectangle( mpCairo.get(), 0, 0, aBitmapSize.Width, aBitmapSize.Height );
cairo_clip( mpCairo.get() );
- cairo_paint( mpCairo.get() );
+
+ if( bModulateColors )
+ cairo_paint_with_alpha( mpCairo.get(), renderState.DeviceColor[3] );
+ else
+ cairo_paint( mpCairo.get() );
cairo_restore( mpCairo.get() );
} else
OSL_TRACE ("CanvasHelper called after it was disposed");
@@ -1309,15 +1389,35 @@ namespace cairocanvas
return rv;
}
- uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* ,
- const uno::Reference< rendering::XBitmap >& /*xBitmap*/,
- const rendering::ViewState& /*viewState*/,
- const rendering::RenderState& /*renderState*/ )
+ uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas,
+ const uno::Reference< rendering::XBitmap >& xBitmap,
+ const rendering::ViewState& viewState,
+ const rendering::RenderState& renderState )
{
- // TODO(F3): Implement modulated bitmap!
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ struct timespec aTimer;
+ mxDevice->startPerfTrace( &aTimer );
+#endif
- // TODO(P1): Provide caching here.
- return uno::Reference< rendering::XCachedPrimitive >(NULL);
+ uno::Reference< rendering::XCachedPrimitive > rv;
+ unsigned char* data = NULL;
+ bool bHasAlpha = false;
+ SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap, mpSurfaceProvider, data, bHasAlpha );
+ geometry::IntegerSize2D aSize = xBitmap->getSize();
+
+ if( pSurface ) {
+ rv = implDrawBitmapSurface( pCanvas, pSurface, viewState, renderState, aSize, true, bHasAlpha );
+
+ if( data )
+ free( data );
+ } else
+ rv = uno::Reference< rendering::XCachedPrimitive >(NULL);
+
+#ifdef CAIRO_CANVAS_PERF_TRACE
+ mxDevice->stopPerfTrace( &aTimer, "drawBitmap" );
+#endif
+
+ return rv;
}
uno::Reference< rendering::XGraphicDevice > CanvasHelper::getDevice()
diff --git a/canvas/source/cairo/cairo_spritecanvas.hxx b/canvas/source/cairo/cairo_spritecanvas.hxx
index bdbb42c6da12..210908552d73 100644
--- a/canvas/source/cairo/cairo_spritecanvas.hxx
+++ b/canvas/source/cairo/cairo_spritecanvas.hxx
@@ -42,7 +42,6 @@
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
#include <com/sun/star/rendering/XGraphicDevice.hpp>
#include <com/sun/star/rendering/XBufferController.hpp>
-#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
#include <cppuhelper/compbase9.hxx>
#include <comphelper/uno3.hxx>
@@ -66,7 +65,7 @@ namespace cairocanvas
typedef ::cppu::WeakComponentImplHelper9< ::com::sun::star::rendering::XSpriteCanvas,
::com::sun::star::rendering::XIntegerBitmap,
::com::sun::star::rendering::XGraphicDevice,
- ::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
+ ::com::sun::star::lang::XMultiServiceFactory,
::com::sun::star::rendering::XBufferController,
::com::sun::star::awt::XWindowListener,
::com::sun::star::util::XUpdatable,
diff --git a/canvas/source/null/null_spritecanvas.hxx b/canvas/source/null/null_spritecanvas.hxx
index 341f2a5a95a6..278bcd9a8e7c 100644
--- a/canvas/source/null/null_spritecanvas.hxx
+++ b/canvas/source/null/null_spritecanvas.hxx
@@ -41,7 +41,7 @@
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
#include <com/sun/star/rendering/XGraphicDevice.hpp>
#include <com/sun/star/rendering/XBufferController.hpp>
-#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <cppuhelper/compbase8.hxx>
#include <comphelper/uno3.hxx>
@@ -60,7 +60,7 @@ namespace nullcanvas
typedef ::cppu::WeakComponentImplHelper8< ::com::sun::star::rendering::XSpriteCanvas,
::com::sun::star::rendering::XIntegerBitmap,
::com::sun::star::rendering::XGraphicDevice,
- ::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
+ ::com::sun::star::lang::XMultiServiceFactory,
::com::sun::star::rendering::XBufferController,
::com::sun::star::awt::XWindowListener,
::com::sun::star::beans::XPropertySet,
diff --git a/canvas/source/tools/parametricpolypolygon.cxx b/canvas/source/tools/parametricpolypolygon.cxx
index bfce116393d0..222b668a5fb0 100644
--- a/canvas/source/tools/parametricpolypolygon.cxx
+++ b/canvas/source/tools/parametricpolypolygon.cxx
@@ -53,68 +53,126 @@ using namespace ::com::sun::star;
namespace canvas
{
- ParametricPolyPolygon* ParametricPolyPolygon::createLinearHorizontalGradient(
- const uno::Reference< rendering::XGraphicDevice >& rDevice,
- const uno::Sequence< uno::Sequence< double > >& colors,
- const uno::Sequence< double >& stops )
+ uno::Sequence<rtl::OUString> ParametricPolyPolygon::getAvailableServiceNames()
{
- // TODO(P2): hold gradient brush statically, and only setup
- // the colors
- return new ParametricPolyPolygon( rDevice, GRADIENT_LINEAR, colors, stops );
+ uno::Sequence<rtl::OUString> aRet(3);
+ aRet[0] = rtl::OUString::createFromAscii("LinearGradient");
+ aRet[1] = rtl::OUString::createFromAscii("EllipticalGradient");
+ aRet[2] = rtl::OUString::createFromAscii("RectangularGradient");
+
+ return aRet;
+ }
+
+ ParametricPolyPolygon* ParametricPolyPolygon::create(
+ const uno::Reference< rendering::XGraphicDevice >& rDevice,
+ const ::rtl::OUString& rServiceName,
+ const uno::Sequence< uno::Any >& rArgs )
+ {
+ uno::Sequence< uno::Sequence< double > > colorSequence(2);
+ uno::Sequence< double > colorStops(2);
+ double fAspectRatio=1.0;
+
+ // defaults
+ uno::Sequence< rendering::RGBColor > rgbColors(1);
+ rgbColors[0] = rendering::RGBColor(0,0,0);
+ colorSequence[0] = rDevice->getDeviceColorSpace()->convertFromRGB(rgbColors);
+ rgbColors[0] = rendering::RGBColor(1,1,1);
+ colorSequence[1] = rDevice->getDeviceColorSpace()->convertFromRGB(rgbColors);
+ colorStops[0] = 0;
+ colorStops[1] = 1;
+
+ // extract args
+ for( sal_Int32 i=0; i<rArgs.getLength(); ++i )
+ {
+ beans::PropertyValue aProp;
+ if( (rArgs[i] >>= aProp) )
+ {
+ if( aProp.Name.equalsAscii("Colors") )
+ {
+ aProp.Value >>= colorSequence;
+ }
+ else if( aProp.Name.equalsAscii("Stops") )
+ {
+ aProp.Value >>= colorStops;
+ }
+ else if( aProp.Name.equalsAscii("AspectRatio") )
+ {
+ aProp.Value >>= fAspectRatio;
+ }
+ }
+ }
+
+ if( rServiceName.equalsAscii("LinearGradient") )
+ {
+ return createLinearHorizontalGradient(rDevice, colorSequence, colorStops);
+ }
+ else if( rServiceName.equalsAscii("EllipticalGradient") )
+ {
+ return createEllipticalGradient(rDevice, colorSequence, colorStops, fAspectRatio);
+ }
+ else if( rServiceName.equalsAscii("RectangularGradient") )
+ {
+ return createRectangularGradient(rDevice, colorSequence, colorStops, fAspectRatio);
+ }
+ else if( rServiceName.equalsAscii("VerticalLineHatch") )
+ {
+ // TODO: NYI
+ }
+ else if( rServiceName.equalsAscii("OrthogonalLinesHatch") )
+ {
+ // TODO: NYI
+ }
+ else if( rServiceName.equalsAscii("ThreeCrossingLinesHatch") )
+ {
+ // TODO: NYI
+ }
+ else if( rServiceName.equalsAscii("FourCrossingLinesHatch") )
+ {
+ // TODO: NYI
+ }
+
+ return NULL;
}
- ParametricPolyPolygon* ParametricPolyPolygon::createAxialHorizontalGradient(
+ ParametricPolyPolygon* ParametricPolyPolygon::createLinearHorizontalGradient(
const uno::Reference< rendering::XGraphicDevice >& rDevice,
const uno::Sequence< uno::Sequence< double > >& colors,
const uno::Sequence< double >& stops )
{
// TODO(P2): hold gradient brush statically, and only setup
// the colors
- return new ParametricPolyPolygon( rDevice, GRADIENT_AXIAL, colors, stops );
- }
-
- namespace
- {
- double calcAspectRatio( const geometry::RealRectangle2D& rBoundRect )
- {
- const double nWidth( rBoundRect.X2 - rBoundRect.X1 );
- const double nHeight( rBoundRect.Y2 - rBoundRect.Y1 );
-
- return ::basegfx::fTools::equalZero( nHeight ) ? 1.0 : fabs( nWidth / nHeight );
- }
+ return new ParametricPolyPolygon( rDevice, GRADIENT_LINEAR, colors, stops );
}
ParametricPolyPolygon* ParametricPolyPolygon::createEllipticalGradient(
const uno::Reference< rendering::XGraphicDevice >& rDevice,
const uno::Sequence< uno::Sequence< double > >& colors,
const uno::Sequence< double >& stops,
- const geometry::RealRectangle2D& boundRect )
+ double fAspectRatio )
{
// TODO(P2): hold gradient polygon statically, and only setup
// the colors
return new ParametricPolyPolygon(
rDevice,
::basegfx::tools::createPolygonFromCircle(
- ::basegfx::B2DPoint( 0.5, 0.5), 0.5 ),
+ ::basegfx::B2DPoint(0,0), 1 ),
GRADIENT_ELLIPTICAL,
- colors, stops,
- calcAspectRatio( boundRect ) );
+ colors, stops, fAspectRatio );
}
ParametricPolyPolygon* ParametricPolyPolygon::createRectangularGradient( const uno::Reference< rendering::XGraphicDevice >& rDevice,
const uno::Sequence< uno::Sequence< double > >& colors,
const uno::Sequence< double >& stops,
- const geometry::RealRectangle2D& boundRect )
+ double fAspectRatio )
{
// TODO(P2): hold gradient polygon statically, and only setup
// the colors
return new ParametricPolyPolygon(
rDevice,
::basegfx::tools::createPolygonFromRect(
- ::basegfx::B2DRectangle( 0.0, 0.0, 1.0, 1.0 ) ),
+ ::basegfx::B2DRectangle( -1, -1, 1, 1 ) ),
GRADIENT_RECTANGULAR,
- colors, stops,
- calcAspectRatio( boundRect ) );
+ colors, stops, fAspectRatio );
}
void SAL_CALL ParametricPolyPolygon::disposing()
diff --git a/canvas/source/vcl/canvas.hxx b/canvas/source/vcl/canvas.hxx
index 2279f817a406..c4e1a2853532 100644
--- a/canvas/source/vcl/canvas.hxx
+++ b/canvas/source/vcl/canvas.hxx
@@ -41,7 +41,6 @@
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
#include <com/sun/star/rendering/XGraphicDevice.hpp>
#include <com/sun/star/rendering/XBufferController.hpp>
-#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
#include <cppuhelper/compbase7.hxx>
#include <comphelper/uno3.hxx>
@@ -63,7 +62,7 @@ namespace vclcanvas
typedef ::cppu::WeakComponentImplHelper7< ::com::sun::star::rendering::XBitmapCanvas,
::com::sun::star::rendering::XIntegerBitmap,
::com::sun::star::rendering::XGraphicDevice,
- ::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
+ ::com::sun::star::lang::XMultiServiceFactory,
::com::sun::star::util::XUpdatable,
::com::sun::star::beans::XPropertySet,
::com::sun::star::lang::XServiceName > GraphicDeviceBase_Base;
diff --git a/canvas/source/vcl/canvashelper_texturefill.cxx b/canvas/source/vcl/canvashelper_texturefill.cxx
index 571a8c4fc5a3..5219c6349186 100644
--- a/canvas/source/vcl/canvashelper_texturefill.cxx
+++ b/canvas/source/vcl/canvashelper_texturefill.cxx
@@ -57,6 +57,8 @@
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dlinegeometry.hxx>
#include <basegfx/tools/tools.hxx>
+#include <basegfx/tools/lerp.hxx>
+#include <basegfx/tools/keystoplerp.hxx>
#include <basegfx/tools/canvastools.hxx>
#include <basegfx/numeric/ftools.hxx>
@@ -65,6 +67,9 @@
#include <canvas/canvastools.hxx>
#include <canvas/parametricpolypolygon.hxx>
+#include <boost/bind.hpp>
+#include <boost/tuple/tuple.hpp>
+
#include "spritecanvas.hxx"
#include "canvashelper.hxx"
#include "impltools.hxx"
@@ -118,17 +123,13 @@ namespace vclcanvas
Since most of the code for linear and axial gradients are
the same, we've a unified method here
*/
- void fillGeneralLinearGradient( OutputDevice& rOutDev,
- const ::basegfx::B2DHomMatrix& rTextureTransform,
- const ::Rectangle& rBounds,
- int nStepCount,
- const ::Color& rColor1,
- const ::Color& rColor2,
- bool bFillNonOverlapping,
- bool bAxialGradient )
+ void fillLinearGradient( OutputDevice& rOutDev,
+ const ::basegfx::B2DHomMatrix& rTextureTransform,
+ const ::Rectangle& rBounds,
+ unsigned int nStepCount,
+ const ::canvas::ParametricPolyPolygon::Values& rValues,
+ const std::vector< ::Color >& rColors )
{
- (void)bFillNonOverlapping;
-
// determine general position of gradient in relation to
// the bound rect
// =====================================================
@@ -207,36 +208,26 @@ namespace vclcanvas
// iteratively render all other strips
// -----------------------------------
- // ensure that nStepCount is odd, to have a well-defined
- // middle index for axial gradients.
- if( bAxialGradient && !(nStepCount % 2) )
+ // ensure that nStepCount matches color stop parity, to
+ // have a well-defined middle color e.g. for axial
+ // gradients.
+ if( (rColors.size() % 2) != (nStepCount % 2) )
++nStepCount;
- const int nStepCountHalved( nStepCount / 2 );
+ basegfx::tools::KeyStopLerp aLerper(rValues.maStops);
// only iterate nStepCount-1 steps, as the last strip is
// explicitely painted below
- for( int i=0; i<nStepCount-1; ++i )
+ for( unsigned int i=0; i<nStepCount-1; ++i )
{
- // lerp color
- if( bAxialGradient )
- {
- // axial gradient has a triangle-like interpolation function
- const int iPrime( i<=nStepCountHalved ? i : nStepCount-i-1);
+ std::ptrdiff_t nIndex;
+ double fAlpha;
+ boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(double(i)/nStepCount);
- rOutDev.SetFillColor(
- Color( (UINT8)(((nStepCountHalved - iPrime)*rColor1.GetRed() + iPrime*rColor2.GetRed())/nStepCountHalved),
- (UINT8)(((nStepCountHalved - iPrime)*rColor1.GetGreen() + iPrime*rColor2.GetGreen())/nStepCountHalved),
- (UINT8)(((nStepCountHalved - iPrime)*rColor1.GetBlue() + iPrime*rColor2.GetBlue())/nStepCountHalved) ) );
- }
- else
- {
- // linear gradient has a plain lerp between start and end color
- rOutDev.SetFillColor(
- Color( (UINT8)(((nStepCount - i)*rColor1.GetRed() + i*rColor2.GetRed())/nStepCount),
- (UINT8)(((nStepCount - i)*rColor1.GetGreen() + i*rColor2.GetGreen())/nStepCount),
- (UINT8)(((nStepCount - i)*rColor1.GetBlue() + i*rColor2.GetBlue())/nStepCount) ) );
- }
+ rOutDev.SetFillColor(
+ Color( (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha)) ));
// copy right egde of polygon to left edge (and also
// copy the closing point)
@@ -283,59 +274,18 @@ namespace vclcanvas
aTempPoly[3] = ::Point( ::basegfx::fround( rPoint4.getX() ),
::basegfx::fround( rPoint4.getY() ) );
- if( bAxialGradient )
- rOutDev.SetFillColor( rColor1 );
- else
- rOutDev.SetFillColor( rColor2 );
+ rOutDev.SetFillColor( rColors.back() );
rOutDev.DrawPolygon( aTempPoly );
}
-
- inline void fillLinearGradient( OutputDevice& rOutDev,
- const ::Color& rColor1,
- const ::Color& rColor2,
- const ::basegfx::B2DHomMatrix& rTextureTransform,
- const ::Rectangle& rBounds,
- int nStepCount,
- bool bFillNonOverlapping )
- {
- fillGeneralLinearGradient( rOutDev,
- rTextureTransform,
- rBounds,
- nStepCount,
- rColor1,
- rColor2,
- bFillNonOverlapping,
- false );
- }
-
- inline void fillAxialGradient( OutputDevice& rOutDev,
- const ::Color& rColor1,
- const ::Color& rColor2,
- const ::basegfx::B2DHomMatrix& rTextureTransform,
- const ::Rectangle& rBounds,
- int nStepCount,
- bool bFillNonOverlapping )
- {
- fillGeneralLinearGradient( rOutDev,
- rTextureTransform,
- rBounds,
- nStepCount,
- rColor1,
- rColor2,
- bFillNonOverlapping,
- true );
- }
-
void fillPolygonalGradient( OutputDevice& rOutDev,
- const ::canvas::ParametricPolyPolygon::Values& rValues,
- const ::Color& rColor1,
- const ::Color& rColor2,
const ::basegfx::B2DHomMatrix& rTextureTransform,
const ::Rectangle& rBounds,
- int nStepCount,
- bool bFillNonOverlapping )
+ unsigned int nStepCount,
+ bool bFillNonOverlapping,
+ const ::canvas::ParametricPolyPolygon::Values& rValues,
+ const std::vector< ::Color >& rColors )
{
const ::basegfx::B2DPolygon& rGradientPoly( rValues.maGradientPoly );
@@ -369,9 +319,6 @@ namespace vclcanvas
// apply scaling (possibly anisotrophic) to inner polygon
// ------------------------------------------------------
- // move center of scaling to origin
- aInnerPolygonTransformMatrix.translate( -0.5, -0.5 );
-
// scale inner polygon according to aspect ratio: for
// wider-than-tall bounds (nAspectRatio > 1.0), the inner
// polygon, representing the gradient focus, must have
@@ -396,9 +343,6 @@ namespace vclcanvas
aInnerPolygonTransformMatrix.scale( 0.0, 0.0 );
}
- // move origin back to former center of polygon
- aInnerPolygonTransformMatrix.translate( 0.5, 0.5 );
-
// and finally, add texture transform to it.
aInnerPolygonTransformMatrix *= rTextureTransform;
@@ -406,8 +350,8 @@ namespace vclcanvas
aInnerPoly.transform( aInnerPolygonTransformMatrix );
- const sal_Int32 nNumPoints( aOuterPoly.count() );
- ::Polygon aTempPoly( static_cast<USHORT>(nNumPoints+1) );
+ const sal_uInt32 nNumPoints( aOuterPoly.count() );
+ ::Polygon aTempPoly( static_cast<USHORT>(nNumPoints+1) );
// increase number of steps by one: polygonal gradients have
// the outermost polygon rendered in rColor2, and the
@@ -425,37 +369,42 @@ namespace vclcanvas
// color).
++nStepCount;
+ basegfx::tools::KeyStopLerp aLerper(rValues.maStops);
+
if( !bFillNonOverlapping )
{
// fill background
- rOutDev.SetFillColor( rColor1 );
+ rOutDev.SetFillColor( rColors.front() );
rOutDev.DrawRect( rBounds );
// render polygon
// ==============
- for( int i=1,p; i<nStepCount; ++i )
+ for( unsigned int i=1,p; i<nStepCount; ++i )
{
+ const double fT( i/double(nStepCount) );
+
+ std::ptrdiff_t nIndex;
+ double fAlpha;
+ boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(fT);
+
// lerp color
rOutDev.SetFillColor(
- Color( (UINT8)(((nStepCount - i)*rColor1.GetRed() + i*rColor2.GetRed())/nStepCount),
- (UINT8)(((nStepCount - i)*rColor1.GetGreen() + i*rColor2.GetGreen())/nStepCount),
- (UINT8)(((nStepCount - i)*rColor1.GetBlue() + i*rColor2.GetBlue())/nStepCount) ) );
+ Color( (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha)) ));
// scale and render polygon, by interpolating between
// outer and inner polygon.
- // calc interpolation parameter in [0,1] range
- const double nT( (nStepCount-i)/double(nStepCount) );
-
for( p=0; p<nNumPoints; ++p )
{
const ::basegfx::B2DPoint& rOuterPoint( aOuterPoly.getB2DPoint(p) );
const ::basegfx::B2DPoint& rInnerPoint( aInnerPoly.getB2DPoint(p) );
aTempPoly[(USHORT)p] = ::Point(
- basegfx::fround( (1.0-nT)*rInnerPoint.getX() + nT*rOuterPoint.getX() ),
- basegfx::fround( (1.0-nT)*rInnerPoint.getY() + nT*rOuterPoint.getY() ) );
+ basegfx::fround( fT*rInnerPoint.getX() + (1-fT)*rOuterPoint.getX() ),
+ basegfx::fround( fT*rInnerPoint.getY() + (1-fT)*rOuterPoint.getY() ) );
}
// close polygon explicitely
@@ -489,13 +438,19 @@ namespace vclcanvas
aTempPolyPoly.Insert( aTempPoly );
aTempPolyPoly.Insert( aTempPoly2 );
- for( int i=0,p; i<nStepCount; ++i )
+ for( unsigned int i=0,p; i<nStepCount; ++i )
{
+ const double fT( (i+1)/double(nStepCount) );
+
+ std::ptrdiff_t nIndex;
+ double fAlpha;
+ boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(fT);
+
// lerp color
rOutDev.SetFillColor(
- Color( (UINT8)(((nStepCount - i)*rColor1.GetRed() + i*rColor2.GetRed())/nStepCount),
- (UINT8)(((nStepCount - i)*rColor1.GetGreen() + i*rColor2.GetGreen())/nStepCount),
- (UINT8)(((nStepCount - i)*rColor1.GetBlue() + i*rColor2.GetBlue())/nStepCount) ) );
+ Color( (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha)),
+ (UINT8)(basegfx::tools::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha)) ));
#if defined(VERBOSE) && OSL_DEBUG_LEVEL > 0
if( i && !(i % 10) )
@@ -506,17 +461,14 @@ namespace vclcanvas
// calculate the inner polygon, which is actually the
// start of the _next_ color strip. Thus, i+1
- // calc interpolation parameter in [0,1] range
- const double nT( (nStepCount-i-1)/double(nStepCount) );
-
for( p=0; p<nNumPoints; ++p )
{
const ::basegfx::B2DPoint& rOuterPoint( aOuterPoly.getB2DPoint(p) );
const ::basegfx::B2DPoint& rInnerPoint( aInnerPoly.getB2DPoint(p) );
aTempPoly[(USHORT)p] = ::Point(
- basegfx::fround( (1.0-nT)*rInnerPoint.getX() + nT*rOuterPoint.getX() ),
- basegfx::fround( (1.0-nT)*rInnerPoint.getY() + nT*rOuterPoint.getY() ) );
+ basegfx::fround( fT*rInnerPoint.getX() + (1-fT)*rOuterPoint.getX() ),
+ basegfx::fround( fT*rInnerPoint.getY() + (1-fT)*rOuterPoint.getY() ) );
}
// close polygon explicitely
@@ -549,46 +501,33 @@ namespace vclcanvas
void doGradientFill( OutputDevice& rOutDev,
const ::canvas::ParametricPolyPolygon::Values& rValues,
- const ::Color& rColor1,
- const ::Color& rColor2,
+ const std::vector< ::Color >& rColors,
const ::basegfx::B2DHomMatrix& rTextureTransform,
const ::Rectangle& rBounds,
- int nStepCount,
+ unsigned int nStepCount,
bool bFillNonOverlapping )
{
switch( rValues.meType )
{
case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR:
fillLinearGradient( rOutDev,
- rColor1,
- rColor2,
rTextureTransform,
rBounds,
nStepCount,
- bFillNonOverlapping );
- break;
-
- case ::canvas::ParametricPolyPolygon::GRADIENT_AXIAL:
- fillAxialGradient( rOutDev,
- rColor1,
- rColor2,
- rTextureTransform,
- rBounds,
- nStepCount,
- bFillNonOverlapping );
+ rValues,
+ rColors );
break;
case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL:
// FALLTHROUGH intended
case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR:
fillPolygonalGradient( rOutDev,
- rValues,
- rColor1,
- rColor2,
rTextureTransform,
rBounds,
nStepCount,
- bFillNonOverlapping );
+ bFillNonOverlapping,
+ rValues,
+ rColors );
break;
default:
@@ -597,11 +536,19 @@ namespace vclcanvas
}
}
+ int numColorSteps( const ::Color& rColor1, const ::Color& rColor2 )
+ {
+ return ::std::max(
+ labs( rColor1.GetRed() - rColor2.GetRed() ),
+ ::std::max(
+ labs( rColor1.GetGreen() - rColor2.GetGreen() ),
+ labs( rColor1.GetBlue() - rColor2.GetBlue() ) ) );
+ }
+
bool gradientFill( OutputDevice& rOutDev,
OutputDevice* p2ndOutDev,
const ::canvas::ParametricPolyPolygon::Values& rValues,
- const ::Color& rColor1,
- const ::Color& rColor2,
+ const std::vector< ::Color >& rColors,
const PolyPolygon& rPoly,
const rendering::ViewState& viewState,
const rendering::RenderState& renderState,
@@ -646,12 +593,9 @@ namespace vclcanvas
// calc step size
// --------------
- const int nColorSteps(
- ::std::max(
- labs( rColor1.GetRed() - rColor2.GetRed() ),
- ::std::max(
- labs( rColor1.GetGreen() - rColor2.GetGreen() ),
- labs( rColor1.GetBlue() - rColor2.GetBlue() ) ) ) );
+ int nColorSteps = 0;
+ for( size_t i=0; i<rColors.size()-1; ++i )
+ nColorSteps += numColorSteps(rColors[i],rColors[i+1]);
// longest line in gradient bound rect
const int nGradientSize(
@@ -690,8 +634,7 @@ namespace vclcanvas
rOutDev.IntersectClipRegion( aPolygonDeviceRectOrig );
doGradientFill( rOutDev,
rValues,
- rColor1,
- rColor2,
+ rColors,
aTextureTransform,
aPolygonDeviceRectOrig,
nStepCount,
@@ -704,8 +647,7 @@ namespace vclcanvas
p2ndOutDev->IntersectClipRegion( aPolygonDeviceRectOrig );
doGradientFill( *p2ndOutDev,
rValues,
- rColor1,
- rColor2,
+ rColors,
aTextureTransform,
aPolygonDeviceRectOrig,
nStepCount,
@@ -723,8 +665,7 @@ namespace vclcanvas
doGradientFill( rOutDev,
rValues,
- rColor1,
- rColor2,
+ rColors,
aTextureTransform,
aPolygonDeviceRectOrig,
nStepCount,
@@ -737,8 +678,7 @@ namespace vclcanvas
p2ndOutDev->SetClipRegion( aPolyClipRegion );
doGradientFill( *p2ndOutDev,
rValues,
- rColor1,
- rColor2,
+ rColors,
aTextureTransform,
aPolygonDeviceRectOrig,
nStepCount,
@@ -753,8 +693,7 @@ namespace vclcanvas
rOutDev.SetRasterOp( ROP_XOR );
doGradientFill( rOutDev,
rValues,
- rColor1,
- rColor2,
+ rColors,
aTextureTransform,
aPolygonDeviceRectOrig,
nStepCount,
@@ -765,8 +704,7 @@ namespace vclcanvas
rOutDev.SetRasterOp( ROP_XOR );
doGradientFill( rOutDev,
rValues,
- rColor1,
- rColor2,
+ rColors,
aTextureTransform,
aPolygonDeviceRectOrig,
nStepCount,
@@ -779,8 +717,7 @@ namespace vclcanvas
p2ndOutDev->SetRasterOp( ROP_XOR );
doGradientFill( *p2ndOutDev,
rValues,
- rColor1,
- rColor2,
+ rColors,
aTextureTransform,
aPolygonDeviceRectOrig,
nStepCount,
@@ -791,8 +728,7 @@ namespace vclcanvas
p2ndOutDev->SetRasterOp( ROP_XOR );
doGradientFill( *p2ndOutDev,
rValues,
- rColor1,
- rColor2,
+ rColors,
aTextureTransform,
aPolygonDeviceRectOrig,
nStepCount,
@@ -855,33 +791,41 @@ namespace vclcanvas
::canvas::ParametricPolyPolygon* pGradient =
dynamic_cast< ::canvas::ParametricPolyPolygon* >( textures[0].Gradient.get() );
- if( pGradient )
+ if( pGradient && pGradient->getValues().maColors.getLength() )
{
// copy state from Gradient polypoly locally
// (given object might change!)
const ::canvas::ParametricPolyPolygon::Values& rValues(
pGradient->getValues() );
- // TODO: use all the colors and place them on given positions/stops
- const ::Color aColor1(
- ::vcl::unotools::stdColorSpaceSequenceToColor(
- rValues.maColors [0] ) );
- const ::Color aColor2(
- ::vcl::unotools::stdColorSpaceSequenceToColor(
- rValues.maColors [rValues.maColors.getLength () - 1] ) );
-
- // TODO(E1): Return value
- // TODO(F1): FillRule
- gradientFill( mpOutDev->getOutDev(),
- mp2ndOutDev.get() ? &mp2ndOutDev->getOutDev() : (OutputDevice*)NULL,
- rValues,
- aColor1,
- aColor2,
- aPolyPoly,
- viewState,
- renderState,
- textures[0],
- nTransparency );
+ if( rValues.maColors.getLength() < 2 )
+ {
+ rendering::RenderState aTempState=renderState;
+ aTempState.DeviceColor = rValues.maColors[0];
+ fillPolyPolygon(pCanvas, xPolyPolygon, viewState, aTempState);
+ }
+ else
+ {
+ std::vector< ::Color > aColors(rValues.maColors.getLength());
+ std::transform(&rValues.maColors[0],
+ &rValues.maColors[0]+rValues.maColors.getLength(),
+ aColors.begin(),
+ boost::bind(
+ &vcl::unotools::stdColorSpaceSequenceToColor,
+ _1));
+
+ // TODO(E1): Return value
+ // TODO(F1): FillRule
+ gradientFill( mpOutDev->getOutDev(),
+ mp2ndOutDev.get() ? &mp2ndOutDev->getOutDev() : (OutputDevice*)NULL,
+ rValues,
+ aColors,
+ aPolyPoly,
+ viewState,
+ renderState,
+ textures[0],
+ nTransparency );
+ }
}
else
{
diff --git a/canvas/source/vcl/spritecanvas.hxx b/canvas/source/vcl/spritecanvas.hxx
index 545eeeed4577..66762bcb65b7 100644
--- a/canvas/source/vcl/spritecanvas.hxx
+++ b/canvas/source/vcl/spritecanvas.hxx
@@ -42,7 +42,6 @@
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
#include <com/sun/star/rendering/XGraphicDevice.hpp>
#include <com/sun/star/rendering/XBufferController.hpp>
-#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp>
#include <cppuhelper/compbase9.hxx>
#include <comphelper/uno3.hxx>
@@ -65,7 +64,7 @@ namespace vclcanvas
typedef ::cppu::WeakComponentImplHelper9< ::com::sun::star::rendering::XSpriteCanvas,
::com::sun::star::rendering::XIntegerBitmap,
::com::sun::star::rendering::XGraphicDevice,
- ::com::sun::star::rendering::XParametricPolyPolygon2DFactory,
+ ::com::sun::star::lang::XMultiServiceFactory,
::com::sun::star::rendering::XBufferController,
::com::sun::star::awt::XWindowListener,
::com::sun::star::util::XUpdatable,