wxGCDC::Clear bitmap background when using wxTRANSPARENT_BRUSH (Issue #22865)

121 views
Skip to first unread message

FillipMatthew

unread,
Oct 11, 2022, 4:33:55 AM10/11/22
to wx-...@googlegroups.com, Subscribed

Description

Drawing to a bitmap using wxTRANSPARENT_BRUSH does not clear the bitmap. I would expect and a few example indicate that this clears the background to be full transparent.

A workaround is to use a custom brush wxBrush(wxColour(0, 0, 0, 0)) to fill the bitmap with an alpha of 0.

#include <wx/wx.h>
#include <wx/bitmap.h>
#include <wx/dcgraph.h>

class MyApp : public wxApp
{
public:
	bool OnInit()  // wxOVERRIDE
	{
		if (!wxApp::OnInit())
			return false;

		wxInitAllImageHandlers();

		wxBitmap bmp(640, 480, 32);
		bmp.UseAlpha();

		wxRect rect1(80, 30, 340, 240);
		wxRect rect2(230, 120, 340, 240);
		wxRect rect3(140, 210, 340, 240);

		for (int i = 0; i < 3; ++i)
		{
			{  // Yes I like using scope for releasing objects.
				wxMemoryDC memDC(bmp);

				{
					wxGCDC gc(memDC);
					gc.SetBackground(*wxTRANSPARENT_BRUSH);
					gc.Clear();

					int index = i % 3;
					switch (index)
					{
						case 0:
							gc.SetBrush(*wxRED_BRUSH);
							gc.DrawRectangle(rect1);
							gc.SetBrush(wxNullBrush);

							break;

						case 1:
							gc.SetBrush(*wxGREEN_BRUSH);
							gc.DrawRectangle(rect2);
							gc.SetBrush(wxNullBrush);

							break;

						case 2:
							gc.SetBrush(*wxBLUE_BRUSH);
							gc.DrawRectangle(rect3);
							gc.SetBrush(wxNullBrush);

							break;
					}
				}
			}

			wxString name("test");
			name << i << ".png";
			bmp.SaveFile(name, wxBITMAP_TYPE_PNG);
		}

		return false;
	}
};

IMPLEMENT_APP(MyApp);

To Reproduce:
The sample generates 3 bitmaps that show the issue. Each image should have a single rectangle but they don't.

Platform and version information

  • wxWidgets version you use: 3.2.1
  • wxWidgets port you use: wxMSW
  • OS and its version: Windows 10


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22865@github.com>

VZ

unread,
Oct 11, 2022, 8:22:26 AM10/11/22
to wx-...@googlegroups.com, Subscribed

I'm really not sure a transparent brush is supposed to clear anything. It's an "absence of the brush", e.g. it is used when you don't want to fill the shape.

It should behave consistently on all platforms, however, so if some of them (which ones?) do clear the background, we could consider making wxMSW work like this too, but otherwise I'd just close this.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22865/1274599656@github.com>

Eric Jensen

unread,
Oct 11, 2022, 12:21:40 PM10/11/22
to wx-...@googlegroups.com, Subscribed

At least under Windows it works if you create a brush from a color with an explicit alpha value, and set a different composition mode:

  wxGraphicsContext *gc = wxGraphicsContext::Create(...);

  gc->SetCompositionMode( wxCOMPOSITION_SOURCE );
  gc->SetBrush( wxColour( 0,0,0, 0 ) );

You have so set the composition mode back afterwards.

Full code sample from: https://forums.wxwidgets.org/viewtopic.php?p=214856#p214856


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22865/1274955813@github.com>

FillipMatthew

unread,
Oct 12, 2022, 3:56:51 AM10/12/22
to wx-...@googlegroups.com, Subscribed

Is using the composition mode better than clearing to a transparent colour?

wxColour colour(0, 0, 0, 0);
wxBrush brush(colour);
gc.SetBackground(brush);
gc.Clear();

Is Clear() intended to be a paint method? I thought it is more like and erase/replace.. Like in for example graphics programs where when setting the background colour to transparent and using an erase/clear it erases and replaces the content with the background setting.

I don't know or have a way of testing on another system. If it is kept the way it is then the docs could maybe use an update to make the behaviour of transparent brushes used in Clear() more understandable and or an assert against transparent brushes being passed to SetBackground() since they have no effect? I was under the assumption a transparent brush meant alpha == 0, this does not seem to be the case though.

If you guys do want to close this issue I don't mind.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22865/1275747162@github.com>

Eric Jensen

unread,
Oct 12, 2022, 11:54:40 AM10/12/22
to wx-...@googlegroups.com, Subscribed

The meaning of wxTRANSPARENT_BRUSH is ambiguous. Right now it's interpreted as a no-operation. E.g. if you want to draw the outline of a rectangle, you would set a wxTRANSPARENT_BRUSH and call wxDC::DrawRectangle. In that case (and most other cases) you want the existing drawing inside the rectangle to remain untouched.

If you want to explicitly draw with transparency, setting the composition mode as shown is the only way i know.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/22865/1276401787@github.com>

Reply all
Reply to author
Forward
0 new messages