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 |