Convert all line endings to LF.
[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, FX_INT32 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, FX_INT32 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 = (FX_INT32)rcTemp.left;
91                 rcDevClip.right = (FX_INT32)rcTemp.right;
92                 rcDevClip.top = (FX_INT32)rcTemp.top;
93                 rcDevClip.bottom = (FX_INT32)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         FX_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         FX_INT32 nHorzScale = pEdit->GetHorzScale();
143
144         FX_COLORREF crCurFill = crTextFill;
145         FX_COLORREF crOldFill = crCurFill;
146
147         FX_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         FX_INT32 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 = (FX_INT32)rcTemp.left;
163                 rcDevClip.right = (FX_INT32)rcTemp.right;
164                 rcDevClip.top = (FX_INT32)rcTemp.top;
165                 rcDevClip.bottom = (FX_INT32)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         FX_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 = (FX_INT32)rcTemp.left;
297                 rcDevClip.right = (FX_INT32)rcTemp.right;
298                 rcDevClip.top = (FX_INT32)rcTemp.top;
299                 rcDevClip.bottom = (FX_INT32)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 AddLineToPageObjects(CPDF_PageObjects* pPageObjs, FX_COLORREF crStroke, 
401                                                                  const CPDF_Point& pt1, const CPDF_Point& pt2)
402 {
403         CPDF_PathObject* pPathObj = new CPDF_PathObject;
404         CPDF_PathData* pPathData = pPathObj->m_Path.GetModify();
405
406         pPathData->SetPointCount(2);
407         pPathData->SetPoint(0, pt1.x, pt1.y, FXPT_MOVETO);
408         pPathData->SetPoint(1, pt2.x, pt2.y, FXPT_LINETO);
409
410         FX_FLOAT rgb[3];
411         rgb[0] = FXARGB_R(crStroke) / 255.0f;
412         rgb[1] = FXARGB_G(crStroke) / 255.0f;
413         rgb[2] = FXARGB_B(crStroke) / 255.0f;
414         pPathObj->m_ColorState.SetStrokeColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3);
415
416         CFX_GraphStateData* pData = pPathObj->m_GraphState.GetModify();
417         pData->m_LineWidth = 1;
418
419         pPageObjs->InsertObject(pPageObjs->GetLastObjectPosition(),pPathObj);
420 }
421
422 static void AddRectToPageObjects(CPDF_PageObjects* pPageObjs, FX_COLORREF crFill, const CPDF_Rect& rcFill)
423 {
424         CPDF_PathObject* pPathObj = new CPDF_PathObject;
425         CPDF_PathData* pPathData = pPathObj->m_Path.GetModify();
426         pPathData->AppendRect(rcFill.left,rcFill.bottom,rcFill.right,rcFill.top);       
427         
428         FX_FLOAT rgb[3];
429         rgb[0] = FXARGB_R(crFill) / 255.0f ;
430         rgb[1] = FXARGB_G(crFill) / 255.0f;
431         rgb[2] = FXARGB_B(crFill) / 255.0f;
432         pPathObj->m_ColorState.SetFillColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3);
433
434         pPathObj->m_FillType = FXFILL_ALTERNATE;
435         pPathObj->m_bStroke = FALSE;
436
437         pPageObjs->InsertObject(pPageObjs->GetLastObjectPosition(),pPathObj);
438 }
439
440 static CPDF_TextObject* AddTextObjToPageObjects(CPDF_PageObjects* pPageObjs, FX_COLORREF crText, 
441                                                          CPDF_Font* pFont, FX_FLOAT fFontSize, FX_FLOAT fCharSpace, FX_INT32 nHorzScale, 
442                                                          const CPDF_Point& point, const CFX_ByteString& text)
443 {
444         CPDF_TextObject* pTxtObj = new CPDF_TextObject;
445                         
446         CPDF_TextStateData* pTextStateData = pTxtObj->m_TextState.GetModify();
447         pTextStateData->m_pFont = pFont;
448         pTextStateData->m_FontSize = fFontSize;
449         pTextStateData->m_CharSpace = fCharSpace;
450         pTextStateData->m_WordSpace = 0;
451         pTextStateData->m_TextMode  = 0;
452         pTextStateData->m_Matrix[0] = nHorzScale / 100.0f;
453         pTextStateData->m_Matrix[1] = 0;
454         pTextStateData->m_Matrix[2] = 0;
455         pTextStateData->m_Matrix[3] = 1;
456
457         FX_FLOAT rgb[3];
458         rgb[0] = FXARGB_R(crText) / 255.0f ;
459         rgb[1] = FXARGB_G(crText) / 255.0f;
460         rgb[2] = FXARGB_B(crText) / 255.0f;
461         pTxtObj->m_ColorState.SetFillColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB),rgb, 3);
462         pTxtObj->m_ColorState.SetStrokeColor(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB),rgb, 3);
463
464         pTxtObj->SetPosition(point.x,point.y);
465         pTxtObj->SetText(text); 
466
467         pPageObjs->InsertObject(pPageObjs->GetLastObjectPosition(),pTxtObj);
468
469         return pTxtObj;
470 }
471
472 /*
473 List of currently supported standard fonts:
474 Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique
475 Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique
476 Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic
477 Symbol, ZapfDingbats
478 */
479
480 const char* g_sFXEDITStandardFontName[] = {"Courier", "Courier-Bold", "Courier-BoldOblique", "Courier-Oblique",
481         "Helvetica", "Helvetica-Bold", "Helvetica-BoldOblique", "Helvetica-Oblique",
482         "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic",
483         "Symbol", "ZapfDingbats"};
484
485 static FX_BOOL FX_EDIT_IsStandardFont(const CFX_ByteString& sFontName)
486 {
487         for (FX_INT32 i=0; i<14; i++)
488         {
489                 if (sFontName == g_sFXEDITStandardFontName[i])
490                         return TRUE;
491         }
492
493         return FALSE;
494 }
495
496 void IFX_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
497                                                                    const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, FX_COLORREF crText, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray)
498 {
499         FX_FLOAT fFontSize = pEdit->GetFontSize();
500
501         FX_INT32 nOldFontIndex = -1;
502
503         CFX_ByteTextBuf sTextBuf;
504         CPDF_Point ptBT(0.0f,0.0f);
505
506         ObjArray.RemoveAll();
507
508         if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
509         {
510                 if (IFX_Edit_FontMap* pFontMap = pEdit->GetFontMap())
511                 {
512                         if (pRange)
513                                 pIterator->SetAt(pRange->BeginPos);
514                         else
515                                 pIterator->SetAt(0);
516
517                         CPVT_WordPlace oldplace;                        
518
519                         while (pIterator->NextWord())
520                         {
521                                 CPVT_WordPlace place = pIterator->GetAt();
522                                 if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
523                                 
524                                 CPVT_Word word;                         
525                                 if (pIterator->GetWord(word))
526                                 {
527                                         if (place.LineCmp(oldplace) != 0 || nOldFontIndex != word.nFontIndex)
528                                         {
529                                                 if (sTextBuf.GetLength() > 0)
530                                                 {
531                                                         ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, 0.0f, 100,
532                                                                 CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
533
534                                                         sTextBuf.Clear();
535                                                 }
536
537                                                 ptBT = word.ptWord;
538                                                 nOldFontIndex = word.nFontIndex;
539                                         }
540
541                                         sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, 0);
542                                         oldplace = place;                                       
543                                 }
544                         }
545
546                         if (sTextBuf.GetLength() > 0)
547                         {                               
548                                 ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, 0.0f, 100,
549                                         CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
550                         }
551                 }
552         }
553 }
554
555 void IFX_Edit::GenerateRichPageObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
556                                                                    const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray)
557 {
558
559
560         FX_COLORREF crCurText = ArgbEncode(255, 0, 0, 0);
561         FX_COLORREF crOld = crCurText;
562
563
564         CFX_ByteTextBuf sTextBuf;
565         CPVT_WordProps wp;
566         CPDF_Point ptBT(0.0f,0.0f);
567
568         ObjArray.RemoveAll();
569
570         if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
571         {
572                 if (IFX_Edit_FontMap* pFontMap = pEdit->GetFontMap())
573                 {
574                         if (pRange)
575                                 pIterator->SetAt(pRange->BeginPos);
576                         else
577                                 pIterator->SetAt(0);
578
579                         CPVT_WordPlace oldplace;                        
580
581                         while (pIterator->NextWord())
582                         {
583                                 CPVT_WordPlace place = pIterator->GetAt();
584                                 if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
585                                 
586                                 CPVT_Word word;                         
587                                 if (pIterator->GetWord(word))
588                                 {
589                                         word.WordProps.fFontSize = word.fFontSize;
590
591                                         crCurText = ArgbEncode(255,word.WordProps.dwWordColor);
592
593                                         if (place.LineCmp(oldplace) != 0 || word.WordProps.fCharSpace > 0.0f || word.WordProps.nHorzScale != 100 || 
594                                                 FXSYS_memcmp(&word.WordProps, &wp, sizeof(CPVT_WordProps)) != 0 || 
595                                                 crOld != crCurText)
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                                                         sTextBuf.Clear();
603                                                 }
604
605                                                 wp = word.WordProps;
606                                                 ptBT = word.ptWord;
607                                                 crOld = crCurText;
608         
609                                         }
610
611                                         sTextBuf << GetPDFWordString(pFontMap, word.WordProps.nFontIndex, word.Word, 0);        
612                                         
613                                         if (word.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE)
614                                         {/*
615                                                 AddLineToPageObjects(pPageObjects, crCurText, 
616                                                         CPDF_Point(word.ptWord.x, word.ptWord.y + word.fDescent * 0.4f),
617                                                         CPDF_Point(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent * 0.4f));                                                 
618 */
619                                                 CPDF_Rect rcUnderline = GetUnderLineRect(word);
620                                                 rcUnderline.left += ptOffset.x;
621                                                 rcUnderline.right += ptOffset.x;
622                                                 rcUnderline.top += ptOffset.y;
623                                                 rcUnderline.bottom += ptOffset.y;
624                                                 
625                                                 AddRectToPageObjects(pPageObjects, crCurText, rcUnderline);                                                     
626                                         }
627
628                                         if (word.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT)
629                                         {
630                                                 CPDF_Rect rcCrossout = GetCrossoutRect(word);
631                                                 rcCrossout.left += ptOffset.x;
632                                                 rcCrossout.right += ptOffset.x;
633                                                 rcCrossout.top += ptOffset.y;
634                                                 rcCrossout.bottom += ptOffset.y;
635
636                                                 AddRectToPageObjects(pPageObjects, crCurText, rcCrossout);                                              
637                                         }
638
639                                         oldplace = place;                                       
640                                 }
641                         }
642
643                         if (sTextBuf.GetLength() > 0)
644                         {                               
645                                 ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crOld, pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize, wp.fCharSpace, wp.nHorzScale,
646                                         CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
647                         }
648                 }
649         }
650 }
651
652 void IFX_Edit::GenerateUnderlineObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
653                                                                    const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, FX_COLORREF color)
654 {
655
656
657         if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
658         {
659                 if (pEdit->GetFontMap())
660                 {
661                         if (pRange)
662                                 pIterator->SetAt(pRange->BeginPos);
663                         else
664                                 pIterator->SetAt(0);
665
666                         CPVT_WordPlace oldplace;                        
667
668                         while (pIterator->NextWord())
669                         {
670                                 CPVT_WordPlace place = pIterator->GetAt();
671                                 if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
672                                 
673                                 CPVT_Word word;                         
674                                 if (pIterator->GetWord(word))
675                                 {
676                                         CPDF_Rect rcUnderline = GetUnderLineRect(word);
677                                         rcUnderline.left += ptOffset.x;
678                                         rcUnderline.right += ptOffset.x;
679                                         rcUnderline.top += ptOffset.y;
680                                         rcUnderline.bottom += ptOffset.y;
681                                         AddRectToPageObjects(pPageObjects, color, rcUnderline);
682                                 }
683                         }
684                 }
685         }
686 }
687