no more X11SalBitmap

Change-Id: I2c721c6058ab17717350742dd4390db0ad74b1f7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145293
Tested-by: Caolán McNamara <caolanm@redhat.com>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
This commit is contained in:
Caolán McNamara 2023-01-10 20:55:31 +00:00
parent d4760b5d4b
commit 4160be791d
5 changed files with 0 additions and 1234 deletions

View file

@ -101,7 +101,6 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gen,\
vcl/unx/generic/gdi/x11cairotextrender \
vcl/unx/generic/gdi/X11CairoSalGraphicsImpl \
vcl/unx/generic/gdi/gdiimpl \
vcl/unx/generic/gdi/salbmp \
vcl/unx/generic/gdi/salgdi2 \
vcl/unx/generic/gdi/font \
vcl/unx/generic/gdi/salgdi \

View file

@ -1,231 +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_UNX_SALBMP_H
#define INCLUDED_VCL_INC_UNX_SALBMP_H
#include <X11/Xlib.h>
#include <vcl/salgtype.hxx>
#include <unx/saldisp.hxx>
#include <salbmp.hxx>
#include <vclpluginapi.h>
struct BitmapBuffer;
class BitmapPalette;
class SalGraphics;
class ImplSalDDB;
class ImplSalBitmapCache;
class X11SalBitmap final : public SalBitmap
{
private:
static std::unique_ptr<BitmapBuffer>
ImplCreateDIB(
const Size& rSize,
vcl::PixelFormat ePixelFormat,
const BitmapPalette& rPal
);
static std::unique_ptr<BitmapBuffer>
ImplCreateDIB(
Drawable aDrawable,
SalX11Screen nXScreen,
tools::Long nDrawableDepth,
tools::Long nX,
tools::Long nY,
tools::Long nWidth,
tools::Long nHeight,
bool bGrey
);
public:
static ImplSalBitmapCache* mpCache;
static unsigned int mnCacheInstCount;
static void ImplCreateCache();
static void ImplDestroyCache();
void ImplRemovedFromCache();
private:
std::unique_ptr<BitmapBuffer> mpDIB;
mutable std::unique_ptr<ImplSalDDB> mpDDB;
bool mbGrey;
public:
bool ImplCreateFromDrawable(
Drawable aDrawable,
SalX11Screen nXScreen,
tools::Long nDrawableDepth,
tools::Long nX,
tools::Long nY,
tools::Long nWidth,
tools::Long nHeight
);
XImage* ImplCreateXImage(
SalDisplay const * pSalDisp,
SalX11Screen nXScreen,
tools::Long nDepth,
const SalTwoRect& rTwoRect
) const;
ImplSalDDB* ImplGetDDB(
Drawable,
SalX11Screen nXScreen,
tools::Long nDrawableDepth,
const SalTwoRect&
) const;
void ImplDraw(
Drawable aDrawable,
SalX11Screen nXScreen,
tools::Long nDrawableDepth,
const SalTwoRect& rTwoRect,
const GC& rGC
) const;
public:
X11SalBitmap();
virtual ~X11SalBitmap() override;
// override pure virtual methods
virtual bool Create(
const Size& rSize,
vcl::PixelFormat ePixelFormat,
const BitmapPalette& rPal
) override;
virtual bool Create( const SalBitmap& rSalBmp ) override;
virtual bool Create(
const SalBitmap& rSalBmp,
SalGraphics* pGraphics
) override;
virtual bool Create(
const SalBitmap& rSalBmp,
vcl::PixelFormat ePixelFormat
) override;
virtual bool Create(
const css::uno::Reference< css::rendering::XBitmapCanvas >& rBitmapCanvas,
Size& rSize,
bool bMask = false
) override;
virtual void Destroy() override;
virtual Size GetSize() const override;
virtual sal_uInt16 GetBitCount() const override;
virtual BitmapBuffer* AcquireBuffer( BitmapAccessMode nMode ) override;
virtual void ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode ) override;
virtual bool GetSystemData( BitmapSystemData& rData ) override;
virtual bool ScalingSupported() const override;
virtual bool Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag ) override;
virtual bool Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uInt8 nTol ) override;
};
class ImplSalDDB
{
private:
Pixmap maPixmap;
SalTwoRect maTwoRect;
tools::Long mnDepth;
SalX11Screen mnXScreen;
static void ImplDraw(
Drawable aSrcDrawable,
tools::Long nSrcDrawableDepth,
Drawable aDstDrawable,
tools::Long nSrcX,
tools::Long nSrcY,
tools::Long nDestWidth,
tools::Long nDestHeight,
tools::Long nDestX,
tools::Long nDestY,
const GC& rGC
);
public:
ImplSalDDB(
XImage* pImage,
Drawable aDrawable,
SalX11Screen nXScreen,
const SalTwoRect& rTwoRect
);
ImplSalDDB(
Drawable aDrawable,
SalX11Screen nXScreen,
tools::Long nDrawableDepth,
tools::Long nX,
tools::Long nY,
tools::Long nWidth,
tools::Long nHeight
);
~ImplSalDDB();
Pixmap ImplGetPixmap() const { return maPixmap; }
tools::Long ImplGetWidth() const { return maTwoRect.mnDestWidth; }
tools::Long ImplGetHeight() const { return maTwoRect.mnDestHeight; }
tools::Long ImplGetDepth() const { return mnDepth; }
const SalX11Screen& ImplGetScreen() const { return mnXScreen; }
bool ImplMatches( SalX11Screen nXScreen, tools::Long nDepth, const SalTwoRect& rTwoRect ) const;
void ImplDraw(
Drawable aDrawable,
const SalTwoRect& rTwoRect,
const GC& rGC
) const;
};
class X11SalBitmap;
class ImplSalBitmapCache
{
private:
std::vector<X11SalBitmap*> maBmpList;
public:
ImplSalBitmapCache();
~ImplSalBitmapCache();
void ImplAdd( X11SalBitmap* pBmp );
void ImplRemove( X11SalBitmap const * pBmp );
void ImplClear();
};
#endif // INCLUDED_VCL_INC_UNX_SALBMP_H
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -58,7 +58,6 @@
#include <salinst.hxx>
#include <unx/salframe.h>
#include <vcl/keycodes.hxx>
#include <unx/salbmp.h>
#include <osl/diagnose.h>
#include <unx/salobj.h>
#include <unx/sm.hxx>
@ -281,7 +280,6 @@ void SalDisplay::doDestruct()
GenericUnixSalData *pData = GetGenericUnixSalData();
m_pWMAdaptor.reset();
X11SalBitmap::ImplDestroyCache();
if (ImplGetSVData())
{
@ -597,7 +595,6 @@ void SalDisplay::Init()
nMaxRequestSize_ = XMaxRequestSize( pDisp_ ) * 4;
meServerVendor = sal_GetServerVendor(pDisp_);
X11SalBitmap::ImplCreateCache();
// - - - - - - - - - - Synchronize - - - - - - - - - - - - -
if( getenv( "SAL_SYNCHRONIZE" ) )

View file

@ -31,7 +31,6 @@
#include <sal/log.hxx>
#include <unx/saldisp.hxx>
#include <unx/salbmp.h>
#include <unx/salgdi.h>
#include <unx/salvd.h>
#include <unx/x11/xlimits.hxx>

View file

@ -1,998 +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 <string.h>
#ifdef FREEBSD
#include <sys/types.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <osl/endian.h>
#include <sal/log.hxx>
#include <tools/helpers.hxx>
#include <tools/debug.hxx>
#include <vcl/bitmap.hxx>
#include <com/sun/star/beans/XFastPropertySet.hpp>
#include <unx/saldisp.hxx>
#include <unx/salbmp.h>
#include <unx/salinst.h>
#include <unx/x11/xlimits.hxx>
#include <o3tl/safeint.hxx>
#include <config_features.h>
#if defined HAVE_VALGRIND_HEADERS
#include <valgrind/valgrind.h>
#endif
#include <memory>
ImplSalBitmapCache* X11SalBitmap::mpCache = nullptr;
unsigned int X11SalBitmap::mnCacheInstCount = 0;
X11SalBitmap::X11SalBitmap()
: mbGrey( false )
{
}
X11SalBitmap::~X11SalBitmap()
{
Destroy();
}
void X11SalBitmap::ImplCreateCache()
{
if( !mnCacheInstCount++ )
mpCache = new ImplSalBitmapCache;
}
void X11SalBitmap::ImplDestroyCache()
{
SAL_WARN_IF( !mnCacheInstCount, "vcl", "X11SalBitmap::ImplDestroyCache(): underflow" );
if( mnCacheInstCount && !--mnCacheInstCount )
{
delete mpCache;
mpCache = nullptr;
}
}
void X11SalBitmap::ImplRemovedFromCache()
{
mpDDB.reset();
}
#if defined HAVE_VALGRIND_HEADERS
namespace
{
void blankExtraSpace(BitmapBuffer* pDIB)
{
size_t nExtraSpaceInScanLine = pDIB->mnScanlineSize - pDIB->mnWidth * pDIB->mnBitCount / 8;
if (nExtraSpaceInScanLine)
{
for (tools::Long i = 0; i < pDIB->mnHeight; ++i)
{
sal_uInt8 *pRow = pDIB->mpBits + (i * pDIB->mnScanlineSize);
memset(pRow + (pDIB->mnScanlineSize - nExtraSpaceInScanLine), 0, nExtraSpaceInScanLine);
}
}
}
}
#endif
std::unique_ptr<BitmapBuffer> X11SalBitmap::ImplCreateDIB(
const Size& rSize,
vcl::PixelFormat ePixelFormat,
const BitmapPalette& rPal)
{
std::unique_ptr<BitmapBuffer> pDIB;
if( !rSize.Width() || !rSize.Height() )
return nullptr;
try
{
pDIB.reset(new BitmapBuffer);
}
catch (const std::bad_alloc&)
{
return nullptr;
}
pDIB->mnFormat = ScanlineFormat::NONE;
switch(ePixelFormat)
{
case vcl::PixelFormat::N8_BPP:
pDIB->mnFormat |= ScanlineFormat::N8BitPal;
break;
case vcl::PixelFormat::N24_BPP:
pDIB->mnFormat |= ScanlineFormat::N24BitTcBgr;
break;
case vcl::PixelFormat::N32_BPP:
default:
SAL_WARN("vcl.gdi", "32-bit images not supported, converting to 24-bit");
ePixelFormat = vcl::PixelFormat::N24_BPP;
pDIB->mnFormat |= ScanlineFormat::N24BitTcBgr;
break;
}
sal_uInt16 nColors = 0;
if (ePixelFormat <= vcl::PixelFormat::N8_BPP)
nColors = vcl::numberOfColors(ePixelFormat);
pDIB->mnWidth = rSize.Width();
pDIB->mnHeight = rSize.Height();
tools::Long nScanlineBase;
bool bFail = o3tl::checked_multiply<tools::Long>(pDIB->mnWidth, vcl::pixelFormatBitCount(ePixelFormat), nScanlineBase);
if (bFail)
{
SAL_WARN("vcl.gdi", "checked multiply failed");
return nullptr;
}
pDIB->mnScanlineSize = AlignedWidth4Bytes(nScanlineBase);
if (pDIB->mnScanlineSize < nScanlineBase/8)
{
SAL_WARN("vcl.gdi", "scanline calculation wraparound");
return nullptr;
}
pDIB->mnBitCount = vcl::pixelFormatBitCount(ePixelFormat);
if( nColors )
{
pDIB->maPalette = rPal;
pDIB->maPalette.SetEntryCount( nColors );
}
try
{
pDIB->mpBits = new sal_uInt8[ pDIB->mnScanlineSize * pDIB->mnHeight ];
#if defined HAVE_VALGRIND_HEADERS
if (RUNNING_ON_VALGRIND)
blankExtraSpace(pDIB.get());
#endif
}
catch (const std::bad_alloc&)
{
return nullptr;
}
return pDIB;
}
std::unique_ptr<BitmapBuffer> X11SalBitmap::ImplCreateDIB(
Drawable aDrawable,
SalX11Screen nScreen,
tools::Long nDrawableDepth,
tools::Long nX,
tools::Long nY,
tools::Long nWidth,
tools::Long nHeight,
bool bGrey
) {
std::unique_ptr<BitmapBuffer> pDIB;
if( aDrawable && nWidth && nHeight && nDrawableDepth )
{
SalDisplay* pSalDisp = vcl_sal::getSalDisplay(GetGenericUnixSalData());
Display* pXDisp = pSalDisp->GetDisplay();
// do not die on XError here
// alternatively one could check the coordinates for being offscreen
// but this call can actually work on servers with backing store
// defaults even if the rectangle is offscreen
// so better catch the XError
GetGenericUnixSalData()->ErrorTrapPush();
XImage* pImage = XGetImage( pXDisp, aDrawable, nX, nY, nWidth, nHeight, AllPlanes, ZPixmap );
bool bWasError = GetGenericUnixSalData()->ErrorTrapPop( false );
if( ! bWasError && pImage && pImage->data )
{
const SalTwoRect aTwoRect = { 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight };
BitmapBuffer aSrcBuf;
std::optional<BitmapPalette> pDstPal;
aSrcBuf.mnFormat = ScanlineFormat::TopDown;
aSrcBuf.mnWidth = nWidth;
aSrcBuf.mnHeight = nHeight;
aSrcBuf.mnBitCount = pImage->bits_per_pixel;
aSrcBuf.mnScanlineSize = pImage->bytes_per_line;
aSrcBuf.mpBits = reinterpret_cast<sal_uInt8*>(pImage->data);
pImage->red_mask = pSalDisp->GetVisual( nScreen ).red_mask;
pImage->green_mask = pSalDisp->GetVisual( nScreen ).green_mask;
pImage->blue_mask = pSalDisp->GetVisual( nScreen ).blue_mask;
switch( aSrcBuf.mnBitCount )
{
case 1:
{
aSrcBuf.mnFormat |= ( LSBFirst == pImage->bitmap_bit_order
? ScanlineFormat::N1BitLsbPal
: ScanlineFormat::N1BitMsbPal
);
}
break;
case 8:
{
aSrcBuf.mnFormat |= ScanlineFormat::N8BitPal;
}
break;
case 24:
{
if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) )
aSrcBuf.mnFormat |= ScanlineFormat::N24BitTcRgb;
else
aSrcBuf.mnFormat |= ScanlineFormat::N24BitTcBgr;
}
break;
case 32:
{
if( LSBFirst == pImage->byte_order )
aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF
? ScanlineFormat::N32BitTcRgba
: ScanlineFormat::N32BitTcBgra
);
else
aSrcBuf.mnFormat |= ( pSalDisp->GetVisual(nScreen).red_mask == 0xFF
? ScanlineFormat::N32BitTcAbgr
: ScanlineFormat::N32BitTcArgb
);
}
break;
default: assert(false);
}
BitmapPalette& rPal = aSrcBuf.maPalette;
if( aSrcBuf.mnBitCount == 1 )
{
rPal.SetEntryCount( 2 );
rPal[ 0 ] = COL_BLACK;
rPal[ 1 ] = COL_WHITE;
pDstPal = rPal;
}
else if( pImage->depth == 8 && bGrey )
{
rPal.SetEntryCount( 256 );
for( sal_uInt16 i = 0; i < 256; i++ )
{
BitmapColor& rBmpCol = rPal[ i ];
rBmpCol.SetRed( i );
rBmpCol.SetGreen( i );
rBmpCol.SetBlue( i );
}
pDstPal = rPal;
}
else if( aSrcBuf.mnBitCount <= 8 )
{
const SalColormap& rColMap = pSalDisp->GetColormap( nScreen );
const sal_uInt16 nCols = std::min(static_cast<sal_uLong>(rColMap.GetUsed()),
sal_uLong(1) << nDrawableDepth);
rPal.SetEntryCount( nCols );
for( sal_uInt16 i = 0; i < nCols; i++ )
{
const Color nColor( rColMap.GetColor( i ) );
BitmapColor& rBmpCol = rPal[ i ];
rBmpCol.SetRed( nColor.GetRed() );
rBmpCol.SetGreen( nColor.GetGreen() );
rBmpCol.SetBlue( nColor.GetBlue() );
}
pDstPal = rPal;
}
pDIB = StretchAndConvert( aSrcBuf, aTwoRect, aSrcBuf.mnFormat,
pDstPal, &aSrcBuf.maColorMask );
XDestroyImage( pImage );
}
}
return pDIB;
}
XImage* X11SalBitmap::ImplCreateXImage(
SalDisplay const *pSalDisp,
SalX11Screen nScreen,
tools::Long nDepth,
const SalTwoRect& rTwoRect
) const
{
XImage* pImage = nullptr;
if( !mpDIB && mpDDB )
{
const_cast<X11SalBitmap*>(this)->mpDIB =
ImplCreateDIB( mpDDB->ImplGetPixmap(),
mpDDB->ImplGetScreen(),
mpDDB->ImplGetDepth(),
0, 0,
mpDDB->ImplGetWidth(),
mpDDB->ImplGetHeight(),
mbGrey );
}
if( mpDIB && mpDIB->mnWidth && mpDIB->mnHeight )
{
Display* pXDisp = pSalDisp->GetDisplay();
tools::Long nWidth = rTwoRect.mnDestWidth;
tools::Long nHeight = rTwoRect.mnDestHeight;
if( 1 == GetBitCount() )
nDepth = 1;
pImage = XCreateImage( pXDisp, pSalDisp->GetVisual( nScreen ).GetVisual(),
nDepth, ( 1 == nDepth ) ? XYBitmap :ZPixmap, 0, nullptr,
nWidth, nHeight, 32, 0 );
if( pImage )
{
std::unique_ptr<BitmapBuffer> pDstBuf;
ScanlineFormat nDstFormat = ScanlineFormat::TopDown;
std::optional<BitmapPalette> xPal;
std::unique_ptr<ColorMask> xMask;
switch( pImage->bits_per_pixel )
{
case 1:
nDstFormat |= ( LSBFirst == pImage->bitmap_bit_order
? ScanlineFormat::N1BitLsbPal
: ScanlineFormat::N1BitMsbPal
);
break;
case 8:
nDstFormat |= ScanlineFormat::N8BitPal;
break;
case 24:
{
if( ( LSBFirst == pImage->byte_order ) && ( pImage->red_mask == 0xFF ) )
nDstFormat |= ScanlineFormat::N24BitTcRgb;
else
nDstFormat |= ScanlineFormat::N24BitTcBgr;
}
break;
case 32:
{
if( LSBFirst == pImage->byte_order )
nDstFormat |= ( pImage->red_mask == 0xFF
? ScanlineFormat::N32BitTcRgba
: ScanlineFormat::N32BitTcBgra
);
else
nDstFormat |= ( pImage->red_mask == 0xFF
? ScanlineFormat::N32BitTcAbgr
: ScanlineFormat::N32BitTcArgb
);
}
break;
default: assert(false);
}
if( pImage->depth == 1 )
{
xPal.emplace(2);
(*xPal)[ 0 ] = COL_BLACK;
(*xPal)[ 1 ] = COL_WHITE;
}
else if( pImage->depth == 8 && mbGrey )
{
xPal.emplace(256);
for( sal_uInt16 i = 0; i < 256; i++ )
{
BitmapColor& rBmpCol = (*xPal)[ i ];
rBmpCol.SetRed( i );
rBmpCol.SetGreen( i );
rBmpCol.SetBlue( i );
}
}
else if( pImage->depth <= 8 )
{
const SalColormap& rColMap = pSalDisp->GetColormap( nScreen );
const sal_uInt16 nCols = std::min( static_cast<sal_uLong>(rColMap.GetUsed())
, static_cast<sal_uLong>(1 << pImage->depth)
);
xPal.emplace(nCols);
for( sal_uInt16 i = 0; i < nCols; i++ )
{
const Color nColor( rColMap.GetColor( i ) );
BitmapColor& rBmpCol = (*xPal)[ i ];
rBmpCol.SetRed( nColor.GetRed() );
rBmpCol.SetGreen( nColor.GetGreen() );
rBmpCol.SetBlue( nColor.GetBlue() );
}
}
pDstBuf = StretchAndConvert( *mpDIB, rTwoRect, nDstFormat, xPal, xMask.get() );
xPal.reset();
xMask.reset();
if( pDstBuf && pDstBuf->mpBits )
{
#if defined HAVE_VALGRIND_HEADERS
if (RUNNING_ON_VALGRIND)
blankExtraSpace(pDstBuf.get());
#endif
// set data in buffer as data member in pImage
pImage->data = reinterpret_cast<char*>(pDstBuf->mpBits);
}
else
{
XDestroyImage( pImage );
pImage = nullptr;
}
// note that pDstBuf it deleted here, but that doesn't destroy allocated data in buffer
}
}
return pImage;
}
bool X11SalBitmap::ImplCreateFromDrawable(
Drawable aDrawable,
SalX11Screen nScreen,
tools::Long nDrawableDepth,
tools::Long nX,
tools::Long nY,
tools::Long nWidth,
tools::Long nHeight
) {
Destroy();
if( aDrawable && nWidth && nHeight && nDrawableDepth )
mpDDB.reset(new ImplSalDDB( aDrawable, nScreen, nDrawableDepth, nX, nY, nWidth, nHeight ));
return( mpDDB != nullptr );
}
ImplSalDDB* X11SalBitmap::ImplGetDDB(
Drawable aDrawable,
SalX11Screen nXScreen,
tools::Long nDrawableDepth,
const SalTwoRect& rTwoRect
) const
{
if( !mpDDB || !mpDDB->ImplMatches( nXScreen, nDrawableDepth, rTwoRect ) )
{
if( mpDDB )
{
// do we already have a DIB? if not, create aDIB from current DDB first
if( !mpDIB )
{
const_cast<X11SalBitmap*>(this)->mpDIB = ImplCreateDIB( mpDDB->ImplGetPixmap(),
mpDDB->ImplGetScreen(),
mpDDB->ImplGetDepth(),
0, 0,
mpDDB->ImplGetWidth(),
mpDDB->ImplGetHeight(),
mbGrey );
}
mpDDB.reset();
}
if( mpCache )
mpCache->ImplRemove( this );
SalTwoRect aTwoRect( rTwoRect );
if( aTwoRect.mnSrcX < 0 )
{
aTwoRect.mnSrcWidth += aTwoRect.mnSrcX;
aTwoRect.mnSrcX = 0;
}
if( aTwoRect.mnSrcY < 0 )
{
aTwoRect.mnSrcHeight += aTwoRect.mnSrcY;
aTwoRect.mnSrcY = 0;
}
// create new DDB from DIB
const Size aSize( GetSize() );
if( aTwoRect.mnSrcWidth == aTwoRect.mnDestWidth &&
aTwoRect.mnSrcHeight == aTwoRect.mnDestHeight )
{
aTwoRect.mnSrcX = aTwoRect.mnSrcY = aTwoRect.mnDestX = aTwoRect.mnDestY = 0;
aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = aSize.Width();
aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = aSize.Height();
}
else if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() ||
aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() )
{
// #i47823# this should not happen at all, but does nonetheless
// because BitmapEx allows for mask bitmaps of different size
// than image bitmap (broken)
if( aTwoRect.mnSrcX >= aSize.Width() ||
aTwoRect.mnSrcY >= aSize.Height() )
return nullptr; // this would be a really mad case
if( aTwoRect.mnSrcWidth+aTwoRect.mnSrcX > aSize.Width() )
{
aTwoRect.mnSrcWidth = aSize.Width()-aTwoRect.mnSrcX;
if( aTwoRect.mnSrcWidth < 1 )
{
aTwoRect.mnSrcX = 0;
aTwoRect.mnSrcWidth = aSize.Width();
}
}
if( aTwoRect.mnSrcHeight+aTwoRect.mnSrcY > aSize.Height() )
{
aTwoRect.mnSrcHeight = aSize.Height() - aTwoRect.mnSrcY;
if( aTwoRect.mnSrcHeight < 1 )
{
aTwoRect.mnSrcY = 0;
aTwoRect.mnSrcHeight = aSize.Height();
}
}
}
XImage* pImage = ImplCreateXImage( vcl_sal::getSalDisplay(GetGenericUnixSalData()), nXScreen,
nDrawableDepth, aTwoRect );
if( pImage )
{
mpDDB.reset(new ImplSalDDB( pImage, aDrawable, nXScreen, aTwoRect ));
delete[] pImage->data;
pImage->data = nullptr;
XDestroyImage( pImage );
if( mpCache )
mpCache->ImplAdd( const_cast<X11SalBitmap*>(this) );
}
}
return mpDDB.get();
}
void X11SalBitmap::ImplDraw(
Drawable aDrawable,
SalX11Screen nXScreen,
tools::Long nDrawableDepth,
const SalTwoRect& rTwoRect,
const GC& rGC
) const
{
ImplGetDDB( aDrawable, nXScreen, nDrawableDepth, rTwoRect );
if( mpDDB )
mpDDB->ImplDraw( aDrawable, rTwoRect, rGC );
}
bool X11SalBitmap::Create( const Size& rSize, vcl::PixelFormat ePixelFormat, const BitmapPalette& rPal )
{
Destroy();
mpDIB = ImplCreateDIB( rSize, ePixelFormat, rPal );
return( mpDIB != nullptr );
}
bool X11SalBitmap::Create( const SalBitmap& rSSalBmp )
{
Destroy();
auto pX11Bmp = dynamic_cast<const X11SalBitmap*>( &rSSalBmp );
if (!pX11Bmp)
return false;
const X11SalBitmap& rSalBmp = *pX11Bmp;
if( rSalBmp.mpDIB )
{
// TODO: reference counting...
mpDIB.reset(new BitmapBuffer( *rSalBmp.mpDIB ));
// TODO: get rid of this when BitmapBuffer gets copy constructor
try
{
mpDIB->mpBits = new sal_uInt8[ mpDIB->mnScanlineSize * mpDIB->mnHeight ];
#if defined HAVE_VALGRIND_HEADERS
if (RUNNING_ON_VALGRIND)
blankExtraSpace(mpDIB.get());
#endif
}
catch (const std::bad_alloc&)
{
mpDIB.reset();
}
if( mpDIB )
memcpy( mpDIB->mpBits, rSalBmp.mpDIB->mpBits, mpDIB->mnScanlineSize * mpDIB->mnHeight );
}
else if( rSalBmp.mpDDB )
ImplCreateFromDrawable( rSalBmp.mpDDB->ImplGetPixmap(),
rSalBmp.mpDDB->ImplGetScreen(),
rSalBmp.mpDDB->ImplGetDepth(),
0, 0, rSalBmp.mpDDB->ImplGetWidth(), rSalBmp.mpDDB->ImplGetHeight() );
return( ( !rSalBmp.mpDIB && !rSalBmp.mpDDB ) ||
( rSalBmp.mpDIB && ( mpDIB != nullptr ) ) ||
( rSalBmp.mpDDB && ( mpDDB != nullptr ) ) );
}
bool X11SalBitmap::Create( const SalBitmap&, SalGraphics* )
{
return false;
}
bool X11SalBitmap::Create(const SalBitmap&, vcl::PixelFormat /*eNewPixelFormat*/)
{
return false;
}
bool X11SalBitmap::Create(
const css::uno::Reference< css::rendering::XBitmapCanvas >& rBitmapCanvas,
Size& rSize,
bool bMask
) {
css::uno::Reference< css::beans::XFastPropertySet > xFastPropertySet( rBitmapCanvas, css::uno::UNO_QUERY );
if( xFastPropertySet ) {
css::uno::Sequence< css::uno::Any > args;
if( xFastPropertySet->getFastPropertyValue(bMask ? 2 : 1) >>= args ) {
sal_Int64 pixmapHandle = {}; // spurious -Werror=maybe-uninitialized
sal_Int32 depth;
if( ( args[1] >>= pixmapHandle ) && ( args[2] >>= depth ) ) {
mbGrey = bMask;
bool bSuccess = ImplCreateFromDrawable(
pixmapHandle,
// FIXME: this seems multi-screen broken to me
SalX11Screen( 0 ),
depth,
0,
0,
rSize.Width(),
rSize.Height()
);
bool bFreePixmap = false;
if( bSuccess && (args[0] >>= bFreePixmap) && bFreePixmap )
XFreePixmap( vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetDisplay(), pixmapHandle );
return bSuccess;
}
}
}
return false;
}
void X11SalBitmap::Destroy()
{
if( mpDIB )
{
delete[] mpDIB->mpBits;
mpDIB.reset();
}
mpDDB.reset();
if( mpCache )
mpCache->ImplRemove( this );
}
Size X11SalBitmap::GetSize() const
{
Size aSize;
if( mpDIB )
{
aSize.setWidth( mpDIB->mnWidth );
aSize.setHeight( mpDIB->mnHeight );
}
else if( mpDDB )
{
aSize.setWidth( mpDDB->ImplGetWidth() );
aSize.setHeight( mpDDB->ImplGetHeight() );
}
return aSize;
}
sal_uInt16 X11SalBitmap::GetBitCount() const
{
sal_uInt16 nBitCount;
if( mpDIB )
nBitCount = mpDIB->mnBitCount;
else if( mpDDB )
nBitCount = mpDDB->ImplGetDepth();
else
nBitCount = 0;
return nBitCount;
}
BitmapBuffer* X11SalBitmap::AcquireBuffer( BitmapAccessMode /*nMode*/ )
{
if( !mpDIB && mpDDB )
{
mpDIB = ImplCreateDIB(
mpDDB->ImplGetPixmap(),
mpDDB->ImplGetScreen(),
mpDDB->ImplGetDepth(),
0, 0,
mpDDB->ImplGetWidth(),
mpDDB->ImplGetHeight(),
mbGrey
);
}
return mpDIB.get();
}
void X11SalBitmap::ReleaseBuffer( BitmapBuffer*, BitmapAccessMode nMode )
{
if( nMode == BitmapAccessMode::Write )
{
mpDDB.reset();
if( mpCache )
mpCache->ImplRemove( this );
InvalidateChecksum();
}
}
bool X11SalBitmap::GetSystemData( BitmapSystemData& rData )
{
if( mpDDB )
{
// Rename/retype pDummy to your likings (though X11 Pixmap is
// prolly not a good idea, since it's accessed from
// non-platform aware code in vcl/bitmap.hxx)
rData.aPixmap = reinterpret_cast<void*>(mpDDB->ImplGetPixmap());
rData.mnWidth = mpDDB->ImplGetWidth ();
rData.mnHeight = mpDDB->ImplGetHeight ();
return true;
}
return false;
}
bool X11SalBitmap::ScalingSupported() const
{
return false;
}
bool X11SalBitmap::Scale( const double& /*rScaleX*/, const double& /*rScaleY*/, BmpScaleFlag /*nScaleFlag*/ )
{
return false;
}
bool X11SalBitmap::Replace( const Color& /*rSearchColor*/, const Color& /*rReplaceColor*/, sal_uInt8 /*nTol*/ )
{
return false;
}
ImplSalDDB::ImplSalDDB( XImage* pImage, Drawable aDrawable,
SalX11Screen nXScreen, const SalTwoRect& rTwoRect )
: maPixmap ( 0 )
, maTwoRect ( rTwoRect )
, mnDepth ( pImage->depth )
, mnXScreen ( nXScreen )
{
SalDisplay* pSalDisp = vcl_sal::getSalDisplay(GetGenericUnixSalData());
Display* pXDisp = pSalDisp->GetDisplay();
maPixmap = limitXCreatePixmap( pXDisp, aDrawable, ImplGetWidth(), ImplGetHeight(), ImplGetDepth() );
if (!maPixmap)
return;
XGCValues aValues;
GC aGC;
int nValues = GCFunction;
aValues.function = GXcopy;
if( 1 == mnDepth )
{
nValues |= ( GCForeground | GCBackground );
aValues.foreground = 1;
aValues.background = 0;
}
aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues );
XPutImage( pXDisp, maPixmap, aGC, pImage, 0, 0, 0, 0, maTwoRect.mnDestWidth, maTwoRect.mnDestHeight );
XFreeGC( pXDisp, aGC );
}
ImplSalDDB::ImplSalDDB(
Drawable aDrawable,
SalX11Screen nXScreen,
tools::Long nDrawableDepth,
tools::Long nX,
tools::Long nY,
tools::Long nWidth,
tools::Long nHeight
) : maTwoRect(0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight)
, mnDepth( nDrawableDepth )
, mnXScreen( nXScreen )
{
SalDisplay* pSalDisp = vcl_sal::getSalDisplay(GetGenericUnixSalData());
Display* pXDisp = pSalDisp->GetDisplay();
if( (maPixmap = limitXCreatePixmap( pXDisp, aDrawable, nWidth, nHeight, nDrawableDepth )) )
{
XGCValues aValues;
GC aGC;
int nValues = GCFunction;
aValues.function = GXcopy;
if( 1 == mnDepth )
{
nValues |= ( GCForeground | GCBackground );
aValues.foreground = 1;
aValues.background = 0;
}
aGC = XCreateGC( pXDisp, maPixmap, nValues, &aValues );
ImplDraw( aDrawable, nDrawableDepth, maPixmap,
nX, nY, nWidth, nHeight, 0, 0, aGC );
XFreeGC( pXDisp, aGC );
}
else
{
maTwoRect.mnSrcWidth = maTwoRect.mnDestWidth = 0;
maTwoRect.mnSrcHeight = maTwoRect.mnDestHeight = 0;
}
}
ImplSalDDB::~ImplSalDDB()
{
if( maPixmap && ImplGetSVData() )
XFreePixmap( vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetDisplay(), maPixmap );
}
bool ImplSalDDB::ImplMatches( SalX11Screen nXScreen, tools::Long nDepth, const SalTwoRect& rTwoRect ) const
{
bool bRet = false;
if( ( maPixmap != 0 ) && ( ( mnDepth == nDepth ) || ( 1 == mnDepth ) ) && nXScreen == mnXScreen)
{
if ( rTwoRect.mnSrcX == maTwoRect.mnSrcX
&& rTwoRect.mnSrcY == maTwoRect.mnSrcY
&& rTwoRect.mnSrcWidth == maTwoRect.mnSrcWidth
&& rTwoRect.mnSrcHeight == maTwoRect.mnSrcHeight
&& rTwoRect.mnDestWidth == maTwoRect.mnDestWidth
&& rTwoRect.mnDestHeight == maTwoRect.mnDestHeight
)
{
// absolutely identically
bRet = true;
}
else if( rTwoRect.mnSrcWidth == rTwoRect.mnDestWidth
&& rTwoRect.mnSrcHeight == rTwoRect.mnDestHeight
&& maTwoRect.mnSrcWidth == maTwoRect.mnDestWidth
&& maTwoRect.mnSrcHeight == maTwoRect.mnDestHeight
&& rTwoRect.mnSrcX >= maTwoRect.mnSrcX
&& rTwoRect.mnSrcY >= maTwoRect.mnSrcY
&& ( rTwoRect.mnSrcX + rTwoRect.mnSrcWidth ) <= ( maTwoRect.mnSrcX + maTwoRect.mnSrcWidth )
&& ( rTwoRect.mnSrcY + rTwoRect.mnSrcHeight ) <= ( maTwoRect.mnSrcY + maTwoRect.mnSrcHeight )
)
{
bRet = true;
}
}
return bRet;
}
void ImplSalDDB::ImplDraw(
Drawable aDrawable,
const SalTwoRect& rTwoRect,
const GC& rGC
) const
{
ImplDraw( maPixmap, mnDepth, aDrawable,
rTwoRect.mnSrcX - maTwoRect.mnSrcX, rTwoRect.mnSrcY - maTwoRect.mnSrcY,
rTwoRect.mnDestWidth, rTwoRect.mnDestHeight,
rTwoRect.mnDestX, rTwoRect.mnDestY, rGC );
}
void ImplSalDDB::ImplDraw(
Drawable aSrcDrawable,
tools::Long nSrcDrawableDepth,
Drawable aDstDrawable,
tools::Long nSrcX,
tools::Long nSrcY,
tools::Long nDestWidth,
tools::Long nDestHeight,
tools::Long nDestX,
tools::Long nDestY,
const GC& rGC
) {
SalDisplay* pSalDisp = vcl_sal::getSalDisplay(GetGenericUnixSalData());
Display* pXDisp = pSalDisp->GetDisplay();
if( 1 == nSrcDrawableDepth )
{
XCopyPlane( pXDisp, aSrcDrawable, aDstDrawable, rGC,
nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY, 1 );
}
else
{
XCopyArea( pXDisp, aSrcDrawable, aDstDrawable, rGC,
nSrcX, nSrcY, nDestWidth, nDestHeight, nDestX, nDestY );
}
}
ImplSalBitmapCache::ImplSalBitmapCache()
{
}
ImplSalBitmapCache::~ImplSalBitmapCache()
{
ImplClear();
}
void ImplSalBitmapCache::ImplAdd( X11SalBitmap* pBmp )
{
for(auto pObj : maBmpList)
{
if( pObj == pBmp )
return;
}
maBmpList.push_back( pBmp );
}
void ImplSalBitmapCache::ImplRemove( X11SalBitmap const * pBmp )
{
auto it = std::find(maBmpList.begin(), maBmpList.end(), pBmp);
if( it != maBmpList.end() )
{
(*it)->ImplRemovedFromCache();
maBmpList.erase( it );
}
}
void ImplSalBitmapCache::ImplClear()
{
for(auto pObj : maBmpList)
{
pObj->ImplRemovedFromCache();
}
maBmpList.clear();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */