// 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.

#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_font.h"
#include "core/fxge/cfx_graphstatedata.h"
#include "core/fxge/cfx_pathdata.h"
#include "core/fxge/cfx_renderdevice.h"
#include "core/fxge/cfx_textrenderoptions.h"
#include "core/fxge/skia/fx_skia_device.h"
#include "core/fxge/text_char_pos.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "public/cpp/fpdf_scopers.h"
#include "public/fpdfview.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"

namespace {

struct State {
  enum class Change { kNo, kYes };
  enum class Save { kNo, kYes };
  enum class Clip { kNo, kSame, kDifferentPath, kDifferentMatrix };
  enum class Graphic { kNone, kPath, kText };

  Change m_change;
  Save m_save;
  Clip m_clip;
  Graphic m_graphic;
  uint32_t m_pixel;
};

void EmptyTest(CFX_SkiaDeviceDriver* driver, const State&) {
  driver->SaveState();
  driver->RestoreState(true);
  driver->RestoreState(false);
}

void CommonTest(CFX_SkiaDeviceDriver* driver, const State& state) {
  TextCharPos charPos[1];
  charPos[0].m_Origin = CFX_PointF(0, 1);
  charPos[0].m_GlyphIndex = 1;
  charPos[0].m_FontCharWidth = 4;

  CFX_Font font;
  float fontSize = 1;
  CFX_PathData clipPath;
  CFX_PathData clipPath2;
  clipPath.AppendRect(0, 0, 3, 1);
  clipPath2.AppendRect(0, 0, 2, 1);
  CFX_Matrix clipMatrix;
  CFX_Matrix clipMatrix2(1, 0, 0, 1, 0, 1);
  driver->SaveState();
  CFX_PathData path1;
  path1.AppendRect(0, 0, 1, 2);

  CFX_Matrix matrix;
  CFX_Matrix matrix2;
  matrix2.Translate(1, 0);
  CFX_GraphStateData graphState;
  static constexpr CFX_TextRenderOptions kTextOptions;
  if (state.m_save == State::Save::kYes)
    driver->SaveState();
  if (state.m_clip != State::Clip::kNo)
    driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
  if (state.m_graphic == State::Graphic::kPath) {
    driver->DrawPath(&path1, &matrix, &graphState, 0xFF112233, 0,
                     CFX_FillRenderOptions::WindingOptions(),
                     BlendMode::kNormal);
  } else if (state.m_graphic == State::Graphic::kText) {
    driver->DrawDeviceText(SK_ARRAY_COUNT(charPos), charPos, &font, matrix,
                           fontSize, 0xFF445566, kTextOptions);
  }
  if (state.m_save == State::Save::kYes)
    driver->RestoreState(true);
  CFX_PathData path2;
  path2.AppendRect(0, 0, 2, 2);
  if (state.m_change == State::Change::kYes) {
    if (state.m_graphic == State::Graphic::kPath)
      graphState.m_LineCap = CFX_GraphStateData::LineCapRound;
    else if (state.m_graphic == State::Graphic::kText)
      fontSize = 2;
  }
  if (state.m_clip == State::Clip::kSame)
    driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
  else if (state.m_clip == State::Clip::kDifferentPath)
    driver->SetClip_PathFill(&clipPath2, &clipMatrix, CFX_FillRenderOptions());
  else if (state.m_clip == State::Clip::kDifferentMatrix)
    driver->SetClip_PathFill(&clipPath, &clipMatrix2, CFX_FillRenderOptions());
  if (state.m_graphic == State::Graphic::kPath) {
    driver->DrawPath(&path2, &matrix2, &graphState, 0xFF112233, 0,
                     CFX_FillRenderOptions::WindingOptions(),
                     BlendMode::kNormal);
  } else if (state.m_graphic == State::Graphic::kText) {
    driver->DrawDeviceText(SK_ARRAY_COUNT(charPos), charPos, &font, matrix2,
                           fontSize, 0xFF445566, kTextOptions);
  }
  if (state.m_save == State::Save::kYes)
    driver->RestoreState(false);
  driver->RestoreState(false);
}

void OutOfSequenceClipTest(CFX_SkiaDeviceDriver* driver, const State&) {
  CFX_PathData clipPath;
  clipPath.AppendRect(1, 0, 3, 1);
  CFX_Matrix clipMatrix;
  driver->SaveState();
  driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
  driver->RestoreState(true);
  driver->SaveState();
  driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
  driver->RestoreState(false);
  driver->RestoreState(false);

  driver->SaveState();
  driver->SaveState();
  driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
  driver->RestoreState(true);
  driver->SetClip_PathFill(&clipPath, &clipMatrix, CFX_FillRenderOptions());
  driver->RestoreState(false);
  driver->RestoreState(false);
}

void Harness(void (*Test)(CFX_SkiaDeviceDriver*, const State&),
             const State& state) {
  constexpr int kWidth = 4;
  constexpr int kHeight = 1;
  ScopedFPDFBitmap bitmap(FPDFBitmap_Create(kWidth, kHeight, 1));
  ASSERT_TRUE(bitmap);
  FPDFBitmap_FillRect(bitmap.get(), 0, 0, kWidth, kHeight, 0x00000000);
  CFX_DefaultRenderDevice device;
  RetainPtr<CFX_DIBitmap> pBitmap(CFXDIBitmapFromFPDFBitmap(bitmap.get()));
  device.Attach(pBitmap, false, nullptr, false);
  auto* driver = static_cast<CFX_SkiaDeviceDriver*>(device.GetDeviceDriver());
  (*Test)(driver, state);
  driver->Flush();
  uint32_t pixel = pBitmap->GetPixel(0, 0);
  EXPECT_EQ(state.m_pixel, pixel);
#ifdef SK_DEBUG
  if (!driver)  // force dump to be linked in so it can be called from debugger
    driver->Dump();
#endif
}

}  // namespace

TEST(fxge, SkiaStateEmpty) {
  Harness(&EmptyTest, {});
}

TEST(fxge, SkiaStatePath) {
  Harness(&CommonTest, {State::Change::kNo, State::Save::kYes,
                        State::Clip::kSame, State::Graphic::kPath, 0xFF112233});
  Harness(&CommonTest,
          {State::Change::kNo, State::Save::kYes, State::Clip::kDifferentPath,
           State::Graphic::kPath, 0xFF112233});
  Harness(&CommonTest, {State::Change::kNo, State::Save::kYes, State::Clip::kNo,
                        State::Graphic::kPath, 0xFF112233});
  Harness(&CommonTest, {State::Change::kYes, State::Save::kNo, State::Clip::kNo,
                        State::Graphic::kPath, 0xFF112233});
  Harness(&CommonTest, {State::Change::kNo, State::Save::kNo, State::Clip::kNo,
                        State::Graphic::kPath, 0xFF112233});
}

#if defined(_SKIA_SUPPORT_)
// TODO(crbug.com/pdfium/11): Fix this test and enable.
TEST(fxge, DISABLED_SkiaStateText) {
  Harness(&CommonTest,
          {State::Change::kNo, State::Save::kYes, State::Clip::kDifferentMatrix,
           State::Graphic::kText, 0xFF445566});
  Harness(&CommonTest, {State::Change::kNo, State::Save::kYes,
                        State::Clip::kSame, State::Graphic::kText, 0xFF445566});
}
#endif

TEST(fxge, SkiaStateOOSClip) {
  Harness(&OutOfSequenceClipTest, {});
}
