mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-16 04:13:50 +00:00
Merge branch 'main' into beta
This commit is contained in:
commit
ff5afba6ae
@ -63,7 +63,7 @@
|
||||
text="@.show_home" />
|
||||
<check id="expand_menubar_on_mouseover"
|
||||
text="@.expand_menu_bar_items_on_mouseover"
|
||||
tooltip="@.expand_menu_bar_items_on_mouseover" />
|
||||
tooltip="@.expand_menu_bar_items_on_mouseover_tooltip" />
|
||||
<check id="color_bar_entries_separator"
|
||||
text="@.color_bar_entries_separator"
|
||||
tooltip="@.color_bar_entries_separator"
|
||||
|
2
laf
2
laf
@ -1 +1 @@
|
||||
Subproject commit e600f3be164c6975ed048f7043b779b11c6aa876
|
||||
Subproject commit 8b0422877a39d655bf6a405eb2e2985763b150da
|
@ -487,11 +487,14 @@ public:
|
||||
|
||||
selectScalingItems();
|
||||
|
||||
if ((int(os::instance()->capabilities()) &
|
||||
int(os::Capabilities::GpuAccelerationSwitch)) == int(os::Capabilities::GpuAccelerationSwitch)) {
|
||||
#ifdef _DEBUG // TODO enable this on Release when Aseprite supports
|
||||
// GPU-acceleration properly
|
||||
if (os::instance()->hasCapability(os::Capabilities::GpuAccelerationSwitch)) {
|
||||
gpuAcceleration()->setSelected(m_pref.general.gpuAcceleration());
|
||||
}
|
||||
else {
|
||||
else
|
||||
#endif
|
||||
{
|
||||
gpuAcceleration()->setVisible(false);
|
||||
}
|
||||
|
||||
|
@ -43,22 +43,6 @@ using namespace gfx;
|
||||
|
||||
namespace {
|
||||
|
||||
gfx::Color gridColor1()
|
||||
{
|
||||
if (ui::is_ui_thread() && current_editor)
|
||||
return color_utils::color_for_ui(current_editor->docPref().bg.color1());
|
||||
else
|
||||
return gfx::rgba(128, 128, 128);
|
||||
}
|
||||
|
||||
gfx::Color gridColor2()
|
||||
{
|
||||
if (ui::is_ui_thread() && current_editor)
|
||||
return color_utils::color_for_ui(current_editor->docPref().bg.color2());
|
||||
else
|
||||
return gfx::rgba(192, 192, 192);
|
||||
}
|
||||
|
||||
void draw_checked_grid(ui::Graphics* g,
|
||||
const gfx::Rect& rc,
|
||||
const gfx::Size& tile,
|
||||
@ -93,11 +77,27 @@ void draw_checked_grid(ui::Graphics* g,
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
gfx::Color grid_color1()
|
||||
{
|
||||
if (ui::is_ui_thread() && current_editor)
|
||||
return color_utils::color_for_ui(current_editor->docPref().bg.color1());
|
||||
else
|
||||
return gfx::rgba(128, 128, 128);
|
||||
}
|
||||
|
||||
gfx::Color grid_color2()
|
||||
{
|
||||
if (ui::is_ui_thread() && current_editor)
|
||||
return color_utils::color_for_ui(current_editor->docPref().bg.color2());
|
||||
else
|
||||
return gfx::rgba(192, 192, 192);
|
||||
}
|
||||
|
||||
void draw_checked_grid(ui::Graphics* g,
|
||||
const gfx::Rect& rc,
|
||||
const gfx::Size& tile)
|
||||
{
|
||||
draw_checked_grid(g, rc, tile, gridColor1(), gridColor2());
|
||||
draw_checked_grid(g, rc, tile, grid_color1(), grid_color2());
|
||||
}
|
||||
|
||||
void draw_checked_grid(ui::Graphics* g,
|
||||
@ -105,7 +105,7 @@ void draw_checked_grid(ui::Graphics* g,
|
||||
const gfx::Size& tile,
|
||||
DocumentPreferences& docPref)
|
||||
{
|
||||
draw_checked_grid(g, rc, tile, gridColor1(), gridColor2());
|
||||
draw_checked_grid(g, rc, tile, grid_color1(), grid_color2());
|
||||
}
|
||||
|
||||
void draw_color(ui::Graphics* g,
|
||||
@ -228,7 +228,18 @@ void draw_tile(ui::Graphics* g,
|
||||
os::SurfaceRef surface = os::instance()->makeRgbaSurface(w, h);
|
||||
convert_image_to_surface(tileImage.get(), get_current_palette(),
|
||||
surface.get(), 0, 0, 0, 0, w, h);
|
||||
g->drawRgbaSurface(surface.get(), gfx::Rect(0, 0, w, h), rc);
|
||||
|
||||
ui::Paint paint;
|
||||
paint.blendMode(os::BlendMode::SrcOver);
|
||||
|
||||
os::Sampling sampling;
|
||||
if (w > rc.w && h > rc.h) {
|
||||
sampling = os::Sampling(os::Sampling::Filter::Linear,
|
||||
os::Sampling::Mipmap::Nearest);
|
||||
}
|
||||
|
||||
g->drawSurface(surface.get(), gfx::Rect(0, 0, w, h), rc,
|
||||
os::Sampling(), &paint);
|
||||
}
|
||||
|
||||
void draw_tile_button(ui::Graphics* g,
|
||||
@ -286,8 +297,8 @@ void draw_alpha_slider(ui::Graphics* g,
|
||||
|
||||
for (int x=0; x<rc.w; ++x) {
|
||||
const int a = (255 * x / xmax);
|
||||
const doc::color_t c1 = doc::rgba_blender_normal(gridColor1(), c, a);
|
||||
const doc::color_t c2 = doc::rgba_blender_normal(gridColor2(), c, a);
|
||||
const doc::color_t c1 = doc::rgba_blender_normal(grid_color1(), c, a);
|
||||
const doc::color_t c2 = doc::rgba_blender_normal(grid_color2(), c, a);
|
||||
const int mid = rc.h/2;
|
||||
const int odd = (x / rc.h) & 1;
|
||||
g->drawVLine(
|
||||
@ -314,8 +325,8 @@ void draw_alpha_slider(os::Surface* s,
|
||||
os::Paint paint;
|
||||
for (int x=0; x<rc.w; ++x) {
|
||||
const int a = (255 * x / xmax);
|
||||
const doc::color_t c1 = doc::rgba_blender_normal(gridColor1(), c, a);
|
||||
const doc::color_t c2 = doc::rgba_blender_normal(gridColor2(), c, a);
|
||||
const doc::color_t c1 = doc::rgba_blender_normal(grid_color1(), c, a);
|
||||
const doc::color_t c2 = doc::rgba_blender_normal(grid_color2(), c, a);
|
||||
const int mid = rc.h/2;
|
||||
const int odd = (x / rc.h) & 1;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -28,6 +28,9 @@ namespace ui {
|
||||
namespace app {
|
||||
class Site;
|
||||
|
||||
gfx::Color grid_color1();
|
||||
gfx::Color grid_color2();
|
||||
|
||||
void draw_checked_grid(ui::Graphics* g,
|
||||
const gfx::Rect& rc,
|
||||
const gfx::Size& tile);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -183,8 +183,7 @@ int init_module_gui()
|
||||
// If we've created the native window with hardware acceleration,
|
||||
// now we try to do it without hardware acceleration.
|
||||
if (gpuAccel &&
|
||||
(int(os::instance()->capabilities()) &
|
||||
int(os::Capabilities::GpuAccelerationSwitch)) == int(os::Capabilities::GpuAccelerationSwitch)) {
|
||||
os::instance()->hasCapability(os::Capabilities::GpuAccelerationSwitch)) {
|
||||
if (create_main_window(false, maximized, lastError)) {
|
||||
// Disable hardware acceleration
|
||||
pref.general.gpuAcceleration(false);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "app/modules/gfx.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/util/shader_helpers.h"
|
||||
#include "base/clamp.h"
|
||||
#include "base/concurrent_queue.h"
|
||||
#include "base/scoped_value.h"
|
||||
@ -36,8 +37,16 @@
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <condition_variable>
|
||||
#include <cstdio>
|
||||
#include <thread>
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
#include "os/skia/skia_surface.h"
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
#endif
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace app::skin;
|
||||
@ -117,8 +126,14 @@ public:
|
||||
paint.color(bgColor);
|
||||
paint.style(os::Paint::Fill);
|
||||
m_canvas->drawRect(gfx::Rect(0, 0, w, h), paint);
|
||||
if (oldCanvas)
|
||||
m_canvas->drawSurface(oldCanvas.get(), 0, 0);
|
||||
if (oldCanvas) {
|
||||
m_canvas->drawSurface(
|
||||
oldCanvas.get(),
|
||||
gfx::Rect(0, 0, oldCanvas->width(), oldCanvas->height()),
|
||||
gfx::Rect(0, 0, w, h),
|
||||
os::Sampling(),
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
return m_canvas.get();
|
||||
}
|
||||
@ -218,6 +233,11 @@ private:
|
||||
|
||||
static ColorSelector::Painter painter;
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
// static
|
||||
sk_sp<SkRuntimeEffect> ColorSelector::m_alphaEffect;
|
||||
#endif
|
||||
|
||||
ColorSelector::ColorSelector()
|
||||
: Widget(kGenericWidget)
|
||||
, m_paintFlags(AllAreasFlag)
|
||||
@ -415,12 +435,88 @@ void ColorSelector::onPaint(ui::PaintEvent& ev)
|
||||
if (rc.isEmpty())
|
||||
return;
|
||||
|
||||
g->drawSurface(
|
||||
painter.getCanvas(rc.w, rc.h, theme->colors.workspace()),
|
||||
rc.x, rc.y);
|
||||
|
||||
gfx::Rect bottomBarBounds = this->bottomBarBounds();
|
||||
gfx::Rect alphaBarBounds = this->alphaBarBounds();
|
||||
|
||||
os::Surface* painterSurface = nullptr;
|
||||
|
||||
#if SK_ENABLE_SKSL // Paint with shaders
|
||||
buildEffects();
|
||||
if (m_mainEffect && m_bottomEffect && m_alphaEffect) {
|
||||
SkCanvas* canvas;
|
||||
bool isSRGB;
|
||||
// TODO compare both color spaces
|
||||
if (get_current_color_space()->isSRGB() &&
|
||||
g->getInternalSurface()->colorSpace()->isSRGB()) {
|
||||
// We can render directly in the ui::Graphics surface
|
||||
canvas = &static_cast<os::SkiaSurface*>(g->getInternalSurface())->canvas();
|
||||
isSRGB = true;
|
||||
}
|
||||
else {
|
||||
// We'll paint in the ColorSelector::Painter canvas, and so we
|
||||
// can convert color spaces.
|
||||
painterSurface = painter.getCanvas(rc.w, rc.h, theme->colors.workspace());
|
||||
canvas = &static_cast<os::SkiaSurface*>(painterSurface)->canvas();
|
||||
isSRGB = false;
|
||||
}
|
||||
|
||||
canvas->save();
|
||||
{
|
||||
SkPaint p;
|
||||
p.setStyle(SkPaint::kFill_Style);
|
||||
|
||||
// Main area
|
||||
gfx::Rect rc2(0, 0, rc.w, std::max(1, rc.h-bottomBarBounds.h-alphaBarBounds.h));
|
||||
|
||||
SkRuntimeShaderBuilder builder1(m_mainEffect);
|
||||
builder1.uniform("iRes") = SkV3{float(rc2.w), float(rc2.h), 0.0f};
|
||||
builder1.uniform("iColor") = appColor_to_SkV4(m_color);
|
||||
p.setShader(builder1.makeShader());
|
||||
|
||||
if (isSRGB)
|
||||
canvas->translate(rc.x+g->getInternalDeltaX(),
|
||||
rc.y+g->getInternalDeltaY());
|
||||
|
||||
canvas->drawRect(SkRect::MakeXYWH(0, 0, rc2.w, rc2.h), p);
|
||||
|
||||
// Bottom bar
|
||||
canvas->translate(0.0, rc2.h);
|
||||
rc2.h = bottomBarBounds.h;
|
||||
|
||||
SkRuntimeShaderBuilder builder2(m_bottomEffect);
|
||||
builder2.uniform("iRes") = SkV3{float(rc2.w), float(rc2.h), 0.0f};
|
||||
builder2.uniform("iColor") = appColor_to_SkV4(m_color);
|
||||
p.setShader(builder2.makeShader());
|
||||
|
||||
canvas->drawRect(SkRect::MakeXYWH(0, 0, rc2.w, rc2.h), p);
|
||||
|
||||
// Alpha bar
|
||||
canvas->translate(0.0, rc2.h);
|
||||
rc2.h = alphaBarBounds.h;
|
||||
|
||||
SkRuntimeShaderBuilder builder3(m_alphaEffect);
|
||||
builder3.uniform("iRes") = SkV3{float(rc2.w), float(rc2.h), 0.0f};
|
||||
builder3.uniform("iColor") = appColor_to_SkV4(m_color);
|
||||
builder3.uniform("iBg1") = gfxColor_to_SkV4(grid_color1());
|
||||
builder3.uniform("iBg2") = gfxColor_to_SkV4(grid_color2());
|
||||
p.setShader(builder3.makeShader());
|
||||
|
||||
canvas->drawRect(SkRect::MakeXYWH(0, 0, rc2.w, rc2.h), p);
|
||||
}
|
||||
canvas->restore();
|
||||
|
||||
// We already painted all areas
|
||||
m_paintFlags = 0;
|
||||
}
|
||||
else
|
||||
#endif // SK_ENABLE_SKSL
|
||||
{
|
||||
painterSurface = painter.getCanvas(rc.w, rc.h, theme->colors.workspace());
|
||||
}
|
||||
|
||||
if (painterSurface)
|
||||
g->drawSurface(painterSurface, rc.x, rc.y);
|
||||
|
||||
rc.h -= bottomBarBounds.h + alphaBarBounds.h;
|
||||
onPaintMainArea(g, rc);
|
||||
|
||||
@ -531,4 +627,56 @@ void ColorSelector::updateColorSpace()
|
||||
invalidate();
|
||||
}
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
// static
|
||||
const char* ColorSelector::getAlphaBarShader()
|
||||
{
|
||||
return R"(
|
||||
uniform half3 iRes;
|
||||
uniform half4 iColor;
|
||||
uniform half4 iBg1;
|
||||
uniform half4 iBg2;
|
||||
|
||||
half4 main(vec2 fragcoord) {
|
||||
vec2 d = (fragcoord.xy / iRes.xy);
|
||||
half4 p = (mod((fragcoord.x / iRes.y) + floor(d.y+0.5), 2.0) > 1.0) ? iBg2: iBg1;
|
||||
half4 q = iColor.rgb1;
|
||||
float a = d.x;
|
||||
return (1.0-a)*p + a*q;
|
||||
}
|
||||
)";
|
||||
}
|
||||
|
||||
void ColorSelector::buildEffects()
|
||||
{
|
||||
if (!m_mainEffect) {
|
||||
if (const char* code = getMainAreaShader())
|
||||
m_mainEffect = buildEffect(code);
|
||||
}
|
||||
|
||||
if (!m_bottomEffect) {
|
||||
if (const char* code = getBottomBarShader())
|
||||
m_bottomEffect = buildEffect(code);
|
||||
}
|
||||
|
||||
if (!m_alphaEffect) {
|
||||
if (const char* code = getAlphaBarShader())
|
||||
m_alphaEffect = buildEffect(code);
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<SkRuntimeEffect> ColorSelector::buildEffect(const char* code)
|
||||
{
|
||||
auto result = SkRuntimeEffect::MakeForShader(SkString(code));
|
||||
if (!result.errorText.isEmpty()) {
|
||||
LOG(ERROR, "Shader error: %s\n", result.errorText.c_str());
|
||||
std::printf("Shader error: %s\n", result.errorText.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
else {
|
||||
return result.effect;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -21,6 +21,13 @@
|
||||
#include <atomic>
|
||||
#include <cmath>
|
||||
|
||||
// TODO We should wrap the SkRuntimeEffect in laf-os, SkRuntimeEffect
|
||||
// and SkRuntimeShaderBuilder might change in future Skia
|
||||
// versions.
|
||||
#if SK_ENABLE_SKSL
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
#endif
|
||||
|
||||
// TODO move this to laf::base
|
||||
inline bool cs_double_diff(double a, double b) {
|
||||
return std::fabs((a)-(b)) > 0.001;
|
||||
@ -61,6 +68,8 @@ namespace app {
|
||||
void onResize(ui::ResizeEvent& ev) override;
|
||||
void onPaint(ui::PaintEvent& ev) override;
|
||||
|
||||
virtual const char* getMainAreaShader() { return nullptr; }
|
||||
virtual const char* getBottomBarShader() { return nullptr; }
|
||||
virtual app::Color getMainAreaColor(const int u, const int umax,
|
||||
const int v, const int vmax) = 0;
|
||||
virtual app::Color getBottomBarColor(const int u, const int umax) = 0;
|
||||
@ -101,6 +110,12 @@ namespace app {
|
||||
|
||||
void updateColorSpace();
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
static const char* getAlphaBarShader();
|
||||
void buildEffects();
|
||||
sk_sp<SkRuntimeEffect> buildEffect(const char* code);
|
||||
#endif
|
||||
|
||||
// Internal flag used to lock the modification of m_color.
|
||||
// E.g. When the user picks a color harmony, we don't want to
|
||||
// change the main color.
|
||||
@ -117,6 +132,13 @@ namespace app {
|
||||
ui::Timer m_timer;
|
||||
|
||||
obs::scoped_connection m_appConn;
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
// Shaders
|
||||
sk_sp<SkRuntimeEffect> m_mainEffect;
|
||||
sk_sp<SkRuntimeEffect> m_bottomEffect;
|
||||
static sk_sp<SkRuntimeEffect> m_alphaEffect;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -14,6 +14,7 @@
|
||||
#include "app/color_utils.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/util/shader_helpers.h"
|
||||
#include "base/clamp.h"
|
||||
#include "os/surface.h"
|
||||
#include "ui/graphics.h"
|
||||
@ -35,6 +36,52 @@ ColorSpectrum::ColorSpectrum()
|
||||
{
|
||||
}
|
||||
|
||||
const char* ColorSpectrum::getMainAreaShader()
|
||||
{
|
||||
#if SK_ENABLE_SKSL
|
||||
if (m_mainShader.empty()) {
|
||||
m_mainShader += "uniform half3 iRes;"
|
||||
"uniform half4 iColor;";
|
||||
m_mainShader += kRGB_to_HSL_sksl;
|
||||
m_mainShader += kHSL_to_RGB_sksl;
|
||||
m_mainShader += R"(
|
||||
half4 main(vec2 fragcoord) {
|
||||
vec2 d = fragcoord.xy / iRes.xy;
|
||||
half hue = d.x;
|
||||
half sat = rgb_to_hsl(iColor.rgb).y;
|
||||
half lit = 1.0 - d.y;
|
||||
return hsl_to_rgb(half3(hue, sat, lit)).rgb1;
|
||||
}
|
||||
)";
|
||||
}
|
||||
return m_mainShader.c_str();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* ColorSpectrum::getBottomBarShader()
|
||||
{
|
||||
#if SK_ENABLE_SKSL
|
||||
if (m_bottomShader.empty()) {
|
||||
m_bottomShader += "uniform half3 iRes;"
|
||||
"uniform half4 iColor;";
|
||||
m_bottomShader += kRGB_to_HSL_sksl;
|
||||
m_bottomShader += kHSL_to_RGB_sksl;
|
||||
m_bottomShader += R"(
|
||||
half4 main(vec2 fragcoord) {
|
||||
half s = (fragcoord.x / iRes.x);
|
||||
half3 hsl = rgb_to_hsl(iColor.rgb);
|
||||
return hsl_to_rgb(half3(hsl.x, s, hsl.z)).rgb1;
|
||||
}
|
||||
)";
|
||||
}
|
||||
return m_bottomShader.c_str();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
app::Color ColorSpectrum::getMainAreaColor(const int u, const int umax,
|
||||
const int v, const int vmax)
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -17,6 +18,8 @@ namespace app {
|
||||
ColorSpectrum();
|
||||
|
||||
protected:
|
||||
const char* getMainAreaShader() override;
|
||||
const char* getBottomBarShader() override;
|
||||
app::Color getMainAreaColor(const int u, const int umax,
|
||||
const int v, const int vmax) override;
|
||||
app::Color getBottomBarColor(const int u, const int umax) override;
|
||||
@ -28,6 +31,10 @@ namespace app {
|
||||
const gfx::Rect& alpha,
|
||||
bool& stop) override;
|
||||
int onNeedsSurfaceRepaint(const app::Color& newColor) override;
|
||||
|
||||
private:
|
||||
std::string m_mainShader;
|
||||
std::string m_bottomShader;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
#include "app/color_utils.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/util/shader_helpers.h"
|
||||
#include "base/clamp.h"
|
||||
#include "ui/graphics.h"
|
||||
|
||||
@ -28,6 +29,54 @@ ColorTintShadeTone::ColorTintShadeTone()
|
||||
{
|
||||
}
|
||||
|
||||
const char* ColorTintShadeTone::getMainAreaShader()
|
||||
{
|
||||
#if SK_ENABLE_SKSL
|
||||
if (m_mainShader.empty()) {
|
||||
m_mainShader += "uniform half3 iRes;"
|
||||
"uniform half4 iColor;";
|
||||
m_mainShader += kRGB_to_HSV_sksl;
|
||||
m_mainShader += kHSV_to_RGB_sksl;
|
||||
m_mainShader += R"(
|
||||
half4 main(vec2 fragcoord) {
|
||||
vec2 d = fragcoord.xy / iRes.xy;
|
||||
half hue = rgb_to_hsv(iColor.rgb).x;
|
||||
half sat = d.x;
|
||||
half val = 1.0 - d.y;
|
||||
return hsv_to_rgb(vec3(hue, sat, val)).rgb1;
|
||||
}
|
||||
)";
|
||||
}
|
||||
return m_mainShader.c_str();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* ColorTintShadeTone::getBottomBarShader()
|
||||
{
|
||||
#if SK_ENABLE_SKSL
|
||||
if (m_bottomShader.empty()) {
|
||||
m_bottomShader += "uniform half3 iRes;"
|
||||
"uniform half4 iColor;";
|
||||
m_bottomShader += kRGB_to_HSV_sksl;
|
||||
m_bottomShader += kHSV_to_RGB_sksl;
|
||||
// TODO should we display the hue bar with the current sat/value?
|
||||
m_bottomShader += R"(
|
||||
half4 main(vec2 fragcoord) {
|
||||
half h = (fragcoord.x / iRes.x);
|
||||
// half3 hsv = rgb_to_hsv(iColor.rgb);
|
||||
// return hsv_to_rgb(half3(h, hsv.y, hsv.z)).rgb1;
|
||||
return hsv_to_rgb(half3(h, 1.0, 1.0)).rgb1;
|
||||
}
|
||||
)";
|
||||
}
|
||||
return m_bottomShader.c_str();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
app::Color ColorTintShadeTone::getMainAreaColor(const int u, const int umax,
|
||||
const int v, const int vmax)
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -18,6 +19,8 @@ namespace app {
|
||||
ColorTintShadeTone();
|
||||
|
||||
protected:
|
||||
const char* getMainAreaShader() override;
|
||||
const char* getBottomBarShader() override;
|
||||
app::Color getMainAreaColor(const int u, const int umax,
|
||||
const int v, const int vmax) override;
|
||||
app::Color getBottomBarColor(const int u, const int umax) override;
|
||||
@ -29,6 +32,10 @@ namespace app {
|
||||
const gfx::Rect& alpha,
|
||||
bool& stop) override;
|
||||
int onNeedsSurfaceRepaint(const app::Color& newColor) override;
|
||||
|
||||
private:
|
||||
std::string m_mainShader;
|
||||
std::string m_bottomShader;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -149,14 +149,20 @@ private:
|
||||
g->drawText(text(), fg, bg,
|
||||
gfx::Point(rc.x+2*guiscale(),
|
||||
rc.y+2*guiscale()));
|
||||
g->drawRgbaSurface(
|
||||
|
||||
ui::Paint paint;
|
||||
paint.blendMode(os::BlendMode::SrcOver);
|
||||
|
||||
g->drawSurface(
|
||||
preview(),
|
||||
preview()->bounds(),
|
||||
gfx::Rect(
|
||||
rc.x+2*guiscale(),
|
||||
rc.y+4*guiscale()+textsz.h,
|
||||
preview()->width()*guiscale(),
|
||||
preview()->height()*guiscale()));
|
||||
preview()->height()*guiscale()),
|
||||
os::Sampling(),
|
||||
&paint);
|
||||
}
|
||||
|
||||
bool m_matrixOnly;
|
||||
|
@ -793,7 +793,8 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite
|
||||
g->drawSurface(tmp.get(),
|
||||
gfx::Rect(0, 0, rc2.w, rc2.h),
|
||||
dest,
|
||||
sampling);
|
||||
sampling,
|
||||
nullptr);
|
||||
}
|
||||
else {
|
||||
g->blit(tmp.get(), 0, 0, dest.x, dest.y, dest.w, dest.h);
|
||||
|
@ -465,9 +465,22 @@ void FileList::onPaint(ui::PaintEvent& ev)
|
||||
tbounds.shrink(1);
|
||||
|
||||
os::SurfaceRef thumbnail = m_selected->getThumbnail();
|
||||
g->drawRgbaSurface(thumbnail.get(),
|
||||
gfx::Rect(0, 0, thumbnail->width(), thumbnail->height()),
|
||||
tbounds);
|
||||
|
||||
ui::Paint paint;
|
||||
paint.blendMode(os::BlendMode::SrcOver);
|
||||
|
||||
os::Sampling sampling;
|
||||
if (thumbnail->width() > tbounds.w &&
|
||||
thumbnail->height() > tbounds.h) {
|
||||
sampling = os::Sampling(os::Sampling::Filter::Linear,
|
||||
os::Sampling::Mipmap::Nearest);
|
||||
}
|
||||
|
||||
g->drawSurface(thumbnail.get(),
|
||||
gfx::Rect(0, 0, thumbnail->width(), thumbnail->height()),
|
||||
tbounds,
|
||||
sampling,
|
||||
&paint);
|
||||
}
|
||||
}
|
||||
|
||||
@ -561,9 +574,21 @@ void FileList::paintItem(ui::Graphics* g, IFileItem* fi, const int i)
|
||||
tbounds.shrink(1);
|
||||
}
|
||||
|
||||
g->drawRgbaSurface(thumbnail.get(),
|
||||
gfx::Rect(0, 0, thumbnail->width(), thumbnail->height()),
|
||||
tbounds);
|
||||
ui::Paint paint;
|
||||
paint.blendMode(os::BlendMode::SrcOver);
|
||||
|
||||
os::Sampling sampling;
|
||||
if (thumbnail->width() > tbounds.w &&
|
||||
thumbnail->height() > tbounds.h) {
|
||||
sampling = os::Sampling(os::Sampling::Filter::Linear,
|
||||
os::Sampling::Mipmap::Nearest);
|
||||
}
|
||||
|
||||
g->drawSurface(thumbnail.get(),
|
||||
gfx::Rect(0, 0, thumbnail->width(), thumbnail->height()),
|
||||
tbounds,
|
||||
sampling,
|
||||
&paint);
|
||||
}
|
||||
else {
|
||||
tbounds = gfx::Rect(0, 0, 20*guiscale(), 2+4*(8.0-m_zoom)/8.0*guiscale())
|
||||
|
@ -316,7 +316,18 @@ public:
|
||||
os::SurfaceRef surface = os::instance()->makeRgbaSurface(w, h);
|
||||
convert_image_to_surface(tileImage.get(), get_current_palette(),
|
||||
surface.get(), 0, 0, 0, 0, w, h);
|
||||
g->drawRgbaSurface(surface.get(), gfx::Rect(0, 0, w, h), box);
|
||||
|
||||
ui::Paint paint;
|
||||
paint.blendMode(os::BlendMode::SrcOver);
|
||||
|
||||
os::Sampling sampling;
|
||||
if (w > box.w && h > box.h) {
|
||||
sampling = os::Sampling(os::Sampling::Filter::Linear,
|
||||
os::Sampling::Mipmap::Nearest);
|
||||
}
|
||||
|
||||
g->drawSurface(surface.get(), gfx::Rect(0, 0, w, h), box,
|
||||
sampling, &paint);
|
||||
}
|
||||
negColor = gfx::rgba(255, 255, 255);
|
||||
}
|
||||
@ -626,6 +637,12 @@ bool PaletteView::onProcessMessage(Message* msg)
|
||||
switch (m_hot.part) {
|
||||
|
||||
case Hit::COLOR:
|
||||
// Clicking outside the palette range will deselect
|
||||
if (m_hot.color >= currentPalette()->size()) {
|
||||
deselect();
|
||||
break;
|
||||
}
|
||||
|
||||
m_state = State::SELECTING_COLOR;
|
||||
|
||||
// As we can ctrl+click color bar + timeline, now we have to
|
||||
|
67
src/app/util/shader_helpers.h
Normal file
67
src/app/util/shader_helpers.h
Normal file
@ -0,0 +1,67 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_UTIL_SHADER_HELPERS_H_INCLUDED
|
||||
#define APP_UTIL_SHADER_HELPERS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
|
||||
#include "app/color.h"
|
||||
#include "gfx/color.h"
|
||||
|
||||
#include "include/core/SkM44.h"
|
||||
|
||||
// To include kRGB_to_HSL_sksl and kHSL_to_RGB_sksl
|
||||
#include "src/core/SkRuntimeEffectPriv.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
// rgb_to_hsl() and hsv_to_hsl() functions by Sam Hocevar licensed
|
||||
// under WTFPL (https://en.wikipedia.org/wiki/WTFPL)
|
||||
// Source:
|
||||
// http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
|
||||
// https://stackoverflow.com/a/17897228/408239
|
||||
|
||||
inline constexpr char kRGB_to_HSV_sksl[] = R"(
|
||||
half3 rgb_to_hsv(half3 c) {
|
||||
half4 K = half4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
half4 p = mix(half4(c.bg, K.wz), half4(c.gb, K.xy), step(c.b, c.g));
|
||||
half4 q = mix(half4(p.xyw, c.r), half4(c.r, p.yzx), step(p.x, c.r));
|
||||
|
||||
float d = q.x - min(q.w, q.y);
|
||||
float e = 1.0e-10;
|
||||
return half3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||
}
|
||||
)";
|
||||
|
||||
inline constexpr char kHSV_to_RGB_sksl[] = R"(
|
||||
half3 hsv_to_rgb(half3 c) {
|
||||
half4 K = half4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
half3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
)";
|
||||
|
||||
inline SkV4 gfxColor_to_SkV4(gfx::Color color) {
|
||||
return SkV4{float(gfx::getr(color) / 255.0),
|
||||
float(gfx::getg(color) / 255.0),
|
||||
float(gfx::getb(color) / 255.0),
|
||||
float(gfx::geta(color) / 255.0)};
|
||||
}
|
||||
|
||||
inline SkV4 appColor_to_SkV4(const app::Color& color) {
|
||||
return SkV4{float(color.getRed() / 255.0),
|
||||
float(color.getGreen() / 255.0),
|
||||
float(color.getBlue() / 255.0),
|
||||
float(color.getAlpha() / 255.0)};
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2019 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -15,7 +15,6 @@
|
||||
#include "gfx/rect.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -26,18 +25,15 @@ namespace doc {
|
||||
template<typename ImageTraits,
|
||||
typename PointerType,
|
||||
typename ReferenceType>
|
||||
class ImageIteratorT : public std::iterator<std::forward_iterator_tag,
|
||||
typename ImageTraits::pixel_t,
|
||||
ptrdiff_t,
|
||||
PointerType,
|
||||
ReferenceType> {
|
||||
class ImageIteratorT {
|
||||
public:
|
||||
// GCC 4.6 needs these re-definitions here.
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef PointerType pointer;
|
||||
typedef ReferenceType reference;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = typename ImageTraits::pixel_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = PointerType;
|
||||
using reference = ReferenceType;
|
||||
|
||||
ImageIteratorT() : m_ptr(NULL) {
|
||||
ImageIteratorT() : m_ptr(nullptr) {
|
||||
}
|
||||
|
||||
ImageIteratorT(const ImageIteratorT& other) :
|
||||
@ -142,17 +138,13 @@ namespace doc {
|
||||
typename ImageTraits::pixel_t *,
|
||||
typename ImageTraits::pixel_t&> {
|
||||
public:
|
||||
// GCC 4.6 needs these re-definitions here.
|
||||
typedef typename ImageTraits::pixel_t* pointer;
|
||||
typedef typename ImageTraits::pixel_t& reference;
|
||||
|
||||
ImageIterator() {
|
||||
}
|
||||
|
||||
ImageIterator(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
||||
ImageIteratorT<ImageTraits,
|
||||
pointer,
|
||||
reference>(image, bounds, x, y) {
|
||||
typename ImageIterator::pointer,
|
||||
typename ImageIterator::reference>(image, bounds, x, y) {
|
||||
}
|
||||
};
|
||||
|
||||
@ -161,17 +153,13 @@ namespace doc {
|
||||
typename ImageTraits::pixel_t const *,
|
||||
typename ImageTraits::pixel_t const &> {
|
||||
public:
|
||||
// GCC 4.6 needs these re-definitions here.
|
||||
typedef typename ImageTraits::pixel_t const* pointer;
|
||||
typedef typename ImageTraits::pixel_t const& reference;
|
||||
|
||||
ImageConstIterator() {
|
||||
}
|
||||
|
||||
ImageConstIterator(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
||||
ImageIteratorT<ImageTraits,
|
||||
pointer,
|
||||
reference>(image, bounds, x, y) {
|
||||
typename ImageConstIterator::pointer,
|
||||
typename ImageConstIterator::reference>(image, bounds, x, y) {
|
||||
}
|
||||
};
|
||||
|
||||
@ -181,7 +169,7 @@ namespace doc {
|
||||
class BitPixelAccess {
|
||||
public:
|
||||
BitPixelAccess() :
|
||||
m_ptr(NULL),
|
||||
m_ptr(nullptr),
|
||||
m_bit(0) {
|
||||
}
|
||||
|
||||
@ -263,20 +251,17 @@ namespace doc {
|
||||
|
||||
template<typename PointerType,
|
||||
typename ReferenceType>
|
||||
class ImageIteratorT<BitmapTraits, PointerType, ReferenceType>
|
||||
: public std::iterator<std::forward_iterator_tag,
|
||||
BitmapTraits::pixel_t,
|
||||
ptrdiff_t,
|
||||
PointerType,
|
||||
ReferenceType> {
|
||||
class ImageIteratorT<BitmapTraits, PointerType, ReferenceType> {
|
||||
public:
|
||||
// GCC 4.6 needs these re-definitions here.
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef PointerType pointer;
|
||||
typedef ReferenceType reference;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = BitmapTraits::pixel_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = PointerType;
|
||||
using reference = ReferenceType;
|
||||
|
||||
enum { pixels_per_byte = BitmapTraits::pixels_per_byte };
|
||||
|
||||
ImageIteratorT() : m_ptr(NULL) {
|
||||
ImageIteratorT() : m_ptr(nullptr) {
|
||||
}
|
||||
|
||||
ImageIteratorT(const ImageIteratorT& other) :
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2022 Igara Studio S.A.
|
||||
// Copyright (c) 2016-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -11,7 +12,6 @@
|
||||
#include "doc/frame_range.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
namespace doc {
|
||||
@ -20,9 +20,15 @@ namespace doc {
|
||||
typedef std::vector<FrameRange> Ranges;
|
||||
|
||||
public:
|
||||
class const_iterator : public std::iterator<std::forward_iterator_tag, frame_t> {
|
||||
class const_iterator {
|
||||
static const int kNullFrame = -2;
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = frame_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = frame_t*;
|
||||
using reference = frame_t&;
|
||||
|
||||
const_iterator(const Ranges::const_iterator& it)
|
||||
: m_it(it), m_frame(kNullFrame) {
|
||||
}
|
||||
@ -70,8 +76,14 @@ namespace doc {
|
||||
mutable frame_t m_frame;
|
||||
};
|
||||
|
||||
class const_reverse_iterator : public std::iterator<std::forward_iterator_tag, frame_t> {
|
||||
class const_reverse_iterator {
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = frame_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = frame_t*;
|
||||
using reference = frame_t&;
|
||||
|
||||
const_reverse_iterator(const Ranges::const_reverse_iterator& it)
|
||||
: m_it(it), m_frame(-1) {
|
||||
}
|
||||
|
@ -257,21 +257,6 @@ void Graphics::drawSurface(os::Surface* surface, int x, int y)
|
||||
m_surface->drawSurface(surface, m_dx+x, m_dy+y);
|
||||
}
|
||||
|
||||
void Graphics::drawSurface(os::Surface* surface,
|
||||
const gfx::Rect& srcRect,
|
||||
const gfx::Rect& dstRect)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+dstRect.x, m_dy+dstRect.y,
|
||||
dstRect.w, dstRect.h));
|
||||
|
||||
os::SurfaceLock lockSrc(surface);
|
||||
os::SurfaceLock lockDst(m_surface.get());
|
||||
m_surface->drawSurface(
|
||||
surface,
|
||||
srcRect,
|
||||
gfx::Rect(dstRect).offset(m_dx, m_dy));
|
||||
}
|
||||
|
||||
void Graphics::drawSurface(os::Surface* surface,
|
||||
const gfx::Rect& srcRect,
|
||||
const gfx::Rect& dstRect,
|
||||
@ -309,21 +294,6 @@ void Graphics::drawRgbaSurface(os::Surface* surface, int srcx, int srcy, int dst
|
||||
m_surface->drawRgbaSurface(surface, srcx, srcy, m_dx+dstx, m_dy+dsty, w, h);
|
||||
}
|
||||
|
||||
void Graphics::drawRgbaSurface(os::Surface* surface,
|
||||
const gfx::Rect& srcRect,
|
||||
const gfx::Rect& dstRect)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+dstRect.x, m_dy+dstRect.y,
|
||||
dstRect.w, dstRect.h));
|
||||
|
||||
os::SurfaceLock lockSrc(surface);
|
||||
os::SurfaceLock lockDst(m_surface.get());
|
||||
m_surface->drawRgbaSurface(
|
||||
surface,
|
||||
srcRect,
|
||||
gfx::Rect(dstRect).offset(m_dx, m_dy));
|
||||
}
|
||||
|
||||
void Graphics::drawColoredRgbaSurface(os::Surface* surface, gfx::Color color, int x, int y)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, surface->width(), surface->height()));
|
||||
|
@ -90,19 +90,13 @@ namespace ui {
|
||||
const gfx::Rect& outer, const gfx::Rect& inner);
|
||||
|
||||
void drawSurface(os::Surface* surface, int x, int y);
|
||||
void drawSurface(os::Surface* surface,
|
||||
const gfx::Rect& srcRect,
|
||||
const gfx::Rect& dstRect);
|
||||
void drawSurface(os::Surface* surface,
|
||||
const gfx::Rect& srcRect,
|
||||
const gfx::Rect& dstRect,
|
||||
const os::Sampling& sampling,
|
||||
const ui::Paint* paint = nullptr);
|
||||
const ui::Paint* paint);
|
||||
void drawRgbaSurface(os::Surface* surface, int x, int y);
|
||||
void drawRgbaSurface(os::Surface* surface, int srcx, int srcy, int dstx, int dsty, int w, int h);
|
||||
void drawRgbaSurface(os::Surface* surface,
|
||||
const gfx::Rect& srcRect,
|
||||
const gfx::Rect& dstRect);
|
||||
void drawColoredRgbaSurface(os::Surface* surface, gfx::Color color, int x, int y);
|
||||
void drawColoredRgbaSurface(os::Surface* surface, gfx::Color color, int srcx, int srcy, int dstx, int dsty, int w, int h);
|
||||
void drawSurfaceNine(os::Surface* surface,
|
||||
|
@ -309,6 +309,8 @@ void Manager::flipAllDisplays()
|
||||
window->display()->flipDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
m_display.nativeWindow()->swapBuffers();
|
||||
}
|
||||
|
||||
void Manager::updateAllDisplaysWithNewScale(int scale)
|
||||
|
Loading…
Reference in New Issue
Block a user