diff options
author | Rüdiger Timm <rt@openoffice.org> | 2004-11-26 16:13:05 +0000 |
---|---|---|
committer | Rüdiger Timm <rt@openoffice.org> | 2004-11-26 16:13:05 +0000 |
commit | 68530643d9d8d2a8805cf8692617a9fd712faaa2 (patch) | |
tree | 1e6d7083d47393557be5def1aeab9b6031772d0b /canvas/source/vcl/impltools.cxx | |
parent | 67490613cad577ebc33df98cec33fd2cbd5491b8 (diff) |
INTEGRATION: CWS presentationengine01 (1.2.2); FILE MERGED
2004/11/22 15:19:14 thb 1.2.2.12: #110496# Ensuring similar types for ternary operator
2004/11/17 17:00:30 thb 1.2.2.11: #118514# Canvas module reorg
2004/11/01 22:19:09 thb 1.2.2.10: #10496# Performance optimizations: added profiling traces
2004/10/11 00:00:06 thb 1.2.2.9: #i34997# Added new method XCanvas::drawBitmapModulated(), to facilitate global alpha channel changes when rendering bitmaps
2004/09/27 20:12:31 thb 1.2.2.8: #110496# Fixed problem with CanvasBitmap instances with alpha channel (simply ignored that before)
2004/08/31 17:50:47 thb 1.2.2.7: #110496# Fixed typo in coordinate range check (compared twice with X)
2004/08/03 19:45:36 thb 1.2.2.6: #110496# Changed vcl canvas to use B2DPolygons, and transforming clip polys before setting them
2004/07/20 19:23:56 thb 1.2.2.5: #110496# Removed self-references to various interface implementations, along the lines, factored out common base implementation for all c++ canvases
2004/07/01 16:56:47 thb 1.2.2.4: #110496# Switched to math.h for PI
2004/06/17 10:33:26 thb 1.2.2.3: #110496# Handle huge shrinks correctly for font scaling; added some more debug code
2004/05/27 20:51:24 thb 1.2.2.2: #110496#
Added classification code to all TODO/HACK/FIXME comments.
There are four categories:
- code quality (C)
- performance (P)
- missing functionality (F)
- and missing/incomplete error handling (E)
Furthermore, every category has a severity number between
1 and 3 associated, where 1 is lowest and 3 highest
severity
2004/04/05 15:57:58 thb 1.2.2.1: Resync with canvas01 changes
Diffstat (limited to 'canvas/source/vcl/impltools.cxx')
-rw-r--r-- | canvas/source/vcl/impltools.cxx | 359 |
1 files changed, 257 insertions, 102 deletions
diff --git a/canvas/source/vcl/impltools.cxx b/canvas/source/vcl/impltools.cxx index 75a492665a74..ae63d04e05d4 100644 --- a/canvas/source/vcl/impltools.cxx +++ b/canvas/source/vcl/impltools.cxx @@ -2,9 +2,9 @@ * * $RCSfile: impltools.cxx,v $ * - * $Revision: 1.2 $ + * $Revision: 1.3 $ * - * last change: $Author: thb $ $Date: 2004-03-18 10:38:41 $ + * last change: $Author: rt $ $Date: 2004-11-26 17:13:05 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -59,6 +59,17 @@ * ************************************************************************/ +#include <canvas/debug.hxx> + +#ifndef _USE_MATH_DEFINES +#define _USE_MATH_DEFINES // needed by Visual C++ for math constants +#endif +#include <math.h> // M_PI definition + +#ifndef _RTL_LOGFILE_HXX_ +#include <rtl/logfile.hxx> +#endif + #ifndef _DRAFTS_COM_SUN_STAR_GEOMETRY_REALSIZE2D_HPP__ #include <drafts/com/sun/star/geometry/RealSize2D.hpp> #endif @@ -88,9 +99,6 @@ #include <drafts/com/sun/star/rendering/XIntegerBitmap.hpp> #endif -#ifndef _TL_POLY_HXX -#include <tools/poly.hxx> -#endif #ifndef _SV_SALBTYPE_HXX #include <vcl/salbtype.hxx> #endif @@ -107,22 +115,29 @@ #include <vcl/canvastools.hxx> #endif +#ifndef _BGFX_POINT_B2DPOINT_HXX +#include <basegfx/point/b2dpoint.hxx> +#endif #ifndef _BGFX_TUPLE_B2DTUPLE_HXX #include <basegfx/tuple/b2dtuple.hxx> #endif +#ifndef _BGFX_RANGE_B2DRECTANGLE_HXX +#include <basegfx/range/b2drectangle.hxx> +#endif #ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX #include <basegfx/matrix/b2dhommatrix.hxx> #endif #ifndef _BGFX_TOOLS_CANVASTOOLS_HXX #include <basegfx/tools/canvastools.hxx> #endif +#ifndef _BGFX_NUMERIC_FTOOLS_HXX +#include <basegfx/numeric/ftools.hxx> +#endif #ifndef INCLUDED_RTL_MATH_HXX #include <rtl/math.hxx> #endif -#include <cmath> // for fmod - #include <canvas/canvastools.hxx> #include "impltools.hxx" @@ -137,7 +152,7 @@ namespace vclcanvas { namespace tools { - ::PolyPolygon polyPolygonFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly ) + ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly ) { uno::Reference< lang::XServiceInfo > xRef( xPoly, uno::UNO_QUERY ); @@ -145,17 +160,19 @@ namespace vclcanvas if( xRef.is() && xRef->getImplementationName().equals( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(LINEPOLYPOLYGON_IMPLEMENTATION_NAME))) ) { - // TODO: Maybe use dynamic_cast here + // TODO(Q1): Maybe use dynamic_cast here - // TODO: Provide true beziers here! - return static_cast<LinePolyPolygon*>(xPoly.get())->getVCLPolyPolygon(); + // TODO(F1): Provide true beziers here! + return static_cast<LinePolyPolygon*>(xPoly.get())->getPolyPolygon(); } else { - // TODO: extract points from polygon interface + // TODO(F1): extract points from polygon interface + ENSURE_AND_THROW( false, + "polyPolygonFromXPolyPolygon2D(): could not extract points" ); } - return ::PolyPolygon(); + return ::basegfx::B2DPolyPolygon(); } ::BitmapEx bitmapExFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap ) @@ -166,26 +183,24 @@ namespace vclcanvas if( xRef.is() && xRef->getImplementationName().equals( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CANVASBITMAP_IMPLEMENTATION_NAME))) ) { - // TODO: Maybe use dynamic_cast here - VirtualDevice& rVDev( static_cast<CanvasBitmap*>(xBitmap.get())->getVirDev() ); - const Point aEmptyPoint(0,0); - const Size aBmpSize(rVDev.GetOutputSizePixel()); - - // TODO: handle alpha vDev here - return rVDev.GetBitmap(aEmptyPoint, aBmpSize); + // TODO(Q1): Maybe use dynamic_cast here + return static_cast<CanvasBitmap*>(xBitmap.get())->getBitmap(); } else { - // TODO: extract points from polygon interface + // TODO(F1): extract pixel from XBitmap interface + ENSURE_AND_THROW( false, + "bitmapExFromXBitmap(): could not extract bitmap" ); } return ::BitmapEx(); } - ::Point setupFontTransform( ::Font& aVCLFont, - const rendering::ViewState& rViewState, - const rendering::RenderState& rRenderState, - OutputDevice& rOutDev ) + bool setupFontTransform( ::Point& o_rPoint, + ::Font& io_rVCLFont, + const rendering::ViewState& rViewState, + const rendering::RenderState& rRenderState, + ::OutputDevice& rOutDev ) { ::basegfx::B2DHomMatrix aMatrix; @@ -203,22 +218,33 @@ namespace vclcanvas if( !::rtl::math::approxEqual(aScale.getX(), aScale.getY()) ) { // retrieve true font width - const int aFontWidth( rOutDev.GetFontMetric( aVCLFont ).GetWidth() ); + const int nFontWidth( rOutDev.GetFontMetric( io_rVCLFont ).GetWidth() ); + + const int nScaledFontWidth( ::basegfx::fround(nFontWidth * aScale.getX()) ); + + if( !nScaledFontWidth ) + { + // scale is smaller than one pixel - disable text + // output altogether + return false; + } - aVCLFont.SetWidth( static_cast<long>(aFontWidth * aScale.getX() + .5) ); + io_rVCLFont.SetWidth( nScaledFontWidth ); } if( !::rtl::math::approxEqual(aScale.getY(), 1.0) ) { - const int nFontHeight( aVCLFont.GetHeight() ); - aVCLFont.SetHeight( static_cast<long>(nFontHeight * aScale.getY() + .5) ); + const int nFontHeight( io_rVCLFont.GetHeight() ); + io_rVCLFont.SetHeight( ::basegfx::fround(nFontHeight * aScale.getY()) ); } - aVCLFont.SetOrientation( static_cast< short >(-fmod(nRotate, 2*F_PI)*(1800.0/F_PI) + .5) ); + io_rVCLFont.SetOrientation( static_cast< short >( ::basegfx::fround(-fmod(nRotate, 2*M_PI)*(1800.0/M_PI)) ) ); - // TODO: Missing functionality in VCL: shearing - return ::Point( static_cast<long>(aTranslate.getX() + .5), - static_cast<long>(aTranslate.getY() + .5) ); + // TODO(F2): Missing functionality in VCL: shearing + o_rPoint.X() = ::basegfx::fround(aTranslate.getX()); + o_rPoint.Y() = ::basegfx::fround(aTranslate.getY()); + + return true; } // VCL-Canvas related @@ -238,40 +264,30 @@ namespace vclcanvas return ::vcl::unotools::pointFromB2DPoint( aPoint ); } - ::PolyPolygon mapPolyPolygon( const ::PolyPolygon& rPoly, - const rendering::ViewState& rViewState, - const rendering::RenderState& rRenderState ) + ::PolyPolygon mapPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly, + const rendering::ViewState& rViewState, + const rendering::RenderState& rRenderState ) { - PolyPolygon aRes; ::basegfx::B2DHomMatrix aMatrix; ::canvas::tools::mergeViewAndRenderTransform(aMatrix, rViewState, rRenderState); - int nCurrPoly, nCurrPoint; - for( nCurrPoly=0; nCurrPoly<rPoly.Count(); ++nCurrPoly ) - { - Polygon aDest(rPoly[nCurrPoly].GetSize()); - - for( nCurrPoint=0; nCurrPoint<aDest.GetSize(); ++nCurrPoint ) - { - ::basegfx::B2DPoint aPoint( ::vcl::unotools::b2DPointFromPoint( rPoly[nCurrPoly][nCurrPoint] ) ); - - aPoint *= aMatrix; + ::basegfx::B2DPolyPolygon aTemp( rPoly ); - aDest[nCurrPoint] = ::vcl::unotools::pointFromB2DPoint( aPoint ); - } - - aRes.Insert(aDest); - } + aTemp.transform( aMatrix ); - return aRes; + return ::PolyPolygon( aTemp ); } ::BitmapEx transformBitmap( const BitmapEx& rBitmap, const rendering::ViewState& rViewState, - const rendering::RenderState& rRenderState ) + const rendering::RenderState& rRenderState, + ModulationMode eModulationMode ) { + RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::tools::transformBitmap()" ); + RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::vclcanvas::tools::transformBitmap: 0x%X", &rBitmap ); + // calc transformation and size of bitmap to be // generated. Note, that the translational components are // deleted from the transformation; this can be handled by @@ -295,6 +311,14 @@ namespace vclcanvas aBmpSize.Height()), aTransform ); + const bool bModulateColors( eModulationMode == MODULATE_WITH_DEVICECOLOR && + rRenderState.DeviceColor.getLength() > 2 ); + const double nRedModulation( bModulateColors ? rRenderState.DeviceColor[0] : 1.0 ); + const double nGreenModulation( bModulateColors ? rRenderState.DeviceColor[1] : 1.0 ); + const double nBlueModulation( bModulateColors ? rRenderState.DeviceColor[2] : 1.0 ); + const double nAlphaModulation( bModulateColors && rRenderState.DeviceColor.getLength() > 3 ? + rRenderState.DeviceColor[3] : 1.0 ); + Bitmap aSrcBitmap( rBitmap.GetBitmap() ); Bitmap aSrcAlpha; @@ -308,32 +332,40 @@ namespace vclcanvas aSrcAlpha = rBitmap.GetMask(); } - Bitmap aDstBitmap( aSrcBitmap ); - Bitmap aDstAlpha( rBitmap.IsTransparent() ? aSrcAlpha : Bitmap( Size(1,1), 8) ); - aDstBitmap.SetSizePixel( Size( FRound( aDestRect.getMaxX() ), - FRound( aDestRect.getMaxY() ) ) ); - aDstAlpha.SetSizePixel( Size(FRound( aDestRect.getMaxX() ), - FRound( aDestRect.getMaxY() ) ) ); + ScopedBitmapReadAccess pReadAccess( aSrcBitmap.AcquireReadAccess(), + aSrcBitmap ); + ScopedBitmapReadAccess pAlphaReadAccess( rBitmap.IsTransparent() ? + aSrcAlpha.AcquireReadAccess() : + (BitmapReadAccess*)NULL, + aSrcAlpha ); + + if( pReadAccess.get() == NULL || + (pAlphaReadAccess.get() == NULL && rBitmap.IsTransparent()) ) + { + // TODO(E2): Error handling! + ENSURE_AND_THROW( false, + "transformBitmap(): could not access source bitmap" ); + } + + const Size aDestBmpSize( ::basegfx::fround( aDestRect.getMaxX() ), + ::basegfx::fround( aDestRect.getMaxY() ) ); + + Bitmap aDstBitmap( aDestBmpSize, aSrcBitmap.GetBitCount(), &pReadAccess->GetPalette() ); + Bitmap aDstAlpha( AlphaMask( aDestBmpSize ).GetBitmap() ); + { // just to be on the safe side: let the // ScopedAccessors get destructed before // copy-constructing the resulting bitmap. This will // rule out the possibility that cached accessor data // is not yet written back. - ScopedBitmapReadAccess pReadAccess( aSrcBitmap.AcquireReadAccess(), - aSrcBitmap ); - ScopedBitmapReadAccess pAlphaReadAccess( rBitmap.IsTransparent() ? aSrcAlpha.AcquireReadAccess() : NULL, - aSrcAlpha ); - ScopedBitmapWriteAccess pWriteAccess( aDstBitmap.AcquireWriteAccess(), aDstBitmap ); ScopedBitmapWriteAccess pAlphaWriteAccess( aDstAlpha.AcquireWriteAccess(), aDstAlpha ); - if( pReadAccess.get() != NULL && - (pAlphaReadAccess.get() != NULL || !rBitmap.IsTransparent()) && - pWriteAccess.get() != NULL && + if( pWriteAccess.get() != NULL && pAlphaWriteAccess.get() != NULL && aTransform.isInvertible() ) { @@ -342,56 +374,177 @@ namespace vclcanvas // source aTransform.invert(); - const Size aDestBmpSize( aDstBitmap.GetSizePixel() ); - // for the time being, always read as ARGB for( int y=0; y<aDestBmpSize.Height(); ++y ) { - // differentiate mask and alpha channel (on-off - // vs. multi-level transparency) - if( rBitmap.IsTransparent() ) + if( bModulateColors ) { - // Handling alpha and mask just the same... - for( int x=0; x<aDestBmpSize.Width(); ++x ) - { - ::basegfx::B2DPoint aPoint(x,y); - aPoint *= aTransform; + // TODO(P2): Have different branches for + // alpha-only modulation (color + // modulations eq. 1.0) + + // modulate all color channels with given + // values - const int nSrcX( FRound( aPoint.getX() + .5 ) ); - const int nSrcY( FRound( aPoint.getY() + .5 ) ); - if( nSrcX < 0 || nSrcX >= aBmpSize.Width() || - nSrcY < 0 || nSrcX >= aBmpSize.Height() ) + // differentiate mask and alpha channel (on-off + // vs. multi-level transparency) + if( rBitmap.IsTransparent() ) + { + // Handling alpha and mask just the same... + for( int x=0; x<aDestBmpSize.Width(); ++x ) { - pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) ); + ::basegfx::B2DPoint aPoint(x,y); + aPoint *= aTransform; + + const int nSrcX( ::basegfx::fround( aPoint.getX() ) ); + const int nSrcY( ::basegfx::fround( aPoint.getY() ) ); + if( nSrcX < 0 || nSrcX >= aBmpSize.Width() || + nSrcY < 0 || nSrcY >= aBmpSize.Height() ) + { + pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) ); + } + else + { + // modulate alpha with + // nAlphaModulation. This is a + // little bit verbose, formula + // is 255 - (255-pixAlpha)*nAlphaModulation + // (invert 'alpha' pixel value, + // to get the standard alpha + // channel behaviour) + pAlphaWriteAccess->SetPixel( y, x, + BitmapColor( + 255U - + static_cast<BYTE>( + nAlphaModulation* + (255U + - pAlphaReadAccess->GetPixel( + nSrcY, + nSrcX ).GetIndex() ) + .5 ) ) ); + + BitmapColor aColor( pReadAccess->GetPixel( nSrcY, + nSrcX ) ); + + aColor.SetRed( + static_cast<BYTE>( + nRedModulation * + aColor.GetRed() + .5 )); + aColor.SetGreen( + static_cast<BYTE>( + nGreenModulation * + aColor.GetGreen() + .5 )); + aColor.SetBlue( + static_cast<BYTE>( + nBlueModulation * + aColor.GetBlue() + .5 )); + + pWriteAccess->SetPixel( y, x, + aColor ); + } } - else + } + else + { + for( int x=0; x<aDestBmpSize.Width(); ++x ) { - pAlphaWriteAccess->SetPixel( y, x, pAlphaReadAccess->GetPixel( nSrcY, - nSrcX ) ); - pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY, - nSrcX ) ); + ::basegfx::B2DPoint aPoint(x,y); + aPoint *= aTransform; + + const int nSrcX( ::basegfx::fround( aPoint.getX() ) ); + const int nSrcY( ::basegfx::fround( aPoint.getY() ) ); + if( nSrcX < 0 || nSrcX >= aBmpSize.Width() || + nSrcY < 0 || nSrcY >= aBmpSize.Height() ) + { + pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) ); + } + else + { + // modulate alpha with + // nAlphaModulation. This is a + // little bit verbose, formula + // is 255 - 255*nAlphaModulation + // (invert 'alpha' pixel value, + // to get the standard alpha + // channel behaviour) + pAlphaWriteAccess->SetPixel( y, x, + BitmapColor( + 255U - + static_cast<BYTE>( + nAlphaModulation*255.0 + + .5 ) ) ); + + BitmapColor aColor( pReadAccess->GetPixel( nSrcY, + nSrcX ) ); + + aColor.SetRed( + static_cast<BYTE>( + nRedModulation * + aColor.GetRed() + .5 )); + aColor.SetGreen( + static_cast<BYTE>( + nGreenModulation * + aColor.GetGreen() + .5 )); + aColor.SetBlue( + static_cast<BYTE>( + nBlueModulation * + aColor.GetBlue() + .5 )); + + pWriteAccess->SetPixel( y, x, + aColor ); + } } } } else { - for( int x=0; x<aDestBmpSize.Width(); ++x ) + // differentiate mask and alpha channel (on-off + // vs. multi-level transparency) + if( rBitmap.IsTransparent() ) { - ::basegfx::B2DPoint aPoint(x,y); - aPoint *= aTransform; - - const int nSrcX( FRound( aPoint.getX() + .5 ) ); - const int nSrcY( FRound( aPoint.getY() + .5 ) ); - if( nSrcX < 0 || nSrcX >= aBmpSize.Width() || - nSrcY < 0 || nSrcX >= aBmpSize.Height() ) + // Handling alpha and mask just the same... + for( int x=0; x<aDestBmpSize.Width(); ++x ) { - pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) ); + ::basegfx::B2DPoint aPoint(x,y); + aPoint *= aTransform; + + const int nSrcX( ::basegfx::fround( aPoint.getX() ) ); + const int nSrcY( ::basegfx::fround( aPoint.getY() ) ); + if( nSrcX < 0 || nSrcX >= aBmpSize.Width() || + nSrcY < 0 || nSrcY >= aBmpSize.Height() ) + { + pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) ); + } + else + { + pAlphaWriteAccess->SetPixel( y, x, + pAlphaReadAccess->GetPixel( nSrcY, + nSrcX ) ); + + pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY, + nSrcX ) ); + } } - else + } + else + { + for( int x=0; x<aDestBmpSize.Width(); ++x ) { - pAlphaWriteAccess->SetPixel( y, x, BitmapColor(0) ); - pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY, - nSrcX ) ); + ::basegfx::B2DPoint aPoint(x,y); + aPoint *= aTransform; + + const int nSrcX( ::basegfx::fround( aPoint.getX() ) ); + const int nSrcY( ::basegfx::fround( aPoint.getY() ) ); + if( nSrcX < 0 || nSrcX >= aBmpSize.Width() || + nSrcY < 0 || nSrcY >= aBmpSize.Height() ) + { + pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) ); + } + else + { + pAlphaWriteAccess->SetPixel( y, x, BitmapColor(0) ); + pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY, + nSrcX ) ); + } } } } @@ -401,7 +554,9 @@ namespace vclcanvas } else { - // TODO: Error handling! + // TODO(E2): Error handling! + ENSURE_AND_THROW( false, + "transformBitmap(): could not access bitmap" ); } } |