mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-24 03:40:14 +00:00
Merge branch 'get-gc-from-image' into beta (#4605)
This commit is contained in:
commit
7e504ad5ea
@ -29,6 +29,36 @@
|
|||||||
namespace app {
|
namespace app {
|
||||||
namespace script {
|
namespace script {
|
||||||
|
|
||||||
|
void GraphicsContext::color(gfx::Color color)
|
||||||
|
{
|
||||||
|
switch (m_formatHint) {
|
||||||
|
case doc::PixelFormat::IMAGE_GRAYSCALE:
|
||||||
|
// Underlying SkSurface's color type is kR8G8_unorm_SkColorType, then we
|
||||||
|
// must transform the color to set R to the gray level and G to the
|
||||||
|
// alpha level.
|
||||||
|
color = gfx::rgba(gfx::getr(color), gfx::geta(color), 0);
|
||||||
|
break;
|
||||||
|
case doc::PixelFormat::IMAGE_INDEXED: {
|
||||||
|
// Underlying SkSurface's color type is kAlpha_8_SkColorType, then we
|
||||||
|
// must transform the color to set Alpha to the corresponding index.
|
||||||
|
int i = get_current_palette()->findExactMatch(gfx::getr(color),
|
||||||
|
gfx::getg(color),
|
||||||
|
gfx::getb(color),
|
||||||
|
gfx::geta(color), -1);
|
||||||
|
if (i == -1) {
|
||||||
|
i = get_current_palette()->findBestfit(gfx::getr(color),
|
||||||
|
gfx::getg(color),
|
||||||
|
gfx::getb(color),
|
||||||
|
gfx::geta(color), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
color = gfx::rgba(0, 0, 0, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_paint.color(color);
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsContext::fillText(const std::string& text, int x, int y)
|
void GraphicsContext::fillText(const std::string& text, int x, int y)
|
||||||
{
|
{
|
||||||
if (auto theme = skin::SkinTheme::instance()) {
|
if (auto theme = skin::SkinTheme::instance()) {
|
||||||
@ -59,7 +89,7 @@ void GraphicsContext::drawImage(const doc::Image* img, int x, int y)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawImage(img, img->bounds(), gfx::Rect(x, y, img->size().w, img->size().h));
|
drawImage(img, img->bounds(), gfx::Rect(x, y, img->size().w, img->size().h));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsContext::drawImage(const doc::Image* img,
|
void GraphicsContext::drawImage(const doc::Image* img,
|
||||||
@ -429,7 +459,23 @@ int GraphicsContext_set_antialias(lua_State* L)
|
|||||||
int GraphicsContext_get_color(lua_State* L)
|
int GraphicsContext_get_color(lua_State* L)
|
||||||
{
|
{
|
||||||
auto gc = get_obj<GraphicsContext>(L, 1);
|
auto gc = get_obj<GraphicsContext>(L, 1);
|
||||||
push_obj(L, color_utils::color_from_ui(gc->color()));
|
|
||||||
|
const gfx::Color gcColor = gc->color();
|
||||||
|
app::Color color;
|
||||||
|
switch (gc->formatHint()) {
|
||||||
|
case IMAGE_GRAYSCALE:
|
||||||
|
color = app::Color::fromGray(gfx::getr(gcColor), gfx::geta(gcColor));
|
||||||
|
break;
|
||||||
|
case IMAGE_INDEXED: {
|
||||||
|
const int i = gfx::geta(gcColor);
|
||||||
|
color = app::Color::fromIndex(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IMAGE_RGB:
|
||||||
|
default:
|
||||||
|
color = color_utils::color_from_ui(gcColor);
|
||||||
|
}
|
||||||
|
push_obj(L, color);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "doc/palette.h"
|
#include "doc/palette.h"
|
||||||
|
#include "doc/pixel_format.h"
|
||||||
#include "gfx/path.h"
|
#include "gfx/path.h"
|
||||||
#include "os/paint.h"
|
#include "os/paint.h"
|
||||||
#include "os/surface.h"
|
#include "os/surface.h"
|
||||||
@ -31,12 +32,26 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GraphicsContext(const os::SurfaceRef& surface, int uiscale) : m_surface(surface), m_uiscale(uiscale) { }
|
GraphicsContext(const os::SurfaceRef& surface,
|
||||||
GraphicsContext(GraphicsContext&& gc) {
|
int uiscale,
|
||||||
|
doc::PixelFormat formatHint = doc::PixelFormat::IMAGE_RGB)
|
||||||
|
: m_surface(surface), m_uiscale(uiscale), m_formatHint(formatHint) { }
|
||||||
|
GraphicsContext(const GraphicsContext& gc) {
|
||||||
|
m_surface = gc.m_surface;
|
||||||
|
m_font = gc.m_font;
|
||||||
|
m_paint = gc.m_paint;
|
||||||
|
m_palette = gc.m_palette;
|
||||||
|
m_path = gc.m_path;
|
||||||
|
m_saved = gc.m_saved;
|
||||||
|
m_formatHint = gc.m_formatHint;
|
||||||
|
m_uiscale = gc.m_uiscale;
|
||||||
|
}
|
||||||
|
GraphicsContext(GraphicsContext&& gc) noexcept {
|
||||||
std::swap(m_surface, gc.m_surface);
|
std::swap(m_surface, gc.m_surface);
|
||||||
std::swap(m_paint, gc.m_paint);
|
std::swap(m_paint, gc.m_paint);
|
||||||
std::swap(m_font, gc.m_font);
|
std::swap(m_font, gc.m_font);
|
||||||
std::swap(m_path, gc.m_path);
|
std::swap(m_path, gc.m_path);
|
||||||
|
m_formatHint = gc.m_formatHint;
|
||||||
m_uiscale = gc.m_uiscale;
|
m_uiscale = gc.m_uiscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +83,7 @@ public:
|
|||||||
void antialias(bool value) { m_paint.antialias(value); }
|
void antialias(bool value) { m_paint.antialias(value); }
|
||||||
|
|
||||||
gfx::Color color() const { return m_paint.color(); }
|
gfx::Color color() const { return m_paint.color(); }
|
||||||
void color(gfx::Color color) { m_paint.color(color); }
|
void color(gfx::Color color);
|
||||||
|
|
||||||
float strokeWidth() const { return m_paint.strokeWidth(); }
|
float strokeWidth() const { return m_paint.strokeWidth(); }
|
||||||
void strokeWidth(float value) { m_paint.strokeWidth(value); }
|
void strokeWidth(float value) { m_paint.strokeWidth(value); }
|
||||||
@ -133,6 +148,10 @@ public:
|
|||||||
return m_uiscale;
|
return m_uiscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doc::PixelFormat formatHint() const {
|
||||||
|
return m_formatHint;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
os::SurfaceRef m_surface = nullptr;
|
os::SurfaceRef m_surface = nullptr;
|
||||||
// Keeps the UI Scale currently in use when canvas autoScaling is enabled.
|
// Keeps the UI Scale currently in use when canvas autoScaling is enabled.
|
||||||
@ -142,6 +161,8 @@ private:
|
|||||||
gfx::Path m_path;
|
gfx::Path m_path;
|
||||||
std::stack<State> m_saved;
|
std::stack<State> m_saved;
|
||||||
doc::Palette* m_palette = nullptr;
|
doc::Palette* m_palette = nullptr;
|
||||||
|
// Pixel format hint about the underlying pixels wrapped by m_surface.
|
||||||
|
doc::PixelFormat m_formatHint = doc::PixelFormat::IMAGE_RGB;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace script
|
} // namespace script
|
||||||
|
@ -20,12 +20,14 @@
|
|||||||
#include "app/script/blend_mode.h"
|
#include "app/script/blend_mode.h"
|
||||||
#include "app/script/docobj.h"
|
#include "app/script/docobj.h"
|
||||||
#include "app/script/engine.h"
|
#include "app/script/engine.h"
|
||||||
|
#include "app/script/graphics_context.h"
|
||||||
#include "app/script/luacpp.h"
|
#include "app/script/luacpp.h"
|
||||||
#include "app/script/security.h"
|
#include "app/script/security.h"
|
||||||
#include "app/site.h"
|
#include "app/site.h"
|
||||||
#include "app/tx.h"
|
#include "app/tx.h"
|
||||||
#include "app/util/autocrop.h"
|
#include "app/util/autocrop.h"
|
||||||
#include "app/util/resize_image.h"
|
#include "app/util/resize_image.h"
|
||||||
|
#include "app/util/shader_helpers.h"
|
||||||
#include "base/fs.h"
|
#include "base/fs.h"
|
||||||
#include "doc/algorithm/flip_image.h"
|
#include "doc/algorithm/flip_image.h"
|
||||||
#include "doc/algorithm/flip_type.h"
|
#include "doc/algorithm/flip_type.h"
|
||||||
@ -37,6 +39,7 @@
|
|||||||
#include "doc/primitives.h"
|
#include "doc/primitives.h"
|
||||||
#include "doc/sprite.h"
|
#include "doc/sprite.h"
|
||||||
#include "render/render.h"
|
#include "render/render.h"
|
||||||
|
#include "ui/scale.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -54,6 +57,11 @@ struct ImageObj {
|
|||||||
doc::ObjectId celId = 0;
|
doc::ObjectId celId = 0;
|
||||||
doc::ObjectId tilesetId = 0;
|
doc::ObjectId tilesetId = 0;
|
||||||
doc::tile_index ti = 0;
|
doc::tile_index ti = 0;
|
||||||
|
|
||||||
|
#if LAF_SKIA
|
||||||
|
std::unique_ptr<GraphicsContext> context = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
ImageObj(doc::Image* image)
|
ImageObj(doc::Image* image)
|
||||||
: imageId(image->id()) {
|
: imageId(image->id()) {
|
||||||
}
|
}
|
||||||
@ -742,6 +750,23 @@ int Image_get_cel(lua_State* L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Image_get_context(lua_State* L)
|
||||||
|
{
|
||||||
|
#if LAF_SKIA
|
||||||
|
auto* obj = get_obj<ImageObj>(L, 1);
|
||||||
|
|
||||||
|
if (!obj->context) {
|
||||||
|
auto surface = wrap_docimage_in_surface(obj->image(L));
|
||||||
|
obj->context = std::make_unique<GraphicsContext>(surface, ui::guiscale(), obj->image(L)->pixelFormat());
|
||||||
|
}
|
||||||
|
|
||||||
|
push_obj(L, *obj->context);
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
const luaL_Reg Image_methods[] = {
|
const luaL_Reg Image_methods[] = {
|
||||||
{ "clone", Image_clone },
|
{ "clone", Image_clone },
|
||||||
{ "clear", Image_clear },
|
{ "clear", Image_clear },
|
||||||
@ -774,6 +799,7 @@ const Property Image_properties[] = {
|
|||||||
{ "colorMode", Image_get_colorMode, nullptr },
|
{ "colorMode", Image_get_colorMode, nullptr },
|
||||||
{ "spec", Image_get_spec, nullptr },
|
{ "spec", Image_get_spec, nullptr },
|
||||||
{ "cel", Image_get_cel, nullptr },
|
{ "cel", Image_get_cel, nullptr },
|
||||||
|
{ "context", Image_get_context, nullptr },
|
||||||
{ nullptr, nullptr, nullptr }
|
{ nullptr, nullptr, nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
#if LAF_SKIA
|
#if LAF_SKIA
|
||||||
|
|
||||||
|
#include "os/skia/skia_surface.h"
|
||||||
|
|
||||||
#include "include/core/SkSurface.h"
|
#include "include/core/SkSurface.h"
|
||||||
#if SK_ENABLE_SKSL
|
#if SK_ENABLE_SKSL
|
||||||
#include "include/effects/SkRuntimeEffect.h"
|
|
||||||
#include "src/core/SkRuntimeEffectPriv.h"
|
#include "src/core/SkRuntimeEffectPriv.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -111,6 +112,11 @@ sk_sp<SkSurface> wrap_docimage_in_sksurface(const doc::Image* img)
|
|||||||
img->rowBytes());
|
img->rowBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os::SurfaceRef wrap_docimage_in_surface(const doc::Image* img)
|
||||||
|
{
|
||||||
|
return os::SurfaceRef(new os::SkiaSurface(wrap_docimage_in_sksurface(img)));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
|
||||||
#endif // LAF_SKIA
|
#endif // LAF_SKIA
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "app/color.h"
|
#include "app/color.h"
|
||||||
#include "gfx/color.h"
|
#include "gfx/color.h"
|
||||||
|
#include "os/surface.h"
|
||||||
|
|
||||||
#include "include/core/SkCanvas.h"
|
#include "include/core/SkCanvas.h"
|
||||||
#include "include/core/SkImage.h"
|
#include "include/core/SkImage.h"
|
||||||
@ -94,6 +95,7 @@ SkImageInfo get_skimageinfo_for_docimage(const doc::Image* img);
|
|||||||
sk_sp<SkImage> make_skimage_for_docimage(const doc::Image* img);
|
sk_sp<SkImage> make_skimage_for_docimage(const doc::Image* img);
|
||||||
std::unique_ptr<SkCanvas> make_skcanvas_for_docimage(const doc::Image* img);
|
std::unique_ptr<SkCanvas> make_skcanvas_for_docimage(const doc::Image* img);
|
||||||
sk_sp<SkSurface> wrap_docimage_in_sksurface(const doc::Image* img);
|
sk_sp<SkSurface> wrap_docimage_in_sksurface(const doc::Image* img);
|
||||||
|
os::SurfaceRef wrap_docimage_in_surface(const doc::Image* img);
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
|
||||||
|
@ -534,3 +534,91 @@ do
|
|||||||
2, 3 })
|
2, 3 })
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Test Image.context
|
||||||
|
do
|
||||||
|
-- Draw onto an indexed image
|
||||||
|
do
|
||||||
|
local spec = ImageSpec{
|
||||||
|
width=3, height=4,
|
||||||
|
colorMode=ColorMode.INDEXED,
|
||||||
|
transparentColor=1 }
|
||||||
|
|
||||||
|
local img = Image(spec)
|
||||||
|
local gc = img.context
|
||||||
|
if gc then
|
||||||
|
expect_eq(gc.width, 3)
|
||||||
|
expect_eq(gc.height, 4)
|
||||||
|
|
||||||
|
gc.color = Color{ index=2 }
|
||||||
|
local c = gc.color.index
|
||||||
|
gc.strokeWidth = 1
|
||||||
|
-- Setting blendMode to BlendMode.SRC will make GraphicsContext's painting
|
||||||
|
-- behave correclty for indexed images.
|
||||||
|
gc.blendMode = BlendMode.SRC
|
||||||
|
gc:rect(Rectangle{0,0,1,1})
|
||||||
|
gc:stroke()
|
||||||
|
|
||||||
|
expect_img(img, { c, c, 1,
|
||||||
|
c, c, 1,
|
||||||
|
1, 1, 1,
|
||||||
|
1, 1, 1 })
|
||||||
|
else
|
||||||
|
skipped("GraphicsContext unavailable")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Draw onto a grayscale image
|
||||||
|
do
|
||||||
|
local spec = ImageSpec{
|
||||||
|
width=3, height=4,
|
||||||
|
colorMode=ColorMode.GRAY }
|
||||||
|
|
||||||
|
local img = Image(spec)
|
||||||
|
local gc = img.context
|
||||||
|
if gc then
|
||||||
|
expect_eq(gc.width, 3)
|
||||||
|
expect_eq(gc.height, 4)
|
||||||
|
|
||||||
|
gc.color = Color{ gray=2, alpha=255 }
|
||||||
|
local c = gc.color.grayPixel
|
||||||
|
gc.strokeWidth = 1
|
||||||
|
gc:rect(Rectangle{0,0,1,1})
|
||||||
|
gc:stroke()
|
||||||
|
|
||||||
|
expect_img(img, { c, c, 0,
|
||||||
|
c, c, 0,
|
||||||
|
0, 0, 0,
|
||||||
|
0, 0, 0 })
|
||||||
|
else
|
||||||
|
skipped("GraphicsContext unavailable")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Draw onto an RGB image
|
||||||
|
do
|
||||||
|
local spec = ImageSpec{
|
||||||
|
width=3, height=4,
|
||||||
|
colorMode=ColorMode.RGB }
|
||||||
|
|
||||||
|
local img = Image(spec)
|
||||||
|
local gc = img.context
|
||||||
|
if gc then
|
||||||
|
expect_eq(gc.width, 3)
|
||||||
|
expect_eq(gc.height, 4)
|
||||||
|
|
||||||
|
gc.color = Color(2,0,0,255)
|
||||||
|
local c = gc.color.rgbaPixel
|
||||||
|
gc.strokeWidth = 1
|
||||||
|
gc:rect(Rectangle{0,0,1,1})
|
||||||
|
gc:stroke()
|
||||||
|
|
||||||
|
expect_img(img, { c, c, 0,
|
||||||
|
c, c, 0,
|
||||||
|
0, 0, 0,
|
||||||
|
0, 0, 0 })
|
||||||
|
else
|
||||||
|
skipped("GraphicsContext unavailable")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -288,3 +288,13 @@ function assert_slices_eq(expectedSlices, slices)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Prints a message indicating that the current test was skipped along with
|
||||||
|
-- a level 2 debug traceback.
|
||||||
|
function skipped(reason)
|
||||||
|
local msg = "Test skipped"
|
||||||
|
if reason then
|
||||||
|
msg = msg .. ": " .. reason
|
||||||
|
end
|
||||||
|
print(debug.traceback(msg, 2))
|
||||||
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user