// Copyright 2021 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/win32/cfx_psrenderer.h"

#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_stream.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/dib/fx_dib.h"
#include "core/fxge/win32/cfx_psfonttracker.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/base/span.h"

namespace {

DataVector<uint8_t> FakeA85Encode(pdfium::span<const uint8_t> src_span) {
  return DataVector<uint8_t>({'d', 'u', 'm', 'm', 'y', 'a', '8', '5'});
}

class TestWriteStream final : public IFX_RetainableWriteStream {
 public:
  CONSTRUCT_VIA_MAKE_RETAIN;

  // IFX_RetainableWriteStream:
  bool WriteBlock(const void* pData, size_t size) override {
    const uint8_t* data_as_uint8 = static_cast<const uint8_t*>(pData);
    data_.insert(data_.end(), data_as_uint8, data_as_uint8 + size);
    return true;
  }

  pdfium::span<const uint8_t> GetSpan() const { return data_; }

 private:
  DataVector<uint8_t> data_;
};

}  // namespace

TEST(PSRendererTest, GenerateType42SfntData) {
  absl::optional<ByteString> result;

  result = CFX_PSRenderer::GenerateType42SfntDataForTesting("empty", {});
  EXPECT_FALSE(result.has_value());

  constexpr uint8_t kOddByteCountTestData[] = {0, 32, 55};
  static constexpr char kExpectedOddByteCountResult[] = R"(/odd_sfnts [
<
002037
>
] def
)";
  result = CFX_PSRenderer::GenerateType42SfntDataForTesting(
      "odd", kOddByteCountTestData);
  ASSERT_TRUE(result.has_value());
  EXPECT_STREQ(kExpectedOddByteCountResult, result.value().c_str());

  // Requires padding.
  constexpr uint8_t kEvenByteCountTestData[] = {0, 32, 66, 77};
  static constexpr char kExpectedEvenByteCountResult[] = R"(/even_sfnts [
<
0020424D00
>
] def
)";
  result = CFX_PSRenderer::GenerateType42SfntDataForTesting(
      "even", kEvenByteCountTestData);
  ASSERT_TRUE(result.has_value());
  EXPECT_STREQ(kExpectedEvenByteCountResult, result.value().c_str());
}

TEST(PSRendererTest, GenerateType42FontDictionary) {
  ByteString result;

  static constexpr char kExpected1DescendantFontResult[] = R"(8 dict begin
/FontType 42 def
/FontMatrix [1 0 0 1 0 0] def
/FontName /1descendant_0 def
/Encoding 3 array
dup 0 /c00 put
dup 1 /c01 put
dup 2 /c02 put
readonly def
/FontBBox [1 2 3 4] def
/PaintType 0 def
/CharStrings 4 dict dup begin
/.notdef 0 def
/c00 0 def
/c01 1 def
/c02 2 def
end readonly def
/sfnts 1descendant_sfnts def
FontName currentdict end definefont pop
6 dict begin
/FontName /1descendant def
/FontType 0 def
/FontMatrix [1 0 0 1 0 0] def
/FMapType 2 def
/Encoding [
0
] def
/FDepVector [
/1descendant_0 findfont
] def
FontName currentdict end definefont pop
%%EndResource
)";
  result = CFX_PSRenderer::GenerateType42FontDictionaryForTesting(
      "1descendant", FX_RECT(1, 2, 3, 4), /*num_glyphs=*/3,
      /*glyphs_per_descendant_font=*/3);
  EXPECT_STREQ(kExpected1DescendantFontResult, result.c_str());

  static constexpr char kExpected2DescendantFontResult[] = R"(8 dict begin
/FontType 42 def
/FontMatrix [1 0 0 1 0 0] def
/FontName /2descendant_0 def
/Encoding 3 array
dup 0 /c00 put
dup 1 /c01 put
dup 2 /c02 put
readonly def
/FontBBox [12 -5 34 199] def
/PaintType 0 def
/CharStrings 4 dict dup begin
/.notdef 0 def
/c00 0 def
/c01 1 def
/c02 2 def
end readonly def
/sfnts 2descendant_sfnts def
FontName currentdict end definefont pop
8 dict begin
/FontType 42 def
/FontMatrix [1 0 0 1 0 0] def
/FontName /2descendant_1 def
/Encoding 3 array
dup 0 /c00 put
dup 1 /c01 put
readonly def
/FontBBox [12 -5 34 199] def
/PaintType 0 def
/CharStrings 4 dict dup begin
/.notdef 0 def
/c00 3 def
/c01 4 def
end readonly def
/sfnts 2descendant_sfnts def
FontName currentdict end definefont pop
6 dict begin
/FontName /2descendant def
/FontType 0 def
/FontMatrix [1 0 0 1 0 0] def
/FMapType 2 def
/Encoding [
0
1
] def
/FDepVector [
/2descendant_0 findfont
/2descendant_1 findfont
] def
FontName currentdict end definefont pop
%%EndResource
)";
  result = CFX_PSRenderer::GenerateType42FontDictionaryForTesting(
      "2descendant", FX_RECT(12, -5, 34, 199), /*num_glyphs=*/5,
      /*glyphs_per_descendant_font=*/3);
  EXPECT_STREQ(kExpected2DescendantFontResult, result.c_str());
}

TEST(PSRendererTest, DrawDIBits) {
  static constexpr char kExpectedOutput[] = R"(
save
/im/initmatrix load def
/n/newpath load def/m/moveto load def/l/lineto load def/c/curveto load def/h/closepath load def
/f/fill load def/F/eofill load def/s/stroke load def/W/clip load def/W*/eoclip load def
/rg/setrgbcolor load def/k/setcmykcolor load def
/J/setlinecap load def/j/setlinejoin load def/w/setlinewidth load def/M/setmiterlimit load def/d/setdash load def
/q/gsave load def/Q/grestore load def/iM/imagemask load def
/Tj/show load def/Ff/findfont load def/Fs/scalefont load def/Sf/setfont load def
/cm/concat load def/Cm/currentmatrix load def/mx/matrix load def/sm/setmatrix load def
q
[1 0 0 1 0 0]cm 10 2 1[10 0 0 -2 0 2]currentfile/ASCII85Decode filter false 1 colorimage
dummya85
Q

restore
)";
  auto output_stream = pdfium::MakeRetain<TestWriteStream>();

  {
    constexpr int kWidth = 10;
    constexpr int kHeight = 2;
    CFX_PSFontTracker font_tracker;
    const EncoderIface encoder_interface{&FakeA85Encode, nullptr, nullptr,
                                         nullptr, nullptr};
    CFX_PSRenderer renderer(&font_tracker, &encoder_interface);
    renderer.Init(output_stream, CFX_PSRenderer::RenderingLevel::kLevel2,
                  kWidth, kHeight);

    auto bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
    bool result = bitmap->Create(kWidth, kHeight, FXDIB_Format::k1bppRgb);
    ASSERT_TRUE(result);
    bitmap->Clear(0);
    ASSERT_TRUE(renderer.DrawDIBits(bitmap, /*color=*/0, CFX_Matrix(),
                                    FXDIB_ResampleOptions()));
  }

  ByteString output(output_stream->GetSpan());
  EXPECT_STREQ(output.c_str(), kExpectedOutput);
}
