fix: -Wunsafe-buffer-usage warnings in GdkPixbufFromSkBitmap() (#43981)

* fix: -Wunsafe-buffer-usage warnings in GdkPixbufFromSkBitmap()

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: don't change previous behavior for 0-height images

Is a 0x0 image even a thing? I'm not sure; but just in case, let's
treat it the same way the previous implementation did.

Co-authored-by: Charles Kerr <charles@charleskerr.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
trop[bot] 2024-09-26 10:55:35 -05:00 committed by GitHub
parent a66e01b555
commit 328afb8a09
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -9,6 +9,7 @@
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <vector>
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
@ -68,42 +69,30 @@ const char* GetYesLabel() {
GdkPixbuf* GdkPixbufFromSkBitmap(const SkBitmap& bitmap) { GdkPixbuf* GdkPixbufFromSkBitmap(const SkBitmap& bitmap) {
if (bitmap.isNull()) if (bitmap.isNull())
return nullptr; return {};
int width = bitmap.width(); constexpr int kBytesPerPixel = 4;
int height = bitmap.height(); const auto [width, height] = bitmap.dimensions();
std::vector<uint8_t> bytes;
GdkPixbuf* pixbuf = bytes.reserve(width * height * kBytesPerPixel);
gdk_pixbuf_new(GDK_COLORSPACE_RGB, // The only colorspace gtk supports. for (int y = 0; y < height; ++y) {
TRUE, // There is an alpha channel. for (int x = 0; x < width; ++x) {
8, width, height); const SkColor pixel = bitmap.getColor(x, y);
bytes.emplace_back(SkColorGetR(pixel));
// SkBitmaps are premultiplied, we need to unpremultiply them. bytes.emplace_back(SkColorGetG(pixel));
const int kBytesPerPixel = 4; bytes.emplace_back(SkColorGetB(pixel));
uint8_t* divided = gdk_pixbuf_get_pixels(pixbuf); bytes.emplace_back(SkColorGetA(pixel));
for (int y = 0, i = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
uint32_t pixel = bitmap.getAddr32(0, y)[x];
int alpha = SkColorGetA(pixel);
if (alpha != 0 && alpha != 255) {
SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel);
divided[i + 0] = SkColorGetR(unmultiplied);
divided[i + 1] = SkColorGetG(unmultiplied);
divided[i + 2] = SkColorGetB(unmultiplied);
divided[i + 3] = alpha;
} else {
divided[i + 0] = SkColorGetR(pixel);
divided[i + 1] = SkColorGetG(pixel);
divided[i + 2] = SkColorGetB(pixel);
divided[i + 3] = alpha;
}
i += kBytesPerPixel;
} }
} }
return pixbuf; constexpr GdkColorspace kColorspace = GDK_COLORSPACE_RGB;
constexpr gboolean kHasAlpha = true;
constexpr int kBitsPerSample = 8;
return gdk_pixbuf_new_from_bytes(
g_bytes_new(std::data(bytes), std::size(bytes)), kColorspace, kHasAlpha,
kBitsPerSample, width, height,
gdk_pixbuf_calculate_rowstride(kColorspace, kHasAlpha, kBitsPerSample,
width, height));
} }
} // namespace gtk_util } // namespace gtk_util