/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #if HAVE_FEATURE_OPENGL #include #include #include #ifdef _WIN32 #include #endif #endif #include #include #include #include #include // The only common SalFrame method SalFrameGeometry SalFrame::GetGeometry() const { // mirror frame coordinates at parent SalFrame *pParent = GetParent(); if( pParent && AllSettings::GetLayoutRTL() ) { SalFrameGeometry aGeom = maGeometry; int parent_x = aGeom.nX - pParent->maGeometry.nX; aGeom.nX = pParent->maGeometry.nX + pParent->maGeometry.nWidth - maGeometry.nWidth - parent_x; return aGeom; } else return maGeometry; } SalGraphics::SalGraphics() : m_nLayout( SalLayoutFlags::NONE ), m_aLastMirror(), m_aLastMirrorW(0), m_bAntiAliasB2DDraw(false) { // read global RTL settings if( AllSettings::GetLayoutRTL() ) m_nLayout = SalLayoutFlags::BiDiRtl; } bool SalGraphics::initWidgetDrawBackends(bool bForce) { bool bFileDefinitionsWidgetDraw = !!getenv("VCL_DRAW_WIDGETS_FROM_FILE"); if (bFileDefinitionsWidgetDraw || bForce) { m_pWidgetDraw.reset(new vcl::FileDefinitionWidgetDraw(*this)); auto pFileDefinitionWidgetDraw = static_cast(m_pWidgetDraw.get()); if (!pFileDefinitionWidgetDraw->isActive()) { m_pWidgetDraw.reset(); return false; } return true; } return false; } SalGraphics::~SalGraphics() COVERITY_NOEXCEPT_FALSE { // can't call ReleaseFonts here, as the destructor just calls this classes SetFont (pure virtual)! } #if HAVE_FEATURE_OPENGL namespace { void disableOpenGLAndTerminateForRestart() { OpenGLZone::hardDisable(); #ifdef _WIN32 TerminateProcess(GetCurrentProcess(), EXITHELPER_NORMAL_RESTART); #endif } } rtl::Reference SalGraphics::GetOpenGLContext() const { OpenGLSalGraphicsImpl *pImpl = dynamic_cast(GetImpl()); if (pImpl) { // If we notice that OpenGL is broken the first time being called, it is not too late to call // disableOpenGLAndTerminateForRestart(). The first time this will be called is from displaying // the splash screen, so if OpenGL is broken, it is "early enough" for us to be able to disable // OpenGL and terminate bluntly with EXITHELPER_NORMAL_RESTART, thus causing the wrapper process // to restart us, then without using OpenGL. static bool bFirstCall = true; rtl::Reference xRet(pImpl->GetOpenGLContext()); if (!xRet.is() && bFirstCall) disableOpenGLAndTerminateForRestart(); bFirstCall = false; return xRet; } return nullptr; } #endif bool SalGraphics::drawTransformedBitmap( const basegfx::B2DPoint& /* rNull */, const basegfx::B2DPoint& /* rX */, const basegfx::B2DPoint& /* rY */, const SalBitmap& /* rSourceBitmap */, const SalBitmap* /* pAlphaBitmap */) { // here direct support for transformed bitmaps can be implemented return false; } long SalGraphics::mirror2( long x, const OutputDevice *pOutDev ) const { mirror(x, pOutDev); return x; } inline long SalGraphics::GetDeviceWidth(const OutputDevice* pOutDev) const { return (pOutDev && pOutDev->IsVirtual()) ? pOutDev->GetOutputWidthPixel() : GetGraphicsWidth(); } void SalGraphics::mirror( long& x, const OutputDevice *pOutDev ) const { const long w = GetDeviceWidth(pOutDev); if( w ) { if( pOutDev && pOutDev->ImplIsAntiparallel() ) { OutputDevice *pOutDevRef = const_cast(pOutDev); // mirror this window back if( m_nLayout & SalLayoutFlags::BiDiRtl ) { long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX x = devX + (x - pOutDevRef->GetOutOffXPixel()); } else { long devX = pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX x = pOutDevRef->GetOutputWidthPixel() - (x - devX) + pOutDevRef->GetOutOffXPixel() - 1; } } else if( m_nLayout & SalLayoutFlags::BiDiRtl ) x = w-1-x; } } void SalGraphics::mirror( long& x, long nWidth, const OutputDevice *pOutDev, bool bBack ) const { const long w = GetDeviceWidth(pOutDev); if( w ) { if( pOutDev && pOutDev->ImplIsAntiparallel() ) { OutputDevice *pOutDevRef = const_cast(pOutDev); // mirror this window back if( m_nLayout & SalLayoutFlags::BiDiRtl ) { long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX if( bBack ) x = x - devX + pOutDevRef->GetOutOffXPixel(); else x = devX + (x - pOutDevRef->GetOutOffXPixel()); } else { long devX = pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX if( bBack ) x = devX + (pOutDevRef->GetOutputWidthPixel() + devX) - (x + nWidth); else x = pOutDevRef->GetOutputWidthPixel() - (x - devX) + pOutDevRef->GetOutOffXPixel() - nWidth; } } else if( m_nLayout & SalLayoutFlags::BiDiRtl ) x = w-nWidth-x; } } bool SalGraphics::mirror( sal_uInt32 nPoints, const SalPoint *pPtAry, SalPoint *pPtAry2, const OutputDevice *pOutDev ) const { const long w = GetDeviceWidth(pOutDev); if( w ) { sal_uInt32 i, j; if( pOutDev && pOutDev->ImplIsAntiparallel() ) { OutputDevice *pOutDevRef = const_cast(pOutDev); // mirror this window back if( m_nLayout & SalLayoutFlags::BiDiRtl ) { long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX for( i=0, j=nPoints-1; iGetOutOffXPixel()); pPtAry2[j].mnY = pPtAry[i].mnY; } } else { long devX = pOutDevRef->GetOutOffXPixel(); // re-mirrored mnOutOffX for( i=0, j=nPoints-1; iGetOutputWidthPixel() - (pPtAry[i].mnX - devX) + pOutDevRef->GetOutOffXPixel() - 1; pPtAry2[j].mnY = pPtAry[i].mnY; } } } else if( m_nLayout & SalLayoutFlags::BiDiRtl ) { for( i=0, j=nPoints-1; i(this)->m_aLastMirrorW = w; if(w) { if(nullptr != i_pOutDev && !i_pOutDev->IsRTLEnabled()) { // Original code was (removed here already pOutDevRef->i_pOutDev): // // mirror this window back // double devX = w-i_pOutDev->GetOutputWidthPixel()-i_pOutDev->GetOutOffXPixel(); // re-mirrored mnOutOffX // aRet.setX( devX + (i_rPoint.getX() - i_pOutDev->GetOutOffXPixel()) ); // I do not really understand the comment 'mirror this window back', so cannot guarantee // that this works as before, but I have reduced this (by re-placing and re-formatting) to // a simple translation: const_cast(this)->m_aLastMirror = basegfx::utils::createTranslateB2DHomMatrix( w - i_pOutDev->GetOutputWidthPixel() - (2 * i_pOutDev->GetOutOffXPixel()), 0.0); } else { // Original code was: // aRet.setX( w-1-i_rPoint.getX() ); // -mirror X -> scale(-1.0, 1.0) // -translate X -> translate(w-1, 0) // Checked this one, works as expected. const_cast(this)->m_aLastMirror = basegfx::utils::createScaleTranslateB2DHomMatrix( -1.0, 1.0, w-1, 0.0); } } else { const_cast(this)->m_aLastMirror.identity(); } } return m_aLastMirror; } bool SalGraphics::SetClipRegion( const vcl::Region& i_rClip, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { vcl::Region aMirror( i_rClip ); mirror( aMirror, pOutDev ); return setClipRegion( aMirror ); } return setClipRegion( i_rClip ); } void SalGraphics::DrawPixel( long nX, long nY, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) mirror( nX, pOutDev ); drawPixel( nX, nY ); } void SalGraphics::DrawPixel( long nX, long nY, Color nColor, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) mirror( nX, pOutDev ); drawPixel( nX, nY, nColor ); } void SalGraphics::DrawLine( long nX1, long nY1, long nX2, long nY2, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { mirror( nX1, pOutDev ); mirror( nX2, pOutDev ); } drawLine( nX1, nY1, nX2, nY2 ); } void SalGraphics::DrawRect( long nX, long nY, long nWidth, long nHeight, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) mirror( nX, nWidth, pOutDev ); drawRect( nX, nY, nWidth, nHeight ); } void SalGraphics::DrawPolyLine( sal_uInt32 nPoints, SalPoint const * pPtAry, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { std::unique_ptr pPtAry2(new SalPoint[nPoints]); bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev ); drawPolyLine( nPoints, bCopied ? pPtAry2.get() : pPtAry ); } else drawPolyLine( nPoints, pPtAry ); } void SalGraphics::DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { std::unique_ptr pPtAry2(new SalPoint[nPoints]); bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev ); drawPolygon( nPoints, bCopied ? pPtAry2.get() : pPtAry ); } else drawPolygon( nPoints, pPtAry ); } void SalGraphics::DrawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { // TODO: optimize, reduce new/delete calls std::unique_ptr pPtAry2( new SalPoint*[nPoly] ); sal_uLong i; for(i=0; i(pPtAry2.get()) ); for(i=0; iIsRTLEnabled()) ) { // mirroring set const basegfx::B2DHomMatrix& rMirror(getMirror(i_pOutDev)); if(!rMirror.isIdentity()) { basegfx::B2DRange aBoundingBox(i_rPolyPolygon.getB2DRange()); aBoundingBox *= rObjectToDevice; auto aTranslateToMirroredBounds = createTranslateToMirroredBounds(aBoundingBox, rMirror); return drawPolyPolygon( aTranslateToMirroredBounds * rObjectToDevice, i_rPolyPolygon, i_fTransparency); } } return drawPolyPolygon( rObjectToDevice, i_rPolyPolygon, i_fTransparency); } bool SalGraphics::DrawPolyLineBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry, const OutputDevice* pOutDev ) { bool bResult = false; if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { std::unique_ptr pPtAry2(new SalPoint[nPoints]); bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev ); bResult = drawPolyLineBezier( nPoints, bCopied ? pPtAry2.get() : pPtAry, pFlgAry ); } else bResult = drawPolyLineBezier( nPoints, pPtAry, pFlgAry ); return bResult; } bool SalGraphics::DrawPolygonBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry, const OutputDevice* pOutDev ) { bool bResult = false; if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { std::unique_ptr pPtAry2(new SalPoint[nPoints]); bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev ); bResult = drawPolygonBezier( nPoints, bCopied ? pPtAry2.get() : pPtAry, pFlgAry ); } else bResult = drawPolygonBezier( nPoints, pPtAry, pFlgAry ); return bResult; } bool SalGraphics::DrawPolyPolygonBezier( sal_uInt32 i_nPoly, const sal_uInt32* i_pPoints, const SalPoint* const* i_pPtAry, const PolyFlags* const* i_pFlgAry, const OutputDevice* i_pOutDev ) { bool bRet = false; if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) ) { // TODO: optimize, reduce new/delete calls std::unique_ptr pPtAry2( new SalPoint*[i_nPoly] ); sal_uLong i; for(i=0; i(pPtAry2.get()), i_pFlgAry ); for(i=0; i* i_pStroke, // MM01 basegfx::B2DLineJoin i_eLineJoin, css::drawing::LineCap i_eLineCap, double i_fMiterMinimumAngle, bool bPixelSnapHairline, const OutputDevice* i_pOutDev) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) ) { // mirroring set const basegfx::B2DHomMatrix& rMirror(getMirror(i_pOutDev)); if(!rMirror.isIdentity()) { basegfx::B2DRange aBoundingBox(i_rPolygon.getB2DRange()); aBoundingBox *= rObjectToDevice; auto aTranslateToMirroredBounds = createTranslateToMirroredBounds(aBoundingBox, rMirror); return drawPolyLine( aTranslateToMirroredBounds * rObjectToDevice, i_rPolygon, i_fTransparency, i_rLineWidth, i_pStroke, // MM01 i_eLineJoin, i_eLineCap, i_fMiterMinimumAngle, bPixelSnapHairline); } } // no mirroring set (or identity), use standard call return drawPolyLine( rObjectToDevice, i_rPolygon, i_fTransparency, i_rLineWidth, i_pStroke, // MM01 i_eLineJoin, i_eLineCap, i_fMiterMinimumAngle, bPixelSnapHairline); } bool SalGraphics::DrawGradient( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient ) { return drawGradient( rPolyPoly, rGradient ); } bool SalGraphics::DrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rSalGradient) { return implDrawGradient(rPolyPolygon, rSalGradient); } void SalGraphics::CopyArea( long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth, long nSrcHeight, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { mirror( nDestX, nSrcWidth, pOutDev ); mirror( nSrcX, nSrcWidth, pOutDev ); } copyArea( nDestX, nDestY, nSrcX, nSrcY, nSrcWidth, nSrcHeight, true/*bWindowInvalidate*/ ); } void SalGraphics::CopyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics, const OutputDevice *pOutDev, const OutputDevice *pSrcOutDev ) { if( ( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) || (pSrcGraphics && ( (pSrcGraphics->GetLayout() & SalLayoutFlags::BiDiRtl) || (pSrcOutDev && pSrcOutDev->IsRTLEnabled()) ) ) ) { SalTwoRect aPosAry2 = rPosAry; if( (pSrcGraphics && (pSrcGraphics->GetLayout() & SalLayoutFlags::BiDiRtl)) || (pSrcOutDev && pSrcOutDev->IsRTLEnabled()) ) mirror( aPosAry2.mnSrcX, aPosAry2.mnSrcWidth, pSrcOutDev ); if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev ); copyBits( aPosAry2, pSrcGraphics ); } else copyBits( rPosAry, pSrcGraphics ); } void SalGraphics::DrawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { SalTwoRect aPosAry2 = rPosAry; mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev ); drawBitmap( aPosAry2, rSalBitmap ); } else drawBitmap( rPosAry, rSalBitmap ); } void SalGraphics::DrawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, const SalBitmap& rTransparentBitmap, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { SalTwoRect aPosAry2 = rPosAry; mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev ); drawBitmap( aPosAry2, rSalBitmap, rTransparentBitmap ); } else drawBitmap( rPosAry, rSalBitmap, rTransparentBitmap ); } void SalGraphics::DrawMask( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, Color nMaskColor, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { SalTwoRect aPosAry2 = rPosAry; mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev ); drawMask( aPosAry2, rSalBitmap, nMaskColor ); } else drawMask( rPosAry, rSalBitmap, nMaskColor ); } std::shared_ptr SalGraphics::GetBitmap( long nX, long nY, long nWidth, long nHeight, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) mirror( nX, nWidth, pOutDev ); return getBitmap( nX, nY, nWidth, nHeight ); } Color SalGraphics::GetPixel( long nX, long nY, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) mirror( nX, pOutDev ); return getPixel( nX, nY ); } void SalGraphics::Invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) mirror( nX, nWidth, pOutDev ); invert( nX, nY, nWidth, nHeight, nFlags ); } void SalGraphics::Invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { std::unique_ptr pPtAry2(new SalPoint[nPoints]); bool bCopied = mirror( nPoints, pPtAry, pPtAry2.get(), pOutDev ); invert( nPoints, bCopied ? pPtAry2.get() : pPtAry, nFlags ); } else invert( nPoints, pPtAry, nFlags ); } bool SalGraphics::DrawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uInt32 nSize, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) mirror( nX, nWidth, pOutDev ); return drawEPS( nX, nY, nWidth, nHeight, pPtr, nSize ); } bool SalGraphics::HitTestNativeScrollbar( ControlPart nPart, const tools::Rectangle& rControlRegion, const Point& aPos, bool& rIsInside, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { Point pt( aPos ); tools::Rectangle rgn( rControlRegion ); pt.setX( mirror2( pt.X(), pOutDev ) ); mirror( rgn, pOutDev ); return forWidget()->hitTestNativeControl( ControlType::Scrollbar, nPart, rgn, pt, rIsInside ); } else return forWidget()->hitTestNativeControl( ControlType::Scrollbar, nPart, rControlRegion, aPos, rIsInside ); } void SalGraphics::mirror( ImplControlValue& rVal, const OutputDevice* pOutDev ) const { switch( rVal.getType() ) { case ControlType::Slider: { SliderValue* pSlVal = static_cast(&rVal); mirror(pSlVal->maThumbRect,pOutDev); } break; case ControlType::Scrollbar: { ScrollbarValue* pScVal = static_cast(&rVal); mirror(pScVal->maThumbRect,pOutDev); mirror(pScVal->maButton1Rect,pOutDev); mirror(pScVal->maButton2Rect,pOutDev); } break; case ControlType::Spinbox: case ControlType::SpinButtons: { SpinbuttonValue* pSpVal = static_cast(&rVal); mirror(pSpVal->maUpperRect,pOutDev); mirror(pSpVal->maLowerRect,pOutDev); } break; case ControlType::Toolbar: { ToolbarValue* pTVal = static_cast(&rVal); mirror(pTVal->maGripRect,pOutDev); } break; default: break; } } bool SalGraphics::DrawNativeControl( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion, ControlState nState, const ImplControlValue& aValue, const OUString& aCaption, const OutputDevice *pOutDev, const Color& rBackgroundColor) { bool bRet = false; tools::Rectangle aControlRegion(rControlRegion); if (aControlRegion.IsEmpty() || aControlRegion.GetWidth() <= 0 || aControlRegion.GetHeight() <= 0) return bRet; if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { mirror(aControlRegion, pOutDev); std::unique_ptr< ImplControlValue > mirrorValue( aValue.clone()); mirror( *mirrorValue, pOutDev ); bRet = forWidget()->drawNativeControl(nType, nPart, aControlRegion, nState, *mirrorValue, aCaption, rBackgroundColor); } else bRet = forWidget()->drawNativeControl(nType, nPart, aControlRegion, nState, aValue, aCaption, rBackgroundColor); if (bRet && m_pWidgetDraw) handleDamage(aControlRegion); return bRet; } bool SalGraphics::GetNativeControlRegion( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion, ControlState nState, const ImplControlValue& aValue, tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { tools::Rectangle rgn( rControlRegion ); mirror( rgn, pOutDev ); std::unique_ptr< ImplControlValue > mirrorValue( aValue.clone()); mirror( *mirrorValue, pOutDev ); if (forWidget()->getNativeControlRegion(nType, nPart, rgn, nState, *mirrorValue, OUString(), rNativeBoundingRegion, rNativeContentRegion)) { mirror( rNativeBoundingRegion, pOutDev, true ); mirror( rNativeContentRegion, pOutDev, true ); return true; } return false; } else return forWidget()->getNativeControlRegion(nType, nPart, rControlRegion, nState, aValue, OUString(), rNativeBoundingRegion, rNativeContentRegion); } bool SalGraphics::BlendBitmap( const SalTwoRect& rPosAry, const SalBitmap& rBitmap, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { SalTwoRect aPosAry2 = rPosAry; mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev ); return blendBitmap( aPosAry2, rBitmap ); } else return blendBitmap( rPosAry, rBitmap ); } bool SalGraphics::BlendAlphaBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSrcBitmap, const SalBitmap& rMaskBitmap, const SalBitmap& rAlphaBitmap, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { SalTwoRect aPosAry2 = rPosAry; mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev ); return blendAlphaBitmap( aPosAry2, rSrcBitmap, rMaskBitmap, rAlphaBitmap ); } else return blendAlphaBitmap( rPosAry, rSrcBitmap, rMaskBitmap, rAlphaBitmap ); } bool SalGraphics::DrawAlphaBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSourceBitmap, const SalBitmap& rAlphaBitmap, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { SalTwoRect aPosAry2 = rPosAry; mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev ); return drawAlphaBitmap( aPosAry2, rSourceBitmap, rAlphaBitmap ); } else return drawAlphaBitmap( rPosAry, rSourceBitmap, rAlphaBitmap ); } bool SalGraphics::DrawTransformedBitmap( const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX, const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap, const SalBitmap* pAlphaBitmap, const OutputDevice* pOutDev) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) { // mirroring set const basegfx::B2DHomMatrix& rMirror(getMirror(pOutDev)); if (!rMirror.isIdentity()) { basegfx::B2DPolygon aPoints({rNull, rX, rY}); basegfx::B2DRange aBoundingBox(aPoints.getB2DRange()); auto aTranslateToMirroredBounds = createTranslateToMirroredBounds(aBoundingBox, rMirror); basegfx::B2DPoint aNull = aTranslateToMirroredBounds * rNull; basegfx::B2DPoint aX = aTranslateToMirroredBounds * rX; basegfx::B2DPoint aY = aTranslateToMirroredBounds * rY; return drawTransformedBitmap(aNull, aX, aY, rSourceBitmap, pAlphaBitmap); } } return drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, pAlphaBitmap); } bool SalGraphics::DrawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency, const OutputDevice *pOutDev ) { if( (m_nLayout & SalLayoutFlags::BiDiRtl) || (pOutDev && pOutDev->IsRTLEnabled()) ) mirror( nX, nWidth, pOutDev ); return drawAlphaRect( nX, nY, nWidth, nHeight, nTransparency ); } OUString SalGraphics::getRenderBackendName() const { if (GetImpl()) return GetImpl()->getRenderBackendName(); return OUString(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */