// 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 "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
#include "core/fpdfapi/fpdf_page/include/cpdf_pageobjectholder.h"
#include "core/fpdfapi/fpdf_page/include/cpdf_pathobject.h"
#include "core/fpdfapi/fpdf_page/include/cpdf_textobject.h"
#include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h"
#include "core/fpdfapi/fpdf_render/include/cpdf_textrenderer.h"
#include "core/fpdfdoc/include/cpvt_word.h"
#include "core/fpdfdoc/include/ipvt_fontmap.h"
#include "core/fxge/include/fx_ge.h"
#include "fpdfsdk/cfx_systemhandler.h"
#include "fpdfsdk/fxedit/include/fx_edit.h"
#include "fpdfsdk/fxedit/include/fxet_edit.h"

#define FX_EDIT_UNDERLINEHALFWIDTH 0.5f
#define FX_EDIT_CROSSOUTHALFWIDTH 0.5f

CFX_FloatRect GetUnderLineRect(const CPVT_Word& word) {
  return CFX_FloatRect(word.ptWord.x, word.ptWord.y + word.fDescent * 0.5f,
                       word.ptWord.x + word.fWidth,
                       word.ptWord.y + word.fDescent * 0.25f);
}

CFX_FloatRect GetCrossoutRect(const CPVT_Word& word) {
  return CFX_FloatRect(word.ptWord.x,
                       word.ptWord.y + (word.fAscent + word.fDescent) * 0.5f +
                           word.fDescent * 0.25f,
                       word.ptWord.x + word.fWidth,
                       word.ptWord.y + (word.fAscent + word.fDescent) * 0.5f);
}

static void DrawTextString(CFX_RenderDevice* pDevice,
                           const CFX_FloatPoint& pt,
                           CPDF_Font* pFont,
                           FX_FLOAT fFontSize,
                           CFX_Matrix* pUser2Device,
                           const CFX_ByteString& str,
                           FX_ARGB crTextFill,
                           FX_ARGB crTextStroke,
                           int32_t nHorzScale) {
  FX_FLOAT x = pt.x, y = pt.y;
  pUser2Device->Transform(x, y);

  if (pFont) {
    if (nHorzScale != 100) {
      CFX_Matrix mt(nHorzScale / 100.0f, 0, 0, 1, 0, 0);
      mt.Concat(*pUser2Device);

      CPDF_RenderOptions ro;
      ro.m_Flags = RENDER_CLEARTYPE;
      ro.m_ColorMode = RENDER_COLOR_NORMAL;

      if (crTextStroke != 0) {
        CFX_FloatPoint pt1(0, 0), pt2(1, 0);
        pUser2Device->Transform(pt1.x, pt1.y);
        pUser2Device->Transform(pt2.x, pt2.y);
        CFX_GraphStateData gsd;
        gsd.m_LineWidth =
            (FX_FLOAT)FXSYS_fabs((pt2.x + pt2.y) - (pt1.x + pt1.y));

        CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize, &mt,
                                          str, crTextFill, crTextStroke, &gsd,
                                          &ro);
      } else {
        CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize, &mt,
                                          str, crTextFill, 0, NULL, &ro);
      }
    } else {
      CPDF_RenderOptions ro;
      ro.m_Flags = RENDER_CLEARTYPE;
      ro.m_ColorMode = RENDER_COLOR_NORMAL;

      if (crTextStroke != 0) {
        CFX_FloatPoint pt1(0, 0), pt2(1, 0);
        pUser2Device->Transform(pt1.x, pt1.y);
        pUser2Device->Transform(pt2.x, pt2.y);
        CFX_GraphStateData gsd;
        gsd.m_LineWidth =
            (FX_FLOAT)FXSYS_fabs((pt2.x + pt2.y) - (pt1.x + pt1.y));

        CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize,
                                          pUser2Device, str, crTextFill,
                                          crTextStroke, &gsd, &ro);
      } else {
        CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize,
                                          pUser2Device, str, crTextFill, 0,
                                          NULL, &ro);
      }
    }
  }
}

void IFX_Edit::DrawUnderline(CFX_RenderDevice* pDevice,
                             CFX_Matrix* pUser2Device,
                             IFX_Edit* pEdit,
                             FX_COLORREF color,
                             const CFX_FloatRect& rcClip,
                             const CFX_FloatPoint& ptOffset,
                             const CPVT_WordRange* pRange) {
  pDevice->SaveState();

  if (!rcClip.IsEmpty()) {
    CFX_FloatRect rcTemp = rcClip;
    pUser2Device->TransformRect(rcTemp);
    pDevice->SetClip_Rect(rcTemp.ToFxRect());
  }

  if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
    if (pEdit->GetFontMap()) {
      if (pRange)
        pIterator->SetAt(pRange->BeginPos);
      else
        pIterator->SetAt(0);

      while (pIterator->NextWord()) {
        CPVT_WordPlace place = pIterator->GetAt();
        if (pRange && place.WordCmp(pRange->EndPos) > 0)
          break;

        CPVT_Word word;
        if (pIterator->GetWord(word)) {
          CFX_PathData pathUnderline;
          CFX_FloatRect rcUnderline = GetUnderLineRect(word);
          rcUnderline.left += ptOffset.x;
          rcUnderline.right += ptOffset.x;
          rcUnderline.top += ptOffset.y;
          rcUnderline.bottom += ptOffset.y;
          pathUnderline.AppendRect(rcUnderline.left, rcUnderline.bottom,
                                   rcUnderline.right, rcUnderline.top);

          pDevice->DrawPath(&pathUnderline, pUser2Device, NULL, color, 0,
                            FXFILL_WINDING);
        }
      }
    }
  }

  pDevice->RestoreState();
}

void IFX_Edit::DrawEdit(CFX_RenderDevice* pDevice,
                        CFX_Matrix* pUser2Device,
                        IFX_Edit* pEdit,
                        FX_COLORREF crTextFill,
                        FX_COLORREF crTextStroke,
                        const CFX_FloatRect& rcClip,
                        const CFX_FloatPoint& ptOffset,
                        const CPVT_WordRange* pRange,
                        CFX_SystemHandler* pSystemHandler,
                        void* pFFLData) {
  const bool bContinuous =
      pEdit->GetCharArray() == 0 && pEdit->GetCharSpace() <= 0.0f;
  uint16_t SubWord = pEdit->GetPasswordChar();
  FX_FLOAT fFontSize = pEdit->GetFontSize();
  CPVT_WordRange wrSelect = pEdit->GetSelectWordRange();
  int32_t nHorzScale = pEdit->GetHorzScale();

  FX_COLORREF crCurFill = crTextFill;
  FX_COLORREF crOldFill = crCurFill;

  FX_BOOL bSelect = FALSE;
  const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255);
  const FX_COLORREF crSelBK = ArgbEncode(255, 0, 51, 113);

  CFX_ByteTextBuf sTextBuf;
  int32_t nFontIndex = -1;
  CFX_FloatPoint ptBT(0.0f, 0.0f);

  pDevice->SaveState();

  if (!rcClip.IsEmpty()) {
    CFX_FloatRect rcTemp = rcClip;
    pUser2Device->TransformRect(rcTemp);
    pDevice->SetClip_Rect(rcTemp.ToFxRect());
  }

  if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
    if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) {
      if (pRange)
        pIterator->SetAt(pRange->BeginPos);
      else
        pIterator->SetAt(0);

      CPVT_WordPlace oldplace;

      while (pIterator->NextWord()) {
        CPVT_WordPlace place = pIterator->GetAt();
        if (pRange && place.WordCmp(pRange->EndPos) > 0)
          break;

        if (wrSelect.IsExist()) {
          bSelect = place.WordCmp(wrSelect.BeginPos) > 0 &&
                    place.WordCmp(wrSelect.EndPos) <= 0;
          if (bSelect) {
            crCurFill = crWhite;
          } else {
            crCurFill = crTextFill;
          }
        }
        if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) {
          crCurFill = crTextFill;
          crOldFill = crCurFill;
        }
        CPVT_Word word;
        if (pIterator->GetWord(word)) {
          if (bSelect) {
            CPVT_Line line;
            pIterator->GetLine(line);

            if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) {
              CFX_FloatRect rc(word.ptWord.x, line.ptLine.y + line.fLineDescent,
                               word.ptWord.x + word.fWidth,
                               line.ptLine.y + line.fLineAscent);
              rc.Intersect(rcClip);
              pSystemHandler->OutputSelectedRect(pFFLData, rc);
            } else {
              CFX_PathData pathSelBK;
              pathSelBK.AppendRect(word.ptWord.x,
                                   line.ptLine.y + line.fLineDescent,
                                   word.ptWord.x + word.fWidth,
                                   line.ptLine.y + line.fLineAscent);

              pDevice->DrawPath(&pathSelBK, pUser2Device, NULL, crSelBK, 0,
                                FXFILL_WINDING);
            }
          }

          if (bContinuous) {
            if (place.LineCmp(oldplace) != 0 || word.nFontIndex != nFontIndex ||
                crOldFill != crCurFill) {
              if (sTextBuf.GetLength() > 0) {
                DrawTextString(
                    pDevice,
                    CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
                    pFontMap->GetPDFFont(nFontIndex), fFontSize, pUser2Device,
                    sTextBuf.AsStringC(), crOldFill, crTextStroke, nHorzScale);

                sTextBuf.Clear();
              }
              nFontIndex = word.nFontIndex;
              ptBT = word.ptWord;
              crOldFill = crCurFill;
            }

            sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word,
                                         SubWord)
                            .AsStringC();
          } else {
            DrawTextString(
                pDevice, CFX_FloatPoint(word.ptWord.x + ptOffset.x,
                                        word.ptWord.y + ptOffset.y),
                pFontMap->GetPDFFont(word.nFontIndex), fFontSize, pUser2Device,
                GetPDFWordString(pFontMap, word.nFontIndex, word.Word, SubWord),
                crCurFill, crTextStroke, nHorzScale);
          }
          oldplace = place;
        }
      }

      if (sTextBuf.GetLength() > 0) {
        DrawTextString(
            pDevice, CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
            pFontMap->GetPDFFont(nFontIndex), fFontSize, pUser2Device,
            sTextBuf.AsStringC(), crOldFill, crTextStroke, nHorzScale);
      }
    }
  }

  pDevice->RestoreState();
}

void IFX_Edit::DrawRichEdit(CFX_RenderDevice* pDevice,
                            CFX_Matrix* pUser2Device,
                            IFX_Edit* pEdit,
                            const CFX_FloatRect& rcClip,
                            const CFX_FloatPoint& ptOffset,
                            const CPVT_WordRange* pRange) {
  CPVT_WordRange wrSelect = pEdit->GetSelectWordRange();

  FX_COLORREF crCurText = ArgbEncode(255, 0, 0, 0);
  FX_COLORREF crOld = crCurText;
  FX_BOOL bSelect = FALSE;
  const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255);
  const FX_COLORREF crSelBK = ArgbEncode(255, 0, 51, 113);

  CFX_ByteTextBuf sTextBuf;
  CPVT_WordProps wp;
  CFX_FloatPoint ptBT(0.0f, 0.0f);

  pDevice->SaveState();

  if (!rcClip.IsEmpty()) {
    CFX_FloatRect rcTemp = rcClip;
    pUser2Device->TransformRect(rcTemp);
    pDevice->SetClip_Rect(rcTemp.ToFxRect());
  }

  if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
    if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) {
      if (pRange)
        pIterator->SetAt(pRange->BeginPos);
      else
        pIterator->SetAt(0);

      CPVT_WordPlace oldplace;

      while (pIterator->NextWord()) {
        CPVT_WordPlace place = pIterator->GetAt();
        if (pRange && place.WordCmp(pRange->EndPos) > 0)
          break;

        CPVT_Word word;
        if (pIterator->GetWord(word)) {
          word.WordProps.fFontSize = word.fFontSize;

          crCurText = ArgbEncode(255, word.WordProps.dwWordColor);

          if (wrSelect.IsExist()) {
            bSelect = place.WordCmp(wrSelect.BeginPos) > 0 &&
                      place.WordCmp(wrSelect.EndPos) <= 0;
            if (bSelect) {
              crCurText = crWhite;
            }
          }

          if (bSelect) {
            CPVT_Line line;
            pIterator->GetLine(line);

            CFX_PathData pathSelBK;
            pathSelBK.AppendRect(word.ptWord.x + ptOffset.x,
                                 line.ptLine.y + line.fLineDescent + ptOffset.y,
                                 word.ptWord.x + word.fWidth + ptOffset.x,
                                 line.ptLine.y + line.fLineAscent + ptOffset.y);

            pDevice->DrawPath(&pathSelBK, pUser2Device, NULL, crSelBK, 0,
                              FXFILL_WINDING);
          }

          if (place.LineCmp(oldplace) != 0 ||
              word.WordProps.fCharSpace > 0.0f ||
              word.WordProps.nHorzScale != 100 ||
              FXSYS_memcmp(&word.WordProps, &wp, sizeof(CPVT_WordProps)) != 0 ||
              crOld != crCurText) {
            if (sTextBuf.GetLength() > 0) {
              DrawTextString(
                  pDevice,
                  CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
                  pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize,
                  pUser2Device, sTextBuf.AsStringC(), crOld, 0, wp.nHorzScale);

              sTextBuf.Clear();
            }
            wp = word.WordProps;
            ptBT = word.ptWord;
            crOld = crCurText;
          }

          sTextBuf << GetPDFWordString(pFontMap, word.WordProps.nFontIndex,
                                       word.Word, 0)
                          .AsStringC();

          if (word.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) {
            CFX_PathData pathUnderline;
            CFX_FloatRect rcUnderline = GetUnderLineRect(word);
            pathUnderline.AppendRect(rcUnderline.left, rcUnderline.bottom,
                                     rcUnderline.right, rcUnderline.top);

            pDevice->DrawPath(&pathUnderline, pUser2Device, NULL, crCurText, 0,
                              FXFILL_WINDING);
          }

          if (word.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) {
            CFX_PathData pathCrossout;
            CFX_FloatRect rcCrossout = GetCrossoutRect(word);
            pathCrossout.AppendRect(rcCrossout.left, rcCrossout.bottom,
                                    rcCrossout.right, rcCrossout.top);

            pDevice->DrawPath(&pathCrossout, pUser2Device, NULL, crCurText, 0,
                              FXFILL_WINDING);
          }

          oldplace = place;
        }
      }

      if (sTextBuf.GetLength() > 0) {
        DrawTextString(
            pDevice, CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
            pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize, pUser2Device,
            sTextBuf.AsStringC(), crOld, 0, wp.nHorzScale);
      }
    }
  }

  pDevice->RestoreState();
}

static void AddRectToPageObjects(CPDF_PageObjectHolder* pObjectHolder,
                                 FX_COLORREF crFill,
                                 const CFX_FloatRect& rcFill) {
  std::unique_ptr<CPDF_PathObject> pPathObj(new CPDF_PathObject);
  CFX_PathData* pPathData = pPathObj->m_Path.GetModify();
  pPathData->AppendRect(rcFill.left, rcFill.bottom, rcFill.right, rcFill.top);

  FX_FLOAT rgb[3];
  rgb[0] = FXARGB_R(crFill) / 255.0f;
  rgb[1] = FXARGB_G(crFill) / 255.0f;
  rgb[2] = FXARGB_B(crFill) / 255.0f;
  pPathObj->m_ColorState.SetFillColor(
      CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3);

  pPathObj->m_FillType = FXFILL_ALTERNATE;
  pPathObj->m_bStroke = FALSE;
  pObjectHolder->GetPageObjectList()->push_back(std::move(pPathObj));
}

static CPDF_TextObject* AddTextObjToPageObjects(
    CPDF_PageObjectHolder* pObjectHolder,
    FX_COLORREF crText,
    CPDF_Font* pFont,
    FX_FLOAT fFontSize,
    FX_FLOAT fCharSpace,
    int32_t nHorzScale,
    const CFX_FloatPoint& point,
    const CFX_ByteString& text) {
  std::unique_ptr<CPDF_TextObject> pTxtObj(new CPDF_TextObject);
  CPDF_TextStateData* pTextStateData = pTxtObj->m_TextState.GetModify();
  pTextStateData->m_pFont = pFont;
  pTextStateData->m_FontSize = fFontSize;
  pTextStateData->m_CharSpace = fCharSpace;
  pTextStateData->m_WordSpace = 0;
  pTextStateData->m_TextMode = 0;
  pTextStateData->m_Matrix[0] = nHorzScale / 100.0f;
  pTextStateData->m_Matrix[1] = 0;
  pTextStateData->m_Matrix[2] = 0;
  pTextStateData->m_Matrix[3] = 1;

  FX_FLOAT rgb[3];
  rgb[0] = FXARGB_R(crText) / 255.0f;
  rgb[1] = FXARGB_G(crText) / 255.0f;
  rgb[2] = FXARGB_B(crText) / 255.0f;
  pTxtObj->m_ColorState.SetFillColor(
      CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3);
  pTxtObj->m_ColorState.SetStrokeColor(
      CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3);

  pTxtObj->SetPosition(point.x, point.y);
  pTxtObj->SetText(text);

  CPDF_TextObject* pRet = pTxtObj.get();
  pObjectHolder->GetPageObjectList()->push_back(std::move(pTxtObj));
  return pRet;
}

void IFX_Edit::GeneratePageObjects(
    CPDF_PageObjectHolder* pObjectHolder,
    IFX_Edit* pEdit,
    const CFX_FloatPoint& ptOffset,
    const CPVT_WordRange* pRange,
    FX_COLORREF crText,
    CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray) {
  FX_FLOAT fFontSize = pEdit->GetFontSize();

  int32_t nOldFontIndex = -1;

  CFX_ByteTextBuf sTextBuf;
  CFX_FloatPoint ptBT(0.0f, 0.0f);

  ObjArray.RemoveAll();

  if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
    if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) {
      if (pRange)
        pIterator->SetAt(pRange->BeginPos);
      else
        pIterator->SetAt(0);

      CPVT_WordPlace oldplace;

      while (pIterator->NextWord()) {
        CPVT_WordPlace place = pIterator->GetAt();
        if (pRange && place.WordCmp(pRange->EndPos) > 0)
          break;

        CPVT_Word word;
        if (pIterator->GetWord(word)) {
          if (place.LineCmp(oldplace) != 0 ||
              nOldFontIndex != word.nFontIndex) {
            if (sTextBuf.GetLength() > 0) {
              ObjArray.Add(AddTextObjToPageObjects(
                  pObjectHolder, crText, pFontMap->GetPDFFont(nOldFontIndex),
                  fFontSize, 0.0f, 100,
                  CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
                  sTextBuf.AsStringC()));

              sTextBuf.Clear();
            }

            ptBT = word.ptWord;
            nOldFontIndex = word.nFontIndex;
          }

          sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, 0)
                          .AsStringC();
          oldplace = place;
        }
      }

      if (sTextBuf.GetLength() > 0) {
        ObjArray.Add(AddTextObjToPageObjects(
            pObjectHolder, crText, pFontMap->GetPDFFont(nOldFontIndex),
            fFontSize, 0.0f, 100,
            CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
            sTextBuf.AsStringC()));
      }
    }
  }
}

void IFX_Edit::GenerateRichPageObjects(
    CPDF_PageObjectHolder* pObjectHolder,
    IFX_Edit* pEdit,
    const CFX_FloatPoint& ptOffset,
    const CPVT_WordRange* pRange,
    CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray) {
  FX_COLORREF crCurText = ArgbEncode(255, 0, 0, 0);
  FX_COLORREF crOld = crCurText;

  CFX_ByteTextBuf sTextBuf;
  CPVT_WordProps wp;
  CFX_FloatPoint ptBT(0.0f, 0.0f);

  ObjArray.RemoveAll();

  if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
    if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) {
      if (pRange)
        pIterator->SetAt(pRange->BeginPos);
      else
        pIterator->SetAt(0);

      CPVT_WordPlace oldplace;

      while (pIterator->NextWord()) {
        CPVT_WordPlace place = pIterator->GetAt();
        if (pRange && place.WordCmp(pRange->EndPos) > 0)
          break;

        CPVT_Word word;
        if (pIterator->GetWord(word)) {
          word.WordProps.fFontSize = word.fFontSize;

          crCurText = ArgbEncode(255, word.WordProps.dwWordColor);

          if (place.LineCmp(oldplace) != 0 ||
              word.WordProps.fCharSpace > 0.0f ||
              word.WordProps.nHorzScale != 100 ||
              FXSYS_memcmp(&word.WordProps, &wp, sizeof(CPVT_WordProps)) != 0 ||
              crOld != crCurText) {
            if (sTextBuf.GetLength() > 0) {
              ObjArray.Add(AddTextObjToPageObjects(
                  pObjectHolder, crOld, pFontMap->GetPDFFont(wp.nFontIndex),
                  wp.fFontSize, wp.fCharSpace, wp.nHorzScale,
                  CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
                  sTextBuf.AsStringC()));

              sTextBuf.Clear();
            }

            wp = word.WordProps;
            ptBT = word.ptWord;
            crOld = crCurText;
          }

          sTextBuf << GetPDFWordString(pFontMap, word.WordProps.nFontIndex,
                                       word.Word, 0)
                          .AsStringC();

          if (word.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) {
            CFX_FloatRect rcUnderline = GetUnderLineRect(word);
            rcUnderline.left += ptOffset.x;
            rcUnderline.right += ptOffset.x;
            rcUnderline.top += ptOffset.y;
            rcUnderline.bottom += ptOffset.y;

            AddRectToPageObjects(pObjectHolder, crCurText, rcUnderline);
          }

          if (word.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) {
            CFX_FloatRect rcCrossout = GetCrossoutRect(word);
            rcCrossout.left += ptOffset.x;
            rcCrossout.right += ptOffset.x;
            rcCrossout.top += ptOffset.y;
            rcCrossout.bottom += ptOffset.y;

            AddRectToPageObjects(pObjectHolder, crCurText, rcCrossout);
          }

          oldplace = place;
        }
      }

      if (sTextBuf.GetLength() > 0) {
        ObjArray.Add(AddTextObjToPageObjects(
            pObjectHolder, crOld, pFontMap->GetPDFFont(wp.nFontIndex),
            wp.fFontSize, wp.fCharSpace, wp.nHorzScale,
            CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
            sTextBuf.AsStringC()));
      }
    }
  }
}

void IFX_Edit::GenerateUnderlineObjects(CPDF_PageObjectHolder* pObjectHolder,
                                        IFX_Edit* pEdit,
                                        const CFX_FloatPoint& ptOffset,
                                        const CPVT_WordRange* pRange,
                                        FX_COLORREF color) {
  if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
    if (pEdit->GetFontMap()) {
      if (pRange)
        pIterator->SetAt(pRange->BeginPos);
      else
        pIterator->SetAt(0);

      CPVT_WordPlace oldplace;

      while (pIterator->NextWord()) {
        CPVT_WordPlace place = pIterator->GetAt();
        if (pRange && place.WordCmp(pRange->EndPos) > 0)
          break;

        CPVT_Word word;
        if (pIterator->GetWord(word)) {
          CFX_FloatRect rcUnderline = GetUnderLineRect(word);
          rcUnderline.left += ptOffset.x;
          rcUnderline.right += ptOffset.x;
          rcUnderline.top += ptOffset.y;
          rcUnderline.bottom += ptOffset.y;
          AddRectToPageObjects(pObjectHolder, color, rcUnderline);
        }
      }
    }
  }
}
