mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-01 18:00:26 +00:00
parent
db348ea3b5
commit
9cf408541f
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Aseprite -->
|
||||
<!-- Copyright (C) 2018 Igara Studio S.A. -->
|
||||
<!-- Copyright (C) 2018-2019 Igara Studio S.A. -->
|
||||
<!-- Copyright (C) 2001-2018 David Capello -->
|
||||
<gui version="1.3-dev">
|
||||
<!-- Keyboard shortcuts -->
|
||||
@ -53,6 +53,7 @@
|
||||
<key command="ReplaceColor" shortcut="Shift+R" />
|
||||
<key command="HueSaturation" shortcut="Ctrl+U" mac="Cmd+U" />
|
||||
<key command="ConvolutionMatrix" shortcut="F9" />
|
||||
<key command="Outline" shortcut="Shift+O" />
|
||||
<key command="ColorCurve" shortcut="Ctrl+M" />
|
||||
<key command="ColorCurve" shortcut="F10" />
|
||||
<key command="PasteText" shortcut="T" />
|
||||
@ -680,6 +681,7 @@
|
||||
<item command="ColorCurve" text="@.edit_adjustments_color_curve" />
|
||||
</menu>
|
||||
<menu text="@.edit_fx" id="fx_popup_menu">
|
||||
<item command="Outline" text="@.edit_fx_outline" />
|
||||
<item command="ConvolutionMatrix" text="@.edit_fx_convolution_matrix" />
|
||||
<item command="Despeckle" text="@.edit_fx_despeckle" />
|
||||
</menu>
|
||||
|
@ -240,6 +240,7 @@ CloseFile = Close File
|
||||
ColorCurve = Color Curve
|
||||
ColorQuantization = Create Palette from Current Sprite (Color Quantization)
|
||||
ContiguousFill = Switch Contiguous Fill
|
||||
Outline = Outline
|
||||
ConvolutionMatrix = Convolution Matrix
|
||||
Copy = Copy
|
||||
CopyCel = Copy Cel
|
||||
@ -716,6 +717,7 @@ edit_adjustments_brightness_contrast = &Brightness/Contrast...
|
||||
edit_adjustments_hue_saturation = &Hue/Saturation...
|
||||
edit_adjustments_color_curve = &Color Curve...
|
||||
edit_fx = F&X
|
||||
edit_fx_outline = &Outline
|
||||
edit_fx_convolution_matrix = Convolution &Matrix...
|
||||
edit_fx_despeckle = &Despeckle (Median Filter)...
|
||||
edit_insert_text = Insert Text
|
||||
@ -1107,6 +1109,14 @@ ok = &OK
|
||||
apply = &Apply
|
||||
cancel = &Cancel
|
||||
|
||||
[outline]
|
||||
color = Outline Color:
|
||||
outside = Outside
|
||||
inside = Inside
|
||||
circle = Circle
|
||||
square = Square
|
||||
bg_color = Background Color:
|
||||
|
||||
[palette_from_sprite]
|
||||
title = Palette from Sprite
|
||||
new_palette = Create a new palette with a specific number of colors (or less):
|
||||
|
22
data/widgets/outline.xml
Normal file
22
data/widgets/outline.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<!-- Aseprite -->
|
||||
<!-- Copyright (C) 2019 by Igara Studio S.A. -->
|
||||
<gui>
|
||||
<vbox id="outline" expansive="true">
|
||||
<grid columns="2">
|
||||
<label text="@.color" />
|
||||
<colorpicker id="color" cell_align="horizontal" />
|
||||
<label text="@.bg_color" />
|
||||
<colorpicker id="bg_color" cell_align="horizontal" />
|
||||
</grid>
|
||||
<hbox>
|
||||
<vbox>
|
||||
<radio id="circle" text="@.circle" group="1" />
|
||||
<radio id="square" text="@.square" group="1" />
|
||||
</vbox>
|
||||
<vbox>
|
||||
<radio id="outside" text="@.outside" group="2" />
|
||||
<radio id="inside" text="@.inside" group="2" />
|
||||
</vbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</gui>
|
@ -293,6 +293,7 @@ if(ENABLE_UI)
|
||||
commands/filters/cmd_despeckle.cpp
|
||||
commands/filters/cmd_hue_saturation.cpp
|
||||
commands/filters/cmd_invert_color.cpp
|
||||
commands/filters/cmd_outline.cpp
|
||||
commands/filters/cmd_replace_color.cpp
|
||||
commands/filters/color_curve_editor.cpp
|
||||
commands/filters/convolution_matrix_stock.cpp
|
||||
|
@ -105,6 +105,7 @@ FOR_EACH_COMMAND(OpenGroup)
|
||||
FOR_EACH_COMMAND(OpenInFolder)
|
||||
FOR_EACH_COMMAND(OpenWithApp)
|
||||
FOR_EACH_COMMAND(Options)
|
||||
FOR_EACH_COMMAND(Outline)
|
||||
FOR_EACH_COMMAND(PaletteEditor)
|
||||
FOR_EACH_COMMAND(Paste)
|
||||
FOR_EACH_COMMAND(PasteText)
|
||||
|
181
src/app/commands/filters/cmd_outline.cpp
Normal file
181
src/app/commands/filters/cmd_outline.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/color.h"
|
||||
#include "app/color_utils.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/commands/filters/filter_manager_impl.h"
|
||||
#include "app/commands/filters/filter_window.h"
|
||||
#include "app/context.h"
|
||||
#include "app/ini_file.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/ui/color_bar.h"
|
||||
#include "app/ui/color_button.h"
|
||||
#include "base/bind.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "filters/outline_filter.h"
|
||||
#include "ui/button.h"
|
||||
#include "ui/label.h"
|
||||
#include "ui/slider.h"
|
||||
#include "ui/widget.h"
|
||||
#include "ui/window.h"
|
||||
|
||||
#include "outline.xml.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
static const char* ConfigSection = "Outline";
|
||||
|
||||
// Wrapper for ReplaceColorFilter to handle colors in an easy way
|
||||
class OutlineFilterWrapper : public OutlineFilter {
|
||||
public:
|
||||
OutlineFilterWrapper(Layer* layer) : m_layer(layer) { }
|
||||
|
||||
void color(const app::Color& color) {
|
||||
m_color = color;
|
||||
if (m_layer)
|
||||
OutlineFilter::color(color_utils::color_for_layer(color, m_layer));
|
||||
}
|
||||
|
||||
void bgColor(const app::Color& color) {
|
||||
m_bgColor = color;
|
||||
if (m_layer)
|
||||
OutlineFilter::bgColor(color_utils::color_for_layer(color, m_layer));
|
||||
}
|
||||
|
||||
app::Color color() const { return m_color; }
|
||||
app::Color bgColor() const { return m_bgColor; }
|
||||
|
||||
private:
|
||||
Layer* m_layer;
|
||||
app::Color m_color;
|
||||
app::Color m_bgColor;
|
||||
};
|
||||
|
||||
class OutlineWindow : public FilterWindow {
|
||||
public:
|
||||
OutlineWindow(OutlineFilterWrapper& filter,
|
||||
FilterManagerImpl& filterMgr)
|
||||
: FilterWindow("Outline", ConfigSection, &filterMgr,
|
||||
WithChannelsSelector,
|
||||
WithTiledCheckBox,
|
||||
filter.tiledMode())
|
||||
, m_filter(filter) {
|
||||
getContainer()->addChild(&m_panel);
|
||||
|
||||
m_panel.color()->setColor(m_filter.color());
|
||||
m_panel.bgColor()->setColor(m_filter.bgColor());
|
||||
m_panel.outside()->setSelected(m_filter.place() == OutlineFilter::Place::Outside);
|
||||
m_panel.inside()->setSelected(m_filter.place() == OutlineFilter::Place::Inside);
|
||||
m_panel.circle()->setSelected(m_filter.shape() == OutlineFilter::Shape::Circle);
|
||||
m_panel.square()->setSelected(m_filter.shape() == OutlineFilter::Shape::Square);
|
||||
|
||||
m_panel.color()->Change.connect(&OutlineWindow::onColorChange, this);
|
||||
m_panel.bgColor()->Change.connect(&OutlineWindow::onBgColorChange, this);
|
||||
m_panel.outside()->Click.connect([this](ui::Event&){ onPlaceChange(OutlineFilter::Place::Outside); });
|
||||
m_panel.inside()->Click.connect([this](ui::Event&){ onPlaceChange(OutlineFilter::Place::Inside); });
|
||||
m_panel.circle()->Click.connect([this](ui::Event&){ onShapeChange(OutlineFilter::Shape::Circle); });
|
||||
m_panel.square()->Click.connect([this](ui::Event&){ onShapeChange(OutlineFilter::Shape::Square); });
|
||||
}
|
||||
|
||||
private:
|
||||
void onColorChange(const app::Color& color) {
|
||||
m_filter.color(color);
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
void onBgColorChange(const app::Color& color) {
|
||||
m_filter.bgColor(color);
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
void onPlaceChange(OutlineFilter::Place place) {
|
||||
m_filter.place(place);
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
void onShapeChange(OutlineFilter::Shape shape) {
|
||||
m_filter.shape(shape);
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
void setupTiledMode(TiledMode tiledMode) override {
|
||||
m_filter.tiledMode(tiledMode);
|
||||
}
|
||||
|
||||
OutlineFilterWrapper& m_filter;
|
||||
gen::Outline m_panel;
|
||||
};
|
||||
|
||||
class OutlineCommand : public Command {
|
||||
public:
|
||||
OutlineCommand();
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context) override;
|
||||
void onExecute(Context* context) override;
|
||||
};
|
||||
|
||||
OutlineCommand::OutlineCommand()
|
||||
: Command(CommandId::Outline(), CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool OutlineCommand::onEnabled(Context* context)
|
||||
{
|
||||
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::HasActiveSprite);
|
||||
}
|
||||
|
||||
void OutlineCommand::onExecute(Context* context)
|
||||
{
|
||||
Site site = context->activeSite();
|
||||
DocumentPreferences& docPref = Preferences::instance()
|
||||
.document(site.document());
|
||||
|
||||
OutlineFilterWrapper filter(site.layer());
|
||||
filter.place((OutlineFilter::Place)get_config_int(ConfigSection, "Place", int(OutlineFilter::Place::Outside)));
|
||||
filter.shape((OutlineFilter::Shape)get_config_int(ConfigSection, "Shape", int(OutlineFilter::Shape::Circle)));
|
||||
filter.color(get_config_color(ConfigSection, "Color", ColorBar::instance()->getFgColor()));
|
||||
filter.tiledMode(docPref.tiled.mode());
|
||||
filter.bgColor(app::Color::fromMask());
|
||||
if (site.layer() && site.layer()->isBackground() && site.image()) {
|
||||
// TODO configure default pixel (same as Autocrop/Trim refpixel)
|
||||
filter.bgColor(app::Color::fromImage(site.image()->pixelFormat(),
|
||||
site.image()->getPixel(0, 0)));
|
||||
}
|
||||
|
||||
FilterManagerImpl filterMgr(context, &filter);
|
||||
filterMgr.setTarget(
|
||||
site.sprite()->pixelFormat() == IMAGE_INDEXED ?
|
||||
TARGET_INDEX_CHANNEL:
|
||||
TARGET_RED_CHANNEL |
|
||||
TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL |
|
||||
TARGET_GRAY_CHANNEL |
|
||||
TARGET_ALPHA_CHANNEL);
|
||||
|
||||
OutlineWindow window(filter, filterMgr);
|
||||
if (window.doModal()) {
|
||||
set_config_int(ConfigSection, "Place", int(filter.place()));
|
||||
set_config_int(ConfigSection, "Shape", int(filter.shape()));
|
||||
set_config_color(ConfigSection, "Color", filter.color());
|
||||
}
|
||||
}
|
||||
|
||||
Command* CommandFactory::createOutlineCommand()
|
||||
{
|
||||
return new OutlineCommand;
|
||||
}
|
||||
|
||||
} // namespace app
|
@ -10,6 +10,7 @@ add_library(filters-lib
|
||||
hue_saturation_filter.cpp
|
||||
invert_color_filter.cpp
|
||||
median_filter.cpp
|
||||
outline_filter.cpp
|
||||
replace_color_filter.cpp)
|
||||
|
||||
target_link_libraries(filters-lib
|
||||
|
236
src/filters/outline_filter.cpp
Normal file
236
src/filters/outline_filter.cpp
Normal file
@ -0,0 +1,236 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "filters/outline_filter.h"
|
||||
|
||||
#include "doc/image.h"
|
||||
#include "doc/palette.h"
|
||||
#include "doc/rgbmap.h"
|
||||
#include "filters/filter_indexed_data.h"
|
||||
#include "filters/filter_manager.h"
|
||||
#include "filters/neighboring_pixels.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace filters {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
namespace {
|
||||
|
||||
static const int kCircleMatrix = 0272;
|
||||
static const int kSquareMatrix = 0777;
|
||||
|
||||
struct GetPixelsDelegate {
|
||||
color_t bgColor;
|
||||
int transparent; // Transparent pixels
|
||||
int opaque; // Opaque pixels
|
||||
int matrix;
|
||||
int bit;
|
||||
|
||||
void init(color_t bgColor, OutlineFilter::Shape shape) {
|
||||
this->bgColor = bgColor;
|
||||
this->matrix = (shape == OutlineFilter::Shape::Circle ? kCircleMatrix:
|
||||
kSquareMatrix);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
transparent = opaque = 0;
|
||||
bit = 1;
|
||||
}
|
||||
};
|
||||
|
||||
struct GetPixelsDelegateRgba : public GetPixelsDelegate {
|
||||
void operator()(RgbTraits::pixel_t color) {
|
||||
if (rgba_geta(color) == 0 || color == bgColor)
|
||||
transparent += (matrix & bit ? 1: 0);
|
||||
else
|
||||
opaque += (matrix & bit ? 1: 0);
|
||||
bit <<= 1;
|
||||
}
|
||||
};
|
||||
|
||||
struct GetPixelsDelegateGrayscale : public GetPixelsDelegate {
|
||||
void operator()(GrayscaleTraits::pixel_t color) {
|
||||
if (graya_geta(color) == 0 || color == bgColor)
|
||||
transparent += (matrix & bit ? 1: 0);
|
||||
else
|
||||
opaque += (matrix & bit ? 1: 0);
|
||||
bit <<= 1;
|
||||
}
|
||||
};
|
||||
|
||||
struct GetPixelsDelegateIndexed : public GetPixelsDelegate {
|
||||
const Palette* pal;
|
||||
|
||||
GetPixelsDelegateIndexed(const Palette* pal) : pal(pal) { }
|
||||
|
||||
void operator()(IndexedTraits::pixel_t color) {
|
||||
color_t rgba = pal->getEntry(color);
|
||||
if (rgba_geta(rgba) == 0 || color == bgColor)
|
||||
transparent += (matrix & bit ? 1: 0);
|
||||
else
|
||||
opaque += (matrix & bit ? 1: 0);
|
||||
bit <<= 1;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
OutlineFilter::OutlineFilter()
|
||||
: m_place(Place::Outside)
|
||||
, m_shape(Shape::Circle)
|
||||
, m_tiledMode(TiledMode::NONE)
|
||||
, m_color(0)
|
||||
, m_bgColor(0)
|
||||
{
|
||||
}
|
||||
|
||||
const char* OutlineFilter::getName()
|
||||
{
|
||||
return "Outline";
|
||||
}
|
||||
|
||||
void OutlineFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
|
||||
uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
|
||||
int x = filterMgr->x();
|
||||
const int x2 = x+filterMgr->getWidth();
|
||||
const int y = filterMgr->y();
|
||||
Target target = filterMgr->getTarget();
|
||||
int r, g, b, a, n;
|
||||
color_t c;
|
||||
bool isTransparent;
|
||||
|
||||
GetPixelsDelegateRgba delegate;
|
||||
delegate.init(m_bgColor, m_shape);
|
||||
|
||||
for (; x<x2; ++x, ++src_address, ++dst_address) {
|
||||
if (filterMgr->skipPixel())
|
||||
continue;
|
||||
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<RgbTraits>(src, x, y, 3, 3, 1, 1, m_tiledMode, delegate);
|
||||
|
||||
c = *src_address;
|
||||
n = (m_place == Place::Outside ? delegate.opaque: delegate.transparent);
|
||||
isTransparent = (rgba_geta(c) == 0 || c == m_bgColor);
|
||||
|
||||
if ((n >= 1) &&
|
||||
((m_place == Place::Outside && isTransparent) ||
|
||||
(m_place == Place::Inside && !isTransparent))) {
|
||||
r = (target & TARGET_RED_CHANNEL ? rgba_getr(m_color): rgba_getr(c));
|
||||
g = (target & TARGET_GREEN_CHANNEL ? rgba_getg(m_color): rgba_getg(c));
|
||||
b = (target & TARGET_BLUE_CHANNEL ? rgba_getb(m_color): rgba_getb(c));
|
||||
a = (target & TARGET_ALPHA_CHANNEL ? rgba_geta(m_color): rgba_geta(c));
|
||||
c = rgba(r, g, b, a);
|
||||
}
|
||||
|
||||
*dst_address = c;
|
||||
}
|
||||
}
|
||||
|
||||
void OutlineFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
const uint16_t* src_address = (uint16_t*)filterMgr->getSourceAddress();
|
||||
uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress();
|
||||
int x = filterMgr->x();
|
||||
const int x2 = x+filterMgr->getWidth();
|
||||
const int y = filterMgr->y();
|
||||
Target target = filterMgr->getTarget();
|
||||
int k, a, n;
|
||||
color_t c;
|
||||
bool isTransparent;
|
||||
|
||||
GetPixelsDelegateGrayscale delegate;
|
||||
delegate.init(m_bgColor, m_shape);
|
||||
|
||||
for (; x<x2; ++x, ++src_address, ++dst_address) {
|
||||
if (filterMgr->skipPixel())
|
||||
continue;
|
||||
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<GrayscaleTraits>(src, x, y, 3, 3, 1, 1, m_tiledMode, delegate);
|
||||
|
||||
c = *src_address;
|
||||
n = (m_place == Place::Outside ? delegate.opaque: delegate.transparent);
|
||||
isTransparent = (graya_geta(c) == 0 || c == m_bgColor);
|
||||
|
||||
if ((n >= 1) &&
|
||||
((m_place == Place::Outside && isTransparent) ||
|
||||
(m_place == Place::Inside && !isTransparent))) {
|
||||
k = (target & TARGET_GRAY_CHANNEL ? graya_getv(m_color): graya_getv(c));
|
||||
a = (target & TARGET_ALPHA_CHANNEL ? graya_geta(m_color): graya_geta(c));
|
||||
c = graya(k, a);
|
||||
}
|
||||
|
||||
*dst_address = c;
|
||||
}
|
||||
}
|
||||
|
||||
void OutlineFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
const uint8_t* src_address = (uint8_t*)filterMgr->getSourceAddress();
|
||||
uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
|
||||
const Palette* pal = filterMgr->getIndexedData()->getPalette();
|
||||
const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
|
||||
int x = filterMgr->x();
|
||||
const int x2 = x+filterMgr->getWidth();
|
||||
const int y = filterMgr->y();
|
||||
Target target = filterMgr->getTarget();
|
||||
int r, g, b, a, n;
|
||||
color_t c;
|
||||
bool isTransparent;
|
||||
|
||||
GetPixelsDelegateIndexed delegate(pal);
|
||||
delegate.init(m_bgColor, m_shape);
|
||||
|
||||
for (; x<x2; ++x, ++src_address, ++dst_address) {
|
||||
if (filterMgr->skipPixel())
|
||||
continue;
|
||||
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<IndexedTraits>(src, x, y, 3, 3, 1, 1, m_tiledMode, delegate);
|
||||
|
||||
c = *src_address;
|
||||
n = (m_place == Place::Outside ? delegate.opaque: delegate.transparent);
|
||||
|
||||
if (target & TARGET_INDEX_CHANNEL) {
|
||||
isTransparent = (c == m_bgColor);
|
||||
}
|
||||
else {
|
||||
isTransparent = (rgba_geta(pal->getEntry(c)) == 0 || c == m_bgColor);
|
||||
}
|
||||
|
||||
if ((n >= 1) &&
|
||||
((m_place == Place::Outside && isTransparent) ||
|
||||
(m_place == Place::Inside && !isTransparent))) {
|
||||
if (target & TARGET_INDEX_CHANNEL) {
|
||||
c = m_color;
|
||||
}
|
||||
else {
|
||||
c = pal->getEntry(c);
|
||||
r = (target & TARGET_RED_CHANNEL ? rgba_getr(m_color): rgba_getr(c));
|
||||
g = (target & TARGET_GREEN_CHANNEL ? rgba_getg(m_color): rgba_getg(c));
|
||||
b = (target & TARGET_BLUE_CHANNEL ? rgba_getb(m_color): rgba_getb(c));
|
||||
a = (target & TARGET_ALPHA_CHANNEL ? rgba_geta(m_color): rgba_geta(c));
|
||||
c = rgbmap->mapColor(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
*dst_address = c;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace filters
|
52
src/filters/outline_filter.h
Normal file
52
src/filters/outline_filter.h
Normal file
@ -0,0 +1,52 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef FILTERS_INVERT_COLOR_FILTER_H_INCLUDED
|
||||
#define FILTERS_INVERT_COLOR_FILTER_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "doc/color.h"
|
||||
#include "filters/filter.h"
|
||||
#include "filters/tiled_mode.h"
|
||||
|
||||
namespace filters {
|
||||
|
||||
class OutlineFilter : public Filter {
|
||||
public:
|
||||
enum class Place { Outside, Inside };
|
||||
enum class Shape { Circle, Square };
|
||||
|
||||
OutlineFilter();
|
||||
|
||||
void place(const Place place) { m_place = place; }
|
||||
void shape(const Shape shape) { m_shape = shape; }
|
||||
void tiledMode(const TiledMode tiledMode) { m_tiledMode = m_tiledMode; }
|
||||
void color(const doc::color_t color) { m_color = color; }
|
||||
void bgColor(const doc::color_t color) { m_bgColor = color; }
|
||||
|
||||
Place place() const { return m_place; }
|
||||
Shape shape() const { return m_shape; }
|
||||
TiledMode tiledMode() const { return m_tiledMode; }
|
||||
doc::color_t color() const { return m_color; }
|
||||
doc::color_t bgColor() const { return m_bgColor; }
|
||||
|
||||
// Filter implementation
|
||||
const char* getName();
|
||||
void applyToRgba(FilterManager* filterMgr);
|
||||
void applyToGrayscale(FilterManager* filterMgr);
|
||||
void applyToIndexed(FilterManager* filterMgr);
|
||||
|
||||
private:
|
||||
Place m_place;
|
||||
Shape m_shape;
|
||||
TiledMode m_tiledMode;
|
||||
doc::color_t m_color;
|
||||
doc::color_t m_bgColor;
|
||||
};
|
||||
|
||||
} // namespace filters
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user