Merge branch 'fix_SVG_premultiply' of https://github.com/teliseo/wxWidgets
Fix wxBitmapBundle::FromSVG(), which renders incorrectly on GTK and add wxHAS_PREMULTIPLIED_ALPHA to make the code dealing with alpha more clear and correct. See #24097.
This commit is contained in:
commit
5318637839
9 changed files with 124 additions and 39 deletions
|
|
@ -210,6 +210,10 @@ Currently the following symbols exist:
|
|||
Windows resource files</a> resource files are available on the current platform.
|
||||
Usually wxHAS_IMAGE_RESOURCES should be used instead.}
|
||||
@itemdef{wxHAS_POWER_EVENTS, Defined if wxPowerEvent are ever generated on the current platform.}
|
||||
@itemdef{wxHAS_PREMULTIPLIED_ALPHA, Defined if wxBitmap stores raw pixel color
|
||||
values premultiplied (scaled) by alpha. This is generally used to switch
|
||||
whether to premultiply before storing pixels via wxAlphaPixelData converted
|
||||
from a straight alpha source.}
|
||||
@itemdef{wxHAS_RADIO_MENU_ITEMS,
|
||||
Defined if the current port supports radio menu items (see wxMenu::AppendRadioItem).}
|
||||
@itemdef{wxHAS_RAW_BITMAP, Defined if direct access to bitmap data using the classes in @c wx/rawbmp.h is supported.}
|
||||
|
|
|
|||
|
|
@ -146,12 +146,19 @@ struct wxPixelFormat
|
|||
// wxImage format is common to all platforms
|
||||
typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxImagePixelFormat;
|
||||
|
||||
// wxPIXEL_FORMAT_ALPHA is the offset of alpha (defined if the format has
|
||||
// alpha).
|
||||
|
||||
// wxHAS_PREMULTIPLIED_ALPHA is defined if R, G, and B are stored premultiplied
|
||||
// (scaled) by alpha, otherwise they have full value ("straight alpha").
|
||||
|
||||
// the (most common) native bitmap format without alpha support
|
||||
#if defined(__WXMSW__)
|
||||
// under MSW the RGB components are reversed, they're in BGR order
|
||||
typedef wxPixelFormat<unsigned char, 24, 2, 1, 0> wxNativePixelFormat;
|
||||
|
||||
#define wxPIXEL_FORMAT_ALPHA 3
|
||||
#define wxHAS_PREMULTIPLIED_ALPHA
|
||||
|
||||
template<>
|
||||
struct wxPixelFormat<void, 1, -1, -1, -1, -1, bool>
|
||||
|
|
@ -170,12 +177,13 @@ typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxImagePixelFormat;
|
|||
enum { HasAlpha = false };
|
||||
};
|
||||
typedef wxPixelFormat<void, 1, -1, -1, -1, -1, bool> wxMonoPixelFormat;
|
||||
#elif defined(__WXMAC__)
|
||||
#elif defined(__WXOSX__)
|
||||
// under Mac, first component is unused but still present, hence we use
|
||||
// 32bpp, not 24
|
||||
typedef wxPixelFormat<unsigned char, 32, 1, 2, 3> wxNativePixelFormat;
|
||||
|
||||
#define wxPIXEL_FORMAT_ALPHA 0
|
||||
#define wxHAS_PREMULTIPLIED_ALPHA
|
||||
#elif defined(__WXGTK__)
|
||||
// Under GTK+ 2.X we use GdkPixbuf, which is standard RGB or RGBA
|
||||
typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxNativePixelFormat;
|
||||
|
|
@ -190,6 +198,7 @@ typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxImagePixelFormat;
|
|||
typedef wxPixelFormat<unsigned char, 24, 0, 1, 2> wxNativePixelFormat;
|
||||
|
||||
#define wxPIXEL_FORMAT_ALPHA 3
|
||||
#define wxHAS_PREMULTIPLIED_ALPHA
|
||||
|
||||
template<>
|
||||
struct wxPixelFormat<void, 1, -1, -1, -1, -1, bool>
|
||||
|
|
|
|||
|
|
@ -675,12 +675,23 @@ public:
|
|||
|
||||
for ( int x = 0; x < REAL_SIZE; ++x )
|
||||
{
|
||||
// note that RGB must be premultiplied by alpha
|
||||
unsigned a = (wxAlphaPixelData::Iterator::ChannelType)((x*255.)/REAL_SIZE);
|
||||
p.Alpha() = a;
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// RGB must be premultiplied by alpha on some platforms
|
||||
p.Red() = r * a / 256;
|
||||
p.Green() = g * a / 256;
|
||||
p.Blue() = b * a / 256;
|
||||
p.Alpha() = a;
|
||||
#else
|
||||
if ( a )
|
||||
{
|
||||
p.Red() = r;
|
||||
p.Green() = g;
|
||||
p.Blue() = b;
|
||||
}
|
||||
else
|
||||
p.Red() = p.Green() = p.Blue() = 0;
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
|
||||
++p; // same as p.OffsetX(1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,11 +189,25 @@ wxBitmap wxBitmapBundleImplSVG::DoRasterize(const wxSize& size)
|
|||
for ( int x = 0; x < size.x; ++x )
|
||||
{
|
||||
const unsigned char a = src[3];
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// Some platforms require premultiplication by alpha.
|
||||
dst.Red() = src[0] * a / 255;
|
||||
dst.Green() = src[1] * a / 255;
|
||||
dst.Blue() = src[2] * a / 255;
|
||||
dst.Alpha() = a;
|
||||
|
||||
#else
|
||||
// Other platforms store bitmaps with straight alpha.
|
||||
dst.Alpha() = a;
|
||||
if ( a )
|
||||
{
|
||||
dst.Red() = src[0];
|
||||
dst.Green() = src[1];
|
||||
dst.Blue() = src[2];
|
||||
}
|
||||
else
|
||||
// A more canonical form for completely transparent pixels.
|
||||
dst.Red() = dst.Green() = dst.Blue() = 0;
|
||||
#endif
|
||||
++dst;
|
||||
src += 4;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1659,11 +1659,11 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||
// with alpha in the upper 8 bits, then red, then green, then
|
||||
// blue. The 32-bit quantities are stored native-endian.
|
||||
// Pre-multiplied alpha is used.
|
||||
#if defined (__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
unsigned char alpha = hasAlpha ? p.Alpha() : wxALPHA_OPAQUE;
|
||||
// MSW, OSX and Qt bitmap pixel bits are already premultiplied.
|
||||
// Bitmap pixel bits are already premultiplied.
|
||||
*data = (alpha << 24 | p.Red() << 16 | p.Green() << 8 | p.Blue());
|
||||
#else // !__WXMSW__ , !__WXOSX__ , !__WXQT__
|
||||
#else // !wxHAS_PREMULTIPLIED_ALPHA
|
||||
// We always have alpha, but we need to premultiply it.
|
||||
unsigned char alpha = p.Alpha();
|
||||
if (alpha == wxALPHA_TRANSPARENT)
|
||||
|
|
@ -1673,7 +1673,7 @@ wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitm
|
|||
| Premultiply(alpha, p.Red()) << 16
|
||||
| Premultiply(alpha, p.Green()) << 8
|
||||
| Premultiply(alpha, p.Blue()));
|
||||
#endif // __WXMSW__, __WXOSX__, __WXQT__ / !__WXMSW__, !__WXOSX__, !__WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA / !wxHAS_PREMULTIPLIED_ALPHA
|
||||
++data;
|
||||
++p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -392,7 +392,7 @@ void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesi
|
|||
hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
|
||||
}
|
||||
|
||||
#if defined(__WXMSW__) || defined(__WXMAC__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
#define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
|
||||
#else
|
||||
#define wxPy_premultiply(p, a) (p)
|
||||
|
|
|
|||
|
|
@ -253,12 +253,12 @@ TEST_CASE("BitmapTestCase::ToImage", "[bitmap][image][convertto]")
|
|||
const wxColour clrBg(*wxGREEN);
|
||||
const unsigned char alpha = 92;
|
||||
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
const wxColour clrFgAlpha(((clrFg.Red() * alpha) + 127) / 255, ((clrFg.Green() * alpha) + 127) / 255, ((clrFg.Blue() * alpha) + 127) / 255);
|
||||
#else
|
||||
const wxColour clrFgAlpha(clrFg);
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
|
||||
wxAlphaPixelData data(bmp);
|
||||
REQUIRE(data);
|
||||
|
|
@ -306,13 +306,13 @@ TEST_CASE("BitmapTestCase::ToImage", "[bitmap][image][convertto]")
|
|||
{
|
||||
wxColour bmpc(iBmp.Red(), iBmp.Green(), iBmp.Blue(), iBmp.Alpha());
|
||||
wxColour imgc(image.GetRed(x, y), image.GetGreen(x, y), image.GetBlue(x, y), image.GetAlpha(x,y));
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// Premultiplied values
|
||||
unsigned char r = ((imgc.Red() * imgc.Alpha()) + 127) / 255;
|
||||
unsigned char g = ((imgc.Green() * imgc.Alpha()) + 127) / 255;
|
||||
unsigned char b = ((imgc.Blue() * imgc.Alpha()) + 127) / 255;
|
||||
imgc.Set(r, g, b, imgc.Alpha());
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
CHECK_EQUAL_COLOUR_RGBA(imgc, bmpc);
|
||||
}
|
||||
rowStartBmp.OffsetY(dataBmp, 1);
|
||||
|
|
@ -330,12 +330,12 @@ TEST_CASE("BitmapTestCase::ToImage", "[bitmap][image][convertto]")
|
|||
const wxColour clrFg(*wxCYAN);
|
||||
const wxColour clrBg(*wxGREEN);
|
||||
const unsigned char alpha = 92;
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
const wxColour clrFgAlpha(((clrFg.Red() * alpha) + 127) / 255, ((clrFg.Green() * alpha) + 127) / 255, ((clrFg.Blue() * alpha) + 127) / 255);
|
||||
#else
|
||||
const wxColour clrFgAlpha(clrFg);
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
|
||||
wxAlphaPixelData data(bmp);
|
||||
REQUIRE(data);
|
||||
|
|
@ -412,13 +412,13 @@ TEST_CASE("BitmapTestCase::ToImage", "[bitmap][image][convertto]")
|
|||
wxColour imgc(image.GetRed(x, y), image.GetGreen(x, y), image.GetBlue(x, y), image.GetAlpha(x,y));
|
||||
if ( maskc == *wxWHITE )
|
||||
{
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// Premultiplied values
|
||||
unsigned char r = ((imgc.Red() * imgc.Alpha()) + 127) / 255;
|
||||
unsigned char g = ((imgc.Green() * imgc.Alpha()) + 127) / 255;
|
||||
unsigned char b = ((imgc.Blue() * imgc.Alpha()) + 127) / 255;
|
||||
imgc.Set(r, g, b, imgc.Alpha());
|
||||
#endif // __WXMSW__ || __WXOSX || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
CHECK_EQUAL_COLOUR_RGBA(imgc, bmpc);
|
||||
unmaskedPixelsCount++;
|
||||
}
|
||||
|
|
@ -545,13 +545,13 @@ TEST_CASE("BitmapTestCase::FromImage", "[bitmap][image][convertfrom]")
|
|||
{
|
||||
wxColour bmpc(iBmp.Red(), iBmp.Green(), iBmp.Blue(), iBmp.Alpha());
|
||||
wxColour imgc(img.GetRed(x, y), img.GetGreen(x, y), img.GetBlue(x, y), img.GetAlpha(x, y));
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// Premultiplied values
|
||||
unsigned char r = ((imgc.Red() * imgc.Alpha()) + 127) / 255;
|
||||
unsigned char g = ((imgc.Green() * imgc.Alpha()) + 127) / 255;
|
||||
unsigned char b = ((imgc.Blue() * imgc.Alpha()) + 127) / 255;
|
||||
imgc.Set(r, g, b, imgc.Alpha());
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
CHECK_EQUAL_COLOUR_RGBA(bmpc, imgc);
|
||||
}
|
||||
rowStartBmp.OffsetY(dataBmp, 1);
|
||||
|
|
@ -596,23 +596,23 @@ TEST_CASE("BitmapTestCase::FromImage", "[bitmap][image][convertfrom]")
|
|||
wxColour bmpc(iBmp.Red(), iBmp.Green(), iBmp.Blue(), iBmp.Alpha());
|
||||
wxColour maskc(iMask.Red(), iMask.Green(), iMask.Blue());
|
||||
wxColour imgc(img.GetRed(x, y), img.GetGreen(x, y), img.GetBlue(x, y), img.GetAlpha(x, y));
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// Premultiplied values
|
||||
unsigned char r = ((imgc.Red() * imgc.Alpha()) + 127) / 255;
|
||||
unsigned char g = ((imgc.Green() * imgc.Alpha()) + 127) / 255;
|
||||
unsigned char b = ((imgc.Blue() * imgc.Alpha()) + 127) / 255;
|
||||
imgc.Set(r, g, b, imgc.Alpha());
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
CHECK_EQUAL_COLOUR_RGBA(bmpc, imgc);
|
||||
|
||||
wxColour c = maskc == *wxWHITE ? fillCol : maskCol;
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// Premultiplied values
|
||||
r = ((c.Red() * imgc.Alpha()) + 127) / 255;
|
||||
g = ((c.Green() * imgc.Alpha()) + 127) / 255;
|
||||
b = ((c.Blue() * imgc.Alpha()) + 127) / 255;
|
||||
c.Set(r, g, b);
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
CHECK_EQUAL_COLOUR_RGB(bmpc, c);
|
||||
}
|
||||
rowStartBmp.OffsetY(dataBmp, 1);
|
||||
|
|
@ -810,12 +810,12 @@ TEST_CASE("BitmapTestCase::DrawAlpha", "[bitmap][draw][alpha]")
|
|||
const wxColour clrBg(*wxGREEN);
|
||||
const unsigned char alpha = 92;
|
||||
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
const wxColour clrFgAlpha(((clrFg.Red() * alpha) + 127) / 255, ((clrFg.Green() * alpha) + 127) / 255, ((clrFg.Blue() * alpha) + 127) / 255);
|
||||
#else
|
||||
const wxColour clrFgAlpha(clrFg);
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
|
||||
// Bitmap to be drawn
|
||||
wxBitmap bmp(w, h, 32);
|
||||
|
|
@ -873,7 +873,7 @@ TEST_CASE("BitmapTestCase::DrawAlpha", "[bitmap][draw][alpha]")
|
|||
p1.OffsetX(data24, w / 4); // left side is opaque
|
||||
ASSERT_EQUAL_COLOUR_RGB(p1, clrFg);
|
||||
p1.OffsetX(data24, w / 2); // right side is with alpha
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
ASSERT_EQUAL_RGB(p1, clrFgAlpha.Red() + (clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Green() + (clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
|
|
@ -882,7 +882,7 @@ TEST_CASE("BitmapTestCase::DrawAlpha", "[bitmap][draw][alpha]")
|
|||
ASSERT_EQUAL_RGB(p1, (clrFg.Red() * alpha + clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Green() * alpha + clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Blue() * alpha + clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
// Drawing the bitmap on 32 bpp xRGB target
|
||||
|
|
@ -906,10 +906,16 @@ TEST_CASE("BitmapTestCase::DrawAlpha", "[bitmap][draw][alpha]")
|
|||
p2.OffsetX(data32, w / 4); // left side is opaque
|
||||
ASSERT_EQUAL_COLOUR_RGB(p2, clrFg);
|
||||
p2.OffsetX(data32, w / 2); // right side is with alpha
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
ASSERT_EQUAL_RGB(p2, clrFgAlpha.Red() + (clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Green() + (clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Blue() + (clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#else
|
||||
ASSERT_EQUAL_RGB(p2, (clrFg.Red() * alpha + clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Green() * alpha + clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Blue() * alpha + clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
}
|
||||
|
||||
|
|
@ -925,12 +931,12 @@ TEST_CASE("BitmapTestCase::DrawAlphaWithMask", "[bitmap][draw][alpha][withmask]"
|
|||
const wxColour clrBg(*wxGREEN);
|
||||
const unsigned char alpha = 92;
|
||||
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
const wxColour clrFgAlpha(((clrFg.Red() * alpha) + 127) / 255, ((clrFg.Green() * alpha) + 127) / 255, ((clrFg.Blue() * alpha) + 127) / 255);
|
||||
#else
|
||||
const wxColour clrFgAlpha(clrFg);
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
|
||||
// Bitmap with mask to be drawn
|
||||
wxBitmap bmp(w, h, 32);
|
||||
|
|
@ -993,7 +999,7 @@ TEST_CASE("BitmapTestCase::DrawAlphaWithMask", "[bitmap][draw][alpha][withmask]"
|
|||
p1.OffsetX(data24, w / 4); // drawn area - left side opaque
|
||||
ASSERT_EQUAL_COLOUR_RGB(p1, clrFg);
|
||||
p1.OffsetX(data24, w / 2); // drawn area - right side with alpha
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
ASSERT_EQUAL_RGB(p1, clrFgAlpha.Red() + (clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Green() + (clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
|
|
@ -1002,7 +1008,7 @@ TEST_CASE("BitmapTestCase::DrawAlphaWithMask", "[bitmap][draw][alpha][withmask]"
|
|||
ASSERT_EQUAL_RGB(p1, (clrFg.Red() * alpha + clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Green() * alpha + clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Blue() * alpha + clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
p1 = rowStart1;
|
||||
p1.OffsetY(data24, h / 2);
|
||||
p1.OffsetX(data24, w / 4); // masked area - left side
|
||||
|
|
@ -1033,7 +1039,7 @@ TEST_CASE("BitmapTestCase::DrawAlphaWithMask", "[bitmap][draw][alpha][withmask]"
|
|||
p1.OffsetX(data24, w / 4); // left upper side opaque
|
||||
ASSERT_EQUAL_COLOUR_RGB(p1, clrFg);
|
||||
p1.OffsetX(data24, w / 2); // right upper side with alpha
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
ASSERT_EQUAL_RGB(p1, clrFgAlpha.Red() + (clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Green() + (clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
|
|
@ -1042,13 +1048,13 @@ TEST_CASE("BitmapTestCase::DrawAlphaWithMask", "[bitmap][draw][alpha][withmask]"
|
|||
ASSERT_EQUAL_RGB(p1, (clrFg.Red() * alpha + clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Green() * alpha + clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Blue() * alpha + clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
p1 = rowStart1;
|
||||
p1.OffsetY(data24, h / 2);
|
||||
p1.OffsetX(data24, w / 4); // left lower side - same colour as upper
|
||||
ASSERT_EQUAL_COLOUR_RGB(p1, clrFg);
|
||||
p1.OffsetX(data24, w / 2); // right lower side - same colour as upper
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
ASSERT_EQUAL_RGB(p1, clrFgAlpha.Red() + (clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Green() + (clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
|
|
@ -1057,7 +1063,7 @@ TEST_CASE("BitmapTestCase::DrawAlphaWithMask", "[bitmap][draw][alpha][withmask]"
|
|||
ASSERT_EQUAL_RGB(p1, (clrFg.Red() * alpha + clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Green() * alpha + clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Blue() * alpha + clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
}
|
||||
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
|
|
@ -1084,10 +1090,16 @@ TEST_CASE("BitmapTestCase::DrawAlphaWithMask", "[bitmap][draw][alpha][withmask]"
|
|||
p2.OffsetX(data32, w / 4); // drawn area - left side opaque
|
||||
ASSERT_EQUAL_COLOUR_RGB(p2, clrFg);
|
||||
p2.OffsetX(data32, w / 2); // drawn area - right side with alpha
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
ASSERT_EQUAL_RGB(p2, clrFgAlpha.Red() + (clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Green() + (clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Blue() + (clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#else
|
||||
ASSERT_EQUAL_RGB(p2, (clrFg.Red() * alpha + clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Green() * alpha + clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Blue() * alpha + clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
p2 = rowStart2;
|
||||
p2.OffsetY(data32, h / 2);
|
||||
p2.OffsetX(data32, w / 4); // masked area - left side
|
||||
|
|
@ -1119,19 +1131,31 @@ TEST_CASE("BitmapTestCase::DrawAlphaWithMask", "[bitmap][draw][alpha][withmask]"
|
|||
p2.OffsetX(data32, w / 4); // left upper side opaque
|
||||
ASSERT_EQUAL_COLOUR_RGB(p2, clrFg);
|
||||
p2.OffsetX(data32, w / 2); // right upper side with alpha
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
ASSERT_EQUAL_RGB(p2, clrFgAlpha.Red() + (clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Green() + (clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Blue() + (clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#else
|
||||
ASSERT_EQUAL_RGB(p2, (clrFg.Red() * alpha + clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Green() * alpha + clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Blue() * alpha + clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
p2 = rowStart2;
|
||||
p2.OffsetY(data32, h / 2);
|
||||
p2.OffsetX(data32, w / 4); // left lower side - same colour as upper
|
||||
ASSERT_EQUAL_COLOUR_RGB(p2, clrFg);
|
||||
p2.OffsetX(data32, w / 2); // right lower side - same colour as upper
|
||||
// premultiplied values
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
ASSERT_EQUAL_RGB(p2, clrFgAlpha.Red() + (clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Green() + (clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
clrFgAlpha.Blue() + (clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#else
|
||||
ASSERT_EQUAL_RGB(p2, (clrFg.Red() * alpha + clrBg.Red() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Green() * alpha + clrBg.Green() * (255 - alpha) + 127) / 255,
|
||||
(clrFg.Blue() * alpha + clrBg.Blue() * (255 - alpha) + 127) / 255);
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
}
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
}
|
||||
|
|
@ -1388,12 +1412,12 @@ TEST_CASE("BitmapTestCase::SubBitmapAlphaWithMask", "[bitmap][subbitmap][alpha][
|
|||
const wxColour clrLeft(*wxCYAN);
|
||||
const unsigned char alpha = 92;
|
||||
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
const wxColour clrRight(((clrLeft.Red() * alpha) + 127) / 255, ((clrLeft.Green() * alpha) + 127) / 255, ((clrLeft.Blue() * alpha) + 127) / 255, alpha);
|
||||
#else
|
||||
const wxColour clrRight(clrLeft.Red(), clrLeft.Green(), clrLeft.Blue(), alpha);
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
|
||||
wxBitmap bmp(w, h, 32);
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__)
|
||||
|
|
|
|||
|
|
@ -378,6 +378,29 @@ TEST_CASE("BitmapBundle::FromSVG", "[bmpbundle][svg]")
|
|||
CHECK( b.GetBitmap(wxSize(16, 16)).GetSize() == wxSize(16, 16) );
|
||||
}
|
||||
|
||||
TEST_CASE("BitmapBundle::FromSVG-alpha", "[bmpbundle][svg][alpha]")
|
||||
{
|
||||
static const char svg_data[] =
|
||||
"<svg viewBox=\"0 0 100 100\">"
|
||||
"<line x1=\"0\" y1=\"0\" x2=\"100%\" y2=\"100%\" stroke=\"#3f7fff\" stroke-width=\"71%\"/>"
|
||||
"</svg>"
|
||||
;
|
||||
|
||||
wxBitmapBundle b = wxBitmapBundle::FromSVG(svg_data, wxSize(2, 2));
|
||||
REQUIRE( b.IsOk() );
|
||||
|
||||
wxImage img = b.GetBitmap(wxDefaultSize).ConvertToImage();
|
||||
REQUIRE( img.HasAlpha() );
|
||||
// Check that anti-aliased edge at 50% alpha round-trips (after possibly
|
||||
// premultiplied storage in wxBitmap) to substantially original straight
|
||||
// alpha pixel values in wxImage, allowing for roundoff error.
|
||||
CHECK( (int)img.GetRed(0, 1) >= 0x3c );
|
||||
CHECK( (int)img.GetRed(0, 1) <= 0x3f );
|
||||
CHECK( (int)img.GetGreen(0, 1) >= 0x7c );
|
||||
CHECK( (int)img.GetGreen(0, 1) <= 0x7f);
|
||||
CHECK( (int)img.GetBlue(0, 1) == 0xff );
|
||||
}
|
||||
|
||||
TEST_CASE("BitmapBundle::FromSVGFile", "[bmpbundle][svg][file]")
|
||||
{
|
||||
const wxSize size(20, 20); // completely arbitrary
|
||||
|
|
|
|||
|
|
@ -101,12 +101,12 @@ wxBitmap CreateBitmapRGBA(int w, int h, bool withMask)
|
|||
const wxColour clrBg(*wxGREEN);
|
||||
const unsigned char alpha = 51;
|
||||
|
||||
#if defined(__WXMSW__) || defined(__WXOSX__) || defined(__WXQT__)
|
||||
#ifdef wxHAS_PREMULTIPLIED_ALPHA
|
||||
// premultiplied values
|
||||
const wxColour clrFgAlpha(((clrFg.Red() * alpha) + 127) / 255, ((clrFg.Green() * alpha) + 127) / 255, ((clrFg.Blue() * alpha) + 127) / 255);
|
||||
#else
|
||||
const wxColour clrFgAlpha(clrFg);
|
||||
#endif // __WXMSW__ || __WXOSX__ || __WXQT__
|
||||
#endif // wxHAS_PREMULTIPLIED_ALPHA
|
||||
|
||||
wxAlphaPixelData data(bmp);
|
||||
REQUIRE(data);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue