diff --git a/src/app/color.cpp b/src/app/color.cpp index 437972eb1..a8fdd97b5 100644 --- a/src/app/color.cpp +++ b/src/app/color.cpp @@ -84,13 +84,21 @@ Color Color::fromGray(int g, int a) // static Color Color::fromIndex(int index) { - ASSERT(index >= 0 || index == doc::notile); + ASSERT(index >= 0); Color color(Color::IndexType); color.m_value.index = index; return color; } +// static +Color Color::fromTile(doc::tile_t tile) +{ + Color color(Color::TileType); + color.m_value.tile = tile; + return color; +} + // static Color Color::fromImage(PixelFormat pixelFormat, color_t c) { @@ -115,9 +123,12 @@ Color Color::fromImage(PixelFormat pixelFormat, color_t c) break; case IMAGE_INDEXED: - case IMAGE_TILEMAP: color = Color::fromIndex(c); break; + + case IMAGE_TILEMAP: + color = Color::fromTile(c); + break; } return color; @@ -869,12 +880,28 @@ int Color::getIndex() const case Color::IndexType: return m_value.index; + case Color::TileType: + return doc::tile_geti(m_value.tile); + } ASSERT(false); return -1; } +doc::tile_t Color::getTile() const +{ + switch (getType()) { + + case Color::TileType: + return m_value.tile; + + } + + ASSERT(false); + return doc::notile; +} + int Color::getAlpha() const { switch (getType()) { diff --git a/src/app/color.h b/src/app/color.h index 2b6d12d1a..38502cdf1 100644 --- a/src/app/color.h +++ b/src/app/color.h @@ -11,6 +11,7 @@ #include "doc/color.h" #include "doc/pixel_format.h" +#include "doc/tile.h" #include @@ -30,6 +31,7 @@ namespace app { HslType, GrayType, IndexType, + TileType, }; enum HumanReadableString { @@ -46,6 +48,7 @@ namespace app { static Color fromHsl(double h, double s, double l, int a = 255); // h=[0,360], s=[0,1], v=[0,1] static Color fromGray(int g, int a = 255); static Color fromIndex(int index); + static Color fromTile(doc::tile_t tile); static Color fromImage(doc::PixelFormat pixelFormat, doc::color_t c); static Color fromImageGetPixel(doc::Image* image, int x, int y); @@ -79,6 +82,7 @@ namespace app { double getHslLightness() const; int getGray() const; int getIndex() const; + doc::tile_t getTile() const; int getAlpha() const; // Setters @@ -107,6 +111,7 @@ namespace app { int g, a; } gray; int index; + doc::tile_t tile; } m_value; }; diff --git a/src/app/color_picker.cpp b/src/app/color_picker.cpp index d780a8d35..20aa142af 100644 --- a/src/app/color_picker.cpp +++ b/src/app/color_picker.cpp @@ -63,10 +63,14 @@ bool get_cel_pixel(const Cel* cel, if (!image->bounds().contains(tilePos)) return false; - const doc::tile_index ti = + const doc::tile_index t = get_pixel(image, tilePos.x, tilePos.y); - PICKER_TRACE("PICKER: tile index=%d\n", ti); + // TODO take care of flip flags + + const doc::tile_index ti = doc::tile_geti(t); + + PICKER_TRACE("PICKER: tile=%d index=%d\n", t, ti); doc::ImageRef tile = layerTilemap->tileset()->get(ti); if (!tile) @@ -143,7 +147,7 @@ void ColorPicker::pickColor(const Site& site, const gfx::Point tilePos = site.grid().canvasToTile(gfx::Point(pos)); if (cels.front()->image()->bounds().contains(tilePos)) { m_tile = doc::get_pixel(cels.front()->image(), tilePos.x, tilePos.y); - m_color = app::Color::fromIndex(m_tile); + m_color = app::Color::fromTile(m_tile); } } else if (site.tilemapMode() == TilemapMode::Pixels) { @@ -166,7 +170,7 @@ void ColorPicker::pickColor(const Site& site, const gfx::Point tilePos = site.grid().canvasToTile(gfx::Point(pos)); if (cel->image()->bounds().contains(tilePos)) { m_tile = doc::get_pixel(cel->image(), tilePos.x, tilePos.y); - m_color = app::Color::fromIndex(m_tile); + m_color = app::Color::fromTile(m_tile); } } else if (site.tilemapMode() == TilemapMode::Pixels) { diff --git a/src/app/modules/gfx.cpp b/src/app/modules/gfx.cpp index 1cff142b1..9990158b1 100644 --- a/src/app/modules/gfx.cpp +++ b/src/app/modules/gfx.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2018-2022 Igara Studio S.A. +// Copyright (C) 2018-2023 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of @@ -212,20 +212,22 @@ void draw_tile(ui::Graphics* g, if (tile == doc::notile) return; - doc::Tileset* ts = site.tileset(); + const doc::Tileset* ts = site.tileset(); if (!ts) return; - doc::tile_index ti = doc::tile_geti(tile); + const doc::tile_index ti = doc::tile_geti(tile); if (ti < 0 || ti >= ts->size()) return; - doc::ImageRef tileImage = ts->get(ti); + const doc::ImageRef tileImage = ts->get(ti); if (!tileImage) return; - const int w = tileImage->width(); - const int h = tileImage->height(); + const doc::tile_index tf = doc::tile_getf(tile); + + int w = tileImage->width(); + int h = tileImage->height(); 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); @@ -239,8 +241,41 @@ void draw_tile(ui::Graphics* g, os::Sampling::Mipmap::Nearest); } - g->drawSurface(surface.get(), gfx::Rect(0, 0, w, h), rc, - os::Sampling(), &paint); + gfx::Matrix m; + + if (tf & doc::tile_f_dflip) { + gfx::Matrix rot; + rot.setRotate(90.0f); + rot.postConcat(gfx::Matrix::MakeScale(-1.0f, 1.0f)); + m.preConcat(rot); + std::swap(w, h); + } + + if (tf & doc::tile_f_xflip) { + gfx::Matrix flip; + flip.setScale(-1.0f, 1.0f, w/float(2.0f), 0.0f); + m.postConcat(flip); + } + + if (tf & doc::tile_f_yflip) { + gfx::Matrix flip; + flip.setScale(1.0f, -1.0f, 0.0f, h/float(2.0f)); + m.postConcat(flip); + } + + m.postConcat(gfx::Matrix::MakeScale(float(rc.w) / w, + float(rc.h) / h)); + + // TODO integrate getInternalDeltaX/Y translation in ui::Graphics + m.postConcat(gfx::Matrix::MakeTrans(rc.x+g->getInternalDeltaX(), + rc.y+g->getInternalDeltaY())); + + g->save(); + g->setMatrix(m); + g->drawRgbaSurface(surface.get(), + -g->getInternalDeltaX(), + -g->getInternalDeltaY()); + g->restore(); } void draw_tile_button(ui::Graphics* g, diff --git a/src/app/modules/gfx.h b/src/app/modules/gfx.h index d9fa28ea5..69ac94928 100644 --- a/src/app/modules/gfx.h +++ b/src/app/modules/gfx.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2019-2022 Igara Studio S.A. +// Copyright (C) 2019-2023 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This program is distributed under the terms of diff --git a/src/app/ui/editor/tool_loop_impl.cpp b/src/app/ui/editor/tool_loop_impl.cpp index 75dab265e..33eefd08b 100644 --- a/src/app/ui/editor/tool_loop_impl.cpp +++ b/src/app/ui/editor/tool_loop_impl.cpp @@ -856,8 +856,8 @@ tools::ToolLoop* create_tool_loop( // Get fg/bg colors ColorBar* colorbar = ColorBar::instance(); if (site.tilemapMode() == TilemapMode::Tiles) { - params.fg = app::Color::fromIndex(colorbar->getFgTile()); // TODO Color::fromTileIndex? - params.bg = app::Color::fromIndex(colorbar->getBgTile()); + params.fg = app::Color::fromTile(colorbar->getFgTile()); + params.bg = app::Color::fromTile(colorbar->getBgTile()); } else { params.fg = colorbar->getFgColor(); @@ -1051,8 +1051,8 @@ tools::ToolLoop* create_tool_loop_preview( // Get fg/bg colors ColorBar* colorbar = ColorBar::instance(); if (site.tilemapMode() == TilemapMode::Tiles) { - params.fg = app::Color::fromIndex(colorbar->getFgTile()); // TODO Color::fromTileIndex? - params.bg = app::Color::fromIndex(colorbar->getBgTile()); + params.fg = app::Color::fromTile(colorbar->getFgTile()); + params.bg = app::Color::fromTile(colorbar->getBgTile()); } else { params.fg = colorbar->getFgColor(); diff --git a/src/app/ui/status_bar.cpp b/src/app/ui/status_bar.cpp index 871fd46dc..fa9294c5e 100644 --- a/src/app/ui/status_bar.cpp +++ b/src/app/ui/status_bar.cpp @@ -472,6 +472,11 @@ public: } IndicatorsGeneration& add(const app::Color& color) { + // For Color::TileType, use the tile version + if (color.getType() == app::Color::TileType) { + return add(color.getTile()); + } + auto theme = SkinTheme::get(m_indicators); // Eyedropper icon diff --git a/src/doc/sprite.cpp b/src/doc/sprite.cpp index 9c22b3412..d97ad4806 100644 --- a/src/doc/sprite.cpp +++ b/src/doc/sprite.cpp @@ -700,13 +700,14 @@ void Sprite::pickCels(const gfx::PointF& pos, const Grid grid = cel->grid(); tile_t tile = notile; - gfx::Point tilePos = grid.canvasToTile(gfx::Point(pos)); + const gfx::Point tilePos = grid.canvasToTile(gfx::Point(pos)); if (image->bounds().contains(tilePos.x, tilePos.y)) tile = image->getPixel(tilePos.x, tilePos.y); if (tile == notile) continue; - image = tileset->get(tile).get(); + const tile_index ti = tile_geti(tile); + image = tileset->get(ti).get(); if (!image) continue; diff --git a/src/render/render.cpp b/src/render/render.cpp index f9a50d99a..e46554d77 100644 --- a/src/render/render.cpp +++ b/src/render/render.cpp @@ -529,15 +529,16 @@ void composite_image_general_with_tile_flags( int(std::ceil(area.dstBounds().w)), int(std::ceil(area.dstBounds().h))); gfx::Rect srcBounds = area.srcBounds(); + const gfx::Rect srcImgBounds = src->bounds(); const gfx::Size srcMinSize = src->size(); dstBounds &= dst->bounds(); if (tileFlags & tile_f_xflip) { - srcBounds.x = src->bounds().x2()-srcBounds.w-srcBounds.x; + srcBounds.x = sx*srcImgBounds.x2() - srcBounds.x2(); } if (tileFlags & tile_f_yflip) { - srcBounds.y = src->bounds().y2()-srcBounds.h-srcBounds.y; + srcBounds.y = sy*srcImgBounds.y2() - srcBounds.y2(); } int dstY = dstBounds.y; @@ -558,7 +559,7 @@ void composite_image_general_with_tile_flags( srcX = (srcBounds.x2()-1-x) / sx; } else { - srcX = srcBounds.x+x / sx; + srcX = (srcBounds.x+x) / sx; } if (tileFlags & tile_f_yflip) { srcY = (srcBounds.y2()-1-y) / sy;