mirror of
https://github.com/aseprite/aseprite.git
synced 2024-10-04 05:50:15 +00:00
parent
5a91325750
commit
0fe5edb7fe
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -8,15 +8,11 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gfx/color.h"
|
||||
#include "ui/intern.h"
|
||||
#include "ui/system.h"
|
||||
#include "ui/theme.h"
|
||||
#include "app/modules/gfx.h"
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/color_utils.h"
|
||||
#include "app/console.h"
|
||||
#include "app/modules/gfx.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/modules/palettes.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
@ -24,8 +20,13 @@
|
||||
#include "doc/blend_funcs.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/palette.h"
|
||||
#include "gfx/color.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "she/surface.h"
|
||||
#include "ui/intern.h"
|
||||
#include "ui/system.h"
|
||||
#include "ui/theme.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -181,4 +182,31 @@ void draw_alpha_slider(ui::Graphics* g,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this code is exactly the same as draw_alpha_slider() with a ui::Graphics
|
||||
void draw_alpha_slider(she::Surface* s,
|
||||
const gfx::Rect& rc,
|
||||
const app::Color& color)
|
||||
{
|
||||
const int xmax = MAX(1, rc.w-1);
|
||||
const doc::color_t c =
|
||||
(color.getType() != app::Color::MaskType ?
|
||||
doc::rgba(color.getRed(),
|
||||
color.getGreen(),
|
||||
color.getBlue(), 255): 0);
|
||||
|
||||
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 int mid = rc.h/2;
|
||||
const int odd = (x / rc.h) & 1;
|
||||
s->drawVLine(
|
||||
app::color_utils::color_for_ui(app::Color::fromImage(IMAGE_RGB, odd ? c2: c1)),
|
||||
rc.x+x, rc.y, mid);
|
||||
s->drawVLine(
|
||||
app::color_utils::color_for_ui(app::Color::fromImage(IMAGE_RGB, odd ? c1: c2)),
|
||||
rc.x+x, rc.y+mid, rc.h-mid);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -13,7 +13,14 @@
|
||||
#include "gfx/color.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "ui/base.h"
|
||||
#include "ui/graphics.h"
|
||||
|
||||
namespace she {
|
||||
class Surface;
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
class Graphics;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
using namespace doc;
|
||||
@ -34,6 +41,10 @@ namespace app {
|
||||
const gfx::Rect& rc,
|
||||
const app::Color& color);
|
||||
|
||||
void draw_alpha_slider(she::Surface* s,
|
||||
const gfx::Rect& rc,
|
||||
const app::Color& color);
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
||||
|
@ -1,9 +1,11 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2016-2017 David Capello
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#define COLSEL_TRACE(...)
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
@ -14,29 +16,193 @@
|
||||
#include "app/modules/gfx.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "base/concurrent_queue.h"
|
||||
#include "base/scoped_value.h"
|
||||
#include "base/thread.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/paint_event.h"
|
||||
#include "ui/register_message.h"
|
||||
#include "ui/scale.h"
|
||||
#include "ui/size_hint_event.h"
|
||||
#include "ui/system.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace app::skin;
|
||||
using namespace ui;
|
||||
|
||||
// TODO This logic could be used to redraw any widget:
|
||||
// 1. We send a onPaintSurfaceInBgThread() to paint the widget on a
|
||||
// offscreen buffer
|
||||
// 2. When the painting is done, we flip the buffer onto the screen
|
||||
// 3. If we receive another onPaint() we can cancel the background
|
||||
// painting and start another onPaintSurfaceInBgThread()
|
||||
class ColorSelector::Painter {
|
||||
public:
|
||||
Painter()
|
||||
: m_canvas(nullptr)
|
||||
, m_paintingThread([this]{ paintingProc(); })
|
||||
{
|
||||
}
|
||||
|
||||
~Painter() {
|
||||
if (m_canvas)
|
||||
m_canvas->dispose();
|
||||
}
|
||||
|
||||
void addRef() {
|
||||
++m_ref;
|
||||
}
|
||||
|
||||
void releaseRef() {
|
||||
--m_ref;
|
||||
if (m_ref == 0) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
stopCurrentPainting(lock);
|
||||
|
||||
m_killing = true;
|
||||
m_paintingCV.notify_one();
|
||||
}
|
||||
|
||||
m_paintingThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
she::Surface* getCanvas(int w, int h, gfx::Color bgColor) {
|
||||
if (!m_canvas ||
|
||||
m_canvas->width() != w ||
|
||||
m_canvas->height() != h) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
stopCurrentPainting(lock);
|
||||
|
||||
auto oldCanvas = m_canvas;
|
||||
m_canvas = she::instance()->createSurface(w, h);
|
||||
m_canvas->fillRect(bgColor, gfx::Rect(0, 0, w, h));
|
||||
if (oldCanvas) {
|
||||
m_canvas->drawSurface(oldCanvas, 0, 0);
|
||||
oldCanvas->dispose();
|
||||
}
|
||||
}
|
||||
return m_canvas;
|
||||
}
|
||||
|
||||
void startBgPainting(ColorSelector* colorSelector,
|
||||
const gfx::Rect& mainBounds,
|
||||
const gfx::Rect& bottomBarBounds,
|
||||
const gfx::Rect& alphaBarBounds) {
|
||||
COLSEL_TRACE("COLSEL: startBgPainting for %p\n", colorSelector);
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
stopCurrentPainting(lock);
|
||||
|
||||
m_colorSelector = colorSelector;
|
||||
m_manager = colorSelector->manager();
|
||||
m_mainBounds = mainBounds;
|
||||
m_bottomBarBounds = bottomBarBounds;
|
||||
m_alphaBarBounds = alphaBarBounds;
|
||||
|
||||
m_stopPainting = false;
|
||||
m_paintingCV.notify_one();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void stopCurrentPainting(std::unique_lock<std::mutex>& lock) {
|
||||
// Stop current
|
||||
if (m_colorSelector) {
|
||||
COLSEL_TRACE("COLSEL: stoppping painting of %p\n", m_colorSelector);
|
||||
|
||||
// TODO use another condition variable here
|
||||
m_stopPainting = true;
|
||||
m_waitStopCV.wait(lock);
|
||||
}
|
||||
|
||||
ASSERT(m_colorSelector == nullptr);
|
||||
}
|
||||
|
||||
void paintingProc() {
|
||||
COLSEL_TRACE("COLSEL: paintingProc starts\n");
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
while (true) {
|
||||
m_paintingCV.wait(lock);
|
||||
|
||||
if (m_killing)
|
||||
break;
|
||||
|
||||
auto colorSel = m_colorSelector;
|
||||
if (!colorSel)
|
||||
break;
|
||||
|
||||
COLSEL_TRACE("COLSEL: starting painting in bg for %p\n", colorSel);
|
||||
|
||||
// Do the intesive painting in the background thread
|
||||
{
|
||||
lock.unlock();
|
||||
colorSel->onPaintSurfaceInBgThread(
|
||||
m_canvas,
|
||||
m_mainBounds,
|
||||
m_bottomBarBounds,
|
||||
m_alphaBarBounds,
|
||||
m_stopPainting);
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
m_colorSelector = nullptr;
|
||||
|
||||
if (m_stopPainting) {
|
||||
COLSEL_TRACE("COLSEL: painting for %p stopped\n");
|
||||
m_waitStopCV.notify_one();
|
||||
}
|
||||
else {
|
||||
COLSEL_TRACE("COLSEL: painting for %p done and sending message\n");
|
||||
colorSel->m_paintFlags |= DoneFlag;
|
||||
}
|
||||
}
|
||||
|
||||
COLSEL_TRACE("COLSEL: paintingProc ends\n");
|
||||
}
|
||||
|
||||
int m_ref = 0;
|
||||
bool m_killing = false;
|
||||
bool m_stopPainting = false;
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_paintingCV;
|
||||
std::condition_variable m_waitStopCV;
|
||||
she::Surface* m_canvas;
|
||||
ColorSelector* m_colorSelector;
|
||||
ui::Manager* m_manager;
|
||||
gfx::Rect m_mainBounds;
|
||||
gfx::Rect m_bottomBarBounds;
|
||||
gfx::Rect m_alphaBarBounds;
|
||||
std::thread m_paintingThread;
|
||||
};
|
||||
|
||||
static ColorSelector::Painter painter;
|
||||
|
||||
ColorSelector::ColorSelector()
|
||||
: Widget(kGenericWidget)
|
||||
, m_paintFlags(AllAreasFlag)
|
||||
, m_lockColor(false)
|
||||
, m_capturedInBottom(false)
|
||||
, m_capturedInAlpha(false)
|
||||
, m_timer(100, this)
|
||||
{
|
||||
initTheme();
|
||||
painter.addRef();
|
||||
}
|
||||
|
||||
ColorSelector::~ColorSelector()
|
||||
{
|
||||
painter.releaseRef();
|
||||
}
|
||||
|
||||
void ColorSelector::selectColor(const app::Color& color)
|
||||
@ -44,6 +210,9 @@ void ColorSelector::selectColor(const app::Color& color)
|
||||
if (m_lockColor)
|
||||
return;
|
||||
|
||||
if (m_color != color)
|
||||
m_paintFlags |= onNeedsSurfaceRepaint(color);
|
||||
|
||||
m_color = color;
|
||||
invalidate();
|
||||
}
|
||||
@ -166,6 +335,14 @@ bool ColorSelector::onProcessMessage(ui::Message* msg)
|
||||
}
|
||||
break;
|
||||
|
||||
case kTimerMessage:
|
||||
if (m_paintFlags & DoneFlag) {
|
||||
m_timer.stop();
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return Widget::onProcessMessage(msg);
|
||||
@ -177,6 +354,15 @@ void ColorSelector::onInitTheme(ui::InitThemeEvent& ev)
|
||||
setBorder(gfx::Border(3*ui::guiscale()));
|
||||
}
|
||||
|
||||
void ColorSelector::onResize(ui::ResizeEvent& ev)
|
||||
{
|
||||
Widget::onResize(ev);
|
||||
|
||||
// We'll need to redraw the whole surface again with the new widget
|
||||
// size.
|
||||
m_paintFlags = AllAreasFlag;
|
||||
}
|
||||
|
||||
void ColorSelector::onPaint(ui::PaintEvent& ev)
|
||||
{
|
||||
ui::Graphics* g = ev.graphics();
|
||||
@ -190,6 +376,10 @@ 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();
|
||||
rc.h -= bottomBarBounds.h + alphaBarBounds.h;
|
||||
@ -204,12 +394,21 @@ void ColorSelector::onPaint(ui::PaintEvent& ev)
|
||||
alphaBarBounds.offset(-bounds().origin());
|
||||
onPaintAlphaBar(g, alphaBarBounds);
|
||||
}
|
||||
|
||||
if ((m_paintFlags & AllAreasFlag) != 0) {
|
||||
m_paintFlags &= ~DoneFlag;
|
||||
m_timer.start();
|
||||
|
||||
gfx::Point d = -rc.origin();
|
||||
rc.offset(d);
|
||||
if (!bottomBarBounds.isEmpty()) bottomBarBounds.offset(d);
|
||||
if (!alphaBarBounds.isEmpty()) alphaBarBounds.offset(d);
|
||||
painter.startBgPainting(this, rc, bottomBarBounds, alphaBarBounds);
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSelector::onPaintAlphaBar(ui::Graphics* g, const gfx::Rect& rc)
|
||||
{
|
||||
draw_alpha_slider(g, rc, m_color);
|
||||
|
||||
const double lit = m_color.getHslLightness();
|
||||
const int alpha = m_color.getAlpha();
|
||||
const gfx::Point pos(rc.x + int(rc.w * alpha / 255),
|
||||
@ -217,6 +416,28 @@ void ColorSelector::onPaintAlphaBar(ui::Graphics* g, const gfx::Rect& rc)
|
||||
paintColorIndicator(g, pos, lit < 0.5);
|
||||
}
|
||||
|
||||
void ColorSelector::onPaintSurfaceInBgThread(
|
||||
she::Surface* s,
|
||||
const gfx::Rect& main,
|
||||
const gfx::Rect& bottom,
|
||||
const gfx::Rect& alpha,
|
||||
bool& stop)
|
||||
{
|
||||
if ((m_paintFlags & AlphaBarFlag) && !alpha.isEmpty()) {
|
||||
draw_alpha_slider(s, alpha, m_color);
|
||||
if (stop)
|
||||
return;
|
||||
m_paintFlags ^= AlphaBarFlag;
|
||||
}
|
||||
}
|
||||
|
||||
int ColorSelector::onNeedsSurfaceRepaint(const app::Color& newColor)
|
||||
{
|
||||
return (m_color.getRed() != newColor.getRed() ||
|
||||
m_color.getGreen() != newColor.getGreen() ||
|
||||
m_color.getBlue() != newColor.getBlue() ? AlphaBarFlag: 0);
|
||||
}
|
||||
|
||||
void ColorSelector::paintColorIndicator(ui::Graphics* g,
|
||||
const gfx::Point& pos,
|
||||
const bool white)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2016-2017 David Capello
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -11,15 +11,27 @@
|
||||
#include "app/color.h"
|
||||
#include "app/ui/color_source.h"
|
||||
#include "obs/signal.h"
|
||||
#include "she/surface.h"
|
||||
#include "ui/mouse_buttons.h"
|
||||
#include "ui/timer.h"
|
||||
#include "ui/widget.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// TODO move this to laf::base
|
||||
inline bool cs_double_diff(double a, double b) {
|
||||
return std::fabs((a)-(b)) > 0.001;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
|
||||
class ColorSelector : public ui::Widget
|
||||
, public IColorSource {
|
||||
public:
|
||||
class Painter;
|
||||
|
||||
ColorSelector();
|
||||
~ColorSelector();
|
||||
|
||||
void selectColor(const app::Color& color);
|
||||
|
||||
@ -30,11 +42,33 @@ namespace app {
|
||||
obs::signal<void(const app::Color&, ui::MouseButtons)> ColorChange;
|
||||
|
||||
protected:
|
||||
// paintFlags for onPaintSurfaceInBgThread and return value of
|
||||
// onNeedsSurfaceRepaint().
|
||||
enum {
|
||||
MainAreaFlag = 1,
|
||||
BottomBarFlag = 2,
|
||||
AlphaBarFlag = 4,
|
||||
AllAreasFlag = MainAreaFlag | BottomBarFlag | AlphaBarFlag,
|
||||
DoneFlag = 8,
|
||||
};
|
||||
|
||||
void onSizeHint(ui::SizeHintEvent& ev) override;
|
||||
bool onProcessMessage(ui::Message* msg) override;
|
||||
void onInitTheme(ui::InitThemeEvent& ev) override;
|
||||
void onResize(ui::ResizeEvent& ev) override;
|
||||
void onPaint(ui::PaintEvent& ev) override;
|
||||
|
||||
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;
|
||||
virtual void onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc) = 0;
|
||||
virtual void onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc) = 0;
|
||||
virtual void onPaintSurfaceInBgThread(she::Surface* s,
|
||||
const gfx::Rect& main,
|
||||
const gfx::Rect& bottom,
|
||||
const gfx::Rect& alpha,
|
||||
bool& stop);
|
||||
virtual int onNeedsSurfaceRepaint(const app::Color& newColor);
|
||||
virtual bool subColorPicked() { return false; }
|
||||
|
||||
void paintColorIndicator(ui::Graphics* g,
|
||||
@ -43,12 +77,12 @@ namespace app {
|
||||
|
||||
app::Color m_color;
|
||||
|
||||
private:
|
||||
void onSizeHint(ui::SizeHintEvent& ev) override;
|
||||
bool onProcessMessage(ui::Message* msg) override;
|
||||
void onInitTheme(ui::InitThemeEvent& ev) override;
|
||||
void onPaint(ui::PaintEvent& ev) override;
|
||||
// These flags indicate which areas must be redrawed in the
|
||||
// background thread. Equal to DoneFlag when the surface is
|
||||
// already painted in the background thread surface.
|
||||
int m_paintFlags;
|
||||
|
||||
private:
|
||||
app::Color getAlphaBarColor(const int u, const int umax);
|
||||
void onPaintAlphaBar(ui::Graphics* g, const gfx::Rect& rc);
|
||||
|
||||
@ -66,6 +100,8 @@ namespace app {
|
||||
// widget.
|
||||
bool m_capturedInBottom;
|
||||
bool m_capturedInAlpha;
|
||||
|
||||
ui::Timer m_timer;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -55,25 +55,6 @@ app::Color ColorSpectrum::getBottomBarColor(const int u, const int umax)
|
||||
|
||||
void ColorSpectrum::onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc)
|
||||
{
|
||||
double sat = m_color.getHslSaturation();
|
||||
int umax = MAX(1, rc.w-1);
|
||||
int vmax = MAX(1, rc.h-1);
|
||||
|
||||
for (int y=0; y<rc.h; ++y) {
|
||||
for (int x=0; x<rc.w; ++x) {
|
||||
double hue = 360.0 * double(x) / double(umax);
|
||||
double lit = 1.0 - double(y) / double(vmax);
|
||||
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsl(
|
||||
MID(0.0, hue, 360.0),
|
||||
sat,
|
||||
MID(0.0, lit, 1.0)));
|
||||
|
||||
g->putPixel(color, rc.x+x, rc.y+y);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_color.getType() != app::Color::MaskType) {
|
||||
double hue = m_color.getHslHue();
|
||||
double lit = m_color.getHslLightness();
|
||||
@ -86,16 +67,8 @@ void ColorSpectrum::onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc)
|
||||
|
||||
void ColorSpectrum::onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc)
|
||||
{
|
||||
double hue = m_color.getHslHue();
|
||||
double lit = m_color.getHslLightness();
|
||||
|
||||
for (int x=0; x<rc.w; ++x) {
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsl(hue, double(x) / double(rc.w), lit));
|
||||
|
||||
g->drawVLine(color, rc.x+x, rc.y, rc.h);
|
||||
}
|
||||
|
||||
if (m_color.getType() != app::Color::MaskType) {
|
||||
double sat = m_color.getHslSaturation();
|
||||
gfx::Point pos(rc.x + int(double(rc.w) * sat),
|
||||
@ -104,4 +77,63 @@ void ColorSpectrum::onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc)
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSpectrum::onPaintSurfaceInBgThread(
|
||||
she::Surface* s,
|
||||
const gfx::Rect& main,
|
||||
const gfx::Rect& bottom,
|
||||
const gfx::Rect& alpha,
|
||||
bool& stop)
|
||||
{
|
||||
if (m_paintFlags & MainAreaFlag) {
|
||||
double sat = m_color.getHslSaturation();
|
||||
int umax = MAX(1, main.w-1);
|
||||
int vmax = MAX(1, main.h-1);
|
||||
|
||||
for (int y=0; y<main.h && !stop; ++y) {
|
||||
for (int x=0; x<main.w && !stop; ++x) {
|
||||
double hue = 360.0 * double(x) / double(umax);
|
||||
double lit = 1.0 - double(y) / double(vmax);
|
||||
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsl(
|
||||
MID(0.0, hue, 360.0),
|
||||
sat,
|
||||
MID(0.0, lit, 1.0)));
|
||||
|
||||
s->putPixel(color, main.x+x, main.y+y);
|
||||
}
|
||||
}
|
||||
if (stop)
|
||||
return;
|
||||
m_paintFlags ^= MainAreaFlag;
|
||||
}
|
||||
|
||||
if (m_paintFlags & BottomBarFlag) {
|
||||
double lit = m_color.getHslLightness();
|
||||
double hue = m_color.getHslHue();
|
||||
for (int x=0; x<bottom.w && !stop; ++x) {
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsl(hue, double(x) / double(bottom.w), lit));
|
||||
|
||||
s->drawVLine(color, bottom.x+x, bottom.y, bottom.h);
|
||||
}
|
||||
if (stop)
|
||||
return;
|
||||
m_paintFlags ^= BottomBarFlag;
|
||||
}
|
||||
|
||||
// Paint alpha bar
|
||||
ColorSelector::onPaintSurfaceInBgThread(s, main, bottom, alpha, stop);
|
||||
}
|
||||
|
||||
int ColorSpectrum::onNeedsSurfaceRepaint(const app::Color& newColor)
|
||||
{
|
||||
return
|
||||
// Only if the saturation changes we have to redraw the main surface.
|
||||
(cs_double_diff(m_color.getHslSaturation(), newColor.getHslSaturation()) ? MainAreaFlag: 0) |
|
||||
(cs_double_diff(m_color.getHslHue(), newColor.getHslHue()) ||
|
||||
cs_double_diff(m_color.getHslLightness(), newColor.getHslLightness()) ? BottomBarFlag: 0) |
|
||||
ColorSelector::onNeedsSurfaceRepaint(newColor);
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -22,6 +22,12 @@ namespace app {
|
||||
app::Color getBottomBarColor(const int u, const int umax) override;
|
||||
void onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc) override;
|
||||
void onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc) override;
|
||||
void onPaintSurfaceInBgThread(she::Surface* s,
|
||||
const gfx::Rect& main,
|
||||
const gfx::Rect& bottom,
|
||||
const gfx::Rect& alpha,
|
||||
bool& stop) override;
|
||||
int onNeedsSurfaceRepaint(const app::Color& newColor) override;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2016-2017 David Capello
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -48,25 +48,6 @@ app::Color ColorTintShadeTone::getBottomBarColor(const int u, const int umax)
|
||||
|
||||
void ColorTintShadeTone::onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc)
|
||||
{
|
||||
double hue = m_color.getHsvHue();
|
||||
int umax = MAX(1, rc.w-1);
|
||||
int vmax = MAX(1, rc.h-1);
|
||||
|
||||
for (int y=0; y<rc.h; ++y) {
|
||||
for (int x=0; x<rc.w; ++x) {
|
||||
double sat = double(x) / double(umax);
|
||||
double val = 1.0 - double(y) / double(vmax);
|
||||
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(
|
||||
hue,
|
||||
MID(0.0, sat, 1.0),
|
||||
MID(0.0, val, 1.0)));
|
||||
|
||||
g->putPixel(color, rc.x+x, rc.y+y);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_color.getType() != app::Color::MaskType) {
|
||||
double sat = m_color.getHsvSaturation();
|
||||
double val = m_color.getHsvValue();
|
||||
@ -79,14 +60,6 @@ void ColorTintShadeTone::onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc)
|
||||
|
||||
void ColorTintShadeTone::onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc)
|
||||
{
|
||||
for (int x=0; x<rc.w; ++x) {
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(
|
||||
(360.0 * x / rc.w), 1.0, 1.0));
|
||||
|
||||
g->drawVLine(color, rc.x+x, rc.y, rc.h);
|
||||
}
|
||||
|
||||
if (m_color.getType() != app::Color::MaskType) {
|
||||
double hue = m_color.getHsvHue();
|
||||
gfx::Point pos(rc.x + int(rc.w * hue / 360.0),
|
||||
@ -95,4 +68,60 @@ void ColorTintShadeTone::onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc)
|
||||
}
|
||||
}
|
||||
|
||||
void ColorTintShadeTone::onPaintSurfaceInBgThread(
|
||||
she::Surface* s,
|
||||
const gfx::Rect& main,
|
||||
const gfx::Rect& bottom,
|
||||
const gfx::Rect& alpha,
|
||||
bool& stop)
|
||||
{
|
||||
double hue = m_color.getHsvHue();
|
||||
int umax = MAX(1, main.w-1);
|
||||
int vmax = MAX(1, main.h-1);
|
||||
|
||||
if (m_paintFlags & MainAreaFlag) {
|
||||
for (int y=0; y<main.h && !stop; ++y) {
|
||||
for (int x=0; x<main.w && !stop; ++x) {
|
||||
double sat = double(x) / double(umax);
|
||||
double val = 1.0 - double(y) / double(vmax);
|
||||
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(
|
||||
hue,
|
||||
MID(0.0, sat, 1.0),
|
||||
MID(0.0, val, 1.0)));
|
||||
|
||||
s->putPixel(color, main.x+x, main.y+y);
|
||||
}
|
||||
}
|
||||
if (stop)
|
||||
return;
|
||||
m_paintFlags ^= MainAreaFlag;
|
||||
}
|
||||
|
||||
if (m_paintFlags & BottomBarFlag) {
|
||||
for (int x=0; x<bottom.w && !stop; ++x) {
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(
|
||||
(360.0 * x / bottom.w), 1.0, 1.0));
|
||||
|
||||
s->drawVLine(color, bottom.x+x, bottom.y, bottom.h);
|
||||
}
|
||||
if (stop)
|
||||
return;
|
||||
m_paintFlags ^= BottomBarFlag;
|
||||
}
|
||||
|
||||
// Paint alpha bar
|
||||
ColorSelector::onPaintSurfaceInBgThread(s, main, bottom, alpha, stop);
|
||||
}
|
||||
|
||||
int ColorTintShadeTone::onNeedsSurfaceRepaint(const app::Color& newColor)
|
||||
{
|
||||
return
|
||||
// Only if the hue changes we have to redraw the main surface.
|
||||
(cs_double_diff(m_color.getHsvHue(), newColor.getHsvHue()) ? MainAreaFlag: 0) |
|
||||
ColorSelector::onNeedsSurfaceRepaint(newColor);
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2016-2017 David Capello
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -11,6 +11,7 @@
|
||||
#include "app/ui/color_selector.h"
|
||||
|
||||
namespace app {
|
||||
class Color;
|
||||
|
||||
class ColorTintShadeTone : public ColorSelector {
|
||||
public:
|
||||
@ -22,6 +23,12 @@ namespace app {
|
||||
app::Color getBottomBarColor(const int u, const int umax) override;
|
||||
void onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc) override;
|
||||
void onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc) override;
|
||||
void onPaintSurfaceInBgThread(she::Surface* s,
|
||||
const gfx::Rect& main,
|
||||
const gfx::Rect& bottom,
|
||||
const gfx::Rect& alpha,
|
||||
bool& stop) override;
|
||||
int onNeedsSurfaceRepaint(const app::Color& newColor) override;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -61,6 +61,7 @@ ColorWheel::ColorWheel()
|
||||
[this]{
|
||||
SkinTheme* theme = SkinTheme::instance();
|
||||
m_options.setStyle(theme->styles.colorWheelOptions());
|
||||
m_bgColor = theme->colors.editorFace();
|
||||
});
|
||||
initTheme();
|
||||
}
|
||||
@ -175,7 +176,6 @@ app::Color ColorWheel::getBottomBarColor(const int u, const int umax)
|
||||
void ColorWheel::onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc)
|
||||
{
|
||||
bool oldHarmonyPicked = m_harmonyPicked;
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
|
||||
|
||||
int r = MIN(rc.w/2, rc.h/2);
|
||||
m_wheelRadius = r;
|
||||
@ -183,28 +183,6 @@ void ColorWheel::onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc)
|
||||
rc.y+rc.h/2-r,
|
||||
r*2, r*2);
|
||||
|
||||
int umax = MAX(1, rc.w-1);
|
||||
int vmax = MAX(1, rc.h-1);
|
||||
|
||||
for (int y=0; y<rc.h; ++y) {
|
||||
for (int x=0; x<rc.w; ++x) {
|
||||
app::Color appColor =
|
||||
getMainAreaColor(x, umax,
|
||||
y, vmax);
|
||||
|
||||
gfx::Color color;
|
||||
if (appColor.getType() != app::Color::MaskType) {
|
||||
appColor.setAlpha(255);
|
||||
color = color_utils::color_for_ui(appColor);
|
||||
}
|
||||
else {
|
||||
color = theme->colors.editorFace();
|
||||
}
|
||||
|
||||
g->putPixel(color, rc.x+x, rc.y+y);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_color.getAlpha() > 0) {
|
||||
if (m_colorModel == ColorModel::NORMAL_MAP) {
|
||||
double angle = std::atan2(m_color.getGreen()-128,
|
||||
@ -253,16 +231,6 @@ void ColorWheel::onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc)
|
||||
|
||||
void ColorWheel::onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc)
|
||||
{
|
||||
double hue = m_color.getHsvHue();
|
||||
double sat = m_color.getHsvSaturation();
|
||||
|
||||
for (int x=0; x<rc.w; ++x) {
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(hue, sat, double(x) / double(rc.w)));
|
||||
|
||||
g->drawVLine(color, rc.x+x, rc.y, rc.h);
|
||||
}
|
||||
|
||||
if (m_color.getType() != app::Color::MaskType) {
|
||||
double val = m_color.getHsvValue();
|
||||
gfx::Point pos(rc.x + int(double(rc.w) * val),
|
||||
@ -271,8 +239,74 @@ void ColorWheel::onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc)
|
||||
}
|
||||
}
|
||||
|
||||
void ColorWheel::onPaintSurfaceInBgThread(she::Surface* s,
|
||||
const gfx::Rect& main,
|
||||
const gfx::Rect& bottom,
|
||||
const gfx::Rect& alpha,
|
||||
bool& stop)
|
||||
{
|
||||
if (m_paintFlags & MainAreaFlag) {
|
||||
int umax = MAX(1, main.w-1);
|
||||
int vmax = MAX(1, main.h-1);
|
||||
|
||||
for (int y=0; y<main.h && !stop; ++y) {
|
||||
for (int x=0; x<main.w && !stop; ++x) {
|
||||
app::Color appColor =
|
||||
getMainAreaColor(x, umax,
|
||||
y, vmax);
|
||||
|
||||
gfx::Color color;
|
||||
if (appColor.getType() != app::Color::MaskType) {
|
||||
appColor.setAlpha(255);
|
||||
color = color_utils::color_for_ui(appColor);
|
||||
}
|
||||
else {
|
||||
color = m_bgColor;
|
||||
}
|
||||
|
||||
s->putPixel(color, main.x+x, main.y+y);
|
||||
}
|
||||
}
|
||||
if (stop)
|
||||
return;
|
||||
m_paintFlags ^= MainAreaFlag;
|
||||
}
|
||||
|
||||
if (m_paintFlags & BottomBarFlag) {
|
||||
double hue = m_color.getHsvHue();
|
||||
double sat = m_color.getHsvSaturation();
|
||||
|
||||
for (int x=0; x<bottom.w && !stop; ++x) {
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(hue, sat, double(x) / double(bottom.w)));
|
||||
|
||||
s->drawVLine(color, bottom.x+x, bottom.y, bottom.h);
|
||||
}
|
||||
if (stop)
|
||||
return;
|
||||
m_paintFlags ^= BottomBarFlag;
|
||||
}
|
||||
|
||||
// Paint alpha bar
|
||||
ColorSelector::onPaintSurfaceInBgThread(s, main, bottom, alpha, stop);
|
||||
}
|
||||
|
||||
int ColorWheel::onNeedsSurfaceRepaint(const app::Color& newColor)
|
||||
{
|
||||
return
|
||||
// Only if the saturation changes we have to redraw the main surface.
|
||||
(m_colorModel != ColorModel::NORMAL_MAP &&
|
||||
cs_double_diff(m_color.getHsvValue(), newColor.getHsvValue()) ? MainAreaFlag: 0) |
|
||||
(cs_double_diff(m_color.getHsvHue(), newColor.getHsvHue()) ||
|
||||
cs_double_diff(m_color.getHsvSaturation(), newColor.getHsvSaturation()) ? BottomBarFlag: 0) |
|
||||
ColorSelector::onNeedsSurfaceRepaint(newColor);
|
||||
}
|
||||
|
||||
void ColorWheel::setDiscrete(bool state)
|
||||
{
|
||||
if (m_discrete != state)
|
||||
m_paintFlags = AllAreasFlag;
|
||||
|
||||
m_discrete = state;
|
||||
Preferences::instance().colorBar.discreteWheel(m_discrete);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -47,6 +47,12 @@ namespace app {
|
||||
app::Color getBottomBarColor(const int u, const int umax) override;
|
||||
void onPaintMainArea(ui::Graphics* g, const gfx::Rect& rc) override;
|
||||
void onPaintBottomBar(ui::Graphics* g, const gfx::Rect& rc) override;
|
||||
void onPaintSurfaceInBgThread(she::Surface* s,
|
||||
const gfx::Rect& main,
|
||||
const gfx::Rect& bottom,
|
||||
const gfx::Rect& alpha,
|
||||
bool& stop) override;
|
||||
int onNeedsSurfaceRepaint(const app::Color& newColor) override;
|
||||
bool subColorPicked() override { return m_harmonyPicked; }
|
||||
|
||||
private:
|
||||
@ -61,6 +67,7 @@ namespace app {
|
||||
int convertHueAngle(int angle, int dir) const;
|
||||
|
||||
gfx::Rect m_wheelBounds;
|
||||
gfx::Color m_bgColor;
|
||||
int m_wheelRadius;
|
||||
bool m_discrete;
|
||||
ColorModel m_colorModel;
|
||||
|
Loading…
Reference in New Issue
Block a user