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