diff options
author | thb <thb@openoffice.org> | 2010-01-20 11:55:37 +0100 |
---|---|---|
committer | thb <thb@openoffice.org> | 2010-01-20 11:55:37 +0100 |
commit | 2ced8e8176dad1fb4618a1c8597b35354c85d9ac (patch) | |
tree | 774f7cfec1b7ac54e145fac60581107ab68fcd59 /canvas/source | |
parent | a63c7b938075cc82f7046364f4933c81473e4d9f (diff) |
#i105937# Finalized gradient rework in dxcanvas
Diffstat (limited to 'canvas/source')
-rw-r--r-- | canvas/source/directx/dx_canvas.hxx | 5 | ||||
-rwxr-xr-x | canvas/source/directx/dx_canvashelper_texturefill.cxx | 248 | ||||
-rwxr-xr-x | canvas/source/directx/dx_spritecanvas.hxx | 17 |
3 files changed, 70 insertions, 200 deletions
diff --git a/canvas/source/directx/dx_canvas.hxx b/canvas/source/directx/dx_canvas.hxx index ab2aa398757d..57349b650925 100644 --- a/canvas/source/directx/dx_canvas.hxx +++ b/canvas/source/directx/dx_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 <cppuhelper/compbase6.hxx> @@ -62,7 +61,7 @@ namespace dxcanvas { typedef ::cppu::WeakComponentImplHelper6< ::com::sun::star::rendering::XCanvas, ::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 > GraphicDeviceBase1_Base; @@ -119,7 +118,7 @@ namespace dxcanvas 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 > GraphicDeviceBase2_Base; diff --git a/canvas/source/directx/dx_canvashelper_texturefill.cxx b/canvas/source/directx/dx_canvashelper_texturefill.cxx index d0ebaf2f2fc9..6b57e2e47a56 100755 --- a/canvas/source/directx/dx_canvashelper_texturefill.cxx +++ b/canvas/source/directx/dx_canvashelper_texturefill.cxx @@ -42,6 +42,8 @@ #include <basegfx/range/b2drectangle.hxx> #include <basegfx/numeric/ftools.hxx> #include <basegfx/tools/tools.hxx> +#include <basegfx/tools/lerp.hxx> +#include <basegfx/tools/keystoplerp.hxx> #include <basegfx/tools/canvastools.hxx> #include <basegfx/matrix/b2dhommatrixtools.hxx> @@ -52,6 +54,8 @@ #include "dx_impltools.hxx" #include <boost/scoped_ptr.hpp> +#include <boost/bind.hpp> +#include <boost/tuple/tuple.hpp> using namespace ::com::sun::star; @@ -62,11 +66,12 @@ namespace dxcanvas { typedef ::boost::shared_ptr< Gdiplus::PathGradientBrush > PathGradientBrushSharedPtr; - bool fillLinearGradient( GraphicsSharedPtr& rGraphics, - const Gdiplus::Color& rColor1, - const Gdiplus::Color& rColor2, - const GraphicsPathSharedPtr& rFillPath, - const rendering::Texture& texture ) + bool fillLinearGradient( GraphicsSharedPtr& rGraphics, + const ::canvas::ParametricPolyPolygon::Values& rValues, + const std::vector< Gdiplus::Color >& rColors, + const std::vector< REAL >& rStops, + const GraphicsPathSharedPtr& rFillPath, + const rendering::Texture& texture ) { // setup a linear gradient with two colors // --------------------------------------- @@ -76,12 +81,16 @@ namespace dxcanvas 0.5f), Gdiplus::PointF(1.0f, 0.5f), - rColor1, - rColor2 ); + rColors[0], + rColors[1] ); + + aBrush.SetInterpolationColors(&rColors[0], + &rStops[0], + rColors.size()); // render background color, as LinearGradientBrush does not // properly support the WrapModeClamp repeat mode - Gdiplus::SolidBrush aBackgroundBrush( rColor1 ); + Gdiplus::SolidBrush aBackgroundBrush( rColors[0] ); rGraphics->FillPath( &aBackgroundBrush, rFillPath.get() ); // TODO(F2): This does not yet support other repeat modes @@ -191,144 +200,10 @@ namespace dxcanvas return true; } - bool fillAxialGradient( GraphicsSharedPtr& rGraphics, - const Gdiplus::Color& rColor1, - const Gdiplus::Color& rColor2, - const GraphicsPathSharedPtr& rFillPath, - const rendering::Texture& texture ) - { - // setup a linear gradient with three colors - // ----------------------------------------- - - Gdiplus::LinearGradientBrush aBrush( - Gdiplus::PointF(0.0f, - 0.5f), - Gdiplus::PointF(1.0f, - 0.5f), - rColor1, - rColor1 ); - - Gdiplus::Color aColors[] = - { - rColor1, // at 0.0 - rColor2, // at 0.5 - rColor1 // at 1.0 - }; - - Gdiplus::REAL aPositions[] = - { - 0.0, - 0.5, - 1.0 - }; - - if( Gdiplus::Ok != aBrush.SetInterpolationColors( aColors, - aPositions, - sizeof( aPositions ) / sizeof(Gdiplus::REAL) ) ) - { - return false; - } - - // render background color, as LinearGradientBrush does not - // properly support the WrapModeClamp repeat mode - Gdiplus::SolidBrush aBackgroundBrush( rColor1 ); - rGraphics->FillPath( &aBackgroundBrush, rFillPath.get() ); - - // TODO(F2): This does not yet support other repeat modes - // except clamp, and probably also no multi-texturing - - // calculate parallelogram of gradient in object space, extend - // top and bottom of it such that they cover the whole fill - // path bound area - ::basegfx::B2DHomMatrix aTextureTransform; - ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform, - texture.AffineTransform ); - - ::basegfx::B2DPoint aLeftTop( 0.0, 0.0 ); - ::basegfx::B2DPoint aLeftBottom( 0.0, 1.0 ); - ::basegfx::B2DPoint aRightTop( 1.0, 0.0 ); - ::basegfx::B2DPoint aRightBottom( 1.0, 1.0 ); - - aLeftTop *= aTextureTransform; - aLeftBottom *= aTextureTransform; - aRightTop *= aTextureTransform; - aRightBottom*= aTextureTransform; - - Gdiplus::RectF aBounds; - rFillPath->GetBounds( &aBounds, NULL, NULL ); - - // now, we potentially have to enlarge our gradient area - // atop and below the transformed [0,1]x[0,1] unit rect, - // for the gradient to fill the complete bound rect. - ::basegfx::tools::infiniteLineFromParallelogram( aLeftTop, - aLeftBottom, - aRightTop, - aRightBottom, - tools::b2dRangeFromGdiPlusRectF( aBounds ) ); - - // generate clip polygon from the extended parallelogram - // (exploit the feature that distinct lines in a figure are - // automatically closed by a straight line) - Gdiplus::GraphicsPath aClipPath; - aClipPath.AddLine( static_cast<Gdiplus::REAL>(aLeftTop.getX()), - static_cast<Gdiplus::REAL>(aLeftTop.getY()), - static_cast<Gdiplus::REAL>(aRightTop.getX()), - static_cast<Gdiplus::REAL>(aRightTop.getY()) ); - aClipPath.AddLine( static_cast<Gdiplus::REAL>(aRightBottom.getX()), - static_cast<Gdiplus::REAL>(aRightBottom.getY()), - static_cast<Gdiplus::REAL>(aLeftBottom.getX()), - static_cast<Gdiplus::REAL>(aLeftBottom.getY()) ); - aClipPath.CloseFigure(); - - // limit output to a _single_ strip of the gradient (have to - // clip here, since GDI+ wrapmode clamp does not work here) - if( Gdiplus::Ok != rGraphics->SetClip( rFillPath.get(), - Gdiplus::CombineModeIntersect ) ) - { - return false; - } - if( Gdiplus::Ok != rGraphics->SetClip( &aClipPath, - Gdiplus::CombineModeIntersect ) ) - { - return false; - } - - // now, finally, output the gradient - Gdiplus::Matrix aMatrix; - tools::gdiPlusMatrixFromAffineMatrix2D( aMatrix, - texture.AffineTransform ); - aBrush.SetTransform( &aMatrix ); - - rGraphics->FillRectangle( &aBrush, aBounds ); - - return true; - } - - PathGradientBrushSharedPtr createPathGradientBrush( const GraphicsPathSharedPtr& rGradientPath, - const Gdiplus::Color& rColor1, - const Gdiplus::Color& rColor2 ) - { - PathGradientBrushSharedPtr pGradientBrush( - new Gdiplus::PathGradientBrush( rGradientPath.get() ) ); - - Gdiplus::Color aColors[] = - { - rColor1 - }; - - INT nCount(1); - - pGradientBrush->SetSurroundColors( aColors, - &nCount ); - pGradientBrush->SetCenterColor( rColor2 ); - - return pGradientBrush; - } - bool fillPolygonalGradient( const ::canvas::ParametricPolyPolygon::Values& rValues, + const std::vector< Gdiplus::Color >& rColors, + const std::vector< REAL >& rStops, GraphicsSharedPtr& rGraphics, - const Gdiplus::Color& rColor1, - const Gdiplus::Color& rColor2, const GraphicsPathSharedPtr& rPath, const rendering::Texture& texture ) { @@ -351,7 +226,7 @@ namespace dxcanvas PathGradientBrushSharedPtr pGradientBrush; // fill background uniformly with end color - Gdiplus::SolidBrush aBackgroundBrush( rColor1 ); + Gdiplus::SolidBrush aBackgroundBrush( rColors[0] ); rGraphics->FillPath( &aBackgroundBrush, pFillPath.get() ); // scale focus according to aspect ratio: for wider-than-tall @@ -391,12 +266,9 @@ namespace dxcanvas // -------------------------------- // TODO(Q2): Unify step calculations with VCL canvas - 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]); Gdiplus::Matrix aWorldTransformMatrix; rGraphics->GetTransform( &aWorldTransformMatrix ); @@ -409,17 +281,16 @@ namespace dxcanvas static_cast<int>( hypot( aBounds.Width, aBounds.Height ) + 1.0 ) ); // typical number for pixel of the same color (strip size) - const int nStripSize( 2 ); + const int nStripSize( nGradientSize < 50 ? 2 : 4 ); - // use at least three steps, and at utmost the number of - // color steps. + // use at least three steps, and at utmost the number of color + // steps const int nStepCount( ::std::max( 3, ::std::min( nGradientSize / nStripSize, - nColorSteps ) ) + 1 ); - + nColorSteps ) ) ); Gdiplus::SolidBrush aFillBrush( rColor1 ); Gdiplus::Matrix aGDIScaleMatrix; @@ -436,19 +307,17 @@ namespace dxcanvas 1.0 - 1.0/rValues.mnAspectRatio : 1.0 - rValues.mnAspectRatio ); + basegfx::tools::KeyStopLerp aLerper(rValues.maStops); for( int i=1; i<nStepCount; ++i ) { - // lerp color. Funnily, the straight-forward integer - // lerp ((nStepCount - i)*val + i*val)/nStepCount gets - // fully botched by MSVC, at least for anything that - // really inlines inlines (i.e. every compile without - // debug=t) - const double nFrac( (double)i/nStepCount ); + std::ptrdiff_t nIndex; + double fAlpha; + boost::tuples::tie(nIndex,fAlpha)=aLerper.lerp(double(i)/nStepCount); const Gdiplus::Color aFillColor( - static_cast<BYTE>( (1.0 - nFrac)*rColor1.GetRed() + nFrac*rColor2.GetRed() ), - static_cast<BYTE>( (1.0 - nFrac)*rColor1.GetGreen() + nFrac*rColor2.GetGreen() ), - static_cast<BYTE>( (1.0 - nFrac)*rColor1.GetBlue() + nFrac*rColor2.GetBlue() ) ); + static_cast<BYTE>( basegfx::tools::lerp(rColors[nIndex].GetRed(),rColors[nIndex+1].GetRed(),fAlpha) ), + static_cast<BYTE>( basegfx::tools::lerp(rColors[nIndex].GetGreen(),rColors[nIndex+1].GetGreen(),fAlpha) ), + static_cast<BYTE>( basegfx::tools::lerp(rColors[nIndex].GetBlue(),rColors[nIndex+1].GetBlue(),fAlpha) ) ); aFillBrush.SetColor( aFillColor ); @@ -512,10 +381,11 @@ namespace dxcanvas pGradientPath->Transform( &aMatrix ); - pGradientBrush = createPathGradientBrush( - pGradientPath, - rColor1, - rColor2 ); + pGradientBrush.reset( + new Gdiplus::PathGradientBrush( pGradientPath.get() ) ); + pGradientBrush->SetInterpolationColors( &rColors[0], + &rStops[0], + rStops.size() ); // explicitely setup center point. Since the center of GDI+ // gradients are by default the _centroid_ of the path @@ -557,8 +427,8 @@ namespace dxcanvas } bool fillGradient( const ::canvas::ParametricPolyPolygon::Values& rValues, - const Gdiplus::Color& rColor1, - const Gdiplus::Color& rColor2, + const std::vector< Gdiplus::Color >& rColors, + const std::vector< REAL >& rStops, GraphicsSharedPtr& rGraphics, const GraphicsPathSharedPtr& rPath, const rendering::Texture& texture ) @@ -567,27 +437,20 @@ namespace dxcanvas { case ::canvas::ParametricPolyPolygon::GRADIENT_LINEAR: fillLinearGradient( rGraphics, - rColor1, - rColor2, + rValues, + rColors, + rStops, rPath, texture ); break; - case ::canvas::ParametricPolyPolygon::GRADIENT_AXIAL: - fillAxialGradient( rGraphics, - rColor1, - rColor2, - rPath, - texture ); - break; - case ::canvas::ParametricPolyPolygon::GRADIENT_ELLIPTICAL: // FALLTHROUGH intended case ::canvas::ParametricPolyPolygon::GRADIENT_RECTANGULAR: fillPolygonalGradient( rValues, + rColors, + rStops, rGraphics, - rColor1, - rColor2, rPath, texture ); break; @@ -709,15 +572,24 @@ namespace dxcanvas const ::canvas::ParametricPolyPolygon::Values& rValues( pGradient->getValues() ); - // TODO: use all the colors and place them on given positions/stops - const Gdiplus::Color aColor1(tools::sequenceToArgb(rValues.maColors[0])); - const Gdiplus::Color aColor2(tools::sequenceToArgb(rValues.maColors[rValues.maColors.getLength () - 1] )); + OSL_ASSERT(rValues.maColors.getLength() == rValues.maStops.getLength() + && rValues.maColors.getLength() > 1); + + std::vector< Gdiplus::Color > aColors(rValues.maColors.getLength()); + std::transform(&rValues.maColors[0], + &rValues.maColors[0]+rValues.maColors.getLength(), + aColors.begin(), + boost::bind( + &tools::sequenceToArgb, + _1)); + std::vector< REAL > aStops; + comphelper::sequenceToContainer(aStops,rValues.maStops); // TODO(E1): Return value // TODO(F1): FillRule fillGradient( rValues, - aColor1, - aColor2, + aColors, + aStops, pGraphics, tools::graphicsPathFromXPolyPolygon2D( xPolyPolygon ), textures[0] ); diff --git a/canvas/source/directx/dx_spritecanvas.hxx b/canvas/source/directx/dx_spritecanvas.hxx index 555316d14b9f..64389dfa4664 100755 --- a/canvas/source/directx/dx_spritecanvas.hxx +++ b/canvas/source/directx/dx_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> @@ -61,14 +60,14 @@ namespace dxcanvas { 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::rendering::XBufferController, - ::com::sun::star::awt::XWindowListener, - ::com::sun::star::util::XUpdatable, - ::com::sun::star::beans::XPropertySet, - ::com::sun::star::lang::XServiceName > WindowGraphicDeviceBase_Base; + ::com::sun::star::rendering::XIntegerBitmap, + ::com::sun::star::rendering::XGraphicDevice, + ::com::sun::star::lang::XMultiServiceFactory, + ::com::sun::star::rendering::XBufferController, + ::com::sun::star::awt::XWindowListener, + ::com::sun::star::util::XUpdatable, + ::com::sun::star::beans::XPropertySet, + ::com::sun::star::lang::XServiceName > WindowGraphicDeviceBase_Base; typedef ::canvas::BufferedGraphicDeviceBase< ::canvas::BaseMutexHelper< WindowGraphicDeviceBase_Base >, SpriteDeviceHelper, ::osl::MutexGuard, |