83 lines
2.7 KiB
C++
83 lines
2.7 KiB
C++
|
// Copyright (c) 2019 GitHub, Inc.
|
||
|
// Use of this source code is governed by the MIT license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#include "shell/browser/ui/gtk_util.h"
|
||
|
|
||
|
#include <gdk/gdk.h>
|
||
|
#include <gtk/gtk.h>
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#include "third_party/skia/include/core/SkBitmap.h"
|
||
|
#include "third_party/skia/include/core/SkColor.h"
|
||
|
#include "third_party/skia/include/core/SkUnPreMultiply.h"
|
||
|
|
||
|
namespace gtk_util {
|
||
|
|
||
|
// Copied from L40-L55 in
|
||
|
// https://cs.chromium.org/chromium/src/chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.cc
|
||
|
#if GTK_CHECK_VERSION(3, 90, 0)
|
||
|
// GTK stock items have been deprecated. The docs say to switch to using the
|
||
|
// strings "_Open", etc. However this breaks i18n. We could supply our own
|
||
|
// internationalized strings, but the "_" in these strings is significant: it's
|
||
|
// the keyboard shortcut to select these actions. TODO: Provide
|
||
|
// internationalized strings when GTK provides support for it.
|
||
|
const char* const kCancelLabel = "_Cancel";
|
||
|
const char* const kNoLabel = "_No";
|
||
|
const char* const kOkLabel = "_OK";
|
||
|
const char* const kOpenLabel = "_Open";
|
||
|
const char* const kSaveLabel = "_Save";
|
||
|
const char* const kYesLabel = "_Yes";
|
||
|
#else
|
||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||
|
const char* const kCancelLabel = GTK_STOCK_CANCEL;
|
||
|
const char* const kNoLabel = GTK_STOCK_NO;
|
||
|
const char* const kOkLabel = GTK_STOCK_OK;
|
||
|
const char* const kOpenLabel = GTK_STOCK_OPEN;
|
||
|
const char* const kSaveLabel = GTK_STOCK_SAVE;
|
||
|
const char* const kYesLabel = GTK_STOCK_YES;
|
||
|
G_GNUC_END_IGNORE_DEPRECATIONS
|
||
|
#endif
|
||
|
|
||
|
GdkPixbuf* GdkPixbufFromSkBitmap(const SkBitmap& bitmap) {
|
||
|
if (bitmap.isNull())
|
||
|
return nullptr;
|
||
|
|
||
|
int width = bitmap.width();
|
||
|
int height = bitmap.height();
|
||
|
|
||
|
GdkPixbuf* pixbuf =
|
||
|
gdk_pixbuf_new(GDK_COLORSPACE_RGB, // The only colorspace gtk supports.
|
||
|
TRUE, // There is an alpha channel.
|
||
|
8, width, height);
|
||
|
|
||
|
// SkBitmaps are premultiplied, we need to unpremultiply them.
|
||
|
const int kBytesPerPixel = 4;
|
||
|
uint8_t* divided = gdk_pixbuf_get_pixels(pixbuf);
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
} // namespace gtk_util
|