| 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 void DrawTextString(CFX_RenderDevice* pDevice, | |
| 23 const CFX_FloatPoint& pt, | |
| 24 CPDF_Font* pFont, | |
| 25 FX_FLOAT fFontSize, | |
| 26 CFX_Matrix* pUser2Device, | |
| 27 const CFX_ByteString& str, | |
| 28 FX_ARGB crTextFill, | |
| 29 FX_ARGB crTextStroke, | |
| 30 int32_t nHorzScale) { | |
| 31 FX_FLOAT x = pt.x, y = pt.y; | |
| 32 pUser2Device->Transform(x, y); | |
| 33 | |
| 34 if (pFont) { | |
| 35 if (nHorzScale != 100) { | |
| 36 CFX_Matrix mt(nHorzScale / 100.0f, 0, 0, 1, 0, 0); | |
| 37 mt.Concat(*pUser2Device); | |
| 38 | |
| 39 CPDF_RenderOptions ro; | |
| 40 ro.m_Flags = RENDER_CLEARTYPE; | |
| 41 ro.m_ColorMode = RENDER_COLOR_NORMAL; | |
| 42 | |
| 43 if (crTextStroke != 0) { | |
| 44 CFX_FloatPoint pt1(0, 0), pt2(1, 0); | |
| 45 pUser2Device->Transform(pt1.x, pt1.y); | |
| 46 pUser2Device->Transform(pt2.x, pt2.y); | |
| 47 CFX_GraphStateData gsd; | |
| 48 gsd.m_LineWidth = | |
| 49 (FX_FLOAT)FXSYS_fabs((pt2.x + pt2.y) - (pt1.x + pt1.y)); | |
| 50 | |
| 51 CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize, &mt, | |
| 52 str, crTextFill, crTextStroke, &gsd, | |
| 53 &ro); | |
| 54 } else { | |
| 55 CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize, &mt, | |
| 56 str, crTextFill, 0, nullptr, &ro); | |
| 57 } | |
| 58 } else { | |
| 59 CPDF_RenderOptions ro; | |
| 60 ro.m_Flags = RENDER_CLEARTYPE; | |
| 61 ro.m_ColorMode = RENDER_COLOR_NORMAL; | |
| 62 | |
| 63 if (crTextStroke != 0) { | |
| 64 CFX_FloatPoint pt1(0, 0), pt2(1, 0); | |
| 65 pUser2Device->Transform(pt1.x, pt1.y); | |
| 66 pUser2Device->Transform(pt2.x, pt2.y); | |
| 67 CFX_GraphStateData gsd; | |
| 68 gsd.m_LineWidth = | |
| 69 (FX_FLOAT)FXSYS_fabs((pt2.x + pt2.y) - (pt1.x + pt1.y)); | |
| 70 | |
| 71 CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize, | |
| 72 pUser2Device, str, crTextFill, | |
| 73 crTextStroke, &gsd, &ro); | |
| 74 } else { | |
| 75 CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize, | |
| 76 pUser2Device, str, crTextFill, 0, | |
| 77 nullptr, &ro); | |
| 78 } | |
| 79 } | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 CPDF_TextObject* AddTextObjToPageObjects(CPDF_PageObjectHolder* pObjectHolder, | |
| 84 FX_COLORREF crText, | |
| 85 CPDF_Font* pFont, | |
| 86 FX_FLOAT fFontSize, | |
| 87 FX_FLOAT fCharSpace, | |
| 88 int32_t nHorzScale, | |
| 89 const CFX_FloatPoint& point, | |
| 90 const CFX_ByteString& text) { | |
| 91 std::unique_ptr<CPDF_TextObject> pTxtObj(new CPDF_TextObject); | |
| 92 CPDF_TextStateData* pTextStateData = pTxtObj->m_TextState.GetModify(); | |
| 93 pTextStateData->m_pFont = pFont; | |
| 94 pTextStateData->m_FontSize = fFontSize; | |
| 95 pTextStateData->m_CharSpace = fCharSpace; | |
| 96 pTextStateData->m_WordSpace = 0; | |
| 97 pTextStateData->m_TextMode = TextRenderingMode::MODE_FILL; | |
| 98 pTextStateData->m_Matrix[0] = nHorzScale / 100.0f; | |
| 99 pTextStateData->m_Matrix[1] = 0; | |
| 100 pTextStateData->m_Matrix[2] = 0; | |
| 101 pTextStateData->m_Matrix[3] = 1; | |
| 102 | |
| 103 FX_FLOAT rgb[3]; | |
| 104 rgb[0] = FXARGB_R(crText) / 255.0f; | |
| 105 rgb[1] = FXARGB_G(crText) / 255.0f; | |
| 106 rgb[2] = FXARGB_B(crText) / 255.0f; | |
| 107 pTxtObj->m_ColorState.SetFillColor( | |
| 108 CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); | |
| 109 pTxtObj->m_ColorState.SetStrokeColor( | |
| 110 CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); | |
| 111 | |
| 112 pTxtObj->SetPosition(point.x, point.y); | |
| 113 pTxtObj->SetText(text); | |
| 114 | |
| 115 CPDF_TextObject* pRet = pTxtObj.get(); | |
| 116 pObjectHolder->GetPageObjectList()->push_back(std::move(pTxtObj)); | |
| 117 return pRet; | |
| 118 } | |
| 119 | |
| 120 } // namespace | |
| 121 | |
| 122 void IFX_Edit::DrawEdit(CFX_RenderDevice* pDevice, | |
| 123 CFX_Matrix* pUser2Device, | |
| 124 IFX_Edit* pEdit, | |
| 125 FX_COLORREF crTextFill, | |
| 126 FX_COLORREF crTextStroke, | |
| 127 const CFX_FloatRect& rcClip, | |
| 128 const CFX_FloatPoint& ptOffset, | |
| 129 const CPVT_WordRange* pRange, | |
| 130 CFX_SystemHandler* pSystemHandler, | |
| 131 void* pFFLData) { | |
| 132 const bool bContinuous = | |
| 133 pEdit->GetCharArray() == 0 && pEdit->GetCharSpace() <= 0.0f; | |
| 134 uint16_t SubWord = pEdit->GetPasswordChar(); | |
| 135 FX_FLOAT fFontSize = pEdit->GetFontSize(); | |
| 136 CPVT_WordRange wrSelect = pEdit->GetSelectWordRange(); | |
| 137 int32_t nHorzScale = pEdit->GetHorzScale(); | |
| 138 | |
| 139 FX_COLORREF crCurFill = crTextFill; | |
| 140 FX_COLORREF crOldFill = crCurFill; | |
| 141 | |
| 142 FX_BOOL bSelect = FALSE; | |
| 143 const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255); | |
| 144 const FX_COLORREF crSelBK = ArgbEncode(255, 0, 51, 113); | |
| 145 | |
| 146 CFX_ByteTextBuf sTextBuf; | |
| 147 int32_t nFontIndex = -1; | |
| 148 CFX_FloatPoint ptBT(0.0f, 0.0f); | |
| 149 | |
| 150 pDevice->SaveState(); | |
| 151 | |
| 152 if (!rcClip.IsEmpty()) { | |
| 153 CFX_FloatRect rcTemp = rcClip; | |
| 154 pUser2Device->TransformRect(rcTemp); | |
| 155 pDevice->SetClip_Rect(rcTemp.ToFxRect()); | |
| 156 } | |
| 157 | |
| 158 IFX_Edit_Iterator* pIterator = pEdit->GetIterator(); | |
| 159 if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) { | |
| 160 if (pRange) | |
| 161 pIterator->SetAt(pRange->BeginPos); | |
| 162 else | |
| 163 pIterator->SetAt(0); | |
| 164 | |
| 165 CPVT_WordPlace oldplace; | |
| 166 while (pIterator->NextWord()) { | |
| 167 CPVT_WordPlace place = pIterator->GetAt(); | |
| 168 if (pRange && place.WordCmp(pRange->EndPos) > 0) | |
| 169 break; | |
| 170 | |
| 171 if (wrSelect.IsExist()) { | |
| 172 bSelect = place.WordCmp(wrSelect.BeginPos) > 0 && | |
| 173 place.WordCmp(wrSelect.EndPos) <= 0; | |
| 174 crCurFill = bSelect ? crWhite : crTextFill; | |
| 175 } | |
| 176 if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) { | |
| 177 crCurFill = crTextFill; | |
| 178 crOldFill = crCurFill; | |
| 179 } | |
| 180 CPVT_Word word; | |
| 181 if (pIterator->GetWord(word)) { | |
| 182 if (bSelect) { | |
| 183 CPVT_Line line; | |
| 184 pIterator->GetLine(line); | |
| 185 | |
| 186 if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) { | |
| 187 CFX_FloatRect rc(word.ptWord.x, line.ptLine.y + line.fLineDescent, | |
| 188 word.ptWord.x + word.fWidth, | |
| 189 line.ptLine.y + line.fLineAscent); | |
| 190 rc.Intersect(rcClip); | |
| 191 pSystemHandler->OutputSelectedRect(pFFLData, rc); | |
| 192 } else { | |
| 193 CFX_PathData pathSelBK; | |
| 194 pathSelBK.AppendRect( | |
| 195 word.ptWord.x, line.ptLine.y + line.fLineDescent, | |
| 196 word.ptWord.x + word.fWidth, line.ptLine.y + line.fLineAscent); | |
| 197 | |
| 198 pDevice->DrawPath(&pathSelBK, pUser2Device, nullptr, crSelBK, 0, | |
| 199 FXFILL_WINDING); | |
| 200 } | |
| 201 } | |
| 202 | |
| 203 if (bContinuous) { | |
| 204 if (place.LineCmp(oldplace) != 0 || word.nFontIndex != nFontIndex || | |
| 205 crOldFill != crCurFill) { | |
| 206 if (sTextBuf.GetLength() > 0) { | |
| 207 DrawTextString( | |
| 208 pDevice, | |
| 209 CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), | |
| 210 pFontMap->GetPDFFont(nFontIndex), fFontSize, pUser2Device, | |
| 211 sTextBuf.MakeString(), crOldFill, crTextStroke, nHorzScale); | |
| 212 | |
| 213 sTextBuf.Clear(); | |
| 214 } | |
| 215 nFontIndex = word.nFontIndex; | |
| 216 ptBT = word.ptWord; | |
| 217 crOldFill = crCurFill; | |
| 218 } | |
| 219 | |
| 220 sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, | |
| 221 SubWord) | |
| 222 .AsStringC(); | |
| 223 } else { | |
| 224 DrawTextString( | |
| 225 pDevice, CFX_FloatPoint(word.ptWord.x + ptOffset.x, | |
| 226 word.ptWord.y + ptOffset.y), | |
| 227 pFontMap->GetPDFFont(word.nFontIndex), fFontSize, pUser2Device, | |
| 228 GetPDFWordString(pFontMap, word.nFontIndex, word.Word, SubWord), | |
| 229 crCurFill, crTextStroke, nHorzScale); | |
| 230 } | |
| 231 oldplace = place; | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 if (sTextBuf.GetLength() > 0) { | |
| 236 DrawTextString( | |
| 237 pDevice, CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), | |
| 238 pFontMap->GetPDFFont(nFontIndex), fFontSize, pUser2Device, | |
| 239 sTextBuf.MakeString(), crOldFill, crTextStroke, nHorzScale); | |
| 240 } | |
| 241 } | |
| 242 | |
| 243 pDevice->RestoreState(false); | |
| 244 } | |
| 245 | |
| 246 void IFX_Edit::GeneratePageObjects( | |
| 247 CPDF_PageObjectHolder* pObjectHolder, | |
| 248 IFX_Edit* pEdit, | |
| 249 const CFX_FloatPoint& ptOffset, | |
| 250 const CPVT_WordRange* pRange, | |
| 251 FX_COLORREF crText, | |
| 252 CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray) { | |
| 253 FX_FLOAT fFontSize = pEdit->GetFontSize(); | |
| 254 | |
| 255 int32_t nOldFontIndex = -1; | |
| 256 | |
| 257 CFX_ByteTextBuf sTextBuf; | |
| 258 CFX_FloatPoint ptBT(0.0f, 0.0f); | |
| 259 | |
| 260 ObjArray.RemoveAll(); | |
| 261 | |
| 262 IFX_Edit_Iterator* pIterator = pEdit->GetIterator(); | |
| 263 if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) { | |
| 264 if (pRange) | |
| 265 pIterator->SetAt(pRange->BeginPos); | |
| 266 else | |
| 267 pIterator->SetAt(0); | |
| 268 | |
| 269 CPVT_WordPlace oldplace; | |
| 270 | |
| 271 while (pIterator->NextWord()) { | |
| 272 CPVT_WordPlace place = pIterator->GetAt(); | |
| 273 if (pRange && place.WordCmp(pRange->EndPos) > 0) | |
| 274 break; | |
| 275 | |
| 276 CPVT_Word word; | |
| 277 if (pIterator->GetWord(word)) { | |
| 278 if (place.LineCmp(oldplace) != 0 || nOldFontIndex != word.nFontIndex) { | |
| 279 if (sTextBuf.GetLength() > 0) { | |
| 280 ObjArray.Add(AddTextObjToPageObjects( | |
| 281 pObjectHolder, crText, pFontMap->GetPDFFont(nOldFontIndex), | |
| 282 fFontSize, 0.0f, 100, | |
| 283 CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), | |
| 284 sTextBuf.MakeString())); | |
| 285 | |
| 286 sTextBuf.Clear(); | |
| 287 } | |
| 288 | |
| 289 ptBT = word.ptWord; | |
| 290 nOldFontIndex = word.nFontIndex; | |
| 291 } | |
| 292 | |
| 293 sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, 0) | |
| 294 .AsStringC(); | |
| 295 oldplace = place; | |
| 296 } | |
| 297 } | |
| 298 | |
| 299 if (sTextBuf.GetLength() > 0) { | |
| 300 ObjArray.Add(AddTextObjToPageObjects( | |
| 301 pObjectHolder, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, | |
| 302 0.0f, 100, CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), | |
| 303 sTextBuf.MakeString())); | |
| 304 } | |
| 305 } | |
| 306 } | |
| OLD | NEW |