Change alpha behavour of OutputDevice::SetFillColor

It is pretty ugly bad on several levels.

Essentially what the currrent behaviour does is, if the fill color has an
transparency value, and draw some pixels, we just don't bother to write
anything to the color surface at all, we only write to the alpha surface.

(*) It is impossible to emulate efficiently when we switch to combined
    color+alpha surfaces
(*) It works completely differently to how every other graphics API in the
    world operates
(*) It makes no sense - it doesn't allow you to fill a shape with partially
    transparent color pixels (because it just doesn't bother writing to the
    color surface).

This behaviour dates back to "initial import", so sadly no reason why.

Noting that we are changing 3 things here:
(1) Setting a fill color with transparency will actually write to the color
    surface.
(2) Previously, SetFillColor(COL_TRANSPARENCY) was the same as
    SetFillColor(), now they mean different things
(3) SetFillColor(x) where x has tranparency will now actually affect the fill
    color of the alpha layer.
(4) VirtualDevice::SetOutputSizePixel will now erase/fill the device with
    data in cases where it previously would not (because previously the
    fill was ignored when background == COL_TRANSPARENT)

Change-Id: I4c8b371a436a4d1ffc4344c7d6b21932d861397d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180184
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
Noel Grandin
2025-01-14 15:47:13 +01:00
parent 3eaa35e8ba
commit e0d4d178ca
6 changed files with 13 additions and 22 deletions
+1 -1
View File
@@ -152,7 +152,7 @@ public:
= o3tl::convert(rTileRect, o3tl::Length::twip, o3tl::Length::mm100);
// Resizes the virtual device so to contain the entries context
rDevice.SetOutputSizePixel(aOutputSize);
rDevice.SetOutputSizePixel(aOutputSize, /*bErase*/ false);
rDevice.Push(vcl::PushFlags::MAPMODE);
MapMode aDeviceMapMode(rDevice.GetMapMode());
+1 -1
View File
@@ -3612,7 +3612,7 @@ void SdXImpressDocument::paintTile( VirtualDevice& rDevice,
rDevice.SetMapMode( aMapMode );
rDevice.SetOutputSizePixel( Size(nOutputWidth, nOutputHeight) );
rDevice.SetOutputSizePixel( Size(nOutputWidth, nOutputHeight), /*bErase*/false );
Point aPoint(nTilePosXHMM, nTilePosYHMM);
Size aSize(nTileWidthHMM, nTileHeightHMM);
+1 -1
View File
@@ -241,7 +241,7 @@ void LokChartHelper::PaintAllChartsOnTile(VirtualDevice& rDevice,
return;
// Resizes the virtual device so to contain the entries context
rDevice.SetOutputSizePixel(Size(nOutputWidth, nOutputHeight));
rDevice.SetOutputSizePixel(Size(nOutputWidth, nOutputHeight), /*bErase*/false);
rDevice.Push(vcl::PushFlags::MAPMODE);
MapMode aMapMode(rDevice.GetMapMode());
+1 -1
View File
@@ -2112,7 +2112,7 @@ void SwViewShell::PaintTile(VirtualDevice &rDevice, int contextWidth, int contex
mpOut = &rDevice;
// resizes the virtual device so to contain the entries context
rDevice.SetOutputSizePixel(Size(contextWidth, contextHeight));
rDevice.SetOutputSizePixel(Size(contextWidth, contextHeight), /*bErase*/false);
// setup the output device to draw the tile
MapMode aMapMode(rDevice.GetMapMode());
+1 -1
View File
@@ -511,7 +511,7 @@ CPPUNIT_TEST_FIXTURE(VclOutdevTest, testTransparentFillColor)
CPPUNIT_ASSERT_EQUAL(COL_WHITE, pVDev->GetFillColor());
pVDev->SetFillColor(COL_TRANSPARENT);
CPPUNIT_ASSERT(!pVDev->IsFillColor());
CPPUNIT_ASSERT(pVDev->IsFillColor());
CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, pVDev->GetFillColor());
MetaAction* pAction = aMtf.GetAction(0);
CPPUNIT_ASSERT_EQUAL(MetaActionType::FILLCOLOR, pAction->GetType());
+8 -17
View File
@@ -50,27 +50,18 @@ void OutputDevice::SetFillColor( const Color& rColor )
if ( mpMetaFile )
mpMetaFile->AddAction( new MetaFillColorAction( aColor, true ) );
if ( aColor.IsTransparent() )
if ( maFillColor != aColor )
{
if ( mbFillColor )
{
mbInitFillColor = true;
mbFillColor = false;
maFillColor = COL_TRANSPARENT;
}
}
else
{
if ( maFillColor != aColor )
{
mbInitFillColor = true;
mbFillColor = true;
maFillColor = aColor;
}
mbInitFillColor = true;
mbFillColor = true;
maFillColor = aColor;
}
if( mpAlphaVDev )
mpAlphaVDev->SetFillColor( COL_ALPHA_OPAQUE );
{
sal_uInt8 nAlpha = rColor.GetAlpha();
mpAlphaVDev->SetFillColor( Color(nAlpha, nAlpha, nAlpha) );
}
}
void OutputDevice::InitFillColor()