bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / gdi / salgdilayout.cxx
blobde11058e4507758909f7a511896917634fa71d6f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <memory>
21 #include <config_features.h>
22 #include <sal/log.hxx>
23 #if HAVE_FEATURE_OPENGL
24 #include <openglgdiimpl.hxx>
25 #include <opengl/zone.hxx>
26 #include <desktop/exithelper.h>
27 #ifdef _WIN32
28 #include <svsys.h>
29 #endif
30 #endif
31 #include <salgdi.hxx>
32 #include <salframe.hxx>
33 #include <basegfx/matrix/b2dhommatrix.hxx>
34 #include <basegfx/matrix/b2dhommatrixtools.hxx>
35 #include <FileDefinitionWidgetDraw.hxx>
37 // The only common SalFrame method
39 SalFrameGeometry SalFrame::GetGeometry() const
41 // mirror frame coordinates at parent
42 SalFrame *pParent = GetParent();
43 if( pParent && AllSettings::GetLayoutRTL() )
45 SalFrameGeometry aGeom = maGeometry;
46 int parent_x = aGeom.nX - pParent->maGeometry.nX;
47 aGeom.nX = pParent->maGeometry.nX + pParent->maGeometry.nWidth - maGeometry.nWidth - parent_x;
48 return aGeom;
50 else
51 return maGeometry;
54 SalGraphics::SalGraphics()
55 : m_nLayout( SalLayoutFlags::NONE ),
56 m_aLastMirror(),
57 m_aLastMirrorW(0),
58 m_bAntiAliasB2DDraw(false)
60 // read global RTL settings
61 if( AllSettings::GetLayoutRTL() )
62 m_nLayout = SalLayoutFlags::BiDiRtl;
65 bool SalGraphics::initWidgetDrawBackends(bool bForce)
67 bool bFileDefinitionsWidgetDraw = !!getenv("VCL_DRAW_WIDGETS_FROM_FILE");
69 if (bFileDefinitionsWidgetDraw || bForce)
71 m_pWidgetDraw.reset(new vcl::FileDefinitionWidgetDraw(*this));
72 auto pFileDefinitionWidgetDraw = static_cast<vcl::FileDefinitionWidgetDraw*>(m_pWidgetDraw.get());
73 if (!pFileDefinitionWidgetDraw->isActive())
75 m_pWidgetDraw.reset();
76 return false;
78 return true;
80 return false;
83 SalGraphics::~SalGraphics() COVERITY_NOEXCEPT_FALSE
85 // can't call ReleaseFonts here, as the destructor just calls this classes SetFont (pure virtual)!
88 #if HAVE_FEATURE_OPENGL
90 namespace
92 void disableOpenGLAndTerminateForRestart()
94 OpenGLZone::hardDisable();
95 #ifdef _WIN32
96 TerminateProcess(GetCurrentProcess(), EXITHELPER_NORMAL_RESTART);
97 #endif
101 rtl::Reference<OpenGLContext> SalGraphics::GetOpenGLContext() const
103 OpenGLSalGraphicsImpl *pImpl = dynamic_cast<OpenGLSalGraphicsImpl*>(GetImpl());
104 if (pImpl)
106 // If we notice that OpenGL is broken the first time being called, it is not too late to call
107 // disableOpenGLAndTerminateForRestart(). The first time this will be called is from displaying
108 // the splash screen, so if OpenGL is broken, it is "early enough" for us to be able to disable
109 // OpenGL and terminate bluntly with EXITHELPER_NORMAL_RESTART, thus causing the wrapper process
110 // to restart us, then without using OpenGL.
111 static bool bFirstCall = true;
112 rtl::Reference<OpenGLContext> xRet(pImpl->GetOpenGLContext());
113 if (!xRet.is() && bFirstCall)
114 disableOpenGLAndTerminateForRestart();
115 bFirstCall = false;
116 return xRet;
118 return nullptr;
121 #endif
123 bool SalGraphics::drawTransformedBitmap(
124 const basegfx::B2DPoint& /* rNull */,
125 const basegfx::B2DPoint& /* rX */,
126 const basegfx::B2DPoint& /* rY */,
127 const SalBitmap& /* rSourceBitmap */,
128 const SalBitmap* /* pAlphaBitmap */)
130 // here direct support for transformed bitmaps can be implemented
131 return false;
134 long SalGraphics::mirror2( long x, const OutputDevice *pOutDev ) const
136 mirror(x, pOutDev);
137 return x;
140 inline long SalGraphics::GetDeviceWidth(const OutputDevice* pOutDev) const
142 return (pOutDev && pOutDev->IsVirtual())
143 ? pOutDev->GetOutputWidthPixel() : GetGraphicsWidth();
146 void SalGraphics::mirror( long& x, const OutputDevice *pOutDev ) const
148 const long w = GetDeviceWidth(pOutDev);
149 if( w )
151 if( pOutDev && pOutDev->ImplIsAntiparallel() )
153 OutputDevice *pOutDevRef = const_cast<OutputDevice*>(pOutDev);
154 // mirror this window back
155 if( m_nLayout & SalLayoutFlags::BiDiRtl )
157 long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
158 x = devX + (x - pOutDevRef->GetOutOffXPixel());
160 else
162 long devX = pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
163 x = pOutDevRef->GetOutputWidthPixel() - (x - devX) + pOutDevRef->GetOutOffXPixel() - 1;
166 else if( m_nLayout & SalLayoutFlags::BiDiRtl )
167 x = w-1-x;
171 void SalGraphics::mirror( long& x, long nWidth, const OutputDevice *pOutDev, bool bBack ) const
173 const long w = GetDeviceWidth(pOutDev);
174 if( w )
176 if( pOutDev && pOutDev->ImplIsAntiparallel() )
178 OutputDevice *pOutDevRef = const_cast<OutputDevice*>(pOutDev);
179 // mirror this window back
180 if( m_nLayout & SalLayoutFlags::BiDiRtl )
182 long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
183 if( bBack )
184 x = x - devX + pOutDevRef->GetOutOffXPixel();
185 else
186 x = devX + (x - pOutDevRef->GetOutOffXPixel());
188 else
190 long devX = pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
191 if( bBack )
192 x = devX + (pOutDevRef->GetOutputWidthPixel() + devX) - (x + nWidth);
193 else
194 x = pOutDevRef->GetOutputWidthPixel() - (x - devX) + pOutDevRef->GetOutOffXPixel() - nWidth;
197 else if( m_nLayout & SalLayoutFlags::BiDiRtl )
198 x = w-nWidth-x;
202 bool SalGraphics::mirror( sal_uInt32 nPoints, const SalPoint *pPtAry, SalPoint *pPtAry2, const OutputDevice *pOutDev ) const
204 const long w = GetDeviceWidth(pOutDev);
205 if( w )
207 sal_uInt32 i, j;
209 if( pOutDev && pOutDev->ImplIsAntiparallel() )
211 OutputDevice *pOutDevRef = const_cast<OutputDevice*>(pOutDev);
212 // mirror this window back
213 if( m_nLayout & SalLayoutFlags::BiDiRtl )
215 long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
216 for( i=0, j=nPoints-1; i<nPoints; i++,j-- )
218 pPtAry2[j].mnX = devX + (pPtAry[i].mnX - pOutDevRef->GetOutOffXPixel());
219 pPtAry2[j].mnY = pPtAry[i].mnY;
222 else
224 long devX = pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX
225 for( i=0, j=nPoints-1; i<nPoints; i++,j-- )
227 pPtAry2[j].mnX = pOutDevRef->GetOutputWidthPixel() - (pPtAry[i].mnX - devX) + pOutDevRef->GetOutOffXPixel() - 1;
228 pPtAry2[j].mnY = pPtAry[i].mnY;
232 else if( m_nLayout & SalLayoutFlags::BiDiRtl )
234 for( i=0, j=nPoints-1; i<nPoints; i++,j-- )
236 pPtAry2[j].mnX = w-1-pPtAry[i].mnX;
237 pPtAry2[j].mnY = pPtAry[i].mnY;
240 return true;
242 else
243 return false;
246 void SalGraphics::mirror( vcl::Region& rRgn, const OutputDevice *pOutDev ) const
248 if( rRgn.HasPolyPolygonOrB2DPolyPolygon() )
250 const basegfx::B2DPolyPolygon aPolyPoly(mirror(rRgn.GetAsB2DPolyPolygon(), pOutDev));
252 rRgn = vcl::Region(aPolyPoly);
254 else
256 RectangleVector aRectangles;
257 rRgn.GetRegionRectangles(aRectangles);
258 rRgn.SetEmpty();
260 for (auto & rectangle : aRectangles)
262 mirror(rectangle, pOutDev);
263 rRgn.Union(rectangle);
266 //ImplRegionInfo aInfo;
267 //bool bRegionRect;
268 //Region aMirroredRegion;
269 //long nX, nY, nWidth, nHeight;
271 //bRegionRect = rRgn.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
272 //while ( bRegionRect )
274 // Rectangle aRect( Point(nX, nY), Size(nWidth, nHeight) );
275 // mirror( aRect, pOutDev, bBack );
276 // aMirroredRegion.Union( aRect );
277 // bRegionRect = rRgn.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
279 //rRgn = aMirroredRegion;
283 void SalGraphics::mirror( tools::Rectangle& rRect, const OutputDevice *pOutDev, bool bBack ) const
285 long nWidth = rRect.GetWidth();
286 long x = rRect.Left();
287 long x_org = x;
289 mirror( x, nWidth, pOutDev, bBack );
290 rRect.Move( x - x_org, 0 );
293 basegfx::B2DPoint SalGraphics::mirror( const basegfx::B2DPoint& i_rPoint, const OutputDevice* i_pOutDev ) const
295 const basegfx::B2DHomMatrix& rMirror(getMirror(i_pOutDev));
297 if(rMirror.isIdentity())
299 return i_rPoint;
301 else
303 return rMirror * i_rPoint;
307 basegfx::B2DPolyPolygon SalGraphics::mirror( const basegfx::B2DPolyPolygon& i_rPoly, const OutputDevice* i_pOutDev ) const
309 const basegfx::B2DHomMatrix& rMirror(getMirror(i_pOutDev));
311 if(rMirror.isIdentity())
313 return i_rPoly;
315 else
317 basegfx::B2DPolyPolygon aRet(i_rPoly);
318 aRet.transform(rMirror);
319 aRet.flip();
320 return aRet;
324 const basegfx::B2DHomMatrix& SalGraphics::getMirror( const OutputDevice* i_pOutDev ) const
326 // get mirroring transformation
327 const long w = GetDeviceWidth(i_pOutDev);
328 SAL_WARN_IF( !w, "vcl", "missing graphics width" );
330 if(w != m_aLastMirrorW)
332 const_cast<SalGraphics*>(this)->m_aLastMirrorW = w;
334 if(w)
336 if(nullptr != i_pOutDev && !i_pOutDev->IsRTLEnabled())
338 // Original code was (removed here already pOutDevRef->i_pOutDev):
339 // // mirror this window back
340 // double devX = w-i_pOutDev->GetOutputWidthPixel()-i_pOutDev->GetOutOffXPixel(); // re-mirrored mnOutOffX
341 // aRet.setX( devX + (i_rPoint.getX() - i_pOutDev->GetOutOffXPixel()) );
342 // I do not really understand the comment 'mirror this window back', so cannot guarantee
343 // that this works as before, but I have reduced this (by re-placing and re-formatting) to
344 // a simple translation:
345 const_cast<SalGraphics*>(this)->m_aLastMirror = basegfx::utils::createTranslateB2DHomMatrix(
346 w - i_pOutDev->GetOutputWidthPixel() - (2 * i_pOutDev->GetOutOffXPixel()),
347 0.0);
349 else
351 // Original code was:
352 // aRet.setX( w-1-i_rPoint.getX() );
353 // -mirror X -> scale(-1.0, 1.0)
354 // -translate X -> translate(w-1, 0); but already mirrored, so use translate(1-w, 0)
355 // Checked this one, works as expected.
356 const_cast<SalGraphics*>(this)->m_aLastMirror = basegfx::utils::createScaleTranslateB2DHomMatrix(
357 -1.0,
358 1.0,
359 1-w,
360 0.0);
363 else
365 const_cast<SalGraphics*>(this)->m_aLastMirror.identity();
369 return m_aLastMirror;
372 basegfx::B2DHomMatrix SalGraphics::mirror( const basegfx::B2DHomMatrix& i_rMatrix, const OutputDevice *pOutDev ) const
374 // add mirroring transformation to i_rMatrix
375 const basegfx::B2DHomMatrix& rMirror(getMirror(pOutDev));
377 // Apply mirror to given matrix by multiply from left ('after' i_rMatrix).
378 // Identity checks and fast-paths are in the operator
379 return rMirror * i_rMatrix;
382 bool SalGraphics::SetClipRegion( const vcl::Region& i_rClip, const OutputDevice *pOutDev )
384 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
386 vcl::Region aMirror( i_rClip );
387 mirror( aMirror, pOutDev );
388 return setClipRegion( aMirror );
390 return setClipRegion( i_rClip );
393 void SalGraphics::DrawPixel( long nX, long nY, const OutputDevice *pOutDev )
395 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
396 mirror( nX, pOutDev );
397 drawPixel( nX, nY );
400 void SalGraphics::DrawPixel( long nX, long nY, Color nColor, const OutputDevice *pOutDev )
402 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
403 mirror( nX, pOutDev );
404 drawPixel( nX, nY, nColor );
407 void SalGraphics::DrawLine( long nX1, long nY1, long nX2, long nY2, const OutputDevice *pOutDev )
409 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
411 mirror( nX1, pOutDev );
412 mirror( nX2, pOutDev );
414 drawLine( nX1, nY1, nX2, nY2 );
417 void SalGraphics::DrawRect( long nX, long nY, long nWidth, long nHeight, const OutputDevice *pOutDev )
419 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
420 mirror( nX, nWidth, pOutDev );
421 drawRect( nX, nY, nWidth, nHeight );
424 void SalGraphics::DrawPolyLine( sal_uInt32 nPoints, SalPoint const * pPtAry, const OutputDevice *pOutDev )
426 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
428 std::unique_ptr<SalPoint[]> pPtAry2(new SalPoint[nPoints]);
429 bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev );
430 drawPolyLine( nPoints, bCopied ? pPtAry2.get() : pPtAry );
432 else
433 drawPolyLine( nPoints, pPtAry );
436 void SalGraphics::DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry, const OutputDevice *pOutDev )
438 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
440 std::unique_ptr<SalPoint[]> pPtAry2(new SalPoint[nPoints]);
441 bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev );
442 drawPolygon( nPoints, bCopied ? pPtAry2.get() : pPtAry );
444 else
445 drawPolygon( nPoints, pPtAry );
448 void SalGraphics::DrawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry, const OutputDevice *pOutDev )
450 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
452 // TODO: optimize, reduce new/delete calls
453 std::unique_ptr<SalPoint*[]> pPtAry2( new SalPoint*[nPoly] );
454 sal_uLong i;
455 for(i=0; i<nPoly; i++)
457 sal_uLong nPoints = pPoints[i];
458 pPtAry2[i] = new SalPoint[ nPoints ];
459 mirror( nPoints, pPtAry[i], pPtAry2[i], pOutDev );
462 drawPolyPolygon( nPoly, pPoints, const_cast<PCONSTSALPOINT*>(pPtAry2.get()) );
464 for(i=0; i<nPoly; i++)
465 delete [] pPtAry2[i];
467 else
468 drawPolyPolygon( nPoly, pPoints, pPtAry );
471 bool SalGraphics::DrawPolyPolygon(
472 const basegfx::B2DHomMatrix& rObjectToDevice,
473 const basegfx::B2DPolyPolygon& i_rPolyPolygon,
474 double i_fTransparency,
475 const OutputDevice* i_pOutDev)
477 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
479 // mirroring set
480 const basegfx::B2DHomMatrix& rMirror(getMirror(i_pOutDev));
482 if(!rMirror.isIdentity())
484 if(rObjectToDevice.isIdentity())
486 // There is no ObjectToDevice transformation set. We can just
487 // use rMirror, that would be the result of the linear combination
488 return drawPolyPolygon(
489 rMirror,
490 i_rPolyPolygon,
491 i_fTransparency);
493 else
495 // Create the linear combination
496 basegfx::B2DHomMatrix aLinearCombination(rObjectToDevice);
497 basegfx::B2DHomMatrix aObjectToDeviceInv(rObjectToDevice);
499 aLinearCombination = rMirror * aLinearCombination;
500 aObjectToDeviceInv.invert();
501 aLinearCombination = aObjectToDeviceInv * aLinearCombination;
503 return drawPolyPolygon(
504 aLinearCombination,
505 i_rPolyPolygon,
506 i_fTransparency);
511 return drawPolyPolygon(
512 rObjectToDevice,
513 i_rPolyPolygon,
514 i_fTransparency);
517 bool SalGraphics::DrawPolyLineBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry, const OutputDevice* pOutDev )
519 bool bResult = false;
520 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
522 std::unique_ptr<SalPoint[]> pPtAry2(new SalPoint[nPoints]);
523 bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev );
524 bResult = drawPolyLineBezier( nPoints, bCopied ? pPtAry2.get() : pPtAry, pFlgAry );
526 else
527 bResult = drawPolyLineBezier( nPoints, pPtAry, pFlgAry );
528 return bResult;
531 bool SalGraphics::DrawPolygonBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry, const OutputDevice* pOutDev )
533 bool bResult = false;
534 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
536 std::unique_ptr<SalPoint[]> pPtAry2(new SalPoint[nPoints]);
537 bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev );
538 bResult = drawPolygonBezier( nPoints, bCopied ? pPtAry2.get() : pPtAry, pFlgAry );
540 else
541 bResult = drawPolygonBezier( nPoints, pPtAry, pFlgAry );
542 return bResult;
545 bool SalGraphics::DrawPolyPolygonBezier( sal_uInt32 i_nPoly, const sal_uInt32* i_pPoints,
546 const SalPoint* const* i_pPtAry, const PolyFlags* const* i_pFlgAry, const OutputDevice* i_pOutDev )
548 bool bRet = false;
549 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
551 // TODO: optimize, reduce new/delete calls
552 std::unique_ptr<SalPoint*[]> pPtAry2( new SalPoint*[i_nPoly] );
553 sal_uLong i;
554 for(i=0; i<i_nPoly; i++)
556 sal_uLong nPoints = i_pPoints[i];
557 pPtAry2[i] = new SalPoint[ nPoints ];
558 mirror( nPoints, i_pPtAry[i], pPtAry2[i], i_pOutDev );
561 bRet = drawPolyPolygonBezier( i_nPoly, i_pPoints, const_cast<PCONSTSALPOINT const *>(pPtAry2.get()), i_pFlgAry );
563 for(i=0; i<i_nPoly; i++)
564 delete [] pPtAry2[i];
566 else
567 bRet = drawPolyPolygonBezier( i_nPoly, i_pPoints, i_pPtAry, i_pFlgAry );
568 return bRet;
571 bool SalGraphics::DrawPolyLine(
572 const basegfx::B2DHomMatrix& rObjectToDevice,
573 const basegfx::B2DPolygon& i_rPolygon,
574 double i_fTransparency,
575 const basegfx::B2DVector& i_rLineWidth,
576 basegfx::B2DLineJoin i_eLineJoin,
577 css::drawing::LineCap i_eLineCap,
578 double i_fMiterMinimumAngle,
579 bool bPixelSnapHairline,
580 const OutputDevice* i_pOutDev)
582 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
584 // mirroring set
585 const basegfx::B2DHomMatrix& rMirror(getMirror(i_pOutDev));
587 if(!rMirror.isIdentity())
589 // If we really have a mirroring to apply, we *could*
590 // use the ::mirror call to modify the B2DPolygon (and
591 // prepare the LineWidth scaling), but we also
592 // can add that mirroring to rObjectToDevice transformation
593 // by using linear combination of transformations and stay
594 // on having the transformation
595 if(rObjectToDevice.isIdentity())
597 // There is no ObjectToDevice transformation set. We can just
598 // use rMirror, that would be the result of the linear combination
599 return drawPolyLine(
600 rMirror,
601 i_rPolygon,
602 i_fTransparency,
603 i_rLineWidth,
604 i_eLineJoin,
605 i_eLineCap,
606 i_fMiterMinimumAngle,
607 bPixelSnapHairline);
609 else
611 // To create the linear combination, we need to
612 // - multiply with rObjectToDevice to get to device-coordinates
613 // (what is a simple copy)
614 // - apply rMirror (multiply from left)
615 // - multiply with inverse of rObjectToDevice to get back from
616 // device-coordinates to object-coordinates
617 // this only makes sense to do when we *have* an ObjectToDevice
618 // transformation, so optimize that
619 basegfx::B2DHomMatrix aLinearCombination(rObjectToDevice);
620 basegfx::B2DHomMatrix aObjectToDeviceInv(rObjectToDevice);
622 aLinearCombination = rMirror * aLinearCombination;
623 aObjectToDeviceInv.invert();
624 aLinearCombination = aObjectToDeviceInv * aLinearCombination;
626 return drawPolyLine(
627 aLinearCombination,
628 i_rPolygon,
629 i_fTransparency,
630 i_rLineWidth,
631 i_eLineJoin,
632 i_eLineCap,
633 i_fMiterMinimumAngle,
634 bPixelSnapHairline);
639 // no mirroring set (or identity), use standard call
640 return drawPolyLine(
641 rObjectToDevice,
642 i_rPolygon,
643 i_fTransparency,
644 i_rLineWidth,
645 i_eLineJoin,
646 i_eLineCap,
647 i_fMiterMinimumAngle,
648 bPixelSnapHairline);
651 bool SalGraphics::DrawGradient( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient )
653 return drawGradient( rPolyPoly, rGradient );
656 bool SalGraphics::DrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rSalGradient)
658 return implDrawGradient(rPolyPolygon, rSalGradient);
661 void SalGraphics::CopyArea( long nDestX, long nDestY,
662 long nSrcX, long nSrcY,
663 long nSrcWidth, long nSrcHeight,
664 const OutputDevice *pOutDev )
666 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
668 mirror( nDestX, nSrcWidth, pOutDev );
669 mirror( nSrcX, nSrcWidth, pOutDev );
671 copyArea( nDestX, nDestY, nSrcX, nSrcY, nSrcWidth, nSrcHeight, true/*bWindowInvalidate*/ );
674 void SalGraphics::CopyBits( const SalTwoRect& rPosAry,
675 SalGraphics* pSrcGraphics, const OutputDevice *pOutDev, const OutputDevice *pSrcOutDev )
677 if( ( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) ||
678 (pSrcGraphics && ( (pSrcGraphics->GetLayout() & SalLayoutFlags::BiDiRtl) || (pSrcOutDev && pSrcOutDev->IsRTLEnabled()) ) ) )
680 SalTwoRect aPosAry2 = rPosAry;
681 if( (pSrcGraphics && (pSrcGraphics->GetLayout() & SalLayoutFlags::BiDiRtl)) || (pSrcOutDev && pSrcOutDev->IsRTLEnabled()) )
682 mirror( aPosAry2.mnSrcX, aPosAry2.mnSrcWidth, pSrcOutDev );
683 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
684 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
685 copyBits( aPosAry2, pSrcGraphics );
687 else
688 copyBits( rPosAry, pSrcGraphics );
691 void SalGraphics::DrawBitmap( const SalTwoRect& rPosAry,
692 const SalBitmap& rSalBitmap, const OutputDevice *pOutDev )
694 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
696 SalTwoRect aPosAry2 = rPosAry;
697 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
698 drawBitmap( aPosAry2, rSalBitmap );
700 else
701 drawBitmap( rPosAry, rSalBitmap );
704 void SalGraphics::DrawBitmap( const SalTwoRect& rPosAry,
705 const SalBitmap& rSalBitmap,
706 const SalBitmap& rTransparentBitmap, const OutputDevice *pOutDev )
708 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
710 SalTwoRect aPosAry2 = rPosAry;
711 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
712 drawBitmap( aPosAry2, rSalBitmap, rTransparentBitmap );
714 else
715 drawBitmap( rPosAry, rSalBitmap, rTransparentBitmap );
718 void SalGraphics::DrawMask( const SalTwoRect& rPosAry,
719 const SalBitmap& rSalBitmap,
720 Color nMaskColor, const OutputDevice *pOutDev )
722 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
724 SalTwoRect aPosAry2 = rPosAry;
725 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
726 drawMask( aPosAry2, rSalBitmap, nMaskColor );
728 else
729 drawMask( rPosAry, rSalBitmap, nMaskColor );
732 std::shared_ptr<SalBitmap> SalGraphics::GetBitmap( long nX, long nY, long nWidth, long nHeight, const OutputDevice *pOutDev )
734 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
735 mirror( nX, nWidth, pOutDev );
736 return getBitmap( nX, nY, nWidth, nHeight );
739 Color SalGraphics::GetPixel( long nX, long nY, const OutputDevice *pOutDev )
741 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
742 mirror( nX, pOutDev );
743 return getPixel( nX, nY );
746 void SalGraphics::Invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags, const OutputDevice *pOutDev )
748 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
749 mirror( nX, nWidth, pOutDev );
750 invert( nX, nY, nWidth, nHeight, nFlags );
753 void SalGraphics::Invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags, const OutputDevice *pOutDev )
755 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
757 std::unique_ptr<SalPoint[]> pPtAry2(new SalPoint[nPoints]);
758 bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev );
759 invert( nPoints, bCopied ? pPtAry2.get() : pPtAry, nFlags );
761 else
762 invert( nPoints, pPtAry, nFlags );
765 bool SalGraphics::DrawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uInt32 nSize, const OutputDevice *pOutDev )
767 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
768 mirror( nX, nWidth, pOutDev );
769 return drawEPS( nX, nY, nWidth, nHeight, pPtr, nSize );
772 bool SalGraphics::HitTestNativeScrollbar( ControlPart nPart, const tools::Rectangle& rControlRegion,
773 const Point& aPos, bool& rIsInside, const OutputDevice *pOutDev )
775 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
777 Point pt( aPos );
778 tools::Rectangle rgn( rControlRegion );
779 pt.setX( mirror2( pt.X(), pOutDev ) );
780 mirror( rgn, pOutDev );
781 return forWidget()->hitTestNativeControl( ControlType::Scrollbar, nPart, rgn, pt, rIsInside );
783 else
784 return forWidget()->hitTestNativeControl( ControlType::Scrollbar, nPart, rControlRegion, aPos, rIsInside );
787 void SalGraphics::mirror( ImplControlValue& rVal, const OutputDevice* pOutDev ) const
789 switch( rVal.getType() )
791 case ControlType::Slider:
793 SliderValue* pSlVal = static_cast<SliderValue*>(&rVal);
794 mirror(pSlVal->maThumbRect,pOutDev);
796 break;
797 case ControlType::Scrollbar:
799 ScrollbarValue* pScVal = static_cast<ScrollbarValue*>(&rVal);
800 mirror(pScVal->maThumbRect,pOutDev);
801 mirror(pScVal->maButton1Rect,pOutDev);
802 mirror(pScVal->maButton2Rect,pOutDev);
804 break;
805 case ControlType::Spinbox:
806 case ControlType::SpinButtons:
808 SpinbuttonValue* pSpVal = static_cast<SpinbuttonValue*>(&rVal);
809 mirror(pSpVal->maUpperRect,pOutDev);
810 mirror(pSpVal->maLowerRect,pOutDev);
812 break;
813 case ControlType::Toolbar:
815 ToolbarValue* pTVal = static_cast<ToolbarValue*>(&rVal);
816 mirror(pTVal->maGripRect,pOutDev);
818 break;
819 default: break;
823 bool SalGraphics::DrawNativeControl( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion,
824 ControlState nState, const ImplControlValue& aValue,
825 const OUString& aCaption, const OutputDevice *pOutDev)
827 bool bRet = false;
828 tools::Rectangle aControlRegion(rControlRegion);
829 if (aControlRegion.IsEmpty())
830 return bRet;
832 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
834 mirror(aControlRegion, pOutDev);
835 std::unique_ptr< ImplControlValue > mirrorValue( aValue.clone());
836 mirror( *mirrorValue, pOutDev );
837 bRet = forWidget()->drawNativeControl(nType, nPart, aControlRegion, nState, *mirrorValue, aCaption);
839 else
840 bRet = forWidget()->drawNativeControl(nType, nPart, aControlRegion, nState, aValue, aCaption);
842 if (bRet && m_pWidgetDraw)
843 handleDamage(aControlRegion);
844 return bRet;
847 bool SalGraphics::GetNativeControlRegion( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion, ControlState nState,
848 const ImplControlValue& aValue,
849 tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion, const OutputDevice *pOutDev )
851 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
853 tools::Rectangle rgn( rControlRegion );
854 mirror( rgn, pOutDev );
855 std::unique_ptr< ImplControlValue > mirrorValue( aValue.clone());
856 mirror( *mirrorValue, pOutDev );
857 if (forWidget()->getNativeControlRegion(nType, nPart, rgn, nState, *mirrorValue, OUString(), rNativeBoundingRegion, rNativeContentRegion))
859 mirror( rNativeBoundingRegion, pOutDev, true );
860 mirror( rNativeContentRegion, pOutDev, true );
861 return true;
863 return false;
865 else
866 return forWidget()->getNativeControlRegion(nType, nPart, rControlRegion, nState, aValue, OUString(), rNativeBoundingRegion, rNativeContentRegion);
869 bool SalGraphics::BlendBitmap( const SalTwoRect& rPosAry,
870 const SalBitmap& rBitmap,
871 const OutputDevice *pOutDev )
873 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
875 SalTwoRect aPosAry2 = rPosAry;
876 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
877 return blendBitmap( aPosAry2, rBitmap );
879 else
880 return blendBitmap( rPosAry, rBitmap );
883 bool SalGraphics::BlendAlphaBitmap( const SalTwoRect& rPosAry,
884 const SalBitmap& rSrcBitmap,
885 const SalBitmap& rMaskBitmap,
886 const SalBitmap& rAlphaBitmap,
887 const OutputDevice *pOutDev )
889 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
891 SalTwoRect aPosAry2 = rPosAry;
892 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
893 return blendAlphaBitmap( aPosAry2, rSrcBitmap, rMaskBitmap, rAlphaBitmap );
895 else
896 return blendAlphaBitmap( rPosAry, rSrcBitmap, rMaskBitmap, rAlphaBitmap );
899 bool SalGraphics::DrawAlphaBitmap( const SalTwoRect& rPosAry,
900 const SalBitmap& rSourceBitmap,
901 const SalBitmap& rAlphaBitmap,
902 const OutputDevice *pOutDev )
904 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
906 SalTwoRect aPosAry2 = rPosAry;
907 mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
908 return drawAlphaBitmap( aPosAry2, rSourceBitmap, rAlphaBitmap );
910 else
911 return drawAlphaBitmap( rPosAry, rSourceBitmap, rAlphaBitmap );
914 bool SalGraphics::DrawTransformedBitmap(
915 const basegfx::B2DPoint& rNull,
916 const basegfx::B2DPoint& rX,
917 const basegfx::B2DPoint& rY,
918 const SalBitmap& rSourceBitmap,
919 const SalBitmap* pAlphaBitmap,
920 const OutputDevice* pOutDev)
922 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
924 mirror(rNull, pOutDev);
925 mirror(rX, pOutDev);
926 mirror(rY, pOutDev);
928 return drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, pAlphaBitmap);
930 else
932 return drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, pAlphaBitmap);
936 bool SalGraphics::DrawAlphaRect( long nX, long nY, long nWidth, long nHeight,
937 sal_uInt8 nTransparency, const OutputDevice *pOutDev )
939 if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) )
940 mirror( nX, nWidth, pOutDev );
942 return drawAlphaRect( nX, nY, nWidth, nHeight, nTransparency );
945 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */