/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Copyright 2011, Blender Foundation. */ #include #include "COM_WrapOperation.h" namespace blender::compositor { WrapOperation::WrapOperation(DataType datatype) : ReadBufferOperation(datatype) { wrapping_type_ = CMP_NODE_WRAP_NONE; } inline float WrapOperation::get_wrapped_original_xpos(float x) { if (this->get_width() == 0) { return 0; } while (x < 0) { x += this->get_width(); } return fmodf(x, this->get_width()); } inline float WrapOperation::get_wrapped_original_ypos(float y) { if (this->get_height() == 0) { return 0; } while (y < 0) { y += this->get_height(); } return fmodf(y, this->get_height()); } void WrapOperation::execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) { float nx, ny; nx = x; ny = y; MemoryBufferExtend extend_x = MemoryBufferExtend::Clip, extend_y = MemoryBufferExtend::Clip; switch (wrapping_type_) { case CMP_NODE_WRAP_NONE: /* Intentionally empty, original_xpos and original_ypos have been set before. */ break; case CMP_NODE_WRAP_X: /* Wrap only on the x-axis. */ nx = this->get_wrapped_original_xpos(x); extend_x = MemoryBufferExtend::Repeat; break; case CMP_NODE_WRAP_Y: /* Wrap only on the y-axis. */ ny = this->get_wrapped_original_ypos(y); extend_y = MemoryBufferExtend::Repeat; break; case CMP_NODE_WRAP_XY: /* Wrap on both. */ nx = this->get_wrapped_original_xpos(x); ny = this->get_wrapped_original_ypos(y); extend_x = MemoryBufferExtend::Repeat; extend_y = MemoryBufferExtend::Repeat; break; } execute_pixel_extend(output, nx, ny, sampler, extend_x, extend_y); } bool WrapOperation::determine_depending_area_of_interest(rcti *input, ReadBufferOperation *read_operation, rcti *output) { rcti new_input; new_input.xmin = input->xmin; new_input.xmax = input->xmax; new_input.ymin = input->ymin; new_input.ymax = input->ymax; if (ELEM(wrapping_type_, CMP_NODE_WRAP_X, CMP_NODE_WRAP_XY)) { /* Wrap only on the x-axis if tile is wrapping. */ new_input.xmin = get_wrapped_original_xpos(input->xmin); new_input.xmax = roundf(get_wrapped_original_xpos(input->xmax)); if (new_input.xmin >= new_input.xmax) { new_input.xmin = 0; new_input.xmax = this->get_width(); } } if (ELEM(wrapping_type_, CMP_NODE_WRAP_Y, CMP_NODE_WRAP_XY)) { /* Wrap only on the y-axis if tile is wrapping. */ new_input.ymin = get_wrapped_original_ypos(input->ymin); new_input.ymax = roundf(get_wrapped_original_ypos(input->ymax)); if (new_input.ymin >= new_input.ymax) { new_input.ymin = 0; new_input.ymax = this->get_height(); } } return ReadBufferOperation::determine_depending_area_of_interest( &new_input, read_operation, output); } void WrapOperation::set_wrapping(int wrapping_type) { wrapping_type_ = wrapping_type; } } // namespace blender::compositor