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