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

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "xfa/fde/cfde_textout.h"

#include <algorithm>

#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_system.h"
#include "third_party/base/ptr_util.h"
#include "third_party/base/stl_util.h"
#include "xfa/fde/cfde_brush.h"
#include "xfa/fde/cfde_path.h"
#include "xfa/fde/cfde_pen.h"
#include "xfa/fde/cfde_renderdevice.h"
#include "xfa/fgas/layout/cfx_txtbreak.h"

FDE_TTOPIECE::FDE_TTOPIECE() = default;

FDE_TTOPIECE::FDE_TTOPIECE(const FDE_TTOPIECE& that) = default;

FDE_TTOPIECE::~FDE_TTOPIECE() = default;

CFDE_TextOut::CFDE_TextOut()
    : m_pTxtBreak(pdfium::MakeUnique<CFX_TxtBreak>()),
      m_pFont(nullptr),
      m_fFontSize(12.0f),
      m_fLineSpace(m_fFontSize),
      m_fLinePos(0.0f),
      m_fTolerance(0.0f),
      m_iAlignment(0),
      m_iTxtBkAlignment(0),
      m_wParagraphBkChar(L'\n'),
      m_TxtColor(0xFF000000),
      m_dwStyles(0),
      m_dwTxtBkStyles(0),
      m_bElliChanged(false),
      m_iEllipsisWidth(0),
      m_ttoLines(5),
      m_iCurLine(0),
      m_iCurPiece(0),
      m_iTotalLines(0) {
  m_Matrix.SetIdentity();
  m_rtClip.Reset();
  m_rtLogicClip.Reset();
}

CFDE_TextOut::~CFDE_TextOut() {}

void CFDE_TextOut::SetFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont) {
  ASSERT(pFont);
  m_pFont = pFont;
  m_pTxtBreak->SetFont(pFont);
}

void CFDE_TextOut::SetFontSize(float fFontSize) {
  ASSERT(fFontSize > 0);
  m_fFontSize = fFontSize;
  m_pTxtBreak->SetFontSize(fFontSize);
}

void CFDE_TextOut::SetTextColor(FX_ARGB color) {
  m_TxtColor = color;
}

void CFDE_TextOut::SetStyles(uint32_t dwStyles) {
  m_dwStyles = dwStyles;
  m_dwTxtBkStyles = 0;
  if (dwStyles & FDE_TTOSTYLE_SingleLine)
    m_dwTxtBkStyles |= FX_LAYOUTSTYLE_SingleLine;

  m_pTxtBreak->SetLayoutStyles(m_dwTxtBkStyles);
}

void CFDE_TextOut::SetTabWidth(float fTabWidth) {
  ASSERT(fTabWidth > 1.0f);
  m_pTxtBreak->SetTabWidth(fTabWidth);
}

void CFDE_TextOut::SetEllipsisString(const CFX_WideString& wsEllipsis) {
  m_bElliChanged = true;
  m_wsEllipsis = wsEllipsis;
}

void CFDE_TextOut::SetParagraphBreakChar(wchar_t wch) {
  m_wParagraphBkChar = wch;
  m_pTxtBreak->SetParagraphBreakChar(wch);
}

void CFDE_TextOut::SetAlignment(int32_t iAlignment) {
  m_iAlignment = iAlignment;
  switch (m_iAlignment) {
    case FDE_TTOALIGNMENT_TopCenter:
    case FDE_TTOALIGNMENT_Center:
    case FDE_TTOALIGNMENT_BottomCenter:
      m_iTxtBkAlignment = CFX_TxtLineAlignment_Center;
      break;
    case FDE_TTOALIGNMENT_TopRight:
    case FDE_TTOALIGNMENT_CenterRight:
    case FDE_TTOALIGNMENT_BottomRight:
      m_iTxtBkAlignment = CFX_TxtLineAlignment_Right;
      break;
    default:
      m_iTxtBkAlignment = CFX_TxtLineAlignment_Left;
      break;
  }
  m_pTxtBreak->SetAlignment(m_iTxtBkAlignment);
}

void CFDE_TextOut::SetLineSpace(float fLineSpace) {
  ASSERT(fLineSpace > 1.0f);
  m_fLineSpace = fLineSpace;
}

void CFDE_TextOut::SetDIBitmap(const CFX_RetainPtr<CFX_DIBitmap>& pDIB) {
  ASSERT(pDIB);

  m_pRenderDevice.reset();
  CFX_FxgeDevice* device = new CFX_FxgeDevice;
  device->Attach(pDIB, false, nullptr, false);
  m_pRenderDevice = pdfium::MakeUnique<CFDE_RenderDevice>(device, false);
}

void CFDE_TextOut::SetRenderDevice(CFX_RenderDevice* pDevice) {
  ASSERT(pDevice);
  m_pRenderDevice = pdfium::MakeUnique<CFDE_RenderDevice>(pDevice, false);
}

void CFDE_TextOut::SetClipRect(const CFX_Rect& rtClip) {
  m_rtClip = rtClip.As<float>();
}

void CFDE_TextOut::SetClipRect(const CFX_RectF& rtClip) {
  m_rtClip = rtClip;
}

void CFDE_TextOut::SetLogicClipRect(const CFX_RectF& rtClip) {
  m_rtLogicClip = rtClip;
}

void CFDE_TextOut::SetMatrix(const CFX_Matrix& matrix) {
  m_Matrix = matrix;
}

void CFDE_TextOut::SetLineBreakTolerance(float fTolerance) {
  m_fTolerance = fTolerance;
  m_pTxtBreak->SetLineBreakTolerance(m_fTolerance);
}

int32_t CFDE_TextOut::GetTotalLines() {
  return m_iTotalLines;
}

void CFDE_TextOut::CalcLogicSize(const wchar_t* pwsStr,
                                 int32_t iLength,
                                 CFX_SizeF& size) {
  CFX_RectF rtText(0.0f, 0.0f, size.width, size.height);
  CalcLogicSize(pwsStr, iLength, rtText);
  size = rtText.Size();
}

void CFDE_TextOut::CalcLogicSize(const wchar_t* pwsStr,
                                 int32_t iLength,
                                 CFX_RectF& rect) {
  if (!pwsStr || iLength < 1) {
    rect.width = 0.0f;
    rect.height = 0.0f;
  } else {
    CalcTextSize(pwsStr, iLength, rect);
  }
}

void CFDE_TextOut::CalcTextSize(const wchar_t* pwsStr,
                                int32_t iLength,
                                CFX_RectF& rect) {
  ASSERT(m_pFont && m_fFontSize >= 1.0f);
  SetLineWidth(rect);
  m_iTotalLines = 0;
  const wchar_t* pStr = pwsStr;
  bool bHotKey = !!(m_dwStyles & FDE_TTOSTYLE_HotKey);
  float fWidth = 0.0f;
  float fHeight = 0.0f;
  float fStartPos = rect.right();
  CFX_BreakType dwBreakStatus = CFX_BreakType::None;
  wchar_t wPreChar = 0;
  wchar_t wch;
  wchar_t wBreak = 0;
  while (iLength-- > 0) {
    wch = *pStr++;
    if (wBreak == 0 && (wch == L'\n' || wch == L'\r')) {
      wBreak = wch;
      m_pTxtBreak->SetParagraphBreakChar(wch);
    }
    if (bHotKey && wch == L'&' && wPreChar != L'&') {
      wPreChar = wch;
      continue;
    }
    dwBreakStatus = m_pTxtBreak->AppendChar(wch);
    if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus))
      RetrieveLineWidth(dwBreakStatus, fStartPos, fWidth, fHeight);

    wPreChar = 0;
  }
  dwBreakStatus = m_pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
  if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus))
    RetrieveLineWidth(dwBreakStatus, fStartPos, fWidth, fHeight);

  m_pTxtBreak->Reset();
  float fInc = rect.Height() - fHeight;
  if (m_iAlignment >= FDE_TTOALIGNMENT_CenterLeft &&
      m_iAlignment < FDE_TTOALIGNMENT_BottomLeft) {
    fInc /= 2.0f;
  } else if (m_iAlignment < FDE_TTOALIGNMENT_CenterLeft) {
    fInc = 0.0f;
  }
  rect.left += fStartPos;
  rect.top += fInc;
  rect.width = std::min(fWidth, rect.Width());
  rect.height = fHeight;
  if (m_dwStyles & FDE_TTOSTYLE_LastLineHeight)
    rect.height -= m_fLineSpace - m_fFontSize;
}

void CFDE_TextOut::SetLineWidth(CFX_RectF& rect) {
  if ((m_dwStyles & FDE_TTOSTYLE_SingleLine) == 0) {
    float fLineWidth = 0.0f;
    if (rect.Width() < 1.0f)
      rect.width = m_fFontSize * 1000.0f;

    fLineWidth = rect.Width();
    m_pTxtBreak->SetLineWidth(fLineWidth);
  }
}

bool CFDE_TextOut::RetrieveLineWidth(CFX_BreakType dwBreakStatus,
                                     float& fStartPos,
                                     float& fWidth,
                                     float& fHeight) {
  if (CFX_BreakTypeNoneOrPiece(dwBreakStatus))
    return false;

  float fLineStep = (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize;
  bool bLineWrap = !!(m_dwStyles & FDE_TTOSTYLE_LineWrap);
  float fLineWidth = 0.0f;
  int32_t iCount = m_pTxtBreak->CountBreakPieces();
  for (int32_t i = 0; i < iCount; i++) {
    const CFX_BreakPiece* pPiece = m_pTxtBreak->GetBreakPieceUnstable(i);
    fLineWidth += static_cast<float>(pPiece->m_iWidth) / 20000.0f;
    fStartPos =
        std::min(fStartPos, static_cast<float>(pPiece->m_iStartPos) / 20000.0f);
  }
  m_pTxtBreak->ClearBreakPieces();
  if (dwBreakStatus == CFX_BreakType::Paragraph) {
    m_pTxtBreak->Reset();
  }
  if (!bLineWrap && dwBreakStatus == CFX_BreakType::Line) {
    fWidth += fLineWidth;
  } else {
    fWidth = std::max(fWidth, fLineWidth);
    fHeight += fLineStep;
  }
  m_iTotalLines++;
  return true;
}

void CFDE_TextOut::DrawText(const wchar_t* pwsStr,
                            int32_t iLength,
                            int32_t x,
                            int32_t y) {
  CFX_RectF rtText(static_cast<float>(x), static_cast<float>(y),
                   m_fFontSize * 1000.0f, m_fFontSize * 1000.0f);
  DrawText(pwsStr, iLength, rtText);
}

void CFDE_TextOut::DrawText(const wchar_t* pwsStr,
                            int32_t iLength,
                            float x,
                            float y) {
  DrawText(pwsStr, iLength,
           CFX_RectF(x, y, m_fFontSize * 1000.0f, m_fFontSize * 1000.0f));
}

void CFDE_TextOut::DrawText(const wchar_t* pwsStr,
                            int32_t iLength,
                            const CFX_Rect& rect) {
  DrawText(pwsStr, iLength, rect.As<float>());
}

void CFDE_TextOut::DrawText(const wchar_t* pwsStr,
                            int32_t iLength,
                            const CFX_RectF& rect) {
  CFX_RectF rtText(rect.left, rect.top, rect.width, rect.height);
  CFX_Matrix rm;
  rm.SetReverse(m_Matrix);
  rm.TransformRect(rtText);
  DrawText(pwsStr, iLength, rtText, m_rtClip);
}

void CFDE_TextOut::DrawLogicText(const wchar_t* pwsStr,
                                 int32_t iLength,
                                 float x,
                                 float y) {
  CFX_RectF rtText(x, y, m_fFontSize * 1000.0f, m_fFontSize * 1000.0f);
  DrawLogicText(pwsStr, iLength, rtText);
}

void CFDE_TextOut::DrawLogicText(const wchar_t* pwsStr,
                                 int32_t iLength,
                                 const CFX_RectF& rect) {
  CFX_RectF rtClip(m_rtLogicClip.left, m_rtLogicClip.top, m_rtLogicClip.width,
                   m_rtLogicClip.height);
  m_Matrix.TransformRect(rtClip);
  DrawText(pwsStr, iLength, rect, rtClip);
}

void CFDE_TextOut::DrawText(const wchar_t* pwsStr,
                            int32_t iLength,
                            const CFX_RectF& rect,
                            const CFX_RectF& rtClip) {
  ASSERT(m_pFont && m_fFontSize >= 1.0f);
  if (!pwsStr || iLength < 1)
    return;
  if (rect.width < m_fFontSize || rect.height < m_fFontSize)
    return;

  float fLineWidth = rect.width;
  m_pTxtBreak->SetLineWidth(fLineWidth);
  m_ttoLines.clear();
  m_wsText.clear();
  LoadText(pwsStr, iLength, rect);
  if (m_dwStyles & FDE_TTOSTYLE_Ellipsis) {
    ReplaceWidthEllipsis();
  }
  Reload(rect);
  DoAlignment(rect);
  OnDraw(rtClip);
}

void CFDE_TextOut::ExpandBuffer(int32_t iSize, int32_t iType) {
  ASSERT(iSize >= 0);
  size_t size = iSize;
  switch (iType) {
    case 0:
      if (m_CharWidths.size() < size)
        m_CharWidths.resize(size, 0);
      break;
    case 1:
      if (m_EllCharWidths.size() < size)
        m_EllCharWidths.resize(size, 0);
      break;
    case 2:
      if (m_CharPos.size() < size)
        m_CharPos.resize(size, FXTEXT_CHARPOS());
      break;
  }
}

void CFDE_TextOut::LoadEllipsis() {
  if (!m_bElliChanged) {
    return;
  }
  m_bElliChanged = false;
  m_iEllipsisWidth = 0;
  int32_t iLength = m_wsEllipsis.GetLength();
  if (iLength < 1) {
    return;
  }
  ExpandBuffer(iLength, 1);
  const wchar_t* pStr = m_wsEllipsis.c_str();
  CFX_BreakType dwBreakStatus;
  wchar_t wch;
  while (iLength-- > 0) {
    wch = *pStr++;
    dwBreakStatus = m_pTxtBreak->AppendChar(wch);
    if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus))
      RetrieveEllPieces(&m_EllCharWidths);
  }
  dwBreakStatus = m_pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
  if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus))
    RetrieveEllPieces(&m_EllCharWidths);

  m_pTxtBreak->Reset();
}

void CFDE_TextOut::RetrieveEllPieces(std::vector<int32_t>* pCharWidths) {
  int32_t iCount = m_pTxtBreak->CountBreakPieces();
  int32_t iCharIndex = 0;
  for (int32_t i = 0; i < iCount; i++) {
    const CFX_BreakPiece* pPiece = m_pTxtBreak->GetBreakPieceUnstable(i);
    int32_t iPieceChars = pPiece->GetLength();
    for (int32_t j = 0; j < iPieceChars; j++) {
      (*pCharWidths)[iCharIndex] =
          std::max(pPiece->GetChar(j)->m_iCharWidth, 0);
      m_iEllipsisWidth += (*pCharWidths)[iCharIndex];
      iCharIndex++;
    }
  }
  m_pTxtBreak->ClearBreakPieces();
}

void CFDE_TextOut::LoadText(const wchar_t* pwsStr,
                            int32_t iLength,
                            const CFX_RectF& rect) {
  wchar_t* pStr = m_wsText.GetBuffer(iLength);
  int32_t iTxtLength = iLength;
  ExpandBuffer(iTxtLength, 0);
  bool bHotKey = !!(m_dwStyles & FDE_TTOSTYLE_HotKey);
  bool bLineWrap = !!(m_dwStyles & FDE_TTOSTYLE_LineWrap);
  float fLineStep = (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize;
  float fLineStop = rect.bottom();
  m_fLinePos = rect.top;
  m_HotKeys.clear();
  int32_t iStartChar = 0;
  int32_t iChars = 0;
  int32_t iPieceWidths = 0;
  CFX_BreakType dwBreakStatus;
  wchar_t wch;
  bool bRet = false;
  while (iTxtLength-- > 0) {
    wch = *pwsStr++;
    if (bHotKey && wch == L'&' && *(pStr - 1) != L'&') {
      if (iTxtLength > 0)
        m_HotKeys.push_back(iChars);
      continue;
    }
    *pStr++ = wch;
    iChars++;
    dwBreakStatus = m_pTxtBreak->AppendChar(wch);
    if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus)) {
      bool bEndofLine =
          RetrievePieces(dwBreakStatus, iStartChar, iPieceWidths, false, rect);
      if (bEndofLine &&
          (bLineWrap || dwBreakStatus == CFX_BreakType::Paragraph ||
           dwBreakStatus == CFX_BreakType::Page)) {
        iPieceWidths = 0;
        m_iCurLine++;
        m_fLinePos += fLineStep;
      }
      if (m_fLinePos + fLineStep > fLineStop) {
        int32_t iCurLine = bEndofLine ? m_iCurLine - 1 : m_iCurLine;
        m_ttoLines[iCurLine].SetNewReload(true);
        bRet = true;
        break;
      }
    }
  }
  dwBreakStatus = m_pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
  if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus) && !bRet)
    RetrievePieces(dwBreakStatus, iStartChar, iPieceWidths, false, rect);

  m_pTxtBreak->ClearBreakPieces();
  m_pTxtBreak->Reset();
  m_wsText.ReleaseBuffer(iLength);
}

bool CFDE_TextOut::RetrievePieces(CFX_BreakType dwBreakStatus,
                                  int32_t& iStartChar,
                                  int32_t& iPieceWidths,
                                  bool bReload,
                                  const CFX_RectF& rect) {
  bool bSingleLine = !!(m_dwStyles & FDE_TTOSTYLE_SingleLine);
  bool bLineWrap = !!(m_dwStyles & FDE_TTOSTYLE_LineWrap);
  float fLineStep = (m_fLineSpace > m_fFontSize) ? m_fLineSpace : m_fFontSize;
  bool bNeedReload = false;
  float fLineWidth = rect.Width();
  int32_t iLineWidth = FXSYS_round(fLineWidth * 20000.0f);
  int32_t iCount = m_pTxtBreak->CountBreakPieces();
  for (int32_t i = 0; i < iCount; i++) {
    const CFX_BreakPiece* pPiece = m_pTxtBreak->GetBreakPieceUnstable(i);
    int32_t iPieceChars = pPiece->GetLength();
    int32_t iChar = iStartChar;
    int32_t iWidth = 0;
    int32_t j = 0;
    for (; j < iPieceChars; j++) {
      const CFX_Char* pTC = pPiece->GetChar(j);
      int32_t iCurCharWidth = pTC->m_iCharWidth > 0 ? pTC->m_iCharWidth : 0;
      if (bSingleLine || !bLineWrap) {
        if (iLineWidth - iPieceWidths - iWidth < iCurCharWidth) {
          bNeedReload = true;
          break;
        }
      }
      iWidth += iCurCharWidth;
      m_CharWidths[iChar++] = iCurCharWidth;
    }
    if (j == 0 && !bReload) {
      m_ttoLines[m_iCurLine].SetNewReload(true);
    } else if (j > 0) {
      CFX_RectF rtPiece;
      rtPiece.left = rect.left + (float)pPiece->m_iStartPos / 20000.0f;
      rtPiece.top = m_fLinePos;
      rtPiece.width = iWidth / 20000.0f;
      rtPiece.height = fLineStep;

      FDE_TTOPIECE ttoPiece;
      ttoPiece.iStartChar = iStartChar;
      ttoPiece.iChars = j;
      ttoPiece.rtPiece = rtPiece;
      ttoPiece.dwCharStyles = pPiece->m_dwCharStyles;
      if (FX_IsOdd(pPiece->m_iBidiLevel)) {
        ttoPiece.dwCharStyles |= FX_TXTCHARSTYLE_OddBidiLevel;
      }
      AppendPiece(ttoPiece, bNeedReload, (bReload && i == iCount - 1));
    }
    iStartChar += iPieceChars;
    iPieceWidths += iWidth;
  }
  m_pTxtBreak->ClearBreakPieces();
  return bSingleLine || bLineWrap || bNeedReload ||
         dwBreakStatus == CFX_BreakType::Paragraph;
}

void CFDE_TextOut::AppendPiece(const FDE_TTOPIECE& ttoPiece,
                               bool bNeedReload,
                               bool bEnd) {
  if (m_iCurLine >= pdfium::CollectionSize<int32_t>(m_ttoLines)) {
    CFDE_TTOLine ttoLine;
    ttoLine.SetNewReload(bNeedReload);
    m_iCurPiece = ttoLine.AddPiece(m_iCurPiece, ttoPiece);
    m_ttoLines.push_back(ttoLine);
    m_iCurLine = pdfium::CollectionSize<int32_t>(m_ttoLines) - 1;
  } else {
    CFDE_TTOLine* pLine = &m_ttoLines[m_iCurLine];
    pLine->SetNewReload(bNeedReload);
    m_iCurPiece = pLine->AddPiece(m_iCurPiece, ttoPiece);
    if (bEnd) {
      int32_t iPieces = pLine->GetSize();
      if (m_iCurPiece < iPieces) {
        pLine->RemoveLast(iPieces - m_iCurPiece - 1);
      }
    }
  }
  if (!bEnd && bNeedReload)
    m_iCurPiece = 0;
}

void CFDE_TextOut::ReplaceWidthEllipsis() {
  LoadEllipsis();
  int32_t iLength = m_wsEllipsis.GetLength();
  if (iLength < 1)
    return;

  for (auto& line : m_ttoLines) {
    if (!line.GetNewReload())
      continue;

    int32_t iEllipsisCharIndex = iLength - 1;
    int32_t iCharWidth = 0;
    int32_t iCharCount = 0;
    int32_t iPiece = line.GetSize();
    while (iPiece-- > 0) {
      FDE_TTOPIECE* pPiece = line.GetPtrAt(iPiece);
      if (!pPiece)
        break;

      for (int32_t j = pPiece->iChars - 1; j >= 0; j--) {
        if (iEllipsisCharIndex < 0)
          break;

        int32_t index = pPiece->iStartChar + j;
        iCharWidth += m_CharWidths[index];
        iCharCount++;
        if (iCharCount <= iLength) {
          m_wsText.SetAt(index, m_wsEllipsis.GetAt(iEllipsisCharIndex));
          m_CharWidths[index] = m_EllCharWidths[iEllipsisCharIndex];
        } else if (iCharWidth <= m_iEllipsisWidth) {
          m_wsText.SetAt(index, 0);
          m_CharWidths[index] = 0;
        }
        iEllipsisCharIndex--;
      }
      if (iEllipsisCharIndex < 0)
        break;
    }
  }
}

void CFDE_TextOut::Reload(const CFX_RectF& rect) {
  int i = 0;
  for (auto& line : m_ttoLines) {
    if (line.GetNewReload()) {
      m_iCurLine = i;
      m_iCurPiece = 0;
      ReloadLinePiece(&line, rect);
    }
    ++i;
  }
}

void CFDE_TextOut::ReloadLinePiece(CFDE_TTOLine* pLine, const CFX_RectF& rect) {
  const wchar_t* pwsStr = m_wsText.c_str();
  int32_t iPieceWidths = 0;
  FDE_TTOPIECE* pPiece = pLine->GetPtrAt(0);
  int32_t iStartChar = pPiece->iStartChar;
  m_fLinePos = pPiece->rtPiece.top;
  int32_t iPieceCount = pLine->GetSize();
  int32_t iPieceIndex = 0;
  CFX_BreakType dwBreakStatus = CFX_BreakType::None;
  wchar_t wch;
  while (iPieceIndex < iPieceCount) {
    int32_t iStar = iStartChar;
    int32_t iEnd = pPiece->iChars + iStar;
    while (iStar < iEnd) {
      wch = *(pwsStr + iStar);
      dwBreakStatus = m_pTxtBreak->AppendChar(wch);
      if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus))
        RetrievePieces(dwBreakStatus, iStartChar, iPieceWidths, true, rect);
      iStar++;
    }
    iPieceIndex++;
    pPiece = pLine->GetPtrAt(iPieceIndex);
  }
  dwBreakStatus = m_pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
  if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus))
    RetrievePieces(dwBreakStatus, iStartChar, iPieceWidths, true, rect);

  m_pTxtBreak->Reset();
}

void CFDE_TextOut::DoAlignment(const CFX_RectF& rect) {
  if (m_ttoLines.empty())
    return;

  float fLineStopS = rect.bottom();
  FDE_TTOPIECE* pFirstPiece = m_ttoLines.back().GetPtrAt(0);
  if (!pFirstPiece)
    return;

  float fLineStopD = pFirstPiece->rtPiece.bottom();
  float fInc = fLineStopS - fLineStopD;
  if (m_iAlignment >= FDE_TTOALIGNMENT_CenterLeft &&
      m_iAlignment < FDE_TTOALIGNMENT_BottomLeft) {
    fInc /= 2.0f;
  } else if (m_iAlignment < FDE_TTOALIGNMENT_CenterLeft) {
    fInc = 0.0f;
  }
  if (fInc < 1.0f)
    return;
  for (auto& line : m_ttoLines) {
    int32_t iPieces = line.GetSize();
    for (int32_t j = 0; j < iPieces; j++) {
      FDE_TTOPIECE* pPiece = line.GetPtrAt(j);
      pPiece->rtPiece.top += fInc;
    }
  }
}

void CFDE_TextOut::OnDraw(const CFX_RectF& rtClip) {
  if (!m_pRenderDevice || m_ttoLines.empty())
    return;

  auto pBrush = pdfium::MakeUnique<CFDE_Brush>();
  pBrush->SetColor(m_TxtColor);
  m_pRenderDevice->SaveState();
  if (rtClip.Width() > 0.0f && rtClip.Height() > 0.0f)
    m_pRenderDevice->SetClipRect(rtClip);

  auto pPen = pdfium::MakeUnique<CFDE_Pen>();
  pPen->SetColor(m_TxtColor);

  for (auto& line : m_ttoLines) {
    int32_t iPieces = line.GetSize();
    for (int32_t j = 0; j < iPieces; j++) {
      FDE_TTOPIECE* pPiece = line.GetPtrAt(j);
      if (!pPiece)
        continue;

      int32_t iCount = GetDisplayPos(pPiece);
      if (iCount > 0) {
        m_pRenderDevice->DrawString(pBrush.get(), m_pFont, m_CharPos.data(),
                                    iCount, m_fFontSize, &m_Matrix);
      }
      DrawLine(pPiece, pPen.get());
    }
  }
  m_pRenderDevice->RestoreState();
}

int32_t CFDE_TextOut::GetDisplayPos(FDE_TTOPIECE* pPiece) {
  FX_TXTRUN tr = ToTextRun(pPiece);
  ExpandBuffer(tr.iLength, 2);
  return m_pTxtBreak->GetDisplayPos(&tr, m_CharPos.data());
}

int32_t CFDE_TextOut::GetCharRects(const FDE_TTOPIECE* pPiece) {
  FX_TXTRUN tr = ToTextRun(pPiece);
  m_rectArray = m_pTxtBreak->GetCharRects(&tr);
  return pdfium::CollectionSize<int32_t>(m_rectArray);
}

FX_TXTRUN CFDE_TextOut::ToTextRun(const FDE_TTOPIECE* pPiece) {
  FX_TXTRUN tr;
  tr.wsStr = m_wsText + pPiece->iStartChar;
  tr.pWidths = &m_CharWidths[pPiece->iStartChar];
  tr.iLength = pPiece->iChars;
  tr.pFont = m_pFont;
  tr.fFontSize = m_fFontSize;
  tr.dwStyles = m_dwTxtBkStyles;
  tr.dwCharStyles = pPiece->dwCharStyles;
  tr.wLineBreakChar = m_wParagraphBkChar;
  tr.pRect = &pPiece->rtPiece;
  return tr;
}

void CFDE_TextOut::DrawLine(const FDE_TTOPIECE* pPiece, CFDE_Pen* pPen) {
  bool bUnderLine = !!(m_dwStyles & FDE_TTOSTYLE_Underline);
  bool bStrikeOut = !!(m_dwStyles & FDE_TTOSTYLE_Strikeout);
  bool bHotKey = !!(m_dwStyles & FDE_TTOSTYLE_HotKey);
  if (!bUnderLine && !bStrikeOut && !bHotKey)
    return;

  auto pPath = pdfium::MakeUnique<CFDE_Path>();
  int32_t iLineCount = 0;
  CFX_RectF rtText = pPiece->rtPiece;
  CFX_PointF pt1, pt2;
  if (bUnderLine) {
    pt1.x = rtText.left;
    pt1.y = rtText.bottom();
    pt2.x = rtText.right();
    pt2.y = rtText.bottom();
    pPath->AddLine(pt1, pt2);
    iLineCount++;
  }
  if (bStrikeOut) {
    pt1.x = rtText.left;
    pt1.y = rtText.bottom() - rtText.height * 2.0f / 5.0f;
    pt2.x = rtText.right();
    pt2.y = pt1.y;
    pPath->AddLine(pt1, pt2);
    iLineCount++;
  }
  if (bHotKey) {
    if (GetCharRects(pPiece) > 0) {
      for (int32_t iCharIndex : m_HotKeys) {
        if (iCharIndex >= pPiece->iStartChar &&
            iCharIndex < pPiece->iStartChar + pPiece->iChars) {
          CFX_RectF rect = m_rectArray[iCharIndex - pPiece->iStartChar];
          pt1.x = rect.left;
          pt1.y = rect.bottom();
          pt2.x = rect.right();
          pt2.y = rect.bottom();
          pPath->AddLine(pt1, pt2);
          iLineCount++;
        }
      }
    }
  }
  if (iLineCount > 0)
    m_pRenderDevice->DrawPath(pPen, 1, pPath.get(), &m_Matrix);
}

CFDE_TTOLine::CFDE_TTOLine() : m_bNewReload(false) {}

CFDE_TTOLine::CFDE_TTOLine(const CFDE_TTOLine& ttoLine) : m_pieces(5) {
  m_bNewReload = ttoLine.m_bNewReload;
  m_pieces = ttoLine.m_pieces;
}

CFDE_TTOLine::~CFDE_TTOLine() {}

int32_t CFDE_TTOLine::AddPiece(int32_t index, const FDE_TTOPIECE& ttoPiece) {
  if (index >= pdfium::CollectionSize<int32_t>(m_pieces)) {
    m_pieces.push_back(ttoPiece);
    return pdfium::CollectionSize<int32_t>(m_pieces);
  }
  m_pieces[index] = ttoPiece;
  return index;
}

int32_t CFDE_TTOLine::GetSize() const {
  return pdfium::CollectionSize<int32_t>(m_pieces);
}

FDE_TTOPIECE* CFDE_TTOLine::GetPtrAt(int32_t index) {
  return pdfium::IndexInBounds(m_pieces, index) ? &m_pieces[index] : nullptr;
}

void CFDE_TTOLine::RemoveLast(int32_t icount) {
  if (icount < 0)
    return;
  icount = std::min(icount, pdfium::CollectionSize<int32_t>(m_pieces));
  m_pieces.erase(m_pieces.end() - icount, m_pieces.end());
}

void CFDE_TTOLine::RemoveAll() {
  m_pieces.clear();
}
