diff options
Diffstat (limited to 'vcl/quartz')
-rw-r--r-- | vcl/quartz/salbmp.cxx | 50 | ||||
-rw-r--r-- | vcl/quartz/salgdicommon.cxx | 429 | ||||
-rw-r--r-- | vcl/quartz/salgdiutils.cxx | 270 | ||||
-rw-r--r-- | vcl/quartz/salvd.cxx | 133 |
4 files changed, 13 insertions, 869 deletions
diff --git a/vcl/quartz/salbmp.cxx b/vcl/quartz/salbmp.cxx index aa932de1fc69..e798f9027d04 100644 --- a/vcl/quartz/salbmp.cxx +++ b/vcl/quartz/salbmp.cxx @@ -69,56 +69,6 @@ QuartzSalBitmap::~QuartzSalBitmap() doDestroy(); } -bool QuartzSalBitmap::Create(CGLayerHolder const & rLayerHolder, int nBitmapBits, int nX, int nY, int nWidth, int nHeight, bool bFlipped) -{ - SAL_WARN_IF(!rLayerHolder.isSet(), "vcl", "QuartzSalBitmap::Create() from non-layered context"); - - // sanitize input parameters - if( nX < 0 ) { - nWidth += nX; - nX = 0; - } - - if( nY < 0 ) { - nHeight += nY; - nY = 0; - } - - const CGSize aLayerSize = CGLayerGetSize(rLayerHolder.get()); - - if( nWidth >= static_cast<int>(aLayerSize.width) - nX ) - nWidth = static_cast<int>(aLayerSize.width) - nX; - - if( nHeight >= static_cast<int>(aLayerSize.height) - nY ) - nHeight = static_cast<int>(aLayerSize.height) - nY; - - if( (nWidth < 0) || (nHeight < 0) ) - nWidth = nHeight = 0; - - // initialize properties - mnWidth = nWidth; - mnHeight = nHeight; - mnBits = nBitmapBits ? nBitmapBits : 32; - - // initialize drawing context - CreateContext(); - - // copy layer content into the bitmap buffer - const CGPoint aSrcPoint = { static_cast<CGFloat>(-nX), static_cast<CGFloat>(-nY) }; - if (maGraphicContext.isSet()) // remove warning - { - if( bFlipped ) - { - CGContextTranslateCTM( maGraphicContext.get(), 0, +mnHeight ); - - CGContextScaleCTM( maGraphicContext.get(), +1, -1 ); - } - - CGContextDrawLayerAtPoint(maGraphicContext.get(), aSrcPoint, rLayerHolder.get()); - } - return true; -} - bool QuartzSalBitmap::Create( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rBitmapPalette ) { if( !isValidBitCount( nBits ) ) diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx index d33b690fdaff..e393659658d6 100644 --- a/vcl/quartz/salgdicommon.cxx +++ b/vcl/quartz/salgdicommon.cxx @@ -127,21 +127,6 @@ static void AddPolygonToPath( CGMutablePathRef xPath, } } -static void AddPolyPolygonToPath( CGMutablePathRef xPath, - const basegfx::B2DPolyPolygon& rPolyPoly, - bool bPixelSnap, bool bLineDraw ) -{ - // short circuit if there is nothing to do - if( rPolyPoly.count() == 0 ) - { - return; - } - for(auto const& rPolygon : rPolyPoly) - { - AddPolygonToPath( xPath, rPolygon, true, bPixelSnap, bLineDraw ); - } -} - bool AquaSalGraphics::CreateFontSubset( const OUString& rToFile, const PhysicalFontFace* pFontData, const sal_GlyphId* pGlyphIds, const sal_uInt8* pEncoding, @@ -199,109 +184,6 @@ static void alignLinePoint( const Point* i_pIn, float& o_fX, float& o_fY ) o_fY = static_cast<float>(i_pIn->getY() ) + 0.5; } -void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGraphics ) -{ - - if( !pSrcGraphics ) - { - pSrcGraphics = this; - } - //from unix salgdi2.cxx - //[FIXME] find a better way to prevent calc from crashing when width and height are negative - if( rPosAry.mnSrcWidth <= 0 || - rPosAry.mnSrcHeight <= 0 || - rPosAry.mnDestWidth <= 0 || - rPosAry.mnDestHeight <= 0 ) - { - return; - } - -#ifdef IOS - // If called from idle layout, maContextHolder.get() is NULL, no idea what to do - if (!maContextHolder.isSet()) - return; -#endif - - // accelerate trivial operations - /*const*/ AquaSalGraphics* pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics); - const bool bSameGraphics = (this == pSrc) -#ifdef MACOSX - || (mbWindow && mpFrame && pSrc->mbWindow && (mpFrame == pSrc->mpFrame)) -#endif - ; - - if( bSameGraphics && - (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) && - (rPosAry.mnSrcHeight == rPosAry.mnDestHeight)) - { - // short circuit if there is nothing to do - if( (rPosAry.mnSrcX == rPosAry.mnDestX) && - (rPosAry.mnSrcY == rPosAry.mnDestY)) - { - return; - } - // use copyArea() if source and destination context are identical - copyArea( rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, false/*bWindowInvalidate*/ ); - return; - } - - ApplyXorContext(); - pSrc->ApplyXorContext(); - - SAL_WARN_IF (!pSrc->maLayer.isSet(), "vcl.quartz", - "AquaSalGraphics::copyBits() from non-layered graphics this=" << this); - - const CGPoint aDstPoint = CGPointMake(+rPosAry.mnDestX - rPosAry.mnSrcX, rPosAry.mnDestY - rPosAry.mnSrcY); - if ((rPosAry.mnSrcWidth == rPosAry.mnDestWidth && - rPosAry.mnSrcHeight == rPosAry.mnDestHeight) && - (!mnBitmapDepth || (aDstPoint.x + pSrc->mnWidth) <= mnWidth) - && pSrc->maLayer.isSet()) // workaround for a Quartz crash - { - // in XOR mode the drawing context is redirected to the XOR mask - // if source and target are identical then copyBits() paints onto the target context though - CGContextHolder aCopyContext = maContextHolder; - if( mpXorEmulation && mpXorEmulation->IsEnabled() ) - { - if( pSrcGraphics == this ) - { - aCopyContext.set(mpXorEmulation->GetTargetContext()); - } - } - aCopyContext.saveState(); - - const CGRect aDstRect = CGRectMake(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight); - CGContextClipToRect(aCopyContext.get(), aDstRect); - - // draw at new destination - // NOTE: flipped drawing gets disabled for this, else the subimage would be drawn upside down - if( pSrc->IsFlipped() ) - { - CGContextTranslateCTM( aCopyContext.get(), 0, +mnHeight ); - CGContextScaleCTM( aCopyContext.get(), +1, -1 ); - } - - // TODO: pSrc->size() != this->size() - CGContextDrawLayerAtPoint(aCopyContext.get(), aDstPoint, pSrc->maLayer.get()); - - aCopyContext.restoreState(); - // mark the destination rectangle as updated - RefreshRect( aDstRect ); - } - else - { - std::shared_ptr<SalBitmap> pBitmap = pSrc->getBitmap( rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ); - if( pBitmap ) - { - SalTwoRect aPosAry( rPosAry ); - aPosAry.mnSrcX = 0; - aPosAry.mnSrcY = 0; - drawBitmap( aPosAry, *pBitmap ); - } - } -} - static void DrawPattern50( void*, CGContextRef rContext ) { static const CGRect aRects[2] = { { {0,0}, { 2, 2 } }, { { 2, 2 }, { 2, 2 } } }; @@ -370,85 +252,6 @@ void AquaSalGraphics::ApplyXorContext() } } -void AquaSalGraphics::copyArea( - tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY, - tools::Long nSrcWidth, tools::Long nSrcHeight, bool /*bWindowInvalidate*/ ) -{ - SAL_WARN_IF (!maLayer.isSet(), "vcl.quartz", - "AquaSalGraphics::copyArea() for non-layered graphics this=" << this); - -#ifdef IOS - if (!maLayer.isSet()) - return; -#endif - float fScale = maLayer.getScale(); - - tools::Long nScaledSourceX = nSrcX * fScale; - tools::Long nScaledSourceY = nSrcY * fScale; - - tools::Long nScaledTargetX = nDstX * fScale; - tools::Long nScaledTargetY = nDstY * fScale; - - tools::Long nScaledSourceWidth = nSrcWidth * fScale; - tools::Long nScaledSourceHeight = nSrcHeight * fScale; - - ApplyXorContext(); - - maContextHolder.saveState(); - - // in XOR mode the drawing context is redirected to the XOR mask - // copyArea() always works on the target context though - CGContextRef xCopyContext = maContextHolder.get(); - - if( mpXorEmulation && mpXorEmulation->IsEnabled() ) - { - xCopyContext = mpXorEmulation->GetTargetContext(); - } - - // If we have a scaled layer, we need to revert the scaling or else - // it will interfere with the coordinate calculation - CGContextScaleCTM(xCopyContext, 1.0 / fScale, 1.0 / fScale); - - // drawing a layer onto its own context causes trouble on OSX => copy it first - // TODO: is it possible to get rid of this unneeded copy more often? - // e.g. on OSX>=10.5 only this situation causes problems: - // mnBitmapDepth && (aDstPoint.x + pSrc->mnWidth) > mnWidth - - CGLayerHolder sSourceLayerHolder(maLayer); - { - const CGSize aSrcSize = CGSizeMake(nScaledSourceWidth, nScaledSourceHeight); - sSourceLayerHolder.set(CGLayerCreateWithContext(xCopyContext, aSrcSize, nullptr)); - - const CGContextRef xSrcContext = CGLayerGetContext(sSourceLayerHolder.get()); - - CGPoint aSrcPoint = CGPointMake(-nScaledSourceX, -nScaledSourceY); - if( IsFlipped() ) - { - CGContextTranslateCTM( xSrcContext, 0, +nScaledSourceHeight ); - CGContextScaleCTM( xSrcContext, +1, -1 ); - aSrcPoint.y = (nScaledSourceY + nScaledSourceHeight) - (mnHeight * fScale); - } - CGContextSetBlendMode(xSrcContext, kCGBlendModeCopy); - - CGContextDrawLayerAtPoint(xSrcContext, aSrcPoint, maLayer.get()); - } - - // draw at new destination - const CGRect aTargetRect = CGRectMake(nScaledTargetX, nScaledTargetY, nScaledSourceWidth, nScaledSourceHeight); - CGContextSetBlendMode(xCopyContext, kCGBlendModeCopy); - CGContextDrawLayerInRect(xCopyContext, aTargetRect, sSourceLayerHolder.get()); - - maContextHolder.restoreState(); - - // cleanup - if (sSourceLayerHolder.get() != maLayer.get()) - { - CGLayerRelease(sSourceLayerHolder.get()); - } - // mark the destination rectangle as updated - RefreshRect( nDstX, nDstY, nSrcWidth, nSrcHeight ); -} - #ifndef IOS void AquaSalGraphics::copyResolution( AquaSalGraphics& rGraphics ) @@ -1613,30 +1416,21 @@ bool AquaSalGraphics::setClipRegion( const vcl::Region& i_rClip ) mxClipPath = CGPathCreateMutable(); // set current path, either as polypolgon or sequence of rectangles - if(i_rClip.HasPolyPolygonOrB2DPolyPolygon()) - { - const basegfx::B2DPolyPolygon aClip(i_rClip.GetAsB2DPolyPolygon()); + RectangleVector aRectangles; + i_rClip.GetRegionRectangles(aRectangles); - AddPolyPolygonToPath( mxClipPath, aClip, !getAntiAlias(), false ); - } - else + for(const auto& rRect : aRectangles) { - RectangleVector aRectangles; - i_rClip.GetRegionRectangles(aRectangles); + const tools::Long nW(rRect.Right() - rRect.Left() + 1); // uses +1 logic in original - for(const auto& rRect : aRectangles) + if(nW) { - const tools::Long nW(rRect.Right() - rRect.Left() + 1); // uses +1 logic in original + const tools::Long nH(rRect.Bottom() - rRect.Top() + 1); // uses +1 logic in original - if(nW) + if(nH) { - const tools::Long nH(rRect.Bottom() - rRect.Top() + 1); // uses +1 logic in original - - if(nH) - { - const CGRect aRect = CGRectMake( rRect.Left(), rRect.Top(), nW, nH); - CGPathAddRect( mxClipPath, nullptr, aRect ); - } + const CGRect aRect = CGRectMake( rRect.Left(), rRect.Top(), nW, nH); + CGPathAddRect( mxClipPath, nullptr, aRect ); } } } @@ -1750,209 +1544,4 @@ XorEmulation::~XorEmulation() SetTarget( 0, 0, 0, nullptr, nullptr ); } -void XorEmulation::SetTarget( int nWidth, int nHeight, int nTargetDepth, - CGContextRef xTargetContext, CGLayerRef xTargetLayer ) -{ - SAL_INFO( "vcl.quartz", "XorEmulation::SetTarget() this=" << this << - " (" << nWidth << "x" << nHeight << ") depth=" << nTargetDepth << - " context=" << xTargetContext << " layer=" << xTargetLayer ); - - // prepare to replace old mask+temp context - if( m_xMaskContext ) - { - // cleanup the mask context - CGContextRelease( m_xMaskContext ); - delete[] m_pMaskBuffer; - m_xMaskContext = nullptr; - m_pMaskBuffer = nullptr; - - // cleanup the temp context if needed - if( m_xTempContext ) - { - CGContextRelease( m_xTempContext ); - delete[] m_pTempBuffer; - m_xTempContext = nullptr; - m_pTempBuffer = nullptr; - } - } - - // return early if there is nothing more to do - if( !xTargetContext ) - { - return; - } - // retarget drawing operations to the XOR mask - m_xTargetLayer = xTargetLayer; - m_xTargetContext = xTargetContext; - - // prepare creation of matching CGBitmaps - CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; - CGBitmapInfo aCGBmpInfo = kCGImageAlphaNoneSkipFirst; - int nBitDepth = nTargetDepth; - if( !nBitDepth ) - { - nBitDepth = 32; - } - int nBytesPerRow = 4; - const size_t nBitsPerComponent = (nBitDepth == 16) ? 5 : 8; - if( nBitDepth <= 8 ) - { - aCGColorSpace = GetSalData()->mxGraySpace; - aCGBmpInfo = kCGImageAlphaNone; - nBytesPerRow = 1; - } - nBytesPerRow *= nWidth; - m_nBufferLongs = (nHeight * nBytesPerRow + sizeof(sal_uLong)-1) / sizeof(sal_uLong); - - // create a XorMask context - m_pMaskBuffer = new sal_uLong[ m_nBufferLongs ]; - m_xMaskContext = CGBitmapContextCreate( m_pMaskBuffer, - nWidth, nHeight, - nBitsPerComponent, nBytesPerRow, - aCGColorSpace, aCGBmpInfo ); - SAL_WARN_IF( !m_xMaskContext, "vcl.quartz", "mask context creation failed" ); - - // reset the XOR mask to black - memset( m_pMaskBuffer, 0, m_nBufferLongs * sizeof(sal_uLong) ); - - // a bitmap context will be needed for manual XORing - // create one unless the target context is a bitmap context - if( nTargetDepth ) - { - m_pTempBuffer = static_cast<sal_uLong*>(CGBitmapContextGetData( m_xTargetContext )); - } - if( !m_pTempBuffer ) - { - // create a bitmap context matching to the target context - m_pTempBuffer = new sal_uLong[ m_nBufferLongs ]; - m_xTempContext = CGBitmapContextCreate( m_pTempBuffer, - nWidth, nHeight, - nBitsPerComponent, nBytesPerRow, - aCGColorSpace, aCGBmpInfo ); - SAL_WARN_IF( !m_xTempContext, "vcl.quartz", "temp context creation failed" ); - } - - // initialize XOR mask context for drawing - CGContextSetFillColorSpace( m_xMaskContext, aCGColorSpace ); - CGContextSetStrokeColorSpace( m_xMaskContext, aCGColorSpace ); - CGContextSetShouldAntialias( m_xMaskContext, false ); - - // improve the XorMask's XOR emulation a little - // NOTE: currently only enabled for monochrome contexts - if( aCGColorSpace == GetSalData()->mxGraySpace ) - { - CGContextSetBlendMode( m_xMaskContext, kCGBlendModeDifference ); - } - // initialize the transformation matrix to the drawing target - const CGAffineTransform aCTM = CGContextGetCTM( xTargetContext ); - CGContextConcatCTM( m_xMaskContext, aCTM ); - if( m_xTempContext ) - { - CGContextConcatCTM( m_xTempContext, aCTM ); - } - // initialize the default XorMask graphics state - CGContextSaveGState( m_xMaskContext ); -} - -bool XorEmulation::UpdateTarget() -{ - SAL_INFO( "vcl.quartz", "XorEmulation::UpdateTarget() this=" << this ); - - if( !IsEnabled() ) - { - return false; - } - // update the temp bitmap buffer if needed - if( m_xTempContext ) - { - SAL_WARN_IF( m_xTargetContext == nullptr, "vcl.quartz", "Target layer is NULL"); - CGContextDrawLayerAtPoint( m_xTempContext, CGPointZero, m_xTargetLayer ); - } - // do a manual XOR with the XorMask - // this approach suffices for simple color manipulations - // and also the complex-clipping-XOR-trick used in metafiles - const sal_uLong* pSrc = m_pMaskBuffer; - sal_uLong* pDst = m_pTempBuffer; - for( int i = m_nBufferLongs; --i >= 0;) - { - *(pDst++) ^= *(pSrc++); - } - // write back the XOR results to the target context - if( m_xTempContext ) - { - CGImageRef xXorImage = CGBitmapContextCreateImage( m_xTempContext ); - const int nWidth = static_cast<int>(CGImageGetWidth( xXorImage )); - const int nHeight = static_cast<int>(CGImageGetHeight( xXorImage )); - // TODO: update minimal changerect - const CGRect aFullRect = CGRectMake(0, 0, nWidth, nHeight); - CGContextDrawImage( m_xTargetContext, aFullRect, xXorImage ); - CGImageRelease( xXorImage ); - } - - // reset the XorMask to black again - // TODO: not needed for last update - memset( m_pMaskBuffer, 0, m_nBufferLongs * sizeof(sal_uLong) ); - - // TODO: return FALSE if target was not changed - return true; -} - -void AquaSalGraphics::SetVirDevGraphics(CGLayerHolder const & rLayer, CGContextRef xContext, - int nBitmapDepth) -{ - SAL_INFO( "vcl.quartz", "SetVirDevGraphics() this=" << this << " layer=" << rLayer.get() << " context=" << xContext ); - -#ifndef IOS - mbWindow = false; -#endif - mbPrinter = false; - mbVirDev = true; - - // set graphics properties - maLayer = rLayer; - maContextHolder.set(xContext); - - mnBitmapDepth = nBitmapDepth; - -#ifdef IOS - mbForeignContext = xContext != NULL; -#endif - - // return early if the virdev is being destroyed - if( !xContext ) - return; - - // get new graphics properties - if (!maLayer.isSet()) - { - mnWidth = CGBitmapContextGetWidth( maContextHolder.get() ); - mnHeight = CGBitmapContextGetHeight( maContextHolder.get() ); - } - else - { - const CGSize aSize = CGLayerGetSize(maLayer.get()); - mnWidth = static_cast<int>(aSize.width); - mnHeight = static_cast<int>(aSize.height); - } - - // prepare graphics for drawing - const CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; - CGContextSetFillColorSpace( maContextHolder.get(), aCGColorSpace ); - CGContextSetStrokeColorSpace( maContextHolder.get(), aCGColorSpace ); - - // re-enable XorEmulation for the new context - if( mpXorEmulation ) - { - mpXorEmulation->SetTarget(mnWidth, mnHeight, mnBitmapDepth, maContextHolder.get(), maLayer.get()); - if( mpXorEmulation->IsEnabled() ) - { - maContextHolder.set(mpXorEmulation->GetMaskContext()); - } - } - - // initialize stack of CGContext states - maContextHolder.saveState(); - SetState(); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/salgdiutils.cxx b/vcl/quartz/salgdiutils.cxx deleted file mode 100644 index 985fe38a2d11..000000000000 --- a/vcl/quartz/salgdiutils.cxx +++ /dev/null @@ -1,270 +0,0 @@ -/* -*- 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 <sal/config.h> - -#include <cstdint> - -#include <sal/log.hxx> - -#include <basegfx/polygon/b2dpolygon.hxx> -#include <basegfx/polygon/b2dpolygontools.hxx> -#include <basegfx/range/b2drectangle.hxx> -#include <basegfx/range/b2irange.hxx> -#include <basegfx/vector/b2ivector.hxx> -#include <vcl/svapp.hxx> - -#include <quartz/salgdi.h> -#include <quartz/utils.h> -#include <osx/salframe.h> -#include <osx/saldata.hxx> - -void AquaSalGraphics::SetWindowGraphics( AquaSalFrame* pFrame ) -{ - mpFrame = pFrame; - mbWindow = true; - mbPrinter = false; - mbVirDev = false; -} - -void AquaSalGraphics::SetPrinterGraphics( CGContextRef xContext, sal_Int32 nDPIX, sal_Int32 nDPIY ) -{ - mbWindow = false; - mbPrinter = true; - mbVirDev = false; - - maContextHolder.set(xContext); - mnRealDPIX = nDPIX; - mnRealDPIY = nDPIY; - - // a previously set clip path is now invalid - if( mxClipPath ) - { - CGPathRelease( mxClipPath ); - mxClipPath = nullptr; - } - - if (maContextHolder.isSet()) - { - CGContextSetFillColorSpace( maContextHolder.get(), GetSalData()->mxRGBSpace ); - CGContextSetStrokeColorSpace( maContextHolder.get(), GetSalData()->mxRGBSpace ); - CGContextSaveGState( maContextHolder.get() ); - SetState(); - } -} - -void AquaSalGraphics::InvalidateContext() -{ - UnsetState(); - - CGContextRelease(maContextHolder.get()); - CGContextRelease(maBGContextHolder.get()); - CGContextRelease(maCSContextHolder.get()); - - maContextHolder.set(nullptr); - maCSContextHolder.set(nullptr); - maBGContextHolder.set(nullptr); -} - -void AquaSalGraphics::UnsetState() -{ - if (maBGContextHolder.isSet()) - { - CGContextRelease(maBGContextHolder.get()); - maBGContextHolder.set(nullptr); - } - if (maCSContextHolder.isSet()) - { - CGContextRelease(maCSContextHolder.get()); - maBGContextHolder.set(nullptr); - } - if (maContextHolder.isSet()) - { - maContextHolder.restoreState(); - maContextHolder.set(nullptr); - } - if( mxClipPath ) - { - CGPathRelease( mxClipPath ); - mxClipPath = nullptr; - } -} - -/** - * (re-)create the off-screen maLayer we render everything to if - * necessary: eg. not initialized yet, or it has an incorrect size. - */ -bool AquaSalGraphics::CheckContext() -{ - if (mbWindow && mpFrame && (mpFrame->getNSWindow() || Application::IsBitmapRendering())) - { - const unsigned int nWidth = mpFrame->maGeometry.nWidth; - const unsigned int nHeight = mpFrame->maGeometry.nHeight; - - // Let's get the window scaling factor if possible, or use 1.0 - // as the scaling factor. - float fScale = 1.0f; - if (mpFrame->getNSWindow()) - fScale = [mpFrame->getNSWindow() backingScaleFactor]; - - CGLayerRef rReleaseLayer = nullptr; - - // check if a new drawing context is needed (e.g. after a resize) - if( (unsigned(mnWidth) != nWidth) || (unsigned(mnHeight) != nHeight) ) - { - mnWidth = nWidth; - mnHeight = nHeight; - // prepare to release the corresponding resources - if (maLayer.isSet()) - { - rReleaseLayer = maLayer.get(); - } - else if (maContextHolder.isSet()) - { - CGContextRelease(maContextHolder.get()); - } - CGContextRelease(maBGContextHolder.get()); - CGContextRelease(maCSContextHolder.get()); - - maContextHolder.set(nullptr); - maBGContextHolder.set(nullptr); - maCSContextHolder.set(nullptr); - maLayer.set(nullptr); - } - - if (!maContextHolder.isSet()) - { - const int nBitmapDepth = 32; - - float nScaledWidth = mnWidth * fScale; - float nScaledHeight = mnHeight * fScale; - - const CGSize aLayerSize = { static_cast<CGFloat>(nScaledWidth), static_cast<CGFloat>(nScaledHeight) }; - - const int nBytesPerRow = (nBitmapDepth * nScaledWidth) / 8; - std::uint32_t nFlags = std::uint32_t(kCGImageAlphaNoneSkipFirst) - | std::uint32_t(kCGBitmapByteOrder32Host); - maBGContextHolder.set(CGBitmapContextCreate( - nullptr, nScaledWidth, nScaledHeight, 8, nBytesPerRow, GetSalData()->mxRGBSpace, nFlags)); - - maLayer.set(CGLayerCreateWithContext(maBGContextHolder.get(), aLayerSize, nullptr)); - maLayer.setScale(fScale); - - nFlags = std::uint32_t(kCGImageAlphaPremultipliedFirst) - | std::uint32_t(kCGBitmapByteOrder32Host); - maCSContextHolder.set(CGBitmapContextCreate( - nullptr, nScaledWidth, nScaledHeight, 8, nBytesPerRow, GetSalData()->mxRGBSpace, nFlags)); - - CGContextRef xDrawContext = CGLayerGetContext(maLayer.get()); - maContextHolder = xDrawContext; - - if (rReleaseLayer) - { - // copy original layer to resized layer - if (maContextHolder.isSet()) - { - CGContextDrawLayerAtPoint(maContextHolder.get(), CGPointZero, rReleaseLayer); - } - CGLayerRelease(rReleaseLayer); - } - - if (maContextHolder.isSet()) - { - CGContextTranslateCTM(maContextHolder.get(), 0, nScaledHeight); - CGContextScaleCTM(maContextHolder.get(), 1.0, -1.0); - CGContextSetFillColorSpace(maContextHolder.get(), GetSalData()->mxRGBSpace); - CGContextSetStrokeColorSpace(maContextHolder.get(), GetSalData()->mxRGBSpace); - // apply a scale matrix so everything is auto-magically scaled - CGContextScaleCTM(maContextHolder.get(), fScale, fScale); - maContextHolder.saveState(); - SetState(); - - // re-enable XOR emulation for the new context - if (mpXorEmulation) - mpXorEmulation->SetTarget(mnWidth, mnHeight, mnBitmapDepth, maContextHolder.get(), maLayer.get()); - } - } - } - - SAL_WARN_IF(!maContextHolder.isSet() && !mbPrinter, "vcl", "<<<WARNING>>> AquaSalGraphics::CheckContext() FAILED!!!!"); - - return maContextHolder.isSet(); -} - -CGContextRef AquaSalGraphics::GetContext() -{ - if (!maContextHolder.isSet()) - { - CheckContext(); - } - return maContextHolder.get(); -} - -/** - * Blit the contents of our internal maLayer state to the - * associated window, if any; cf. drawRect event handling - * on the frame. - */ -void AquaSalGraphics::UpdateWindow( NSRect& ) -{ - if( !mpFrame ) - { - return; - } - - NSGraphicsContext* pContext = [NSGraphicsContext currentContext]; - if (maLayer.isSet() && pContext != nullptr) - { - CGContextHolder rCGContextHolder([pContext CGContext]); - - rCGContextHolder.saveState(); - - CGMutablePathRef rClip = mpFrame->getClipPath(); - if (rClip) - { - CGContextBeginPath(rCGContextHolder.get()); - CGContextAddPath(rCGContextHolder.get(), rClip ); - CGContextClip(rCGContextHolder.get()); - } - - ApplyXorContext(); - - const CGSize aSize = maLayer.getSizePoints(); - const CGRect aRect = CGRectMake(0, 0, aSize.width, aSize.height); - const CGRect aRectPoints = { CGPointZero, maLayer.getSizePixels() }; - CGContextSetBlendMode(maCSContextHolder.get(), kCGBlendModeCopy); - CGContextDrawLayerInRect(maCSContextHolder.get(), aRectPoints, maLayer.get()); - - CGImageRef img = CGBitmapContextCreateImage(maCSContextHolder.get()); - CGImageRef displayColorSpaceImage = CGImageCreateCopyWithColorSpace(img, [[mpFrame->getNSWindow() colorSpace] CGColorSpace]); - CGContextSetBlendMode(rCGContextHolder.get(), kCGBlendModeCopy); - CGContextDrawImage(rCGContextHolder.get(), aRect, displayColorSpaceImage); - - CGImageRelease(img); - CGImageRelease(displayColorSpaceImage); - - rCGContextHolder.restoreState(); - } - else - { - SAL_WARN_IF( !mpFrame->mbInitShow, "vcl", "UpdateWindow called on uneligible graphics" ); - } -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/salvd.cxx b/vcl/quartz/salvd.cxx index 57ba971a927a..7e1194798899 100644 --- a/vcl/quartz/salvd.cxx +++ b/vcl/quartz/salvd.cxx @@ -104,6 +104,10 @@ AquaSalVirtualDevice::AquaSalVirtualDevice( } mpGraphics->SetVirDevGraphics(maLayer, pData->rCGContext); + + SAL_INFO("vcl.virdev", "AquaSalVirtualDevice::AquaSalVirtualDevice() this=" << this << + " (" << nDX << "x" << nDY << ") mbForeignContext=" << (mbForeignContext ? "YES" : "NO")); + } else { @@ -157,36 +161,6 @@ AquaSalVirtualDevice::~AquaSalVirtualDevice() Destroy(); } -void AquaSalVirtualDevice::Destroy() -{ - SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::Destroy() this=" << this << " mbForeignContext=" << mbForeignContext ); - - if( mbForeignContext ) - { - // Do not delete mxContext that we have received from outside VCL - maLayer.set(nullptr); - return; - } - - if (maLayer.isSet()) - { - if( mpGraphics ) - { - mpGraphics->SetVirDevGraphics(nullptr, nullptr); - } - CGLayerRelease(maLayer.get()); - maLayer.set(nullptr); - } - - if (maBitmapContext.isSet()) - { - void* pRawData = CGBitmapContextGetData(maBitmapContext.get()); - std::free(pRawData); - CGContextRelease(maBitmapContext.get()); - maBitmapContext.set(nullptr); - } -} - SalGraphics* AquaSalVirtualDevice::AcquireGraphics() { if( mbGraphicsUsed || !mpGraphics ) @@ -202,103 +176,4 @@ void AquaSalVirtualDevice::ReleaseGraphics( SalGraphics* ) mbGraphicsUsed = false; } -bool AquaSalVirtualDevice::SetSize( tools::Long nDX, tools::Long nDY ) -{ - SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::SetSize() this=" << this << - " (" << nDX << "x" << nDY << ") mbForeignContext=" << (mbForeignContext ? "YES" : "NO")); - - if( mbForeignContext ) - { - // Do not delete/resize mxContext that we have received from outside VCL - return true; - } - - if (maLayer.isSet()) - { - const CGSize aSize = CGLayerGetSize(maLayer.get()); - if( (nDX == aSize.width) && (nDY == aSize.height) ) - { - // Yay, we do not have to do anything :) - return true; - } - } - - Destroy(); - - mnWidth = nDX; - mnHeight = nDY; - - // create a Quartz layer matching to the intended virdev usage - CGContextHolder xCGContextHolder; - if( mnBitmapDepth && (mnBitmapDepth < 16) ) - { - mnBitmapDepth = 8; // TODO: are 1bit vdevs worth it? - const int nBytesPerRow = (mnBitmapDepth * nDX + 7) / 8; - - void* pRawData = std::malloc( nBytesPerRow * nDY ); - maBitmapContext.set(CGBitmapContextCreate( pRawData, nDX, nDY, - mnBitmapDepth, nBytesPerRow, - GetSalData()->mxGraySpace, kCGImageAlphaNone)); - xCGContextHolder = maBitmapContext; - } - else - { -#ifdef MACOSX - // default to a NSView target context - AquaSalFrame* pSalFrame = mpGraphics->getGraphicsFrame(); - if( !pSalFrame || !AquaSalFrame::isAlive( pSalFrame )) - { - pSalFrame = static_cast<AquaSalFrame*>( GetSalData()->mpInstance->anyFrame() ); - if ( pSalFrame ) - // update the frame reference - mpGraphics->setGraphicsFrame( pSalFrame ); - } - if( pSalFrame ) - { - // #i91990# - NSWindow* pNSWindow = pSalFrame->getNSWindow(); - if ( pNSWindow ) - { - NSGraphicsContext* pNSContext = [NSGraphicsContext graphicsContextWithWindow: pNSWindow]; - if( pNSContext ) - { - xCGContextHolder.set([pNSContext CGContext]); - } - } - } -#endif - - if (!xCGContextHolder.isSet()) - { - // assert(Application::IsBitmapRendering()); - mnBitmapDepth = 32; - - const int nBytesPerRow = (mnBitmapDepth * nDX) / 8; - void* pRawData = std::malloc( nBytesPerRow * nDY ); -#ifdef MACOSX - const int nFlags = kCGImageAlphaNoneSkipFirst; -#else - const int nFlags = kCGImageAlphaNoneSkipFirst | kCGImageByteOrder32Little; -#endif - maBitmapContext.set(CGBitmapContextCreate(pRawData, nDX, nDY, 8, nBytesPerRow, - GetSalData()->mxRGBSpace, nFlags)); - xCGContextHolder = maBitmapContext; - } - } - - SAL_WARN_IF(!xCGContextHolder.isSet(), "vcl.quartz", "No context"); - - const CGSize aNewSize = { static_cast<CGFloat>(nDX), static_cast<CGFloat>(nDY) }; - maLayer.set(CGLayerCreateWithContext(xCGContextHolder.get(), aNewSize, nullptr)); - - if (maLayer.isSet() && mpGraphics) - { - // get the matching Quartz context - CGContextRef xDrawContext = CGLayerGetContext( maLayer.get() ); - mpGraphics->SetVirDevGraphics(maLayer.get(), xDrawContext, mnBitmapDepth); - } - - return maLayer.isSet(); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |