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