diff --git a/src/app/script/graphics_context.cpp b/src/app/script/graphics_context.cpp index 4b6e2244a..9cfc1af85 100644 --- a/src/app/script/graphics_context.cpp +++ b/src/app/script/graphics_context.cpp @@ -29,6 +29,36 @@ namespace app { 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) { if (auto theme = skin::SkinTheme::instance()) { @@ -59,7 +89,7 @@ void GraphicsContext::drawImage(const doc::Image* img, int x, int y) 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, @@ -429,7 +459,23 @@ int GraphicsContext_set_antialias(lua_State* L) int GraphicsContext_get_color(lua_State* L) { auto gc = get_obj(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; } diff --git a/src/app/script/graphics_context.h b/src/app/script/graphics_context.h index 06ef17961..9037c04a3 100644 --- a/src/app/script/graphics_context.h +++ b/src/app/script/graphics_context.h @@ -9,6 +9,7 @@ #pragma once #include "doc/palette.h" +#include "doc/pixel_format.h" #include "gfx/path.h" #include "os/paint.h" #include "os/surface.h" @@ -31,7 +32,10 @@ private: }; public: - GraphicsContext(const os::SurfaceRef& surface, int uiscale) : m_surface(surface), m_uiscale(uiscale) { } + GraphicsContext(const os::SurfaceRef& surface, + 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; @@ -39,6 +43,7 @@ public: 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 { @@ -46,6 +51,7 @@ public: std::swap(m_paint, gc.m_paint); std::swap(m_font, gc.m_font); std::swap(m_path, gc.m_path); + m_formatHint = gc.m_formatHint; m_uiscale = gc.m_uiscale; } @@ -77,7 +83,7 @@ public: void antialias(bool value) { m_paint.antialias(value); } 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(); } void strokeWidth(float value) { m_paint.strokeWidth(value); } @@ -142,6 +148,10 @@ public: return m_uiscale; } + doc::PixelFormat formatHint() const { + return m_formatHint; + } + private: os::SurfaceRef m_surface = nullptr; // Keeps the UI Scale currently in use when canvas autoScaling is enabled. @@ -151,6 +161,8 @@ private: gfx::Path m_path; std::stack m_saved; 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 diff --git a/src/app/script/image_class.cpp b/src/app/script/image_class.cpp index 4ee82895e..fdc955c16 100644 --- a/src/app/script/image_class.cpp +++ b/src/app/script/image_class.cpp @@ -757,7 +757,7 @@ int Image_get_context(lua_State* L) if (!obj->context) { auto surface = wrap_docimage_in_surface(obj->image(L)); - obj->context = std::make_unique(surface, ui::guiscale()); + obj->context = std::make_unique(surface, ui::guiscale(), obj->image(L)->pixelFormat()); } push_obj(L, *obj->context);