diff options
Diffstat (limited to 'canvas/source')
-rw-r--r-- | canvas/source/cairo/cairo_canvas.hxx | 3 | ||||
-rw-r--r-- | canvas/source/cairo/cairo_canvashelper.cxx | 281 | ||||
-rw-r--r-- | canvas/source/cairo/cairo_spritecanvas.hxx | 3 | ||||
-rwxr-xr-x | canvas/source/directx/dx_canvashelper_texturefill.cxx | 4 | ||||
-rw-r--r-- | canvas/source/null/null_spritecanvas.hxx | 4 | ||||
-rw-r--r-- | canvas/source/tools/parametricpolypolygon.cxx | 114 | ||||
-rw-r--r-- | canvas/source/tools/verifyinput.cxx | 4 | ||||
-rw-r--r-- | canvas/source/vcl/canvas.hxx | 3 | ||||
-rw-r--r-- | canvas/source/vcl/canvashelper_texturefill.cxx | 399 | ||||
-rw-r--r-- | canvas/source/vcl/spritecanvas.hxx | 3 |
10 files changed, 421 insertions, 397 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 5469010f2745..f0ba4067f899 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: @@ -754,7 +779,20 @@ namespace cairocanvas if( aTexture.RepeatModeX == rendering::TexturingMode::REPEAT && aTexture.RepeatModeY == rendering::TexturingMode::REPEAT ) + { cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_REPEAT ); + } + else if ( aTexture.RepeatModeX == rendering::TexturingMode::NONE && + aTexture.RepeatModeY == rendering::TexturingMode::NONE ) + { + cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_NONE ); + } + else if ( aTexture.RepeatModeX == rendering::TexturingMode::CLAMP && + aTexture.RepeatModeY == rendering::TexturingMode::CLAMP ) + { + cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_PAD ); + } + aScaledTextureMatrix.x0 = basegfx::fround( aScaledTextureMatrix.x0 ); aScaledTextureMatrix.y0 = basegfx::fround( aScaledTextureMatrix.y0 ); cairo_pattern_set_matrix( pPattern, &aScaledTextureMatrix ); @@ -790,19 +828,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_pattern_destroy( pPattern ); + cairo_save( pCairo ); + + cairo_transform( pCairo, &aTextureMatrix ); + cairo_set_source( pCairo, pPattern ); + cairo_fill( pCairo ); + cairo_restore( pCairo ); + + cairo_pattern_destroy( pPattern ); + } } } } @@ -935,7 +1024,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 +1037,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 ); @@ -1211,12 +1300,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() ); @@ -1238,38 +1327,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 ) { @@ -1310,7 +1399,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"); @@ -1349,15 +1442,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/directx/dx_canvashelper_texturefill.cxx b/canvas/source/directx/dx_canvashelper_texturefill.cxx index 73a2d49bfb62..d0ebaf2f2fc9 100755 --- a/canvas/source/directx/dx_canvashelper_texturefill.cxx +++ b/canvas/source/directx/dx_canvashelper_texturefill.cxx @@ -609,8 +609,8 @@ namespace dxcanvas rTexture.RepeatModeY, "CanvasHelper::fillBitmap(): GDI+ cannot handle differing X/Y repeat mode." ); - const bool bClamp( rTexture.RepeatModeX == rendering::TexturingMode::CLAMP && - rTexture.RepeatModeY == rendering::TexturingMode::CLAMP ); + const bool bClamp( rTexture.RepeatModeX == rendering::TexturingMode::NONE && + rTexture.RepeatModeY == rendering::TexturingMode::NONE ); const geometry::IntegerSize2D aBmpSize( xBitmap->getSize() ); ENSURE_ARG_OR_THROW( aBmpSize.Width != 0 && 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/tools/verifyinput.cxx b/canvas/source/tools/verifyinput.cxx index a270f6158979..37a0ef687df1 100644 --- a/canvas/source/tools/verifyinput.cxx +++ b/canvas/source/tools/verifyinput.cxx @@ -429,7 +429,7 @@ namespace canvas #endif } - if( texture.RepeatModeX < rendering::TexturingMode::CLAMP || + if( texture.RepeatModeX < rendering::TexturingMode::NONE || texture.RepeatModeX > rendering::TexturingMode::REPEAT ) { #if OSL_DEBUG_LEVEL > 0 @@ -445,7 +445,7 @@ namespace canvas #endif } - if( texture.RepeatModeY < rendering::TexturingMode::CLAMP || + if( texture.RepeatModeY < rendering::TexturingMode::NONE || texture.RepeatModeY > rendering::TexturingMode::REPEAT ) { #if OSL_DEBUG_LEVEL > 0 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..9f8118e8a8f8 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 { @@ -892,10 +836,6 @@ namespace vclcanvas } else if( textures[0].Bitmap.is() ) { -// OSL_ENSURE( textures[0].RepeatModeX == rendering::TexturingMode::REPEAT && -// textures[0].RepeatModeY == rendering::TexturingMode::REPEAT, -// "CanvasHelper::fillTexturedPolyPolygon(): VCL canvas cannot currently clamp textures." ); - const geometry::IntegerSize2D aBmpSize( textures[0].Bitmap->getSize() ); ENSURE_ARG_OR_THROW( aBmpSize.Width != 0 && @@ -970,23 +910,6 @@ namespace vclcanvas aLocalState ); } } - else if ( textures[0].RepeatModeX == rendering::TexturingMode::CLAMP &&
- textures[0].RepeatModeY == rendering::TexturingMode::CLAMP )
- {
- rendering::RenderState aLocalState( renderState );
- ::canvas::tools::appendToRenderState(aLocalState,
- aTextureTransform);
- ::basegfx::B2DHomMatrix aScaleCorrection;
- aScaleCorrection.scale( 1.0/aBmpSize.Width,
- 1.0/aBmpSize.Height );
- ::canvas::tools::appendToRenderState(aLocalState,
- aScaleCorrection);
-
- return drawBitmap( pCanvas,
- textures[0].Bitmap,
- viewState,
- aLocalState );
- } else { // No easy mapping to drawBitmap() - calculate @@ -1120,15 +1043,21 @@ namespace vclcanvas aSingleTextureRect, aPureTotalTransform ); - const ::Point aPt( ::vcl::unotools::pointFromB2DPoint( - aSingleDeviceTextureRect.getMinimum() ) ); + const ::Point aPtRepeat( ::vcl::unotools::pointFromB2DPoint( + aSingleDeviceTextureRect.getMinimum() ) ); const ::Size aSz( ::basegfx::fround( aScale.getX() * aBmpSize.Width ), ::basegfx::fround( aScale.getY() * aBmpSize.Height ) ); const ::Size aIntegerNextTileX( ::vcl::unotools::sizeFromB2DSize(aNextTileX) ); const ::Size aIntegerNextTileY( ::vcl::unotools::sizeFromB2DSize(aNextTileY) ); - const sal_Int32 nTilesX( nX2 - nX1 ); - const sal_Int32 nTilesY( nY2 - nY1 ); + const ::Point aPt( textures[0].RepeatModeX == rendering::TexturingMode::NONE ? + ::basegfx::fround( aOutputPos.getX() ) : aPtRepeat.X(), + textures[0].RepeatModeY == rendering::TexturingMode::NONE ? + ::basegfx::fround( aOutputPos.getY() ) : aPtRepeat.Y() ); + const sal_Int32 nTilesX( textures[0].RepeatModeX == rendering::TexturingMode::NONE ? + 1 : nX2 - nX1 ); + const sal_Int32 nTilesY( textures[0].RepeatModeX == rendering::TexturingMode::NONE ? + 1 : nY2 - nY1 ); OutputDevice& rOutDev( mpOutDev->getOutDev() ); @@ -1209,20 +1138,9 @@ namespace vclcanvas aPolyPoly.Translate( ::Point( -aPolygonDeviceRect.Left(), -aPolygonDeviceRect.Top() ) ); - aVDev.SetRasterOp( ROP_XOR ); - textureFill( aVDev, - *pGrfObj, - aOutPos, - aIntegerNextTileX, - aIntegerNextTileY, - nTilesX, - nTilesY, - aSz, - aGrfAttr ); - aVDev.SetFillColor( COL_BLACK ); - aVDev.SetRasterOp( ROP_0 ); - aVDev.DrawPolyPolygon( aPolyPoly ); - aVDev.SetRasterOp( ROP_XOR ); + const Region aPolyClipRegion( aPolyPoly ); + + aVDev.SetClipRegion( aPolyClipRegion ); textureFill( aVDev, *pGrfObj, aOutPos, @@ -1254,7 +1172,6 @@ namespace vclcanvas aOutputBmpEx ); } else -#if defined(QUARTZ) // TODO: other ports should avoid the XOR-trick too (implementation vs. interface!) { const Region aPolyClipRegion( aPolyPoly ); @@ -1290,66 +1207,6 @@ namespace vclcanvas r2ndOutDev.Pop(); } } -#else // TODO: remove once doing the XOR-trick in the canvas-layer becomes redundant - { - // output via repeated XORing - rOutDev.Push( PUSH_RASTEROP ); - rOutDev.SetRasterOp( ROP_XOR ); - textureFill( rOutDev, - *pGrfObj, - aPt, - aIntegerNextTileX, - aIntegerNextTileY, - nTilesX, - nTilesY, - aSz, - aGrfAttr ); - rOutDev.SetFillColor( COL_BLACK ); - rOutDev.SetRasterOp( ROP_0 ); - rOutDev.DrawPolyPolygon( aPolyPoly ); - rOutDev.SetRasterOp( ROP_XOR ); - textureFill( rOutDev, - *pGrfObj, - aPt, - aIntegerNextTileX, - aIntegerNextTileY, - nTilesX, - nTilesY, - aSz, - aGrfAttr ); - rOutDev.Pop(); - - if( mp2ndOutDev ) - { - OutputDevice& r2ndOutDev( mp2ndOutDev->getOutDev() ); - r2ndOutDev.Push( PUSH_RASTEROP ); - r2ndOutDev.SetRasterOp( ROP_XOR ); - textureFill( r2ndOutDev, - *pGrfObj, - aPt, - aIntegerNextTileX, - aIntegerNextTileY, - nTilesX, - nTilesY, - aSz, - aGrfAttr ); - r2ndOutDev.SetFillColor( COL_BLACK ); - r2ndOutDev.SetRasterOp( ROP_0 ); - r2ndOutDev.DrawPolyPolygon( aPolyPoly ); - r2ndOutDev.SetRasterOp( ROP_XOR ); - textureFill( r2ndOutDev, - *pGrfObj, - aPt, - aIntegerNextTileX, - aIntegerNextTileY, - nTilesX, - nTilesY, - aSz, - aGrfAttr ); - r2ndOutDev.Pop(); - } - } -#endif // complex-clipping vs. XOR-trick } } } 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, |