// 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 "../../include/fxedit/fxet_stub.h"
#include "../../include/fxedit/fx_edit.h"
#include "../../include/fxedit/fxet_edit.h"

#define FX_EDIT_UNDERLINEHALFWIDTH				0.5f
#define FX_EDIT_CROSSOUTHALFWIDTH				0.5f

extern CFX_ByteString GetPDFWordString(IFX_Edit_FontMap * pFontMap, FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord);

CPDF_Rect GetUnderLineRect(const CPVT_Word& word)
{
	return CPDF_Rect(word.ptWord.x, word.ptWord.y + word.fDescent * 0.5f,
						word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent * 0.25f);
}

CPDF_Rect GetCrossoutRect(const CPVT_Word& word)
{
	return CPDF_Rect(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 CPDF_Point& pt, CPDF_Font* pFont, FX_FLOAT fFontSize, CPDF_Matrix* pUser2Device,
					  const CFX_ByteString& str, FX_ARGB crTextFill, FX_ARGB crTextStroke, FX_INT32 nHorzScale)
{
	FX_FLOAT x = pt.x, y = pt.y;
	pUser2Device->Transform(x, y);

	if (pFont)
	{
		if (nHorzScale != 100)
		{
			CPDF_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)
			{
				CPDF_Point 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)
			{
				CPDF_Point 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, CPDF_Matrix* pUser2Device, IFX_Edit* pEdit, FX_COLORREF color,
								const CPDF_Rect& rcClip, const CPDF_Point& ptOffset, const CPVT_WordRange* pRange)
{
	pDevice->SaveState();

	if (!rcClip.IsEmpty())
	{
		CPDF_Rect rcTemp = rcClip;
		pUser2Device->TransformRect(rcTemp);
		FX_RECT rcDevClip;
		rcDevClip.left = (FX_INT32)rcTemp.left;
		rcDevClip.right = (FX_INT32)rcTemp.right;
		rcDevClip.top = (FX_INT32)rcTemp.top;
		rcDevClip.bottom = (FX_INT32)rcTemp.bottom;
		pDevice->SetClip_Rect(&rcDevClip);
	}

	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;
					CPDF_Rect 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, CPDF_Matrix* pUser2Device, IFX_Edit* pEdit, FX_COLORREF crTextFill, FX_COLORREF crTextStroke, 
						const CPDF_Rect& rcClip, const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, IFX_SystemHandler* pSystemHandler, void* pFFLData)
{
	
	FX_BOOL bContinuous = pEdit->GetCharArray() == 0;
	if (pEdit->GetCharSpace() > 0.0f)
		bContinuous = FALSE;

	FX_WORD SubWord = pEdit->GetPasswordChar();
	FX_FLOAT fFontSize = pEdit->GetFontSize();
	CPVT_WordRange wrSelect = pEdit->GetSelectWordRange();
	FX_INT32 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;
	FX_INT32 nFontIndex = -1;
	CPDF_Point ptBT(0.0f,0.0f);

	pDevice->SaveState();

	if (!rcClip.IsEmpty())
	{
		CPDF_Rect rcTemp = rcClip;
		pUser2Device->TransformRect(rcTemp);
		FX_RECT rcDevClip;
		rcDevClip.left = (FX_INT32)rcTemp.left;
		rcDevClip.right = (FX_INT32)rcTemp.right;
		rcDevClip.top = (FX_INT32)rcTemp.top;
		rcDevClip.bottom = (FX_INT32)rcTemp.bottom;
		pDevice->SetClip_Rect(&rcDevClip);
	}

	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())
						{
							CPDF_Rect rc(word.ptWord.x,line.ptLine.y + line.fLineDescent,
								word.ptWord.x+word.fWidth,line.ptLine.y + line.fLineAscent);
							rc.Intersect(rcClip);
							//CFX_Edit* pEt = (CFX_Edit*)pEdit;
							//CPDF_Rect rcEdit = pEt->VTToEdit(rc);
							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, CPDF_Point(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,CPDF_Point(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, CPDF_Point(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, CPDF_Matrix* pUser2Device, IFX_Edit* pEdit,  
						const CPDF_Rect& rcClip, const CPDF_Point& ptOffset, const CPVT_WordRange* pRange)
{
	//FX_FLOAT fFontSize = pEdit->GetFontSize();
	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;
	CPDF_Point ptBT(0.0f,0.0f);

	pDevice->SaveState();

	if (!rcClip.IsEmpty())
	{
		CPDF_Rect rcTemp = rcClip;
		pUser2Device->TransformRect(rcTemp);
		FX_RECT rcDevClip;
		rcDevClip.left = (FX_INT32)rcTemp.left;
		rcDevClip.right = (FX_INT32)rcTemp.right;
		rcDevClip.top = (FX_INT32)rcTemp.top;
		rcDevClip.bottom = (FX_INT32)rcTemp.bottom;
		pDevice->SetClip_Rect(&rcDevClip);
	}

	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, CPDF_Point(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;
						CPDF_Rect 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;
						CPDF_Rect 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, CPDF_Point(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 AddLineToPageObjects(CPDF_PageObjects* pPageObjs, FX_COLORREF crStroke, 
								 const CPDF_Point& pt1, const CPDF_Point& pt2)
{
	CPDF_PathObject* pPathObj = new CPDF_PathObject;
	CPDF_PathData* pPathData = pPathObj->m_Path.GetModify();

	pPathData->SetPointCount(2);
	pPathData->SetPoint(0, pt1.x, pt1.y, FXPT_MOVETO);
	pPathData->SetPoint(1, pt2.x, pt2.y, FXPT_LINETO);

	FX_FLOAT rgb[3];
	rgb[0] = FXARGB_R(crStroke) / 255.0f;
	rgb[1] = FXARGB_G(crStroke) / 255.0f;
	rgb[2] = FXARGB_B(crStroke) / 255.0f;
	pPathObj->m_ColorState.SetStrokeColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3);

	CFX_GraphStateData* pData = pPathObj->m_GraphState.GetModify();
	pData->m_LineWidth = 1;

	pPageObjs->InsertObject(pPageObjs->GetLastObjectPosition(),pPathObj);
}

static void AddRectToPageObjects(CPDF_PageObjects* pPageObjs, FX_COLORREF crFill, const CPDF_Rect& rcFill)
{
	CPDF_PathObject* pPathObj = new CPDF_PathObject;
	CPDF_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;

	pPageObjs->InsertObject(pPageObjs->GetLastObjectPosition(),pPathObj);
}

static CPDF_TextObject* AddTextObjToPageObjects(CPDF_PageObjects* pPageObjs, FX_COLORREF crText, 
							 CPDF_Font* pFont, FX_FLOAT fFontSize, FX_FLOAT fCharSpace, FX_INT32 nHorzScale, 
							 const CPDF_Point& point, const CFX_ByteString& text)
{
	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);	

	pPageObjs->InsertObject(pPageObjs->GetLastObjectPosition(),pTxtObj);

	return pTxtObj;
}

/*
List of currently supported standard fonts:
Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique
Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique
Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic
Symbol, ZapfDingbats
*/

const char* g_sFXEDITStandardFontName[] = {"Courier", "Courier-Bold", "Courier-BoldOblique", "Courier-Oblique",
	"Helvetica", "Helvetica-Bold", "Helvetica-BoldOblique", "Helvetica-Oblique",
	"Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic",
	"Symbol", "ZapfDingbats"};

static FX_BOOL FX_EDIT_IsStandardFont(const CFX_ByteString& sFontName)
{
	for (FX_INT32 i=0; i<14; i++)
	{
		if (sFontName == g_sFXEDITStandardFontName[i])
			return TRUE;
	}

	return FALSE;
}

void IFX_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
								   const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, FX_COLORREF crText, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray)
{
	FX_FLOAT fFontSize = pEdit->GetFontSize();

	FX_INT32 nOldFontIndex = -1;

	CFX_ByteTextBuf sTextBuf;
	CPDF_Point 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(pPageObjects, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, 0.0f, 100,
								CPDF_Point(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(pPageObjects, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, 0.0f, 100,
					CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
			}
		}
	}
}

void IFX_Edit::GenerateRichPageObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
								   const CPDF_Point& 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;
	CPDF_Point 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(pPageObjects, crOld, pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize, wp.fCharSpace, wp.nHorzScale,
								CPDF_Point(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)
					{/*
						AddLineToPageObjects(pPageObjects, crCurText, 
							CPDF_Point(word.ptWord.x, word.ptWord.y + word.fDescent * 0.4f),
							CPDF_Point(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent * 0.4f));							
*/
						CPDF_Rect rcUnderline = GetUnderLineRect(word);
						rcUnderline.left += ptOffset.x;
						rcUnderline.right += ptOffset.x;
						rcUnderline.top += ptOffset.y;
						rcUnderline.bottom += ptOffset.y;
						
						AddRectToPageObjects(pPageObjects, crCurText, rcUnderline);							
					}

					if (word.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT)
					{
						CPDF_Rect rcCrossout = GetCrossoutRect(word);
						rcCrossout.left += ptOffset.x;
						rcCrossout.right += ptOffset.x;
						rcCrossout.top += ptOffset.y;
						rcCrossout.bottom += ptOffset.y;

						AddRectToPageObjects(pPageObjects, crCurText, rcCrossout);						
					}

					oldplace = place;					
				}
			}

			if (sTextBuf.GetLength() > 0)
			{				
				ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crOld, pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize, wp.fCharSpace, wp.nHorzScale,
					CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
			}
		}
	}
}

void IFX_Edit::GenerateUnderlineObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
								   const CPDF_Point& 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))
				{
					CPDF_Rect rcUnderline = GetUnderLineRect(word);
					rcUnderline.left += ptOffset.x;
					rcUnderline.right += ptOffset.x;
					rcUnderline.top += ptOffset.y;
					rcUnderline.bottom += ptOffset.y;
					AddRectToPageObjects(pPageObjects, color, rcUnderline);
				}
			}
		}
	}
}

