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