/* Crafter®.Graphics Copyright (C) 2025 Catcrafts® Catcrafts.net This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ module Crafter.Graphics:RenderingElement_impl; import :RenderingElement; import :Window; import :Types; import :Font; import std; using namespace Crafter; RenderingElement::RenderingElement(bool opaque) : Transform(), opaque(opaque) { } RenderingElement::RenderingElement(bool opaque, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : Transform(anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling), opaque(opaque) { } RenderingElementPreScaled::RenderingElementPreScaled(bool opaque) : RenderingElement(opaque) { } RenderingElementPreScaled::RenderingElementPreScaled(bool opaque, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : RenderingElement(opaque, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling) { } RenderingElementScaling::RenderingElementScaling(bool opaque) : RenderingElement(opaque) { } RenderingElementScaling::RenderingElementScaling(bool opaque, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : RenderingElement(opaque, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling) { } RenderingElementScaling::RenderingElementScaling(bool opaque, std::uint_fast32_t bufferWidth, std::uint_fast32_t bufferHeight, std::int_fast32_t anchorX, std::int_fast32_t anchorY, std::uint_fast32_t relativeWidth, std::uint_fast32_t relativeHeight, std::int_fast32_t anchorOffsetX, std::int_fast32_t anchorOffsetY, std::int_fast32_t z, bool ignoreScaling) : bufferWidth(bufferWidth), bufferHeight(bufferHeight), buffer(bufferWidth*bufferHeight), RenderingElement(opaque, anchorX, anchorY, relativeWidth, relativeHeight, anchorOffsetX, anchorOffsetY, z, ignoreScaling) { } void RenderingElementPreScaled::UpdatePosition(Window& window) { ScaleData oldScale = scaled; window.ScaleElement(*this); if(oldScale.width != scaled.width || oldScale.height != scaled.height) { bufferScaled.resize(scaled.width * scaled.height); window.AddDirtyRect(oldScale); window.AddDirtyRect(scaled); } else if(oldScale.x != scaled.x || oldScale.y != scaled.y) { window.AddDirtyRect(oldScale); window.AddDirtyRect(scaled); } for(Transform* child : children) { child->UpdatePosition(window, *this); } } void RenderingElementPreScaled::UpdatePosition(Window& window, Transform& parent) { ScaleData oldScale = scaled; window.ScaleElement(*this, parent); if(oldScale.width != scaled.width || oldScale.height != scaled.height) { bufferScaled.resize(scaled.width * scaled.height); window.AddDirtyRect(oldScale); window.AddDirtyRect(scaled); } else if(oldScale.x != scaled.x || oldScale.y != scaled.y) { window.AddDirtyRect(oldScale); window.AddDirtyRect(scaled); } for(Transform* child : children) { child->UpdatePosition(window, *this); } } void RenderingElementPreScaled::CopyNearestNeighbour(Pixel_BU8_GU8_RU8_AU8* dst, std::uint_fast32_t dstWidth, std::uint_fast32_t dstHeight) const { for (std::uint_fast32_t y = 0; y < dstHeight; y++) { std::uint_fast32_t srcY = y * scaled.height / dstHeight; for (std::uint_fast32_t x = 0; x < dstWidth; x++) { std::uint_fast32_t srcX = x * scaled.width / dstWidth; dst[y * dstWidth + x] = bufferScaled[srcY * scaled.width + srcX]; } } } void RenderingElementScaling::CopyNearestNeighbour(Pixel_BU8_GU8_RU8_AU8* dst, std::uint_fast32_t dstWidth, std::uint_fast32_t dstHeight) const { for (std::uint_fast32_t y = 0; y < dstHeight; y++) { std::uint_fast32_t srcY = y * bufferHeight / dstHeight; for (std::uint_fast32_t x = 0; x < dstWidth; x++) { std::uint_fast32_t srcX = x * bufferWidth / dstWidth; dst[y * dstWidth + x] = buffer[srcY * bufferWidth + srcX]; } } } void RenderingElementScaling::UpdatePosition(Window& window) { ScaleData oldScale = scaled; window.ScaleElement(*this); if(oldScale.width != scaled.width || oldScale.height != scaled.height) { bufferScaled.resize(scaled.width * scaled.height); CopyNearestNeighbour(bufferScaled.data(), scaled.width, scaled.height); window.AddDirtyRect(oldScale); window.AddDirtyRect(scaled); } else if(oldScale.x != scaled.x || oldScale.y != scaled.y) { window.AddDirtyRect(oldScale); window.AddDirtyRect(scaled); } for(Transform* child : children) { child->UpdatePosition(window, *this); } } void RenderingElementScaling::UpdatePosition(Window& window, Transform& parent) { ScaleData oldScale = scaled; window.ScaleElement(*this, parent); if(oldScale.width != scaled.width || oldScale.height != scaled.height) { bufferScaled.resize(scaled.width * scaled.height); CopyNearestNeighbour(bufferScaled.data(), scaled.width, scaled.height); window.AddDirtyRect(oldScale); window.AddDirtyRect(scaled); } else if(oldScale.x != scaled.x || oldScale.y != scaled.y) { window.AddDirtyRect(oldScale); window.AddDirtyRect(scaled); } for(Transform* child : children) { child->UpdatePosition(window, *this); } } void RenderingElementScaling::ResizeBuffer(std::uint_fast32_t width, std::uint_fast32_t height) { this->bufferWidth = width; this->bufferHeight = height; buffer.resize(width * height); }