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

