From b43fbe224969400a55f818e335f8ba8940ce0379 Mon Sep 17 00:00:00 2001 From: David Capello Date: Mon, 17 Jul 2023 19:37:27 -0300 Subject: [PATCH] Add simple rendering of tiles w/flags (x/y/d flip) --- src/render/render.cpp | 166 +++++++++++++++++++++++++++++++++++------- src/render/render.h | 12 ++- 2 files changed, 148 insertions(+), 30 deletions(-) diff --git a/src/render/render.cpp b/src/render/render.cpp index 45324d8f6..f9a50d99a 100644 --- a/src/render/render.cpp +++ b/src/render/render.cpp @@ -155,7 +155,8 @@ void composite_image_without_scale( const BlendMode blendMode, const double sx, const double sy, - const bool newBlend) + const bool newBlend, + const tile_flags) // Ignored { ASSERT(dst); ASSERT(src); @@ -178,9 +179,9 @@ void composite_image_without_scale( // Lock all necessary bits const LockImageBits srcBits(src, srcBounds); LockImageBits dstBits(dst, dstBounds); - typename LockImageBits::const_iterator src_it = srcBits.begin(); + auto src_it = srcBits.begin(); #ifdef _DEBUG - typename LockImageBits::const_iterator src_end = srcBits.end(); + auto src_end = srcBits.end(); #endif typename LockImageBits::iterator dst_it, dst_end; @@ -211,7 +212,8 @@ void composite_image_scale_up( const BlendMode blendMode, const double sx, const double sy, - const bool newBlend) + const bool newBlend, + const tile_flags) // Ignored { ASSERT(dst); ASSERT(src); @@ -363,7 +365,8 @@ void composite_image_scale_down( const BlendMode blendMode, const double sx, const double sy, - const bool newBlend) + const bool newBlend, + const tile_flags) // Ignored { ASSERT(dst); ASSERT(src); @@ -431,7 +434,8 @@ void composite_image_general( const BlendMode blendMode, const double sx, const double sy, - const bool newBlend) + const bool newBlend, + const tile_flags) // Ignored { ASSERT(dst); ASSERT(src); @@ -498,10 +502,106 @@ void composite_image_general( } template -CompositeImageFunc get_fastest_composition_path(const Projection& proj, - const bool finegrain) +void composite_image_general_with_tile_flags( + Image* dst, const Image* src, const Palette* pal, + const gfx::ClipF& areaF, + const int opacity, + const BlendMode blendMode, + const double sx, + const double sy, + const bool newBlend, + const tile_flags tileFlags) { - if (finegrain || !proj.zoom().isSimpleZoomLevel()) { + ASSERT(dst); + ASSERT(src); + ASSERT(DstTraits::pixel_format == dst->pixelFormat()); + ASSERT(SrcTraits::pixel_format == src->pixelFormat()); + + gfx::ClipF area(areaF); + if (!area.clip(dst->width(), dst->height(), + sx*src->width(), sy*src->height())) + return; + + BlenderHelper blender(src, pal, blendMode, newBlend); + + gfx::Rect dstBounds( + area.dstBounds().x, area.dstBounds().y, + int(std::ceil(area.dstBounds().w)), + int(std::ceil(area.dstBounds().h))); + gfx::Rect srcBounds = area.srcBounds(); + const gfx::Size srcMinSize = src->size(); + + dstBounds &= dst->bounds(); + + if (tileFlags & tile_f_xflip) { + srcBounds.x = src->bounds().x2()-srcBounds.w-srcBounds.x; + } + if (tileFlags & tile_f_yflip) { + srcBounds.y = src->bounds().y2()-srcBounds.h-srcBounds.y; + } + + int dstY = dstBounds.y; + + for (int y=0; y= 0 && dstY < dst->height()); + + auto dstPtr = get_pixel_address_fast(dst, dstBounds.x, dstY); + +#if _DEBUG + int dstX = dstBounds.x; +#endif + + for (int x=0; x= 0 && dstX < dst->width()); + + if (srcX >= 0 && srcX < minSize.w && + srcY >= 0 && srcY < minSize.h) { + auto srcPtr = get_pixel_address_fast(src, srcX, srcY); + *dstPtr = blender(*dstPtr, *srcPtr, opacity); + } + else { + *dstPtr = 0; + } +#if _DEBUG + ++dstX; +#endif + } + } +} + +template +CompositeImageFunc get_fastest_composition_path(const Projection& proj, + const bool finegrain, + const tile_flags tileFlags) +{ + if (tileFlags) { + return composite_image_general_with_tile_flags; + } + else if (finegrain || !proj.zoom().isSimpleZoomLevel()) { return composite_image_general; } else if (proj.applyX(1) == 1 && proj.applyY(1) == 1) { @@ -976,10 +1076,12 @@ void Render::renderImage( const int opacity, const BlendMode blendMode) { + const tile_flags tileFlags = 0; + CompositeImageFunc compositeImage = getImageComposition( dst_image->pixelFormat(), - src_image->pixelFormat(), nullptr); + src_image->pixelFormat(), nullptr, tileFlags); if (!compositeImage) return; @@ -991,7 +1093,8 @@ void Render::renderImage( opacity, blendMode, m_proj.scaleX(), m_proj.scaleY(), - m_newBlendMethod); + m_newBlendMethod, + tileFlags); } void Render::renderPlan( @@ -1297,7 +1400,7 @@ void Render::renderCel( continue; renderImage(dst_image, tile_image.get(), pal, tileBoundsOnCanvas, - area, compositeImage, opacity, blendMode); + area, compositeImage, opacity, blendMode, tile_getf(t)); } } } @@ -1315,15 +1418,24 @@ void Render::renderImage( const Palette* pal, const gfx::RectF& celBounds, const gfx::Clip& area, - const CompositeImageFunc compositeImage, + CompositeImageFunc compositeImage, const int opacity, - const BlendMode blendMode) + const BlendMode blendMode, + const tile_flags tileFlags) { gfx::RectF scaledBounds = m_proj.apply(celBounds); gfx::RectF srcBounds = gfx::RectF(area.srcBounds()).createIntersection(scaledBounds); if (srcBounds.isEmpty()) return; + // Get the function to composite the tile with the given flip flags + if (tileFlags) { + compositeImage = getImageComposition( + dst_image->pixelFormat(), + cel_image->pixelFormat(), + nullptr, tileFlags); + } + compositeImage( dst_image, cel_image, pal, gfx::ClipF( @@ -1337,13 +1449,15 @@ void Render::renderImage( blendMode, m_proj.scaleX() * celBounds.w / double(cel_image->width()), m_proj.scaleY() * celBounds.h / double(cel_image->height()), - m_newBlendMethod); + m_newBlendMethod, + tileFlags); } CompositeImageFunc Render::getImageComposition( const PixelFormat dstFormat, const PixelFormat srcFormat, - const Layer* layer) + const Layer* layer, + const tile_flags tileFlags) { // True if we need blending pixel by pixel. If this is false we can // blend src+dst one time and repeat the resulting color in dst @@ -1362,32 +1476,32 @@ CompositeImageFunc Render::getImageComposition( case IMAGE_RGB: switch (dstFormat) { - case IMAGE_RGB: return get_fastest_composition_path(m_proj, finegrain); - case IMAGE_GRAYSCALE: return get_fastest_composition_path(m_proj, finegrain); - case IMAGE_INDEXED: return get_fastest_composition_path(m_proj, finegrain); + case IMAGE_RGB: return get_fastest_composition_path(m_proj, finegrain, tileFlags); + case IMAGE_GRAYSCALE: return get_fastest_composition_path(m_proj, finegrain, tileFlags); + case IMAGE_INDEXED: return get_fastest_composition_path(m_proj, finegrain, tileFlags); } break; case IMAGE_GRAYSCALE: switch (dstFormat) { - case IMAGE_RGB: return get_fastest_composition_path(m_proj, finegrain); - case IMAGE_GRAYSCALE: return get_fastest_composition_path(m_proj, finegrain); - case IMAGE_INDEXED: return get_fastest_composition_path(m_proj, finegrain); + case IMAGE_RGB: return get_fastest_composition_path(m_proj, finegrain, tileFlags); + case IMAGE_GRAYSCALE: return get_fastest_composition_path(m_proj, finegrain, tileFlags); + case IMAGE_INDEXED: return get_fastest_composition_path(m_proj, finegrain, tileFlags); } break; case IMAGE_INDEXED: switch (dstFormat) { - case IMAGE_RGB: return get_fastest_composition_path(m_proj, finegrain); - case IMAGE_GRAYSCALE: return get_fastest_composition_path(m_proj, finegrain); - case IMAGE_INDEXED: return get_fastest_composition_path(m_proj, finegrain); + case IMAGE_RGB: return get_fastest_composition_path(m_proj, finegrain, tileFlags); + case IMAGE_GRAYSCALE: return get_fastest_composition_path(m_proj, finegrain, tileFlags); + case IMAGE_INDEXED: return get_fastest_composition_path(m_proj, finegrain, tileFlags); } break; case IMAGE_TILEMAP: switch (dstFormat) { case IMAGE_TILEMAP: - return get_fastest_composition_path(m_proj, finegrain); + return get_fastest_composition_path(m_proj, finegrain, tileFlags); } break; } diff --git a/src/render/render.h b/src/render/render.h index fb6d6c0f5..c6c4212ad 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -15,6 +15,7 @@ #include "doc/doc.h" #include "doc/frame.h" #include "doc/pixel_format.h" +#include "doc/tile.h" #include "gfx/clip.h" #include "gfx/point.h" #include "gfx/size.h" @@ -45,7 +46,8 @@ namespace render { const BlendMode blendMode, const double sx, const double sy, - const bool newBlend); + const bool newBlend, + const tile_flags tileFlags); class Render { enum Flags { @@ -187,14 +189,16 @@ namespace render { const Palette* pal, const gfx::RectF& celBounds, const gfx::Clip& area, - const CompositeImageFunc compositeImage, + CompositeImageFunc compositeImage, const int opacity, - const BlendMode blendMode); + const BlendMode blendMode, + const tile_flags tileFlags = notile); CompositeImageFunc getImageComposition( const PixelFormat dstFormat, const PixelFormat srcFormat, - const Layer* layer); + const Layer* layer, + const tile_flags tileFlags = notile); bool checkIfWeShouldUsePreview(const Cel* cel) const;