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 |