// 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/include/fpdfapi/fpdf_pageobj.h"
#include "core/include/fpdfapi/fpdf_render.h"
#include "fpdfsdk/include/fx_systemhandler.h"
#include "fpdfsdk/include/fxedit/fx_edit.h"
#include "fpdfsdk/include/fxedit/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,
                        IFX_SystemHandler* pSystemHandler,
                        void* pFFLData) {
  const bool bContinuous =
      pEdit->GetCharArray() == 0 && pEdit->GetCharSpace() <= 0.0f;
  FX_WORD 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 (IFX_Edit_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.GetByteString(),
                               crOldFill, crTextStroke, nHorzScale);

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

            sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word,
                                         SubWord);
          } 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.GetByteString(), 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 (IFX_Edit_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.GetByteString(), crOld, 0,
                             wp.nHorzScale);

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

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

          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.GetByteString(), 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 (IFX_Edit_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.GetByteString()));

              sTextBuf.Clear();
            }

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

          sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, 0);
          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.GetByteString()));
      }
    }
  }
}

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 (IFX_Edit_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.GetByteString()));

              sTextBuf.Clear();
            }

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

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

          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.GetByteString()));
      }
    }
  }
}

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);
        }
      }
    }
  }
}
