// Copyright 2016 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "core/fxge/ge/cfx_cliprgn.h"

CFX_ClipRgn::CFX_ClipRgn(int width, int height)
    : m_Type(RectI), m_Box(0, 0, width, height) {}

CFX_ClipRgn::CFX_ClipRgn(const CFX_ClipRgn& src) {
  m_Type = src.m_Type;
  m_Box = src.m_Box;
  m_Mask = src.m_Mask;
}

CFX_ClipRgn::~CFX_ClipRgn() {}

void CFX_ClipRgn::Reset(const FX_RECT& rect) {
  m_Type = RectI;
  m_Box = rect;
  m_Mask.SetNull();
}

void CFX_ClipRgn::IntersectRect(const FX_RECT& rect) {
  if (m_Type == RectI) {
    m_Box.Intersect(rect);
    return;
  }
  if (m_Type == MaskF) {
    IntersectMaskRect(rect, m_Box, m_Mask);
    return;
  }
}

void CFX_ClipRgn::IntersectMaskRect(FX_RECT rect,
                                    FX_RECT mask_rect,
                                    CFX_DIBitmapRef Mask) {
  const CFX_DIBitmap* mask_dib = Mask.GetObject();
  m_Type = MaskF;
  m_Box = rect;
  m_Box.Intersect(mask_rect);
  if (m_Box.IsEmpty()) {
    m_Type = RectI;
    return;
  }
  if (m_Box == mask_rect) {
    m_Mask = Mask;
    return;
  }
  CFX_DIBitmap* new_dib = m_Mask.New();
  if (!new_dib)
    return;
  new_dib->Create(m_Box.Width(), m_Box.Height(), FXDIB_8bppMask);
  for (int row = m_Box.top; row < m_Box.bottom; row++) {
    uint8_t* dest_scan =
        new_dib->GetBuffer() + new_dib->GetPitch() * (row - m_Box.top);
    uint8_t* src_scan =
        mask_dib->GetBuffer() + mask_dib->GetPitch() * (row - mask_rect.top);
    for (int col = m_Box.left; col < m_Box.right; col++)
      dest_scan[col - m_Box.left] = src_scan[col - mask_rect.left];
  }
}

void CFX_ClipRgn::IntersectMaskF(int left, int top, CFX_DIBitmapRef Mask) {
  const CFX_DIBitmap* mask_dib = Mask.GetObject();
  ASSERT(mask_dib->GetFormat() == FXDIB_8bppMask);
  FX_RECT mask_box(left, top, left + mask_dib->GetWidth(),
                   top + mask_dib->GetHeight());
  if (m_Type == RectI) {
    IntersectMaskRect(m_Box, mask_box, Mask);
    return;
  }
  if (m_Type == MaskF) {
    FX_RECT new_box = m_Box;
    new_box.Intersect(mask_box);
    if (new_box.IsEmpty()) {
      m_Type = RectI;
      m_Mask.SetNull();
      m_Box = new_box;
      return;
    }
    CFX_DIBitmapRef new_mask;
    CFX_DIBitmap* new_dib = new_mask.New();
    if (!new_dib)
      return;
    new_dib->Create(new_box.Width(), new_box.Height(), FXDIB_8bppMask);
    const CFX_DIBitmap* old_dib = m_Mask.GetObject();
    for (int row = new_box.top; row < new_box.bottom; row++) {
      uint8_t* old_scan =
          old_dib->GetBuffer() + (row - m_Box.top) * old_dib->GetPitch();
      uint8_t* mask_scan =
          mask_dib->GetBuffer() + (row - top) * mask_dib->GetPitch();
      uint8_t* new_scan =
          new_dib->GetBuffer() + (row - new_box.top) * new_dib->GetPitch();
      for (int col = new_box.left; col < new_box.right; col++) {
        new_scan[col - new_box.left] =
            old_scan[col - m_Box.left] * mask_scan[col - left] / 255;
      }
    }
    m_Box = new_box;
    m_Mask = new_mask;
    return;
  }
  ASSERT(FALSE);
}
