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