// Copyright 2020 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/ctext_only_printer_driver.h"

#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include <algorithm>

#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxge/cfx_font.h"
#include "core/fxge/text_char_pos.h"
#include "third_party/base/check_op.h"
#include "third_party/base/notreached.h"

CTextOnlyPrinterDriver::CTextOnlyPrinterDriver(HDC hDC)
    : m_hDC(hDC),
      m_Width(INT_MAX),
      m_Height(INT_MAX),
      m_HorzSize(INT_MAX),
      m_VertSize(INT_MAX),
      m_OriginY(0.0f),
      m_SetOrigin(false) {
  m_nBitsPerPixel = ::GetDeviceCaps(m_hDC, BITSPIXEL);
}

CTextOnlyPrinterDriver::~CTextOnlyPrinterDriver() = default;

DeviceType CTextOnlyPrinterDriver::GetDeviceType() const {
  return DeviceType::kPrinter;
}

int CTextOnlyPrinterDriver::GetDeviceCaps(int caps_id) const {
  switch (caps_id) {
    case FXDC_PIXEL_WIDTH:
      return m_Width;
    case FXDC_PIXEL_HEIGHT:
      return m_Height;
    case FXDC_BITS_PIXEL:
      return m_nBitsPerPixel;
    case FXDC_RENDER_CAPS:
      return 0;
    case FXDC_HORZ_SIZE:
      return m_HorzSize;
    case FXDC_VERT_SIZE:
      return m_VertSize;
    default:
      NOTREACHED();
      return 0;
  }
}

void CTextOnlyPrinterDriver::SaveState() {}

void CTextOnlyPrinterDriver::RestoreState(bool bKeepSaved) {}

bool CTextOnlyPrinterDriver::SetClip_PathFill(
    const CFX_Path& path,
    const CFX_Matrix* pObject2Device,
    const CFX_FillRenderOptions& fill_options) {
  return true;
}

bool CTextOnlyPrinterDriver::SetClip_PathStroke(
    const CFX_Path& path,
    const CFX_Matrix* pObject2Device,
    const CFX_GraphStateData* pGraphState) {
  return false;
}

bool CTextOnlyPrinterDriver::DrawPath(const CFX_Path& path,
                                      const CFX_Matrix* pObject2Device,
                                      const CFX_GraphStateData* pGraphState,
                                      uint32_t fill_color,
                                      uint32_t stroke_color,
                                      const CFX_FillRenderOptions& fill_options,
                                      BlendMode blend_type) {
  return false;
}

bool CTextOnlyPrinterDriver::SetDIBits(const RetainPtr<CFX_DIBBase>& pBitmap,
                                       uint32_t color,
                                       const FX_RECT& src_rect,
                                       int left,
                                       int top,
                                       BlendMode blend_type) {
  return false;
}

bool CTextOnlyPrinterDriver::GetClipBox(FX_RECT* pRect) {
  pRect->left = 0;
  pRect->right = m_Width;
  pRect->top = 0;
  pRect->bottom = m_Height;
  return true;
}

bool CTextOnlyPrinterDriver::StretchDIBits(
    const RetainPtr<CFX_DIBBase>& pBitmap,
    uint32_t color,
    int dest_left,
    int dest_top,
    int dest_width,
    int dest_height,
    const FX_RECT* pClipRect,
    const FXDIB_ResampleOptions& options,
    BlendMode blend_type) {
  return false;
}

bool CTextOnlyPrinterDriver::StartDIBits(
    const RetainPtr<CFX_DIBBase>& pBitmap,
    int bitmap_alpha,
    uint32_t color,
    const CFX_Matrix& matrix,
    const FXDIB_ResampleOptions& options,
    std::unique_ptr<CFX_ImageRenderer>* handle,
    BlendMode blend_type) {
  return false;
}

bool CTextOnlyPrinterDriver::DrawDeviceText(
    int nChars,
    const TextCharPos* pCharPos,
    CFX_Font* pFont,
    const CFX_Matrix& mtObject2Device,
    float font_size,
    uint32_t color,
    const CFX_TextRenderOptions& /*options*/) {
  if (g_pdfium_print_mode != WindowsPrintMode::kTextOnly)
    return false;
  if (nChars < 1 || !pFont || !pFont->IsEmbedded() || !pFont->IsTTFont())
    return false;

  // Scale factor used to minimize the kerning problems caused by rounding
  // errors below. Value chosen based on the title of https://crbug.com/18383
  const double kScaleFactor = 10;

  // Detect new lines and add clrf characters (since this is Windows only).
  // These characters are removed by SkPDF, but the new line information is
  // preserved in the text location. clrf characters seem to be ignored by
  // label printers that use this driver.
  WideString wsText;
  size_t len = nChars;
  float fOffsetY = mtObject2Device.f * kScaleFactor;
  if (m_SetOrigin && FXSYS_roundf(m_OriginY) != FXSYS_roundf(fOffsetY)) {
    wsText += L"\r\n";
    len += 2;
  }
  wsText.Reserve(len);
  m_OriginY = fOffsetY;
  m_SetOrigin = true;

  // Text
  for (int i = 0; i < nChars; ++i) {
    // Only works with PDFs from Skia's PDF generator. Cannot handle arbitrary
    // values from PDFs.
    const TextCharPos& charpos = pCharPos[i];
    DCHECK_EQ(charpos.m_AdjustMatrix[0], 0);
    DCHECK_EQ(charpos.m_AdjustMatrix[1], 0);
    DCHECK_EQ(charpos.m_AdjustMatrix[2], 0);
    DCHECK_EQ(charpos.m_AdjustMatrix[3], 0);
    DCHECK_EQ(charpos.m_Origin.y, 0);

    wsText += charpos.m_Unicode;
  }
  ByteString text = wsText.ToDefANSI();
  auto text_span = text.span();
  while (!text_span.empty()) {
    uint8_t buffer[1026];
    size_t send_len = std::min<size_t>(text_span.size(), 1024);
    *(reinterpret_cast<uint16_t*>(buffer)) = static_cast<uint16_t>(send_len);
    memcpy(buffer + 2, text_span.data(), send_len);
    ::GdiComment(m_hDC, static_cast<UINT>(send_len + 2), buffer);
    text_span = text_span.subspan(send_len);
  }
  return true;
}
