// Copyright (c) 2012 The Chromium 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 "printing/metafile_skia.h"

#include <algorithm>
#include <map>
#include <tuple>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/containers/contains.h"
#include "base/containers/span.h"
#include "base/files/file.h"
#include "base/memory/raw_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "cc/paint/paint_record.h"
#include "cc/paint/paint_recorder.h"
#include "cc/paint/skia_paint_canvas.h"
#include "printing/metafile_agent.h"
#include "printing/mojom/print.mojom.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkSerialProcs.h"
#include "third_party/skia/include/core/SkStream.h"
// Note that headers in third_party/skia/src are fragile.  This is
// an experimental, fragile, and diagnostic-only document type.
#include "third_party/skia/src/utils/SkMultiPictureDocument.h"
#include "ui/gfx/geometry/skia_conversions.h"

#if BUILDFLAG(IS_MAC)
#include "printing/pdf_metafile_cg_mac.h"
#endif

#if BUILDFLAG(IS_POSIX)
#include "base/file_descriptor_posix.h"
#endif

#if BUILDFLAG(IS_ANDROID)
#include "base/files/file_util.h"
#endif  // BUILDFLAG(IS_ANDROID)

namespace {

// `InitFromData()` should make a copy of data for the safety of all operations
// which would then operate upon that.
constexpr bool kInitFromDataCopyData = true;

bool WriteAssetToBuffer(const SkStreamAsset* asset, void* buffer, size_t size) {
  // Calling duplicate() keeps original asset state unchanged.
  std::unique_ptr<SkStreamAsset> assetCopy(asset->duplicate());
  size_t length = assetCopy->getLength();
  return length <= size && length == assetCopy->read(buffer, length);
}

}  // namespace

namespace printing {

struct Page {
  Page(const SkSize& s, sk_sp<cc::PaintRecord> c)
      : size(s), content(std::move(c)) {}
  Page(Page&& that) : size(that.size), content(std::move(that.content)) {}
  Page(const Page&) = default;
  Page& operator=(const Page&) = default;
  Page& operator=(Page&& that) {
    size = that.size;
    content = std::move(that.content);
    return *this;
  }
  SkSize size;
  sk_sp<cc::PaintRecord> content;
};

struct MetafileSkiaData {
  cc::PaintRecorder recorder;  // Current recording

  std::vector<Page> pages;
  std::unique_ptr<SkStreamAsset> data_stream;
  ContentToProxyTokenMap subframe_content_info;
  std::map<uint32_t, sk_sp<SkPicture>> subframe_pics;
  int document_cookie = 0;
  raw_ptr<ContentProxySet> typeface_content_info = nullptr;

  // The scale factor is used because Blink occasionally calls
  // PaintCanvas::getTotalMatrix() even though the total matrix is not as
  // meaningful for a vector canvas as for a raster canvas.
  float scale_factor;
  SkSize size;
  mojom::SkiaDocumentType type;

#if BUILDFLAG(IS_MAC)
  PdfMetafileCg pdf_cg;
#endif
};

MetafileSkia::MetafileSkia() : data_(std::make_unique<MetafileSkiaData>()) {
  data_->type = mojom::SkiaDocumentType::kPDF;
}

MetafileSkia::MetafileSkia(mojom::SkiaDocumentType type, int document_cookie)
    : data_(std::make_unique<MetafileSkiaData>()) {
  data_->type = type;
  data_->document_cookie = document_cookie;
}

MetafileSkia::~MetafileSkia() = default;

bool MetafileSkia::Init() {
  return true;
}

void MetafileSkia::UtilizeTypefaceContext(
    ContentProxySet* typeface_content_info) {
  data_->typeface_content_info = typeface_content_info;
}

// TODO(halcanary): Create a Metafile class that only stores data.
// Metafile::InitFromData is orthogonal to what the rest of
// MetafileSkia does.
bool MetafileSkia::InitFromData(base::span<const uint8_t> data) {
  data_->data_stream = std::make_unique<SkMemoryStream>(
      data.data(), data.size(), kInitFromDataCopyData);
  return true;
}

void MetafileSkia::StartPage(const gfx::Size& page_size,
                             const gfx::Rect& content_area,
                             float scale_factor,
                             mojom::PageOrientation page_orientation) {
  gfx::Size physical_page_size = page_size;
  if (page_orientation != mojom::PageOrientation::kUpright)
    physical_page_size.SetSize(page_size.height(), page_size.width());

  DCHECK_GT(page_size.width(), 0);
  DCHECK_GT(page_size.height(), 0);
  DCHECK_GT(scale_factor, 0.0f);
  if (data_->recorder.getRecordingCanvas())
    FinishPage();
  DCHECK(!data_->recorder.getRecordingCanvas());

  float inverse_scale = 1.0 / scale_factor;
  cc::PaintCanvas* canvas = data_->recorder.beginRecording(
      inverse_scale * physical_page_size.width(),
      inverse_scale * physical_page_size.height());
  // Recording canvas is owned by the `data_->recorder`.  No ref() necessary.
  if (content_area != gfx::Rect(page_size) ||
      page_orientation != mojom::PageOrientation::kUpright) {
    canvas->scale(inverse_scale, inverse_scale);
    if (page_orientation == mojom::PageOrientation::kRotateLeft) {
      canvas->translate(0, physical_page_size.height());
      canvas->rotate(-90);
    } else if (page_orientation == mojom::PageOrientation::kRotateRight) {
      canvas->translate(physical_page_size.width(), 0);
      canvas->rotate(90);
    }
    SkRect sk_content_area = gfx::RectToSkRect(content_area);
    canvas->clipRect(sk_content_area);
    canvas->translate(sk_content_area.x(), sk_content_area.y());
    canvas->scale(scale_factor, scale_factor);
  }

  data_->size = gfx::SizeFToSkSize(gfx::SizeF(physical_page_size));
  data_->scale_factor = scale_factor;
  // We scale the recording canvas's size so that
  // canvas->getTotalMatrix() returns a value that ignores the scale
  // factor.  We store the scale factor and re-apply it later.
  // http://crbug.com/469656
}

cc::PaintCanvas* MetafileSkia::GetVectorCanvasForNewPage(
    const gfx::Size& page_size,
    const gfx::Rect& content_area,
    float scale_factor,
    mojom::PageOrientation page_orientation) {
  StartPage(page_size, content_area, scale_factor, page_orientation);
  return data_->recorder.getRecordingCanvas();
}

bool MetafileSkia::FinishPage() {
  if (!data_->recorder.getRecordingCanvas())
    return false;

  sk_sp<cc::PaintRecord> pic = data_->recorder.finishRecordingAsPicture();
  if (data_->scale_factor != 1.0f) {
    cc::PaintCanvas* canvas = data_->recorder.beginRecording(
        data_->size.width(), data_->size.height());
    canvas->scale(data_->scale_factor, data_->scale_factor);
    canvas->drawPicture(pic);
    pic = data_->recorder.finishRecordingAsPicture();
  }
  data_->pages.emplace_back(data_->size, std::move(pic));
  return true;
}

bool MetafileSkia::FinishDocument() {
  // If we've already set the data in InitFromData, leave it be.
  if (data_->data_stream)
    return false;

  if (data_->recorder.getRecordingCanvas())
    FinishPage();

  SkDynamicMemoryWStream stream;
  sk_sp<SkDocument> doc;
  cc::PlaybackParams::CustomDataRasterCallback custom_callback;
  switch (data_->type) {
    case mojom::SkiaDocumentType::kPDF:
      doc = MakePdfDocument(printing::GetAgent(), accessibility_tree_, &stream);
      break;
    case mojom::SkiaDocumentType::kMSKP:
      SkSerialProcs procs = SerializationProcs(&data_->subframe_content_info,
                                               data_->typeface_content_info);
      doc = SkMakeMultiPictureDocument(&stream, &procs);
      // It is safe to use base::Unretained(this) because the callback
      // is only used by `canvas` in the following loop which has shorter
      // lifetime than `this`.
      custom_callback = base::BindRepeating(
          &MetafileSkia::CustomDataToSkPictureCallback, base::Unretained(this));
      break;
  }

  for (const Page& page : data_->pages) {
    cc::SkiaPaintCanvas canvas(
        doc->beginPage(page.size.width(), page.size.height()));
    canvas.drawPicture(page.content, custom_callback);
    doc->endPage();
  }
  doc->close();

  data_->data_stream = stream.detachAsStream();
  return true;
}

void MetafileSkia::FinishFrameContent() {
  // Sanity check to make sure we print the entire frame as a single page
  // content.
  DCHECK_EQ(data_->pages.size(), 1u);
  // Also make sure it is in skia multi-picture document format.
  DCHECK_EQ(data_->type, mojom::SkiaDocumentType::kMSKP);
  DCHECK(!data_->data_stream);

  cc::PlaybackParams::CustomDataRasterCallback custom_callback =
      base::BindRepeating(&MetafileSkia::CustomDataToSkPictureCallback,
                          base::Unretained(this));
  sk_sp<SkPicture> pic = ToSkPicture(data_->pages[0].content,
                                     SkRect::MakeSize(data_->pages[0].size),
                                     nullptr, custom_callback);
  SkSerialProcs procs = SerializationProcs(&data_->subframe_content_info,
                                           data_->typeface_content_info);
  SkDynamicMemoryWStream stream;
  pic->serialize(&stream, &procs);
  data_->data_stream = stream.detachAsStream();
}

uint32_t MetafileSkia::GetDataSize() const {
  if (!data_->data_stream)
    return 0;
  return base::checked_cast<uint32_t>(data_->data_stream->getLength());
}

bool MetafileSkia::GetData(void* dst_buffer, uint32_t dst_buffer_size) const {
  if (!data_->data_stream)
    return false;
  return WriteAssetToBuffer(data_->data_stream.get(), dst_buffer,
                            base::checked_cast<size_t>(dst_buffer_size));
}

bool MetafileSkia::ShouldCopySharedMemoryRegionData() const {
  // When `InitFromData()` copies the data, the caller doesn't have to.
  return !kInitFromDataCopyData;
}

mojom::MetafileDataType MetafileSkia::GetDataType() const {
  return mojom::MetafileDataType::kPDF;
}

gfx::Rect MetafileSkia::GetPageBounds(unsigned int page_number) const {
  if (page_number < data_->pages.size()) {
    SkSize size = data_->pages[page_number].size;
    return gfx::Rect(base::ClampRound(size.width()),
                     base::ClampRound(size.height()));
  }
  return gfx::Rect();
}

unsigned int MetafileSkia::GetPageCount() const {
  return base::checked_cast<unsigned int>(data_->pages.size());
}

printing::NativeDrawingContext MetafileSkia::context() const {
  NOTREACHED();
  return nullptr;
}

#if BUILDFLAG(IS_WIN)
bool MetafileSkia::Playback(printing::NativeDrawingContext hdc,
                            const RECT* rect) const {
  NOTREACHED();
  return false;
}

bool MetafileSkia::SafePlayback(printing::NativeDrawingContext hdc) const {
  NOTREACHED();
  return false;
}

#elif BUILDFLAG(IS_MAC)
/* TODO(caryclark): The set up of PluginInstance::PrintPDFOutput may result in
   rasterized output.  Even if that flow uses PdfMetafileCg::RenderPage,
   the drawing of the PDF into the canvas may result in a rasterized output.
   PDFMetafileSkia::RenderPage should be not implemented as shown and instead
   should do something like the following CL in PluginInstance::PrintPDFOutput:
http://codereview.chromium.org/7200040/diff/1/webkit/plugins/ppapi/ppapi_plugin_instance.cc
*/
bool MetafileSkia::RenderPage(unsigned int page_number,
                              CGContextRef context,
                              const CGRect& rect,
                              bool autorotate,
                              bool fit_to_page) const {
  DCHECK_GT(GetDataSize(), 0U);
  if (data_->pdf_cg.GetDataSize() == 0) {
    if (GetDataSize() == 0)
      return false;
    size_t length = data_->data_stream->getLength();
    std::vector<uint8_t> buffer(length);
    std::ignore =
        WriteAssetToBuffer(data_->data_stream.get(), &buffer[0], length);
    data_->pdf_cg.InitFromData(buffer);
  }
  return data_->pdf_cg.RenderPage(page_number, context, rect, autorotate,
                                  fit_to_page);
}
#endif

#if BUILDFLAG(IS_ANDROID)
bool MetafileSkia::SaveToFileDescriptor(int fd) const {
  if (GetDataSize() == 0u)
    return false;

  std::unique_ptr<SkStreamAsset> asset(data_->data_stream->duplicate());

  static constexpr size_t kMaximumBufferSize = 1024 * 1024;
  std::vector<uint8_t> buffer(std::min(kMaximumBufferSize, asset->getLength()));
  do {
    size_t read_size = asset->read(&buffer[0], buffer.size());
    if (read_size == 0u)
      break;
    DCHECK_GE(buffer.size(), read_size);
    buffer.resize(read_size);
    if (!base::WriteFileDescriptor(fd, buffer))
      return false;
  } while (!asset->isAtEnd());

  return true;
}
#else
bool MetafileSkia::SaveTo(base::File* file) const {
  if (GetDataSize() == 0U)
    return false;

  // Calling duplicate() keeps original asset state unchanged.
  std::unique_ptr<SkStreamAsset> asset(data_->data_stream->duplicate());

  static constexpr size_t kMaximumBufferSize = 1024 * 1024;
  std::vector<uint8_t> buffer(std::min(kMaximumBufferSize, asset->getLength()));
  do {
    size_t read_size = asset->read(&buffer[0], buffer.size());
    if (read_size == 0)
      break;
    DCHECK_GE(buffer.size(), read_size);
    if (!file->WriteAtCurrentPosAndCheck(
            base::make_span(&buffer[0], read_size))) {
      return false;
    }
  } while (!asset->isAtEnd());

  return true;
}
#endif  // BUILDFLAG(IS_ANDROID)

std::unique_ptr<MetafileSkia> MetafileSkia::GetMetafileForCurrentPage(
    mojom::SkiaDocumentType type) {
  // If we only ever need the metafile for the last page, should we
  // only keep a handle on one PaintRecord?
  auto metafile = std::make_unique<MetafileSkia>(type, data_->document_cookie);
  if (data_->pages.size() == 0)
    return metafile;

  if (data_->recorder.getRecordingCanvas())  // page outstanding
    return metafile;

  metafile->data_->pages.push_back(data_->pages.back());
  metafile->data_->subframe_content_info = data_->subframe_content_info;
  metafile->data_->subframe_pics = data_->subframe_pics;
  metafile->data_->typeface_content_info = data_->typeface_content_info;

  if (!metafile->FinishDocument())  // Generate PDF.
    metafile.reset();

  return metafile;
}

uint32_t MetafileSkia::CreateContentForRemoteFrame(
    const gfx::Rect& rect,
    const base::UnguessableToken& render_proxy_token) {
  // Create a place holder picture.
  sk_sp<SkPicture> pic = SkPicture::MakePlaceholder(
      SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()));

  // Store the map between content id and the proxy id.
  uint32_t content_id = pic->uniqueID();
  DCHECK(!base::Contains(data_->subframe_content_info, content_id));
  data_->subframe_content_info[content_id] = render_proxy_token;

  // Store the picture content.
  data_->subframe_pics[content_id] = pic;
  return content_id;
}

int MetafileSkia::GetDocumentCookie() const {
  return data_->document_cookie;
}

const ContentToProxyTokenMap& MetafileSkia::GetSubframeContentInfo() const {
  return data_->subframe_content_info;
}

void MetafileSkia::AppendPage(const SkSize& page_size,
                              sk_sp<cc::PaintRecord> record) {
  data_->pages.emplace_back(page_size, std::move(record));
}

void MetafileSkia::AppendSubframeInfo(uint32_t content_id,
                                      const base::UnguessableToken& proxy_token,
                                      sk_sp<SkPicture> pic_holder) {
  data_->subframe_content_info[content_id] = proxy_token;
  data_->subframe_pics[content_id] = pic_holder;
}

SkStreamAsset* MetafileSkia::GetPdfData() const {
  return data_->data_stream.get();
}

void MetafileSkia::CustomDataToSkPictureCallback(SkCanvas* canvas,
                                                 uint32_t content_id) {
  // Check whether this is the one we need to handle.
  if (!base::Contains(data_->subframe_content_info, content_id))
    return;

  auto it = data_->subframe_pics.find(content_id);
  DCHECK(it != data_->subframe_pics.end());

  // Found the picture, draw it on canvas.
  sk_sp<SkPicture> pic = it->second;
  SkRect rect = pic->cullRect();
  SkMatrix matrix = SkMatrix::Translate(rect.x(), rect.y());
  canvas->drawPicture(it->second, &matrix, nullptr);
}

}  // namespace printing
