29#include <com/sun/star/rendering/CompositeOperation.hpp>
30#include <com/sun/star/rendering/PathCapType.hpp>
31#include <com/sun/star/rendering/PathJoinType.hpp>
32#include <com/sun/star/rendering/RepaintResult.hpp>
33#include <com/sun/star/rendering/TexturingMode.hpp>
36#include <rtl/math.hxx>
54 Gdiplus::LineCap gdiLineCapFromCap(
sal_Int8 nCapType )
58 case rendering::PathCapType::BUTT:
59 return Gdiplus::LineCapFlat;
61 case rendering::PathCapType::ROUND:
62 return Gdiplus::LineCapRound;
64 case rendering::PathCapType::SQUARE:
65 return Gdiplus::LineCapSquare;
69 "gdiLineCapFromCap(): Unexpected cap type" );
72 return Gdiplus::LineCapFlat;
75 Gdiplus::DashCap gdiDashCapFromCap(
sal_Int8 nCapType )
79 case rendering::PathCapType::BUTT:
80 return Gdiplus::DashCapFlat;
82 case rendering::PathCapType::ROUND:
83 return Gdiplus::DashCapRound;
87 case rendering::PathCapType::SQUARE:
88 return Gdiplus::DashCapTriangle;
92 "gdiDashCapFromCap(): Unexpected cap type" );
95 return Gdiplus::DashCapFlat;
98 Gdiplus::LineJoin gdiJoinFromJoin(
sal_Int8 nJoinType )
102 case rendering::PathJoinType::NONE:
103 SAL_WARN(
"canvas.directx",
"gdiJoinFromJoin(): Join NONE not possible, mapping to BEVEL (closest to NONE)" );
104 return Gdiplus::LineJoinBevel;
106 case rendering::PathJoinType::MITER:
109 return Gdiplus::LineJoinMiterClipped;
111 case rendering::PathJoinType::ROUND:
112 return Gdiplus::LineJoinRound;
114 case rendering::PathJoinType::BEVEL:
115 return Gdiplus::LineJoinBevel;
119 "gdiJoinFromJoin(): Unexpected join type" );
122 return Gdiplus::LineJoinMiter;
129 mpGraphicsProvider(),
149 "CanvasHelper::setTarget(): Invalid target" );
151 "CanvasHelper::setTarget(): target set, old target would be overwritten" );
157 const ::basegfx::B2ISize& rOutputOffset )
160 "CanvasHelper::setTarget(): invalid target" );
162 "CanvasHelper::setTarget(): target set, old target would be overwritten" );
173 Gdiplus::Color aClearColor{Gdiplus::ARGB(Gdiplus::Color::White)};
176 Gdiplus::Ok == pGraphics->SetCompositingMode(
177 Gdiplus::CompositingModeSourceCopy ),
178 "CanvasHelper::clear(): GDI+ SetCompositingMode call failed" );
180 Gdiplus::Ok == pGraphics->Clear( aClearColor ),
181 "CanvasHelper::clear(): GDI+ Clear call failed" );
186 const geometry::RealPoint2D& aPoint,
187 const rendering::ViewState& viewState,
188 const rendering::RenderState& renderState )
196 Gdiplus::SolidBrush aBrush(
201 Gdiplus::Matrix aMatrix;
202 pGraphics->GetTransform(&aMatrix);
204 Gdiplus::PointF vector(1, 1);
205 aMatrix.TransformVectors(&vector);
210 Gdiplus::Ok == pGraphics->FillEllipse( &aBrush,
212 Gdiplus::REAL(aPoint.X),
213 Gdiplus::REAL(aPoint.Y),
214 Gdiplus::REAL(vector.X),
215 Gdiplus::REAL(vector.Y) ),
216 "CanvasHelper::drawPoint(): GDI+ call failed" );
221 const geometry::RealPoint2D& aStartPoint,
222 const geometry::RealPoint2D& aEndPoint,
223 const rendering::ViewState& viewState,
224 const rendering::RenderState& renderState )
235 Gdiplus::REAL(0.0) );
242 const Gdiplus::PixelOffsetMode aOldMode(
243 pGraphics->GetPixelOffsetMode() );
244 pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
246 Gdiplus::Status
hr = pGraphics->DrawLine( &aPen,
247 Gdiplus::REAL(aStartPoint.X),
248 Gdiplus::REAL(aStartPoint.Y),
249 Gdiplus::REAL(aEndPoint.X),
250 Gdiplus::REAL(aEndPoint.Y) );
251 pGraphics->SetPixelOffsetMode( aOldMode );
255 "CanvasHelper::drawLine(): GDI+ call failed" );
260 const geometry::RealBezierSegment2D& aBezierSegment,
261 const geometry::RealPoint2D& aEndPoint,
262 const rendering::ViewState& viewState,
263 const rendering::RenderState& renderState )
274 Gdiplus::REAL(0.0) );
281 const Gdiplus::PixelOffsetMode aOldMode(
282 pGraphics->GetPixelOffsetMode() );
283 pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
285 Gdiplus::Status
hr = pGraphics->DrawBezier( &aPen,
286 Gdiplus::REAL(aBezierSegment.Px),
287 Gdiplus::REAL(aBezierSegment.Py),
288 Gdiplus::REAL(aBezierSegment.C1x),
289 Gdiplus::REAL(aBezierSegment.C1y),
290 Gdiplus::REAL(aEndPoint.X),
291 Gdiplus::REAL(aEndPoint.Y),
292 Gdiplus::REAL(aBezierSegment.C2x),
293 Gdiplus::REAL(aBezierSegment.C2y) );
295 pGraphics->SetPixelOffsetMode( aOldMode );
299 "CanvasHelper::drawBezier(): GDI+ call failed" );
304 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
305 const rendering::ViewState& viewState,
306 const rendering::RenderState& renderState )
309 "CanvasHelper::drawPolyPolygon: polygon is NULL");
320 Gdiplus::REAL(0.0) );
327 const Gdiplus::PixelOffsetMode aOldMode(
328 pGraphics->GetPixelOffsetMode() );
329 pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
334 Gdiplus::Status
hr = pGraphics->DrawPath( &aPen, pPath.get() );
336 pGraphics->SetPixelOffsetMode( aOldMode );
340 "CanvasHelper::drawPolyPolygon(): GDI+ call failed" );
344 return uno::Reference< rendering::XCachedPrimitive >(
nullptr);
348 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
349 const rendering::ViewState& viewState,
350 const rendering::RenderState& renderState,
351 const rendering::StrokeAttributes& strokeAttributes )
354 "CanvasHelper::drawPolyPolygon: polygon is NULL");
369 static_cast< Gdiplus::REAL
>(strokeAttributes.StrokeWidth) );
376 const Gdiplus::PixelOffsetMode aOldMode(
377 pGraphics->GetPixelOffsetMode() );
378 pGraphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
380 const bool bIsMiter(rendering::PathJoinType::MITER == strokeAttributes.JoinType);
381 const bool bIsNone(rendering::PathJoinType::NONE == strokeAttributes.JoinType);
384 aPen.SetMiterLimit(
static_cast< Gdiplus::REAL
>(strokeAttributes.MiterLimit) );
386 const std::vector< Gdiplus::REAL >& rDashArray(
387 ::comphelper::sequenceToContainer< std::vector< Gdiplus::REAL >,
double >(
388 strokeAttributes.DashArray ) );
389 if( !rDashArray.empty() )
391 aPen.SetDashPattern( rDashArray.data(),
394 aPen.SetLineCap( gdiLineCapFromCap(strokeAttributes.StartCapType),
395 gdiLineCapFromCap(strokeAttributes.EndCapType),
396 gdiDashCapFromCap(strokeAttributes.StartCapType));
398 aPen.SetLineJoin( gdiJoinFromJoin(strokeAttributes.JoinType) );
403 Gdiplus::Status
hr = pGraphics->DrawPath( &aPen, pPath.get() );
405 pGraphics->SetPixelOffsetMode( aOldMode );
409 "CanvasHelper::strokePolyPolygon(): GDI+ call failed" );
413 return uno::Reference< rendering::XCachedPrimitive >(
nullptr);
417 const uno::Reference< rendering::XPolyPolygon2D >& ,
418 const rendering::ViewState& ,
419 const rendering::RenderState& ,
420 const uno::Sequence< rendering::Texture >& ,
421 const rendering::StrokeAttributes& )
424 return uno::Reference< rendering::XCachedPrimitive >(
nullptr);
428 const uno::Reference< rendering::XPolyPolygon2D >& ,
429 const rendering::ViewState& ,
430 const rendering::RenderState& ,
431 const uno::Sequence< rendering::Texture >& ,
432 const uno::Reference< geometry::XMapping2D >& ,
433 const rendering::StrokeAttributes& )
436 return uno::Reference< rendering::XCachedPrimitive >(
nullptr);
440 const uno::Reference< rendering::XPolyPolygon2D >& ,
441 const rendering::ViewState& ,
442 const rendering::RenderState& ,
443 const rendering::StrokeAttributes& )
446 return uno::Reference< rendering::XPolyPolygon2D >(
nullptr);
450 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
451 const rendering::ViewState& viewState,
452 const rendering::RenderState& renderState )
455 "CanvasHelper::fillPolyPolygon: polygon is NULL");
463 Gdiplus::SolidBrush aBrush(
469 ENSURE_OR_THROW( Gdiplus::Ok == pGraphics->FillPath( &aBrush, pPath.get() ),
470 "CanvasHelper::fillPolyPolygon(): GDI+ call failed " );
474 return uno::Reference< rendering::XCachedPrimitive >(
nullptr);
478 const uno::Reference< rendering::XPolyPolygon2D >& ,
479 const rendering::ViewState& ,
480 const rendering::RenderState& ,
481 const uno::Sequence< rendering::Texture >& ,
482 const uno::Reference< geometry::XMapping2D >& )
485 return uno::Reference< rendering::XCachedPrimitive >(
nullptr);
489 const rendering::FontRequest& fontRequest,
490 const uno::Sequence< beans::PropertyValue >& extraFontProperties,
491 const geometry::Matrix2D& fontMatrix )
495 return uno::Reference< rendering::XCanvasFont >(
496 new CanvasFont(fontRequest, extraFontProperties, fontMatrix ) );
499 return uno::Reference< rendering::XCanvasFont >();
503 const rendering::FontInfo& ,
504 const uno::Sequence< beans::PropertyValue >& )
507 return uno::Sequence< rendering::FontInfo >();
511 const rendering::StringContext& text,
512 const uno::Reference< rendering::XCanvasFont >& xFont,
513 const rendering::ViewState& viewState,
514 const rendering::RenderState& renderState,
518 "CanvasHelper::drawText: font is NULL");
526 Gdiplus::SolidBrush aBrush(
535 Gdiplus::PointF aPoint( 0.0,
536 static_cast<Gdiplus::REAL
>(-(pFont->getFont()->GetSize()*
537 pFont->getCellAscent() /
538 pFont->getEmHeight())) );
549 Gdiplus::Ok == pGraphics->DrawString( o3tl::toW(
text.Text.copy(
text.StartPosition,
550 text.Length ).getStr()),
552 pFont->getFont().get(),
555 "CanvasHelper::drawText(): GDI+ call failed" );
558 return uno::Reference< rendering::XCachedPrimitive >(
nullptr);
562 const uno::Reference< rendering::XTextLayout >& xLayoutetText,
563 const rendering::ViewState& viewState,
564 const rendering::RenderState& renderState )
567 "CanvasHelper::drawTextLayout: layout is NULL");
571 TextLayout* pTextLayout =
572 dynamic_cast< TextLayout*
>( xLayoutetText.get() );
575 "CanvasHelper::drawTextLayout(): TextLayout not compatible with this canvas" );
585 return uno::Reference< rendering::XCachedPrimitive >(
nullptr);
589 const uno::Reference< rendering::XBitmap >& xBitmap,
590 const rendering::ViewState& viewState,
591 const rendering::RenderState& renderState )
594 "CanvasHelper::drawBitmap: bitmap is NULL");
603 BitmapProvider* pBitmap =
dynamic_cast< BitmapProvider*
>(xBitmap.get());
608 pGdiBitmap = pDXBitmap->getBitmap();
622 return uno::Reference< rendering::XCachedPrimitive >(
nullptr);
626 const uno::Reference< rendering::XBitmap >& xBitmap,
627 const rendering::ViewState& viewState,
628 const rendering::RenderState& renderState )
631 "CanvasHelper::drawBitmap: bitmap is NULL");
634 if( renderState.DeviceColor.getLength() < 3 )
635 return drawBitmap( pCanvas, xBitmap, viewState, renderState );
644 Gdiplus::Rect aRect( 0, 0,
646 pBitmap->GetHeight() );
650 rendering::ARGBColor aARGBColor(
651 mpDevice->getDeviceColorSpace()->convertToARGB(renderState.DeviceColor)[0]);
653 Gdiplus::ImageAttributes aImgAttr;
661 Gdiplus::Ok == pGraphics->DrawImage( pBitmap.get(),
665 pBitmap->GetHeight(),
668 "CanvasHelper::drawBitmapModulated(): GDI+ call failed" );
672 return uno::Reference< rendering::XCachedPrimitive >(
nullptr);
677 return uno::Reference< rendering::XGraphicDevice >(
mpDevice);
685 Gdiplus::CompositingMode aRet( Gdiplus::CompositingModeSourceOver );
689 case rendering::CompositeOperation::OVER:
690 case rendering::CompositeOperation::CLEAR:
691 aRet = Gdiplus::CompositingModeSourceOver;
694 case rendering::CompositeOperation::SOURCE:
695 aRet = Gdiplus::CompositingModeSourceCopy;
698 case rendering::CompositeOperation::DESTINATION:
699 case rendering::CompositeOperation::UNDER:
700 case rendering::CompositeOperation::INSIDE:
701 case rendering::CompositeOperation::INSIDE_REVERSE:
702 case rendering::CompositeOperation::OUTSIDE:
703 case rendering::CompositeOperation::OUTSIDE_REVERSE:
704 case rendering::CompositeOperation::ATOP:
705 case rendering::CompositeOperation::ATOP_REVERSE:
706 case rendering::CompositeOperation::XOR:
707 case rendering::CompositeOperation::ADD:
708 case rendering::CompositeOperation::SATURATE:
710 aRet = Gdiplus::CompositingModeSourceOver;
714 ENSURE_OR_THROW(
false,
"CanvasHelper::calcCompositingMode: unexpected mode" );
722 const rendering::ViewState& viewState,
723 const rendering::RenderState& renderState )
726 "CanvasHelper::setupGraphicsState: primary graphics invalid" );
728 "CanvasHelper::setupGraphicsState: reference device invalid" );
739 aTransform = aOutputOffset * aTransform;
742 Gdiplus::Matrix aMatrix;
746 Gdiplus::Ok == rGraphics->SetTransform( &aMatrix ),
747 "CanvasHelper::setupGraphicsState(): Failed to set GDI+ transformation" );
751 Gdiplus::Ok == rGraphics->ResetClip(),
752 "CanvasHelper::setupGraphicsState(): Failed to reset GDI+ clip" );
754 if( viewState.Clip.is() )
762 Gdiplus::Ok == rGraphics->SetClip( aClipPath.get(),
763 Gdiplus::CombineModeIntersect ),
764 "CanvasHelper::setupGraphicsState(): Cannot set GDI+ clip" );
778 aTransform = aOutputOffset * aTransform;
784 Gdiplus::Ok == rGraphics->SetTransform( &aMatrix ),
785 "CanvasHelper::setupGraphicsState(): Cannot set GDI+ transformation" );
787 if( renderState.Clip.is() )
795 Gdiplus::Ok == rGraphics->SetClip( aClipPath.get(),
796 Gdiplus::CombineModeIntersect ),
797 "CanvasHelper::setupGraphicsState(): Cannot set GDI+ clip" );
801 const Gdiplus::CompositingMode eCompositing(
calcCompositingMode( renderState.CompositeOperation ) );
803 Gdiplus::Ok == rGraphics->SetCompositingMode( eCompositing ),
804 "CanvasHelper::setupGraphicsState(): Cannot set GDI* compositing mode)" );
HRESULT createInstance(REFIID iid, Ifc **ppIfc)
rtl::Reference< CanvasFont > ImplRef
void setDevice(css::rendering::XGraphicDevice &rDevice)
Initialize canvas helper.
css::rendering::XGraphicDevice * mpDevice
Phyical output device.
::basegfx::B2ISize maOutputOffset
Current (transformation-independent) output buffer offset.
css::uno::Reference< css::rendering::XCachedPrimitive > drawBitmapModulated(const css::rendering::XCanvas *pCanvas, const css::uno::Reference< css::rendering::XBitmap > &xBitmap, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
css::uno::Reference< css::rendering::XCachedPrimitive > drawText(const css::rendering::XCanvas *pCanvas, const css::rendering::StringContext &text, const css::uno::Reference< css::rendering::XCanvasFont > &xFont, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, sal_Int8 textDirection)
css::uno::Reference< css::rendering::XCachedPrimitive > fillPolyPolygon(const css::rendering::XCanvas *pCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
css::uno::Reference< css::rendering::XCachedPrimitive > strokePolyPolygon(const css::rendering::XCanvas *pCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const css::rendering::StrokeAttributes &strokeAttributes)
Gdiplus::CompositingMode calcCompositingMode(sal_Int8 nMode)
void drawLine(const css::rendering::XCanvas *pCanvas, const css::geometry::RealPoint2D &aStartPoint, const css::geometry::RealPoint2D &aEndPoint, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
css::uno::Sequence< css::rendering::FontInfo > queryAvailableFonts(const css::rendering::XCanvas *pCanvas, const css::rendering::FontInfo &aFilter, const css::uno::Sequence< css::beans::PropertyValue > &aFontProperties)
void drawPoint(const css::rendering::XCanvas *pCanvas, const css::geometry::RealPoint2D &aPoint, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
css::uno::Reference< css::rendering::XCanvasFont > createFont(const css::rendering::XCanvas *pCanvas, const css::rendering::FontRequest &fontRequest, const css::uno::Sequence< css::beans::PropertyValue > &extraFontProperties, const css::geometry::Matrix2D &fontMatrix)
css::uno::Reference< css::rendering::XCachedPrimitive > drawPolyPolygon(const css::rendering::XCanvas *pCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
css::uno::Reference< css::rendering::XCachedPrimitive > drawBitmap(const css::rendering::XCanvas *pCanvas, const css::uno::Reference< css::rendering::XBitmap > &xBitmap, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
GDIPlusUserSharedPtr mpGdiPlusUser
Refcounted global GDI+ state container.
void setTarget(const GraphicsProviderSharedPtr &rTarget)
Set the target for rendering operations.
GraphicsProviderSharedPtr mpGraphicsProvider
Provides the Gdiplus::Graphics to render into.
css::uno::Reference< css::rendering::XCachedPrimitive > strokeTextureMappedPolyPolygon(const css::rendering::XCanvas *pCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const css::uno::Sequence< css::rendering::Texture > &textures, const css::uno::Reference< css::geometry::XMapping2D > &xMapping, const css::rendering::StrokeAttributes &strokeAttributes)
css::uno::Reference< css::rendering::XCachedPrimitive > drawTextLayout(const css::rendering::XCanvas *pCanvas, const css::uno::Reference< css::rendering::XTextLayout > &laidOutText, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
void disposing()
Release all references.
css::uno::Reference< css::rendering::XPolyPolygon2D > queryStrokeShapes(const css::rendering::XCanvas *pCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const css::rendering::StrokeAttributes &strokeAttributes)
css::uno::Reference< css::rendering::XCachedPrimitive > strokeTexturedPolyPolygon(const css::rendering::XCanvas *pCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const css::uno::Sequence< css::rendering::Texture > &textures, const css::rendering::StrokeAttributes &strokeAttributes)
css::uno::Reference< css::rendering::XCachedPrimitive > fillTextureMappedPolyPolygon(const css::rendering::XCanvas *pCanvas, const css::uno::Reference< css::rendering::XPolyPolygon2D > &xPolyPolygon, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState, const css::uno::Sequence< css::rendering::Texture > &textures, const css::uno::Reference< css::geometry::XMapping2D > &xMapping)
void setupGraphicsState(GraphicsSharedPtr const &rGraphics, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
void drawBezier(const css::rendering::XCanvas *pCanvas, const css::geometry::RealBezierSegment2D &aBezierSegment, const css::geometry::RealPoint2D &aEndPoint, const css::rendering::ViewState &viewState, const css::rendering::RenderState &renderState)
css::uno::Reference< css::rendering::XGraphicDevice > getDevice()
#define ENSURE_OR_THROW(c, m)
sal::systools::COMReference< IDirect3DDevice9 > mpDevice
#define SAL_WARN(area, stream)
B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY)
std::shared_ptr< ::cppcanvas::Bitmap > BitmapSharedPtr
std::shared_ptr< Gdiplus::Graphics > GraphicsSharedPtr
std::shared_ptr< IBitmap > IBitmapSharedPtr
std::shared_ptr< GraphicsProvider > GraphicsProviderSharedPtr
std::shared_ptr< Gdiplus::GraphicsPath > GraphicsPathSharedPtr