Sfoglia il codice sorgente

LibGfx: Implement Gfx::AlphaType for SkiaPainter

Always assuming unpremultiplied color data only worked for PNGs (which
are specced as unpremultiplied) and bitmaps with alpha set to 100%.
Properly propagate the Gfx::AlphaType of a bitmap to Skia.

The reference tests were updated to reflect this change, but visually
it's practically impossible to see the difference. A new test was added
to clearly expose this issue.

Fixes #1104
Jelle Raaijmakers 11 mesi fa
parent
commit
bd55e85027

+ 12 - 0
Tests/LibWeb/Screenshot/canvas-unpremultiplied-image.html

@@ -0,0 +1,12 @@
+<link rel="match" href="reference/canvas-unpremultiplied-image-ref.html" />
+<script type="module">
+const canvas = document.querySelector('#canvas');
+canvas.width = 100;
+canvas.height = 100;
+const ctx = canvas.getContext('2d');
+
+const img = new Image();
+img.addEventListener('load', () => ctx.drawImage(img, 25, 25, 50, 50));
+img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQIW2P43wAAAoEBgD2oaNcAAAAASUVORK5CYII=';
+</script>
+<canvas id="canvas" style="background-color: #f00"></canvas>

BIN
Tests/LibWeb/Screenshot/images/canvas-arcs-and-ellipses-ref.png


BIN
Tests/LibWeb/Screenshot/images/canvas-implict-moves-and-lines-ref.png


BIN
Tests/LibWeb/Screenshot/images/canvas-path-rect-ref.png


BIN
Tests/LibWeb/Screenshot/images/canvas-text-ref.png


BIN
Tests/LibWeb/Screenshot/images/canvas-unpremultiplied-image-ref.png


+ 9 - 0
Tests/LibWeb/Screenshot/reference/canvas-unpremultiplied-image-ref.html

@@ -0,0 +1,9 @@
+<style>
+    * {
+        margin: 0;
+    }
+    body {
+        background-color: white;
+    }
+</style>
+<img src="../images/canvas-unpremultiplied-image-ref.png">

+ 29 - 17
Userland/Libraries/LibGfx/PainterSkia.cpp

@@ -28,6 +28,33 @@
 
 
 namespace Gfx {
 namespace Gfx {
 
 
+static SkColorType to_skia_color_type(Gfx::BitmapFormat format)
+{
+    switch (format) {
+    case Gfx::BitmapFormat::Invalid:
+        return kUnknown_SkColorType;
+    case Gfx::BitmapFormat::BGRA8888:
+    case Gfx::BitmapFormat::BGRx8888:
+        return kBGRA_8888_SkColorType;
+    case Gfx::BitmapFormat::RGBA8888:
+        return kRGBA_8888_SkColorType;
+    default:
+        return kUnknown_SkColorType;
+    }
+}
+
+static SkAlphaType to_skia_alpha_type(Gfx::AlphaType alpha_type)
+{
+    switch (alpha_type) {
+    case AlphaType::Premultiplied:
+        return kPremul_SkAlphaType;
+    case AlphaType::Unpremultiplied:
+        return kUnpremul_SkAlphaType;
+    default:
+        VERIFY_NOT_REACHED();
+    }
+}
+
 struct PainterSkia::Impl {
 struct PainterSkia::Impl {
     NonnullRefPtr<Gfx::Bitmap> gfx_bitmap;
     NonnullRefPtr<Gfx::Bitmap> gfx_bitmap;
     OwnPtr<SkBitmap> sk_bitmap;
     OwnPtr<SkBitmap> sk_bitmap;
@@ -37,7 +64,7 @@ struct PainterSkia::Impl {
         : gfx_bitmap(move(target_bitmap))
         : gfx_bitmap(move(target_bitmap))
     {
     {
         sk_bitmap = make<SkBitmap>();
         sk_bitmap = make<SkBitmap>();
-        SkImageInfo info = SkImageInfo::Make(gfx_bitmap->width(), gfx_bitmap->height(), kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
+        SkImageInfo info = SkImageInfo::Make(gfx_bitmap->width(), gfx_bitmap->height(), to_skia_color_type(gfx_bitmap->format()), to_skia_alpha_type(gfx_bitmap->alpha_type()));
         sk_bitmap->installPixels(info, gfx_bitmap->scanline(0), gfx_bitmap->pitch());
         sk_bitmap->installPixels(info, gfx_bitmap->scanline(0), gfx_bitmap->pitch());
 
 
         sk_canvas = make<SkCanvas>(*sk_bitmap);
         sk_canvas = make<SkCanvas>(*sk_bitmap);
@@ -109,25 +136,10 @@ static SkSamplingOptions to_skia_sampling_options(Gfx::ScalingMode scaling_mode)
     }
     }
 }
 }
 
 
-static SkColorType to_skia_color_type(Gfx::BitmapFormat format)
-{
-    switch (format) {
-    case Gfx::BitmapFormat::Invalid:
-        return kUnknown_SkColorType;
-    case Gfx::BitmapFormat::BGRA8888:
-    case Gfx::BitmapFormat::BGRx8888:
-        return kBGRA_8888_SkColorType;
-    case Gfx::BitmapFormat::RGBA8888:
-        return kRGBA_8888_SkColorType;
-    default:
-        return kUnknown_SkColorType;
-    }
-}
-
 void PainterSkia::draw_bitmap(Gfx::FloatRect const& dst_rect, Gfx::Bitmap const& src_bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode, float global_alpha)
 void PainterSkia::draw_bitmap(Gfx::FloatRect const& dst_rect, Gfx::Bitmap const& src_bitmap, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode, float global_alpha)
 {
 {
     SkBitmap sk_bitmap;
     SkBitmap sk_bitmap;
-    SkImageInfo info = SkImageInfo::Make(src_bitmap.width(), src_bitmap.height(), to_skia_color_type(src_bitmap.format()), kUnpremul_SkAlphaType);
+    SkImageInfo info = SkImageInfo::Make(src_bitmap.width(), src_bitmap.height(), to_skia_color_type(src_bitmap.format()), to_skia_alpha_type(src_bitmap.alpha_type()));
     sk_bitmap.installPixels(info, const_cast<void*>(static_cast<void const*>(src_bitmap.scanline(0))), src_bitmap.pitch());
     sk_bitmap.installPixels(info, const_cast<void*>(static_cast<void const*>(src_bitmap.scanline(0))), src_bitmap.pitch());
 
 
     SkPaint paint;
     SkPaint paint;