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