GAL: Add transparency for bitmaps and Cairo draw
Bitmaps loaded via wx can contain alpha channels. We utilize underlying routines to correctly map the alpha. This also standardizes the Cairo alpha calls to ensure correct display in Fallback for partially transparent highlights Fixes: lp:1809845 * https://bugs.launchpad.net/kicad/+bug/1809845
This commit is contained in:
parent
e8333633fe
commit
3a3bbbb545
|
@ -294,7 +294,7 @@ void CAIRO_GAL_BASE::DrawBitmap( const BITMAP_BASE& aBitmap )
|
|||
cairo_translate( currentContext, -w/2, -h/2 );
|
||||
|
||||
cairo_new_path( currentContext );
|
||||
cairo_surface_t* image = cairo_image_surface_create( CAIRO_FORMAT_RGB24, w, h );
|
||||
cairo_surface_t* image = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, w, h );
|
||||
cairo_surface_flush( image );
|
||||
|
||||
unsigned char* pix_buffer = cairo_image_surface_get_data( image );
|
||||
|
@ -302,8 +302,8 @@ void CAIRO_GAL_BASE::DrawBitmap( const BITMAP_BASE& aBitmap )
|
|||
auto bm_pix_buffer = (( BITMAP_BASE&)aBitmap).GetImageData();
|
||||
|
||||
// Copy the source bitmap to the cairo bitmap buffer.
|
||||
// In cairo bitmap buffer, a RGB24 bitmap is a RGB pixel packed into a uint_32
|
||||
// 24 low bits only are used.
|
||||
// In cairo bitmap buffer, a ARGB32 bitmap is an ARGB pixel packed into a uint_32
|
||||
// 24 low bits only are used for color, top 8 are transparency.
|
||||
for( int row = 0; row < h; row++ )
|
||||
{
|
||||
for( int col = 0; col < w; col++ )
|
||||
|
@ -313,6 +313,11 @@ void CAIRO_GAL_BASE::DrawBitmap( const BITMAP_BASE& aBitmap )
|
|||
pixel += bm_pix_buffer->GetGreen( col, row ) << 8;
|
||||
pixel += bm_pix_buffer->GetBlue( col, row );
|
||||
|
||||
if( bm_pix_buffer->HasAlpha() )
|
||||
pixel += bm_pix_buffer->GetAlpha( col, row ) << 24;
|
||||
else
|
||||
pixel += ( 0xff << 24 );
|
||||
|
||||
// Write the pixel to the cairo image buffer:
|
||||
uint32_t* pix_ptr = (uint32_t*) pix_buffer;
|
||||
*pix_ptr = pixel;
|
||||
|
@ -618,13 +623,13 @@ void CAIRO_GAL_BASE::DrawGroup( int aGroupNumber )
|
|||
|
||||
|
||||
case CMD_STROKE_PATH:
|
||||
cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g, strokeColor.b );
|
||||
cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
|
||||
cairo_append_path( currentContext, it->cairoPath );
|
||||
cairo_stroke( currentContext );
|
||||
break;
|
||||
|
||||
case CMD_FILL_PATH:
|
||||
cairo_set_source_rgb( currentContext, fillColor.r, fillColor.g, fillColor.b );
|
||||
cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b, strokeColor.a );
|
||||
cairo_append_path( currentContext, it->cairoPath );
|
||||
cairo_fill( currentContext );
|
||||
break;
|
||||
|
@ -806,14 +811,14 @@ void CAIRO_GAL_BASE::storePath()
|
|||
{
|
||||
if( isFillEnabled )
|
||||
{
|
||||
cairo_set_source_rgb( currentContext, fillColor.r, fillColor.g, fillColor.b );
|
||||
cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b, fillColor.a );
|
||||
cairo_fill_preserve( currentContext );
|
||||
}
|
||||
|
||||
if( isStrokeEnabled )
|
||||
{
|
||||
cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g,
|
||||
strokeColor.b );
|
||||
cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g,
|
||||
strokeColor.b, strokeColor.a );
|
||||
cairo_stroke_preserve( currentContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,38 +131,44 @@ GLuint GL_BITMAP_CACHE::cacheBitmap( const BITMAP_BASE* aBitmap )
|
|||
bmp.w = aBitmap->GetSizePixels().x;
|
||||
bmp.h = aBitmap->GetSizePixels().y;
|
||||
|
||||
// There are draw issues (incorrect rendering) with some w values.
|
||||
// It happens when the w value is not a multiple of 4
|
||||
// so we use only a sub image with a modified width
|
||||
bmp.w -= bmp.w % 4;
|
||||
// The bitmap size needs to be a multiple of 4.
|
||||
// This is easiest to achieve by ensuring that each row
|
||||
// has a multiple of 4 pixels
|
||||
int extra_w = bmp.w % 4;
|
||||
|
||||
if( extra_w )
|
||||
extra_w = 4 - extra_w;
|
||||
|
||||
GLuint textureID;
|
||||
glGenTextures(1, &textureID);
|
||||
|
||||
uint8_t *buf = new uint8_t [ bmp.w * bmp.h * 3];
|
||||
// make_unique initializes this to 0, so extra pixels are transparent
|
||||
auto buf = std::make_unique<uint8_t[]>( ( bmp.w + extra_w ) * bmp.h * 4 );
|
||||
auto imgData = const_cast<BITMAP_BASE*>( aBitmap )->GetImageData();
|
||||
|
||||
for( int y = 0; y < bmp.h; y++ )
|
||||
{
|
||||
for( int x = 0; x < bmp.w; x++ )
|
||||
{
|
||||
uint8_t *p = buf + ( bmp.w * y + x ) * 3;
|
||||
uint8_t *p = buf.get() + ( ( bmp.w + extra_w ) * y + x ) * 4;
|
||||
|
||||
p[0] = imgData->GetRed( x, y );
|
||||
p[1] = imgData->GetGreen( x, y );
|
||||
p[2] = imgData->GetBlue( x, y );
|
||||
|
||||
if( imgData->HasAlpha() )
|
||||
p[3] = imgData->GetAlpha( x, y );
|
||||
else
|
||||
p[3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, textureID );
|
||||
|
||||
glTexImage2D( GL_TEXTURE_2D, 0,GL_RGB, bmp.w, bmp.h, 0, GL_RGB, GL_UNSIGNED_BYTE, buf );
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, bmp.w + extra_w, bmp.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf.get() );
|
||||
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
||||
|
||||
delete [] buf;
|
||||
|
||||
bmp.id = textureID;
|
||||
|
||||
#ifndef DISABLE_BITMAP_CACHE
|
||||
|
|
Loading…
Reference in New Issue