In windows printing, convert src bitmap to dest bitmap using CompositeBitmap.
[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 void IFX_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
473                                                                    const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, FX_COLORREF crText, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray)
474 {
475         FX_FLOAT fFontSize = pEdit->GetFontSize();
476
477         FX_INT32 nOldFontIndex = -1;
478
479         CFX_ByteTextBuf sTextBuf;
480         CPDF_Point ptBT(0.0f,0.0f);
481
482         ObjArray.RemoveAll();
483
484         if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
485         {
486                 if (IFX_Edit_FontMap* pFontMap = pEdit->GetFontMap())
487                 {
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                         {
497                                 CPVT_WordPlace place = pIterator->GetAt();
498                                 if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
499                                 
500                                 CPVT_Word word;                         
501                                 if (pIterator->GetWord(word))
502                                 {
503                                         if (place.LineCmp(oldplace) != 0 || nOldFontIndex != word.nFontIndex)
504                                         {
505                                                 if (sTextBuf.GetLength() > 0)
506                                                 {
507                                                         ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, 0.0f, 100,
508                                                                 CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
509
510                                                         sTextBuf.Clear();
511                                                 }
512
513                                                 ptBT = word.ptWord;
514                                                 nOldFontIndex = word.nFontIndex;
515                                         }
516
517                                         sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, 0);
518                                         oldplace = place;                                       
519                                 }
520                         }
521
522                         if (sTextBuf.GetLength() > 0)
523                         {                               
524                                 ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, 0.0f, 100,
525                                         CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
526                         }
527                 }
528         }
529 }
530
531 void IFX_Edit::GenerateRichPageObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
532                                                                    const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray)
533 {
534
535
536         FX_COLORREF crCurText = ArgbEncode(255, 0, 0, 0);
537         FX_COLORREF crOld = crCurText;
538
539
540         CFX_ByteTextBuf sTextBuf;
541         CPVT_WordProps wp;
542         CPDF_Point ptBT(0.0f,0.0f);
543
544         ObjArray.RemoveAll();
545
546         if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
547         {
548                 if (IFX_Edit_FontMap* pFontMap = pEdit->GetFontMap())
549                 {
550                         if (pRange)
551                                 pIterator->SetAt(pRange->BeginPos);
552                         else
553                                 pIterator->SetAt(0);
554
555                         CPVT_WordPlace oldplace;                        
556
557                         while (pIterator->NextWord())
558                         {
559                                 CPVT_WordPlace place = pIterator->GetAt();
560                                 if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
561                                 
562                                 CPVT_Word word;                         
563                                 if (pIterator->GetWord(word))
564                                 {
565                                         word.WordProps.fFontSize = word.fFontSize;
566
567                                         crCurText = ArgbEncode(255,word.WordProps.dwWordColor);
568
569                                         if (place.LineCmp(oldplace) != 0 || word.WordProps.fCharSpace > 0.0f || word.WordProps.nHorzScale != 100 || 
570                                                 FXSYS_memcmp(&word.WordProps, &wp, sizeof(CPVT_WordProps)) != 0 || 
571                                                 crOld != crCurText)
572                                         {
573                                                 if (sTextBuf.GetLength() > 0)
574                                                 {
575                                                         ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crOld, pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize, wp.fCharSpace, wp.nHorzScale,
576                                                                 CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
577
578                                                         sTextBuf.Clear();
579                                                 }
580
581                                                 wp = word.WordProps;
582                                                 ptBT = word.ptWord;
583                                                 crOld = crCurText;
584         
585                                         }
586
587                                         sTextBuf << GetPDFWordString(pFontMap, word.WordProps.nFontIndex, word.Word, 0);        
588                                         
589                                         if (word.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE)
590                                         {/*
591                                                 AddLineToPageObjects(pPageObjects, crCurText, 
592                                                         CPDF_Point(word.ptWord.x, word.ptWord.y + word.fDescent * 0.4f),
593                                                         CPDF_Point(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent * 0.4f));                                                 
594 */
595                                                 CPDF_Rect rcUnderline = GetUnderLineRect(word);
596                                                 rcUnderline.left += ptOffset.x;
597                                                 rcUnderline.right += ptOffset.x;
598                                                 rcUnderline.top += ptOffset.y;
599                                                 rcUnderline.bottom += ptOffset.y;
600                                                 
601                                                 AddRectToPageObjects(pPageObjects, crCurText, rcUnderline);                                                     
602                                         }
603
604                                         if (word.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT)
605                                         {
606                                                 CPDF_Rect rcCrossout = GetCrossoutRect(word);
607                                                 rcCrossout.left += ptOffset.x;
608                                                 rcCrossout.right += ptOffset.x;
609                                                 rcCrossout.top += ptOffset.y;
610                                                 rcCrossout.bottom += ptOffset.y;
611
612                                                 AddRectToPageObjects(pPageObjects, crCurText, rcCrossout);                                              
613                                         }
614
615                                         oldplace = place;                                       
616                                 }
617                         }
618
619                         if (sTextBuf.GetLength() > 0)
620                         {                               
621                                 ObjArray.Add(AddTextObjToPageObjects(pPageObjects, crOld, pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize, wp.fCharSpace, wp.nHorzScale,
622                                         CPDF_Point(ptBT.x+ptOffset.x, ptBT.y+ptOffset.y), sTextBuf.GetByteString()));
623                         }
624                 }
625         }
626 }
627
628 void IFX_Edit::GenerateUnderlineObjects(CPDF_PageObjects* pPageObjects, IFX_Edit* pEdit,
629                                                                    const CPDF_Point& ptOffset, const CPVT_WordRange* pRange, FX_COLORREF color)
630 {
631
632
633         if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
634         {
635                 if (pEdit->GetFontMap())
636                 {
637                         if (pRange)
638                                 pIterator->SetAt(pRange->BeginPos);
639                         else
640                                 pIterator->SetAt(0);
641
642                         CPVT_WordPlace oldplace;                        
643
644                         while (pIterator->NextWord())
645                         {
646                                 CPVT_WordPlace place = pIterator->GetAt();
647                                 if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
648                                 
649                                 CPVT_Word word;                         
650                                 if (pIterator->GetWord(word))
651                                 {
652                                         CPDF_Rect rcUnderline = GetUnderLineRect(word);
653                                         rcUnderline.left += ptOffset.x;
654                                         rcUnderline.right += ptOffset.x;
655                                         rcUnderline.top += ptOffset.y;
656                                         rcUnderline.bottom += ptOffset.y;
657                                         AddRectToPageObjects(pPageObjects, color, rcUnderline);
658                                 }
659                         }
660                 }
661         }
662 }
663