// Aseprite
// Copyright (C) 2019-2023  Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.

#ifdef HAVE_CONFIG_H
  #include "config.h"
#endif

#include "app/util/buffer_region.h"

#include "doc/image.h"
#include "gfx/region.h"

#include <algorithm>

namespace app {

void save_image_region_in_buffer(const gfx::Region& region,
                                 const doc::Image* image,
                                 const gfx::Point& imagePos,
                                 base::buffer& buffer)
{
  // Calculate buffer size for the region
  const size_t bytesPerPixel = image->bytesPerPixel();
  size_t reqBytes = 0;
  for (const auto& rc : region)
    reqBytes += bytesPerPixel * rc.w * rc.h;

  // Save region pixels
  buffer.resize(reqBytes);
  auto it = buffer.begin();
  for (const auto& rc : region) {
    for (int y = 0; y < rc.h; ++y) {
      auto p = (const uint8_t*)image->getPixelAddress(rc.x - imagePos.x, rc.y - imagePos.y + y);
      const size_t rowBytes = bytesPerPixel * rc.w;
      std::copy(p, p + rowBytes, it);
      it += rowBytes;
    }
  }
}

void swap_image_region_with_buffer(const gfx::Region& region,
                                   doc::Image* image,
                                   base::buffer& buffer)
{
  const size_t bytesPerPixel = image->bytesPerPixel();
  auto it = buffer.begin();
  for (const auto& rc : region) {
    for (int y = 0; y < rc.h; ++y) {
      auto p = (uint8_t*)image->getPixelAddress(rc.x, rc.y + y);
      const size_t rowBytes = bytesPerPixel * rc.w;
      std::swap_ranges(it, it + rowBytes, p);
      it += rowBytes;
    }
  }
}

} // namespace app
