diff options
author | Jan Holesovsky <kendy@collabora.com> | 2016-05-13 09:34:55 +0200 |
---|---|---|
committer | Jan Holesovsky <kendy@collabora.com> | 2016-05-16 14:56:55 +0200 |
commit | 404f6c9d4f9d151958c4644608477c9245d101e0 (patch) | |
tree | 6b3c97787014ff4d55697bf88a52d48760de7ba4 | |
parent | 96744275f4ead236e666a2c39037300c4924f771 (diff) |
cairo svp: Initial copy from master.
Change-Id: Ie5677ee777ee81e35cb22ba9f7bd9acfefe75444
25 files changed, 1767 insertions, 2217 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index c6b33e64272d..0f2bd28e1fd8 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -566,7 +566,6 @@ vcl_headless_code= \ vcl_headless_freetype_code=\ vcl/headless/svpprn \ vcl/headless/svptext \ - vcl/headless/svptextrender \ ifeq ($(GUIBASE),unx) $(eval $(call gb_Library_add_exception_objects,vcl,\ diff --git a/vcl/headless/headlessinst.cxx b/vcl/headless/headlessinst.cxx index f204b5f3fd84..a1c1da353f64 100644 --- a/vcl/headless/headlessinst.cxx +++ b/vcl/headless/headlessinst.cxx @@ -8,12 +8,12 @@ */ #include <headless/svpinst.hxx> #include <headless/svpdummies.hxx> -#include <generic/gendata.hxx> +#include <unx/gendata.hxx> class HeadlessSalInstance : public SvpSalInstance { public: - HeadlessSalInstance( SalYieldMutex *pMutex ); + explicit HeadlessSalInstance( SalYieldMutex *pMutex ); virtual ~HeadlessSalInstance(); virtual SalSystem* CreateSalSystem(); @@ -53,7 +53,7 @@ SalSystem *HeadlessSalInstance::CreateSalSystem() class HeadlessSalData : public SalGenericData { public: - HeadlessSalData( SalInstance *pInstance ) : SalGenericData( SAL_DATA_HEADLESS, pInstance ) {} + explicit HeadlessSalData( SalInstance *pInstance ) : SalGenericData( SAL_DATA_HEADLESS, pInstance ) {} virtual void ErrorTrapPush() {} virtual bool ErrorTrapPop( bool ) { return false; } }; diff --git a/vcl/headless/svpbmp.cxx b/vcl/headless/svpbmp.cxx index 901526ea7fea..180ad2c5d0d6 100644 --- a/vcl/headless/svpbmp.cxx +++ b/vcl/headless/svpbmp.cxx @@ -19,77 +19,166 @@ #ifndef IOS +#include <sal/config.h> + +#include <cstring> + #include "headless/svpbmp.hxx" +#include "headless/svpgdi.hxx" #include "headless/svpinst.hxx" #include <basegfx/vector/b2ivector.hxx> #include <basegfx/range/b2ibox.hxx> -#include <basebmp/scanlineformats.hxx> -#include <basebmp/color.hxx> #include <vcl/salbtype.hxx> #include <vcl/bitmap.hxx> -using namespace basebmp; using namespace basegfx; SvpSalBitmap::~SvpSalBitmap() { + Destroy(); } -bool SvpSalBitmap::Create( const Size& rSize, - sal_uInt16 nBitCount, - const BitmapPalette& rPalette ) +BitmapBuffer* ImplCreateDIB( + const Size& rSize, + sal_uInt16 nBitCount, + const BitmapPalette& rPal) { - SAL_INFO( "vcl.headless", "SvpSalBitmap::Create(" << rSize.Width() << "," << rSize.Height() << "," << nBitCount << ")" ); - - SvpSalInstance* pInst = SvpSalInstance::s_pDefaultInstance; - assert( pInst ); - basebmp::Format nFormat = pInst->getFormatForBitCount( nBitCount ); - - B2IVector aSize( rSize.Width(), rSize.Height() ); - if( aSize.getX() == 0 ) - aSize.setX( 1 ); - if( aSize.getY() == 0 ) - aSize.setY( 1 ); - sal_Int32 nStride = getBitmapDeviceStrideForWidth(nFormat, aSize.getX()); - if( nBitCount > 8 ) - m_aBitmap = createBitmapDevice( aSize, false, nFormat, nStride ); - else + assert( + (nBitCount == 0 + || nBitCount == 1 + || nBitCount == 4 + || nBitCount == 8 + || nBitCount == 16 + || nBitCount == 24 + || nBitCount == 32) + && "Unsupported BitCount!"); + + BitmapBuffer* pDIB = nullptr; + + if( rSize.Width() && rSize.Height() ) { - // prepare palette - unsigned int nEntries = 1U << nBitCount; - std::vector<basebmp::Color>* pPalette = - new std::vector<basebmp::Color>( nEntries, basebmp::Color(COL_WHITE) ); - unsigned int nColors = rPalette.GetEntryCount(); - for( unsigned int i = 0; i < nColors; i++ ) + try { - const BitmapColor& rCol = rPalette[i]; - (*pPalette)[i] = basebmp::Color( rCol.GetRed(), rCol.GetGreen(), rCol.GetBlue() ); + pDIB = new BitmapBuffer; + } + catch (const std::bad_alloc&) + { + pDIB = nullptr; + } + + if( pDIB ) + { + const sal_uInt16 nColors = ( nBitCount <= 8 ) ? ( 1 << nBitCount ) : 0; + + switch (nBitCount) + { + case 1: + pDIB->mnFormat = BMP_FORMAT_1BIT_MSB_PAL; + break; + case 4: + pDIB->mnFormat = BMP_FORMAT_4BIT_MSN_PAL; + break; + case 8: + pDIB->mnFormat = BMP_FORMAT_8BIT_PAL; + break; + case 16: + { +#ifdef OSL_BIGENDIAN + pDIB->mnFormat= BMP_FORMAT_16BIT_TC_MSB_MASK; +#else + pDIB->mnFormat= BMP_FORMAT_16BIT_TC_LSB_MASK; +#endif + ColorMaskElement aRedMask(0xf800); + aRedMask.CalcMaskShift(); + ColorMaskElement aGreenMask(0x07e0); + aGreenMask.CalcMaskShift(); + ColorMaskElement aBlueMask(0x001f); + aBlueMask.CalcMaskShift(); + pDIB->maColorMask = ColorMask(aRedMask, aGreenMask, aBlueMask); + break; + } + default: + nBitCount = 32; + SAL_FALLTHROUGH; + case 32: + { + pDIB->mnFormat = SVP_CAIRO_FORMAT; + break; + } + } + + pDIB->mnFormat |= BMP_FORMAT_TOP_DOWN; + pDIB->mnWidth = rSize.Width(); + pDIB->mnHeight = rSize.Height(); + pDIB->mnScanlineSize = AlignedWidth4Bytes( pDIB->mnWidth * nBitCount ); + pDIB->mnBitCount = nBitCount; + + if( nColors ) + { + pDIB->maPalette = rPal; + pDIB->maPalette.SetEntryCount( nColors ); + } + + try + { + size_t size = pDIB->mnScanlineSize * pDIB->mnHeight; + pDIB->mpBits = new sal_uInt8[size]; + std::memset(pDIB->mpBits, 0, size); + } + catch (const std::bad_alloc&) + { + delete pDIB; + pDIB = nullptr; + } } - m_aBitmap = createBitmapDevice( aSize, false, nFormat, nStride, - basebmp::RawMemorySharedArray(), - basebmp::PaletteMemorySharedVector( pPalette ) - ); } - return true; + else + pDIB = nullptr; + + return pDIB; +} + +bool SvpSalBitmap::Create(BitmapBuffer *pBuf) +{ + Destroy(); + mpDIB = pBuf; + return mpDIB != nullptr; } -bool SvpSalBitmap::Create( const SalBitmap& rSalBmp ) +bool SvpSalBitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal) { - const SvpSalBitmap& rSrc = static_cast<const SvpSalBitmap&>(rSalBmp); - const BitmapDeviceSharedPtr& rSrcBmp = rSrc.getBitmap(); - if( rSrcBmp.get() ) + Destroy(); + mpDIB = ImplCreateDIB( rSize, nBitCount, rPal ); + return mpDIB != nullptr; +} + +bool SvpSalBitmap::Create(const SalBitmap& rBmp) +{ + Destroy(); + + const SvpSalBitmap& rSalBmp = static_cast<const SvpSalBitmap&>(rBmp); + + if (rSalBmp.mpDIB) { - B2IVector aSize = rSrcBmp->getSize(); - m_aBitmap = cloneBitmapDevice( aSize, rSrcBmp ); - B2IBox aRect( 0, 0, aSize.getX(), aSize.getY() ); - m_aBitmap->drawBitmap( rSrcBmp, aRect, aRect, DrawMode_PAINT ); + // TODO: reference counting... + mpDIB = new BitmapBuffer( *rSalBmp.mpDIB ); + // TODO: get rid of this when BitmapBuffer gets copy constructor + try + { + size_t size = mpDIB->mnScanlineSize * mpDIB->mnHeight; + mpDIB->mpBits = new sal_uInt8[size]; + std::memcpy(mpDIB->mpBits, rSalBmp.mpDIB->mpBits, size); + } + catch (const std::bad_alloc&) + { + delete mpDIB; + mpDIB = nullptr; + } } - else - m_aBitmap.reset(); - return true; + return !rSalBmp.mpDIB || (mpDIB != nullptr); } bool SvpSalBitmap::Create( const SalBitmap& /*rSalBmp*/, @@ -104,23 +193,29 @@ bool SvpSalBitmap::Create( const SalBitmap& /*rSalBmp*/, return false; } -bool SvpSalBitmap::Create( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas >& /*xBitmapCanvas*/, Size& /*rSize*/, bool /*bMask*/ ) +bool SvpSalBitmap::Create( const css::uno::Reference< css::rendering::XBitmapCanvas >& /*xBitmapCanvas*/, Size& /*rSize*/, bool /*bMask*/ ) { return false; } void SvpSalBitmap::Destroy() { - m_aBitmap.reset(); + if (mpDIB) + { + delete[] mpDIB->mpBits; + delete mpDIB; + mpDIB = nullptr; + } } Size SvpSalBitmap::GetSize() const { Size aSize; - if( m_aBitmap.get() ) + + if (mpDIB) { - B2IVector aVec( m_aBitmap->getSize() ); - aSize = Size( aVec.getX(), aVec.getY() ); + aSize.Width() = mpDIB->mnWidth; + aSize.Height() = mpDIB->mnHeight; } return aSize; @@ -128,234 +223,26 @@ Size SvpSalBitmap::GetSize() const sal_uInt16 SvpSalBitmap::GetBitCount() const { - sal_uInt16 nDepth = 0; - if( m_aBitmap.get() ) - nDepth = getBitCountFromScanlineFormat( m_aBitmap->getScanlineFormat() ); - return nDepth; -} + sal_uInt16 nBitCount; -BitmapBuffer* SvpSalBitmap::AcquireBuffer( BitmapAccessMode ) -{ - BitmapBuffer* pBuf = NULL; - if( m_aBitmap.get() ) - { - pBuf = new BitmapBuffer(); - sal_uInt16 nBitCount = 1; - switch( m_aBitmap->getScanlineFormat() ) - { - case FORMAT_ONE_BIT_MSB_GREY: - case FORMAT_ONE_BIT_MSB_PAL: - nBitCount = 1; - pBuf->mnFormat = BMP_FORMAT_1BIT_MSB_PAL; - break; - case FORMAT_ONE_BIT_LSB_GREY: - case FORMAT_ONE_BIT_LSB_PAL: - nBitCount = 1; - pBuf->mnFormat = BMP_FORMAT_1BIT_LSB_PAL; - break; - case FORMAT_FOUR_BIT_MSB_GREY: - case FORMAT_FOUR_BIT_MSB_PAL: - nBitCount = 4; - pBuf->mnFormat = BMP_FORMAT_4BIT_MSN_PAL; - break; - case FORMAT_FOUR_BIT_LSB_GREY: - case FORMAT_FOUR_BIT_LSB_PAL: - nBitCount = 4; - pBuf->mnFormat = BMP_FORMAT_4BIT_LSN_PAL; - break; - case FORMAT_EIGHT_BIT_PAL: - nBitCount = 8; - pBuf->mnFormat = BMP_FORMAT_8BIT_PAL; - break; - case FORMAT_EIGHT_BIT_GREY: - nBitCount = 8; - pBuf->mnFormat = BMP_FORMAT_8BIT_PAL; - break; - case FORMAT_SIXTEEN_BIT_LSB_TC_MASK: - nBitCount = 16; - pBuf->mnFormat = BMP_FORMAT_16BIT_TC_LSB_MASK; - pBuf->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f ); - break; - case FORMAT_SIXTEEN_BIT_MSB_TC_MASK: - nBitCount = 16; - pBuf->mnFormat = BMP_FORMAT_16BIT_TC_MSB_MASK; - pBuf->maColorMask = ColorMask( 0xf800, 0x07e0, 0x001f ); - break; - case FORMAT_TWENTYFOUR_BIT_TC_MASK: - nBitCount = 24; - pBuf->mnFormat = BMP_FORMAT_24BIT_TC_BGR; - break; - case FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX: - nBitCount = 32; - pBuf->mnFormat = BMP_FORMAT_32BIT_TC_MASK; -#ifdef OSL_BIGENDIAN - pBuf->maColorMask = ColorMask( 0x0000ff00, 0x00ff0000, 0xff000000 ); -#else - pBuf->maColorMask = ColorMask( 0x00ff0000, 0x0000ff00, 0x000000ff ); -#endif - break; - case FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA: - nBitCount = 32; - pBuf->mnFormat = BMP_FORMAT_32BIT_TC_MASK; -#ifdef OSL_BIGENDIAN - pBuf->maColorMask = ColorMask( 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff ); -#else - pBuf->maColorMask = ColorMask( 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 ); -#endif - break; - case FORMAT_THIRTYTWO_BIT_TC_MASK_ARGB: - nBitCount = 32; - pBuf->mnFormat = BMP_FORMAT_32BIT_TC_MASK; -#ifdef OSL_BIGENDIAN - pBuf->maColorMask = ColorMask( 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 ); -#else - pBuf->maColorMask = ColorMask( 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff ); -#endif - break; - case FORMAT_THIRTYTWO_BIT_TC_MASK_ABGR: - nBitCount = 32; - pBuf->mnFormat = BMP_FORMAT_32BIT_TC_MASK; -#ifdef OSL_BIGENDIAN - pBuf->maColorMask = ColorMask( 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 ); -#else - pBuf->maColorMask = ColorMask( 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff ); -#endif - break; - case FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA: - nBitCount = 32; - pBuf->mnFormat = BMP_FORMAT_32BIT_TC_MASK; -#ifdef OSL_BIGENDIAN - pBuf->maColorMask = ColorMask( 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff ); -#else - pBuf->maColorMask = ColorMask( 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 ); -#endif - break; - - default: - // this is an error case !!!!! - nBitCount = 1; - pBuf->mnFormat = BMP_FORMAT_1BIT_MSB_PAL; - break; - } - if( m_aBitmap->isTopDown() ) - pBuf->mnFormat |= BMP_FORMAT_TOP_DOWN; - - B2IVector aSize = m_aBitmap->getSize(); - pBuf->mnWidth = aSize.getX(); - pBuf->mnHeight = aSize.getY(); - pBuf->mnScanlineSize = m_aBitmap->getScanlineStride(); - pBuf->mnBitCount = nBitCount; - pBuf->mpBits = (sal_uInt8*)m_aBitmap->getBuffer().get(); - if( nBitCount <= 8 ) - { - if( m_aBitmap->getScanlineFormat() == FORMAT_EIGHT_BIT_GREY || - m_aBitmap->getScanlineFormat() == FORMAT_FOUR_BIT_LSB_GREY || - m_aBitmap->getScanlineFormat() == FORMAT_FOUR_BIT_MSB_GREY || - m_aBitmap->getScanlineFormat() == FORMAT_ONE_BIT_LSB_GREY || - m_aBitmap->getScanlineFormat() == FORMAT_ONE_BIT_MSB_GREY - ) - pBuf->maPalette = Bitmap::GetGreyPalette( 1U << nBitCount ); - else - { - basebmp::PaletteMemorySharedVector aPalette = m_aBitmap->getPalette(); - if( aPalette.get() ) - { - unsigned int nColors = aPalette->size(); - if( nColors > 0 ) - { - pBuf->maPalette.SetEntryCount( nColors ); - for( unsigned int i = 0; i < nColors; i++ ) - { - const basebmp::Color& rCol = (*aPalette)[i]; - pBuf->maPalette[i] = BitmapColor( rCol.getRed(), rCol.getGreen(), rCol.getBlue() ); - } - } - } - } - } - } - - return pBuf; -} - -void SvpSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode ) -{ - if( nMode == BITMAP_WRITE_ACCESS && pBuffer->maPalette.GetEntryCount() ) - { - // palette might have changed, clone device (but recycle - // memory) - sal_uInt16 nBitCount = 0; - switch( m_aBitmap->getScanlineFormat() ) - { - case FORMAT_ONE_BIT_MSB_GREY: - // FALLTHROUGH intended - case FORMAT_ONE_BIT_MSB_PAL: - // FALLTHROUGH intended - case FORMAT_ONE_BIT_LSB_GREY: - // FALLTHROUGH intended - case FORMAT_ONE_BIT_LSB_PAL: - nBitCount = 1; - break; - - case FORMAT_FOUR_BIT_MSB_GREY: - // FALLTHROUGH intended - case FORMAT_FOUR_BIT_MSB_PAL: - // FALLTHROUGH intended - case FORMAT_FOUR_BIT_LSB_GREY: - // FALLTHROUGH intended - case FORMAT_FOUR_BIT_LSB_PAL: - nBitCount = 4; - break; - - case FORMAT_EIGHT_BIT_PAL: - // FALLTHROUGH intended - case FORMAT_EIGHT_BIT_GREY: - nBitCount = 8; - break; - - default: - break; - } - - if( nBitCount ) - { - sal_uInt32 nEntries = 1U << nBitCount; - - boost::shared_ptr< std::vector<basebmp::Color> > pPal( - new std::vector<basebmp::Color>( nEntries, - basebmp::Color(COL_WHITE))); - const sal_uInt32 nColors = std::min( - (sal_uInt32)pBuffer->maPalette.GetEntryCount(), - nEntries); - for( sal_uInt32 i = 0; i < nColors; i++ ) - { - const BitmapColor& rCol = pBuffer->maPalette[i]; - (*pPal)[i] = basebmp::Color( rCol.GetRed(), rCol.GetGreen(), rCol.GetBlue() ); - } - - m_aBitmap = basebmp::createBitmapDevice( m_aBitmap->getSize(), - m_aBitmap->isTopDown(), - m_aBitmap->getScanlineFormat(), - m_aBitmap->getScanlineStride(), - m_aBitmap->getBuffer(), - pPal ); - } - } + if (mpDIB) + nBitCount = mpDIB->mnBitCount; + else + nBitCount = 0; - delete pBuffer; + return nBitCount; } -bool SvpSalBitmap::GetSystemData( BitmapSystemData& ) +BitmapBuffer* SvpSalBitmap::AcquireBuffer(BitmapAccessMode) { - return false; + return mpDIB; } -bool SvpSalBitmap::Crop( const Rectangle& /*rRectPixel*/ ) +void SvpSalBitmap::ReleaseBuffer(BitmapBuffer*, BitmapAccessMode) { - return false; } -bool SvpSalBitmap::Erase( const ::Color& /*rFillColor*/ ) +bool SvpSalBitmap::GetSystemData( BitmapSystemData& ) { return false; } @@ -370,48 +257,6 @@ bool SvpSalBitmap::Replace( const ::Color& /*rSearchColor*/, const ::Color& /*rR return false; } -sal_uInt32 SvpSalBitmap::getBitCountFromScanlineFormat( basebmp::Format nFormat ) -{ - sal_uInt32 nBitCount = 1; - switch( nFormat ) - { - case FORMAT_ONE_BIT_MSB_GREY: - case FORMAT_ONE_BIT_LSB_GREY: - case FORMAT_ONE_BIT_MSB_PAL: - case FORMAT_ONE_BIT_LSB_PAL: - nBitCount = 1; - break; - case FORMAT_FOUR_BIT_MSB_GREY: - case FORMAT_FOUR_BIT_LSB_GREY: - case FORMAT_FOUR_BIT_MSB_PAL: - case FORMAT_FOUR_BIT_LSB_PAL: - nBitCount = 4; - break; - case FORMAT_EIGHT_BIT_PAL: - case FORMAT_EIGHT_BIT_GREY: - nBitCount = 8; - break; - case FORMAT_SIXTEEN_BIT_LSB_TC_MASK: - case FORMAT_SIXTEEN_BIT_MSB_TC_MASK: - nBitCount = 16; - break; - case FORMAT_TWENTYFOUR_BIT_TC_MASK: - nBitCount = 24; - break; - case FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX: - case FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA: - case FORMAT_THIRTYTWO_BIT_TC_MASK_ARGB: - case FORMAT_THIRTYTWO_BIT_TC_MASK_ABGR: - case FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA: - nBitCount = 32; - break; - default: - OSL_FAIL( "unsupported basebmp format" ); - break; - } - return nBitCount; -} - #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/headless/svpcairotextrender.cxx b/vcl/headless/svpcairotextrender.cxx new file mode 100644 index 000000000000..94687933cbd2 --- /dev/null +++ b/vcl/headless/svpcairotextrender.cxx @@ -0,0 +1,45 @@ +/* -*- 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/. + */ + +#include "headless/svpcairotextrender.hxx" +#include "headless/svpgdi.hxx" +#include <cairo.h> + +SvpCairoTextRender::SvpCairoTextRender(SvpSalGraphics& rParent) + : mrParent(rParent) +{ +} + +GlyphCache& SvpCairoTextRender::getPlatformGlyphCache() +{ + return SvpSalGraphics::getPlatformGlyphCache(); +} + +cairo_t* SvpCairoTextRender::getCairoContext() +{ + return mrParent.getCairoContext(false); +} + +void SvpCairoTextRender::getSurfaceOffset(double& nDX, double& nDY) +{ + nDX = 0; + nDY = 0; +} + +void SvpCairoTextRender::clipRegion(cairo_t* cr) +{ + mrParent.clipRegion(cr); +} + +void SvpCairoTextRender::releaseCairoContext(cairo_t* cr) +{ + mrParent.releaseCairoContext(cr, false, basegfx::B2DRange()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/headless/svpdata.cxx b/vcl/headless/svpdata.cxx index 56e7b8d82db0..d4fbdaed41cf 100644 --- a/vcl/headless/svpdata.cxx +++ b/vcl/headless/svpdata.cxx @@ -13,9 +13,9 @@ class SvpSalData : public SalGenericData { public: - SvpSalData( SalInstance *pInstance ) : SalGenericData( SAL_DATA_SVP, pInstance ) {} - virtual void ErrorTrapPush() SAL_OVERRIDE {} - virtual bool ErrorTrapPop( bool ) SAL_OVERRIDE { return false; } + explicit SvpSalData( SalInstance *pInstance ) : SalGenericData( SAL_DATA_SVP, pInstance ) {} + virtual void ErrorTrapPush() override {} + virtual bool ErrorTrapPop( bool ) override { return false; } }; // plugin factory function diff --git a/vcl/headless/svpdummies.cxx b/vcl/headless/svpdummies.cxx index b5e033a127ea..0c1b8c3ebf66 100644 --- a/vcl/headless/svpdummies.cxx +++ b/vcl/headless/svpdummies.cxx @@ -26,7 +26,7 @@ SvpSalObject::SvpSalObject() { // fast and easy cross-platform wiping of the data - memset( (void *)&m_aSystemChildData, 0, sizeof( SystemEnvData ) ); + memset( static_cast<void *>(&m_aSystemChildData), 0, sizeof( SystemEnvData ) ); m_aSystemChildData.nSize = sizeof( SystemEnvData ); } @@ -35,7 +35,6 @@ SvpSalObject::~SvpSalObject() } void SvpSalObject::ResetClipRegion() {} -sal_uInt16 SvpSalObject::GetClipRegionType() { return 0; } void SvpSalObject::BeginSetClipRegion( sal_uLong ) {} void SvpSalObject::UnionClipRegion( long, long, long, long ) {} void SvpSalObject::EndSetClipRegion() {} @@ -64,11 +63,6 @@ Rectangle SvpSalSystem::GetDisplayScreenPosSizePixel( unsigned int nScreen ) return aRect; } -OUString SvpSalSystem::GetDisplayScreenName( unsigned int nScreen ) -{ - return "VirtualScreen " + OUString::number(nScreen); -} - int SvpSalSystem::ShowNativeDialog( const OUString&, const OUString&, const std::list< OUString >&, int ) { diff --git a/vcl/headless/svpframe.cxx b/vcl/headless/svpframe.cxx index e1218d7ab3e6..a7f81819fb3e 100644 --- a/vcl/headless/svpframe.cxx +++ b/vcl/headless/svpframe.cxx @@ -18,80 +18,44 @@ */ #include <string.h> -#include <vcl/svpforlokit.hxx> #include <vcl/syswin.hxx> #include "headless/svpframe.hxx" #include "headless/svpinst.hxx" #include "headless/svpgdi.hxx" -#include <basebmp/bitmapdevice.hxx> -#include <basebmp/scanlineformats.hxx> #include <basegfx/vector/b2ivector.hxx> -using namespace basebmp; +#include <cairo.h> + using namespace basegfx; -SvpSalFrame* SvpSalFrame::s_pFocusFrame = NULL; +SvpSalFrame* SvpSalFrame::s_pFocusFrame = nullptr; #ifdef IOS #define SvpSalGraphics AquaSalGraphics #endif -#ifndef IOS - -namespace { - /// Decouple SalFrame lifetime from damagetracker lifetime - struct DamageTracker : public basebmp::IBitmapDeviceDamageTracker - { - virtual ~DamageTracker() {} - virtual void damaged( const basegfx::B2IBox& ) const SAL_OVERRIDE {} - }; -} - -void SvpSalFrame::enableDamageTracker( bool bOn ) -{ - if( m_bDamageTracking == bOn ) - return; - if( m_aFrame.get() ) - { - if( m_bDamageTracking ) - m_aFrame->setDamageTracker( basebmp::IBitmapDeviceDamageTrackerSharedPtr() ); - else - m_aFrame->setDamageTracker( - basebmp::IBitmapDeviceDamageTrackerSharedPtr( new DamageTracker ) ); - } - m_bDamageTracking = bOn; -} - -#endif - SvpSalFrame::SvpSalFrame( SvpSalInstance* pInstance, SalFrame* pParent, - sal_uLong nSalFrameStyle, - bool bTopDown, - basebmp::Format nScanlineFormat, + SalFrameStyleFlags nSalFrameStyle, SystemParentData* ) : m_pInstance( pInstance ), m_pParent( static_cast<SvpSalFrame*>(pParent) ), m_nStyle( nSalFrameStyle ), m_bVisible( false ), - m_bTopDown( bTopDown ), -#ifndef IOS - m_bDamageTracking( false ), -#endif - m_nScanlineFormat( nScanlineFormat ), + m_pSurface( nullptr ), m_nMinWidth( 0 ), m_nMinHeight( 0 ), m_nMaxWidth( 0 ), m_nMaxHeight( 0 ) { - // SAL_DEBUG("SvpSalFrame::SvpSalFrame: " << this); + // SAL-DEBUG("SvpSalFrame::SvpSalFrame: " << this); // fast and easy cross-platform wiping of the data - memset( (void *)&m_aSystemChildData, 0, sizeof( SystemEnvData ) ); + memset( static_cast<void *>(&m_aSystemChildData), 0, sizeof( SystemEnvData ) ); m_aSystemChildData.nSize = sizeof( SystemEnvData ); #ifdef IOS - // Nothing + (void) nScanlineFormat; #elif defined ANDROID // Nothing #else @@ -122,23 +86,23 @@ SvpSalFrame::~SvpSalFrame() if( s_pFocusFrame == this ) { - // SAL_DEBUG("SvpSalFrame::~SvpSalFrame: losing focus: " << this); - s_pFocusFrame = NULL; + // SAL-DEBUG("SvpSalFrame::~SvpSalFrame: losing focus: " << this); + s_pFocusFrame = nullptr; // call directly here, else an event for a destroyed frame would be dispatched - CallCallback( SALEVENT_LOSEFOCUS, NULL ); + CallCallback( SalEvent::LoseFocus, nullptr ); // if the handler has not set a new focus frame // pass focus to another frame, preferably a document style window - if( s_pFocusFrame == NULL ) + if( s_pFocusFrame == nullptr ) { const std::list< SalFrame* >& rFrames( m_pInstance->getFrames() ); for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it ) { SvpSalFrame* pFrame = const_cast<SvpSalFrame*>(static_cast<const SvpSalFrame*>(*it)); if( pFrame->m_bVisible && - pFrame->m_pParent == NULL && - (pFrame->m_nStyle & (SAL_FRAME_STYLE_MOVEABLE | - SAL_FRAME_STYLE_SIZEABLE | - SAL_FRAME_STYLE_CLOSEABLE) ) != 0 + pFrame->m_pParent == nullptr && + (pFrame->m_nStyle & (SalFrameStyleFlags::MOVEABLE | + SalFrameStyleFlags::SIZEABLE | + SalFrameStyleFlags::CLOSEABLE) ) ) { pFrame->GetFocus(); @@ -147,6 +111,8 @@ SvpSalFrame::~SvpSalFrame() } } } + if (m_pSurface) + cairo_surface_destroy(m_pSurface); } void SvpSalFrame::GetFocus() @@ -154,13 +120,13 @@ void SvpSalFrame::GetFocus() if( s_pFocusFrame == this ) return; - if( (m_nStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_FLOAT)) == 0 ) + if( (m_nStyle & (SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::FLOAT)) == SalFrameStyleFlags::NONE ) { if( s_pFocusFrame ) s_pFocusFrame->LoseFocus(); - // SAL_DEBUG("SvpSalFrame::GetFocus(): " << this); + // SAL-DEBUG("SvpSalFrame::GetFocus(): " << this); s_pFocusFrame = this; - m_pInstance->PostEvent( this, NULL, SALEVENT_GETFOCUS ); + m_pInstance->PostEvent( this, nullptr, SalEvent::GetFocus ); } } @@ -168,9 +134,9 @@ void SvpSalFrame::LoseFocus() { if( s_pFocusFrame == this ) { - // SAL_DEBUG("SvpSalFrame::LoseFocus: " << this); - m_pInstance->PostEvent( this, NULL, SALEVENT_LOSEFOCUS ); - s_pFocusFrame = NULL; + // SAL-DEBUG("SvpSalFrame::LoseFocus: " << this); + m_pInstance->PostEvent( this, nullptr, SalEvent::LoseFocus ); + s_pFocusFrame = nullptr; } } @@ -178,7 +144,7 @@ SalGraphics* SvpSalFrame::AcquireGraphics() { SvpSalGraphics* pGraphics = new SvpSalGraphics(); #ifndef IOS - pGraphics->setDevice( m_aFrame ); + pGraphics->setSurface( m_pSurface ); #endif m_aGraphics.push_back( pGraphics ); return pGraphics; @@ -191,19 +157,19 @@ void SvpSalFrame::ReleaseGraphics( SalGraphics* pGraphics ) delete pSvpGraphics; } -bool SvpSalFrame::PostEvent( void* pData ) +bool SvpSalFrame::PostEvent(ImplSVEvent* pData) { - m_pInstance->PostEvent( this, pData, SALEVENT_USEREVENT ); + m_pInstance->PostEvent( this, pData, SalEvent::UserEvent ); return true; } -void SvpSalFrame::PostPaint(bool bImmediate) const +void SvpSalFrame::PostPaint() const { if( m_bVisible ) { SalPaintEvent aPEvt(0, 0, maGeometry.nWidth, maGeometry.nHeight); - aPEvt.mbImmediateUpdate = bImmediate; - CallCallback( SALEVENT_PAINT, &aPEvt ); + aPEvt.mbImmediateUpdate = false; + CallCallback( SalEvent::Paint, &aPEvt ); } } @@ -231,22 +197,22 @@ void SvpSalFrame::Show( bool bVisible, bool bNoActivate ) { if( bVisible && ! m_bVisible ) { - // SAL_DEBUG("SvpSalFrame::Show: showing: " << this); + // SAL-DEBUG("SvpSalFrame::Show: showing: " << this); m_bVisible = true; - m_pInstance->PostEvent( this, NULL, SALEVENT_RESIZE ); + m_pInstance->PostEvent( this, nullptr, SalEvent::Resize ); if( ! bNoActivate ) GetFocus(); } else if( ! bVisible && m_bVisible ) { - // SAL_DEBUG("SvpSalFrame::Show: hiding: " << this); + // SAL-DEBUG("SvpSalFrame::Show: hiding: " << this); m_bVisible = false; - m_pInstance->PostEvent( this, NULL, SALEVENT_RESIZE ); + m_pInstance->PostEvent( this, nullptr, SalEvent::Resize ); LoseFocus(); } else { - // SAL_DEBUG("SvpSalFrame::Show: nothihg: " << this); + // SAL-DEBUG("SvpSalFrame::Show: nothing: " << this); } } @@ -286,26 +252,34 @@ void SvpSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_u } #ifndef IOS B2IVector aFrameSize( maGeometry.nWidth, maGeometry.nHeight ); - if( ! m_aFrame.get() || m_aFrame->getSize() != aFrameSize ) + if (!m_pSurface || cairo_image_surface_get_width(m_pSurface) != aFrameSize.getX() || + cairo_image_surface_get_height(m_pSurface) != aFrameSize.getY() ) { if( aFrameSize.getX() == 0 ) aFrameSize.setX( 1 ); if( aFrameSize.getY() == 0 ) aFrameSize.setY( 1 ); - sal_Int32 nStride = basebmp::getBitmapDeviceStrideForWidth(m_nScanlineFormat, aFrameSize.getX()); - m_aFrame = createBitmapDevice( aFrameSize, m_bTopDown, m_nScanlineFormat, nStride ); - if (m_bDamageTracking) - m_aFrame->setDamageTracker( - basebmp::IBitmapDeviceDamageTrackerSharedPtr( new DamageTracker ) ); + + if (m_pSurface) + cairo_surface_destroy(m_pSurface); + + // Creating backing surfaces for invisible windows costs a big chunk of RAM. + if (Application::IsHeadlessModeEnabled()) + aFrameSize = B2IVector( 1, 1 ); + + m_pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + aFrameSize.getX(), + aFrameSize.getY()); + // update device in existing graphics for( std::list< SvpSalGraphics* >::iterator it = m_aGraphics.begin(); it != m_aGraphics.end(); ++it ) { - (*it)->setDevice( m_aFrame ); + (*it)->setSurface(m_pSurface); } } if( m_bVisible ) - m_pInstance->PostEvent( this, NULL, SALEVENT_RESIZE ); + m_pInstance->PostEvent( this, nullptr, SalEvent::Resize ); #endif } @@ -331,17 +305,17 @@ SalFrame* SvpSalFrame::GetParent() const return m_pParent; } -#define _FRAMESTATE_MASK_GEOMETRY \ - (WINDOWSTATE_MASK_X | WINDOWSTATE_MASK_Y | \ - WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT) +#define FRAMESTATE_MASK_GEOMETRY \ + (WindowStateMask::X | WindowStateMask::Y | \ + WindowStateMask::Width | WindowStateMask::Height) void SvpSalFrame::SetWindowState( const SalFrameState *pState ) { - if (pState == NULL) + if (pState == nullptr) return; // Request for position or size change - if (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) + if (pState->mnMask & FRAMESTATE_MASK_GEOMETRY) { long nX = maGeometry.nX; long nY = maGeometry.nY; @@ -349,13 +323,13 @@ void SvpSalFrame::SetWindowState( const SalFrameState *pState ) long nHeight = maGeometry.nHeight; // change requested properties - if (pState->mnMask & WINDOWSTATE_MASK_X) + if (pState->mnMask & WindowStateMask::X) nX = pState->mnX; - if (pState->mnMask & WINDOWSTATE_MASK_Y) + if (pState->mnMask & WindowStateMask::Y) nY = pState->mnY; - if (pState->mnMask & WINDOWSTATE_MASK_WIDTH) + if (pState->mnMask & WindowStateMask::Width) nWidth = pState->mnWidth; - if (pState->mnMask & WINDOWSTATE_MASK_HEIGHT) + if (pState->mnMask & WindowStateMask::Height) nHeight = pState->mnHeight; SetPosSize( nX, nY, nWidth, nHeight, @@ -366,12 +340,12 @@ void SvpSalFrame::SetWindowState( const SalFrameState *pState ) bool SvpSalFrame::GetWindowState( SalFrameState* pState ) { - pState->mnState = WINDOWSTATE_STATE_NORMAL; + pState->mnState = WindowStateState::Normal; pState->mnX = maGeometry.nX; pState->mnY = maGeometry.nY; pState->mnWidth = maGeometry.nWidth; pState->mnHeight = maGeometry.nHeight; - pState->mnMask = _FRAMESTATE_MASK_GEOMETRY | WINDOWSTATE_MASK_STATE; + pState->mnMask = FRAMESTATE_MASK_GEOMETRY | WindowStateMask::State; return true; } @@ -390,7 +364,7 @@ void SvpSalFrame::SetAlwaysOnTop( bool ) { } -void SvpSalFrame::ToTop( sal_uInt16 ) +void SvpSalFrame::ToTop( SalFrameToTop ) { GetFocus(); } @@ -411,15 +385,11 @@ void SvpSalFrame::Flush() { } -void SvpSalFrame::Sync() -{ -} - void SvpSalFrame::SetInputContext( SalInputContext* ) { } -void SvpSalFrame::EndExtTextInput( sal_uInt16 ) +void SvpSalFrame::EndExtTextInput( EndExtTextInputFlags ) { } @@ -495,14 +465,4 @@ void SvpSalFrame::EndSetClipRegion() { } -SalFrame* GetSvpFocusFrameForLibreOfficeKit() -{ - return SvpSalFrame::GetFocusFrame(); -} - -vcl::Window* GetSalFrameWindowForLibreOfficeKit(SalFrame *pSF) -{ - return pSF->GetWindow(); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx index 21efd33c3921..2c2408bec8c9 100644 --- a/vcl/headless/svpgdi.cxx +++ b/vcl/headless/svpgdi.cxx @@ -19,70 +19,231 @@ #include "headless/svpgdi.hxx" #include "headless/svpbmp.hxx" +#include "headless/svpframe.hxx" #ifndef IOS -#include "headless/svptextrender.hxx" +#include "headless/svpcairotextrender.hxx" #endif #include "saldatabasic.hxx" #include <vcl/sysdata.hxx> +#include <config_cairo_canvas.h> +#include <basegfx/numeric/ftools.hxx> #include <basegfx/range/b2drange.hxx> #include <basegfx/range/b2ibox.hxx> #include <basegfx/polygon/b2dpolypolygon.hxx> #include <basegfx/polygon/b2dpolypolygontools.hxx> #include <basegfx/polygon/b2dpolygon.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> -#include <basebmp/scanlineformats.hxx> -#if ENABLE_CAIRO_CANVAS #include <cairo.h> -#endif -#if OSL_DEBUG_LEVEL > 2 -#include <basebmp/debug.hxx> -#include <fstream> -#include <rtl/strbuf.hxx> -#include <sys/stat.h> +#if ENABLE_CAIRO_CANVAS +#if defined CAIRO_VERSION && CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 10, 0) +# define CAIRO_OPERATOR_DIFFERENCE (static_cast<cairo_operator_t>(23)) +#endif #endif -#include <stdio.h> +namespace +{ + basegfx::B2DRange getClipBox(cairo_t* cr) + { + double x1, y1, x2, y2; + + cairo_clip_extents(cr, &x1, &y1, &x2, &y2); -inline void dbgOut( const basebmp::BitmapDeviceSharedPtr& -#if OSL_DEBUG_LEVEL > 2 -rDevice -#endif -) -{ - #if OSL_DEBUG_LEVEL > 2 - static int dbgStreamNum = 0; - OStringBuffer aBuf( 256 ); - aBuf.append( "debug" ); - mkdir( aBuf.getStr(), 0777 ); - aBuf.append( "/" ); - aBuf.append( sal_Int64(reinterpret_cast<sal_IntPtr>(rDevice.get())), 16 ); - mkdir( aBuf.getStr(), 0777 ); - aBuf.append( "/bmp" ); - aBuf.append( sal_Int32(dbgStreamNum++) ); - std::fstream bmpstream( aBuf.getStr(), std::ios::out ); - debugDump( rDevice, bmpstream ); - #endif + return basegfx::B2DRange(x1, y1, x2, y2); + } + + basegfx::B2DRange getFillDamage(cairo_t* cr) + { + double x1, y1, x2, y2; + + cairo_fill_extents(cr, &x1, &y1, &x2, &y2); + + return basegfx::B2DRange(x1, y1, x2, y2); + } + + basegfx::B2DRange getClippedFillDamage(cairo_t* cr) + { + basegfx::B2DRange aDamageRect(getFillDamage(cr)); + aDamageRect.intersect(getClipBox(cr)); + return aDamageRect; + } + + basegfx::B2DRange getStrokeDamage(cairo_t* cr) + { + double x1, y1, x2, y2; + + cairo_stroke_extents(cr, &x1, &y1, &x2, &y2); + + return basegfx::B2DRange(x1, y1, x2, y2); + } + + basegfx::B2DRange getClippedStrokeDamage(cairo_t* cr) + { + basegfx::B2DRange aDamageRect(getStrokeDamage(cr)); + aDamageRect.intersect(getClipBox(cr)); + return aDamageRect; + } } #ifndef IOS bool SvpSalGraphics::blendBitmap( const SalTwoRect&, const SalBitmap& /*rBitmap*/ ) { + SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::blendBitmap case"); return false; } bool SvpSalGraphics::blendAlphaBitmap( const SalTwoRect&, const SalBitmap&, const SalBitmap&, const SalBitmap& ) { + SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::blendAlphaBitmap case"); return false; } -bool SvpSalGraphics::drawAlphaBitmap( const SalTwoRect&, const SalBitmap& /*rSourceBitmap*/, const SalBitmap& /*rAlphaBitmap*/ ) +namespace { - // TODO(P3) implement alpha blending - return false; + class SourceHelper + { + public: + explicit SourceHelper(const SalBitmap& rSourceBitmap) + { + const SvpSalBitmap& rSrcBmp = static_cast<const SvpSalBitmap&>(rSourceBitmap); + + if (rSrcBmp.GetBitCount() != 32) + { + //big stupid copy here + static bool bWarnedOnce; + SAL_WARN_IF(!bWarnedOnce, "vcl.gdi", "non default depth bitmap, slow convert, upscale the input"); + bWarnedOnce = true; + + const BitmapBuffer* pSrc = rSrcBmp.GetBuffer(); + const SalTwoRect aTwoRect = { 0, 0, pSrc->mnWidth, pSrc->mnHeight, + 0, 0, pSrc->mnWidth, pSrc->mnHeight }; + aTmpBmp.Create(StretchAndConvert(*pSrc, aTwoRect, SVP_CAIRO_FORMAT)); + + + assert(aTmpBmp.GetBitCount() == 32); + source = SvpSalGraphics::createCairoSurface(aTmpBmp.GetBuffer()); + } + else + source = SvpSalGraphics::createCairoSurface(rSrcBmp.GetBuffer()); + } + ~SourceHelper() + { + cairo_surface_destroy(source); + } + cairo_surface_t* getSurface() + { + return source; + } + private: + SvpSalBitmap aTmpBmp; + cairo_surface_t* source; + }; + + class MaskHelper + { + public: + explicit MaskHelper(const SalBitmap& rAlphaBitmap) + { + const SvpSalBitmap& rMask = static_cast<const SvpSalBitmap&>(rAlphaBitmap); + const BitmapBuffer* pMaskBuf = rMask.GetBuffer(); + + if (rAlphaBitmap.GetBitCount() == 8) + { + // the alpha values need to be inverted for Cairo + // so big stupid copy and invert here + const int nImageSize = pMaskBuf->mnHeight * pMaskBuf->mnScanlineSize; + pAlphaBits = new unsigned char[nImageSize]; + memcpy(pAlphaBits, pMaskBuf->mpBits, nImageSize); + + // TODO: make upper layers use standard alpha + sal_uInt32* pLDst = reinterpret_cast<sal_uInt32*>(pAlphaBits); + for( int i = nImageSize/sizeof(sal_uInt32); --i >= 0; ++pLDst ) + *pLDst = ~*pLDst; + assert(reinterpret_cast<unsigned char*>(pLDst) == pAlphaBits+nImageSize); + + mask = cairo_image_surface_create_for_data(pAlphaBits, + CAIRO_FORMAT_A8, + pMaskBuf->mnWidth, pMaskBuf->mnHeight, + pMaskBuf->mnScanlineSize); + } + else + { + // the alpha values need to be inverted for Cairo + // so big stupid copy and invert here + const int nImageSize = pMaskBuf->mnHeight * pMaskBuf->mnScanlineSize; + pAlphaBits = new unsigned char[nImageSize]; + memcpy(pAlphaBits, pMaskBuf->mpBits, nImageSize); + + // TODO: make upper layers use standard alpha + unsigned char* pDst = pAlphaBits; + for (int i = nImageSize; --i >= 0; ++pDst) + *pDst = ~*pDst; + + mask = cairo_image_surface_create_for_data(pAlphaBits, + CAIRO_FORMAT_A1, + pMaskBuf->mnWidth, pMaskBuf->mnHeight, + pMaskBuf->mnScanlineSize); + } + } + ~MaskHelper() + { + cairo_surface_destroy(mask); + delete[] pAlphaBits; + } + cairo_surface_t* getMask() + { + return mask; + } + private: + cairo_surface_t *mask; + unsigned char* pAlphaBits; + }; +} + +bool SvpSalGraphics::drawAlphaBitmap( const SalTwoRect& rTR, const SalBitmap& rSourceBitmap, const SalBitmap& rAlphaBitmap ) +{ + if (rAlphaBitmap.GetBitCount() != 8 && rAlphaBitmap.GetBitCount() != 1) + { + SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawAlphaBitmap alpha depth case: " << rAlphaBitmap.GetBitCount()); + return false; + } + + SourceHelper aSurface(rSourceBitmap); + cairo_surface_t* source = aSurface.getSurface(); + if (!source) + { + SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawAlphaBitmap case"); + return false; + } + + MaskHelper aMask(rAlphaBitmap); + cairo_surface_t *mask = aMask.getMask(); + if (!mask) + { + SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawAlphaBitmap case"); + return false; + } + + cairo_t* cr = getCairoContext(false); + clipRegion(cr); + + cairo_rectangle(cr, rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight); + + basegfx::B2DRange extents = getClippedFillDamage(cr); + + cairo_clip(cr); + + cairo_translate(cr, rTR.mnDestX, rTR.mnDestY); + cairo_scale(cr, (double)(rTR.mnDestWidth)/rTR.mnSrcWidth, ((double)rTR.mnDestHeight)/rTR.mnSrcHeight); + cairo_set_source_surface(cr, source, -rTR.mnSrcX, -rTR.mnSrcY); + cairo_mask_surface(cr, mask, -rTR.mnSrcX, -rTR.mnSrcY); + + releaseCairoContext(cr, false, extents); + + return true; } bool SvpSalGraphics::drawTransformedBitmap( @@ -92,33 +253,67 @@ bool SvpSalGraphics::drawTransformedBitmap( const SalBitmap& rSourceBitmap, const SalBitmap* pAlphaBitmap) { - // here direct support for transformed bitmaps can be implemented - (void)rNull; (void)rX; (void)rY; (void)rSourceBitmap; (void)pAlphaBitmap; - return false; -} + if (pAlphaBitmap && pAlphaBitmap->GetBitCount() != 8 && pAlphaBitmap->GetBitCount() != 1) + { + SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawTransformedBitmap alpha depth case: " << pAlphaBitmap->GetBitCount()); + return false; + } -#if ENABLE_CAIRO_CANVAS + SourceHelper aSurface(rSourceBitmap); + cairo_surface_t* source = aSurface.getSurface(); + if (!source) + { + SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawTransformedBitmap case"); + return false; + } -namespace -{ - bool isCairoCompatible(const basebmp::BitmapDeviceSharedPtr &rBuffer) + std::unique_ptr<MaskHelper> xMask; + cairo_surface_t *mask = nullptr; + if (pAlphaBitmap) { - if (!rBuffer) + xMask.reset(new MaskHelper(*pAlphaBitmap)); + mask = xMask->getMask(); + if (!mask) + { + SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawTransformedBitmap case"); return false; + } + } - if (rBuffer->getScanlineFormat() != basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX) - return false; + const Size aSize = rSourceBitmap.GetSize(); -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0) - basegfx::B2IVector size = rBuffer->getSize(); - sal_Int32 nStride = rBuffer->getScanlineStride(); - return (cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, size.getX()) == nStride); -#else - return false; -#endif - } + cairo_t* cr = getCairoContext(false); + clipRegion(cr); + + // setup the image transformation + // using the rNull,rX,rY points as destinations for the (0,0),(0,Width),(Height,0) source points + const basegfx::B2DVector aXRel = rX - rNull; + const basegfx::B2DVector aYRel = rY - rNull; + cairo_matrix_t matrix; + cairo_matrix_init(&matrix, + aXRel.getX()/aSize.Width(), aXRel.getY()/aSize.Width(), + aYRel.getX()/aSize.Height(), aYRel.getY()/aSize.Height(), + rNull.getX(), rNull.getY()); + + cairo_transform(cr, &matrix); + + cairo_rectangle(cr, 0, 0, aSize.Width(), aSize.Height()); + basegfx::B2DRange extents = getClippedFillDamage(cr); + cairo_clip(cr); + + cairo_set_source_surface(cr, source, 0, 0); + if (mask) + cairo_mask_surface(cr, mask, 0, 0); + else + cairo_paint(cr); + + releaseCairoContext(cr, false, extents); + + return true; } +#endif + void SvpSalGraphics::clipRegion(cairo_t* cr) { RectangleVector aRectangles; @@ -135,129 +330,67 @@ void SvpSalGraphics::clipRegion(cairo_t* cr) cairo_clip(cr); } } -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0) -namespace -{ - cairo_rectangle_int_t getFillDamage(cairo_t* cr) - { - cairo_rectangle_int_t extents; - double x1, y1, x2, y2; - cairo_clip_extents(cr, &x1, &y1, &x2, &y2); - extents.x = x1, extents.y = y1, extents.width = x2-x1, extents.height = y2-y1; - cairo_region_t *region = cairo_region_create_rectangle(&extents); +bool SvpSalGraphics::drawAlphaRect(long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency) +{ + cairo_t* cr = getCairoContext(false); + clipRegion(cr); - cairo_fill_extents(cr, &x1, &y1, &x2, &y2); - extents.x = x1, extents.y = y1, extents.width = x2-x1, extents.height = y2-y1; - cairo_region_intersect_rectangle(region, &extents); + const double fTransparency = (100 - nTransparency) * (1.0/100); - cairo_region_get_extents(region, &extents); - cairo_region_destroy(region); + basegfx::B2DRange extents(0, 0, 0, 0); - return extents; - } + cairo_rectangle(cr, nX, nY, nWidth, nHeight); - cairo_rectangle_int_t getStrokeDamage(cairo_t* cr) + if (m_aFillColor != SALCOLOR_NONE) { - cairo_rectangle_int_t extents; - double x1, y1, x2, y2; - - cairo_clip_extents(cr, &x1, &y1, &x2, &y2); - extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1; -#if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 10) - cairo_region_t *region = cairo_region_create_rectangle(&extents); - - cairo_stroke_extents(cr, &x1, &y1, &x2, &y2); - extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1; - cairo_region_intersect_rectangle(region, &extents); + cairo_set_source_rgba(cr, SALCOLOR_RED(m_aFillColor)/255.0, + SALCOLOR_GREEN(m_aFillColor)/255.0, + SALCOLOR_BLUE(m_aFillColor)/255.0, + fTransparency); - cairo_region_get_extents(region, &extents); - cairo_region_destroy(region); -#endif + if (m_aLineColor == SALCOLOR_NONE) + extents = getClippedFillDamage(cr); - return extents; + cairo_fill_preserve(cr); } -} -#endif - -#endif -bool SvpSalGraphics::drawAlphaRect(long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency) -{ - bool bRet = false; - (void)nX; (void)nY; (void)nWidth; (void)nHeight; (void)nTransparency; -#if ENABLE_CAIRO_CANVAS -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0) - if (m_bUseLineColor || !m_bUseFillColor) + if (m_aLineColor != SALCOLOR_NONE) { - SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawAlphaRect case"); - return false; - } + cairo_set_source_rgba(cr, SALCOLOR_RED(m_aLineColor)/255.0, + SALCOLOR_GREEN(m_aLineColor)/255.0, + SALCOLOR_BLUE(m_aLineColor)/255.0, + fTransparency); - cairo_t* cr = createCairoContext(m_aDevice); - if (!cr) - return bRet; + extents = getClippedStrokeDamage(cr); - if (!m_aDevice->isTopDown()) - { - cairo_scale(cr, 1, -1.0); - cairo_translate(cr, 0.0, -m_aDevice->getSize().getY()); + cairo_stroke_preserve(cr); } - clipRegion(cr); - - const double fTransparency = (100 - nTransparency) * (1.0/100); - cairo_set_source_rgba(cr, m_aFillColor.getRed()/255.0, - m_aFillColor.getGreen()/255.0, - m_aFillColor.getBlue()/255.0, - fTransparency); - cairo_rectangle(cr, nX, nY, nWidth, nHeight); - - cairo_rectangle_int_t extents; - basebmp::IBitmapDeviceDamageTrackerSharedPtr xDamageTracker(m_aDevice->getDamageTracker()); - if (xDamageTracker) - extents = getFillDamage(cr); - - cairo_fill(cr); + releaseCairoContext(cr, false, extents); - cairo_surface_flush(cairo_get_target(cr)); - cairo_destroy(cr); // unref - - if (xDamageTracker) - { - xDamageTracker->damaged(basegfx::B2IBox(extents.x, extents.y, extents.x + extents.width, - extents.y + extents.height)); - } - bRet = true; -#endif -#endif - return bRet; + return true; } -SvpSalGraphics::SvpSalGraphics() : - m_bUseLineColor( true ), - m_aLineColor( COL_BLACK ), - m_bUseFillColor( false ), - m_aFillColor( COL_WHITE ), - m_aDrawMode( basebmp::DrawMode_PAINT ), - m_bClipSetup( false ) +SvpSalGraphics::SvpSalGraphics() + : m_pSurface(nullptr) + , m_aLineColor(MAKE_SALCOLOR(0x00, 0x00, 0x00)) + , m_aFillColor(MAKE_SALCOLOR(0xFF, 0xFF, 0XFF)) + , m_ePaintMode(OVERPAINT) + , m_aTextRenderImpl(*this) { - m_xTextRenderImpl.reset(new SvpTextRender(*this)); } SvpSalGraphics::~SvpSalGraphics() { } -void SvpSalGraphics::setDevice( basebmp::BitmapDeviceSharedPtr& rDevice ) +void SvpSalGraphics::setSurface(cairo_surface_t* pSurface) { - m_aOrigDevice = rDevice; + m_pSurface = pSurface; ResetClipRegion(); - m_xTextRenderImpl->setDevice(rDevice); } -#endif - void SvpSalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) { rDPIX = rDPIY = 96; @@ -267,386 +400,185 @@ void SvpSalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) sal_uInt16 SvpSalGraphics::GetBitCount() const { - return SvpSalBitmap::getBitCountFromScanlineFormat( m_aDevice->getScanlineFormat() ); + if (CAIRO_FORMAT_A1 == cairo_image_surface_get_format(m_pSurface)) + return 1; + return 32; } long SvpSalGraphics::GetGraphicsWidth() const { - if( m_aDevice.get() ) - { - basegfx::B2IVector aSize = m_aOrigDevice->getSize(); - return aSize.getX(); - } - return 0; + return m_pSurface ? cairo_image_surface_get_width(m_pSurface) : 0; } void SvpSalGraphics::ResetClipRegion() { - m_aDevice = m_aOrigDevice; - m_aClipMap.reset(); - m_bClipSetup = true; m_aClipRegion.SetNull(); } -// verify clip for the whole area is setup -void SvpSalGraphics::ensureClip() -{ - if (m_bClipSetup) - return; - - m_aDevice = m_aOrigDevice; - basegfx::B2IVector aSize = m_aDevice->getSize(); - m_aClipMap = basebmp::createClipDevice( aSize ); - - RectangleVector aRectangles; - m_aClipRegion.GetRegionRectangles(aRectangles); - - for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter) - { - const long nW(aRectIter->GetWidth()); - if(nW) - { - const long nH(aRectIter->GetHeight()); - - if(nH) - { - basegfx::B2DPolyPolygon aFull; - - aFull.append( - basegfx::tools::createPolygonFromRect( - basegfx::B2DRectangle( - aRectIter->Left(), - aRectIter->Top(), - aRectIter->Left() + nW, - aRectIter->Top() + nH))); - m_aClipMap->fillPolyPolygon(aFull, basebmp::Color(0), basebmp::DrawMode_PAINT); - } - } - } - m_bClipSetup = true; -} - -SvpSalGraphics::ClipUndoHandle::~ClipUndoHandle() -{ - if( m_aDevice.get() ) - m_rGfx.m_aDevice = m_aDevice; -} - -// setup a clip rectangle -only- iff we have to; if aRange -// is entirely contained inside an existing clip frame, we -// will avoid setting up the clip bitmap. Similarly if the -// range doesn't appear at all we return true to avoid -// rendering -bool SvpSalGraphics::isClippedSetup( const basegfx::B2IBox &aRange, SvpSalGraphics::ClipUndoHandle &rUndo ) -{ - if( m_bClipSetup ) - return false; - - if( m_aClipRegion.IsEmpty() ) // no clipping - return false; - - // fprintf( stderr, "ensureClipFor: %d, %d %dx%d\n", - // aRange.getMinX(), aRange.getMinY(), - // (int)aRange.getWidth(), (int)aRange.getHeight() ); - - // first see if aRange is purely internal to one of the clip regions - Rectangle aRect( Point( aRange.getMinX(), aRange.getMinY() ), - Size( aRange.getWidth(), aRange.getHeight() ) ); - - // then see if we are overlapping with just one - int nHit = 0; - Rectangle aHitRect; - RectangleVector aRectangles; - m_aClipRegion.GetRegionRectangles(aRectangles); - for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter) - { - if( aRectIter->IsOver( aRect ) ) - { - aHitRect = *aRectIter; - nHit++; - } - } - - if( nHit == 0 ) // rendering outside any clipping region - { - SAL_INFO("vcl.headless", "SvpSalGraphics::isClippedSetup: degenerate case detected ..."); - return true; - } - else if( nHit == 1 ) // common path: rendering against just one clipping region - { - if( aHitRect.IsInside( aRect ) ) - { - //The region to be painted (aRect) is equal to or inside the - //current clipping region - SAL_INFO("vcl.headless", "SvpSalGraphics::isClippedSetup: is inside ! avoid deeper clip ..."); - return false; - } - SAL_INFO("vcl.headless", "SvpSalGraphics::isClippedSetup: operation only overlaps with a single clip zone"); - rUndo.m_aDevice = m_aDevice; - m_aDevice = basebmp::subsetBitmapDevice( m_aOrigDevice, - basegfx::B2IBox (aHitRect.Left(), - aHitRect.Top(), - aHitRect.Right() + 1, - aHitRect.Bottom() + 1) ); - return false; - } -// fprintf (stderr, "URK: complex & slow clipping case\n" ); - // horribly slow & complicated case ... - - ensureClip(); - return false; -} - -// Clipping by creating unconditional mask bitmaps is horribly -// slow so defer it, as much as possible. It is common to get -// 3 rectangles pushed, and have to create a vast off-screen -// mask only to destroy it shortly afterwards. That is -// particularly galling if we render only to a small, -// well defined rectangular area inside one of these clip -// rectangles. - -// ensureClipFor() or ensureClip() need to be called before -// real rendering. FIXME: we should prolly push this down to -// bitmapdevice instead. bool SvpSalGraphics::setClipRegion( const vcl::Region& i_rClip ) { m_aClipRegion = i_rClip; - m_aClipMap.reset(); - if( i_rClip.IsEmpty() ) - { - m_aDevice = m_aOrigDevice; - m_bClipSetup = true; - return true; - } - - RectangleVector aRectangles; - i_rClip.GetRegionRectangles(aRectangles); - - if (1 == aRectangles.size()) - { - //simplest case, subset the device to clip bounds - m_aClipMap.reset(); - - const Rectangle& aBoundRect = aRectangles[0]; - m_aDevice = basebmp::subsetBitmapDevice( - m_aOrigDevice, - basegfx::B2IBox(aBoundRect.Left(),aBoundRect.Top(),aBoundRect.Right() + 1,aBoundRect.Bottom() + 1) ); - - m_bClipSetup = true; - } - else - { - //more complex, either setup and tear down temporary - //subsets of the original device around render calls - //or generate m_aClipMap and pass that to basebmp - //calls - m_aDevice = m_aOrigDevice; - m_bClipSetup = false; - } - return true; } void SvpSalGraphics::SetLineColor() { - m_bUseLineColor = false; + m_aLineColor = SALCOLOR_NONE; } void SvpSalGraphics::SetLineColor( SalColor nSalColor ) { - m_bUseLineColor = true; - m_aLineColor = basebmp::Color( nSalColor ); + m_aLineColor = nSalColor; } void SvpSalGraphics::SetFillColor() { - m_bUseFillColor = false; + m_aFillColor = SALCOLOR_NONE; } void SvpSalGraphics::SetFillColor( SalColor nSalColor ) { - m_bUseFillColor = true; - m_aFillColor = basebmp::Color( nSalColor ); + m_aFillColor = nSalColor; } -void SvpSalGraphics::SetXORMode( bool bSet, bool ) +void SvpSalGraphics::SetXORMode(bool bSet, bool bInvert) { - m_aDrawMode = bSet ? basebmp::DrawMode_XOR : basebmp::DrawMode_PAINT; + m_ePaintMode = bInvert ? INVERT : (bSet ? XOR : OVERPAINT); } void SvpSalGraphics::SetROPLineColor( SalROPColor nROPColor ) { - m_bUseLineColor = true; switch( nROPColor ) { - case SAL_ROP_0: - m_aLineColor = basebmp::Color( 0 ); + case SalROPColor::N0: + m_aLineColor = MAKE_SALCOLOR(0, 0, 0); break; - case SAL_ROP_1: - m_aLineColor = basebmp::Color( 0xffffff ); + case SalROPColor::N1: + m_aLineColor = MAKE_SALCOLOR(0xff, 0xff, 0xff); break; - case SAL_ROP_INVERT: - m_aLineColor = basebmp::Color( 0xffffff ); + case SalROPColor::Invert: + m_aLineColor = MAKE_SALCOLOR(0xff, 0xff, 0xff); break; } } void SvpSalGraphics::SetROPFillColor( SalROPColor nROPColor ) { - m_bUseFillColor = true; switch( nROPColor ) { - case SAL_ROP_0: - m_aFillColor = basebmp::Color( 0 ); + case SalROPColor::N0: + m_aFillColor = MAKE_SALCOLOR(0, 0, 0); break; - case SAL_ROP_1: - m_aFillColor = basebmp::Color( 0xffffff ); + case SalROPColor::N1: + m_aFillColor = MAKE_SALCOLOR(0xff, 0xff, 0xff); break; - case SAL_ROP_INVERT: - m_aFillColor = basebmp::Color( 0xffffff ); + case SalROPColor::Invert: + m_aFillColor = MAKE_SALCOLOR(0xff, 0xff, 0xff); break; } } void SvpSalGraphics::drawPixel( long nX, long nY ) { - if( m_bUseLineColor ) + if (m_aLineColor != SALCOLOR_NONE) { - ensureClip(); - m_aDevice->setPixel( basegfx::B2IPoint( nX, nY ), - m_aLineColor, - m_aDrawMode, - m_aClipMap - ); + drawPixel(nX, nY, m_aLineColor); } - dbgOut( m_aDevice ); } void SvpSalGraphics::drawPixel( long nX, long nY, SalColor nSalColor ) { - basebmp::Color aColor( nSalColor ); - ensureClip(); - m_aDevice->setPixel( basegfx::B2IPoint( nX, nY ), - aColor, - m_aDrawMode, - m_aClipMap - ); - dbgOut( m_aDevice ); + SalColor aOrigFillColor = m_aFillColor; + SalColor aOrigLineColor = m_aLineColor; + + basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect(basegfx::B2DRectangle(nX, nY, nX+1, nY+1)); + m_aLineColor = SALCOLOR_NONE; + m_aFillColor = nSalColor; + + drawPolyPolygon(basegfx::B2DPolyPolygon(aRect)); + + m_aFillColor = aOrigFillColor; + m_aLineColor = aOrigLineColor; } -void SvpSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) +void SvpSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight ) { - if( m_bUseLineColor ) + // because of the -1 hack we have to do fill and draw separately + SalColor aOrigFillColor = m_aFillColor; + SalColor aOrigLineColor = m_aLineColor; + m_aFillColor = SALCOLOR_NONE; + m_aLineColor = SALCOLOR_NONE; + + if (aOrigFillColor != SALCOLOR_NONE) { - ensureClip(); // FIXME: for ... - m_aDevice->drawLine( basegfx::B2IPoint( nX1, nY1 ), - basegfx::B2IPoint( nX2, nY2 ), - m_aLineColor, - m_aDrawMode, - m_aClipMap ); + basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect(basegfx::B2DRectangle(nX, nY, nX+nWidth, nY+nHeight)); + m_aFillColor = aOrigFillColor; + drawPolyPolygon(basegfx::B2DPolyPolygon(aRect)); + m_aFillColor = SALCOLOR_NONE; } - dbgOut( m_aDevice ); -} -void SvpSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight ) -{ - if ((m_bUseLineColor || m_bUseFillColor) && m_aDevice) + if (aOrigLineColor != SALCOLOR_NONE) { - ensureClip(); // FIXME: for ... - if( m_bUseFillColor ) - { - basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( nX, nY, nX+nWidth, nY+nHeight ) ); - basegfx::B2DPolyPolygon aPolyPoly( aRect ); - m_aDevice->fillPolyPolygon( aPolyPoly, m_aFillColor, m_aDrawMode, m_aClipMap ); - } - if( m_bUseLineColor ) - { - // need same -1 hack as X11SalGraphicsImpl::drawRect - basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( nX, nY, nX+nWidth-1, nY+nHeight-1 ) ); - m_aDevice->drawPolygon( aRect, m_aLineColor, m_aDrawMode, m_aClipMap ); - } + // need same -1 hack as X11SalGraphicsImpl::drawRect + basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect(basegfx::B2DRectangle( nX, nY, nX+nWidth-1, nY+nHeight-1)); + m_aLineColor = aOrigLineColor; + drawPolyPolygon(basegfx::B2DPolyPolygon(aRect)); + m_aLineColor = SALCOLOR_NONE; } - dbgOut( m_aDevice ); + + m_aFillColor = aOrigFillColor; + m_aLineColor = aOrigLineColor; } -void SvpSalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry ) +void SvpSalGraphics::drawPolyLine(sal_uInt32 nPoints, const SalPoint* pPtAry) { - if (m_bUseLineColor && nPoints && m_aDevice) - { - basegfx::B2DPolygon aPoly; - aPoly.append( basegfx::B2DPoint( pPtAry->mnX, pPtAry->mnY ), nPoints ); - for( sal_uLong i = 1; i < nPoints; i++ ) - aPoly.setB2DPoint( i, basegfx::B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) ); - aPoly.setClosed( false ); - ensureClip(); // FIXME: for ... - m_aDevice->drawPolygon( aPoly, m_aLineColor, m_aDrawMode, m_aClipMap ); - } - dbgOut( m_aDevice ); + basegfx::B2DPolygon aPoly; + aPoly.append(basegfx::B2DPoint(pPtAry->mnX, pPtAry->mnY), nPoints); + for (sal_uInt32 i = 1; i < nPoints; ++i) + aPoly.setB2DPoint(i, basegfx::B2DPoint(pPtAry[i].mnX, pPtAry[i].mnY)); + aPoly.setClosed(false); + + drawPolyLine(aPoly, 0.0, basegfx::B2DVector(1.0, 1.0), basegfx::B2DLineJoin::Miter, + css::drawing::LineCap_BUTT, 15.0 * F_PI180 /*default*/); } -void SvpSalGraphics::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) +void SvpSalGraphics::drawPolygon(sal_uInt32 nPoints, const SalPoint* pPtAry) { - if ((m_bUseLineColor || m_bUseFillColor) && nPoints && m_aDevice) - { - basegfx::B2DPolygon aPoly; - aPoly.append( basegfx::B2DPoint( pPtAry->mnX, pPtAry->mnY ), nPoints ); - for( sal_uLong i = 1; i < nPoints; i++ ) - aPoly.setB2DPoint( i, basegfx::B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) ); - ensureClip(); // FIXME: for ... - if( m_bUseFillColor ) - { - aPoly.setClosed( true ); - m_aDevice->fillPolyPolygon( basegfx::B2DPolyPolygon(aPoly), m_aFillColor, m_aDrawMode, m_aClipMap ); - } - if( m_bUseLineColor ) - { - aPoly.setClosed( false ); - m_aDevice->drawPolygon( aPoly, m_aLineColor, m_aDrawMode, m_aClipMap ); - } - } - dbgOut( m_aDevice ); + basegfx::B2DPolygon aPoly; + aPoly.append(basegfx::B2DPoint(pPtAry->mnX, pPtAry->mnY), nPoints); + for (sal_uInt32 i = 1; i < nPoints; ++i) + aPoly.setB2DPoint(i, basegfx::B2DPoint(pPtAry[i].mnX, pPtAry[i].mnY)); + + drawPolyPolygon(basegfx::B2DPolyPolygon(aPoly)); } -void SvpSalGraphics::drawPolyPolygon( sal_uInt32 nPoly, - const sal_uInt32* pPointCounts, - PCONSTSALPOINT* pPtAry ) +void SvpSalGraphics::drawPolyPolygon(sal_uInt32 nPoly, + const sal_uInt32* pPointCounts, + PCONSTSALPOINT* pPtAry) { - if ((m_bUseLineColor || m_bUseFillColor) && nPoly && m_aDevice) + basegfx::B2DPolyPolygon aPolyPoly; + for(sal_uInt32 nPolygon = 0; nPolygon < nPoly; ++nPolygon) { - basegfx::B2DPolyPolygon aPolyPoly; - for( sal_uInt32 nPolygon = 0; nPolygon < nPoly; nPolygon++ ) + sal_uInt32 nPoints = pPointCounts[nPolygon]; + if (nPoints) { - sal_uInt32 nPoints = pPointCounts[nPolygon]; - if( nPoints ) - { - PCONSTSALPOINT pPoints = pPtAry[nPolygon]; - basegfx::B2DPolygon aPoly; - aPoly.append( basegfx::B2DPoint( pPoints->mnX, pPoints->mnY ), nPoints ); - for( sal_uInt32 i = 1; i < nPoints; i++ ) - aPoly.setB2DPoint( i, basegfx::B2DPoint( pPoints[i].mnX, pPoints[i].mnY ) ); + PCONSTSALPOINT pPoints = pPtAry[nPolygon]; + basegfx::B2DPolygon aPoly; + aPoly.append( basegfx::B2DPoint(pPoints->mnX, pPoints->mnY), nPoints); + for (sal_uInt32 i = 1; i < nPoints; ++i) + aPoly.setB2DPoint(i, basegfx::B2DPoint( pPoints[i].mnX, pPoints[i].mnY)); - aPolyPoly.append( aPoly ); - } - } - ensureClip(); // FIXME: for ... - if( m_bUseFillColor ) - { - aPolyPoly.setClosed( true ); - m_aDevice->fillPolyPolygon( aPolyPoly, m_aFillColor, m_aDrawMode, m_aClipMap ); - } - if( m_bUseLineColor ) - { - aPolyPoly.setClosed( false ); - nPoly = aPolyPoly.count(); - for( sal_uInt32 i = 0; i < nPoly; i++ ) - m_aDevice->drawPolygon( aPolyPoly.getB2DPolygon(i), m_aLineColor, m_aDrawMode, m_aClipMap ); + aPolyPoly.append(aPoly); } } - dbgOut( m_aDevice ); + + drawPolyPolygon(aPolyPoly); } -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0) -static void AddPolygonToPath(cairo_t* cr, const basegfx::B2DPolygon& rPolygon, bool bClosePath) +static const basegfx::B2DPoint aHalfPointOfs(0.5, 0.5); + +static void AddPolygonToPath(cairo_t* cr, const basegfx::B2DPolygon& rPolygon, bool bClosePath, + bool bPixelSnap, bool bLineDraw) { // short circuit if there is nothing to do const int nPointCount = rPolygon.count(); @@ -656,6 +588,8 @@ static void AddPolygonToPath(cairo_t* cr, const basegfx::B2DPolygon& rPolygon, b } const bool bHasCurves = rPolygon.areControlPointsUsed(); + basegfx::B2DPoint aLast; + for( int nPointIdx = 0, nPrevIdx = 0;; nPrevIdx = nPointIdx++ ) { int nClosedIdx = nPointIdx; @@ -674,10 +608,23 @@ static void AddPolygonToPath(cairo_t* cr, const basegfx::B2DPolygon& rPolygon, b basegfx::B2DPoint aPoint = rPolygon.getB2DPoint( nClosedIdx ); + if( bPixelSnap) + { + // snap device coordinates to full pixels + aPoint.setX( basegfx::fround( aPoint.getX() ) ); + aPoint.setY( basegfx::fround( aPoint.getY() ) ); + } + + if( bLineDraw ) + { + aPoint += aHalfPointOfs; + } + if( !nPointIdx ) { // first point => just move there cairo_move_to(cr, aPoint.getX(), aPoint.getY()); + aLast = aPoint; continue; } @@ -696,9 +643,29 @@ static void AddPolygonToPath(cairo_t* cr, const basegfx::B2DPolygon& rPolygon, b { basegfx::B2DPoint aCP1 = rPolygon.getNextControlPoint( nPrevIdx ); basegfx::B2DPoint aCP2 = rPolygon.getPrevControlPoint( nClosedIdx ); + if( bLineDraw ) + { + aCP1 += aHalfPointOfs; + aCP2 += aHalfPointOfs; + } + + // tdf#99165 if the control points are 'empty', create the mathematical + // correct replacement ones to avoid problems with the graphical sub-system + if(aCP1.equal(aLast)) + { + aCP1 = aLast + ((aCP2 - aLast) * 0.3); + } + + if(aCP2.equal(aPoint)) + { + aCP2 = aPoint + ((aCP1 - aPoint) * 0.3); + } + cairo_curve_to(cr, aCP1.getX(), aCP1.getY(), aCP2.getX(), aCP2.getY(), aPoint.getX(), aPoint.getY()); } + + aLast = aPoint; } if( bClosePath ) @@ -706,18 +673,36 @@ static void AddPolygonToPath(cairo_t* cr, const basegfx::B2DPolygon& rPolygon, b cairo_close_path(cr); } } -#endif + +void SvpSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) +{ + basegfx::B2DPolygon aPoly; + aPoly.append(basegfx::B2DPoint(nX1, nY1), 2); + aPoly.setB2DPoint(1, basegfx::B2DPoint(nX2, nY2)); + aPoly.setClosed(false); + + cairo_t* cr = getCairoContext(false); + clipRegion(cr); + + AddPolygonToPath(cr, aPoly, aPoly.isClosed(), !getAntiAliasB2DDraw(), true); + + applyColor(cr, m_aLineColor); + + basegfx::B2DRange extents = getClippedStrokeDamage(cr); + + cairo_stroke(cr); + + releaseCairoContext(cr, false, extents); +} bool SvpSalGraphics::drawPolyLine( - const ::basegfx::B2DPolygon& rPolyLine, + const basegfx::B2DPolygon& rPolyLine, double fTransparency, - const ::basegfx::B2DVector& rLineWidths, + const basegfx::B2DVector& rLineWidths, basegfx::B2DLineJoin eLineJoin, - css::drawing::LineCap eLineCap) + css::drawing::LineCap eLineCap, + double fMiterMinimumAngle) { - bool bRet = false; - (void)rPolyLine; (void)fTransparency; (void)rLineWidths; (void)eLineJoin; (void)eLineCap; -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0) // short circuit if there is nothing to do const int nPointCount = rPolyLine.count(); if (nPointCount <= 0) @@ -725,55 +710,30 @@ bool SvpSalGraphics::drawPolyLine( return true; } - // reject requests that cannot be handled yet - if (rLineWidths.getX() != rLineWidths.getY()) - { - SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawPolyLine case"); - return false; - } - - // #i101491# Cairo does not support B2DLineJoin::NONE; return false to use - // the fallback (own geometry preparation) - // #i104886# linejoin-mode and thus the above only applies to "fat" lines - if (basegfx::B2DLINEJOIN_NONE == eLineJoin && rLineWidths.getX() > 1.3) - { - SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawPolyLine case"); - return false; - } - - cairo_t* cr = createCairoContext(m_aDevice); - if (!cr) - return bRet; - - if (!m_aDevice->isTopDown()) - { - cairo_scale(cr, 1, -1.0); - cairo_translate(cr, 0.0, -m_aDevice->getSize().getY()); - } + const bool bNoJoin = (basegfx::B2DLineJoin::NONE == eLineJoin && basegfx::fTools::more(rLineWidths.getX(), 0.0)); + cairo_t* cr = getCairoContext(false); clipRegion(cr); // setup line attributes cairo_line_join_t eCairoLineJoin = CAIRO_LINE_JOIN_MITER; switch (eLineJoin) { - case basegfx::B2DLINEJOIN_NONE: - eCairoLineJoin = /*TODO?*/CAIRO_LINE_JOIN_MITER; - break; - case basegfx::B2DLINEJOIN_MIDDLE: - eCairoLineJoin = /*TODO?*/CAIRO_LINE_JOIN_MITER; - break; - case basegfx::B2DLINEJOIN_BEVEL: + case basegfx::B2DLineJoin::Bevel: eCairoLineJoin = CAIRO_LINE_JOIN_BEVEL; break; - case basegfx::B2DLINEJOIN_MITER: - eCairoLineJoin = CAIRO_LINE_JOIN_MITER; - break; - case basegfx::B2DLINEJOIN_ROUND: + case basegfx::B2DLineJoin::Round: eCairoLineJoin = CAIRO_LINE_JOIN_ROUND; break; + case basegfx::B2DLineJoin::NONE: + case basegfx::B2DLineJoin::Miter: + eCairoLineJoin = CAIRO_LINE_JOIN_MITER; + break; } + // convert miter minimum angle to miter limit + double fMiterLimit = 1.0 / sin( fMiterMinimumAngle / 2.0); + // setup cap attribute cairo_line_cap_t eCairoLineCap(CAIRO_LINE_CAP_BUTT); @@ -796,43 +756,63 @@ bool SvpSalGraphics::drawPolyLine( } } - AddPolygonToPath(cr, rPolyLine, rPolyLine.isClosed()); - - cairo_rectangle_int_t extents; - basebmp::IBitmapDeviceDamageTrackerSharedPtr xDamageTracker(m_aDevice->getDamageTracker()); - - cairo_set_source_rgba(cr, m_aLineColor.getRed()/255.0, - m_aLineColor.getGreen()/255.0, - m_aLineColor.getBlue()/255.0, + cairo_set_source_rgba(cr, SALCOLOR_RED(m_aLineColor)/255.0, + SALCOLOR_GREEN(m_aLineColor)/255.0, + SALCOLOR_BLUE(m_aLineColor)/255.0, 1.0-fTransparency); cairo_set_line_join(cr, eCairoLineJoin); cairo_set_line_cap(cr, eCairoLineCap); cairo_set_line_width(cr, rLineWidths.getX()); + cairo_set_miter_limit(cr, fMiterLimit); - if (xDamageTracker) - extents = getStrokeDamage(cr); - - cairo_stroke(cr); - cairo_surface_flush(cairo_get_target(cr)); - cairo_destroy(cr); // unref + basegfx::B2DRange extents(0, 0, 0, 0); - if (xDamageTracker) + if (!bNoJoin) { - xDamageTracker->damaged(basegfx::B2IBox(extents.x, extents.y, extents.x + extents.width, - extents.y + extents.height)); + AddPolygonToPath(cr, rPolyLine, rPolyLine.isClosed(), !getAntiAliasB2DDraw(), true); + extents = getClippedStrokeDamage(cr); + cairo_stroke(cr); } - bRet = true; -#endif - return bRet; + else + { + // emulate rendering::PathJoinType::NONE by painting single edges + const sal_uInt32 nEdgeCount(rPolyLine.isClosed() ? nPointCount : nPointCount - 1); + basegfx::B2DPolygon aEdge; + aEdge.append(rPolyLine.getB2DPoint(0)); + aEdge.append(basegfx::B2DPoint(0.0, 0.0)); + + for (sal_uInt32 i = 0; i < nEdgeCount; ++i) + { + const sal_uInt32 nNextIndex((i + 1) % nPointCount); + aEdge.setB2DPoint(1, rPolyLine.getB2DPoint(nNextIndex)); + aEdge.setNextControlPoint(0, rPolyLine.getNextControlPoint(i % nPointCount)); + aEdge.setPrevControlPoint(1, rPolyLine.getPrevControlPoint(nNextIndex)); + + AddPolygonToPath(cr, aEdge, false, !getAntiAliasB2DDraw(), true); + + extents.expand(getStrokeDamage(cr)); + + cairo_stroke(cr); + + // prepare next step + aEdge.setB2DPoint(0, aEdge.getB2DPoint(1)); + } + + extents.intersect(getClipBox(cr)); + } + + releaseCairoContext(cr, false, extents); + + return true; } bool SvpSalGraphics::drawPolyLineBezier( sal_uInt32, const SalPoint*, const sal_uInt8* ) { - SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawPolyLineBezier case"); + SAL_INFO("vcl.gdi", "unsupported SvpSalGraphics::drawPolyLineBezier case"); return false; } @@ -840,7 +820,7 @@ bool SvpSalGraphics::drawPolygonBezier( sal_uInt32, const SalPoint*, const sal_uInt8* ) { - SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawPolygonBezier case"); + SAL_INFO("vcl.gdi", "unsupported SvpSalGraphics::drawPolygonBezier case"); return false; } @@ -849,59 +829,97 @@ bool SvpSalGraphics::drawPolyPolygonBezier( sal_uInt32, const SalPoint* const*, const sal_uInt8* const* ) { - SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawPolyPolygonBezier case"); + SAL_INFO("vcl.gdi", "unsupported SvpSalGraphics::drawPolyPolygonBezier case"); return false; } +void SvpSalGraphics::setupPolyPolygon(cairo_t* cr, const basegfx::B2DPolyPolygon& rPolyPoly) +{ + clipRegion(cr); + + for (const basegfx::B2DPolygon* pPoly = rPolyPoly.begin(); pPoly != rPolyPoly.end(); ++pPoly) + AddPolygonToPath(cr, *pPoly, true, !getAntiAliasB2DDraw(), m_aLineColor != SALCOLOR_NONE); +} + bool SvpSalGraphics::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly, double fTransparency) { - bool bRet = false; - (void)rPolyPoly; (void)fTransparency; -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0) - if (m_bUseLineColor || !m_bUseFillColor) + cairo_t* cr = getCairoContext(true); + + setupPolyPolygon(cr, rPolyPoly); + + basegfx::B2DRange extents(0, 0, 0, 0); + + if (m_aFillColor != SALCOLOR_NONE) { - SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawPolyPolygon case"); - return false; - } + cairo_set_source_rgba(cr, SALCOLOR_RED(m_aFillColor)/255.0, + SALCOLOR_GREEN(m_aFillColor)/255.0, + SALCOLOR_BLUE(m_aFillColor)/255.0, + 1.0-fTransparency); - cairo_t* cr = createCairoContext(m_aDevice); - if (!cr) - return false; + if (m_aLineColor == SALCOLOR_NONE) + extents = getClippedFillDamage(cr); - if (!m_aDevice->isTopDown()) + cairo_fill_preserve(cr); + } + + if (m_aLineColor != SALCOLOR_NONE) { - cairo_scale(cr, 1, -1.0); - cairo_translate(cr, 0.0, -m_aDevice->getSize().getY()); + cairo_set_source_rgba(cr, SALCOLOR_RED(m_aLineColor)/255.0, + SALCOLOR_GREEN(m_aLineColor)/255.0, + SALCOLOR_BLUE(m_aLineColor)/255.0, + 1.0-fTransparency); + + extents = getClippedStrokeDamage(cr); + + cairo_stroke_preserve(cr); } - clipRegion(cr); + releaseCairoContext(cr, true, extents); - cairo_set_source_rgba(cr, m_aFillColor.getRed()/255.0, - m_aFillColor.getGreen()/255.0, - m_aFillColor.getBlue()/255.0, - 1.0-fTransparency); + return true; +} - for (const basegfx::B2DPolygon* pPoly = rPolyPoly.begin(); pPoly != rPolyPoly.end(); ++pPoly) - AddPolygonToPath(cr, *pPoly, true); +void SvpSalGraphics::applyColor(cairo_t *cr, SalColor aColor) +{ + if (CAIRO_FORMAT_ARGB32 == cairo_image_surface_get_format(m_pSurface)) + { + cairo_set_source_rgba(cr, SALCOLOR_RED(aColor)/255.0, + SALCOLOR_GREEN(aColor)/255.0, + SALCOLOR_BLUE(aColor)/255.0, + 1.0); + } + else + { + double fSet = aColor == COL_BLACK ? 0.0 : 1.0; + cairo_set_source_rgba(cr, 1, 1, 1, fSet); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + } +} - cairo_rectangle_int_t extents; - basebmp::IBitmapDeviceDamageTrackerSharedPtr xDamageTracker(m_aDevice->getDamageTracker()); - if (xDamageTracker) - extents = getFillDamage(cr); +void SvpSalGraphics::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly) +{ + cairo_t* cr = getCairoContext(true); - cairo_fill(cr); + setupPolyPolygon(cr, rPolyPoly); - cairo_surface_flush(cairo_get_target(cr)); - cairo_destroy(cr); // unref + basegfx::B2DRange extents(0, 0, 0, 0); - if (xDamageTracker) + if (m_aFillColor != SALCOLOR_NONE) { - xDamageTracker->damaged(basegfx::B2IBox(extents.x, extents.y, extents.x + extents.width, - extents.y + extents.height)); + applyColor(cr, m_aFillColor); + if (m_aLineColor == SALCOLOR_NONE) + extents = getClippedFillDamage(cr); + cairo_fill_preserve(cr); } - bRet = true; -#endif - return bRet; + + if (m_aLineColor != SALCOLOR_NONE) + { + applyColor(cr, m_aLineColor); + extents = getClippedStrokeDamage(cr); + cairo_stroke_preserve(cr); + } + + releaseCairoContext(cr, true, extents); } void SvpSalGraphics::copyArea( long nDestX, @@ -912,164 +930,291 @@ void SvpSalGraphics::copyArea( long nDestX, long nSrcHeight, sal_uInt16 /*nFlags*/ ) { - basegfx::B2IBox aSrcRect( nSrcX, nSrcY, nSrcX+nSrcWidth, nSrcY+nSrcHeight ); - basegfx::B2IBox aDestRect( nDestX, nDestY, nDestX+nSrcWidth, nDestY+nSrcHeight ); - // fprintf( stderr, "copyArea %ld pixels - clip region %d\n", - // (long)(nSrcWidth * nSrcHeight), m_aClipMap.get() != NULL ); - SvpSalGraphics::ClipUndoHandle aUndo( this ); - if( !isClippedSetup( aDestRect, aUndo ) ) - m_aDevice->drawBitmap( m_aOrigDevice, aSrcRect, aDestRect, basebmp::DrawMode_PAINT, m_aClipMap ); - dbgOut( m_aDevice ); + SalTwoRect aTR(nSrcX, nSrcY, nSrcWidth, nSrcHeight, nDestX, nDestY, nSrcWidth, nSrcHeight); + copyBits(aTR, this); +} + +static basegfx::B2DRange renderSource(cairo_t* cr, const SalTwoRect& rTR, + cairo_surface_t* source) +{ + cairo_rectangle(cr, rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight); + + basegfx::B2DRange extents = getClippedFillDamage(cr); + + cairo_clip(cr); + + cairo_translate(cr, rTR.mnDestX, rTR.mnDestY); + if (rTR.mnSrcWidth != 0 && rTR.mnSrcHeight != 0) { + cairo_scale(cr, (double)(rTR.mnDestWidth)/rTR.mnSrcWidth, ((double)rTR.mnDestHeight)/rTR.mnSrcHeight); + } + cairo_set_source_surface(cr, source, -rTR.mnSrcX, -rTR.mnSrcY); + cairo_paint(cr); + + return extents; } -void SvpSalGraphics::copyBits( const SalTwoRect& rPosAry, +void SvpSalGraphics::copySource( const SalTwoRect& rTR, + cairo_surface_t* source ) +{ + cairo_t* cr = getCairoContext(false); + clipRegion(cr); + + basegfx::B2DRange extents = renderSource(cr, rTR, source); + + releaseCairoContext(cr, false, extents); +} + +void SvpSalGraphics::copyBits( const SalTwoRect& rTR, SalGraphics* pSrcGraphics ) { - if( !m_aDevice.get() ) - return; + SalTwoRect aTR(rTR); SvpSalGraphics* pSrc = pSrcGraphics ? static_cast<SvpSalGraphics*>(pSrcGraphics) : this; - basegfx::B2IBox aSrcRect( rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcX+rPosAry.mnSrcWidth, - rPosAry.mnSrcY+rPosAry.mnSrcHeight ); - basegfx::B2IBox aDestRect( rPosAry.mnDestX, rPosAry.mnDestY, - rPosAry.mnDestX+rPosAry.mnDestWidth, - rPosAry.mnDestY+rPosAry.mnDestHeight ); - SvpSalGraphics::ClipUndoHandle aUndo( this ); - if( !isClippedSetup( aDestRect, aUndo ) ) - m_aDevice->drawBitmap( pSrc->m_aOrigDevice, aSrcRect, aDestRect, basebmp::DrawMode_PAINT, m_aClipMap ); - dbgOut( m_aDevice ); -} + cairo_surface_t* source = pSrc->m_pSurface; -void SvpSalGraphics::drawBitmap( const SalTwoRect& rPosAry, - const SalBitmap& rSalBitmap ) -{ - if( !m_aDevice.get() ) - return; + cairo_surface_t *pCopy = nullptr; + if (pSrc == this) + { + //self copy is a problem, so dup source in that case +#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 12, 0) + pCopy = cairo_surface_create_similar(source, + cairo_surface_get_content(m_pSurface), + aTR.mnSrcWidth, + aTR.mnSrcHeight); +#else + pCopy = cairo_surface_create_similar_image(source, + cairo_image_surface_get_format(m_pSurface), + aTR.mnSrcWidth, + aTR.mnSrcHeight); +#endif - const SvpSalBitmap& rSrc = static_cast<const SvpSalBitmap&>(rSalBitmap); - basegfx::B2IBox aSrcRect( rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcX+rPosAry.mnSrcWidth, - rPosAry.mnSrcY+rPosAry.mnSrcHeight ); - basegfx::B2IBox aDestRect( rPosAry.mnDestX, rPosAry.mnDestY, - rPosAry.mnDestX+rPosAry.mnDestWidth, - rPosAry.mnDestY+rPosAry.mnDestHeight ); + cairo_t* cr = cairo_create(pCopy); + cairo_set_source_surface(cr, source, -aTR.mnSrcX, -aTR.mnSrcY); + cairo_rectangle(cr, 0, 0, aTR.mnSrcWidth, aTR.mnSrcHeight); + cairo_fill(cr); + cairo_destroy(cr); + + source = pCopy; + + aTR.mnSrcX = 0; + aTR.mnSrcY = 0; + } - SvpSalGraphics::ClipUndoHandle aUndo( this ); - if( !isClippedSetup( aDestRect, aUndo ) ) - m_aDevice->drawBitmap( rSrc.getBitmap(), aSrcRect, aDestRect, basebmp::DrawMode_PAINT, m_aClipMap ); - dbgOut( m_aDevice ); + copySource(aTR, source); + + if (pCopy) + cairo_surface_destroy(pCopy); } -void SvpSalGraphics::drawBitmap( const SalTwoRect&, - const SalBitmap&, - SalColor ) +void SvpSalGraphics::drawBitmap(const SalTwoRect& rTR, const SalBitmap& rSourceBitmap) { - // SNI, as in X11 plugin + SourceHelper aSurface(rSourceBitmap); + cairo_surface_t* source = aSurface.getSurface(); + if (!source) + { + SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawBitmap case"); + } + copySource(rTR, source); } -void SvpSalGraphics::drawBitmap( const SalTwoRect& rPosAry, - const SalBitmap& rSalBitmap, +void SvpSalGraphics::drawBitmap( const SalTwoRect& rTR, + const SalBitmap& rSourceBitmap, const SalBitmap& rTransparentBitmap ) { - const SvpSalBitmap& rSrc = static_cast<const SvpSalBitmap&>(rSalBitmap); - const SvpSalBitmap& rSrcTrans = static_cast<const SvpSalBitmap&>(rTransparentBitmap); - basegfx::B2IBox aSrcRect( rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcX+rPosAry.mnSrcWidth, - rPosAry.mnSrcY+rPosAry.mnSrcHeight ); - basegfx::B2IBox aDestRect( rPosAry.mnDestX, rPosAry.mnDestY, - rPosAry.mnDestX+rPosAry.mnDestWidth, - rPosAry.mnDestY+rPosAry.mnDestHeight ); - SvpSalGraphics::ClipUndoHandle aUndo( this ); - if (!isClippedSetup(aDestRect, aUndo) && m_aDevice) - m_aDevice->drawMaskedBitmap( rSrc.getBitmap(), rSrcTrans.getBitmap(), - aSrcRect, aDestRect, basebmp::DrawMode_PAINT, m_aClipMap ); - dbgOut( m_aDevice ); -} - -void SvpSalGraphics::drawMask( const SalTwoRect& rPosAry, + drawAlphaBitmap(rTR, rSourceBitmap, rTransparentBitmap); +} + +static sal_uInt8 unpremultiply(sal_uInt8 c, sal_uInt8 a) +{ + return (a > 0) ? (c * 255 + a / 2) / a : 0; +} + +static sal_uInt8 premultiply(sal_uInt8 c, sal_uInt8 a) +{ + return (c * a + 127) / 255; +} + +void SvpSalGraphics::drawMask( const SalTwoRect& rTR, const SalBitmap& rSalBitmap, SalColor nMaskColor ) { - const SvpSalBitmap& rSrc = static_cast<const SvpSalBitmap&>(rSalBitmap); - basegfx::B2IBox aSrcRect( rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcX+rPosAry.mnSrcWidth, - rPosAry.mnSrcY+rPosAry.mnSrcHeight ); - basegfx::B2IPoint aDestPoint( rPosAry.mnDestX, rPosAry.mnDestY ); - - // BitmapDevice::drawMaskedColor works with 0==transparent, - // 255==opaque. drawMask() semantic is the other way - // around. Therefore, invert mask. - basebmp::BitmapDeviceSharedPtr aCopy = - cloneBitmapDevice( basegfx::B2IVector( rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ), - rSrc.getBitmap() ); - basebmp::Color aBgColor( COL_WHITE ); - aCopy->clear(aBgColor); - basebmp::Color aFgColor( COL_BLACK ); - aCopy->drawMaskedColor( aFgColor, rSrc.getBitmap(), aSrcRect, basegfx::B2IPoint() ); - - basebmp::Color aColor( nMaskColor ); - basegfx::B2IBox aSrcRect2( 0, 0, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ); - const basegfx::B2IBox aClipRect( aDestPoint, basegfx::B2ITuple( aSrcRect.getWidth(), aSrcRect.getHeight() ) ); - - SvpSalGraphics::ClipUndoHandle aUndo( this ); - if( !isClippedSetup( aClipRect, aUndo ) ) - m_aDevice->drawMaskedColor( aColor, aCopy, aSrcRect, aDestPoint, m_aClipMap ); - dbgOut( m_aDevice ); + /** creates an image from the given rectangle, replacing all black pixels + * with nMaskColor and make all other full transparent */ + SourceHelper aSurface(rSalBitmap); + cairo_surface_t* mask = aSurface.getSurface(); + + cairo_surface_flush(mask); + + unsigned char *mask_data = cairo_image_surface_get_data(mask); + + cairo_format_t nFormat = cairo_image_surface_get_format(mask); + assert(nFormat == CAIRO_FORMAT_ARGB32 && "need to implement CAIRO_FORMAT_A1 after all here"); + sal_Int32 nStride = cairo_format_stride_for_width(nFormat, + cairo_image_surface_get_width(mask)); + for (sal_Int32 y = rTR.mnSrcY ; y < rTR.mnSrcY + rTR.mnSrcHeight; ++y) + { + unsigned char *row = mask_data + (nStride*y); + unsigned char *data = row + (rTR.mnSrcX * 4); + for (sal_Int32 x = rTR.mnSrcX; x < rTR.mnSrcX + rTR.mnSrcWidth; ++x) + { + sal_uInt8 b = unpremultiply(data[0], data[3]); + sal_uInt8 g = unpremultiply(data[1], data[3]); + sal_uInt8 r = unpremultiply(data[2], data[3]); + if (r == 0 && g == 0 && b == 0) + { + data[0] = SALCOLOR_BLUE(nMaskColor); + data[1] = SALCOLOR_GREEN(nMaskColor); + data[2] = SALCOLOR_RED(nMaskColor); + data[3] = 0xff; + } + else + { + data[0] = 0; + data[1] = 0; + data[2] = 0; + data[3] = 0; + } + data+=4; + } + } + cairo_surface_mark_dirty(mask); + + cairo_t* cr = getCairoContext(false); + clipRegion(cr); + + cairo_rectangle(cr, rTR.mnDestX, rTR.mnDestY, rTR.mnDestWidth, rTR.mnDestHeight); + + basegfx::B2DRange extents = getClippedFillDamage(cr); + + cairo_clip(cr); + + cairo_translate(cr, rTR.mnDestX, rTR.mnDestY); + cairo_scale(cr, (double)(rTR.mnDestWidth)/rTR.mnSrcWidth, ((double)rTR.mnDestHeight)/rTR.mnSrcHeight); + cairo_set_source_surface(cr, mask, -rTR.mnSrcX, -rTR.mnSrcY); + cairo_paint(cr); + + releaseCairoContext(cr, false, extents); } SalBitmap* SvpSalGraphics::getBitmap( long nX, long nY, long nWidth, long nHeight ) { SvpSalBitmap* pBitmap = new SvpSalBitmap(); + pBitmap->Create(Size(nWidth, nHeight), 32, BitmapPalette()); - if (m_aDevice) - { - basebmp::BitmapDeviceSharedPtr aCopy; - aCopy = cloneBitmapDevice(basegfx::B2IVector(nWidth, nHeight), - m_aDevice); - basegfx::B2IBox aSrcRect( nX, nY, nX+nWidth, nY+nHeight ); - basegfx::B2IBox aDestRect( 0, 0, nWidth, nHeight ); + cairo_surface_t* target = SvpSalGraphics::createCairoSurface(pBitmap->GetBuffer()); + cairo_t* cr = cairo_create(target); - aCopy->drawBitmap( m_aOrigDevice, aSrcRect, aDestRect, basebmp::DrawMode_PAINT ); + SalTwoRect aTR(nX, nY, nWidth, nHeight, 0, 0, nWidth, nHeight); + renderSource(cr, aTR, m_pSurface); - pBitmap->setBitmap( aCopy ); - } + cairo_destroy(cr); + cairo_surface_destroy(target); return pBitmap; } SalColor SvpSalGraphics::getPixel( long nX, long nY ) { - basebmp::Color aColor( m_aOrigDevice->getPixel( basegfx::B2IPoint( nX, nY ) ) ); - return aColor.toInt32(); + cairo_surface_flush(m_pSurface); + cairo_format_t nFormat = cairo_image_surface_get_format(m_pSurface); + assert(nFormat == CAIRO_FORMAT_ARGB32 && "need to implement CAIRO_FORMAT_A1 after all here"); + sal_Int32 nStride = cairo_format_stride_for_width(nFormat, + cairo_image_surface_get_width(m_pSurface)); + unsigned char *surface_data = cairo_image_surface_get_data(m_pSurface); + unsigned char *row = surface_data + (nStride*nY); + unsigned char *data = row + (nX * 4); + sal_uInt8 b = unpremultiply(data[0], data[3]); + sal_uInt8 g = unpremultiply(data[1], data[3]); + sal_uInt8 r = unpremultiply(data[2], data[3]); + return MAKE_SALCOLOR(r, g, b); +} + +namespace +{ + cairo_pattern_t * create_stipple() + { + static unsigned char data[16] = { 0xFF, 0xFF, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0xFF, + 0x00, 0x00, 0xFF, 0xFF }; + cairo_surface_t* surface = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_A8, 4, 4, 4); + cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface); + cairo_surface_destroy(surface); + cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); + cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); + return pattern; + } } -void SvpSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert /*nFlags*/ ) +void SvpSalGraphics::invert(const basegfx::B2DPolygon &rPoly, SalInvert nFlags) { - // FIXME: handle SAL_INVERT_50 and SAL_INVERT_TRACKFRAME - basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( nX, nY, nX+nWidth, nY+nHeight ) ); - basegfx::B2DPolyPolygon aPolyPoly( aRect ); - basegfx::B2IBox aDestRange( nX, nY, nX + nWidth, nY + nHeight ); + cairo_t* cr = getCairoContext(false); + clipRegion(cr); + + basegfx::B2DRange extents(0, 0, 0, 0); + + AddPolygonToPath(cr, rPoly, true, !getAntiAliasB2DDraw(), false); + + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); - SvpSalGraphics::ClipUndoHandle aUndo( this ); - if( !isClippedSetup( aDestRange, aUndo ) ) - m_aDevice->fillPolyPolygon( aPolyPoly, basebmp::Color( 0xffffff ), basebmp::DrawMode_XOR, m_aClipMap ); - dbgOut( m_aDevice ); + if (cairo_version() >= CAIRO_VERSION_ENCODE(1, 10, 0)) + { + cairo_set_operator(cr, CAIRO_OPERATOR_DIFFERENCE); + } + else + { + SAL_WARN("vcl.gdi", "SvpSalGraphics::invert, archaic cairo"); + } + + if (nFlags & SalInvert::TrackFrame) + { + cairo_set_line_width(cr, 2.0); + const double dashLengths[2] = { 4.0, 4.0 }; + cairo_set_dash(cr, dashLengths, 2, 0); + + extents = getClippedStrokeDamage(cr); + + cairo_stroke(cr); + } + else + { + extents = getClippedFillDamage(cr); + + cairo_clip(cr); + + if (nFlags & SalInvert::N50) + { + cairo_pattern_t *pattern = create_stipple(); + cairo_mask(cr, pattern); + cairo_pattern_destroy(pattern); + } + else + { + cairo_paint(cr); + } + } + + releaseCairoContext(cr, false, extents); +} + +void SvpSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags ) +{ + basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect(basegfx::B2DRectangle(nX, nY, nX+nWidth, nY+nHeight)); + + invert(aRect, nFlags); } -void SvpSalGraphics::invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert /*nFlags*/ ) +void SvpSalGraphics::invert(sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags) { - // FIXME: handle SAL_INVERT_50 and SAL_INVERT_TRACKFRAME basegfx::B2DPolygon aPoly; - aPoly.append( basegfx::B2DPoint( pPtAry->mnX, pPtAry->mnY ), nPoints ); - for( sal_uLong i = 1; i < nPoints; i++ ) - aPoly.setB2DPoint( i, basegfx::B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) ); - aPoly.setClosed( true ); - ensureClip(); // FIXME for ... - m_aDevice->fillPolyPolygon( basegfx::B2DPolyPolygon(aPoly), basebmp::Color( 0xffffff ), basebmp::DrawMode_XOR, m_aClipMap ); - dbgOut( m_aDevice ); + aPoly.append(basegfx::B2DPoint(pPtAry->mnX, pPtAry->mnY), nPoints); + for (sal_uInt32 i = 1; i < nPoints; ++i) + aPoly.setB2DPoint(i, basegfx::B2DPoint(pPtAry[i].mnX, pPtAry[i].mnY)); + aPoly.setClosed(true); + + invert(aPoly, nFlags); } #endif @@ -1079,29 +1224,146 @@ bool SvpSalGraphics::drawEPS( long, long, long, long, void*, sal_uLong ) return false; } -#if ENABLE_CAIRO_CANVAS - -cairo_t* SvpSalGraphics::createCairoContext(const basebmp::BitmapDeviceSharedPtr &rBuffer) +namespace { - if (!isCairoCompatible(rBuffer)) - return NULL; + cairo_format_t getCairoFormat(const BitmapBuffer& rBuffer) + { + cairo_format_t nFormat; + assert(rBuffer.mnBitCount == 32 || rBuffer.mnBitCount == 1); + if (rBuffer.mnBitCount == 32) + nFormat = CAIRO_FORMAT_ARGB32; + else + nFormat = CAIRO_FORMAT_A1; + return nFormat; + } - basegfx::B2IVector size = rBuffer->getSize(); - sal_Int32 nStride = rBuffer->getScanlineStride(); + bool isCairoCompatible(const BitmapBuffer* pBuffer) + { + if (!pBuffer) + return false; + + if (pBuffer->mnBitCount != 32 && pBuffer->mnBitCount != 1) + return false; - basebmp::RawMemorySharedArray data = rBuffer->getBuffer(); + cairo_format_t nFormat = getCairoFormat(*pBuffer); + return (cairo_format_stride_for_width(nFormat, pBuffer->mnWidth) == pBuffer->mnScanlineSize); + } +} + +cairo_surface_t* SvpSalGraphics::createCairoSurface(const BitmapBuffer *pBuffer) +{ + if (!isCairoCompatible(pBuffer)) + return nullptr; + + cairo_format_t nFormat = getCairoFormat(*pBuffer); cairo_surface_t *target = - cairo_image_surface_create_for_data(data.get(), - CAIRO_FORMAT_RGB24, - size.getX(), size.getY(), - nStride); - cairo_t* cr = cairo_create(target); - cairo_surface_destroy(target); + cairo_image_surface_create_for_data(pBuffer->mpBits, + nFormat, + pBuffer->mnWidth, pBuffer->mnHeight, + pBuffer->mnScanlineSize); + return target; +} + +static cairo_t* createTmpCompatibleCairoContext(cairo_surface_t* pSurface) +{ + cairo_surface_t *target = cairo_image_surface_create( + cairo_image_surface_get_format(pSurface), + cairo_image_surface_get_width(pSurface), + cairo_image_surface_get_height(pSurface)); + return cairo_create(target); +} + +cairo_t* SvpSalGraphics::getCairoContext(bool bXorModeAllowed) const +{ + cairo_t* cr; + if (m_ePaintMode == XOR && bXorModeAllowed) + cr = createTmpCompatibleCairoContext(m_pSurface); + else + cr = cairo_create(m_pSurface); + cairo_set_line_width(cr, 1); + if (m_ePaintMode == INVERT) + cairo_set_operator(cr, CAIRO_OPERATOR_DIFFERENCE); + else + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); return cr; } -#endif +cairo_user_data_key_t* SvpSalGraphics::getDamageKey() +{ + static cairo_user_data_key_t aDamageKey; + return &aDamageKey; +} + +void SvpSalGraphics::releaseCairoContext(cairo_t* cr, bool bXorModeAllowed, const basegfx::B2DRange& rExtents) const +{ + if (rExtents.isEmpty()) + { + //nothing changed, return early + cairo_destroy(cr); + return; + } + sal_Int32 nExtentsLeft(rExtents.getMinX()), nExtentsTop(rExtents.getMinY()); + sal_Int32 nExtentsRight(rExtents.getMaxX()), nExtentsBottom(rExtents.getMaxY()); + sal_Int32 nWidth = cairo_image_surface_get_width(m_pSurface); + sal_Int32 nHeight = cairo_image_surface_get_height(m_pSurface); + nExtentsLeft = std::max<sal_Int32>(nExtentsLeft, 0); + nExtentsTop = std::max<sal_Int32>(nExtentsTop, 0); + nExtentsRight = std::min<sal_Int32>(nExtentsRight, nWidth); + nExtentsBottom = std::min<sal_Int32>(nExtentsBottom, nHeight); + + cairo_surface_t* surface = cairo_get_target(cr); + cairo_surface_flush(surface); + + //For the most part we avoid the use of XOR these days, but there + //are some edge cases where legacy stuff still supports it, so + //emulate it (slowly) here. + if (m_ePaintMode == XOR && bXorModeAllowed) + { + cairo_surface_t* true_surface = m_pSurface; + cairo_surface_flush(true_surface); + unsigned char *true_surface_data = cairo_image_surface_get_data(true_surface); + unsigned char *xor_surface_data = cairo_image_surface_get_data(surface); + + cairo_format_t nFormat = cairo_image_surface_get_format(m_pSurface); + assert(nFormat == CAIRO_FORMAT_ARGB32 && "need to implement CAIRO_FORMAT_A1 after all here"); + sal_Int32 nStride = cairo_format_stride_for_width(nFormat, nWidth); + for (sal_Int32 y = nExtentsTop; y < nExtentsBottom; ++y) + { + unsigned char *true_row = true_surface_data + (nStride*y); + unsigned char *xor_row = xor_surface_data + (nStride*y); + unsigned char *true_data = true_row + (nExtentsLeft * 4); + unsigned char *xor_data = xor_row + (nExtentsLeft * 4); + for (sal_Int32 x = nExtentsLeft; x < nExtentsRight; ++x) + { + sal_uInt8 b = unpremultiply(true_data[0], true_data[3]) ^ + unpremultiply(xor_data[0], xor_data[3]); + sal_uInt8 g = unpremultiply(true_data[1], true_data[3]) ^ + unpremultiply(xor_data[1], xor_data[3]); + sal_uInt8 r = unpremultiply(true_data[2], true_data[3]) ^ + unpremultiply(xor_data[2], xor_data[3]); + true_data[0] = premultiply(b, true_data[3]); + true_data[1] = premultiply(g, true_data[3]); + true_data[2] = premultiply(r, true_data[3]); + true_data+=4; + xor_data+=4; + } + } + cairo_surface_mark_dirty(true_surface); + cairo_surface_destroy(surface); + } + + cairo_destroy(cr); // unref + + DamageHandler* pDamage = static_cast<DamageHandler*>(cairo_surface_get_user_data(m_pSurface, getDamageKey())); + + if (pDamage) + { + pDamage->damaged(pDamage->handle, nExtentsLeft, nExtentsTop, nExtentsRight, nExtentsBottom); + } +} + +#if ENABLE_CAIRO_CANVAS bool SvpSalGraphics::SupportsCairo() const { return false; @@ -1127,6 +1389,8 @@ css::uno::Any SvpSalGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& /* return css::uno::Any(); } +#endif // ENABLE_CAIRO_CANVAS + #ifndef IOS SystemGraphicsData SvpSalGraphics::GetGraphicsData() const @@ -1136,24 +1400,13 @@ SystemGraphicsData SvpSalGraphics::GetGraphicsData() const bool SvpSalGraphics::supportsOperation(OutDevSupportType eType) const { -#if ENABLE_CAIRO_CANVAS - if (m_aDrawMode == basebmp::DrawMode_XOR) - return false; - if (!isCairoCompatible(m_aDevice)) - return false; switch (eType) { case OutDevSupport_TransparentRect: case OutDevSupport_B2DDraw: return true; - case OutDevSupport_B2DClip: //what's this one ? - return false; } return false; -#else - (void)eType; - return false; -#endif } #endif diff --git a/vcl/headless/svpglyphcache.cxx b/vcl/headless/svpglyphcache.cxx new file mode 100644 index 000000000000..f1af1e6a62c0 --- /dev/null +++ b/vcl/headless/svpglyphcache.cxx @@ -0,0 +1,62 @@ +/* -*- 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/types.h> + +#include <cassert> + +#include <rtl/instance.hxx> +#include <tools/debug.hxx> + +#include "unx/geninst.h" +#include "unx/glyphcache.hxx" +#include "headless/svpgdi.hxx" + +namespace +{ + struct GlyphCacheHolder + { + private: + GlyphCache* m_pSvpGlyphCache; + public: + GlyphCacheHolder() + { + m_pSvpGlyphCache = new GlyphCache; + } + GlyphCache& getGlyphCache() + { + return *m_pSvpGlyphCache; + } + ~GlyphCacheHolder() + { + delete m_pSvpGlyphCache; + } + }; + + struct theGlyphCacheHolder : + public rtl::Static<GlyphCacheHolder, theGlyphCacheHolder> + {}; +} + +GlyphCache& SvpSalGraphics::getPlatformGlyphCache() +{ + return theGlyphCacheHolder::get().getGlyphCache(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx index 0b2471858700..616865696ba1 100644 --- a/vcl/headless/svpinst.cxx +++ b/vcl/headless/svpinst.cxx @@ -18,6 +18,7 @@ */ #include <unistd.h> +#include <errno.h> #include <fcntl.h> #include <pthread.h> #include <sys/time.h> @@ -27,26 +28,23 @@ #include <vcl/apptypes.hxx> -#include "headless/svpinst.hxx" -#include "headless/svpframe.hxx" -#include "headless/svpdummies.hxx" -#include "headless/svpvd.hxx" +#include <headless/svpinst.hxx> +#include <headless/svpframe.hxx> +#include <headless/svpdummies.hxx> +#include <headless/svpvd.hxx> #ifdef IOS -#include "headless/svpgdi.hxx" -#include "quartz/salbmp.h" -#include "quartz/salgdi.h" -#include "quartz/salvd.h" +#include <quartz/salbmp.h> +#include <quartz/salgdi.h> +#include <quartz/salvd.h> #endif -#include "headless/svpbmp.hxx" +#include <headless/svpbmp.hxx> +#include <headless/svpgdi.hxx> -#include <salframe.hxx> -#include <svdata.hxx> -#include <generic/gendata.hxx> -#include <basebmp/scanlineformats.hxx> +#include "salframe.hxx" +#include "svdata.hxx" +#include "generic/gendata.hxx" // FIXME: remove when we re-work the svp mainloop -#include <unx/salunxtime.h> - -using namespace basebmp; +#include "unx/salunxtime.h" bool SvpSalInstance::isFrameAlive( const SalFrame* pFrame ) const { @@ -61,17 +59,21 @@ bool SvpSalInstance::isFrameAlive( const SalFrame* pFrame ) const return false; } -SvpSalInstance* SvpSalInstance::s_pDefaultInstance = NULL; +SvpSalInstance* SvpSalInstance::s_pDefaultInstance = nullptr; + +#ifndef ANDROID static void atfork_child() { - if (SvpSalInstance::s_pDefaultInstance != NULL) + if (SvpSalInstance::s_pDefaultInstance != nullptr) { - SvpSalInstance::s_pDefaultInstance->CloseWakeupPipe(); - SvpSalInstance::s_pDefaultInstance->CreateWakeupPipe(); + SvpSalInstance::s_pDefaultInstance->CloseWakeupPipe(false); + SvpSalInstance::s_pDefaultInstance->CreateWakeupPipe(false); } } +#endif + SvpSalInstance::SvpSalInstance( SalYieldMutex *pMutex ) : SalGenericInstance( pMutex ) { @@ -80,42 +82,51 @@ SvpSalInstance::SvpSalInstance( SalYieldMutex *pMutex ) : m_nTimeoutMS = 0; m_pTimeoutFDS[0] = m_pTimeoutFDS[1] = -1; - CreateWakeupPipe(); - m_aEventGuard = osl_createMutex(); - if( s_pDefaultInstance == NULL ) + CreateWakeupPipe(true); + if( s_pDefaultInstance == nullptr ) s_pDefaultInstance = this; - pthread_atfork(NULL, NULL, atfork_child); +#ifndef ANDROID + pthread_atfork(nullptr, nullptr, atfork_child); +#endif } SvpSalInstance::~SvpSalInstance() { if( s_pDefaultInstance == this ) - s_pDefaultInstance = NULL; + s_pDefaultInstance = nullptr; - CloseWakeupPipe(); - osl_destroyMutex( m_aEventGuard ); + CloseWakeupPipe(true); } -void SvpSalInstance::CloseWakeupPipe() +void SvpSalInstance::CloseWakeupPipe(bool log) { if (m_pTimeoutFDS[0] != -1) { - SAL_INFO("vcl.headless", "CloseWakeupPipe: Closing inherited wakeup pipe: [" << m_pTimeoutFDS[0] << "," << m_pTimeoutFDS[1] << "]"); + if (log) + { + SAL_INFO("vcl.headless", "CloseWakeupPipe: Closing inherited wakeup pipe: [" << m_pTimeoutFDS[0] << "," << m_pTimeoutFDS[1] << "]"); + } close (m_pTimeoutFDS[0]); close (m_pTimeoutFDS[1]); m_pTimeoutFDS[0] = m_pTimeoutFDS[1] = -1; } } -void SvpSalInstance::CreateWakeupPipe() +void SvpSalInstance::CreateWakeupPipe(bool log) { if (pipe (m_pTimeoutFDS) == -1) { - SAL_WARN("vcl.headless", "Could not create wakeup pipe: " << strerror(errno)); + if (log) + { + SAL_WARN("vcl.headless", "Could not create wakeup pipe: " << strerror(errno)); + } } else { - SAL_INFO("vcl.headless", "CreateWakeupPipe: Created wakeup pipe: [" << m_pTimeoutFDS[0] << "," << m_pTimeoutFDS[1] << "]"); + if (log) + { + SAL_INFO("vcl.headless", "CreateWakeupPipe: Created wakeup pipe: [" << m_pTimeoutFDS[0] << "," << m_pTimeoutFDS[1] << "]"); + } // initialize 'wakeup' pipe. int flags; @@ -146,48 +157,49 @@ void SvpSalInstance::CreateWakeupPipe() } } -void SvpSalInstance::PostEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent ) +void SvpSalInstance::PostEvent(const SalFrame* pFrame, ImplSVEvent* pData, SalEvent nEvent) { - if( osl_acquireMutex( m_aEventGuard ) ) { + osl::MutexGuard g(m_aEventGuard); m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) ); - osl_releaseMutex( m_aEventGuard ); } Wakeup(); } +#ifdef ANDROID bool SvpSalInstance::PostedEventsInQueue() { bool result = false; - if( osl_acquireMutex( m_aEventGuard ) ) { + osl::MutexGuard g(m_aEventGuard); result = m_aUserEvents.size() > 0; - osl_releaseMutex( m_aEventGuard ); } return result; } +#endif void SvpSalInstance::deregisterFrame( SalFrame* pFrame ) { m_aFrames.remove( pFrame ); - if( osl_acquireMutex( m_aEventGuard ) ) + osl::MutexGuard g(m_aEventGuard); + // cancel outstanding events for this frame + if( ! m_aUserEvents.empty() ) { - // cancel outstanding events for this frame - if( ! m_aUserEvents.empty() ) + std::list< SalUserEvent >::iterator it = m_aUserEvents.begin(); + do { - std::list< SalUserEvent >::iterator it = m_aUserEvents.begin(); - do + if( it->m_pFrame == pFrame ) { - if( it->m_pFrame == pFrame ) + if (it->m_nEvent == SalEvent::UserEvent) { - it = m_aUserEvents.erase( it ); + delete static_cast<ImplSVEvent *>(it->m_pData); } - else - ++it; - } while( it != m_aUserEvents.end() ); - } - osl_releaseMutex( m_aEventGuard ); + it = m_aUserEvents.erase( it ); + } + else + ++it; + } while( it != m_aUserEvents.end() ); } } @@ -202,7 +214,7 @@ bool SvpSalInstance::CheckTimeout( bool bExecuteTimers ) if( m_aTimeout.tv_sec ) // timer is started { timeval aTimeOfDay; - gettimeofday( &aTimeOfDay, 0 ); + gettimeofday( &aTimeOfDay, nullptr ); if( aTimeOfDay >= m_aTimeout ) { bRet = true; @@ -227,14 +239,14 @@ bool SvpSalInstance::CheckTimeout( bool bExecuteTimers ) return bRet; } -SalFrame* SvpSalInstance::CreateChildFrame( SystemParentData* pParent, sal_uLong nStyle ) +SalFrame* SvpSalInstance::CreateChildFrame( SystemParentData* pParent, SalFrameStyleFlags nStyle ) { - return new SvpSalFrame( this, NULL, nStyle, false, SVP_DEFAULT_BITMAP_FORMAT, pParent ); + return new SvpSalFrame( this, nullptr, nStyle, pParent ); } -SalFrame* SvpSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nStyle ) +SalFrame* SvpSalInstance::CreateFrame( SalFrame* pParent, SalFrameStyleFlags nStyle ) { - return new SvpSalFrame( this, pParent, nStyle, false, SVP_DEFAULT_BITMAP_FORMAT ); + return new SvpSalFrame( this, pParent, nStyle ); } void SvpSalInstance::DestroyFrame( SalFrame* pFrame ) @@ -256,10 +268,10 @@ void SvpSalInstance::DestroyObject( SalObject* pObject ) SalVirtualDevice* SvpSalInstance::CreateVirtualDevice( SalGraphics* /* pGraphics */, long &nDX, long &nDY, - sal_uInt16 nBitCount, + DeviceFormat eFormat, const SystemGraphicsData* /* pData */ ) { - SvpSalVirtualDevice* pNew = new SvpSalVirtualDevice( nBitCount ); + SvpSalVirtualDevice* pNew = new SvpSalVirtualDevice(eFormat); pNew->SetSize( nDX, nDY ); return pNew; } @@ -290,15 +302,17 @@ SalBitmap* SvpSalInstance::CreateSalBitmap() #endif } -void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) +SalYieldResult SvpSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong const nReleased) { + (void) nReleased; + assert(nReleased == 0); // not implemented // first, check for already queued events. // release yield mutex std::list< SalUserEvent > aEvents; sal_uLong nAcquireCount = ReleaseYieldMutex(); - if( osl_acquireMutex( m_aEventGuard ) ) { + osl::MutexGuard g(m_aEventGuard); if( ! m_aUserEvents.empty() ) { if( bHandleAllCurrentEvents ) @@ -312,7 +326,6 @@ void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) m_aUserEvents.pop_front(); } } - osl_releaseMutex( m_aEventGuard ); } // acquire yield mutex again AcquireYieldMutex( nAcquireCount ); @@ -325,11 +338,11 @@ void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) if ( isFrameAlive( it->m_pFrame ) ) { it->m_pFrame->CallCallback( it->m_nEvent, it->m_pData ); - if( it->m_nEvent == SALEVENT_RESIZE ) + if( it->m_nEvent == SalEvent::Resize ) { // this would be a good time to post a paint const SvpSalFrame* pSvpFrame = static_cast<const SvpSalFrame*>(it->m_pFrame); - pSvpFrame->PostPaint(false); + pSvpFrame->PostPaint(); } } } @@ -344,7 +357,7 @@ void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) { timeval Timeout; // determine remaining timeout. - gettimeofday (&Timeout, 0); + gettimeofday (&Timeout, nullptr); nTimeoutMS = (m_aTimeout.tv_sec - Timeout.tv_sec) * 1000 + m_aTimeout.tv_usec/1000 - Timeout.tv_usec/1000; if( nTimeoutMS < 0 ) @@ -355,6 +368,9 @@ void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents ) DoReleaseYield(nTimeoutMS); } + + return bEvent ? SalYieldResult::EVENT : + SalYieldResult::TIMEOUT; } void SvpSalInstance::DoReleaseYield( int nTimeoutMS ) @@ -391,7 +407,7 @@ bool SvpSalInstance::AnyInput( VclInputFlags nType ) SalSession* SvpSalInstance::CreateSalSession() { - return NULL; + return nullptr; } void* SvpSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) @@ -411,7 +427,7 @@ void SvpSalInstance::StopTimer() void SvpSalInstance::StartTimer( sal_uLong nMS ) { timeval aPrevTimeout (m_aTimeout); - gettimeofday (&m_aTimeout, 0); + gettimeofday (&m_aTimeout, nullptr); m_nTimeoutMS = nMS; m_aTimeout += m_nTimeoutMS; @@ -441,47 +457,4 @@ void SvpSalTimer::Start( sal_uLong nMS ) m_pInstance->StartTimer( nMS ); } -void SvpSalInstance::setBitCountFormatMapping( sal_uInt16 nBitCount, - Format aFormat ) -{ - m_aBitCountFormatMap[nBitCount] = aFormat; -} - -Format SvpSalInstance::getFormatForBitCount( sal_uInt16 nBitCount ) -{ - BitCountFormatMap::iterator aIt; - if ( (aIt = m_aBitCountFormatMap.find( nBitCount )) != m_aBitCountFormatMap.end() ) - { - return aIt->second; - } - - switch( nBitCount ) - { - case 1: - return FORMAT_ONE_BIT_MSB_PAL; - case 4: - return FORMAT_FOUR_BIT_MSB_PAL; - case 8: - return FORMAT_EIGHT_BIT_PAL; - case 16: -#ifdef OSL_BIGENDIAN - return FORMAT_SIXTEEN_BIT_MSB_TC_MASK; -#else - return FORMAT_SIXTEEN_BIT_LSB_TC_MASK; -#endif - case 24: - return FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX; - case 32: - return FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA; - case 0: -#ifdef ANDROID - return FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA; -#else - return FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX; -#endif - default: - return SVP_DEFAULT_BITMAP_FORMAT; - } - -} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/headless/svpprn.cxx b/vcl/headless/svpprn.cxx index cc7034930bd0..83276960e1c6 100644 --- a/vcl/headless/svpprn.cxx +++ b/vcl/headless/svpprn.cxx @@ -17,9 +17,9 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include "vcl/svapp.hxx" -#include "vcl/timer.hxx" -#include "vcl/printerinfomanager.hxx" +#include <vcl/svapp.hxx> +#include <vcl/timer.hxx> +#include <vcl/printerinfomanager.hxx> #include "jobset.h" #include "print.h" @@ -89,8 +89,8 @@ static void copyJobDataToJobSetup( ImplJobSetup* pJobSetup, JobData& rData ) } // copy input slot - const PPDKey* pKey = NULL; - const PPDValue* pValue = NULL; + const PPDKey* pKey = nullptr; + const PPDValue* pValue = nullptr; pJobSetup->mnPaperBin = 0xffff; if( rData.m_pParser ) @@ -109,8 +109,8 @@ static void copyJobDataToJobSetup( ImplJobSetup* pJobSetup, JobData& rData ) } // copy duplex - pKey = NULL; - pValue = NULL; + pKey = nullptr; + pValue = nullptr; pJobSetup->meDuplexMode = DUPLEX_UNKNOWN; if( rData.m_pParser ) @@ -139,8 +139,8 @@ static void copyJobDataToJobSetup( ImplJobSetup* pJobSetup, JobData& rData ) if( pJobSetup->mpDriverData ) rtl_freeMemory( pJobSetup->mpDriverData ); - int nBytes; - void* pBuffer = NULL; + sal_uInt32 nBytes; + void* pBuffer = nullptr; if( rData.getStreamBuffer( pBuffer, nBytes ) ) { pJobSetup->mnDriverDataLen = nBytes; @@ -149,7 +149,7 @@ static void copyJobDataToJobSetup( ImplJobSetup* pJobSetup, JobData& rData ) else { pJobSetup->mnDriverDataLen = 0; - pJobSetup->mpDriverData = NULL; + pJobSetup->mpDriverData = nullptr; } } @@ -220,7 +220,7 @@ void SvpSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* pList ) pInfo->maDriver = rInfo.m_aDriverName; pInfo->maLocation = rInfo.m_aLocation; pInfo->maComment = rInfo.m_aComment; - pInfo->mpSysData = NULL; + pInfo->mpSysData = nullptr; sal_Int32 nIndex = 0; while( nIndex != -1 ) @@ -257,7 +257,7 @@ void SvpSalInstance::PostPrintersChanged() const std::list< SalFrame* >& rList = SvpSalInstance::s_pDefaultInstance->getFrames(); for( std::list< SalFrame* >::const_iterator it = rList.begin(); it != rList.end(); ++it ) - SvpSalInstance::s_pDefaultInstance->PostEvent( *it, NULL, SALEVENT_PRINTERCHANGED ); + SvpSalInstance::s_pDefaultInstance->PostEvent( *it, nullptr, SalEvent::PrinterChanged ); } GenPspGraphics *SvpSalInstance::CreatePrintGraphics() diff --git a/vcl/headless/svptext.cxx b/vcl/headless/svptext.cxx index 1651a3a49c5d..568c2565170a 100644 --- a/vcl/headless/svptext.cxx +++ b/vcl/headless/svptext.cxx @@ -18,43 +18,46 @@ */ #include <sal/types.h> +#include <vcl/metric.hxx> #include <basegfx/range/b2ibox.hxx> #include "headless/svpgdi.hxx" +#include <config_cairo_canvas.h> +#include "outfont.hxx" -sal_uInt16 SvpSalGraphics::SetFont( FontSelectPattern* pIFSD, int nFallbackLevel ) +void SvpSalGraphics::SetFont( FontSelectPattern* pIFSD, int nFallbackLevel ) { - return m_xTextRenderImpl->SetFont(pIFSD, nFallbackLevel); + m_aTextRenderImpl.SetFont(pIFSD, nFallbackLevel); } -void SvpSalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int nFallbackLevel ) +void SvpSalGraphics::GetFontMetric( ImplFontMetricDataPtr& xFontMetric, int nFallbackLevel ) { - m_xTextRenderImpl->GetFontMetric(pMetric, nFallbackLevel); + m_aTextRenderImpl.GetFontMetric(xFontMetric, nFallbackLevel); } const FontCharMapPtr SvpSalGraphics::GetFontCharMap() const { - return m_xTextRenderImpl->GetFontCharMap(); + return m_aTextRenderImpl.GetFontCharMap(); } bool SvpSalGraphics::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const { - return m_xTextRenderImpl->GetFontCapabilities(rFontCapabilities); + return m_aTextRenderImpl.GetFontCapabilities(rFontCapabilities); } void SvpSalGraphics::GetDevFontList( PhysicalFontCollection* pFontCollection ) { - m_xTextRenderImpl->GetDevFontList(pFontCollection); + m_aTextRenderImpl.GetDevFontList(pFontCollection); } void SvpSalGraphics::ClearDevFontCache() { - m_xTextRenderImpl->ClearDevFontCache(); + m_aTextRenderImpl.ClearDevFontCache(); } bool SvpSalGraphics::AddTempDevFont( PhysicalFontCollection* pFontCollection, const OUString& rFileURL, const OUString& rFontName) { - return m_xTextRenderImpl->AddTempDevFont(pFontCollection, rFileURL, rFontName); + return m_aTextRenderImpl.AddTempDevFont(pFontCollection, rFileURL, rFontName); } bool SvpSalGraphics::CreateFontSubset( @@ -66,12 +69,12 @@ bool SvpSalGraphics::CreateFontSubset( int nGlyphCount, FontSubsetInfo& rInfo) { - return m_xTextRenderImpl->CreateFontSubset(rToFile, pFont, pGlyphIds, pEncoding, pWidths, nGlyphCount, rInfo); + return m_aTextRenderImpl.CreateFontSubset(rToFile, pFont, pGlyphIds, pEncoding, pWidths, nGlyphCount, rInfo); } const Ucs2SIntMap* SvpSalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded, std::set<sal_Unicode> const** ppPriority) { - return m_xTextRenderImpl->GetFontEncodingVector(pFont, pNonEncoded, ppPriority); + return m_aTextRenderImpl.GetFontEncodingVector(pFont, pNonEncoded, ppPriority); } const void* SvpSalGraphics::GetEmbedFontData( @@ -82,12 +85,12 @@ const void* SvpSalGraphics::GetEmbedFontData( FontSubsetInfo& rInfo, long* pDataLen) { - return m_xTextRenderImpl->GetEmbedFontData(pFont, pUnicodes, pWidths, nLen, rInfo, pDataLen); + return m_aTextRenderImpl.GetEmbedFontData(pFont, pUnicodes, pWidths, nLen, rInfo, pDataLen); } void SvpSalGraphics::FreeEmbedFontData( const void* pData, long nLen ) { - m_xTextRenderImpl->FreeEmbedFontData(pData, nLen); + m_aTextRenderImpl.FreeEmbedFontData(pData, nLen); } void SvpSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFont, @@ -95,51 +98,41 @@ void SvpSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFont, Int32Vector& rWidths, Ucs2UIntMap& rUnicodeEnc ) { - m_xTextRenderImpl->GetGlyphWidths(pFont, bVertical, rWidths, rUnicodeEnc); + m_aTextRenderImpl.GetGlyphWidths(pFont, bVertical, rWidths, rUnicodeEnc); } bool SvpSalGraphics::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect ) { - return m_xTextRenderImpl->GetGlyphBoundRect(aGlyphId, rRect); + return m_aTextRenderImpl.GetGlyphBoundRect(aGlyphId, rRect); } bool SvpSalGraphics::GetGlyphOutline( sal_GlyphId aGlyphId, basegfx::B2DPolyPolygon& rPolyPoly ) { - return m_xTextRenderImpl->GetGlyphOutline(aGlyphId, rPolyPoly); + return m_aTextRenderImpl.GetGlyphOutline(aGlyphId, rPolyPoly); } SalLayout* SvpSalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel ) { - return m_xTextRenderImpl->GetTextLayout(rArgs, nFallbackLevel); + return m_aTextRenderImpl.GetTextLayout(rArgs, nFallbackLevel); } void SvpSalGraphics::DrawServerFontLayout( const ServerFontLayout& rSalLayout ) { - m_xTextRenderImpl->DrawServerFontLayout(rSalLayout ); + m_aTextRenderImpl.DrawServerFontLayout(rSalLayout ); } void SvpSalGraphics::SetTextColor( SalColor nSalColor ) { - m_xTextRenderImpl->SetTextColor(nSalColor); + m_aTextRenderImpl.SetTextColor(nSalColor); } +#if ENABLE_CAIRO_CANVAS + SystemFontData SvpSalGraphics::GetSysFontData( int nFallbacklevel ) const { - return m_xTextRenderImpl->GetSysFontData(nFallbacklevel); + return m_aTextRenderImpl.GetSysFontData(nFallbacklevel); } -void SvpSalGraphics::BlendTextColor(const basebmp::Color &rTextColor, const basebmp::BitmapDeviceSharedPtr &rAlphaMask, - const basegfx::B2IPoint &rDstPoint) -{ - // blend text color into target using the glyph's mask - const basegfx::B2IBox aSrcRect(basegfx::B2ITuple(0,0), rAlphaMask->getSize()); - const basegfx::B2IBox aClipRect(rDstPoint, rAlphaMask->getSize()); - - SvpSalGraphics::ClipUndoHandle aUndo(this); - if (isClippedSetup(aClipRect, aUndo)) - return; - - m_aDevice->drawMaskedColor(rTextColor, rAlphaMask, aSrcRect, rDstPoint, m_aClipMap); -} +#endif // ENABLE_CAIRO_CANVAS /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/headless/svptextrender.cxx b/vcl/headless/svptextrender.cxx deleted file mode 100644 index 65dc37564c37..000000000000 --- a/vcl/headless/svptextrender.cxx +++ /dev/null @@ -1,496 +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/types.h> - -#include <cassert> - -#include <basebmp/scanlineformats.hxx> -#include <basegfx/polygon/b2dpolypolygon.hxx> -#include <basegfx/range/b2drange.hxx> -#include <basegfx/range/b2ibox.hxx> -#include <rtl/instance.hxx> -#include <tools/debug.hxx> -#include <vcl/sysdata.hxx> - -#include "generic/geninst.h" -#include "generic/genpspgraphics.h" -#include "generic/glyphcache.hxx" -#include "headless/svpbmp.hxx" -#include "headless/svpgdi.hxx" -#include "headless/svptextrender.hxx" -#include "impfont.hxx" -#include "outfont.hxx" -#include "PhysicalFontFace.hxx" - -class PhysicalFontCollection; - -using namespace basegfx; -using namespace basebmp; - -class SvpGlyphPeer : public GlyphCachePeer -{ -public: - SvpGlyphPeer() {} - - BitmapDeviceSharedPtr GetGlyphBmp( ServerFont&, sal_GlyphId, - basebmp::Format nBmpFormat, B2IPoint& rTargetPos ); - -protected: - virtual void RemovingFont( ServerFont& ) SAL_OVERRIDE; - virtual void RemovingGlyph( GlyphData& ) SAL_OVERRIDE; - - class SvpGcpHelper - { - public: - RawBitmap maRawBitmap; - BitmapDeviceSharedPtr maBitmapDev; - }; -}; - -class SvpGlyphCache : public GlyphCache -{ -public: - SvpGlyphCache( SvpGlyphPeer& rPeer ) : GlyphCache( rPeer) {} - SvpGlyphPeer& GetPeer() { return reinterpret_cast<SvpGlyphPeer&>( mrPeer ); } - static SvpGlyphCache& GetInstance(); -}; - -namespace -{ - struct GlyphCacheHolder - { - private: - SvpGlyphPeer* m_pSvpGlyphPeer; - SvpGlyphCache* m_pSvpGlyphCache; - public: - GlyphCacheHolder() - { - m_pSvpGlyphPeer = new SvpGlyphPeer(); - m_pSvpGlyphCache = new SvpGlyphCache( *m_pSvpGlyphPeer ); - } - SvpGlyphCache& getGlyphCache() - { - return *m_pSvpGlyphCache; - } - ~GlyphCacheHolder() - { - delete m_pSvpGlyphCache; - delete m_pSvpGlyphPeer; - } - }; - - struct theGlyphCacheHolder : - public rtl::Static<GlyphCacheHolder, theGlyphCacheHolder> - {}; -} - -SvpGlyphCache& SvpGlyphCache::GetInstance() -{ - return theGlyphCacheHolder::get().getGlyphCache(); -} - -BitmapDeviceSharedPtr SvpGlyphPeer::GetGlyphBmp( ServerFont& rServerFont, - sal_GlyphId aGlyphId, basebmp::Format nBmpFormat, B2IPoint& rTargetPos ) -{ - GlyphData& rGlyphData = rServerFont.GetGlyphData( aGlyphId ); - - if( rGlyphData.ExtDataRef().meInfo != nBmpFormat ) - { - SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>( - rGlyphData.ExtDataRef().mpData); - bool bNew = pGcpHelper == 0; - if( bNew ) - pGcpHelper = new SvpGcpHelper; - - // get glyph bitmap in matching format - bool bFound = false; - switch( nBmpFormat ) - { - case FORMAT_ONE_BIT_LSB_GREY: - bFound = rServerFont.GetGlyphBitmap1( aGlyphId, pGcpHelper->maRawBitmap ); - break; - case FORMAT_EIGHT_BIT_GREY: - bFound = rServerFont.GetGlyphBitmap8( aGlyphId, pGcpHelper->maRawBitmap ); - break; - default: - OSL_FAIL( "SVP GCP::GetGlyphBmp(): illegal scanline format"); - // fall back to black&white mask - nBmpFormat = FORMAT_ONE_BIT_LSB_GREY; - bFound = false; - break; - } - - // return .notdef glyph if needed - if( !bFound && (aGlyphId != 0) ) - { - if( bNew ) - delete pGcpHelper; - return GetGlyphBmp( rServerFont, 0, nBmpFormat, rTargetPos ); - } - - // construct alpha mask from raw bitmap - if (pGcpHelper->maRawBitmap.mnScanlineSize && pGcpHelper->maRawBitmap.mnHeight) - { - const B2IVector aSize( - pGcpHelper->maRawBitmap.mnScanlineSize, - pGcpHelper->maRawBitmap.mnHeight ); - static PaletteMemorySharedVector aDummyPAL; - pGcpHelper->maBitmapDev = createBitmapDevice( aSize, true, nBmpFormat, aSize.getX(), pGcpHelper->maRawBitmap.mpBits, aDummyPAL ); - } - - rGlyphData.ExtDataRef().meInfo = nBmpFormat; - rGlyphData.ExtDataRef().mpData = pGcpHelper; - } - - SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>( - rGlyphData.ExtDataRef().mpData); - assert(pGcpHelper != 0); - rTargetPos += B2IPoint( pGcpHelper->maRawBitmap.mnXOffset, pGcpHelper->maRawBitmap.mnYOffset ); - return pGcpHelper->maBitmapDev; -} - -void SvpGlyphPeer::RemovingFont( ServerFont& ) -{ - // nothing to do: no font resources held in SvpGlyphPeer -} - -void SvpGlyphPeer::RemovingGlyph( GlyphData& rGlyphData ) -{ - SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>( - rGlyphData.ExtDataRef().mpData); - rGlyphData.ExtDataRef().meInfo = basebmp::FORMAT_NONE; - rGlyphData.ExtDataRef().mpData = 0; - delete pGcpHelper; -} - -SvpTextRender::SvpTextRender(SvpSalGraphics& rParent) - : m_rParent(rParent) - , m_aTextColor(COL_BLACK) - , m_eTextFmt(basebmp::FORMAT_EIGHT_BIT_GREY) -{ - for( int i = 0; i < MAX_FALLBACK; ++i ) - m_pServerFont[i] = NULL; -} - -sal_uInt16 SvpTextRender::SetFont( FontSelectPattern* pIFSD, int nFallbackLevel ) -{ - // release all no longer needed font resources - for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i ) - { - if( m_pServerFont[i] != NULL ) - { - // old server side font is no longer referenced - SvpGlyphCache::GetInstance().UncacheFont( *m_pServerFont[i] ); - m_pServerFont[i] = NULL; - } - } - - // return early if there is no new font - if( !pIFSD ) - return 0; - - // handle the request for a non-native X11-font => use the GlyphCache - ServerFont* pServerFont = SvpGlyphCache::GetInstance().CacheFont( *pIFSD ); - if( !pServerFont ) - return SAL_SETFONT_BADFONT; - - // check selected font - if( !pServerFont->TestFont() ) - { - SvpGlyphCache::GetInstance().UncacheFont( *pServerFont ); - return SAL_SETFONT_BADFONT; - } - - // update SalGraphics font settings - m_pServerFont[ nFallbackLevel ] = pServerFont; - return SAL_SETFONT_USEDRAWTEXTARRAY; -} - -void SvpTextRender::GetFontMetric( ImplFontMetricData* pMetric, int nFallbackLevel ) -{ - if( nFallbackLevel >= MAX_FALLBACK ) - return; - - if( m_pServerFont[nFallbackLevel] != NULL ) - { - long rDummyFactor; - m_pServerFont[nFallbackLevel]->FetchFontMetric( *pMetric, rDummyFactor ); - } -} - -const FontCharMapPtr SvpTextRender::GetFontCharMap() const -{ - if( !m_pServerFont[0] ) - return NULL; - - const FontCharMapPtr pFCMap = m_pServerFont[0]->GetFontCharMap(); - return pFCMap; -} - -bool SvpTextRender::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const -{ - if (!m_pServerFont[0]) - return false; - - return m_pServerFont[0]->GetFontCapabilities(rFontCapabilities); -} - -void SvpTextRender::GetDevFontList( PhysicalFontCollection* pFontCollection ) -{ - GlyphCache& rGC = SvpGlyphCache::GetInstance(); - - psp::PrintFontManager& rMgr = psp::PrintFontManager::get(); - psp::FastPrintFontInfo aInfo; - ::std::list< psp::fontID > aList; - rMgr.getFontList( aList ); - ::std::list< psp::fontID >::iterator it; - for( it = aList.begin(); it != aList.end(); ++it ) - { - if( !rMgr.getFontFastInfo( *it, aInfo ) ) - continue; - - // normalize face number to the GlyphCache - int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID ); - - // inform GlyphCache about this font provided by the PsPrint subsystem - ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo ); - aDFA.mnQuality += 4096; - const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID ); - rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA ); - } - - // announce glyphcache fonts - rGC.AnnounceFonts( pFontCollection ); - - // register platform specific font substitutions if available - SalGenericInstance::RegisterFontSubstitutors( pFontCollection ); - - ImplGetSVData()->maGDIData.mbNativeFontConfig = true; -} - -void SvpTextRender::ClearDevFontCache() -{ - GlyphCache& rGC = SvpGlyphCache::GetInstance(); - rGC.ClearFontCache(); -} - -bool SvpTextRender::AddTempDevFont( PhysicalFontCollection* pFontCollection, - const OUString& rFileURL, - const OUString& rFontName ) -{ - return GenPspGraphics::AddTempDevFontHelper( pFontCollection, rFileURL, rFontName, SvpGlyphCache::GetInstance() ); -} - -bool SvpTextRender::CreateFontSubset( - const OUString& rToFile, - const PhysicalFontFace* pFont, - const sal_GlyphId* pGlyphIds, - const sal_uInt8* pEncoding, - sal_Int32* pWidths, - int nGlyphCount, - FontSubsetInfo& rInfo - ) -{ - // in this context the pFont->GetFontId() is a valid PSP - // font since they are the only ones left after the PDF - // export has filtered its list of subsettable fonts (for - // which this method was created). The correct way would - // be to have the GlyphCache search for the PhysicalFontFace pFont - psp::fontID aFont = pFont->GetFontId(); - - psp::PrintFontManager& rMgr = psp::PrintFontManager::get(); - bool bSuccess = rMgr.createFontSubset( rInfo, - aFont, - rToFile, - pGlyphIds, - pEncoding, - pWidths, - nGlyphCount ); - return bSuccess; -} - -const Ucs2SIntMap* SvpTextRender::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded, std::set<sal_Unicode> const** ppPriority) -{ - // in this context the pFont->GetFontId() is a valid PSP - // font since they are the only ones left after the PDF - // export has filtered its list of subsettable fonts (for - // which this method was created). The correct way would - // be to have the GlyphCache search for the PhysicalFontFace pFont - psp::fontID aFont = pFont->GetFontId(); - return GenPspGraphics::DoGetFontEncodingVector(aFont, pNonEncoded, ppPriority); -} - -const void* SvpTextRender::GetEmbedFontData( - const PhysicalFontFace* pFont, - const sal_Ucs* pUnicodes, - sal_Int32* pWidths, - size_t nLen, - FontSubsetInfo& rInfo, - long* pDataLen - ) -{ - // in this context the pFont->GetFontId() is a valid PSP - // font since they are the only ones left after the PDF - // export has filtered its list of subsettable fonts (for - // which this method was created). The correct way would - // be to have the GlyphCache search for the PhysicalFontFace pFont - psp::fontID aFont = pFont->GetFontId(); - return GenPspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, nLen, rInfo, pDataLen ); -} - -void SvpTextRender::FreeEmbedFontData( const void* pData, long nLen ) -{ - GenPspGraphics::DoFreeEmbedFontData( pData, nLen ); -} - -void SvpTextRender::GetGlyphWidths( const PhysicalFontFace* pFont, - bool bVertical, - Int32Vector& rWidths, - Ucs2UIntMap& rUnicodeEnc ) -{ - // in this context the pFont->GetFontId() is a valid PSP - // font since they are the only ones left after the PDF - // export has filtered its list of subsettable fonts (for - // which this method was created). The correct way would - // be to have the GlyphCache search for the PhysicalFontFace pFont - psp::fontID aFont = pFont->GetFontId(); - GenPspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc ); -} - -bool SvpTextRender::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect ) -{ - const int nLevel = aGlyphId >> GF_FONTSHIFT; - if( nLevel >= MAX_FALLBACK ) - return false; - - ServerFont* pSF = m_pServerFont[ nLevel ]; - if( !pSF ) - return false; - - aGlyphId &= GF_IDXMASK; - const GlyphMetric& rGM = pSF->GetGlyphMetric( aGlyphId ); - rRect = Rectangle( rGM.GetOffset(), rGM.GetSize() ); - return true; -} - -bool SvpTextRender::GetGlyphOutline( sal_GlyphId aGlyphId, B2DPolyPolygon& rPolyPoly ) -{ - const int nLevel = aGlyphId >> GF_FONTSHIFT; - if( nLevel >= MAX_FALLBACK ) - return false; - - const ServerFont* pSF = m_pServerFont[ nLevel ]; - if( !pSF ) - return false; - - aGlyphId &= GF_IDXMASK; - if( pSF->GetGlyphOutline( aGlyphId, rPolyPoly ) ) - return true; - - return false; -} - -SalLayout* SvpTextRender::GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ) -{ - GenericSalLayout* pLayout = NULL; - - if( m_pServerFont[ nFallbackLevel ] ) - pLayout = new ServerFontLayout( *m_pServerFont[ nFallbackLevel ] ); - - return pLayout; -} - -void SvpTextRender::DrawServerFontLayout( const ServerFontLayout& rSalLayout ) -{ - // iterate over all glyphs in the layout - Point aPos; - sal_GlyphId aGlyphId; - SvpGlyphPeer& rGlyphPeer = SvpGlyphCache::GetInstance().GetPeer(); - for( int nStart = 0; rSalLayout.GetNextGlyphs( 1, &aGlyphId, aPos, nStart ); ) - { - ServerFont& rFont = rSalLayout.GetServerFont(); - // get the glyph's alpha mask and adjust the drawing position - aGlyphId &= GF_IDXMASK; - B2IPoint aDstPoint( aPos.X(), aPos.Y() ); - BitmapDeviceSharedPtr aAlphaMask - = rGlyphPeer.GetGlyphBmp(rFont, aGlyphId, m_eTextFmt, aDstPoint); - if( !aAlphaMask ) // ignore empty glyphs - continue; - - // blend text color into target using the glyph's mask - m_rParent.BlendTextColor(m_aTextColor, aAlphaMask, aDstPoint); - } -} - -void SvpTextRender::SetTextColor( SalColor nSalColor ) -{ - m_aTextColor = basebmp::Color( nSalColor ); -} - -SystemFontData SvpTextRender::GetSysFontData( int nFallbackLevel ) const -{ - SystemFontData aSysFontData; - - if (nFallbackLevel >= MAX_FALLBACK) nFallbackLevel = MAX_FALLBACK - 1; - if (nFallbackLevel < 0 ) nFallbackLevel = 0; - - if (m_pServerFont[nFallbackLevel] != NULL) - { - ServerFont* rFont = m_pServerFont[nFallbackLevel]; - aSysFontData.nFontId = rFont->GetFtFace(); - aSysFontData.nFontFlags = rFont->GetLoadFlags(); - aSysFontData.bFakeBold = rFont->NeedsArtificialBold(); - aSysFontData.bFakeItalic = rFont->NeedsArtificialItalic(); - aSysFontData.bAntialias = rFont->GetAntialiasAdvice(); - aSysFontData.bVerticalCharacterType = rFont->GetFontSelData().mbVertical; - } - - return aSysFontData; -} - -void SvpTextRender::setDevice( basebmp::BitmapDeviceSharedPtr& rDevice ) -{ - // determine matching bitmap format for masks - basebmp::Format nDeviceFmt = rDevice ? rDevice->getScanlineFormat() : basebmp::FORMAT_EIGHT_BIT_GREY; - switch( nDeviceFmt ) - { - case basebmp::FORMAT_EIGHT_BIT_GREY: - case basebmp::FORMAT_SIXTEEN_BIT_LSB_TC_MASK: - case basebmp::FORMAT_SIXTEEN_BIT_MSB_TC_MASK: - case basebmp::FORMAT_TWENTYFOUR_BIT_TC_MASK: - case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX: - case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA: - case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_ARGB: - case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_ABGR: - case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA: - m_eTextFmt = basebmp::FORMAT_EIGHT_BIT_GREY; - break; - default: - m_eTextFmt = basebmp::FORMAT_ONE_BIT_LSB_GREY; - break; - } -} - -GlyphCache& SvpSalGraphics::getPlatformGlyphCache() -{ - return SvpGlyphCache::GetInstance(); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/headless/svpvd.cxx b/vcl/headless/svpvd.cxx index 1e4050a639cf..f356d7dfbb3e 100644 --- a/vcl/headless/svpvd.cxx +++ b/vcl/headless/svpvd.cxx @@ -19,29 +19,26 @@ #ifndef IOS -#include <vcl/svpforlokit.hxx> - #include "headless/svpbmp.hxx" #include "headless/svpinst.hxx" #include "headless/svpvd.hxx" #include "headless/svpgdi.hxx" #include <basegfx/vector/b2ivector.hxx> -#include <basebmp/scanlineformats.hxx> -#include "stdio.h" +#include <cairo.h> using namespace basegfx; -using namespace basebmp; SvpSalVirtualDevice::~SvpSalVirtualDevice() { + cairo_surface_destroy(m_pSurface); } SalGraphics* SvpSalVirtualDevice::AcquireGraphics() { SvpSalGraphics* pGraphics = new SvpSalGraphics(); - pGraphics->setDevice( m_aDevice ); + pGraphics->setSurface(m_pSurface); m_aGraphics.push_back( pGraphics ); return pGraphics; } @@ -54,54 +51,62 @@ void SvpSalVirtualDevice::ReleaseGraphics( SalGraphics* pGraphics ) bool SvpSalVirtualDevice::SetSize( long nNewDX, long nNewDY ) { - return SetSizeUsingBuffer( nNewDX, nNewDY, basebmp::RawMemorySharedArray(), false ); + return SetSizeUsingBuffer(nNewDX, nNewDY, nullptr); } bool SvpSalVirtualDevice::SetSizeUsingBuffer( long nNewDX, long nNewDY, - const basebmp::RawMemorySharedArray &pBuffer, - const bool bTopDown ) + sal_uInt8 *const pBuffer) { B2IVector aDevSize( nNewDX, nNewDY ); if( aDevSize.getX() == 0 ) aDevSize.setX( 1 ); if( aDevSize.getY() == 0 ) aDevSize.setY( 1 ); - if( ! m_aDevice.get() || m_aDevice->getSize() != aDevSize ) + + if (!m_pSurface || cairo_image_surface_get_width(m_pSurface) != aDevSize.getX() || + cairo_image_surface_get_height(m_pSurface) != aDevSize.getY() ) { - SvpSalInstance* pInst = SvpSalInstance::s_pDefaultInstance; - assert( pInst ); - basebmp::Format nFormat = pInst->getFormatForBitCount( m_nBitCount ); - sal_Int32 nStride = basebmp::getBitmapDeviceStrideForWidth(nFormat, aDevSize.getX()); + if (m_pSurface) + { + cairo_surface_destroy(m_pSurface); + } - if ( m_nBitCount == 1 ) + if (m_eFormat == DeviceFormat::BITMASK) { - std::vector< basebmp::Color > aDevPal(2); - aDevPal[0] = basebmp::Color( 0, 0, 0 ); - aDevPal[1] = basebmp::Color( 0xff, 0xff, 0xff ); - m_aDevice = createBitmapDevice( aDevSize, bTopDown, nFormat, nStride, - PaletteMemorySharedVector( new std::vector< basebmp::Color >(aDevPal) ) ); + m_pSurface = cairo_image_surface_create(CAIRO_FORMAT_A1, + aDevSize.getX(), + aDevSize.getY()); } else { - m_aDevice = pBuffer ? - createBitmapDevice( aDevSize, bTopDown, nFormat, nStride, pBuffer, PaletteMemorySharedVector() ) - : createBitmapDevice( aDevSize, bTopDown, nFormat, nStride ); + m_pSurface = pBuffer ? + cairo_image_surface_create_for_data(pBuffer, CAIRO_FORMAT_ARGB32, + aDevSize.getX(), + aDevSize.getY(), + cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, aDevSize.getX())) + : + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + aDevSize.getX(), + aDevSize.getY()); } // update device in existing graphics for( std::list< SvpSalGraphics* >::iterator it = m_aGraphics.begin(); it != m_aGraphics.end(); ++it ) - (*it)->setDevice( m_aDevice ); + (*it)->setSurface(m_pSurface); } return true; } -void InitSvpForLibreOfficeKit() +long SvpSalVirtualDevice::GetWidth() const +{ + return m_pSurface ? cairo_image_surface_get_width(m_pSurface) : 0; +} + +long SvpSalVirtualDevice::GetHeight() const { - ImplSVData* pSVData = ImplGetSVData(); - SvpSalInstance* pSalInstance = static_cast< SvpSalInstance* >(pSVData->mpDefInst); - pSalInstance->setBitCountFormatMapping( 32, ::basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA ); + return m_pSurface ? cairo_image_surface_get_height(m_pSurface) : 0; } #endif diff --git a/vcl/inc/cairotextrender.hxx b/vcl/inc/cairotextrender.hxx index 26ab3c98bc28..922329dd541d 100644 --- a/vcl/inc/cairotextrender.hxx +++ b/vcl/inc/cairotextrender.hxx @@ -20,20 +20,18 @@ #ifndef INCLUDED_VCL_INC_UNX_CAIROTEXTRENDER_HXX #define INCLUDED_VCL_INC_UNX_CAIROTEXTRENDER_HXX -#include "textrender.hxx" +#include <config_cairo_canvas.h> + #include <vcl/region.hxx> + +#include "textrender.hxx" + #include <deque> typedef struct FT_FaceRec_* FT_Face; -class PspSalPrinter; -class PspSalInfoPrinter; class ServerFont; class GlyphCache; -class ImplLayoutArgs; -class ServerFontLayout; -class PhysicalFontCollection; -class PhysicalFontFace; typedef struct _cairo cairo_t; class VCL_DLLPUBLIC CairoFontsCache @@ -71,7 +69,6 @@ class VCL_DLLPUBLIC CairoTextRender : public TextRenderImpl ServerFont* mpServerFont[ MAX_FALLBACK ]; SalColor mnTextColor; - CairoFontsCache m_aCairoFontsCache; bool bDisableGraphite_; @@ -79,7 +76,7 @@ protected: virtual GlyphCache& getPlatformGlyphCache() = 0; virtual cairo_t* getCairoContext() = 0; virtual void getSurfaceOffset(double& nDX, double& nDY) = 0; - virtual void drawSurface(cairo_t* cr) = 0; + virtual void releaseCairoContext(cairo_t* cr) = 0; bool setFont( const FontSelectPattern *pEntry, int nFallbackLevel ); @@ -89,14 +86,14 @@ public: CairoTextRender(); - virtual void SetTextColor( SalColor nSalColor ) SAL_OVERRIDE; - virtual sal_uInt16 SetFont( FontSelectPattern*, int nFallbackLevel ) SAL_OVERRIDE; - virtual void GetFontMetric( ImplFontMetricData*, int nFallbackLevel ) SAL_OVERRIDE; - virtual const FontCharMapPtr GetFontCharMap() const SAL_OVERRIDE; - virtual bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const SAL_OVERRIDE; - virtual void GetDevFontList( PhysicalFontCollection* ) SAL_OVERRIDE; - virtual void ClearDevFontCache() SAL_OVERRIDE; - virtual bool AddTempDevFont( PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) SAL_OVERRIDE; + virtual void SetTextColor( SalColor nSalColor ) override; + virtual sal_uInt16 SetFont( FontSelectPattern*, int nFallbackLevel ) override; + virtual void GetFontMetric( ImplFontMetricData *, int nFallbackLevel ) override; + virtual const FontCharMapPtr GetFontCharMap() const override; + virtual bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const override; + virtual void GetDevFontList( PhysicalFontCollection* ) override; + virtual void ClearDevFontCache() override; + virtual bool AddTempDevFont( PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) override; virtual bool CreateFontSubset( const OUString& rToFile, const PhysicalFontFace*, @@ -104,29 +101,31 @@ public: const sal_uInt8* pEncoding, sal_Int32* pWidths, int nGlyphs, - FontSubsetInfo& rInfo) SAL_OVERRIDE; + FontSubsetInfo& rInfo) override; - virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded, std::set<sal_Unicode> const**) SAL_OVERRIDE; + virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded, std::set<sal_Unicode> const**) override; virtual const void* GetEmbedFontData( const PhysicalFontFace*, const sal_Ucs* pUnicodes, sal_Int32* pWidths, size_t nLen, FontSubsetInfo& rInfo, - long* pDataLen ) SAL_OVERRIDE; + long* pDataLen ) override; - virtual void FreeEmbedFontData( const void* pData, long nDataLen ) SAL_OVERRIDE; + virtual void FreeEmbedFontData( const void* pData, long nDataLen ) override; virtual void GetGlyphWidths( const PhysicalFontFace*, bool bVertical, Int32Vector& rWidths, - Ucs2UIntMap& rUnicodeEnc ) SAL_OVERRIDE; - - virtual bool GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& ) SAL_OVERRIDE; - virtual bool GetGlyphOutline( sal_GlyphId nIndex, ::basegfx::B2DPolyPolygon& ) SAL_OVERRIDE; - virtual SalLayout* GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ) SAL_OVERRIDE; - virtual void DrawServerFontLayout( const ServerFontLayout& ) SAL_OVERRIDE; - virtual SystemFontData GetSysFontData( int nFallbackLevel ) const SAL_OVERRIDE; + Ucs2UIntMap& rUnicodeEnc ) override; + + virtual bool GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& ) override; + virtual bool GetGlyphOutline( sal_GlyphId nIndex, basegfx::B2DPolyPolygon& ) override; + virtual SalLayout* GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ) override; + virtual void DrawServerFontLayout( const ServerFontLayout& ) override; +#if ENABLE_CAIRO_CANVAS + virtual SystemFontData GetSysFontData( int nFallbackLevel ) const override; +#endif }; #endif diff --git a/vcl/inc/headless/svpbmp.hxx b/vcl/inc/headless/svpbmp.hxx index 168852e3caf2..85c4e13c5a5a 100644 --- a/vcl/inc/headless/svpbmp.hxx +++ b/vcl/inc/headless/svpbmp.hxx @@ -23,48 +23,42 @@ #include "sal/config.h" #include "tools/solar.h" -#include "basebmp/bitmapdevice.hxx" - #include <salbmp.hxx> -#define SVP_DEFAULT_BITMAP_FORMAT basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX - class VCL_DLLPUBLIC SvpSalBitmap : public SalBitmap { - basebmp::BitmapDeviceSharedPtr m_aBitmap; + BitmapBuffer* mpDIB; public: - SvpSalBitmap() {} + SvpSalBitmap() : mpDIB(nullptr) {} virtual ~SvpSalBitmap(); - const basebmp::BitmapDeviceSharedPtr& getBitmap() const { return m_aBitmap; } - void setBitmap( const basebmp::BitmapDeviceSharedPtr& rSrc ) { m_aBitmap = rSrc; } - // SalBitmap virtual bool Create( const Size& rSize, sal_uInt16 nBitCount, - const BitmapPalette& rPal ) SAL_OVERRIDE; - virtual bool Create( const SalBitmap& rSalBmp ) SAL_OVERRIDE; + const BitmapPalette& rPal ) override; + virtual bool Create( const SalBitmap& rSalBmp ) override; virtual bool Create( const SalBitmap& rSalBmp, - SalGraphics* pGraphics ) SAL_OVERRIDE; + SalGraphics* pGraphics ) override; virtual bool Create( const SalBitmap& rSalBmp, - sal_uInt16 nNewBitCount ) SAL_OVERRIDE; - virtual bool Create( const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XBitmapCanvas >& rBitmapCanvas, + sal_uInt16 nNewBitCount ) override; + virtual bool Create( const css::uno::Reference< css::rendering::XBitmapCanvas >& rBitmapCanvas, Size& rSize, - bool bMask = false ) SAL_OVERRIDE; - virtual void Destroy() SAL_OVERRIDE; - virtual Size GetSize() const SAL_OVERRIDE; - virtual sal_uInt16 GetBitCount() const SAL_OVERRIDE; - - virtual BitmapBuffer* AcquireBuffer( BitmapAccessMode nMode ) SAL_OVERRIDE; - virtual void ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode ) SAL_OVERRIDE; - virtual bool GetSystemData( BitmapSystemData& rData ) SAL_OVERRIDE; + bool bMask = false ) override; + bool Create(BitmapBuffer *pBuf); + const BitmapBuffer* GetBuffer() const + { + return mpDIB; + } + virtual void Destroy() override; + virtual Size GetSize() const override; + virtual sal_uInt16 GetBitCount() const override; - virtual bool Crop( const Rectangle& rRectPixel ) SAL_OVERRIDE; - virtual bool Erase( const Color& rFillColor ) SAL_OVERRIDE; - virtual bool Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag ) SAL_OVERRIDE; - virtual bool Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol ) SAL_OVERRIDE; + virtual BitmapBuffer* AcquireBuffer( BitmapAccessMode nMode ) override; + virtual void ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode ) override; + virtual bool GetSystemData( BitmapSystemData& rData ) override; - static sal_uInt32 getBitCountFromScanlineFormat( basebmp::Format nFormat ); + virtual bool Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag ) override; + virtual bool Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol ) override; }; #endif // INCLUDED_VCL_INC_HEADLESS_SVPBMP_HXX diff --git a/vcl/inc/headless/svpcairotextrender.hxx b/vcl/inc/headless/svpcairotextrender.hxx new file mode 100644 index 000000000000..847b9ec28a94 --- /dev/null +++ b/vcl/inc/headless/svpcairotextrender.hxx @@ -0,0 +1,34 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_VCL_UNX_GTK3_GDI_GTK3CAIROTEXTRENDER_HXX +#define INCLUDED_VCL_UNX_GTK3_GDI_GTK3CAIROTEXTRENDER_HXX + +#include "cairotextrender.hxx" + +class SvpSalGraphics; + +class SvpCairoTextRender : public CairoTextRender +{ +protected: + SvpSalGraphics& mrParent; + +public: + explicit SvpCairoTextRender(SvpSalGraphics& rParent); + + virtual GlyphCache& getPlatformGlyphCache() override; + virtual cairo_t* getCairoContext() override; + virtual void getSurfaceOffset(double& nDX, double& nDY) override; + virtual void clipRegion(cairo_t* cr) override; + virtual void releaseCairoContext(cairo_t* cr) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/headless/svpdummies.hxx b/vcl/inc/headless/svpdummies.hxx index bbe23e478624..bb12c5ad7656 100644 --- a/vcl/inc/headless/svpdummies.hxx +++ b/vcl/inc/headless/svpdummies.hxx @@ -37,16 +37,15 @@ public: virtual ~SvpSalObject(); // override all pure virtual methods - virtual void ResetClipRegion() SAL_OVERRIDE; - virtual sal_uInt16 GetClipRegionType() SAL_OVERRIDE; - virtual void BeginSetClipRegion( sal_uLong nRects ) SAL_OVERRIDE; - virtual void UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) SAL_OVERRIDE; - virtual void EndSetClipRegion() SAL_OVERRIDE; + virtual void ResetClipRegion() override; + virtual void BeginSetClipRegion( sal_uLong nRects ) override; + virtual void UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) override; + virtual void EndSetClipRegion() override; - virtual void SetPosSize( long nX, long nY, long nWidth, long nHeight ) SAL_OVERRIDE; - virtual void Show( bool bVisible ) SAL_OVERRIDE; + virtual void SetPosSize( long nX, long nY, long nWidth, long nHeight ) override; + virtual void Show( bool bVisible ) override; - virtual const SystemEnvData* GetSystemData() const SAL_OVERRIDE; + virtual const SystemEnvData* GetSystemData() const override; }; class VCL_DLLPUBLIC SvpImeStatus : public SalI18NImeStatus @@ -55,8 +54,8 @@ class VCL_DLLPUBLIC SvpImeStatus : public SalI18NImeStatus SvpImeStatus() {} virtual ~SvpImeStatus(); - virtual bool canToggle() SAL_OVERRIDE; - virtual void toggle() SAL_OVERRIDE; + virtual bool canToggle() override; + virtual void toggle() override; }; class VCL_DLLPUBLIC SvpSalSystem : public SalGenericSystem @@ -65,14 +64,13 @@ public: SvpSalSystem() {} virtual ~SvpSalSystem(); // get info about the display - virtual unsigned int GetDisplayScreenCount() SAL_OVERRIDE; - virtual Rectangle GetDisplayScreenPosSizePixel( unsigned int nScreen ) SAL_OVERRIDE; - virtual OUString GetDisplayScreenName( unsigned int nScreen ) SAL_OVERRIDE; + virtual unsigned int GetDisplayScreenCount() override; + virtual Rectangle GetDisplayScreenPosSizePixel( unsigned int nScreen ) override; virtual int ShowNativeDialog( const OUString& rTitle, const OUString& rMessage, const std::list< OUString >& rButtons, - int nDefButton ) SAL_OVERRIDE; + int nDefButton ) override; }; #endif // INCLUDED_VCL_INC_HEADLESS_SVPDUMMIES_HXX diff --git a/vcl/inc/headless/svpframe.hxx b/vcl/inc/headless/svpframe.hxx index b07c2163794f..bcf504ef2e98 100644 --- a/vcl/inc/headless/svpframe.hxx +++ b/vcl/inc/headless/svpframe.hxx @@ -22,7 +22,6 @@ #include <vcl/sysdata.hxx> #include <basegfx/range/b2ibox.hxx> -#include <basebmp/bitmapdevice.hxx> #include <salframe.hxx> @@ -41,14 +40,11 @@ class VCL_DLLPUBLIC SvpSalFrame : public SalFrame SvpSalInstance* m_pInstance; SvpSalFrame* m_pParent; // pointer to parent frame std::list< SvpSalFrame* > m_aChildren; // List of child frames - sal_uLong m_nStyle; + SalFrameStyleFlags m_nStyle; bool m_bVisible; - bool m_bTopDown; #ifndef IOS - basebmp::BitmapDeviceSharedPtr m_aFrame; - bool m_bDamageTracking; + cairo_surface_t* m_pSurface; #endif - basebmp::Format m_nScanlineFormat; long m_nMinWidth; long m_nMinHeight; long m_nMaxWidth; @@ -62,81 +58,65 @@ class VCL_DLLPUBLIC SvpSalFrame : public SalFrame public: SvpSalFrame( SvpSalInstance* pInstance, SalFrame* pParent, - sal_uLong nSalFrameStyle, - bool bTopDown, - basebmp::Format nScanlineFormat, - SystemParentData* pSystemParent = NULL ); + SalFrameStyleFlags nSalFrameStyle, + SystemParentData* pSystemParent = nullptr ); virtual ~SvpSalFrame(); void GetFocus(); void LoseFocus(); - void PostPaint(bool bImmediate) const; - void AllocateFrame(); - -#if defined ANDROID - const basebmp::BitmapDeviceSharedPtr& getDevice() const { return m_aFrame; } -#endif + void PostPaint() const; // SalFrame - virtual SalGraphics* AcquireGraphics() SAL_OVERRIDE; - virtual void ReleaseGraphics( SalGraphics* pGraphics ) SAL_OVERRIDE; - - virtual bool PostEvent( void* pData ) SAL_OVERRIDE; - - virtual void SetTitle( const OUString& rTitle ) SAL_OVERRIDE; - virtual void SetIcon( sal_uInt16 nIcon ) SAL_OVERRIDE; - virtual void SetMenu( SalMenu* pMenu ) SAL_OVERRIDE; - virtual void DrawMenuBar() SAL_OVERRIDE; - - virtual void SetExtendedFrameStyle( SalExtStyle nExtStyle ) SAL_OVERRIDE; - virtual void Show( bool bVisible, bool bNoActivate = false ) SAL_OVERRIDE; - virtual void SetMinClientSize( long nWidth, long nHeight ) SAL_OVERRIDE; - virtual void SetMaxClientSize( long nWidth, long nHeight ) SAL_OVERRIDE; - virtual void SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ) SAL_OVERRIDE; - virtual void GetClientSize( long& rWidth, long& rHeight ) SAL_OVERRIDE; - virtual void GetWorkArea( Rectangle& rRect ) SAL_OVERRIDE; - virtual SalFrame* GetParent() const SAL_OVERRIDE; - virtual void SetWindowState( const SalFrameState* pState ) SAL_OVERRIDE; - virtual bool GetWindowState( SalFrameState* pState ) SAL_OVERRIDE; - virtual void ShowFullScreen( bool bFullScreen, sal_Int32 nDisplay ) SAL_OVERRIDE; - virtual void StartPresentation( bool bStart ) SAL_OVERRIDE; - virtual void SetAlwaysOnTop( bool bOnTop ) SAL_OVERRIDE; - virtual void ToTop( sal_uInt16 nFlags ) SAL_OVERRIDE; - virtual void SetPointer( PointerStyle ePointerStyle ) SAL_OVERRIDE; - virtual void CaptureMouse( bool bMouse ) SAL_OVERRIDE; - virtual void SetPointerPos( long nX, long nY ) SAL_OVERRIDE; + virtual SalGraphics* AcquireGraphics() override; + virtual void ReleaseGraphics( SalGraphics* pGraphics ) override; + + virtual bool PostEvent(ImplSVEvent* pData) override; + + virtual void SetTitle( const OUString& rTitle ) override; + virtual void SetIcon( sal_uInt16 nIcon ) override; + virtual void SetMenu( SalMenu* pMenu ) override; + virtual void DrawMenuBar() override; + + virtual void SetExtendedFrameStyle( SalExtStyle nExtStyle ) override; + virtual void Show( bool bVisible, bool bNoActivate = false ) override; + virtual void SetMinClientSize( long nWidth, long nHeight ) override; + virtual void SetMaxClientSize( long nWidth, long nHeight ) override; + virtual void SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ) override; + virtual void GetClientSize( long& rWidth, long& rHeight ) override; + virtual void GetWorkArea( Rectangle& rRect ) override; + virtual SalFrame* GetParent() const override; + virtual void SetWindowState( const SalFrameState* pState ) override; + virtual bool GetWindowState( SalFrameState* pState ) override; + virtual void ShowFullScreen( bool bFullScreen, sal_Int32 nDisplay ) override; + virtual void StartPresentation( bool bStart ) override; + virtual void SetAlwaysOnTop( bool bOnTop ) override; + virtual void ToTop( SalFrameToTop nFlags ) override; + virtual void SetPointer( PointerStyle ePointerStyle ) override; + virtual void CaptureMouse( bool bMouse ) override; + virtual void SetPointerPos( long nX, long nY ) override; using SalFrame::Flush; - virtual void Flush() SAL_OVERRIDE; - virtual void Sync() SAL_OVERRIDE; - virtual void SetInputContext( SalInputContext* pContext ) SAL_OVERRIDE; - virtual void EndExtTextInput( sal_uInt16 nFlags ) SAL_OVERRIDE; - virtual OUString GetKeyName( sal_uInt16 nKeyCode ) SAL_OVERRIDE; - virtual bool MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, vcl::KeyCode& rKeyCode ) SAL_OVERRIDE; - virtual LanguageType GetInputLanguage() SAL_OVERRIDE; - virtual void UpdateSettings( AllSettings& rSettings ) SAL_OVERRIDE; - virtual void Beep() SAL_OVERRIDE; - virtual const SystemEnvData* GetSystemData() const SAL_OVERRIDE; - virtual SalPointerState GetPointerState() SAL_OVERRIDE; - virtual KeyIndicatorState GetIndicatorState() SAL_OVERRIDE; - virtual void SimulateKeyPress( sal_uInt16 nKeyCode ) SAL_OVERRIDE; - virtual void SetParent( SalFrame* pNewParent ) SAL_OVERRIDE; - virtual bool SetPluginParent( SystemParentData* pNewParent ) SAL_OVERRIDE; - virtual void ResetClipRegion() SAL_OVERRIDE; - virtual void BeginSetClipRegion( sal_uLong nRects ) SAL_OVERRIDE; - virtual void UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) SAL_OVERRIDE; - virtual void EndSetClipRegion() SAL_OVERRIDE; - -#ifndef IOS - // If enabled we can get damage notifications for regions immediately rendered to ... - void enableDamageTracker( bool bOn = true ); -#endif + virtual void Flush() override; + virtual void SetInputContext( SalInputContext* pContext ) override; + virtual void EndExtTextInput( EndExtTextInputFlags nFlags ) override; + virtual OUString GetKeyName( sal_uInt16 nKeyCode ) override; + virtual bool MapUnicodeToKeyCode( sal_Unicode aUnicode, LanguageType aLangType, vcl::KeyCode& rKeyCode ) override; + virtual LanguageType GetInputLanguage() override; + virtual void UpdateSettings( AllSettings& rSettings ) override; + virtual void Beep() override; + virtual const SystemEnvData* GetSystemData() const override; + virtual SalPointerState GetPointerState() override; + virtual KeyIndicatorState GetIndicatorState() override; + virtual void SimulateKeyPress( sal_uInt16 nKeyCode ) override; + virtual void SetParent( SalFrame* pNewParent ) override; + virtual bool SetPluginParent( SystemParentData* pNewParent ) override; + virtual void ResetClipRegion() override; + virtual void BeginSetClipRegion( sal_uLong nRects ) override; + virtual void UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) override; + virtual void EndSetClipRegion() override; /*TODO: functional implementation */ - virtual void SetScreenNumber( unsigned int nScreen ) SAL_OVERRIDE { (void)nScreen; } - virtual void SetApplicationID(const OUString &rApplicationID) SAL_OVERRIDE { (void) rApplicationID; } - bool IsVisible() { return m_bVisible; } - - static SvpSalFrame* GetFocusFrame() { return s_pFocusFrame; } + virtual void SetScreenNumber( unsigned int nScreen ) override { (void)nScreen; } + virtual void SetApplicationID(const OUString &rApplicationID) override { (void) rApplicationID; } }; diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx index f4503e8f9824..26ef9b47bc94 100644 --- a/vcl/inc/headless/svpgdi.hxx +++ b/vcl/inc/headless/svpgdi.hxx @@ -20,107 +20,115 @@ #ifndef INCLUDED_VCL_INC_HEADLESS_SVPGDI_HXX #define INCLUDED_VCL_INC_HEADLESS_SVPGDI_HXX -#include <basebmp/bitmapdevice.hxx> -#include <basebmp/color.hxx> #include <vcl/sysdata.hxx> #include <vcl/metric.hxx> #include <config_cairo_canvas.h> #include "salgdi.hxx" #include "sallayout.hxx" -#include "textrender.hxx" +#include "svpcairotextrender.hxx" +#include "outfont.hxx" #ifdef IOS #define SvpSalGraphics AquaSalGraphics #else +//Using formats that match cairo's formats. For android we patch cairo, +//which is internal in that case, to swap the rgb components so that +//cairo then matches the OpenGL GL_RGBA format so we can use it there +//where we don't have GL_BGRA support. +#ifdef ANDROID +# define SVP_CAIRO_FORMAT (BMP_FORMAT_32BIT_TC_RGBA | BMP_FORMAT_TOP_DOWN) +#else +# define SVP_CAIRO_FORMAT (BMP_FORMAT_32BIT_TC_BGRA | BMP_FORMAT_TOP_DOWN) +#endif + +struct BitmapBuffer; class GlyphCache; class ServerFont; typedef struct _cairo cairo_t; +typedef struct _cairo_surface cairo_surface_t; +typedef struct _cairo_user_data_key cairo_user_data_key_t; -class VCL_DLLPUBLIC SvpSalGraphics : public SalGraphics -{ - basebmp::BitmapDeviceSharedPtr m_aDevice; - basebmp::BitmapDeviceSharedPtr m_aOrigDevice; +enum PaintMode { OVERPAINT, XOR, INVERT }; - basebmp::BitmapDeviceSharedPtr m_aClipMap; +typedef void (*damageHandler)(void* handle, + sal_Int32 nExtentsLeft, sal_Int32 nExtentsTop, + sal_Int32 nExtentsRight, sal_Int32 nExtentsBottom); - bool m_bUseLineColor; - basebmp::Color m_aLineColor; - bool m_bUseFillColor; - basebmp::Color m_aFillColor; - - basebmp::DrawMode m_aDrawMode; +struct VCL_DLLPUBLIC DamageHandler +{ + void *handle; + damageHandler damaged; +}; -protected: - basegfx::B2IVector GetSize() { return m_aOrigDevice->getSize(); } +class VCL_DLLPUBLIC SvpSalGraphics : public SalGraphics +{ + cairo_surface_t* m_pSurface; + SalColor m_aLineColor; + SalColor m_aFillColor; + PaintMode m_ePaintMode; public: static GlyphCache& getPlatformGlyphCache(); - void setDevice(basebmp::BitmapDeviceSharedPtr& rDevice); - void BlendTextColor(const basebmp::Color &rTextColor, const basebmp::BitmapDeviceSharedPtr &rAlphaMask, - const basegfx::B2IPoint &rDstPoint); + void setSurface(cairo_surface_t* pSurface); + static cairo_user_data_key_t* getDamageKey(); private: - bool m_bClipSetup; - struct ClipUndoHandle { - SvpSalGraphics &m_rGfx; - basebmp::BitmapDeviceSharedPtr m_aDevice; - ClipUndoHandle( SvpSalGraphics *pGfx ) : m_rGfx( *pGfx ) {} - ~ClipUndoHandle(); - }; - bool isClippedSetup( const basegfx::B2IBox &aRange, ClipUndoHandle &rUndo ); - void ensureClip(); - + void invert(const basegfx::B2DPolygon &rPoly, SalInvert nFlags); + void copySource(const SalTwoRect& rTR, cairo_surface_t* source); + void setupPolyPolygon(cairo_t* cr, const basegfx::B2DPolyPolygon& rPolyPoly); + void applyColor(cairo_t *cr, SalColor rColor); + void drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly); protected: vcl::Region m_aClipRegion; - std::unique_ptr<TextRenderImpl> m_xTextRenderImpl; + SvpCairoTextRender m_aTextRenderImpl; protected: - virtual bool blendBitmap( const SalTwoRect&, const SalBitmap& rBitmap ) SAL_OVERRIDE; + virtual bool blendBitmap( const SalTwoRect&, const SalBitmap& rBitmap ) override; virtual bool blendAlphaBitmap( const SalTwoRect&, const SalBitmap& rSrcBitmap, const SalBitmap& rMaskBitmap, - const SalBitmap& rAlphaBitmap ) SAL_OVERRIDE; - virtual bool drawAlphaBitmap( const SalTwoRect&, const SalBitmap& rSourceBitmap, const SalBitmap& rAlphaBitmap ) SAL_OVERRIDE; + const SalBitmap& rAlphaBitmap ) override; + virtual bool drawAlphaBitmap( const SalTwoRect&, const SalBitmap& rSourceBitmap, const SalBitmap& rAlphaBitmap ) override; virtual bool drawTransformedBitmap( const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX, const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap, - const SalBitmap* pAlphaBitmap) SAL_OVERRIDE; - virtual bool drawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency ) SAL_OVERRIDE; + const SalBitmap* pAlphaBitmap) override; + virtual bool drawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency ) override; public: SvpSalGraphics(); virtual ~SvpSalGraphics(); - virtual SalGraphicsImpl* GetImpl() const SAL_OVERRIDE { return NULL; }; - virtual void GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) SAL_OVERRIDE; - virtual sal_uInt16 GetBitCount() const SAL_OVERRIDE; - virtual long GetGraphicsWidth() const SAL_OVERRIDE; + virtual SalGraphicsImpl* GetImpl() const override { return nullptr; }; + virtual void GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) override; + virtual sal_uInt16 GetBitCount() const override; + virtual long GetGraphicsWidth() const override; - virtual void ResetClipRegion() SAL_OVERRIDE; - virtual bool setClipRegion( const vcl::Region& ) SAL_OVERRIDE; + virtual void ResetClipRegion() override; + virtual bool setClipRegion( const vcl::Region& ) override; - virtual void SetLineColor() SAL_OVERRIDE; - virtual void SetLineColor( SalColor nSalColor ) SAL_OVERRIDE; - virtual void SetFillColor() SAL_OVERRIDE; - virtual void SetFillColor( SalColor nSalColor ) SAL_OVERRIDE; + virtual void SetLineColor() override; + virtual void SetLineColor( SalColor nSalColor ) override; + virtual void SetFillColor() override; + virtual void SetFillColor( SalColor nSalColor ) override; - virtual void SetXORMode( bool bSet, bool ) SAL_OVERRIDE; + virtual void SetXORMode( bool bSet, bool ) override; - virtual void SetROPLineColor( SalROPColor nROPColor ) SAL_OVERRIDE; - virtual void SetROPFillColor( SalROPColor nROPColor ) SAL_OVERRIDE; + virtual void SetROPLineColor( SalROPColor nROPColor ) override; + virtual void SetROPFillColor( SalROPColor nROPColor ) override; - virtual void SetTextColor( SalColor nSalColor ) SAL_OVERRIDE; - virtual sal_uInt16 SetFont( FontSelectPattern*, int nFallbackLevel ) SAL_OVERRIDE; - virtual void GetFontMetric( ImplFontMetricData*, int nFallbackLevel ) SAL_OVERRIDE; - virtual const FontCharMapPtr GetFontCharMap() const SAL_OVERRIDE; - virtual bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const SAL_OVERRIDE; - virtual void GetDevFontList( PhysicalFontCollection* ) SAL_OVERRIDE; - virtual void ClearDevFontCache() SAL_OVERRIDE; - virtual bool AddTempDevFont( PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) SAL_OVERRIDE; + virtual void SetTextColor( SalColor nSalColor ) override; + virtual sal_uInt16 SetFont( FontSelectPattern*, int nFallbackLevel ) override; + virtual void GetFontMetric( ImplFontMetricData *, int nFallbackLevel ) override; + virtual const FontCharMapPtr GetFontCharMap() const override; + virtual bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const override; + virtual void GetDevFontList( PhysicalFontCollection* ) override; + virtual void ClearDevFontCache() override; + virtual bool AddTempDevFont( PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) override; virtual bool CreateFontSubset( const OUString& rToFile, const PhysicalFontFace*, const sal_GlyphId* pGlyphIds, @@ -128,50 +136,51 @@ public: sal_Int32* pWidths, int nGlyphs, FontSubsetInfo& rInfo - ) SAL_OVERRIDE; - virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded, std::set<sal_Unicode> const** ) SAL_OVERRIDE; + ) override; + virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded, std::set<sal_Unicode> const** ) override; virtual const void* GetEmbedFontData( const PhysicalFontFace*, const sal_Ucs* pUnicodes, sal_Int32* pWidths, size_t nLen, FontSubsetInfo& rInfo, - long* pDataLen ) SAL_OVERRIDE; - virtual void FreeEmbedFontData( const void* pData, long nDataLen ) SAL_OVERRIDE; + long* pDataLen ) override; + virtual void FreeEmbedFontData( const void* pData, long nDataLen ) override; virtual void GetGlyphWidths( const PhysicalFontFace*, bool bVertical, Int32Vector& rWidths, - Ucs2UIntMap& rUnicodeEnc ) SAL_OVERRIDE; - virtual bool GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& ) SAL_OVERRIDE; - virtual bool GetGlyphOutline( sal_GlyphId nIndex, ::basegfx::B2DPolyPolygon& ) SAL_OVERRIDE; - virtual SalLayout* GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ) SAL_OVERRIDE; - virtual void DrawServerFontLayout( const ServerFontLayout& ) SAL_OVERRIDE; - virtual bool supportsOperation( OutDevSupportType ) const SAL_OVERRIDE; - virtual void drawPixel( long nX, long nY ) SAL_OVERRIDE; - virtual void drawPixel( long nX, long nY, SalColor nSalColor ) SAL_OVERRIDE; - virtual void drawLine( long nX1, long nY1, long nX2, long nY2 ) SAL_OVERRIDE; - virtual void drawRect( long nX, long nY, long nWidth, long nHeight ) SAL_OVERRIDE; - virtual bool drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double fTransparency ) SAL_OVERRIDE; - virtual bool drawPolyLine( const ::basegfx::B2DPolygon&, + Ucs2UIntMap& rUnicodeEnc ) override; + virtual bool GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& ) override; + virtual bool GetGlyphOutline( sal_GlyphId nIndex, basegfx::B2DPolyPolygon& ) override; + virtual SalLayout* GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ) override; + virtual void DrawServerFontLayout( const ServerFontLayout& ) override; + virtual bool supportsOperation( OutDevSupportType ) const override; + virtual void drawPixel( long nX, long nY ) override; + virtual void drawPixel( long nX, long nY, SalColor nSalColor ) override; + virtual void drawLine( long nX1, long nY1, long nX2, long nY2 ) override; + virtual void drawRect( long nX, long nY, long nWidth, long nHeight ) override; + virtual bool drawPolyPolygon( const basegfx::B2DPolyPolygon&, double fTransparency ) override; + virtual bool drawPolyLine( const basegfx::B2DPolygon&, double fTransparency, - const ::basegfx::B2DVector& rLineWidths, + const basegfx::B2DVector& rLineWidths, basegfx::B2DLineJoin, - com::sun::star::drawing::LineCap) SAL_OVERRIDE; - virtual void drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry ) SAL_OVERRIDE; - virtual void drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) SAL_OVERRIDE; + css::drawing::LineCap, + double fMiterMinimumAngle) override; + virtual void drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry ) override; + virtual void drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) override; virtual void drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, - PCONSTSALPOINT* pPtAry ) SAL_OVERRIDE; + PCONSTSALPOINT* pPtAry ) override; virtual bool drawPolyLineBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, - const sal_uInt8* pFlgAry ) SAL_OVERRIDE; + const sal_uInt8* pFlgAry ) override; virtual bool drawPolygonBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, - const sal_uInt8* pFlgAry ) SAL_OVERRIDE; + const sal_uInt8* pFlgAry ) override; virtual bool drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32* pPoints, const SalPoint* const* pPtAry, - const sal_uInt8* const* pFlgAry ) SAL_OVERRIDE; - virtual bool drawGradient( const tools::PolyPolygon&, const Gradient& ) SAL_OVERRIDE { return false; }; + const sal_uInt8* const* pFlgAry ) override; + virtual bool drawGradient( const tools::PolyPolygon&, const Gradient& ) override { return false; }; virtual void copyArea( long nDestX, long nDestY, @@ -179,42 +188,39 @@ public: long nSrcY, long nSrcWidth, long nSrcHeight, - sal_uInt16 nFlags ) SAL_OVERRIDE; + sal_uInt16 nFlags ) override; virtual void copyBits( const SalTwoRect& rPosAry, - SalGraphics* pSrcGraphics ) SAL_OVERRIDE; + SalGraphics* pSrcGraphics ) override; virtual void drawBitmap( const SalTwoRect& rPosAry, - const SalBitmap& rSalBitmap ) SAL_OVERRIDE; - virtual void drawBitmap( const SalTwoRect& rPosAry, - const SalBitmap& rSalBitmap, - SalColor nTransparentColor ) SAL_OVERRIDE; + const SalBitmap& rSalBitmap ) override; virtual void drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, - const SalBitmap& rTransparentBitmap ) SAL_OVERRIDE; + const SalBitmap& rTransparentBitmap ) override; virtual void drawMask( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap, - SalColor nMaskColor ) SAL_OVERRIDE; - virtual SalBitmap* getBitmap( long nX, long nY, long nWidth, long nHeight ) SAL_OVERRIDE; - virtual SalColor getPixel( long nX, long nY ) SAL_OVERRIDE; - virtual void invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags ) SAL_OVERRIDE; - virtual void invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags ) SAL_OVERRIDE; + SalColor nMaskColor ) override; + virtual SalBitmap* getBitmap( long nX, long nY, long nWidth, long nHeight ) override; + virtual SalColor getPixel( long nX, long nY ) override; + virtual void invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags ) override; + virtual void invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags ) override; - virtual bool drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize ) SAL_OVERRIDE; + virtual bool drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize ) override; - virtual SystemGraphicsData GetGraphicsData() const SAL_OVERRIDE; - virtual bool SupportsCairo() const SAL_OVERRIDE; - virtual cairo::SurfaceSharedPtr CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const SAL_OVERRIDE; - virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const SAL_OVERRIDE; - virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const SAL_OVERRIDE; - virtual css::uno::Any GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize) const SAL_OVERRIDE; - - virtual SystemFontData GetSysFontData( int nFallbacklevel ) const SAL_OVERRIDE; + virtual SystemGraphicsData GetGraphicsData() const override; #if ENABLE_CAIRO_CANVAS + virtual bool SupportsCairo() const override; + virtual cairo::SurfaceSharedPtr CreateSurface(const cairo::CairoSurfaceSharedPtr& rSurface) const override; + virtual cairo::SurfaceSharedPtr CreateSurface(const OutputDevice& rRefDevice, int x, int y, int width, int height) const override; + virtual cairo::SurfaceSharedPtr CreateBitmapSurface(const OutputDevice& rRefDevice, const BitmapSystemData& rData, const Size& rSize) const override; + virtual css::uno::Any GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rSurface, const basegfx::B2ISize& rSize) const override; + virtual SystemFontData GetSysFontData( int nFallbacklevel ) const override; +#endif // ENABLE_CAIRO_CANVAS - static cairo_t* createCairoContext(const basebmp::BitmapDeviceSharedPtr& rBuffer); + cairo_t* getCairoContext(bool bXorModeAllowed) const; + void releaseCairoContext(cairo_t* cr, bool bXorModeAllowed, const basegfx::B2DRange& rExtents) const; + static cairo_surface_t* createCairoSurface(const BitmapBuffer *pBuffer); void clipRegion(cairo_t* cr); - -#endif // ENABLE_CAIRO_CANVAS }; #endif diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx index e004a44a197c..343bc666da58 100644 --- a/vcl/inc/headless/svpinst.hxx +++ b/vcl/inc/headless/svpinst.hxx @@ -27,10 +27,8 @@ #include <saltimer.hxx> #include <generic/geninst.h> #include <generic/genprn.h> -#include <basebmp/scanlineformats.hxx> #include <list> -#include <map> #include <time.h> @@ -50,8 +48,8 @@ public: virtual ~SvpSalTimer(); // override all pure virtual methods - virtual void Start( sal_uLong nMS ) SAL_OVERRIDE; - virtual void Stop() SAL_OVERRIDE; + virtual void Start( sal_uLong nMS ) override; + virtual void Stop() override; }; class SvpSalFrame; @@ -69,17 +67,17 @@ class VCL_DLLPUBLIC SvpSalInstance : public SalGenericInstance struct SalUserEvent { const SalFrame* m_pFrame; - void* m_pData; - sal_uInt16 m_nEvent; + ImplSVEvent* m_pData; + SalEvent m_nEvent; - SalUserEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent = SALEVENT_USEREVENT ) + SalUserEvent( const SalFrame* pFrame, ImplSVEvent* pData, SalEvent nEvent = SalEvent::UserEvent ) : m_pFrame( pFrame ), m_pData( pData ), m_nEvent( nEvent ) {} }; - oslMutex m_aEventGuard; + osl::Mutex m_aEventGuard; std::list< SalUserEvent > m_aUserEvents; std::list< SalFrame* > m_aFrames; @@ -88,21 +86,20 @@ class VCL_DLLPUBLIC SvpSalInstance : public SalGenericInstance void DoReleaseYield( int nTimeoutMS ); - typedef std::map< sal_uInt16, ::basebmp::Format > BitCountFormatMap; - BitCountFormatMap m_aBitCountFormatMap; - public: static SvpSalInstance* s_pDefaultInstance; SvpSalInstance( SalYieldMutex *pMutex ); virtual ~SvpSalInstance(); - void CloseWakeupPipe(); - void CreateWakeupPipe(); + void CloseWakeupPipe(bool log); + void CreateWakeupPipe(bool log); - void PostEvent( const SalFrame* pFrame, void* pData, sal_uInt16 nEvent ); + void PostEvent(const SalFrame* pFrame, ImplSVEvent* pData, SalEvent nEvent); +#ifdef ANDROID bool PostedEventsInQueue(); +#endif void StartTimer( sal_uLong nMS ); void StopTimer(); @@ -116,13 +113,13 @@ public: bool CheckTimeout( bool bExecuteTimers = true ); // Frame - virtual SalFrame* CreateChildFrame( SystemParentData* pParent, sal_uLong nStyle ) SAL_OVERRIDE; - virtual SalFrame* CreateFrame( SalFrame* pParent, sal_uLong nStyle ) SAL_OVERRIDE; - virtual void DestroyFrame( SalFrame* pFrame ) SAL_OVERRIDE; + virtual SalFrame* CreateChildFrame( SystemParentData* pParent, SalFrameStyleFlags nStyle ) override; + virtual SalFrame* CreateFrame( SalFrame* pParent, SalFrameStyleFlags nStyle ) override; + virtual void DestroyFrame( SalFrame* pFrame ) override; // Object (System Child Window) - virtual SalObject* CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, bool bShow = true ) SAL_OVERRIDE; - virtual void DestroyObject( SalObject* pObject ) SAL_OVERRIDE; + virtual SalObject* CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, bool bShow = true ) override; + virtual void DestroyObject( SalObject* pObject ) override; // VirtualDevice // nDX and nDY in Pixel @@ -130,55 +127,47 @@ public: // pData allows for using a system dependent graphics or device context virtual SalVirtualDevice* CreateVirtualDevice( SalGraphics* pGraphics, long &nDX, long &nDY, - sal_uInt16 nBitCount, const SystemGraphicsData *pData = NULL ) SAL_OVERRIDE; + DeviceFormat eFormat, const SystemGraphicsData *pData = nullptr ) override; // Printer // pSetupData->mpDriverData can be 0 // pSetupData must be updatet with the current // JobSetup virtual SalInfoPrinter* CreateInfoPrinter( SalPrinterQueueInfo* pQueueInfo, - ImplJobSetup* pSetupData ) SAL_OVERRIDE; - virtual void DestroyInfoPrinter( SalInfoPrinter* pPrinter ) SAL_OVERRIDE; - virtual SalPrinter* CreatePrinter( SalInfoPrinter* pInfoPrinter ) SAL_OVERRIDE; - virtual void DestroyPrinter( SalPrinter* pPrinter ) SAL_OVERRIDE; + ImplJobSetup* pSetupData ) override; + virtual void DestroyInfoPrinter( SalInfoPrinter* pPrinter ) override; + virtual SalPrinter* CreatePrinter( SalInfoPrinter* pInfoPrinter ) override; + virtual void DestroyPrinter( SalPrinter* pPrinter ) override; - virtual void GetPrinterQueueInfo( ImplPrnQueueList* pList ) SAL_OVERRIDE; - virtual void GetPrinterQueueState( SalPrinterQueueInfo* pInfo ) SAL_OVERRIDE; - virtual void DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo ) SAL_OVERRIDE; - virtual OUString GetDefaultPrinter() SAL_OVERRIDE; - virtual void PostPrintersChanged() SAL_OVERRIDE; + virtual void GetPrinterQueueInfo( ImplPrnQueueList* pList ) override; + virtual void GetPrinterQueueState( SalPrinterQueueInfo* pInfo ) override; + virtual void DeletePrinterQueueInfo( SalPrinterQueueInfo* pInfo ) override; + virtual OUString GetDefaultPrinter() override; + virtual void PostPrintersChanged() override; // SalTimer - virtual SalTimer* CreateSalTimer() SAL_OVERRIDE; + virtual SalTimer* CreateSalTimer() override; // SalI18NImeStatus - virtual SalI18NImeStatus* CreateI18NImeStatus() SAL_OVERRIDE; + virtual SalI18NImeStatus* CreateI18NImeStatus() override; // SalSystem - virtual SalSystem* CreateSalSystem() SAL_OVERRIDE; + virtual SalSystem* CreateSalSystem() override; // SalBitmap - virtual SalBitmap* CreateSalBitmap() SAL_OVERRIDE; + virtual SalBitmap* CreateSalBitmap() override; // wait next event and dispatch // must returned by UserEvent (SalFrame::PostEvent) // and timer - virtual void Yield( bool bWait, bool bHandleAllCurrentEvents ) SAL_OVERRIDE; - virtual bool AnyInput( VclInputFlags nType ) SAL_OVERRIDE; + virtual SalYieldResult DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) override; + virtual bool AnyInput( VclInputFlags nType ) override; // may return NULL to disable session management - virtual SalSession* CreateSalSession() SAL_OVERRIDE; - - virtual void* GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) SAL_OVERRIDE; - - virtual void AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService) SAL_OVERRIDE; + virtual SalSession* CreateSalSession() override; - virtual GenPspGraphics *CreatePrintGraphics() SAL_OVERRIDE; + virtual void* GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes ) override; - // We want to be able to select colourspace, i.e. ARGB vs RGBA vs BGRA etc. - // -- as the rest of vcl always uses bit depths, it is perhaps simplest - // to let us simply change the mapping of bitcount to format (which was - // previously unchangeable). - void setBitCountFormatMapping( sal_uInt16 nBitCount, ::basebmp::Format aFormat ); + virtual void AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService) override; - ::basebmp::Format getFormatForBitCount( sal_uInt16 ); + virtual GenPspGraphics *CreatePrintGraphics() override; }; #endif // INCLUDED_VCL_INC_HEADLESS_SVPINST_HXX diff --git a/vcl/inc/headless/svpprn.hxx b/vcl/inc/headless/svpprn.hxx index b8a3b3fa52c4..30f7e11dd4dc 100644 --- a/vcl/inc/headless/svpprn.hxx +++ b/vcl/inc/headless/svpprn.hxx @@ -20,7 +20,7 @@ #ifndef INCLUDED_VCL_INC_HEADLESS_SVPPRN_HXX #define INCLUDED_VCL_INC_HEADLESS_SVPPRN_HXX -#include "vcl/jobdata.hxx" +#include <vcl/jobdata.hxx> #include "generic/printergfx.hxx" #include "generic/printerjob.hxx" #include "generic/genprn.h" @@ -30,7 +30,7 @@ class SvpSalInfoPrinter : public PspSalInfoPrinter { public: - virtual bool Setup( SalFrame* pFrame, ImplJobSetup* pSetupData ) SAL_OVERRIDE; + virtual bool Setup( SalFrame* pFrame, ImplJobSetup* pSetupData ) override; }; class SvpSalPrinter : public PspSalPrinter diff --git a/vcl/inc/headless/svptextrender.hxx b/vcl/inc/headless/svptextrender.hxx deleted file mode 100644 index 13d99f4eaf4f..000000000000 --- a/vcl/inc/headless/svptextrender.hxx +++ /dev/null @@ -1,82 +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 . - */ - -#ifndef INCLUDED_VCL_INC_HEADLESS_SVPTEXTRENDER_HXX -#define INCLUDED_VCL_INC_HEADLESS_SVPTEXTRENDER_HXX - -#include "textrender.hxx" -#include <vcl/region.hxx> -#include <deque> - -class VCL_DLLPUBLIC SvpTextRender : public TextRenderImpl -{ -private: - SvpSalGraphics& m_rParent; - // These fields are used only when we use FreeType to draw into a - // headless backend, i.e. not on iOS. - basebmp::Color m_aTextColor; - basebmp::Format m_eTextFmt; - ServerFont* m_pServerFont[ MAX_FALLBACK ]; -public: - SvpTextRender(SvpSalGraphics& rParent); - virtual void setDevice(basebmp::BitmapDeviceSharedPtr& rDevice) SAL_OVERRIDE; - - virtual void SetTextColor( SalColor nSalColor ) SAL_OVERRIDE; - virtual sal_uInt16 SetFont( FontSelectPattern*, int nFallbackLevel ) SAL_OVERRIDE; - virtual void GetFontMetric( ImplFontMetricData*, int nFallbackLevel ) SAL_OVERRIDE; - virtual const FontCharMapPtr GetFontCharMap() const SAL_OVERRIDE; - virtual bool GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const SAL_OVERRIDE; - virtual void GetDevFontList( PhysicalFontCollection* ) SAL_OVERRIDE; - virtual void ClearDevFontCache() SAL_OVERRIDE; - virtual bool AddTempDevFont( PhysicalFontCollection*, const OUString& rFileURL, const OUString& rFontName ) SAL_OVERRIDE; - virtual bool CreateFontSubset( - const OUString& rToFile, - const PhysicalFontFace*, - const sal_GlyphId* pGlyphIDs, - const sal_uInt8* pEncoding, - sal_Int32* pWidths, - int nGlyphs, - FontSubsetInfo& rInfo) SAL_OVERRIDE; - - virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded, std::set<sal_Unicode> const**) SAL_OVERRIDE; - virtual const void* GetEmbedFontData( - const PhysicalFontFace*, - const sal_Ucs* pUnicodes, - sal_Int32* pWidths, - size_t nLen, - FontSubsetInfo& rInfo, - long* pDataLen ) SAL_OVERRIDE; - - virtual void FreeEmbedFontData( const void* pData, long nDataLen ) SAL_OVERRIDE; - virtual void GetGlyphWidths( - const PhysicalFontFace*, - bool bVertical, - Int32Vector& rWidths, - Ucs2UIntMap& rUnicodeEnc ) SAL_OVERRIDE; - - virtual bool GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& ) SAL_OVERRIDE; - virtual bool GetGlyphOutline( sal_GlyphId nIndex, ::basegfx::B2DPolyPolygon& ) SAL_OVERRIDE; - virtual SalLayout* GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ) SAL_OVERRIDE; - virtual void DrawServerFontLayout( const ServerFontLayout& ) SAL_OVERRIDE; - virtual SystemFontData GetSysFontData( int nFallbackLevel ) const SAL_OVERRIDE; -}; - -#endif // INCLUDED_VCL_INC_HEADLESS_SVPTEXTRENDER_HXX - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/headless/svpvd.hxx b/vcl/inc/headless/svpvd.hxx index 255de3a67923..9256768a0fed 100644 --- a/vcl/inc/headless/svpvd.hxx +++ b/vcl/inc/headless/svpvd.hxx @@ -25,32 +25,34 @@ #include <list> class SvpSalGraphics; +typedef struct _cairo_surface cairo_surface_t; class VCL_DLLPUBLIC SvpSalVirtualDevice : public SalVirtualDevice { - sal_uInt16 m_nBitCount; - basebmp::BitmapDeviceSharedPtr m_aDevice; + DeviceFormat m_eFormat; + cairo_surface_t* m_pSurface; std::list< SvpSalGraphics* > m_aGraphics; public: - SvpSalVirtualDevice( sal_uInt16 nBitCount ) : m_nBitCount(nBitCount) {} + SvpSalVirtualDevice(DeviceFormat eFormat) + : m_eFormat(eFormat) + , m_pSurface(nullptr) + { + } virtual ~SvpSalVirtualDevice(); // SalVirtualDevice - virtual SalGraphics* AcquireGraphics() SAL_OVERRIDE; - virtual void ReleaseGraphics( SalGraphics* pGraphics ) SAL_OVERRIDE; + virtual SalGraphics* AcquireGraphics() override; + virtual void ReleaseGraphics( SalGraphics* pGraphics ) override; - virtual bool SetSize( long nNewDX, long nNewDY ) SAL_OVERRIDE; + virtual bool SetSize( long nNewDX, long nNewDY ) override; virtual bool SetSizeUsingBuffer( long nNewDX, long nNewDY, - const basebmp::RawMemorySharedArray &pBuffer, - const bool bTopDown - ) SAL_OVERRIDE; - - basebmp::BitmapDeviceSharedPtr getBitmapDevice() { return m_aDevice; } + sal_uInt8 * pBuffer + ) override; // SalGeometryProvider - virtual long GetWidth() const SAL_OVERRIDE { return m_aDevice.get() ? m_aDevice->getSize().getX() : 0; } - virtual long GetHeight() const SAL_OVERRIDE { return m_aDevice.get() ? m_aDevice->getSize().getY() : 0; } + virtual long GetWidth() const override; + virtual long GetHeight() const override; }; #endif // INCLUDED_VCL_INC_HEADLESS_SVPVD_HXX diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx index 0f9fafc93df4..055153d95270 100644 --- a/vcl/unx/generic/gdi/cairotextrender.cxx +++ b/vcl/unx/generic/gdi/cairotextrender.cxx @@ -23,6 +23,7 @@ #include <vcl/settings.hxx> #include <vcl/sysdata.hxx> #include <vcl/svapp.hxx> +#include <vcl/metric.hxx> #include "generic/printergfx.hxx" #include "generic/genpspgraphics.h" @@ -30,6 +31,7 @@ #include "generic/glyphcache.hxx" #include "PhysicalFontFace.hxx" #include "impfont.hxx" +#include "outfont.hxx" #include <config_graphite.h> #if ENABLE_GRAPHITE @@ -39,14 +41,12 @@ #include <cairo.h> #include <cairo-ft.h> -#include <cairo-xlib.h> -#include <cairo-xlib-xrender.h> CairoTextRender::CairoTextRender() : mnTextColor(MAKE_SALCOLOR(0x00, 0x00, 0x00)) //black { for( int i = 0; i < MAX_FALLBACK; ++i ) - mpServerFont[i] = NULL; + mpServerFont[i] = nullptr; #if ENABLE_GRAPHITE // check if graphite fonts have been disabled @@ -60,11 +60,11 @@ bool CairoTextRender::setFont( const FontSelectPattern *pEntry, int nFallbackLev // release all no longer needed font resources for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i ) { - if( mpServerFont[i] != NULL ) + if( mpServerFont[i] != nullptr ) { // old server side font is no longer referenced GlyphCache::GetInstance().UncacheFont( *mpServerFont[i] ); - mpServerFont[i] = NULL; + mpServerFont[i] = nullptr; } } @@ -78,7 +78,7 @@ bool CairoTextRender::setFont( const FontSelectPattern *pEntry, int nFallbackLev // handle the request for a non-native X11-font => use the GlyphCache ServerFont* pServerFont = GlyphCache::GetInstance().CacheFont( *pEntry ); - if( pServerFont != NULL ) + if( pServerFont != nullptr ) { // ignore fonts with e.g. corrupted font files if( !pServerFont->TestFont() ) @@ -91,7 +91,7 @@ bool CairoTextRender::setFont( const FontSelectPattern *pEntry, int nFallbackLev mpServerFont[ nFallbackLevel ] = pServerFont; // apply font specific-hint settings - ImplServerFontEntry* pSFE = static_cast<ImplServerFontEntry*>( pEntry->mpFontEntry ); + ServerFontInstance* pSFE = static_cast<ServerFontInstance*>( pEntry->mpFontInstance ); pSFE->HandleFontOptions(); return true; @@ -100,9 +100,9 @@ bool CairoTextRender::setFont( const FontSelectPattern *pEntry, int nFallbackLev return false; } -ImplFontOptions* GetFCFontOptions( const ImplFontAttributes& rFontAttributes, int nSize); +FontConfigFontOptions* GetFCFontOptions( const FontAttributes& rFontAttributes, int nSize); -void ImplServerFontEntry::HandleFontOptions() +void ServerFontInstance::HandleFontOptions() { if( !mpServerFont ) return; @@ -152,7 +152,7 @@ void* CairoFontsCache::FindCachedFont(const CairoFontsCache::CacheId &rId) for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI) if (aI->second == rId) return aI->first; - return NULL; + return nullptr; } namespace @@ -201,6 +201,13 @@ void CairoTextRender::DrawServerFontLayout( const ServerFontLayout& rLayout ) if (cairo_glyphs.empty()) return; + ServerFont& rFont = rLayout.GetServerFont(); + const FontSelectPattern& rFSD = rFont.GetFontSelData(); + int nHeight = rFSD.mnHeight; + int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight; + if (nWidth == 0 || nHeight == 0) + return; + /* * It might be ideal to cache surface and cairo context between calls and * only destroy it when the drawable changes, but to do that we need to at @@ -214,8 +221,9 @@ void CairoTextRender::DrawServerFontLayout( const ServerFontLayout& rLayout ) return; } - if (const void *pOptions = Application::GetSettings().GetStyleSettings().GetCairoFontOptions()) - cairo_set_font_options(cr, static_cast<const cairo_font_options_t*>(pOptions)); + ImplSVData* pSVData = ImplGetSVData(); + if (const cairo_font_options_t* pFontOptions = pSVData->mpDefInst->GetCairoFontOptions()) + cairo_set_font_options(cr, pFontOptions); double nDX, nDY; getSurfaceOffset(nDX, nDY); @@ -228,8 +236,6 @@ void CairoTextRender::DrawServerFontLayout( const ServerFontLayout& rLayout ) SALCOLOR_GREEN(mnTextColor)/255.0, SALCOLOR_BLUE(mnTextColor)/255.0); - ServerFont& rFont = rLayout.GetServerFont(); - FT_Face aFace = rFont.GetFtFace(); CairoFontsCache::CacheId aId; aId.maFace = aFace; @@ -237,9 +243,6 @@ void CairoTextRender::DrawServerFontLayout( const ServerFontLayout& rLayout ) aId.mbEmbolden = rFont.NeedsArtificialBold(); cairo_matrix_t m; - const FontSelectPattern& rFSD = rFont.GetFontSelData(); - int nHeight = rFSD.mnHeight; - int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight; std::vector<int>::const_iterator aEnd = glyph_extrarotation.end(); std::vector<int>::const_iterator aStart = glyph_extrarotation.begin(); @@ -257,8 +260,8 @@ void CairoTextRender::DrawServerFontLayout( const ServerFontLayout& rLayout ) cairo_font_face_t* font_face = static_cast<cairo_font_face_t*>(CairoFontsCache::FindCachedFont(aId)); if (!font_face) { - const ImplFontOptions *pOptions = rFont.GetFontOptions().get(); - void *pPattern = pOptions ? pOptions->GetPattern(aFace, aId.mbEmbolden, aId.mbVerticalMetrics) : NULL; + const FontConfigFontOptions *pOptions = rFont.GetFontOptions().get(); + void *pPattern = pOptions ? pOptions->GetPattern(aFace, aId.mbEmbolden) : nullptr; if (pPattern) font_face = cairo_ft_font_face_create_for_pattern(static_cast<FcPattern*>(pPattern)); if (!font_face) @@ -340,18 +343,16 @@ void CairoTextRender::DrawServerFontLayout( const ServerFontLayout& rLayout ) aI = aNext; } - cairo_surface_flush(cairo_get_target(cr)); - drawSurface(cr); - cairo_destroy(cr); + releaseCairoContext(cr); } const FontCharMapPtr CairoTextRender::GetFontCharMap() const { if( !mpServerFont[0] ) - return NULL; + return nullptr; - const FontCharMapPtr pFCMap = mpServerFont[0]->GetFontCharMap(); - return pFCMap; + const FontCharMapPtr xFCMap = mpServerFont[0]->GetFontCharMap(); + return xFCMap; } bool CairoTextRender::GetFontCapabilities(vcl::FontCapabilities &rGetImplFontCapabilities) const @@ -363,14 +364,9 @@ bool CairoTextRender::GetFontCapabilities(vcl::FontCapabilities &rGetImplFontCap // SalGraphics -sal_uInt16 CairoTextRender::SetFont( FontSelectPattern *pEntry, int nFallbackLevel ) +void CairoTextRender::SetFont( FontSelectPattern *pEntry, int nFallbackLevel ) { - sal_uInt16 nRetVal = 0; - if (!setFont(pEntry, nFallbackLevel)) - nRetVal |= SAL_SETFONT_BADFONT; - if (mpServerFont[nFallbackLevel]) - nRetVal |= SAL_SETFONT_USEDRAWTEXTARRAY; - return nRetVal; + setFont(pEntry, nFallbackLevel); } void @@ -414,8 +410,8 @@ void CairoTextRender::GetDevFontList( PhysicalFontCollection* pFontCollection ) int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID ); // inform GlyphCache about this font provided by the PsPrint subsystem - ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo ); - aDFA.mnQuality += 4096; + FontAttributes aDFA = GenPspGraphics::Info2FontAttributes( aInfo ); + aDFA.IncreaseQualityBy( 4096 ); const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID ); rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA ); } @@ -431,20 +427,19 @@ void CairoTextRender::GetDevFontList( PhysicalFontCollection* pFontCollection ) void cairosubcallback(void* pPattern) { - const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); - const void* pFontOptions = rStyleSettings.GetCairoFontOptions(); + ImplSVData* pSVData = ImplGetSVData(); + const cairo_font_options_t* pFontOptions = pSVData->mpDefInst->GetCairoFontOptions(); if( !pFontOptions ) return; - cairo_ft_font_options_substitute(static_cast<const cairo_font_options_t*>(pFontOptions), - static_cast<FcPattern*>(pPattern)); + cairo_ft_font_options_substitute(pFontOptions, static_cast<FcPattern*>(pPattern)); } -ImplFontOptions* GetFCFontOptions( const ImplFontAttributes& rFontAttributes, int nSize) +FontConfigFontOptions* GetFCFontOptions( const FontAttributes& rFontAttributes, int nSize) { psp::FastPrintFontInfo aInfo; aInfo.m_aFamilyName = rFontAttributes.GetFamilyName(); - aInfo.m_eItalic = rFontAttributes.GetSlant(); + aInfo.m_eItalic = rFontAttributes.GetItalic(); aInfo.m_eWeight = rFontAttributes.GetWeight(); aInfo.m_eWidth = rFontAttributes.GetWidthType(); @@ -452,15 +447,15 @@ ImplFontOptions* GetFCFontOptions( const ImplFontAttributes& rFontAttributes, in } void -CairoTextRender::GetFontMetric( ImplFontMetricData *pMetric, int nFallbackLevel ) +CairoTextRender::GetFontMetric( ImplFontMetricDataPtr& rxFontMetric, int nFallbackLevel ) { if( nFallbackLevel >= MAX_FALLBACK ) return; - if( mpServerFont[nFallbackLevel] != NULL ) + if( mpServerFont[nFallbackLevel] != nullptr ) { long rDummyFactor; - mpServerFont[nFallbackLevel]->FetchFontMetric( *pMetric, rDummyFactor ); + mpServerFont[nFallbackLevel]->GetFontMetric( rxFontMetric, rDummyFactor ); } } @@ -495,7 +490,7 @@ bool CairoTextRender::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect } bool CairoTextRender::GetGlyphOutline( sal_GlyphId aGlyphId, - ::basegfx::B2DPolyPolygon& rPolyPoly ) + basegfx::B2DPolyPolygon& rPolyPoly ) { const int nLevel = aGlyphId >> GF_FONTSHIFT; if( nLevel >= MAX_FALLBACK ) @@ -514,7 +509,7 @@ bool CairoTextRender::GetGlyphOutline( sal_GlyphId aGlyphId, SalLayout* CairoTextRender::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel ) { - SalLayout* pLayout = NULL; + SalLayout* pLayout = nullptr; if( mpServerFont[ nFallbackLevel ] && !(rArgs.mnFlags & SalLayoutFlags::DisableGlyphProcessing) ) @@ -534,6 +529,7 @@ SalLayout* CairoTextRender::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackL return pLayout; } +#if ENABLE_CAIRO_CANVAS SystemFontData CairoTextRender::GetSysFontData( int nFallbackLevel ) const { SystemFontData aSysFontData; @@ -541,7 +537,7 @@ SystemFontData CairoTextRender::GetSysFontData( int nFallbackLevel ) const if (nFallbackLevel >= MAX_FALLBACK) nFallbackLevel = MAX_FALLBACK - 1; if (nFallbackLevel < 0 ) nFallbackLevel = 0; - if (mpServerFont[nFallbackLevel] != NULL) + if (mpServerFont[nFallbackLevel] != nullptr) { ServerFont* rFont = mpServerFont[nFallbackLevel]; aSysFontData.nFontId = rFont->GetFtFace(); @@ -554,6 +550,7 @@ SystemFontData CairoTextRender::GetSysFontData( int nFallbackLevel ) const return aSysFontData; } +#endif bool CairoTextRender::CreateFontSubset( const OUString& rToFile, |