// 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 <utility>
#include <vector>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/files/file.h"
#include "base/numerics/safe_conversions.h"
#include "base/stl_util.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "cc/paint/paint_record.h"
#include "cc/paint/paint_recorder.h"
#include "cc/paint/skia_paint_canvas.h"
#include "printing/mojom/print.mojom.h"
#include "printing/print_settings.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/skia_util.h"

#if defined(OS_MAC)
#include "printing/pdf_metafile_cg_mac.h"
#endif

#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
#endif

#if defined(OS_ANDROID)
#include "base/files/file_util.h"
#endif  // defined(OS_ANDROID)

namespace {

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;
  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 defined(OS_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(), /*copy_data=*/true);
  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));
}

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 defined(OS_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 defined(OS_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);
    (void)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 defined(OS_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);
    if (!base::WriteFileDescriptor(
            fd, reinterpret_cast<const char*>(buffer.data()), read_size)) {
      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  // defined(OS_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
