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 14extern CFX_ByteString GetPDFWordString(IFX_Edit_FontMap * pFontMap, FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord); 15 16CPDF_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 22CPDF_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 28static 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 80void 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 131void 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 273void 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 400static void AddRectToPageObjects(CPDF_PageObjects* pPageObjs, FX_COLORREF crFill, const CPDF_Rect& rcFill) 401{ 402 CPDF_PathObject* pPathObj = new CPDF_PathObject; 403 CPDF_PathData* pPathData = pPathObj->m_Path.GetModify(); 404 pPathData->AppendRect(rcFill.left,rcFill.bottom,rcFill.right,rcFill.top); 405 406 FX_FLOAT rgb[3]; 407 rgb[0] = FXARGB_R(crFill) / 255.0f ; 408 rgb[1] = FXARGB_G(crFill) / 255.0f; 409 rgb[2] = FXARGB_B(crFill) / 255.0f; 410 pPathObj->m_ColorState.SetFillColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); 411 412 pPathObj->m_FillType = FXFILL_ALTERNATE; 413 pPathObj->m_bStroke = FALSE; 414 415 pPageObjs->InsertObject(pPageObjs->GetLastObjectPosition(),pPathObj); 416} 417 418static CPDF_TextObject* AddTextObjToPageObjects(CPDF_PageObjects* pPageObjs, FX_COLORREF crText, 419 CPDF_Font* pFont, FX_FLOAT fFontSize, FX_FLOAT fCharSpace, FX_INT32 nHorzScale, 420 const CPDF_Point& point, const CFX_ByteString& text) 421{ 422 CPDF_TextObject* pTxtObj = new CPDF_TextObject; 423 424 CPDF_TextStateData* pTextStateData = pTxtObj->m_TextState.GetModify(); 425 pTextStateData->m_pFont = pFont; 426 pTextStateData->m_FontSize = fFontSize; 427 pTextStateData->m_CharSpace = fCharSpace; 428 pTextStateData->m_WordSpace = 0; 429 pTextStateData->m_TextMode = 0; 430 pTextStateData->m_Matrix[0] = nHorzScale / 100.0f; 431 pTextStateData->m_Matrix[1] = 0; 432 pTextStateData->m_Matrix[2] = 0; 433 pTextStateData->m_Matrix[3] = 1; 434 435 FX_FLOAT rgb[3]; 436 rgb[0] = FXARGB_R(crText) / 255.0f ; 437 rgb[1] = FXARGB_G(crText) / 255.0f; 438 rgb[2] = FXARGB_B(crText) / 255.0f; 439 pTxtObj->m_ColorState.SetFillColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB),rgb, 3); 440 pTxtObj->m_ColorState.SetStrokeColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB),rgb, 3); 441 442 pTxtObj->SetPosition(point.x,point.y); 443 pTxtObj->SetText(text); 444 445 pPageObjs->InsertObject(pPageObjs->GetLastObjectPosition(),pTxtObj); 446 447 return pTxtObj; 448} 449 450void IFX_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit, 451 const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, FX_COLORREF crText, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray) 452{ 453 FX_FLOAT fFontSize = pEdit->GetFontSize(); 454 455 FX_INT32 nOldFontIndex = -1; 456 457 CFX_ByteTextBuf sTextBuf; 458 CPDF_Point ptBT(0.0f,0.0f); 459 460 ObjArray.RemoveAll(); 461 462 if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) 463 { 464 if (IFX_Edit_FontMap* pFontMap = pEdit->GetFontMap()) 465 { 466 if (pRange) 467 pIterator->SetAt(pRange->BeginPos); 468 else 469 pIterator->SetAt(0); 470 471 CPVT_WordPlace oldplace; 472 473 while (pIterator->NextWord()) 474 { 475 CPVT_WordPlace place = pIterator->GetAt(); 476 if (pRange && place.WordCmp(pRange->EndPos) > 0) break; 477 478 CPVT_Word word; 479 if (pIterator->GetWord(word)) 480 { 481 if (place.LineCmp(oldplace) != 0 || nOldFontIndex != word.nFontIndex) 482 { 483 if (sTextBuf.GetLength() > 0) 484 { 485 ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, 0.0f, 100, 486 CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString())); 487 488 sTextBuf.Clear(); 489 } 490 491 ptBT = word.ptWord; 492 nOldFontIndex = word.nFontIndex; 493 } 494 495 sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, 0); 496 oldplace = place; 497 } 498 } 499 500 if (sTextBuf.GetLength() > 0) 501 { 502 ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, 0.0f, 100, 503 CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString())); 504 } 505 } 506 } 507} 508 509void IFX_Edit::GenerateRichPageObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit, 510 const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray) 511{ 512 513 514 FX_COLORREF crCurText = ArgbEncode(255, 0, 0, 0); 515 FX_COLORREF crOld = crCurText; 516 517 518 CFX_ByteTextBuf sTextBuf; 519 CPVT_WordProps wp; 520 CPDF_Point ptBT(0.0f,0.0f); 521 522 ObjArray.RemoveAll(); 523 524 if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) 525 { 526 if (IFX_Edit_FontMap* pFontMap = pEdit->GetFontMap()) 527 { 528 if (pRange) 529 pIterator->SetAt(pRange->BeginPos); 530 else 531 pIterator->SetAt(0); 532 533 CPVT_WordPlace oldplace; 534 535 while (pIterator->NextWord()) 536 { 537 CPVT_WordPlace place = pIterator->GetAt(); 538 if (pRange && place.WordCmp(pRange->EndPos) > 0) break; 539 540 CPVT_Word word; 541 if (pIterator->GetWord(word)) 542 { 543 word.WordProps.fFontSize = word.fFontSize; 544 545 crCurText = ArgbEncode(255,word.WordProps.dwWordColor); 546 547 if (place.LineCmp(oldplace) != 0 || word.WordProps.fCharSpace > 0.0f || word.WordProps.nHorzScale != 100 || 548 FXSYS_memcmp(&word.WordProps, &wp, sizeof(CPVT_WordProps)) != 0 || 549 crOld != crCurText) 550 { 551 if (sTextBuf.GetLength() > 0) 552 { 553 ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crOld, pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize, wp.fCharSpace, wp.nHorzScale, 554 CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString())); 555 556 sTextBuf.Clear(); 557 } 558 559 wp = word.WordProps; 560 ptBT = word.ptWord; 561 crOld = crCurText; 562 563 } 564 565 sTextBuf << GetPDFWordString(pFontMap, word.WordProps.nFontIndex, word.Word, 0); 566 567 if (word.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) 568 {/* 569 AddLineToPageObjects(pPageObjects, crCurText, 570 CPDF_Point(word.ptWord.x, word.ptWord.y + word.fDescent * 0.4f), 571 CPDF_Point(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent * 0.4f)); 572*/ 573 CPDF_Rect rcUnderline = GetUnderLineRect(word); 574 rcUnderline.left += ptOffset.x; 575 rcUnderline.right += ptOffset.x; 576 rcUnderline.top += ptOffset.y; 577 rcUnderline.bottom += ptOffset.y; 578 579 AddRectToPageObjects(pPageObjects, crCurText, rcUnderline); 580 } 581 582 if (word.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) 583 { 584 CPDF_Rect rcCrossout = GetCrossoutRect(word); 585 rcCrossout.left += ptOffset.x; 586 rcCrossout.right += ptOffset.x; 587 rcCrossout.top += ptOffset.y; 588 rcCrossout.bottom += ptOffset.y; 589 590 AddRectToPageObjects(pPageObjects, crCurText, rcCrossout); 591 } 592 593 oldplace = place; 594 } 595 } 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 } 603 } 604} 605 606void IFX_Edit::GenerateUnderlineObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit, 607 const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, FX_COLORREF color) 608{ 609 610 611 if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) 612 { 613 if (pEdit->GetFontMap()) 614 { 615 if (pRange) 616 pIterator->SetAt(pRange->BeginPos); 617 else 618 pIterator->SetAt(0); 619 620 CPVT_WordPlace oldplace; 621 622 while (pIterator->NextWord()) 623 { 624 CPVT_WordPlace place = pIterator->GetAt(); 625 if (pRange && place.WordCmp(pRange->EndPos) > 0) break; 626 627 CPVT_Word word; 628 if (pIterator->GetWord(word)) 629 { 630 CPDF_Rect rcUnderline = GetUnderLineRect(word); 631 rcUnderline.left += ptOffset.x; 632 rcUnderline.right += ptOffset.x; 633 rcUnderline.top += ptOffset.y; 634 rcUnderline.bottom += ptOffset.y; 635 AddRectToPageObjects(pPageObjects, color, rcUnderline); 636 } 637 } 638 } 639 } 640} 641 642