diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp index aa81d5a9a5..9314b8573f 100644 --- a/common/gal/cairo/cairo_gal.cpp +++ b/common/gal/cairo/cairo_gal.cpp @@ -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 ); } } diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index 7a3c6ed3dd..e8b41b8023 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -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( ( bmp.w + extra_w ) * bmp.h * 4 ); auto imgData = const_cast( 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