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