xref: /aoo41x/main/canvas/source/vcl/impltools.cxx (revision 83d0117d)
125ea7f45SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
325ea7f45SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
425ea7f45SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
525ea7f45SAndrew Rist  * distributed with this work for additional information
625ea7f45SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
725ea7f45SAndrew Rist  * to you under the Apache License, Version 2.0 (the
825ea7f45SAndrew Rist  * "License"); you may not use this file except in compliance
925ea7f45SAndrew Rist  * with the License.  You may obtain a copy of the License at
1025ea7f45SAndrew Rist  *
1125ea7f45SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1225ea7f45SAndrew Rist  *
1325ea7f45SAndrew Rist  * Unless required by applicable law or agreed to in writing,
1425ea7f45SAndrew Rist  * software distributed under the License is distributed on an
1525ea7f45SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1625ea7f45SAndrew Rist  * KIND, either express or implied.  See the License for the
1725ea7f45SAndrew Rist  * specific language governing permissions and limitations
1825ea7f45SAndrew Rist  * under the License.
1925ea7f45SAndrew Rist  *
2025ea7f45SAndrew Rist  *************************************************************/
2125ea7f45SAndrew Rist 
2225ea7f45SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_canvas.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <canvas/debug.hxx>
28cdf0e10cSrcweir #include <tools/diagnose_ex.h>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <rtl/math.hxx>
31cdf0e10cSrcweir #include <rtl/logfile.hxx>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <com/sun/star/geometry/RealSize2D.hpp>
34cdf0e10cSrcweir #include <com/sun/star/geometry/RealPoint2D.hpp>
35cdf0e10cSrcweir #include <com/sun/star/geometry/RealRectangle2D.hpp>
36cdf0e10cSrcweir #include <com/sun/star/rendering/RenderState.hpp>
37cdf0e10cSrcweir #include <com/sun/star/rendering/XCanvas.hpp>
38cdf0e10cSrcweir #include <com/sun/star/rendering/XBitmap.hpp>
39cdf0e10cSrcweir #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
40cdf0e10cSrcweir #include <com/sun/star/geometry/RealBezierSegment2D.hpp>
41cdf0e10cSrcweir #include <com/sun/star/rendering/XIntegerBitmap.hpp>
42cdf0e10cSrcweir 
43cdf0e10cSrcweir #include <vcl/salbtype.hxx>
44cdf0e10cSrcweir #include <vcl/bmpacc.hxx>
45cdf0e10cSrcweir #include <vcl/bitmapex.hxx>
46cdf0e10cSrcweir #include <vcl/metric.hxx>
47cdf0e10cSrcweir #include <vcl/canvastools.hxx>
48cdf0e10cSrcweir 
49cdf0e10cSrcweir #include <basegfx/point/b2dpoint.hxx>
50cdf0e10cSrcweir #include <basegfx/tuple/b2dtuple.hxx>
51cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
52cdf0e10cSrcweir #include <basegfx/range/b2drectangle.hxx>
53cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
54cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
55cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
56cdf0e10cSrcweir 
57cdf0e10cSrcweir #include <canvas/canvastools.hxx>
58cdf0e10cSrcweir 
59cdf0e10cSrcweir #include "impltools.hxx"
60cdf0e10cSrcweir #include "canvasbitmap.hxx"
61cdf0e10cSrcweir 
62cdf0e10cSrcweir #include <numeric>
63cdf0e10cSrcweir 
64cdf0e10cSrcweir 
65cdf0e10cSrcweir using namespace ::com::sun::star;
66cdf0e10cSrcweir 
67cdf0e10cSrcweir namespace vclcanvas
68cdf0e10cSrcweir {
69cdf0e10cSrcweir     namespace tools
70cdf0e10cSrcweir     {
bitmapExFromXBitmap(const uno::Reference<rendering::XBitmap> & xBitmap)71cdf0e10cSrcweir         ::BitmapEx bitmapExFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
72cdf0e10cSrcweir         {
73cdf0e10cSrcweir             // TODO(F3): CanvasCustomSprite should also be tunnelled
74cdf0e10cSrcweir             // through (also implements XIntegerBitmap interface)
75cdf0e10cSrcweir             CanvasBitmap* pBitmapImpl = dynamic_cast< CanvasBitmap* >( xBitmap.get() );
76cdf0e10cSrcweir 
77cdf0e10cSrcweir             if( pBitmapImpl )
78cdf0e10cSrcweir             {
79cdf0e10cSrcweir                 return pBitmapImpl->getBitmap();
80cdf0e10cSrcweir             }
81cdf0e10cSrcweir             else
82cdf0e10cSrcweir             {
83cdf0e10cSrcweir                 SpriteCanvas* pCanvasImpl = dynamic_cast< SpriteCanvas* >( xBitmap.get() );
84cdf0e10cSrcweir                 if( pCanvasImpl && pCanvasImpl->getBackBuffer() )
85cdf0e10cSrcweir                 {
86cdf0e10cSrcweir                     // TODO(F3): mind the plain Canvas impl. Consolidate with CWS canvas05
87cdf0e10cSrcweir                     const ::OutputDevice& rDev( pCanvasImpl->getBackBuffer()->getOutDev() );
88cdf0e10cSrcweir                     const ::Point aEmptyPoint;
89cdf0e10cSrcweir                     return rDev.GetBitmapEx( aEmptyPoint,
90cdf0e10cSrcweir                                              rDev.GetOutputSizePixel() );
91cdf0e10cSrcweir                 }
92cdf0e10cSrcweir 
93cdf0e10cSrcweir                 // TODO(F2): add support for floating point bitmap formats
94cdf0e10cSrcweir                 uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntBmp(
95cdf0e10cSrcweir                     xBitmap, uno::UNO_QUERY_THROW );
96cdf0e10cSrcweir 
97cdf0e10cSrcweir                 ::BitmapEx aBmpEx = ::vcl::unotools::bitmapExFromXBitmap( xIntBmp );
98cdf0e10cSrcweir                 if( !!aBmpEx )
99cdf0e10cSrcweir                     return aBmpEx;
100cdf0e10cSrcweir 
101cdf0e10cSrcweir                 // TODO(F1): extract pixel from XBitmap interface
102cdf0e10cSrcweir                 ENSURE_OR_THROW( false,
103cdf0e10cSrcweir                                   "bitmapExFromXBitmap(): could not extract bitmap" );
104cdf0e10cSrcweir             }
105cdf0e10cSrcweir 
106cdf0e10cSrcweir             return ::BitmapEx();
107cdf0e10cSrcweir         }
108cdf0e10cSrcweir 
setupFontTransform(::Point & o_rPoint,::Font & io_rVCLFont,const rendering::ViewState & rViewState,const rendering::RenderState & rRenderState,::OutputDevice & rOutDev)109cdf0e10cSrcweir         bool setupFontTransform( ::Point&						o_rPoint,
110cdf0e10cSrcweir                                  ::Font& 						io_rVCLFont,
111cdf0e10cSrcweir                                  const rendering::ViewState& 	rViewState,
112cdf0e10cSrcweir                                  const rendering::RenderState& 	rRenderState,
113cdf0e10cSrcweir                                  ::OutputDevice&				rOutDev )
114cdf0e10cSrcweir         {
115cdf0e10cSrcweir             ::basegfx::B2DHomMatrix aMatrix;
116cdf0e10cSrcweir 
117cdf0e10cSrcweir             ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
118cdf0e10cSrcweir                                                          rViewState,
119cdf0e10cSrcweir                                                          rRenderState);
120cdf0e10cSrcweir 
121cdf0e10cSrcweir             ::basegfx::B2DTuple aScale;
122cdf0e10cSrcweir             ::basegfx::B2DTuple aTranslate;
123cdf0e10cSrcweir             double nRotate, nShearX;
124cdf0e10cSrcweir 
125cdf0e10cSrcweir             aMatrix.decompose( aScale, aTranslate, nRotate, nShearX );
126cdf0e10cSrcweir 
127cdf0e10cSrcweir             // #i72417# detecting the 180 degree rotation case manually here.
128cdf0e10cSrcweir             if( aScale.getX() < 0.0 &&
129cdf0e10cSrcweir                 aScale.getY() < 0.0 &&
130cdf0e10cSrcweir                 basegfx::fTools::equalZero(nRotate) )
131cdf0e10cSrcweir             {
132cdf0e10cSrcweir                 aScale *= -1.0;
133cdf0e10cSrcweir                 nRotate += M_PI;
134cdf0e10cSrcweir             }
135cdf0e10cSrcweir 
136cdf0e10cSrcweir             // query font metric _before_ tampering with width and height
137cdf0e10cSrcweir             if( !::rtl::math::approxEqual(aScale.getX(), aScale.getY()) )
138cdf0e10cSrcweir             {
139cdf0e10cSrcweir                 // retrieve true font width
140cdf0e10cSrcweir                 const sal_Int32 nFontWidth( rOutDev.GetFontMetric( io_rVCLFont ).GetWidth() );
141cdf0e10cSrcweir 
142cdf0e10cSrcweir                 const sal_Int32 nScaledFontWidth( ::basegfx::fround(nFontWidth * aScale.getX()) );
143cdf0e10cSrcweir 
144cdf0e10cSrcweir                 if( !nScaledFontWidth )
145cdf0e10cSrcweir                 {
146cdf0e10cSrcweir                     // scale is smaller than one pixel - disable text
147cdf0e10cSrcweir                     // output altogether
148cdf0e10cSrcweir                     return false;
149cdf0e10cSrcweir                 }
150cdf0e10cSrcweir 
151cdf0e10cSrcweir                 io_rVCLFont.SetWidth( nScaledFontWidth );
152cdf0e10cSrcweir             }
153cdf0e10cSrcweir 
154cdf0e10cSrcweir             if( !::rtl::math::approxEqual(aScale.getY(), 1.0) )
155cdf0e10cSrcweir             {
156cdf0e10cSrcweir                 const sal_Int32 nFontHeight( io_rVCLFont.GetHeight() );
157cdf0e10cSrcweir                 io_rVCLFont.SetHeight( ::basegfx::fround(nFontHeight * aScale.getY()) );
158cdf0e10cSrcweir             }
159cdf0e10cSrcweir 
160cdf0e10cSrcweir             io_rVCLFont.SetOrientation( static_cast< short >( ::basegfx::fround(-fmod(nRotate, 2*M_PI)*(1800.0/M_PI)) ) );
161cdf0e10cSrcweir 
162cdf0e10cSrcweir             // TODO(F2): Missing functionality in VCL: shearing
163cdf0e10cSrcweir             o_rPoint.X() = ::basegfx::fround(aTranslate.getX());
164cdf0e10cSrcweir             o_rPoint.Y() = ::basegfx::fround(aTranslate.getY());
165cdf0e10cSrcweir 
166cdf0e10cSrcweir             return true;
167cdf0e10cSrcweir         }
168cdf0e10cSrcweir 
isRectangle(const PolyPolygon & rPolyPoly)169cdf0e10cSrcweir         bool isRectangle( const PolyPolygon& rPolyPoly )
170cdf0e10cSrcweir         {
171cdf0e10cSrcweir             // exclude some cheap cases first
172cdf0e10cSrcweir             if( rPolyPoly.Count() != 1 )
173cdf0e10cSrcweir                 return false;
174cdf0e10cSrcweir 
175cdf0e10cSrcweir             const ::Polygon& rPoly( rPolyPoly[0] );
176cdf0e10cSrcweir 
177cdf0e10cSrcweir             sal_uInt16 nCount( rPoly.GetSize() );
178cdf0e10cSrcweir             if( nCount < 4 )
179cdf0e10cSrcweir                 return false;
180cdf0e10cSrcweir 
181cdf0e10cSrcweir             // delegate to basegfx
182cdf0e10cSrcweir             return ::basegfx::tools::isRectangle( rPoly.getB2DPolygon() );
183cdf0e10cSrcweir         }
184cdf0e10cSrcweir 
185cdf0e10cSrcweir 
186cdf0e10cSrcweir         // VCL-Canvas related
187cdf0e10cSrcweir         //---------------------------------------------------------------------
188cdf0e10cSrcweir 
mapRealPoint2D(const geometry::RealPoint2D & rPoint,const rendering::ViewState & rViewState,const rendering::RenderState & rRenderState)189cdf0e10cSrcweir         ::Point mapRealPoint2D( const geometry::RealPoint2D& 	rPoint,
190cdf0e10cSrcweir                                 const rendering::ViewState& 	rViewState,
191cdf0e10cSrcweir                                 const rendering::RenderState&	rRenderState )
192cdf0e10cSrcweir         {
193cdf0e10cSrcweir             ::basegfx::B2DPoint aPoint( ::basegfx::unotools::b2DPointFromRealPoint2D(rPoint) );
194cdf0e10cSrcweir 
195cdf0e10cSrcweir             ::basegfx::B2DHomMatrix aMatrix;
196cdf0e10cSrcweir             aPoint *= ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
197cdf0e10cSrcweir                                                                    rViewState,
198cdf0e10cSrcweir                                                                    rRenderState);
199cdf0e10cSrcweir 
200cdf0e10cSrcweir             return ::vcl::unotools::pointFromB2DPoint( aPoint );
201cdf0e10cSrcweir         }
202cdf0e10cSrcweir 
mapPolyPolygon(const::basegfx::B2DPolyPolygon & rPoly,const rendering::ViewState & rViewState,const rendering::RenderState & rRenderState)203cdf0e10cSrcweir         ::PolyPolygon mapPolyPolygon( const ::basegfx::B2DPolyPolygon& 	rPoly,
204cdf0e10cSrcweir                                       const rendering::ViewState& 		rViewState,
205cdf0e10cSrcweir                                       const rendering::RenderState&		rRenderState )
206cdf0e10cSrcweir         {
207cdf0e10cSrcweir             ::basegfx::B2DHomMatrix aMatrix;
208cdf0e10cSrcweir             ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
209cdf0e10cSrcweir                                                          rViewState,
210cdf0e10cSrcweir                                                          rRenderState);
211cdf0e10cSrcweir 
212cdf0e10cSrcweir             ::basegfx::B2DPolyPolygon aTemp( rPoly );
213cdf0e10cSrcweir 
214cdf0e10cSrcweir             aTemp.transform( aMatrix );
215cdf0e10cSrcweir 
216cdf0e10cSrcweir             return ::PolyPolygon( aTemp );
217cdf0e10cSrcweir         }
218cdf0e10cSrcweir 
transformBitmap(const BitmapEx & rBitmap,const::basegfx::B2DHomMatrix & rTransform,const uno::Sequence<double> & rDeviceColor,ModulationMode eModulationMode)219cdf0e10cSrcweir         ::BitmapEx transformBitmap( const BitmapEx& 				rBitmap,
220cdf0e10cSrcweir                                     const ::basegfx::B2DHomMatrix& 	rTransform,
221cdf0e10cSrcweir                                     const uno::Sequence< double >&	rDeviceColor,
222cdf0e10cSrcweir                                     ModulationMode					eModulationMode )
223cdf0e10cSrcweir         {
224cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::tools::transformBitmap()" );
225cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::vclcanvas::tools::transformBitmap: 0x%X", &rBitmap );
226cdf0e10cSrcweir 
227cdf0e10cSrcweir             // calc transformation and size of bitmap to be
228cdf0e10cSrcweir             // generated. Note, that the translational components are
229cdf0e10cSrcweir             // deleted from the transformation; this can be handled by
230cdf0e10cSrcweir             // an offset when painting the bitmap
231cdf0e10cSrcweir             const Size 					aBmpSize( rBitmap.GetSizePixel() );
232cdf0e10cSrcweir             ::basegfx::B2DRectangle		aDestRect;
233cdf0e10cSrcweir 
234cdf0e10cSrcweir             bool bCopyBack( false );
235cdf0e10cSrcweir 
236cdf0e10cSrcweir             // calc effective transformation for bitmap
237cdf0e10cSrcweir             const ::basegfx::B2DRectangle aSrcRect( 0, 0,
238cdf0e10cSrcweir                                                     aBmpSize.Width(),
239cdf0e10cSrcweir                                                     aBmpSize.Height() );
240cdf0e10cSrcweir             ::canvas::tools::calcTransformedRectBounds( aDestRect,
241cdf0e10cSrcweir                                                         aSrcRect,
242cdf0e10cSrcweir                                                         rTransform );
243cdf0e10cSrcweir 
244cdf0e10cSrcweir             // re-center bitmap, such that it's left, top border is
245cdf0e10cSrcweir             // aligned with (0,0). The method takes the given
246cdf0e10cSrcweir             // rectangle, and calculates a transformation that maps
247cdf0e10cSrcweir             // this rectangle unscaled to the origin.
248cdf0e10cSrcweir             ::basegfx::B2DHomMatrix aLocalTransform;
249cdf0e10cSrcweir             ::canvas::tools::calcRectToOriginTransform( aLocalTransform,
250cdf0e10cSrcweir                                                         aSrcRect,
251cdf0e10cSrcweir                                                         rTransform );
252cdf0e10cSrcweir 
253cdf0e10cSrcweir             const bool bModulateColors( eModulationMode == MODULATE_WITH_DEVICECOLOR &&
254cdf0e10cSrcweir                                         rDeviceColor.getLength() > 2 );
255cdf0e10cSrcweir             const double nRedModulation( bModulateColors ? rDeviceColor[0] : 1.0 );
256cdf0e10cSrcweir             const double nGreenModulation( bModulateColors ? rDeviceColor[1] : 1.0 );
257cdf0e10cSrcweir             const double nBlueModulation( bModulateColors ? rDeviceColor[2] : 1.0 );
258cdf0e10cSrcweir             const double nAlphaModulation( bModulateColors && rDeviceColor.getLength() > 3 ?
259cdf0e10cSrcweir                                            rDeviceColor[3] : 1.0 );
260cdf0e10cSrcweir 
261cdf0e10cSrcweir             Bitmap aSrcBitmap( rBitmap.GetBitmap() );
262cdf0e10cSrcweir             Bitmap aSrcAlpha;
263cdf0e10cSrcweir 
264cdf0e10cSrcweir             // differentiate mask and alpha channel (on-off
265cdf0e10cSrcweir             // vs. multi-level transparency)
266cdf0e10cSrcweir             if( rBitmap.IsTransparent() )
267cdf0e10cSrcweir             {
268cdf0e10cSrcweir                 if( rBitmap.IsAlpha() )
269cdf0e10cSrcweir                     aSrcAlpha = rBitmap.GetAlpha().GetBitmap();
270cdf0e10cSrcweir                 else
271cdf0e10cSrcweir                     aSrcAlpha = rBitmap.GetMask();
272cdf0e10cSrcweir             }
273cdf0e10cSrcweir 
274cdf0e10cSrcweir             ScopedBitmapReadAccess pReadAccess( aSrcBitmap.AcquireReadAccess(),
275cdf0e10cSrcweir                                                 aSrcBitmap );
276cdf0e10cSrcweir             ScopedBitmapReadAccess pAlphaReadAccess( rBitmap.IsTransparent() ?
277cdf0e10cSrcweir                                                      aSrcAlpha.AcquireReadAccess() :
278cdf0e10cSrcweir                                                      (BitmapReadAccess*)NULL,
279cdf0e10cSrcweir                                                      aSrcAlpha );
280cdf0e10cSrcweir 
281cdf0e10cSrcweir             if( pReadAccess.get() == NULL ||
282cdf0e10cSrcweir                 (pAlphaReadAccess.get() == NULL && rBitmap.IsTransparent()) )
283cdf0e10cSrcweir             {
284cdf0e10cSrcweir                 // TODO(E2): Error handling!
285cdf0e10cSrcweir                 ENSURE_OR_THROW( false,
286cdf0e10cSrcweir                                   "transformBitmap(): could not access source bitmap" );
287cdf0e10cSrcweir             }
288cdf0e10cSrcweir 
289cdf0e10cSrcweir             // mapping table, to translate pAlphaReadAccess' pixel
290cdf0e10cSrcweir             // values into destination alpha values (needed e.g. for
291cdf0e10cSrcweir             // paletted 1-bit masks).
292cdf0e10cSrcweir             sal_uInt8 aAlphaMap[256];
293cdf0e10cSrcweir 
294cdf0e10cSrcweir             if( rBitmap.IsTransparent() )
295cdf0e10cSrcweir             {
296cdf0e10cSrcweir                 if( rBitmap.IsAlpha() )
297cdf0e10cSrcweir                 {
298cdf0e10cSrcweir                     // source already has alpha channel - 1:1 mapping,
299cdf0e10cSrcweir                     // i.e. aAlphaMap[0]=0,...,aAlphaMap[255]=255.
300*83d0117dSHerbert Dürr                     sal_uInt8* p = aAlphaMap;
301*83d0117dSHerbert Dürr                     for( int n = 0; n < 256; ++n) *(p++) = n;
302cdf0e10cSrcweir                 }
303cdf0e10cSrcweir                 else
304cdf0e10cSrcweir                 {
305cdf0e10cSrcweir                     // mask transparency - determine used palette colors
306cdf0e10cSrcweir                     const BitmapColor& rCol0( pAlphaReadAccess->GetPaletteColor( 0 ) );
307cdf0e10cSrcweir                     const BitmapColor& rCol1( pAlphaReadAccess->GetPaletteColor( 1 ) );
308cdf0e10cSrcweir 
309cdf0e10cSrcweir                     // shortcut for true luminance calculation
310cdf0e10cSrcweir                     // (assumes that palette is grey-level)
311cdf0e10cSrcweir                     aAlphaMap[0] = rCol0.GetRed();
312cdf0e10cSrcweir                     aAlphaMap[1] = rCol1.GetRed();
313cdf0e10cSrcweir                 }
314cdf0e10cSrcweir             }
315cdf0e10cSrcweir             // else: mapping table is not used
316cdf0e10cSrcweir 
317cdf0e10cSrcweir             const Size aDestBmpSize( ::basegfx::fround( aDestRect.getWidth() ),
318cdf0e10cSrcweir                                      ::basegfx::fround( aDestRect.getHeight() ) );
319cdf0e10cSrcweir 
320cdf0e10cSrcweir             if( aDestBmpSize.Width() == 0 || aDestBmpSize.Height() == 0 )
321cdf0e10cSrcweir                 return BitmapEx();
322cdf0e10cSrcweir 
323cdf0e10cSrcweir             Bitmap aDstBitmap( aDestBmpSize, aSrcBitmap.GetBitCount(), &pReadAccess->GetPalette() );
324cdf0e10cSrcweir             Bitmap aDstAlpha( AlphaMask( aDestBmpSize ).GetBitmap() );
325cdf0e10cSrcweir 
326cdf0e10cSrcweir             {
327cdf0e10cSrcweir                 // just to be on the safe side: let the
328cdf0e10cSrcweir                 // ScopedAccessors get destructed before
329cdf0e10cSrcweir                 // copy-constructing the resulting bitmap. This will
330cdf0e10cSrcweir                 // rule out the possibility that cached accessor data
331cdf0e10cSrcweir                 // is not yet written back.
332cdf0e10cSrcweir                 ScopedBitmapWriteAccess pWriteAccess( aDstBitmap.AcquireWriteAccess(),
333cdf0e10cSrcweir                                                       aDstBitmap );
334cdf0e10cSrcweir                 ScopedBitmapWriteAccess pAlphaWriteAccess( aDstAlpha.AcquireWriteAccess(),
335cdf0e10cSrcweir                                                            aDstAlpha );
336cdf0e10cSrcweir 
337cdf0e10cSrcweir 
338cdf0e10cSrcweir                 if( pWriteAccess.get() != NULL &&
339cdf0e10cSrcweir                     pAlphaWriteAccess.get() != NULL &&
340cdf0e10cSrcweir                     rTransform.isInvertible() )
341cdf0e10cSrcweir                 {
342cdf0e10cSrcweir                     // we're doing inverse mapping here, i.e. mapping
343cdf0e10cSrcweir                     // points from the destination bitmap back to the
344cdf0e10cSrcweir                     // source
345cdf0e10cSrcweir                     ::basegfx::B2DHomMatrix aTransform( aLocalTransform );
346cdf0e10cSrcweir                     aTransform.invert();
347cdf0e10cSrcweir 
348cdf0e10cSrcweir                     // for the time being, always read as ARGB
349cdf0e10cSrcweir                     for( int y=0; y<aDestBmpSize.Height(); ++y )
350cdf0e10cSrcweir                     {
351cdf0e10cSrcweir                         if( bModulateColors )
352cdf0e10cSrcweir                         {
353cdf0e10cSrcweir                             // TODO(P2): Have different branches for
354cdf0e10cSrcweir                             // alpha-only modulation (color
355cdf0e10cSrcweir                             // modulations eq. 1.0)
356cdf0e10cSrcweir 
357cdf0e10cSrcweir                             // modulate all color channels with given
358cdf0e10cSrcweir                             // values
359cdf0e10cSrcweir 
360cdf0e10cSrcweir                             // differentiate mask and alpha channel (on-off
361cdf0e10cSrcweir                             // vs. multi-level transparency)
362cdf0e10cSrcweir                             if( rBitmap.IsTransparent() )
363cdf0e10cSrcweir                             {
364cdf0e10cSrcweir                                 // Handling alpha and mask just the same...
365cdf0e10cSrcweir                                 for( int x=0; x<aDestBmpSize.Width(); ++x )
366cdf0e10cSrcweir                                 {
367cdf0e10cSrcweir                                     ::basegfx::B2DPoint aPoint(x,y);
368cdf0e10cSrcweir                                     aPoint *= aTransform;
369cdf0e10cSrcweir 
370cdf0e10cSrcweir                                     const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
371cdf0e10cSrcweir                                     const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
372cdf0e10cSrcweir                                     if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
373cdf0e10cSrcweir                                         nSrcY < 0 || nSrcY >= aBmpSize.Height() )
374cdf0e10cSrcweir                                     {
375cdf0e10cSrcweir                                         pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
376cdf0e10cSrcweir                                     }
377cdf0e10cSrcweir                                     else
378cdf0e10cSrcweir                                     {
379cdf0e10cSrcweir                                         // modulate alpha with
380cdf0e10cSrcweir                                         // nAlphaModulation. This is a
381cdf0e10cSrcweir                                         // little bit verbose, formula
382cdf0e10cSrcweir                                         // is 255 - (255-pixAlpha)*nAlphaModulation
383cdf0e10cSrcweir                                         // (invert 'alpha' pixel value,
384cdf0e10cSrcweir                                         // to get the standard alpha
385cdf0e10cSrcweir                                         // channel behaviour)
38687bc88d3SHerbert Dürr                                         const sal_uInt8 cMappedAlphaIdx = aAlphaMap[ pAlphaReadAccess->GetPixelIndex( nSrcY, nSrcX ) ];
38787bc88d3SHerbert Dürr                                         const sal_uInt8 cModulatedAlphaIdx = 255U - static_cast<sal_uInt8>( nAlphaModulation* (255U - cMappedAlphaIdx) + .5 );
38887bc88d3SHerbert Dürr                                         pAlphaWriteAccess->SetPixelIndex( y, x, cModulatedAlphaIdx );
38987bc88d3SHerbert Dürr                                         BitmapColor aColor( pReadAccess->GetPixel( nSrcY, nSrcX ) );
390cdf0e10cSrcweir 
391cdf0e10cSrcweir                                         aColor.SetRed(
392cdf0e10cSrcweir                                             static_cast<sal_uInt8>(
393cdf0e10cSrcweir                                                 nRedModulation *
394cdf0e10cSrcweir                                                 aColor.GetRed() + .5 ));
395cdf0e10cSrcweir                                         aColor.SetGreen(
396cdf0e10cSrcweir                                             static_cast<sal_uInt8>(
397cdf0e10cSrcweir                                                 nGreenModulation *
398cdf0e10cSrcweir                                                 aColor.GetGreen() + .5 ));
399cdf0e10cSrcweir                                         aColor.SetBlue(
400cdf0e10cSrcweir                                             static_cast<sal_uInt8>(
401cdf0e10cSrcweir                                                 nBlueModulation *
402cdf0e10cSrcweir                                                 aColor.GetBlue() + .5 ));
403cdf0e10cSrcweir 
404cdf0e10cSrcweir                                         pWriteAccess->SetPixel( y, x,
405cdf0e10cSrcweir                                                                 aColor );
406cdf0e10cSrcweir                                     }
407cdf0e10cSrcweir                                 }
408cdf0e10cSrcweir                             }
409cdf0e10cSrcweir                             else
410cdf0e10cSrcweir                             {
411cdf0e10cSrcweir                                 for( int x=0; x<aDestBmpSize.Width(); ++x )
412cdf0e10cSrcweir                                 {
413cdf0e10cSrcweir                                     ::basegfx::B2DPoint aPoint(x,y);
414cdf0e10cSrcweir                                     aPoint *= aTransform;
415cdf0e10cSrcweir 
416cdf0e10cSrcweir                                     const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
417cdf0e10cSrcweir                                     const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
418cdf0e10cSrcweir                                     if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
419cdf0e10cSrcweir                                         nSrcY < 0 || nSrcY >= aBmpSize.Height() )
420cdf0e10cSrcweir                                     {
421cdf0e10cSrcweir                                         pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
422cdf0e10cSrcweir                                     }
423cdf0e10cSrcweir                                     else
424cdf0e10cSrcweir                                     {
425cdf0e10cSrcweir                                         // modulate alpha with
426cdf0e10cSrcweir                                         // nAlphaModulation. This is a
427cdf0e10cSrcweir                                         // little bit verbose, formula
428cdf0e10cSrcweir                                         // is 255 - 255*nAlphaModulation
429cdf0e10cSrcweir                                         // (invert 'alpha' pixel value,
430cdf0e10cSrcweir                                         // to get the standard alpha
431cdf0e10cSrcweir                                         // channel behaviour)
432cdf0e10cSrcweir                                         pAlphaWriteAccess->SetPixel( y, x,
433cdf0e10cSrcweir                                                                      BitmapColor(
434cdf0e10cSrcweir                                                                          255U -
435cdf0e10cSrcweir                                                                          static_cast<sal_uInt8>(
436cdf0e10cSrcweir                                                                              nAlphaModulation*255.0
437cdf0e10cSrcweir                                                                              + .5 ) ) );
438cdf0e10cSrcweir 
439cdf0e10cSrcweir                                         BitmapColor aColor( pReadAccess->GetPixel( nSrcY,
440cdf0e10cSrcweir                                                                                    nSrcX ) );
441cdf0e10cSrcweir 
442cdf0e10cSrcweir                                         aColor.SetRed(
443cdf0e10cSrcweir                                             static_cast<sal_uInt8>(
444cdf0e10cSrcweir                                                 nRedModulation *
445cdf0e10cSrcweir                                                 aColor.GetRed() + .5 ));
446cdf0e10cSrcweir                                         aColor.SetGreen(
447cdf0e10cSrcweir                                             static_cast<sal_uInt8>(
448cdf0e10cSrcweir                                                 nGreenModulation *
449cdf0e10cSrcweir                                                 aColor.GetGreen() + .5 ));
450cdf0e10cSrcweir                                         aColor.SetBlue(
451cdf0e10cSrcweir                                             static_cast<sal_uInt8>(
452cdf0e10cSrcweir                                                 nBlueModulation *
453cdf0e10cSrcweir                                                 aColor.GetBlue() + .5 ));
454cdf0e10cSrcweir 
455cdf0e10cSrcweir                                         pWriteAccess->SetPixel( y, x,
456cdf0e10cSrcweir                                                                 aColor );
457cdf0e10cSrcweir                                     }
458cdf0e10cSrcweir                                 }
459cdf0e10cSrcweir                             }
460cdf0e10cSrcweir                         }
461cdf0e10cSrcweir                         else
462cdf0e10cSrcweir                         {
463cdf0e10cSrcweir                             // differentiate mask and alpha channel (on-off
464cdf0e10cSrcweir                             // vs. multi-level transparency)
465cdf0e10cSrcweir                             if( rBitmap.IsTransparent() )
466cdf0e10cSrcweir                             {
467cdf0e10cSrcweir                                 // Handling alpha and mask just the same...
468cdf0e10cSrcweir                                 for( int x=0; x<aDestBmpSize.Width(); ++x )
469cdf0e10cSrcweir                                 {
470cdf0e10cSrcweir                                     ::basegfx::B2DPoint aPoint(x,y);
471cdf0e10cSrcweir                                     aPoint *= aTransform;
472cdf0e10cSrcweir 
473cdf0e10cSrcweir                                     const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
474cdf0e10cSrcweir                                     const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
475cdf0e10cSrcweir                                     if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
476cdf0e10cSrcweir                                         nSrcY < 0 || nSrcY >= aBmpSize.Height() )
477cdf0e10cSrcweir                                     {
47887bc88d3SHerbert Dürr                                         pAlphaWriteAccess->SetPixelIndex( y, x, 255 );
479cdf0e10cSrcweir                                     }
480cdf0e10cSrcweir                                     else
481cdf0e10cSrcweir                                     {
48287bc88d3SHerbert Dürr                                         const sal_uInt8 cAlphaIdx = pAlphaReadAccess->GetPixelIndex( nSrcY, nSrcX );
48387bc88d3SHerbert Dürr                                         pAlphaWriteAccess->SetPixelIndex( y, x, aAlphaMap[ cAlphaIdx ] );
48487bc88d3SHerbert Dürr                                         pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY, nSrcX ) );
485cdf0e10cSrcweir                                     }
486cdf0e10cSrcweir                                 }
487cdf0e10cSrcweir                             }
488cdf0e10cSrcweir                             else
489cdf0e10cSrcweir                             {
490cdf0e10cSrcweir                                 for( int x=0; x<aDestBmpSize.Width(); ++x )
491cdf0e10cSrcweir                                 {
492cdf0e10cSrcweir                                     ::basegfx::B2DPoint aPoint(x,y);
493cdf0e10cSrcweir                                     aPoint *= aTransform;
494cdf0e10cSrcweir 
495cdf0e10cSrcweir                                     const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
496cdf0e10cSrcweir                                     const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
497cdf0e10cSrcweir                                     if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
498cdf0e10cSrcweir                                         nSrcY < 0 || nSrcY >= aBmpSize.Height() )
499cdf0e10cSrcweir                                     {
500cdf0e10cSrcweir                                         pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
501cdf0e10cSrcweir                                     }
502cdf0e10cSrcweir                                     else
503cdf0e10cSrcweir                                     {
504cdf0e10cSrcweir                                         pAlphaWriteAccess->SetPixel( y, x, BitmapColor(0) );
505cdf0e10cSrcweir                                         pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY,
506cdf0e10cSrcweir                                                                                              nSrcX ) );
507cdf0e10cSrcweir                                     }
508cdf0e10cSrcweir                                 }
509cdf0e10cSrcweir                             }
510cdf0e10cSrcweir                         }
511cdf0e10cSrcweir                     }
512cdf0e10cSrcweir 
513cdf0e10cSrcweir                     bCopyBack = true;
514cdf0e10cSrcweir                 }
515cdf0e10cSrcweir                 else
516cdf0e10cSrcweir                 {
517cdf0e10cSrcweir                     // TODO(E2): Error handling!
518cdf0e10cSrcweir                     ENSURE_OR_THROW( false,
519cdf0e10cSrcweir                                       "transformBitmap(): could not access bitmap" );
520cdf0e10cSrcweir                 }
521cdf0e10cSrcweir             }
522cdf0e10cSrcweir 
523cdf0e10cSrcweir             if( bCopyBack )
524cdf0e10cSrcweir                 return BitmapEx( aDstBitmap, AlphaMask( aDstAlpha ) );
525cdf0e10cSrcweir             else
526cdf0e10cSrcweir                 return BitmapEx();
527cdf0e10cSrcweir         }
528cdf0e10cSrcweir     }
529cdf0e10cSrcweir }
530