Home | History | Annotate | Download | only in fxedit
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../include/fxedit/fxet_stub.h"
      8 #include "../../include/fxedit/fx_edit.h"
      9 #include "../../include/fxedit/fxet_edit.h"
     10 
     11 #define FX_EDIT_UNDERLINEHALFWIDTH				0.5f
     12 #define FX_EDIT_CROSSOUTHALFWIDTH				0.5f
     13 
     14 extern CFX_ByteString GetPDFWordString(IFX_Edit_FontMap * pFontMap, FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord);
     15 
     16 CPDF_Rect GetUnderLineRect(const CPVT_Word& word)
     17 {
     18 	return CPDF_Rect(word.ptWord.x, word.ptWord.y + word.fDescent * 0.5f,
     19 						word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent * 0.25f);
     20 }
     21 
     22 CPDF_Rect GetCrossoutRect(const CPVT_Word& word)
     23 {
     24 	return CPDF_Rect(word.ptWord.x, word.ptWord.y + (word.fAscent + word.fDescent) * 0.5f + word.fDescent * 0.25f,
     25 							word.ptWord.x + word.fWidth, word.ptWord.y + (word.fAscent + word.fDescent) * 0.5f);
     26 }
     27 
     28 static void DrawTextString(CFX_RenderDevice* pDevice, const CPDF_Point& pt, CPDF_Font* pFont, FX_FLOAT fFontSize, CPDF_Matrix* pUser2Device,
     29 					  const CFX_ByteString& str, FX_ARGB crTextFill, FX_ARGB crTextStroke, FX_INT32 nHorzScale)
     30 {
     31 	FX_FLOAT x = pt.x, y = pt.y;
     32 	pUser2Device->Transform(x, y);
     33 
     34 	if (pFont)
     35 	{
     36 		if (nHorzScale != 100)
     37 		{
     38 			CPDF_Matrix mt(nHorzScale/100.0f,0,0,1,0,0);
     39 			mt.Concat(*pUser2Device);
     40 
     41 			CPDF_RenderOptions ro;
     42 			ro.m_Flags = RENDER_CLEARTYPE;
     43 			ro.m_ColorMode = RENDER_COLOR_NORMAL;
     44 
     45 			if (crTextStroke != 0)
     46 			{
     47 				CPDF_Point pt1(0,0), pt2(1,0);
     48 				pUser2Device->Transform(pt1.x, pt1.y);
     49 				pUser2Device->Transform(pt2.x, pt2.y);
     50 				CFX_GraphStateData gsd;
     51 				gsd.m_LineWidth = (FX_FLOAT)FXSYS_fabs((pt2.x + pt2.y) - (pt1.x + pt1.y));
     52 
     53 				CPDF_TextRenderer::DrawTextString(pDevice,x, y, pFont, fFontSize, &mt, str, crTextFill, crTextStroke, &gsd, &ro);
     54 			}
     55 			else
     56 				CPDF_TextRenderer::DrawTextString(pDevice,x, y, pFont, fFontSize, &mt, str, crTextFill, 0, NULL, &ro);
     57 		}
     58 		else
     59 		{
     60 			CPDF_RenderOptions ro;
     61 			ro.m_Flags = RENDER_CLEARTYPE;
     62 			ro.m_ColorMode = RENDER_COLOR_NORMAL;
     63 
     64 			if (crTextStroke != 0)
     65 			{
     66 				CPDF_Point pt1(0,0), pt2(1,0);
     67 				pUser2Device->Transform(pt1.x, pt1.y);
     68 				pUser2Device->Transform(pt2.x, pt2.y);
     69 				CFX_GraphStateData gsd;
     70 				gsd.m_LineWidth = (FX_FLOAT)FXSYS_fabs((pt2.x + pt2.y) - (pt1.x + pt1.y));
     71 
     72 				CPDF_TextRenderer::DrawTextString(pDevice,x, y, pFont, fFontSize, pUser2Device, str, crTextFill, crTextStroke, &gsd, &ro);
     73 			}
     74 			else
     75 				CPDF_TextRenderer::DrawTextString(pDevice,x, y, pFont, fFontSize, pUser2Device, str, crTextFill, 0, NULL, &ro);
     76 		}
     77 	}
     78 }
     79 
     80 void IFX_Edit::DrawUnderline(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device, IFX_Edit* pEdit, FX_COLORREF color,
     81 								const CPDF_Rect& rcClip, const CPDF_Point& ptOffset, const CPVT_WordRange* pRange)
     82 {
     83 	pDevice->SaveState();
     84 
     85 	if (!rcClip.IsEmpty())
     86 	{
     87 		CPDF_Rect rcTemp = rcClip;
     88 		pUser2Device->TransformRect(rcTemp);
     89 		FX_RECT rcDevClip;
     90 		rcDevClip.left = (FX_INT32)rcTemp.left;
     91 		rcDevClip.right = (FX_INT32)rcTemp.right;
     92 		rcDevClip.top = (FX_INT32)rcTemp.top;
     93 		rcDevClip.bottom = (FX_INT32)rcTemp.bottom;
     94 		pDevice->SetClip_Rect(&rcDevClip);
     95 	}
     96 
     97 	if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
     98 	{
     99 		if (pEdit->GetFontMap())
    100 		{
    101 			if (pRange)
    102 				pIterator->SetAt(pRange->BeginPos);
    103 			else
    104 				pIterator->SetAt(0);
    105 
    106 			while (pIterator->NextWord())
    107 			{
    108 				CPVT_WordPlace place = pIterator->GetAt();
    109 				if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
    110 
    111 				CPVT_Word word;
    112 				if (pIterator->GetWord(word))
    113 				{
    114 					CFX_PathData pathUnderline;
    115 					CPDF_Rect rcUnderline = GetUnderLineRect(word);
    116 					rcUnderline.left += ptOffset.x;
    117 					rcUnderline.right += ptOffset.x;
    118 					rcUnderline.top += ptOffset.y;
    119 					rcUnderline.bottom += ptOffset.y;
    120 					pathUnderline.AppendRect(rcUnderline.left, rcUnderline.bottom, rcUnderline.right, rcUnderline.top);
    121 
    122 					pDevice->DrawPath(&pathUnderline, pUser2Device, NULL, color, 0, FXFILL_WINDING);
    123 				}
    124 			}
    125 		}
    126 	}
    127 
    128 	pDevice->RestoreState();
    129 }
    130 
    131 void IFX_Edit::DrawEdit(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device, IFX_Edit* pEdit, FX_COLORREF crTextFill, FX_COLORREF crTextStroke,
    132 						const CPDF_Rect& rcClip, const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, IFX_SystemHandler* pSystemHandler, void* pFFLData)
    133 {
    134 
    135 	FX_BOOL bContinuous = pEdit->GetCharArray() == 0;
    136 	if (pEdit->GetCharSpace() > 0.0f)
    137 		bContinuous = FALSE;
    138 
    139 	FX_WORD SubWord = pEdit->GetPasswordChar();
    140 	FX_FLOAT fFontSize = pEdit->GetFontSize();
    141 	CPVT_WordRange wrSelect = pEdit->GetSelectWordRange();
    142 	FX_INT32 nHorzScale = pEdit->GetHorzScale();
    143 
    144 	FX_COLORREF crCurFill = crTextFill;
    145 	FX_COLORREF crOldFill = crCurFill;
    146 
    147 	FX_BOOL bSelect = FALSE;
    148 	const FX_COLORREF crWhite = ArgbEncode(255,255,255,255);
    149 	const FX_COLORREF crSelBK = ArgbEncode(255,0,51,113);
    150 
    151 	CFX_ByteTextBuf sTextBuf;
    152 	FX_INT32 nFontIndex = -1;
    153 	CPDF_Point ptBT(0.0f,0.0f);
    154 
    155 	pDevice->SaveState();
    156 
    157 	if (!rcClip.IsEmpty())
    158 	{
    159 		CPDF_Rect rcTemp = rcClip;
    160 		pUser2Device->TransformRect(rcTemp);
    161 		FX_RECT rcDevClip;
    162 		rcDevClip.left = (FX_INT32)rcTemp.left;
    163 		rcDevClip.right = (FX_INT32)rcTemp.right;
    164 		rcDevClip.top = (FX_INT32)rcTemp.top;
    165 		rcDevClip.bottom = (FX_INT32)rcTemp.bottom;
    166 		pDevice->SetClip_Rect(&rcDevClip);
    167 	}
    168 
    169 	if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
    170 	{
    171 		if (IFX_Edit_FontMap* pFontMap = pEdit->GetFontMap())
    172 		{
    173 			if (pRange)
    174 				pIterator->SetAt(pRange->BeginPos);
    175 			else
    176 				pIterator->SetAt(0);
    177 
    178 			CPVT_WordPlace oldplace;
    179 
    180 			while (pIterator->NextWord())
    181 			{
    182 				CPVT_WordPlace place = pIterator->GetAt();
    183 				if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
    184 
    185 				if (wrSelect.IsExist())
    186 				{
    187 					bSelect = place.WordCmp(wrSelect.BeginPos) > 0 && place.WordCmp(wrSelect.EndPos) <= 0;
    188 					if (bSelect)
    189 					{
    190 						crCurFill = crWhite;
    191 					}
    192 					else
    193 					{
    194 						crCurFill = crTextFill;
    195 					}
    196 				}
    197 				if(pSystemHandler && pSystemHandler->IsSelectionImplemented())
    198 				{
    199 					crCurFill = crTextFill;
    200  					crOldFill = crCurFill;
    201 				}
    202 				CPVT_Word word;
    203 				if (pIterator->GetWord(word))
    204 				{
    205 
    206 					if (bSelect)
    207 					{
    208 
    209 						CPVT_Line line;
    210 						pIterator->GetLine(line);
    211 
    212 						if(pSystemHandler && pSystemHandler->IsSelectionImplemented())
    213 						{
    214 							CPDF_Rect rc(word.ptWord.x,line.ptLine.y + line.fLineDescent,
    215 								word.ptWord.x+word.fWidth,line.ptLine.y + line.fLineAscent);
    216 							rc.Intersect(rcClip);
    217 							//CFX_Edit* pEt = (CFX_Edit*)pEdit;
    218 							//CPDF_Rect rcEdit = pEt->VTToEdit(rc);
    219 							pSystemHandler->OutputSelectedRect(pFFLData,rc);
    220 						}
    221 						else
    222 						{
    223  							CFX_PathData pathSelBK;
    224  							pathSelBK.AppendRect(word.ptWord.x,line.ptLine.y + line.fLineDescent,
    225  								word.ptWord.x+word.fWidth,line.ptLine.y + line.fLineAscent);
    226 
    227  							pDevice->DrawPath(&pathSelBK, pUser2Device, NULL, crSelBK, 0, FXFILL_WINDING);
    228 						}
    229 					}
    230 
    231 					if (bContinuous)
    232 					{
    233 						if (place.LineCmp(oldplace) != 0 || word.nFontIndex != nFontIndex ||
    234 							crOldFill != crCurFill)
    235 						{
    236 							if (sTextBuf.GetLength() > 0)
    237 							{
    238 								DrawTextString(pDevice, CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), pFontMap->GetPDFFont(nFontIndex),
    239 									fFontSize, pUser2Device, sTextBuf.GetByteString(), crOldFill, crTextStroke, nHorzScale);
    240 
    241 								sTextBuf.Clear();
    242 							}
    243 							nFontIndex = word.nFontIndex;
    244 							ptBT = word.ptWord;
    245 							crOldFill = crCurFill;
    246 						}
    247 
    248 						sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, SubWord);
    249 					}
    250 					else
    251 					{
    252 						DrawTextString(pDevice,CPDF_Point(word.ptWord.x+ptOffset.x, word.ptWord.y+ptOffset.y), pFontMap->GetPDFFont(word.nFontIndex),
    253 							fFontSize, pUser2Device, GetPDFWordString(pFontMap, word.nFontIndex, word.Word, SubWord), crCurFill, crTextStroke, nHorzScale);
    254 
    255 					}
    256 					oldplace = place;
    257 
    258 
    259 				}
    260 			}
    261 
    262 			if (sTextBuf.GetLength() > 0)
    263 			{
    264 				DrawTextString(pDevice, CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), pFontMap->GetPDFFont(nFontIndex),
    265 					fFontSize, pUser2Device, sTextBuf.GetByteString(), crOldFill, crTextStroke, nHorzScale);
    266 			}
    267 		}
    268 	}
    269 
    270 	pDevice->RestoreState();
    271 }
    272 
    273 void IFX_Edit::DrawRichEdit(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device, IFX_Edit* pEdit,
    274 						const CPDF_Rect& rcClip, const CPDF_Point& ptOffset, const CPVT_WordRange* pRange)
    275 {
    276 	//FX_FLOAT fFontSize = pEdit->GetFontSize();
    277 	CPVT_WordRange wrSelect = pEdit->GetSelectWordRange();
    278 
    279 	FX_COLORREF crCurText = ArgbEncode(255, 0,0,0);
    280 	FX_COLORREF crOld = crCurText;
    281 	FX_BOOL bSelect = FALSE;
    282 	const FX_COLORREF crWhite = ArgbEncode(255,255,255,255);
    283 	const FX_COLORREF crSelBK = ArgbEncode(255,0,51,113);
    284 
    285 	CFX_ByteTextBuf sTextBuf;
    286 	CPVT_WordProps wp;
    287 	CPDF_Point ptBT(0.0f,0.0f);
    288 
    289 	pDevice->SaveState();
    290 
    291 	if (!rcClip.IsEmpty())
    292 	{
    293 		CPDF_Rect rcTemp = rcClip;
    294 		pUser2Device->TransformRect(rcTemp);
    295 		FX_RECT rcDevClip;
    296 		rcDevClip.left = (FX_INT32)rcTemp.left;
    297 		rcDevClip.right = (FX_INT32)rcTemp.right;
    298 		rcDevClip.top = (FX_INT32)rcTemp.top;
    299 		rcDevClip.bottom = (FX_INT32)rcTemp.bottom;
    300 		pDevice->SetClip_Rect(&rcDevClip);
    301 	}
    302 
    303 	if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
    304 	{
    305 		if (IFX_Edit_FontMap* pFontMap = pEdit->GetFontMap())
    306 		{
    307 			if (pRange)
    308 				pIterator->SetAt(pRange->BeginPos);
    309 			else
    310 				pIterator->SetAt(0);
    311 
    312 			CPVT_WordPlace oldplace;
    313 
    314 			while (pIterator->NextWord())
    315 			{
    316 				CPVT_WordPlace place = pIterator->GetAt();
    317 				if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
    318 
    319 				CPVT_Word word;
    320 				if (pIterator->GetWord(word))
    321 				{
    322 					word.WordProps.fFontSize = word.fFontSize;
    323 
    324 					crCurText = ArgbEncode(255,word.WordProps.dwWordColor);
    325 
    326 					if (wrSelect.IsExist())
    327 					{
    328 						bSelect = place.WordCmp(wrSelect.BeginPos) > 0 && place.WordCmp(wrSelect.EndPos) <= 0;
    329 						if (bSelect)
    330 						{
    331 							crCurText = crWhite;
    332 						}
    333 					}
    334 
    335 					if (bSelect)
    336 					{
    337 						CPVT_Line line;
    338 						pIterator->GetLine(line);
    339 
    340 						CFX_PathData pathSelBK;
    341 						pathSelBK.AppendRect(word.ptWord.x		+ ptOffset.x,
    342 							line.ptLine.y + line.fLineDescent	+ ptOffset.y,
    343 							word.ptWord.x+word.fWidth			+ ptOffset.x,
    344 							line.ptLine.y + line.fLineAscent	+ ptOffset.y);
    345 
    346 						pDevice->DrawPath(&pathSelBK, pUser2Device, NULL, crSelBK, 0, FXFILL_WINDING);
    347 					}
    348 
    349 					if (place.LineCmp(oldplace) != 0 || word.WordProps.fCharSpace > 0.0f || word.WordProps.nHorzScale != 100 ||
    350 						FXSYS_memcmp(&word.WordProps, &wp, sizeof(CPVT_WordProps)) != 0 ||
    351 						crOld != crCurText)
    352 					{
    353 						if (sTextBuf.GetLength() > 0)
    354 						{
    355 							DrawTextString(pDevice, CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), pFontMap->GetPDFFont(wp.nFontIndex),
    356 								wp.fFontSize, pUser2Device, sTextBuf.GetByteString(), crOld, 0, wp.nHorzScale);
    357 
    358 							sTextBuf.Clear();
    359 						}
    360 						wp = word.WordProps;
    361 						ptBT = word.ptWord;
    362 						crOld = crCurText;
    363 					}
    364 
    365 					sTextBuf << GetPDFWordString(pFontMap, word.WordProps.nFontIndex, word.Word, 0);
    366 
    367 					if (word.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE)
    368 					{
    369 						CFX_PathData pathUnderline;
    370 						CPDF_Rect rcUnderline = GetUnderLineRect(word);
    371 						pathUnderline.AppendRect(rcUnderline.left, rcUnderline.bottom, rcUnderline.right, rcUnderline.top);
    372 
    373 						pDevice->DrawPath(&pathUnderline, pUser2Device, NULL, crCurText, 0, FXFILL_WINDING);
    374 					}
    375 
    376 					if (word.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT)
    377 					{
    378 						CFX_PathData pathCrossout;
    379 						CPDF_Rect rcCrossout = GetCrossoutRect(word);
    380 						pathCrossout.AppendRect(rcCrossout.left, rcCrossout.bottom, rcCrossout.right, rcCrossout.top);
    381 
    382 						pDevice->DrawPath(&pathCrossout, pUser2Device, NULL, crCurText, 0, FXFILL_WINDING);
    383 					}
    384 
    385 					oldplace = place;
    386 				}
    387 			}
    388 
    389 			if (sTextBuf.GetLength() > 0)
    390 			{
    391 				DrawTextString(pDevice, CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), pFontMap->GetPDFFont(wp.nFontIndex),
    392 					wp.fFontSize, pUser2Device, sTextBuf.GetByteString(), crOld, 0, wp.nHorzScale);
    393 			}
    394 		}
    395 	}
    396 
    397 	pDevice->RestoreState();
    398 }
    399 
    400 static void AddLineToPageObjects(CPDF_PageObjects* pPageObjs, FX_COLORREF crStroke,
    401 								 const CPDF_Point& pt1, const CPDF_Point& pt2)
    402 {
    403 	CPDF_PathObject* pPathObj = new CPDF_PathObject;
    404 	CPDF_PathData* pPathData = pPathObj->m_Path.GetModify();
    405 
    406 	pPathData->SetPointCount(2);
    407 	pPathData->SetPoint(0, pt1.x, pt1.y, FXPT_MOVETO);
    408 	pPathData->SetPoint(1, pt2.x, pt2.y, FXPT_LINETO);
    409 
    410 	FX_FLOAT rgb[3];
    411 	rgb[0] = FXARGB_R(crStroke) / 255.0f;
    412 	rgb[1] = FXARGB_G(crStroke) / 255.0f;
    413 	rgb[2] = FXARGB_B(crStroke) / 255.0f;
    414 	pPathObj->m_ColorState.SetStrokeColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3);
    415 
    416 	CFX_GraphStateData* pData = pPathObj->m_GraphState.GetModify();
    417 	pData->m_LineWidth = 1;
    418 
    419 	pPageObjs->InsertObject(pPageObjs->GetLastObjectPosition(),pPathObj);
    420 }
    421 
    422 static void AddRectToPageObjects(CPDF_PageObjects* pPageObjs, FX_COLORREF crFill, const CPDF_Rect& rcFill)
    423 {
    424 	CPDF_PathObject* pPathObj = new CPDF_PathObject;
    425 	CPDF_PathData* pPathData = pPathObj->m_Path.GetModify();
    426 	pPathData->AppendRect(rcFill.left,rcFill.bottom,rcFill.right,rcFill.top);
    427 
    428 	FX_FLOAT rgb[3];
    429 	rgb[0] = FXARGB_R(crFill) / 255.0f ;
    430 	rgb[1] = FXARGB_G(crFill) / 255.0f;
    431 	rgb[2] = FXARGB_B(crFill) / 255.0f;
    432 	pPathObj->m_ColorState.SetFillColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3);
    433 
    434 	pPathObj->m_FillType = FXFILL_ALTERNATE;
    435 	pPathObj->m_bStroke = FALSE;
    436 
    437 	pPageObjs->InsertObject(pPageObjs->GetLastObjectPosition(),pPathObj);
    438 }
    439 
    440 static CPDF_TextObject* AddTextObjToPageObjects(CPDF_PageObjects* pPageObjs, FX_COLORREF crText,
    441 							 CPDF_Font* pFont, FX_FLOAT fFontSize, FX_FLOAT fCharSpace, FX_INT32 nHorzScale,
    442 							 const CPDF_Point& point, const CFX_ByteString& text)
    443 {
    444 	CPDF_TextObject* pTxtObj = new CPDF_TextObject;
    445 
    446 	CPDF_TextStateData* pTextStateData = pTxtObj->m_TextState.GetModify();
    447 	pTextStateData->m_pFont = pFont;
    448 	pTextStateData->m_FontSize = fFontSize;
    449 	pTextStateData->m_CharSpace = fCharSpace;
    450 	pTextStateData->m_WordSpace = 0;
    451 	pTextStateData->m_TextMode  = 0;
    452 	pTextStateData->m_Matrix[0] = nHorzScale / 100.0f;
    453 	pTextStateData->m_Matrix[1] = 0;
    454 	pTextStateData->m_Matrix[2] = 0;
    455 	pTextStateData->m_Matrix[3] = 1;
    456 
    457 	FX_FLOAT rgb[3];
    458 	rgb[0] = FXARGB_R(crText) / 255.0f ;
    459 	rgb[1] = FXARGB_G(crText) / 255.0f;
    460 	rgb[2] = FXARGB_B(crText) / 255.0f;
    461 	pTxtObj->m_ColorState.SetFillColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB),rgb, 3);
    462 	pTxtObj->m_ColorState.SetStrokeColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB),rgb, 3);
    463 
    464 	pTxtObj->SetPosition(point.x,point.y);
    465 	pTxtObj->SetText(text);
    466 
    467 	pPageObjs->InsertObject(pPageObjs->GetLastObjectPosition(),pTxtObj);
    468 
    469 	return pTxtObj;
    470 }
    471 
    472 /*
    473 List of currently supported standard fonts:
    474 Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique
    475 Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique
    476 Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic
    477 Symbol, ZapfDingbats
    478 */
    479 
    480 const char* g_sFXEDITStandardFontName[] = {"Courier", "Courier-Bold", "Courier-BoldOblique", "Courier-Oblique",
    481 	"Helvetica", "Helvetica-Bold", "Helvetica-BoldOblique", "Helvetica-Oblique",
    482 	"Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic",
    483 	"Symbol", "ZapfDingbats"};
    484 
    485 static FX_BOOL FX_EDIT_IsStandardFont(const CFX_ByteString& sFontName)
    486 {
    487 	for (FX_INT32 i=0; i<14; i++)
    488 	{
    489 		if (sFontName == g_sFXEDITStandardFontName[i])
    490 			return TRUE;
    491 	}
    492 
    493 	return FALSE;
    494 }
    495 
    496 void IFX_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
    497 								   const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, FX_COLORREF crText, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray)
    498 {
    499 	FX_FLOAT fFontSize = pEdit->GetFontSize();
    500 
    501 	FX_INT32 nOldFontIndex = -1;
    502 
    503 	CFX_ByteTextBuf sTextBuf;
    504 	CPDF_Point ptBT(0.0f,0.0f);
    505 
    506 	ObjArray.RemoveAll();
    507 
    508 	if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
    509 	{
    510 		if (IFX_Edit_FontMap* pFontMap = pEdit->GetFontMap())
    511 		{
    512 			if (pRange)
    513 				pIterator->SetAt(pRange->BeginPos);
    514 			else
    515 				pIterator->SetAt(0);
    516 
    517 			CPVT_WordPlace oldplace;
    518 
    519 			while (pIterator->NextWord())
    520 			{
    521 				CPVT_WordPlace place = pIterator->GetAt();
    522 				if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
    523 
    524 				CPVT_Word word;
    525 				if (pIterator->GetWord(word))
    526 				{
    527 					if (place.LineCmp(oldplace) != 0 || nOldFontIndex != word.nFontIndex)
    528 					{
    529 						if (sTextBuf.GetLength() > 0)
    530 						{
    531 							ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, 0.0f, 100,
    532 								CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
    533 
    534 							sTextBuf.Clear();
    535 						}
    536 
    537 						ptBT = word.ptWord;
    538 						nOldFontIndex = word.nFontIndex;
    539 					}
    540 
    541 					sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, 0);
    542 					oldplace = place;
    543 				}
    544 			}
    545 
    546 			if (sTextBuf.GetLength() > 0)
    547 			{
    548 				ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, 0.0f, 100,
    549 					CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
    550 			}
    551 		}
    552 	}
    553 }
    554 
    555 void IFX_Edit::GenerateRichPageObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
    556 								   const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray)
    557 {
    558 
    559 
    560 	FX_COLORREF crCurText = ArgbEncode(255, 0, 0, 0);
    561 	FX_COLORREF crOld = crCurText;
    562 
    563 
    564 	CFX_ByteTextBuf sTextBuf;
    565 	CPVT_WordProps wp;
    566 	CPDF_Point ptBT(0.0f,0.0f);
    567 
    568 	ObjArray.RemoveAll();
    569 
    570 	if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
    571 	{
    572 		if (IFX_Edit_FontMap* pFontMap = pEdit->GetFontMap())
    573 		{
    574 			if (pRange)
    575 				pIterator->SetAt(pRange->BeginPos);
    576 			else
    577 				pIterator->SetAt(0);
    578 
    579 			CPVT_WordPlace oldplace;
    580 
    581 			while (pIterator->NextWord())
    582 			{
    583 				CPVT_WordPlace place = pIterator->GetAt();
    584 				if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
    585 
    586 				CPVT_Word word;
    587 				if (pIterator->GetWord(word))
    588 				{
    589 					word.WordProps.fFontSize = word.fFontSize;
    590 
    591 					crCurText = ArgbEncode(255,word.WordProps.dwWordColor);
    592 
    593 					if (place.LineCmp(oldplace) != 0 || word.WordProps.fCharSpace > 0.0f || word.WordProps.nHorzScale != 100 ||
    594 						FXSYS_memcmp(&word.WordProps, &wp, sizeof(CPVT_WordProps)) != 0 ||
    595 						crOld != crCurText)
    596 					{
    597 						if (sTextBuf.GetLength() > 0)
    598 						{
    599 							ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crOld, pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize, wp.fCharSpace, wp.nHorzScale,
    600 								CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
    601 
    602 							sTextBuf.Clear();
    603 						}
    604 
    605 						wp = word.WordProps;
    606 						ptBT = word.ptWord;
    607 						crOld = crCurText;
    608 
    609 					}
    610 
    611 					sTextBuf << GetPDFWordString(pFontMap, word.WordProps.nFontIndex, word.Word, 0);
    612 
    613 					if (word.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE)
    614 					{/*
    615 						AddLineToPageObjects(pPageObjects, crCurText,
    616 							CPDF_Point(word.ptWord.x, word.ptWord.y + word.fDescent * 0.4f),
    617 							CPDF_Point(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent * 0.4f));
    618 */
    619 						CPDF_Rect rcUnderline = GetUnderLineRect(word);
    620 						rcUnderline.left += ptOffset.x;
    621 						rcUnderline.right += ptOffset.x;
    622 						rcUnderline.top += ptOffset.y;
    623 						rcUnderline.bottom += ptOffset.y;
    624 
    625 						AddRectToPageObjects(pPageObjects, crCurText, rcUnderline);
    626 					}
    627 
    628 					if (word.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT)
    629 					{
    630 						CPDF_Rect rcCrossout = GetCrossoutRect(word);
    631 						rcCrossout.left += ptOffset.x;
    632 						rcCrossout.right += ptOffset.x;
    633 						rcCrossout.top += ptOffset.y;
    634 						rcCrossout.bottom += ptOffset.y;
    635 
    636 						AddRectToPageObjects(pPageObjects, crCurText, rcCrossout);
    637 					}
    638 
    639 					oldplace = place;
    640 				}
    641 			}
    642 
    643 			if (sTextBuf.GetLength() > 0)
    644 			{
    645 				ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crOld, pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize, wp.fCharSpace, wp.nHorzScale,
    646 					CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
    647 			}
    648 		}
    649 	}
    650 }
    651 
    652 void IFX_Edit::GenerateUnderlineObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
    653 								   const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, FX_COLORREF color)
    654 {
    655 
    656 
    657 	if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
    658 	{
    659 		if (pEdit->GetFontMap())
    660 		{
    661 			if (pRange)
    662 				pIterator->SetAt(pRange->BeginPos);
    663 			else
    664 				pIterator->SetAt(0);
    665 
    666 			CPVT_WordPlace oldplace;
    667 
    668 			while (pIterator->NextWord())
    669 			{
    670 				CPVT_WordPlace place = pIterator->GetAt();
    671 				if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
    672 
    673 				CPVT_Word word;
    674 				if (pIterator->GetWord(word))
    675 				{
    676 					CPDF_Rect rcUnderline = GetUnderLineRect(word);
    677 					rcUnderline.left += ptOffset.x;
    678 					rcUnderline.right += ptOffset.x;
    679 					rcUnderline.top += ptOffset.y;
    680 					rcUnderline.bottom += ptOffset.y;
    681 					AddRectToPageObjects(pPageObjects, color, rcUnderline);
    682 				}
    683 			}
    684 		}
    685 	}
    686 }
    687 
    688