diff options
Diffstat (limited to 'cppcanvas/source')
-rw-r--r-- | cppcanvas/source/mtfrenderer/implrenderer.cxx | 371 |
1 files changed, 133 insertions, 238 deletions
diff --git a/cppcanvas/source/mtfrenderer/implrenderer.cxx b/cppcanvas/source/mtfrenderer/implrenderer.cxx index e6fb12cb2003..1423cd42ed93 100644 --- a/cppcanvas/source/mtfrenderer/implrenderer.cxx +++ b/cppcanvas/source/mtfrenderer/implrenderer.cxx @@ -41,7 +41,6 @@ #include <cppcanvas/canvas.hxx> #include <com/sun/star/rendering/XGraphicDevice.hpp> #include <com/sun/star/rendering/TexturingMode.hpp> -#include <com/sun/star/rendering/XParametricPolyPolygon2DFactory.hpp> #include <com/sun/star/uno/Sequence.hxx> #include <com/sun/star/geometry/RealPoint2D.hpp> #include <com/sun/star/rendering/ViewState.hpp> @@ -52,6 +51,7 @@ #include <com/sun/star/rendering/PathCapType.hpp> #include <com/sun/star/rendering/PathJoinType.hpp> #include <basegfx/tools/canvastools.hxx> +#include <basegfx/tools/gradienttools.hxx> #include <basegfx/numeric/ftools.hxx> #include <basegfx/polygon/b2dpolypolygontools.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> @@ -591,13 +591,12 @@ namespace cppcanvas // discernible difference should be visible. nSteps > 64 ) { - uno::Reference< rendering::XParametricPolyPolygon2DFactory > xFactory( + uno::Reference< lang::XMultiServiceFactory> xFactory( rParms.mrCanvas->getUNOCanvas()->getDevice()->getParametricPolyPolygonFactory() ); if( xFactory.is() ) { - ::basegfx::B2DHomMatrix aTextureTransformation; - rendering::Texture aTexture; + rendering::Texture aTexture; aTexture.RepeatModeX = rendering::TexturingMode::CLAMP; aTexture.RepeatModeY = rendering::TexturingMode::CLAMP; @@ -632,240 +631,118 @@ namespace cppcanvas uno::Sequence< uno::Sequence < double > > aColors(2); uno::Sequence< double > aStops(2); - aStops[0] = 0.0; - aStops[1] = 1.0; + if( rGradient.GetStyle() == GRADIENT_AXIAL ) + { + aStops.realloc(3); + aColors.realloc(3); - aColors[0] = aStartColor; - aColors[1] = aEndColor; + aStops[0] = 0.0; + aStops[1] = 0.5; + aStops[2] = 1.0; + aColors[0] = aEndColor; + aColors[1] = aStartColor; + aColors[2] = aEndColor; + } + else + { + aStops[0] = 0.0; + aStops[1] = 1.0; - // Setup texture transformation - // ---------------------------- + aColors[0] = aStartColor; + aColors[1] = aEndColor; + } const ::basegfx::B2DRectangle aBounds( ::basegfx::tools::getRange(aDevicePoly) ); + const ::basegfx::B2DVector aOffset( + rGradient.GetOfsX() / 100.0, + rGradient.GetOfsY() / 100.0); + double fRotation( rGradient.GetAngle() * M_PI / 1800.0 ); + const double fBorder( rGradient.GetBorder() / 100.0 ); - // setup rotation angle. VCL rotates - // counter-clockwise, while canvas transformation - // rotates clockwise - double nRotation( -rGradient.GetAngle() * M_PI / 1800.0 ); + basegfx::B2DHomMatrix aRot90; + aRot90.rotate(M_PI_2); + basegfx::ODFGradientInfo aGradInfo; + rtl::OUString aGradientService; switch( rGradient.GetStyle() ) { case GRADIENT_LINEAR: - // FALLTHROUGH intended + basegfx::tools::createLinearODFGradientInfo(aGradInfo, + aBounds, + nSteps, + fBorder, + fRotation); + // map odf to svg gradient orientation - x + // instead of y direction + aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aRot90; + aGradientService = rtl::OUString::createFromAscii("LinearGradient"); + break; + case GRADIENT_AXIAL: { - // standard orientation for VCL linear - // gradient is vertical, thus, rotate 90 - // degrees - nRotation += M_PI/2.0; - - const double nBorder( - ::basegfx::pruneScaleValue( - (1.0 - rGradient.GetBorder() / 100.0) ) ); - - // shrink texture, to account for border - // (only in x direction, linear gradient - // is constant in y direction, anyway) - aTextureTransformation.scale( nBorder, - 1.0 ); - - // linear gradients don't respect offsets - // (they are implicitely assumed to be - // 50%). linear gradients don't have - // border on both sides, only on the - // startColor side, axial gradients have - // border on both sides. As both gradients - // are invariant in y direction: leave y - // offset alone. - double nOffsetX( rGradient.GetBorder() / 200.0 ); - - // determine type of gradient (and necessary - // transformation matrix, should it be emulated by a - // generic gradient) - switch( rGradient.GetStyle() ) - { - case GRADIENT_LINEAR: - nOffsetX = rGradient.GetBorder() / 100.0; - aTexture.Gradient = xFactory->createLinearHorizontalGradient( aColors, - aStops ); - break; - - case GRADIENT_AXIAL: - // vcl considers center color as start color - ::std::swap(aColors[0],aColors[1]); - aTexture.Gradient = xFactory->createAxialHorizontalGradient( aColors, - aStops ); - break; - - default: // other cases can't happen - break; - } - - // apply border offset values - aTextureTransformation.translate( nOffsetX, - 0.0 ); - - // rotate texture according to gradient rotation - aTextureTransformation.translate( -0.5, -0.5 ); - aTextureTransformation.rotate( nRotation ); - - // to let the first strip of a rotated - // gradient start at the _edge_ of the - // bound rect (and not, due to rotation, - // slightly inside), slightly enlarge the - // gradient: - // - // y/2 sin(alpha) + x/2 cos(alpha) - // - // (values to change are not actual - // gradient scales, but original bound - // rect dimensions. Since we still want - // the border setting to apply after that, - // we multiply with that as above for - // nScaleX) - const double nScale( - ::basegfx::pruneScaleValue( - fabs( aBounds.getHeight()*sin(nRotation) ) + - fabs( aBounds.getWidth()*cos(nRotation) ))); - - // scale and translate back origin to center of - // primitive - aTextureTransformation = basegfx::tools::createScaleTranslateB2DHomMatrix( - nScale, nScale, 0.5*aBounds.getWidth(), 0.5*aBounds.getHeight()) - * aTextureTransformation; + basegfx::tools::createLinearODFGradientInfo(aGradInfo, + aBounds, + nSteps, + fBorder, + fRotation); + // map odf to svg gradient orientation - x + // instead of y direction + aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aRot90; + + // map odf axial gradient to 3-stop linear + // gradient - shift left by 0.5 + basegfx::B2DHomMatrix aShift; + aShift.translate(-0.5,0); + aGradInfo.maTextureTransform = aGradInfo.maTextureTransform * aShift; + + aGradientService = rtl::OUString::createFromAscii("LinearGradient"); + break; } - break; case GRADIENT_RADIAL: - // FALLTHROUGH intended - case GRADIENT_ELLIPTICAL: - // FALLTHROUGH intended - case GRADIENT_SQUARE: - // FALLTHROUGH intended - case GRADIENT_RECT: - { - // determine scale factors for the gradient (must - // be scaled up from [0,1]x[0,1] rect to object - // bounds). Will potentially changed in switch - // statement below. - // Respect border value, while doing so, the VCL - // gradient's border will effectively shrink the - // resulting gradient. - double nScaleX( aBounds.getWidth() * (1.0 - rGradient.GetBorder() / 100.0) ); - double nScaleY( aBounds.getHeight()* (1.0 - rGradient.GetBorder() / 100.0) ); - - // determine offset values. Since the border is - // divided half-by-half to both sides of the - // gradient, divide translation offset by an - // additional 2. Also respect offset here, but - // since VCL gradients have their center at [0,0] - // for zero offset, but canvas gradients have - // their top, left edge aligned with the - // primitive, and offset of 50% effectively must - // yield zero shift. Both values will potentially - // be adapted in switch statement below. - double nOffsetX( aBounds.getWidth() * - (2.0 * rGradient.GetOfsX() - 100.0 + rGradient.GetBorder()) / 200.0 ); - double nOffsetY( aBounds.getHeight() * - (2.0 * rGradient.GetOfsY() - 100.0 + rGradient.GetBorder()) / 200.0 ); - - // determine type of gradient (and necessary - // transformation matrix, should it be emulated by a - // generic gradient) - switch( rGradient.GetStyle() ) - { - case GRADIENT_RADIAL: - { - // create isotrophic scaling - if( nScaleX > nScaleY ) - { - nOffsetY -= (nScaleX - nScaleY) * 0.5; - nScaleY = nScaleX; - } - else - { - nOffsetX -= (nScaleY - nScaleX) * 0.5; - nScaleX = nScaleY; - } - - // enlarge gradient to match bound rect diagonal - aTextureTransformation.translate( -0.5, -0.5 ); - const double nScale( hypot(aBounds.getWidth(), aBounds.getHeight()) / nScaleX ); - aTextureTransformation.scale( nScale, nScale ); - aTextureTransformation.translate( 0.5, 0.5 ); - - aTexture.Gradient = xFactory->createEllipticalGradient( aColors, - aStops, - geometry::RealRectangle2D(0.0,0.0, - 1.0,1.0) ); - } - break; - - case GRADIENT_ELLIPTICAL: - { - // enlarge gradient slightly - aTextureTransformation.translate( -0.5, -0.5 ); - const double nSqrt2( sqrt(2.0) ); - aTextureTransformation.scale( nSqrt2,nSqrt2 ); - aTextureTransformation.translate( 0.5, 0.5 ); - - aTexture.Gradient = xFactory->createEllipticalGradient( - aColors, - aStops, - ::basegfx::unotools::rectangle2DFromB2DRectangle( - aBounds )); - } - break; - - case GRADIENT_SQUARE: - // create isotrophic scaling - if( nScaleX > nScaleY ) - { - nOffsetY -= (nScaleX - nScaleY) * 0.5; - nScaleY = nScaleX; - } - else - { - nOffsetX -= (nScaleY - nScaleX) * 0.5; - nScaleX = nScaleY; - } - - aTexture.Gradient = xFactory->createRectangularGradient( aColors, - aStops, - geometry::RealRectangle2D(0.0,0.0, - 1.0,1.0) ); - break; - - case GRADIENT_RECT: - aTexture.Gradient = xFactory->createRectangularGradient( - aColors, - aStops, - ::basegfx::unotools::rectangle2DFromB2DRectangle( - aBounds ) ); - break; - - default: // other cases can't happen - break; - } - - nScaleX = ::basegfx::pruneScaleValue( nScaleX ); - nScaleY = ::basegfx::pruneScaleValue( nScaleY ); + basegfx::tools::createRadialODFGradientInfo(aGradInfo, + aBounds, + aOffset, + nSteps, + fBorder); + aGradientService = rtl::OUString::createFromAscii("EllipticalGradient"); + break; - aTextureTransformation.scale( nScaleX, nScaleY ); + case GRADIENT_ELLIPTICAL: + basegfx::tools::createEllipticalODFGradientInfo(aGradInfo, + aBounds, + aOffset, + nSteps, + fBorder, + fRotation); + aGradientService = rtl::OUString::createFromAscii("EllipticalGradient"); + break; - // rotate texture according to gradient rotation - aTextureTransformation = basegfx::tools::createRotateAroundPoint(0.5*nScaleX, 0.5*nScaleY, nRotation) - * aTextureTransformation; + case GRADIENT_SQUARE: + basegfx::tools::createSquareODFGradientInfo(aGradInfo, + aBounds, + aOffset, + nSteps, + fBorder, + fRotation); + aGradientService = rtl::OUString::createFromAscii("RectangularGradient"); + break; - aTextureTransformation.translate( nOffsetX, nOffsetY ); - } - break; + case GRADIENT_RECT: + basegfx::tools::createRectangularODFGradientInfo(aGradInfo, + aBounds, + aOffset, + nSteps, + fBorder, + fRotation); + aGradientService = rtl::OUString::createFromAscii("RectangularGradient"); + break; default: ENSURE_OR_THROW( false, - "ImplRenderer::createGradientAction(): Unexpected gradient type" ); + "ImplRenderer::createGradientAction(): Unexpected gradient type" ); break; } @@ -876,31 +753,49 @@ namespace cppcanvas // gradient will always display at the origin, and // not within the polygon bound (which might be // miles away from the origin). - aTextureTransformation.translate( aBounds.getMinX(), - aBounds.getMinY() ); - + aGradInfo.maTextureTransform.translate( aBounds.getMinX(), + aBounds.getMinY() ); ::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform, - aTextureTransformation ); + aGradInfo.maTextureTransform ); + + uno::Sequence<uno::Any> args(3); + beans::PropertyValue aProp; + aProp.Name = rtl::OUString::createFromAscii("Colors"); + aProp.Value <<= aColors; + args[0] <<= aProp; + aProp.Name = rtl::OUString::createFromAscii("Stops"); + aProp.Value <<= aStops; + args[1] <<= aProp; + aProp.Name = rtl::OUString::createFromAscii("AspectRatio"); + aProp.Value <<= aGradInfo.mfAspectRatio; + args[2] <<= aProp; + + aTexture.Gradient.set( + xFactory->createInstanceWithArguments(aGradientService, + args), + uno::UNO_QUERY); + if( aTexture.Gradient.is() ) + { + ActionSharedPtr pPolyAction( + internal::PolyPolyActionFactory::createPolyPolyAction( + aDevicePoly, + rParms.mrCanvas, + getState( rParms.mrStates ), + aTexture ) ); - ActionSharedPtr pPolyAction( - internal::PolyPolyActionFactory::createPolyPolyAction( - aDevicePoly, - rParms.mrCanvas, - getState( rParms.mrStates ), - aTexture ) ); + if( pPolyAction ) + { + maActions.push_back( + MtfAction( + pPolyAction, + rParms.mrCurrActionIndex ) ); - if( pPolyAction ) - { - maActions.push_back( - MtfAction( - pPolyAction, - rParms.mrCurrActionIndex ) ); + rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1; + } - rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1; + // done, using native gradients + return; } - - // done, using native gradients - return; } } @@ -1880,8 +1775,8 @@ namespace cppcanvas } else { - aTexture.RepeatModeX = rendering::TexturingMode::CLAMP; - aTexture.RepeatModeY = rendering::TexturingMode::CLAMP; + aTexture.RepeatModeX = rendering::TexturingMode::NONE; + aTexture.RepeatModeY = rendering::TexturingMode::NONE; } ::PolyPolygon aPath; |