1*25ea7f45SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*25ea7f45SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*25ea7f45SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*25ea7f45SAndrew Rist  * distributed with this work for additional information
6*25ea7f45SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*25ea7f45SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*25ea7f45SAndrew Rist  * "License"); you may not use this file except in compliance
9*25ea7f45SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*25ea7f45SAndrew Rist  *
11*25ea7f45SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*25ea7f45SAndrew Rist  *
13*25ea7f45SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*25ea7f45SAndrew Rist  * software distributed under the License is distributed on an
15*25ea7f45SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*25ea7f45SAndrew Rist  * KIND, either express or implied.  See the License for the
17*25ea7f45SAndrew Rist  * specific language governing permissions and limitations
18*25ea7f45SAndrew Rist  * under the License.
19*25ea7f45SAndrew Rist  *
20*25ea7f45SAndrew Rist  *************************************************************/
21*25ea7f45SAndrew Rist 
22*25ea7f45SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_canvas.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <ctype.h> // don't ask. msdev breaks otherwise...
28cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <canvas/debug.hxx>
31cdf0e10cSrcweir #include <canvas/verbosetrace.hxx>
32cdf0e10cSrcweir #include <tools/diagnose_ex.h>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <com/sun/star/lang/XServiceInfo.hpp>
35cdf0e10cSrcweir #include <com/sun/star/lang/XUnoTunnel.hpp>
36cdf0e10cSrcweir #include <com/sun/star/geometry/RealPoint2D.hpp>
37cdf0e10cSrcweir #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
40cdf0e10cSrcweir #include <basegfx/range/b2irectangle.hxx>
41cdf0e10cSrcweir #include <basegfx/range/b2drectangle.hxx>
42cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
43cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygon.hxx>
44cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
45cdf0e10cSrcweir 
46cdf0e10cSrcweir #include <canvas/canvastools.hxx>
47cdf0e10cSrcweir #include <canvas/verifyinput.hxx>
48cdf0e10cSrcweir 
49cdf0e10cSrcweir #include "dx_impltools.hxx"
50cdf0e10cSrcweir #include "dx_vcltools.hxx"
51cdf0e10cSrcweir #include "dx_linepolypolygon.hxx"
52cdf0e10cSrcweir #include "dx_canvasbitmap.hxx"
53cdf0e10cSrcweir #include "dx_canvasfont.hxx"
54cdf0e10cSrcweir #include "dx_canvas.hxx"
55cdf0e10cSrcweir #include "dx_spritecanvas.hxx"
56cdf0e10cSrcweir 
57cdf0e10cSrcweir #include <boost/scoped_array.hpp>
58cdf0e10cSrcweir 
59cdf0e10cSrcweir #include <vector>
60cdf0e10cSrcweir #include <algorithm>
61cdf0e10cSrcweir 
62cdf0e10cSrcweir 
63cdf0e10cSrcweir using namespace ::com::sun::star;
64cdf0e10cSrcweir 
65cdf0e10cSrcweir 
66cdf0e10cSrcweir namespace dxcanvas
67cdf0e10cSrcweir {
68cdf0e10cSrcweir     namespace tools
69cdf0e10cSrcweir     {
polyPolygonFromXPolyPolygon2D(const uno::Reference<rendering::XPolyPolygon2D> & xPoly)70cdf0e10cSrcweir         ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly )
71cdf0e10cSrcweir         {
72cdf0e10cSrcweir             LinePolyPolygon* pPolyImpl = dynamic_cast< LinePolyPolygon* >( xPoly.get() );
73cdf0e10cSrcweir 
74cdf0e10cSrcweir             if( pPolyImpl )
75cdf0e10cSrcweir             {
76cdf0e10cSrcweir                 return pPolyImpl->getPolyPolygon();
77cdf0e10cSrcweir             }
78cdf0e10cSrcweir             else
79cdf0e10cSrcweir             {
80cdf0e10cSrcweir                 const sal_Int32 nPolys( xPoly->getNumberOfPolygons() );
81cdf0e10cSrcweir 
82cdf0e10cSrcweir                 // not a known implementation object - try data source
83cdf0e10cSrcweir                 // interfaces
84cdf0e10cSrcweir                 uno::Reference< rendering::XBezierPolyPolygon2D > xBezierPoly(
85cdf0e10cSrcweir                     xPoly,
86cdf0e10cSrcweir                     uno::UNO_QUERY );
87cdf0e10cSrcweir 
88cdf0e10cSrcweir                 if( xBezierPoly.is() )
89cdf0e10cSrcweir                 {
90cdf0e10cSrcweir                     return ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(
91cdf0e10cSrcweir                         xBezierPoly->getBezierSegments( 0,
92cdf0e10cSrcweir                                                         nPolys,
93cdf0e10cSrcweir                                                         0,
94cdf0e10cSrcweir                                                         -1 ) );
95cdf0e10cSrcweir                 }
96cdf0e10cSrcweir                 else
97cdf0e10cSrcweir                 {
98cdf0e10cSrcweir                     uno::Reference< rendering::XLinePolyPolygon2D > xLinePoly(
99cdf0e10cSrcweir                         xPoly,
100cdf0e10cSrcweir                         uno::UNO_QUERY );
101cdf0e10cSrcweir 
102cdf0e10cSrcweir                     // no implementation class and no data provider
103cdf0e10cSrcweir                     // found - contract violation.
104cdf0e10cSrcweir                     ENSURE_ARG_OR_THROW( xLinePoly.is(),
105cdf0e10cSrcweir                                      "VCLCanvas::polyPolygonFromXPolyPolygon2D(): Invalid input "
106cdf0e10cSrcweir                                      "poly-polygon, cannot retrieve vertex data" );
107cdf0e10cSrcweir 
108cdf0e10cSrcweir                     return ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence(
109cdf0e10cSrcweir                         xLinePoly->getPoints( 0,
110cdf0e10cSrcweir                                               nPolys,
111cdf0e10cSrcweir                                               0,
112cdf0e10cSrcweir                                               -1 ) );
113cdf0e10cSrcweir                 }
114cdf0e10cSrcweir             }
115cdf0e10cSrcweir         }
116cdf0e10cSrcweir 
setupGraphics(Gdiplus::Graphics & rGraphics)117cdf0e10cSrcweir         void setupGraphics( Gdiplus::Graphics& rGraphics )
118cdf0e10cSrcweir         {
119cdf0e10cSrcweir             // setup graphics with (somewhat arbitrary) defaults
120cdf0e10cSrcweir             //rGraphics.SetCompositingQuality( Gdiplus::CompositingQualityHighQuality );
121cdf0e10cSrcweir             rGraphics.SetCompositingQuality( Gdiplus::CompositingQualityHighSpeed );
122cdf0e10cSrcweir             //rGraphics.SetInterpolationMode( Gdiplus::InterpolationModeHighQualityBilinear ); // with prefiltering for shrinks
123cdf0e10cSrcweir             rGraphics.SetInterpolationMode( Gdiplus::InterpolationModeBilinear );
124cdf0e10cSrcweir 
125cdf0e10cSrcweir             // #122683# Switched precedence of pixel offset
126cdf0e10cSrcweir             // mode. Seemingly, polygon stroking needs
127cdf0e10cSrcweir             // PixelOffsetModeNone to achieve visually pleasing
128cdf0e10cSrcweir             // results, whereas all other operations (e.g. polygon
129cdf0e10cSrcweir             // fills, bitmaps) look better with PixelOffsetModeHalf.
130cdf0e10cSrcweir             rGraphics.SetPixelOffsetMode( Gdiplus::PixelOffsetModeHalf ); // Pixel center at (0.5, 0.5) etc.
131cdf0e10cSrcweir             //rGraphics.SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
132cdf0e10cSrcweir 
133cdf0e10cSrcweir             //rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeHighSpeed ); // no line/curve antialiasing
134cdf0e10cSrcweir             //rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeHighQuality );
135cdf0e10cSrcweir             rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeAntiAlias );
136cdf0e10cSrcweir             //rGraphics.SetTextRenderingHint( Gdiplus::TextRenderingHintAntiAlias );
137cdf0e10cSrcweir             rGraphics.SetTextRenderingHint( Gdiplus::TextRenderingHintSystemDefault );
138cdf0e10cSrcweir 			rGraphics.SetPageUnit(Gdiplus::UnitPixel);
139cdf0e10cSrcweir         }
140cdf0e10cSrcweir 
createGraphicsFromHDC(HDC aHDC)141cdf0e10cSrcweir         Gdiplus::Graphics* createGraphicsFromHDC(HDC aHDC)
142cdf0e10cSrcweir         {
143cdf0e10cSrcweir             Gdiplus::Graphics* pRet = new Gdiplus::Graphics(aHDC);
144cdf0e10cSrcweir 			if( pRet )
145cdf0e10cSrcweir                 setupGraphics( *pRet );
146cdf0e10cSrcweir             return pRet;
147cdf0e10cSrcweir         }
148cdf0e10cSrcweir 
createGraphicsFromBitmap(const BitmapSharedPtr & rBitmap)149cdf0e10cSrcweir         Gdiplus::Graphics* createGraphicsFromBitmap(const BitmapSharedPtr& rBitmap)
150cdf0e10cSrcweir         {
151cdf0e10cSrcweir             Gdiplus::Graphics* pRet = Gdiplus::Graphics::FromImage(rBitmap.get());
152cdf0e10cSrcweir             if( pRet )
153cdf0e10cSrcweir                 setupGraphics( *pRet );
154cdf0e10cSrcweir             return pRet;
155cdf0e10cSrcweir         }
156cdf0e10cSrcweir 
gdiPlusMatrixFromB2DHomMatrix(Gdiplus::Matrix & rGdiplusMatrix,const::basegfx::B2DHomMatrix & rMatrix)157cdf0e10cSrcweir         void gdiPlusMatrixFromB2DHomMatrix( Gdiplus::Matrix& rGdiplusMatrix, const ::basegfx::B2DHomMatrix& rMatrix )
158cdf0e10cSrcweir         {
159cdf0e10cSrcweir             rGdiplusMatrix.SetElements( static_cast<Gdiplus::REAL>(rMatrix.get(0,0)),
160cdf0e10cSrcweir                                         static_cast<Gdiplus::REAL>(rMatrix.get(1,0)),
161cdf0e10cSrcweir                                         static_cast<Gdiplus::REAL>(rMatrix.get(0,1)),
162cdf0e10cSrcweir                                         static_cast<Gdiplus::REAL>(rMatrix.get(1,1)),
163cdf0e10cSrcweir                                         static_cast<Gdiplus::REAL>(rMatrix.get(0,2)),
164cdf0e10cSrcweir                                         static_cast<Gdiplus::REAL>(rMatrix.get(1,2)) );
165cdf0e10cSrcweir         }
166cdf0e10cSrcweir 
gdiPlusMatrixFromAffineMatrix2D(Gdiplus::Matrix & rGdiplusMatrix,const geometry::AffineMatrix2D & rMatrix)167cdf0e10cSrcweir         void gdiPlusMatrixFromAffineMatrix2D( Gdiplus::Matrix& 					rGdiplusMatrix,
168cdf0e10cSrcweir                                               const geometry::AffineMatrix2D&	rMatrix )
169cdf0e10cSrcweir         {
170cdf0e10cSrcweir             rGdiplusMatrix.SetElements( static_cast<Gdiplus::REAL>(rMatrix.m00),
171cdf0e10cSrcweir                                         static_cast<Gdiplus::REAL>(rMatrix.m10),
172cdf0e10cSrcweir                                         static_cast<Gdiplus::REAL>(rMatrix.m01),
173cdf0e10cSrcweir                                         static_cast<Gdiplus::REAL>(rMatrix.m11),
174cdf0e10cSrcweir                                         static_cast<Gdiplus::REAL>(rMatrix.m02),
175cdf0e10cSrcweir                                         static_cast<Gdiplus::REAL>(rMatrix.m12) );
176cdf0e10cSrcweir         }
177cdf0e10cSrcweir 
178cdf0e10cSrcweir         namespace
179cdf0e10cSrcweir         {
180cdf0e10cSrcweir             // TODO(P2): Check whether this gets inlined. If not, make functor
181cdf0e10cSrcweir             // out of it
implGdiPlusPointFromRealPoint2D(const::com::sun::star::geometry::RealPoint2D & rPoint)182cdf0e10cSrcweir             inline Gdiplus::PointF implGdiPlusPointFromRealPoint2D( const ::com::sun::star::geometry::RealPoint2D& rPoint )
183cdf0e10cSrcweir             {
184cdf0e10cSrcweir                 return Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.X),
185cdf0e10cSrcweir                                         static_cast<Gdiplus::REAL>(rPoint.Y) );
186cdf0e10cSrcweir             }
187cdf0e10cSrcweir 
graphicsPathFromB2DPolygon(GraphicsPathSharedPtr & rOutput,::std::vector<Gdiplus::PointF> & rPoints,const::basegfx::B2DPolygon & rPoly,bool bNoLineJoin)188cdf0e10cSrcweir             void graphicsPathFromB2DPolygon( GraphicsPathSharedPtr&             rOutput,
189cdf0e10cSrcweir                                              ::std::vector< Gdiplus::PointF >&  rPoints,
190cdf0e10cSrcweir                                              const ::basegfx::B2DPolygon&       rPoly,
191cdf0e10cSrcweir                                              bool bNoLineJoin)
192cdf0e10cSrcweir             {
193cdf0e10cSrcweir                 const sal_uInt32 nPoints( rPoly.count() );
194cdf0e10cSrcweir 
195cdf0e10cSrcweir                 if( nPoints < 2 )
196cdf0e10cSrcweir                     return;
197cdf0e10cSrcweir 
198cdf0e10cSrcweir                 rOutput->StartFigure();
199cdf0e10cSrcweir 
200cdf0e10cSrcweir                 const bool bClosedPolygon( rPoly.isClosed() );
201cdf0e10cSrcweir 
202cdf0e10cSrcweir                 if( rPoly.areControlPointsUsed() )
203cdf0e10cSrcweir                 {
204cdf0e10cSrcweir                     // control points used -> for now, add all
205cdf0e10cSrcweir                     // segments as curves to GraphicsPath
206cdf0e10cSrcweir 
207cdf0e10cSrcweir                     // If the polygon is closed, we need to add the
208cdf0e10cSrcweir                     // first point, thus, one more (can't simply
209cdf0e10cSrcweir                     // GraphicsPath::CloseFigure() it, since the last
210cdf0e10cSrcweir                     // point cannot have any control points for GDI+)
211cdf0e10cSrcweir                     rPoints.resize( 3*nPoints + bClosedPolygon );
212cdf0e10cSrcweir 
213cdf0e10cSrcweir                     sal_uInt32 nCurrOutput=0;
214cdf0e10cSrcweir                     for( sal_uInt32 nCurrPoint=0; nCurrPoint<nPoints; ++nCurrPoint )
215cdf0e10cSrcweir                     {
216cdf0e10cSrcweir                         const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint( nCurrPoint ) );
217cdf0e10cSrcweir                         rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
218cdf0e10cSrcweir                                                                   static_cast<Gdiplus::REAL>(rPoint.getY()) );
219cdf0e10cSrcweir 
220cdf0e10cSrcweir                         const ::basegfx::B2DPoint& rControlPointA( rPoly.getNextControlPoint( nCurrPoint ) );
221cdf0e10cSrcweir                         rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rControlPointA.getX()),
222cdf0e10cSrcweir                                                                   static_cast<Gdiplus::REAL>(rControlPointA.getY()) );
223cdf0e10cSrcweir 
224cdf0e10cSrcweir                         const ::basegfx::B2DPoint& rControlPointB( rPoly.getPrevControlPoint( (nCurrPoint + 1) % nPoints) );
225cdf0e10cSrcweir                         rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rControlPointB.getX()),
226cdf0e10cSrcweir                                                                   static_cast<Gdiplus::REAL>(rControlPointB.getY()) );
227cdf0e10cSrcweir                     }
228cdf0e10cSrcweir 
229cdf0e10cSrcweir                     if( bClosedPolygon )
230cdf0e10cSrcweir                     {
231cdf0e10cSrcweir                         // add first point again (to be able to pass
232cdf0e10cSrcweir                         // control points for the last point, see
233cdf0e10cSrcweir                         // above)
234cdf0e10cSrcweir                         const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint(0) );
235cdf0e10cSrcweir                         rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
236cdf0e10cSrcweir                                                                   static_cast<Gdiplus::REAL>(rPoint.getY()) );
237cdf0e10cSrcweir 
238cdf0e10cSrcweir                         if(bNoLineJoin && nCurrOutput > 7)
239cdf0e10cSrcweir                         {
240cdf0e10cSrcweir                             for(sal_uInt32 a(3); a < nCurrOutput; a+=3)
241cdf0e10cSrcweir                             {
242cdf0e10cSrcweir         				        rOutput->StartFigure();
243cdf0e10cSrcweir                                 rOutput->AddBezier(rPoints[a - 3], rPoints[a - 2], rPoints[a - 1], rPoints[a]);
244cdf0e10cSrcweir                             }
245cdf0e10cSrcweir                         }
246cdf0e10cSrcweir                         else
247cdf0e10cSrcweir                         {
248cdf0e10cSrcweir                             rOutput->AddBeziers( &rPoints[0], nCurrOutput );
249cdf0e10cSrcweir                         }
250cdf0e10cSrcweir                     }
251cdf0e10cSrcweir                     else
252cdf0e10cSrcweir                     {
253cdf0e10cSrcweir                         // GraphicsPath expects 3(n-1)+1 points (i.e. the
254cdf0e10cSrcweir                         // last point must not have any trailing control
255cdf0e10cSrcweir                         // points after it).
256cdf0e10cSrcweir                         // Therefore, simply don't pass the last two
257cdf0e10cSrcweir                         // points here.
258cdf0e10cSrcweir                         if( nCurrOutput > 3 )
259cdf0e10cSrcweir                         {
260cdf0e10cSrcweir                             if(bNoLineJoin && nCurrOutput > 7)
261cdf0e10cSrcweir                             {
262cdf0e10cSrcweir                                 for(sal_uInt32 a(3); a < nCurrOutput; a+=3)
263cdf0e10cSrcweir                                 {
264cdf0e10cSrcweir         				            rOutput->StartFigure();
265cdf0e10cSrcweir                                     rOutput->AddBezier(rPoints[a - 3], rPoints[a - 2], rPoints[a - 1], rPoints[a]);
266cdf0e10cSrcweir                                 }
267cdf0e10cSrcweir                             }
268cdf0e10cSrcweir                             else
269cdf0e10cSrcweir                             {
270cdf0e10cSrcweir                                 rOutput->AddBeziers( &rPoints[0], nCurrOutput-2 );
271cdf0e10cSrcweir                             }
272cdf0e10cSrcweir                         }
273cdf0e10cSrcweir                     }
274cdf0e10cSrcweir                 }
275cdf0e10cSrcweir                 else
276cdf0e10cSrcweir                 {
277cdf0e10cSrcweir                     // no control points -> no curves, simply add
278cdf0e10cSrcweir                     // straigt lines to GraphicsPath
279cdf0e10cSrcweir                     rPoints.resize( nPoints );
280cdf0e10cSrcweir 
281cdf0e10cSrcweir                     for( sal_uInt32 nCurrPoint=0; nCurrPoint<nPoints; ++nCurrPoint )
282cdf0e10cSrcweir                     {
283cdf0e10cSrcweir                         const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint( nCurrPoint ) );
284cdf0e10cSrcweir                         rPoints[nCurrPoint] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
285cdf0e10cSrcweir                                                                static_cast<Gdiplus::REAL>(rPoint.getY()) );
286cdf0e10cSrcweir                     }
287cdf0e10cSrcweir 
288cdf0e10cSrcweir                     if(bNoLineJoin && nPoints > 2)
289cdf0e10cSrcweir                     {
290cdf0e10cSrcweir                         for(sal_uInt32 a(1); a < nPoints; a++)
291cdf0e10cSrcweir                         {
292cdf0e10cSrcweir         				    rOutput->StartFigure();
293cdf0e10cSrcweir                             rOutput->AddLine(rPoints[a - 1], rPoints[a]);
294cdf0e10cSrcweir                         }
295cdf0e10cSrcweir 
296cdf0e10cSrcweir                         if(bClosedPolygon)
297cdf0e10cSrcweir                         {
298cdf0e10cSrcweir         				    rOutput->StartFigure();
299cdf0e10cSrcweir                             rOutput->AddLine(rPoints[nPoints - 1], rPoints[0]);
300cdf0e10cSrcweir                         }
301cdf0e10cSrcweir                     }
302cdf0e10cSrcweir                     else
303cdf0e10cSrcweir                     {
304cdf0e10cSrcweir                         rOutput->AddLines( &rPoints[0], nPoints );
305cdf0e10cSrcweir                     }
306cdf0e10cSrcweir                 }
307cdf0e10cSrcweir 
308cdf0e10cSrcweir                 if( bClosedPolygon && !bNoLineJoin )
309cdf0e10cSrcweir                     rOutput->CloseFigure();
310cdf0e10cSrcweir             }
311cdf0e10cSrcweir         }
312cdf0e10cSrcweir 
gdiPlusPointFromRealPoint2D(const::com::sun::star::geometry::RealPoint2D & rPoint)313cdf0e10cSrcweir         Gdiplus::PointF gdiPlusPointFromRealPoint2D( const ::com::sun::star::geometry::RealPoint2D& rPoint )
314cdf0e10cSrcweir         {
315cdf0e10cSrcweir             return implGdiPlusPointFromRealPoint2D( rPoint );
316cdf0e10cSrcweir         }
317cdf0e10cSrcweir 
gdiPlusRectFromIntegerRectangle2D(const geometry::IntegerRectangle2D & rRect)318cdf0e10cSrcweir         Gdiplus::Rect gdiPlusRectFromIntegerRectangle2D( const geometry::IntegerRectangle2D& rRect )
319cdf0e10cSrcweir         {
320cdf0e10cSrcweir             return Gdiplus::Rect( rRect.X1,
321cdf0e10cSrcweir                                   rRect.Y1,
322cdf0e10cSrcweir                                   rRect.X2 - rRect.X1,
323cdf0e10cSrcweir                                   rRect.Y2 - rRect.Y1 );
324cdf0e10cSrcweir         }
325cdf0e10cSrcweir 
gdiPlusRectFFromRectangle2D(const geometry::RealRectangle2D & rRect)326cdf0e10cSrcweir         Gdiplus::RectF gdiPlusRectFFromRectangle2D( const geometry::RealRectangle2D& rRect )
327cdf0e10cSrcweir         {
328cdf0e10cSrcweir             return Gdiplus::RectF( static_cast<Gdiplus::REAL>(rRect.X1),
329cdf0e10cSrcweir                                    static_cast<Gdiplus::REAL>(rRect.Y1),
330cdf0e10cSrcweir                                    static_cast<Gdiplus::REAL>(rRect.X2 - rRect.X1),
331cdf0e10cSrcweir                                    static_cast<Gdiplus::REAL>(rRect.Y2 - rRect.Y1) );
332cdf0e10cSrcweir         }
333cdf0e10cSrcweir 
gdiRectFromB2IRect(const::basegfx::B2IRange & rRect)334cdf0e10cSrcweir         RECT gdiRectFromB2IRect( const ::basegfx::B2IRange& rRect )
335cdf0e10cSrcweir         {
336cdf0e10cSrcweir             RECT aRect = {rRect.getMinX(),
337cdf0e10cSrcweir                           rRect.getMinY(),
338cdf0e10cSrcweir                           rRect.getMaxX(),
339cdf0e10cSrcweir                           rRect.getMaxY()};
340cdf0e10cSrcweir 
341cdf0e10cSrcweir             return aRect;
342cdf0e10cSrcweir         }
343cdf0e10cSrcweir 
realPoint2DFromGdiPlusPointF(const Gdiplus::PointF & rPoint)344cdf0e10cSrcweir         geometry::RealPoint2D realPoint2DFromGdiPlusPointF( const Gdiplus::PointF& rPoint )
345cdf0e10cSrcweir         {
346cdf0e10cSrcweir             return geometry::RealPoint2D( rPoint.X, rPoint.Y );
347cdf0e10cSrcweir         }
348cdf0e10cSrcweir 
realRectangle2DFromGdiPlusRectF(const Gdiplus::RectF & rRect)349cdf0e10cSrcweir         geometry::RealRectangle2D realRectangle2DFromGdiPlusRectF( const Gdiplus::RectF& rRect )
350cdf0e10cSrcweir         {
351cdf0e10cSrcweir             return geometry::RealRectangle2D( rRect.X, rRect.Y,
352cdf0e10cSrcweir                                               rRect.X + rRect.Width,
353cdf0e10cSrcweir                                               rRect.Y + rRect.Height );
354cdf0e10cSrcweir         }
355cdf0e10cSrcweir 
b2dPointFromGdiPlusPointF(const Gdiplus::PointF & rPoint)356cdf0e10cSrcweir         ::basegfx::B2DPoint	b2dPointFromGdiPlusPointF( const Gdiplus::PointF& rPoint )
357cdf0e10cSrcweir         {
358cdf0e10cSrcweir             return ::basegfx::B2DPoint( rPoint.X, rPoint.Y );
359cdf0e10cSrcweir         }
360cdf0e10cSrcweir 
b2dRangeFromGdiPlusRectF(const Gdiplus::RectF & rRect)361cdf0e10cSrcweir         ::basegfx::B2DRange	b2dRangeFromGdiPlusRectF( const Gdiplus::RectF& rRect )
362cdf0e10cSrcweir         {
363cdf0e10cSrcweir             return ::basegfx::B2DRange( rRect.X, rRect.Y,
364cdf0e10cSrcweir                                         rRect.X + rRect.Width,
365cdf0e10cSrcweir                                         rRect.Y + rRect.Height );
366cdf0e10cSrcweir         }
367cdf0e10cSrcweir 
argbToDoubleSequence(const Gdiplus::ARGB & rColor)368cdf0e10cSrcweir         uno::Sequence< double > argbToDoubleSequence( const Gdiplus::ARGB& rColor )
369cdf0e10cSrcweir         {
370cdf0e10cSrcweir             // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
371cdf0e10cSrcweir             uno::Sequence< double > aRet(4);
372cdf0e10cSrcweir 
373cdf0e10cSrcweir             aRet[0] = ((rColor >> 16) & 0xFF) / 255.0; 	// red
374cdf0e10cSrcweir             aRet[1] = ((rColor >> 8) & 0xFF) / 255.0;	// green
375cdf0e10cSrcweir             aRet[2] = (rColor & 0xFF) / 255.0;			// blue
376cdf0e10cSrcweir             aRet[3] = ((rColor >> 24) & 0xFF) / 255.0;	// alpha
377cdf0e10cSrcweir 
378cdf0e10cSrcweir             return aRet;
379cdf0e10cSrcweir         }
380cdf0e10cSrcweir 
argbToIntSequence(const Gdiplus::ARGB & rColor)381cdf0e10cSrcweir         uno::Sequence< sal_Int8 > argbToIntSequence( const Gdiplus::ARGB& rColor )
382cdf0e10cSrcweir         {
383cdf0e10cSrcweir             // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
384cdf0e10cSrcweir             uno::Sequence< sal_Int8 > aRet(4);
385cdf0e10cSrcweir 
386cdf0e10cSrcweir             aRet[0] = static_cast<sal_Int8>((rColor >> 16) & 0xFF);	// red
387cdf0e10cSrcweir             aRet[1] = static_cast<sal_Int8>((rColor >> 8) & 0xFF);	// green
388cdf0e10cSrcweir             aRet[2] = static_cast<sal_Int8>(rColor & 0xFF);			// blue
389cdf0e10cSrcweir             aRet[3] = static_cast<sal_Int8>((rColor >> 24) & 0xFF);	// alpha
390cdf0e10cSrcweir 
391cdf0e10cSrcweir             return aRet;
392cdf0e10cSrcweir         }
393cdf0e10cSrcweir 
sequenceToArgb(const uno::Sequence<sal_Int8> & rColor)394cdf0e10cSrcweir         Gdiplus::ARGB sequenceToArgb( const uno::Sequence< sal_Int8 >& rColor )
395cdf0e10cSrcweir         {
396cdf0e10cSrcweir             ENSURE_OR_THROW( rColor.getLength() > 2,
397cdf0e10cSrcweir                               "sequenceToArgb: need at least three channels" );
398cdf0e10cSrcweir 
399cdf0e10cSrcweir             // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
400cdf0e10cSrcweir             Gdiplus::ARGB aColor;
401cdf0e10cSrcweir 
402cdf0e10cSrcweir             aColor = (static_cast<sal_uInt8>(rColor[0]) << 16) | (static_cast<sal_uInt8>(rColor[1]) << 8) | static_cast<sal_uInt8>(rColor[2]);
403cdf0e10cSrcweir 
404cdf0e10cSrcweir             if( rColor.getLength() > 3 )
405cdf0e10cSrcweir                 aColor |= static_cast<sal_uInt8>(rColor[3]) << 24;
406cdf0e10cSrcweir 
407cdf0e10cSrcweir             return aColor;
408cdf0e10cSrcweir         }
409cdf0e10cSrcweir 
sequenceToArgb(const uno::Sequence<double> & rColor)410cdf0e10cSrcweir         Gdiplus::ARGB sequenceToArgb( const uno::Sequence< double >& rColor )
411cdf0e10cSrcweir         {
412cdf0e10cSrcweir             ENSURE_OR_THROW( rColor.getLength() > 2,
413cdf0e10cSrcweir                               "sequenceToColor: need at least three channels" );
414cdf0e10cSrcweir 
415cdf0e10cSrcweir             // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
416cdf0e10cSrcweir             Gdiplus::ARGB aColor;
417cdf0e10cSrcweir 
418cdf0e10cSrcweir             ::canvas::tools::verifyRange(rColor[0],0.0,1.0);
419cdf0e10cSrcweir             ::canvas::tools::verifyRange(rColor[1],0.0,1.0);
420cdf0e10cSrcweir             ::canvas::tools::verifyRange(rColor[2],0.0,1.0);
421cdf0e10cSrcweir 
422cdf0e10cSrcweir             aColor =
423cdf0e10cSrcweir                 (static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[0] ) ) << 16) |
424cdf0e10cSrcweir                 (static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[1] ) ) << 8) |
425cdf0e10cSrcweir                 static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[2] ) );
426cdf0e10cSrcweir 
427cdf0e10cSrcweir             if( rColor.getLength() > 3 )
428cdf0e10cSrcweir             {
429cdf0e10cSrcweir                 ::canvas::tools::verifyRange(rColor[3],0.0,1.0);
430cdf0e10cSrcweir                 aColor |= static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[3] ) ) << 24;
431cdf0e10cSrcweir             }
432cdf0e10cSrcweir 
433cdf0e10cSrcweir             return aColor;
434cdf0e10cSrcweir         }
435cdf0e10cSrcweir 
graphicsPathFromRealPoint2DSequence(const uno::Sequence<uno::Sequence<geometry::RealPoint2D>> & points)436cdf0e10cSrcweir         GraphicsPathSharedPtr graphicsPathFromRealPoint2DSequence( const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
437cdf0e10cSrcweir         {
438cdf0e10cSrcweir             GraphicsPathSharedPtr pRes( new Gdiplus::GraphicsPath() );
439cdf0e10cSrcweir             ::std::vector< Gdiplus::PointF > aPoints;
440cdf0e10cSrcweir 
441cdf0e10cSrcweir             sal_Int32 nCurrPoly;
442cdf0e10cSrcweir             for( nCurrPoly=0; nCurrPoly<points.getLength(); ++nCurrPoly )
443cdf0e10cSrcweir             {
444cdf0e10cSrcweir                 const sal_Int32 nCurrSize( points[nCurrPoly].getLength() );
445cdf0e10cSrcweir                 if( nCurrSize )
446cdf0e10cSrcweir                 {
447cdf0e10cSrcweir                     aPoints.resize( nCurrSize );
448cdf0e10cSrcweir 
449cdf0e10cSrcweir                     // TODO(F1): Closed/open polygons
450cdf0e10cSrcweir 
451cdf0e10cSrcweir                     // convert from RealPoint2D array to Gdiplus::PointF array
452cdf0e10cSrcweir                     ::std::transform( const_cast< uno::Sequence< geometry::RealPoint2D >& >(points[nCurrPoly]).getArray(),
453cdf0e10cSrcweir                                       const_cast< uno::Sequence< geometry::RealPoint2D >& >(points[nCurrPoly]).getArray()+nCurrSize,
454cdf0e10cSrcweir                                       aPoints.begin(),
455cdf0e10cSrcweir                                       implGdiPlusPointFromRealPoint2D );
456cdf0e10cSrcweir 
457cdf0e10cSrcweir                     pRes->AddLines( &aPoints[0], nCurrSize );
458cdf0e10cSrcweir                 }
459cdf0e10cSrcweir             }
460cdf0e10cSrcweir 
461cdf0e10cSrcweir             return pRes;
462cdf0e10cSrcweir         }
463cdf0e10cSrcweir 
graphicsPathFromB2DPolygon(const::basegfx::B2DPolygon & rPoly,bool bNoLineJoin)464cdf0e10cSrcweir         GraphicsPathSharedPtr graphicsPathFromB2DPolygon( const ::basegfx::B2DPolygon& rPoly, bool bNoLineJoin )
465cdf0e10cSrcweir         {
466cdf0e10cSrcweir             GraphicsPathSharedPtr 				pRes( new Gdiplus::GraphicsPath() );
467cdf0e10cSrcweir             ::std::vector< Gdiplus::PointF > 	aPoints;
468cdf0e10cSrcweir 
469cdf0e10cSrcweir             graphicsPathFromB2DPolygon( pRes, aPoints, rPoly, bNoLineJoin );
470cdf0e10cSrcweir 
471cdf0e10cSrcweir             return pRes;
472cdf0e10cSrcweir         }
473cdf0e10cSrcweir 
graphicsPathFromB2DPolyPolygon(const::basegfx::B2DPolyPolygon & rPoly,bool bNoLineJoin)474cdf0e10cSrcweir         GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly, bool bNoLineJoin )
475cdf0e10cSrcweir         {
476cdf0e10cSrcweir             GraphicsPathSharedPtr 				pRes( new Gdiplus::GraphicsPath() );
477cdf0e10cSrcweir             ::std::vector< Gdiplus::PointF > 	aPoints;
478cdf0e10cSrcweir 
479cdf0e10cSrcweir             const sal_uInt32 nPolies( rPoly.count() );
480cdf0e10cSrcweir             for( sal_uInt32 nCurrPoly=0; nCurrPoly<nPolies; ++nCurrPoly )
481cdf0e10cSrcweir             {
482cdf0e10cSrcweir                 graphicsPathFromB2DPolygon( pRes,
483cdf0e10cSrcweir                                             aPoints,
484cdf0e10cSrcweir                                             rPoly.getB2DPolygon( nCurrPoly ),
485cdf0e10cSrcweir                                             bNoLineJoin);
486cdf0e10cSrcweir             }
487cdf0e10cSrcweir 
488cdf0e10cSrcweir             return pRes;
489cdf0e10cSrcweir         }
490cdf0e10cSrcweir 
graphicsPathFromXPolyPolygon2D(const uno::Reference<rendering::XPolyPolygon2D> & xPoly,bool bNoLineJoin)491cdf0e10cSrcweir         GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly, bool bNoLineJoin )
492cdf0e10cSrcweir         {
493cdf0e10cSrcweir             LinePolyPolygon* pPolyImpl = dynamic_cast< LinePolyPolygon* >( xPoly.get() );
494cdf0e10cSrcweir 
495cdf0e10cSrcweir             if( pPolyImpl )
496cdf0e10cSrcweir             {
497cdf0e10cSrcweir                 return pPolyImpl->getGraphicsPath( bNoLineJoin );
498cdf0e10cSrcweir             }
499cdf0e10cSrcweir             else
500cdf0e10cSrcweir             {
501cdf0e10cSrcweir                 return tools::graphicsPathFromB2DPolyPolygon(
502cdf0e10cSrcweir                     polyPolygonFromXPolyPolygon2D( xPoly ), bNoLineJoin );
503cdf0e10cSrcweir             }
504cdf0e10cSrcweir         }
505cdf0e10cSrcweir 
drawGdiPlusBitmap(const GraphicsSharedPtr & rGraphics,const BitmapSharedPtr & rBitmap)506cdf0e10cSrcweir         bool drawGdiPlusBitmap( const GraphicsSharedPtr& rGraphics,
507cdf0e10cSrcweir                                 const BitmapSharedPtr&	 rBitmap )
508cdf0e10cSrcweir         {
509cdf0e10cSrcweir             Gdiplus::PointF	aPoint;
510cdf0e10cSrcweir             return (Gdiplus::Ok == rGraphics->DrawImage( rBitmap.get(),
511cdf0e10cSrcweir                                                          aPoint ) );
512cdf0e10cSrcweir         }
513cdf0e10cSrcweir 
drawDIBits(const GraphicsSharedPtr & rGraphics,const BITMAPINFO & rBI,const void * pBits)514cdf0e10cSrcweir         bool drawDIBits( const GraphicsSharedPtr& rGraphics,
515cdf0e10cSrcweir                          const BITMAPINFO&		  rBI,
516cdf0e10cSrcweir                          const void*			  pBits )
517cdf0e10cSrcweir         {
518cdf0e10cSrcweir             BitmapSharedPtr pBitmap(
519cdf0e10cSrcweir                 Gdiplus::Bitmap::FromBITMAPINFO( &rBI,
520cdf0e10cSrcweir                                                  (void*)pBits ) );
521cdf0e10cSrcweir 
522cdf0e10cSrcweir             return drawGdiPlusBitmap( rGraphics,
523cdf0e10cSrcweir                                       pBitmap );
524cdf0e10cSrcweir         }
525cdf0e10cSrcweir 
drawRGBABits(const GraphicsSharedPtr & rGraphics,const RawRGBABitmap & rRawRGBAData)526cdf0e10cSrcweir         bool drawRGBABits( const GraphicsSharedPtr& rGraphics,
527cdf0e10cSrcweir                            const RawRGBABitmap&		rRawRGBAData )
528cdf0e10cSrcweir         {
529cdf0e10cSrcweir             BitmapSharedPtr pBitmap( new Gdiplus::Bitmap( rRawRGBAData.mnWidth,
530cdf0e10cSrcweir                                                           rRawRGBAData.mnHeight,
531cdf0e10cSrcweir                                                           PixelFormat32bppARGB ) );
532cdf0e10cSrcweir 
533cdf0e10cSrcweir             Gdiplus::BitmapData aBmpData;
534cdf0e10cSrcweir             aBmpData.Width		 = rRawRGBAData.mnWidth;
535cdf0e10cSrcweir             aBmpData.Height		 = rRawRGBAData.mnHeight;
536cdf0e10cSrcweir             aBmpData.Stride 	 = 4*aBmpData.Width; // bottom-up format
537cdf0e10cSrcweir             aBmpData.PixelFormat = PixelFormat32bppARGB;
538cdf0e10cSrcweir             aBmpData.Scan0		 = rRawRGBAData.mpBitmapData.get();
539cdf0e10cSrcweir 
540cdf0e10cSrcweir             const Gdiplus::Rect aRect( 0,0,aBmpData.Width,aBmpData.Height );
541cdf0e10cSrcweir             if( Gdiplus::Ok != pBitmap->LockBits( &aRect,
542cdf0e10cSrcweir                                                   Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
543cdf0e10cSrcweir                                                   PixelFormat32bppARGB,
544cdf0e10cSrcweir                                                   &aBmpData ) )
545cdf0e10cSrcweir             {
546cdf0e10cSrcweir                 return false;
547cdf0e10cSrcweir             }
548cdf0e10cSrcweir 
549cdf0e10cSrcweir             // commit data to bitmap
550cdf0e10cSrcweir             pBitmap->UnlockBits( &aBmpData );
551cdf0e10cSrcweir 
552cdf0e10cSrcweir             return drawGdiPlusBitmap( rGraphics,
553cdf0e10cSrcweir                                       pBitmap );
554cdf0e10cSrcweir         }
555cdf0e10cSrcweir 
bitmapFromXBitmap(const uno::Reference<rendering::XBitmap> & xBitmap)556cdf0e10cSrcweir         BitmapSharedPtr bitmapFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
557cdf0e10cSrcweir         {
558cdf0e10cSrcweir             BitmapProvider* pBitmapProvider = dynamic_cast< BitmapProvider* >(xBitmap.get());
559cdf0e10cSrcweir 
560cdf0e10cSrcweir             if( pBitmapProvider )
561cdf0e10cSrcweir             {
562cdf0e10cSrcweir 				IBitmapSharedPtr pBitmap( pBitmapProvider->getBitmap() );
563cdf0e10cSrcweir 				return pBitmap->getBitmap();
564cdf0e10cSrcweir             }
565cdf0e10cSrcweir             else
566cdf0e10cSrcweir             {
567cdf0e10cSrcweir                 // not a native CanvasBitmap, extract VCL bitmap and
568cdf0e10cSrcweir                 // render into GDI+ bitmap of similar size
569cdf0e10cSrcweir                 // =================================================
570cdf0e10cSrcweir 
571cdf0e10cSrcweir                 const geometry::IntegerSize2D aBmpSize( xBitmap->getSize() );
572cdf0e10cSrcweir                 BitmapSharedPtr 			  pBitmap;
573cdf0e10cSrcweir 
574cdf0e10cSrcweir                 if( xBitmap->hasAlpha() )
575cdf0e10cSrcweir                 {
576cdf0e10cSrcweir                     // TODO(P2): At least for the alpha bitmap case, it
577cdf0e10cSrcweir                     // would be possible to generate the corresponding
578cdf0e10cSrcweir                     // bitmap directly
579cdf0e10cSrcweir                     pBitmap.reset( new Gdiplus::Bitmap( aBmpSize.Width,
580cdf0e10cSrcweir                                                         aBmpSize.Height,
581cdf0e10cSrcweir                                                         PixelFormat32bppARGB ) );
582cdf0e10cSrcweir                 }
583cdf0e10cSrcweir                 else
584cdf0e10cSrcweir                 {
585cdf0e10cSrcweir                     // TODO(F2): Might be wise to create bitmap compatible
586cdf0e10cSrcweir                     // to the VCL bitmap. Also, check whether the VCL
587cdf0e10cSrcweir                     // bitmap's system handles can be used to create the
588cdf0e10cSrcweir                     // GDI+ bitmap (currently, it does not seem so).
589cdf0e10cSrcweir                     pBitmap.reset( new Gdiplus::Bitmap( aBmpSize.Width,
590cdf0e10cSrcweir                                                         aBmpSize.Height,
591cdf0e10cSrcweir                                                         PixelFormat24bppRGB ) );
592cdf0e10cSrcweir                 }
593cdf0e10cSrcweir 
594cdf0e10cSrcweir 				GraphicsSharedPtr pGraphics(createGraphicsFromBitmap(pBitmap));
595cdf0e10cSrcweir 		        tools::setupGraphics(*pGraphics);
596cdf0e10cSrcweir                 if( !drawVCLBitmapFromXBitmap(
597cdf0e10cSrcweir                         pGraphics,
598cdf0e10cSrcweir                         xBitmap) )
599cdf0e10cSrcweir                 {
600cdf0e10cSrcweir                     pBitmap.reset();
601cdf0e10cSrcweir                 }
602cdf0e10cSrcweir 
603cdf0e10cSrcweir                 return pBitmap;
604cdf0e10cSrcweir             }
605cdf0e10cSrcweir         }
606cdf0e10cSrcweir 
canvasFontFromXFont(const uno::Reference<rendering::XCanvasFont> & xFont)607cdf0e10cSrcweir         CanvasFont::ImplRef	canvasFontFromXFont( const uno::Reference< rendering::XCanvasFont >& xFont )
608cdf0e10cSrcweir         {
609cdf0e10cSrcweir             CanvasFont* pCanvasFont = dynamic_cast< CanvasFont* >(xFont.get());
610cdf0e10cSrcweir 
611cdf0e10cSrcweir             ENSURE_ARG_OR_THROW( pCanvasFont,
612cdf0e10cSrcweir                              "canvasFontFromXFont(): Invalid XFont (or incompatible font for this XCanvas)" );
613cdf0e10cSrcweir 
614cdf0e10cSrcweir             return CanvasFont::ImplRef( pCanvasFont );
615cdf0e10cSrcweir         }
616cdf0e10cSrcweir 
setModulateImageAttributes(Gdiplus::ImageAttributes & o_rAttr,double nRedModulation,double nGreenModulation,double nBlueModulation,double nAlphaModulation)617cdf0e10cSrcweir         void setModulateImageAttributes( Gdiplus::ImageAttributes& o_rAttr,
618cdf0e10cSrcweir                                          double					   nRedModulation,
619cdf0e10cSrcweir                                          double					   nGreenModulation,
620cdf0e10cSrcweir                                          double					   nBlueModulation,
621cdf0e10cSrcweir                                          double					   nAlphaModulation )
622cdf0e10cSrcweir         {
623cdf0e10cSrcweir             // This gets rather verbose, but we have to setup a color
624cdf0e10cSrcweir             // transformation matrix, in order to incorporate the global
625cdf0e10cSrcweir             // alpha value mfAlpha into the bitmap rendering.
626cdf0e10cSrcweir             Gdiplus::ColorMatrix	 aColorMatrix;
627cdf0e10cSrcweir 
628cdf0e10cSrcweir             aColorMatrix.m[0][0] = static_cast<Gdiplus::REAL>(nRedModulation);
629cdf0e10cSrcweir             aColorMatrix.m[0][1] = 0.0;
630cdf0e10cSrcweir             aColorMatrix.m[0][2] = 0.0;
631cdf0e10cSrcweir             aColorMatrix.m[0][3] = 0.0;
632cdf0e10cSrcweir             aColorMatrix.m[0][4] = 0.0;
633cdf0e10cSrcweir 
634cdf0e10cSrcweir             aColorMatrix.m[1][0] = 0.0;
635cdf0e10cSrcweir             aColorMatrix.m[1][1] = static_cast<Gdiplus::REAL>(nGreenModulation);
636cdf0e10cSrcweir             aColorMatrix.m[1][2] = 0.0;
637cdf0e10cSrcweir             aColorMatrix.m[1][3] = 0.0;
638cdf0e10cSrcweir             aColorMatrix.m[1][4] = 0.0;
639cdf0e10cSrcweir 
640cdf0e10cSrcweir             aColorMatrix.m[2][0] = 0.0;
641cdf0e10cSrcweir             aColorMatrix.m[2][1] = 0.0;
642cdf0e10cSrcweir             aColorMatrix.m[2][2] = static_cast<Gdiplus::REAL>(nBlueModulation);
643cdf0e10cSrcweir             aColorMatrix.m[2][3] = 0.0;
644cdf0e10cSrcweir             aColorMatrix.m[2][4] = 0.0;
645cdf0e10cSrcweir 
646cdf0e10cSrcweir             aColorMatrix.m[3][0] = 0.0;
647cdf0e10cSrcweir             aColorMatrix.m[3][1] = 0.0;
648cdf0e10cSrcweir             aColorMatrix.m[3][2] = 0.0;
649cdf0e10cSrcweir             aColorMatrix.m[3][3] = static_cast<Gdiplus::REAL>(nAlphaModulation);
650cdf0e10cSrcweir             aColorMatrix.m[3][4] = 0.0;
651cdf0e10cSrcweir 
652cdf0e10cSrcweir             aColorMatrix.m[4][0] = 0.0;
653cdf0e10cSrcweir             aColorMatrix.m[4][1] = 0.0;
654cdf0e10cSrcweir             aColorMatrix.m[4][2] = 0.0;
655cdf0e10cSrcweir             aColorMatrix.m[4][3] = 0.0;
656cdf0e10cSrcweir             aColorMatrix.m[4][4] = 1.0;
657cdf0e10cSrcweir 
658cdf0e10cSrcweir             o_rAttr.SetColorMatrix( &aColorMatrix,
659cdf0e10cSrcweir                                     Gdiplus::ColorMatrixFlagsDefault,
660cdf0e10cSrcweir                                     Gdiplus::ColorAdjustTypeDefault );
661cdf0e10cSrcweir         }
662cdf0e10cSrcweir 
663cdf0e10cSrcweir     } // namespace tools
664cdf0e10cSrcweir } // namespace dxcanvas
665