From 1cda310bbfc45743974a8f204283d12aad20d281 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Fri, 16 Oct 2020 18:17:35 +0200 Subject: [PATCH] Attempt at a All-In-One implementation --- src/osx/core/bitmap.cpp | 118 +++++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 44 deletions(-) diff --git a/src/osx/core/bitmap.cpp b/src/osx/core/bitmap.cpp index c0f54d71a9..e1bddf920a 100644 --- a/src/osx/core/bitmap.cpp +++ b/src/osx/core/bitmap.cpp @@ -1129,66 +1129,96 @@ wxBitmap::wxBitmap(const wxImage& image, int depth, double scale) if ( bitmapRefData->IsOk()) { - // Create picture - wxImage img; - if ( image.HasMask() && !image.HasAlpha() ) - { - // takes precedence - // Since we already use 32 bpp bitmap here, we can use alpha channel - // directly and there is no reason to keep a separate mask. - img = image.Copy(); - img.InitAlpha(); + bool hasMask = image.HasMask(); + bool hasAlpha = image.HasAlpha(); + bool wantsAlpha = hasMask || hasAlpha ; - wxASSERT( !img.HasMask() ); - } - else - { - img = image; - } - bool hasAlpha = img.HasAlpha() ; + // convert this bitmap to use its alpha channel + if ( wantsAlpha ) + UseAlpha(); - if ( hasAlpha ) - UseAlpha() ; + const unsigned char *sourcePixels = image.GetData(); + unsigned char* destinationPixels = (unsigned char*) GetBitmapData()->BeginRawAccess() ; - unsigned char* destinationstart = (unsigned char*) GetBitmapData()->BeginRawAccess() ; - const unsigned char* data = img.GetData(); - if ( destinationstart != NULL && data != NULL ) + if ( destinationPixels != NULL && sourcePixels != NULL ) { - const unsigned char *alpha = hasAlpha ? img.GetAlpha() : NULL ; - for (int y = 0; y < height; destinationstart += GetBitmapData()->GetBytesPerRow(), y++) + const unsigned char *sourceAlpha = hasAlpha ? image.GetAlpha() : NULL ; + + const unsigned char mr = hasMask ? image.GetMaskRed() : 0; + const unsigned char mg = hasMask ? image.GetMaskGreen() : 0; + const unsigned char mb = hasMask ? image.GetMaskBlue() : 0; + + unsigned char* destinationRowStart = destinationPixels; + + wxMemoryBuffer maskbuf ; + int maskRowBytes = GetBestBytesPerRow( width * kMaskBytesPerPixel ); + size_t maskbufsize = maskRowBytes * height ; + + unsigned char *destinationMask = NULL; + if ( hasMask ) + destinationMask = (unsigned char * ) maskbuf.GetWriteBuf( maskbufsize ) ; + + unsigned char* destinationMaskRowStart = destinationMask; + + for (int y = 0; y < height; + destinationRowStart += GetBitmapData()->GetBytesPerRow(), + destinationMaskRowStart += hasMask ? maskRowBytes : 0, + y++) { - unsigned char * destination = destinationstart; + unsigned char * destination = destinationRowStart; + unsigned char * destinationMask = destinationMaskRowStart; for (int x = 0; x < width; x++) { - if ( hasAlpha ) - { - const unsigned char a = *alpha++; - *destination++ = a ; + bool isMasked = false; - #if wxOSX_USE_PREMULTIPLIED_ALPHA - *destination++ = ((*data++) * a + 127) / 255 ; - *destination++ = ((*data++) * a + 127) / 255 ; - *destination++ = ((*data++) * a + 127) / 255 ; - #else - *destination++ = *data++ ; - *destination++ = *data++ ; - *destination++ = *data++ ; - #endif + if ( hasMask ) + { + if ( sourcePixels[0] == mr && sourcePixels[1] == mg && sourcePixels[2] == mb ) + isMasked = true; + *destinationMask++ = isMasked ? wxIMAGE_ALPHA_TRANSPARENT : wxIMAGE_ALPHA_OPAQUE ; + } + + if ( wantsAlpha ) + { + unsigned char a; + if ( hasAlpha ) + a = *sourceAlpha++; + else + a = isMasked ? wxIMAGE_ALPHA_TRANSPARENT : wxIMAGE_ALPHA_OPAQUE; + + *destination++ = a ; +#if wxOSX_USE_PREMULTIPLIED_ALPHA + *destination++ = ((*sourcePixels++) * a + 127) / 255 ; + *destination++ = ((*sourcePixels++) * a + 127) / 255 ; + *destination++ = ((*sourcePixels++) * a + 127) / 255 ; +#else + *destination++ = *sourcePixels++ ; + *destination++ = *sourcePixels++ ; + *destination++ = *sourcePixels++ ; +#endif } else { - *destination++ = 0xFF ; - *destination++ = *data++ ; - *destination++ = *data++ ; - *destination++ = *data++ ; + *destination++ = wxIMAGE_ALPHA_OPAQUE ; + *destination++ = *sourcePixels++ ; + *destination++ = *sourcePixels++ ; + *destination++ = *sourcePixels++ ; + } } } - GetBitmapData()->EndRawAccess() ; + + if ( hasMask ) + { + maskbuf.UngetWriteBuf( maskbufsize ) ; + + wxMask* mask = new wxMask(); + mask->OSXCreate(maskbuf, width , height , maskRowBytes ) ; + + SetMask( mask ); + } } - if ( image.HasMask() ) - SetMask(new wxMask(*this, wxColour(image.GetMaskRed(), image.GetMaskGreen(), image.GetMaskBlue()))); } }