• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/include/fpdfapi/fpdf_resource.h"
8 #include "fpdfsdk/include/fxedit/fx_edit.h"
9 #include "fpdfsdk/include/fxedit/fxet_edit.h"
10 
GetPDFWordString(IFX_Edit_FontMap * pFontMap,int32_t nFontIndex,FX_WORD Word,FX_WORD SubWord)11 CFX_ByteString GetPDFWordString(IFX_Edit_FontMap* pFontMap,
12                                 int32_t nFontIndex,
13                                 FX_WORD Word,
14                                 FX_WORD SubWord) {
15   CFX_ByteString sWord;
16   if (CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex)) {
17     if (SubWord > 0) {
18       Word = SubWord;
19     } else {
20       FX_DWORD dwCharCode = -1;
21 
22       if (pPDFFont->IsUnicodeCompatible())
23         dwCharCode = pPDFFont->CharCodeFromUnicode(Word);
24       else
25         dwCharCode = pFontMap->CharCodeFromUnicode(nFontIndex, Word);
26 
27       if (dwCharCode > 0) {
28         pPDFFont->AppendChar(sWord, dwCharCode);
29         return sWord;
30       }
31     }
32 
33     pPDFFont->AppendChar(sWord, Word);
34   }
35 
36   return sWord;
37 }
38 
GetWordRenderString(const CFX_ByteString & strWords)39 static CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) {
40   if (strWords.GetLength() > 0)
41     return PDF_EncodeString(strWords) + " Tj\n";
42 
43   return "";
44 }
45 
GetFontSetString(IFX_Edit_FontMap * pFontMap,int32_t nFontIndex,FX_FLOAT fFontSize)46 static CFX_ByteString GetFontSetString(IFX_Edit_FontMap* pFontMap,
47                                        int32_t nFontIndex,
48                                        FX_FLOAT fFontSize) {
49   CFX_ByteTextBuf sRet;
50 
51   if (pFontMap) {
52     CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex);
53 
54     if (sFontAlias.GetLength() > 0 && fFontSize > 0)
55       sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n";
56   }
57 
58   return sRet.GetByteString();
59 }
60 
GetEditAppearanceStream(IFX_Edit * pEdit,const CPDF_Point & ptOffset,const CPVT_WordRange * pRange,FX_BOOL bContinuous,FX_WORD SubWord)61 CFX_ByteString IFX_Edit::GetEditAppearanceStream(
62     IFX_Edit* pEdit,
63     const CPDF_Point& ptOffset,
64     const CPVT_WordRange* pRange /* = NULL*/,
65     FX_BOOL bContinuous /* = TRUE*/,
66     FX_WORD SubWord /* = 0*/) {
67   CFX_ByteTextBuf sEditStream, sWords;
68 
69   CPDF_Point ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f);
70   int32_t nCurFontIndex = -1;
71 
72   if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
73     if (pRange)
74       pIterator->SetAt(pRange->BeginPos);
75     else
76       pIterator->SetAt(0);
77 
78     CPVT_WordPlace oldplace;
79 
80     while (pIterator->NextWord()) {
81       CPVT_WordPlace place = pIterator->GetAt();
82 
83       if (pRange && place.WordCmp(pRange->EndPos) > 0)
84         break;
85 
86       if (bContinuous) {
87         if (place.LineCmp(oldplace) != 0) {
88           if (sWords.GetSize() > 0) {
89             sEditStream << GetWordRenderString(sWords.GetByteString());
90             sWords.Clear();
91           }
92 
93           CPVT_Word word;
94           if (pIterator->GetWord(word)) {
95             ptNew = CPDF_Point(word.ptWord.x + ptOffset.x,
96                                word.ptWord.y + ptOffset.y);
97           } else {
98             CPVT_Line line;
99             pIterator->GetLine(line);
100             ptNew = CPDF_Point(line.ptLine.x + ptOffset.x,
101                                line.ptLine.y + ptOffset.y);
102           }
103 
104           if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
105             sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y
106                         << " Td\n";
107 
108             ptOld = ptNew;
109           }
110         }
111 
112         CPVT_Word word;
113         if (pIterator->GetWord(word)) {
114           if (word.nFontIndex != nCurFontIndex) {
115             if (sWords.GetSize() > 0) {
116               sEditStream << GetWordRenderString(sWords.GetByteString());
117               sWords.Clear();
118             }
119             sEditStream << GetFontSetString(pEdit->GetFontMap(),
120                                             word.nFontIndex, word.fFontSize);
121             nCurFontIndex = word.nFontIndex;
122           }
123 
124           sWords << GetPDFWordString(pEdit->GetFontMap(), nCurFontIndex,
125                                      word.Word, SubWord);
126         }
127 
128         oldplace = place;
129       } else {
130         CPVT_Word word;
131         if (pIterator->GetWord(word)) {
132           ptNew = CPDF_Point(word.ptWord.x + ptOffset.x,
133                              word.ptWord.y + ptOffset.y);
134 
135           if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
136             sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y
137                         << " Td\n";
138             ptOld = ptNew;
139           }
140 
141           if (word.nFontIndex != nCurFontIndex) {
142             sEditStream << GetFontSetString(pEdit->GetFontMap(),
143                                             word.nFontIndex, word.fFontSize);
144             nCurFontIndex = word.nFontIndex;
145           }
146 
147           sEditStream << GetWordRenderString(GetPDFWordString(
148               pEdit->GetFontMap(), nCurFontIndex, word.Word, SubWord));
149         }
150       }
151     }
152 
153     if (sWords.GetSize() > 0) {
154       sEditStream << GetWordRenderString(sWords.GetByteString());
155       sWords.Clear();
156     }
157   }
158 
159   CFX_ByteTextBuf sAppStream;
160   if (sEditStream.GetSize() > 0) {
161     int32_t nHorzScale = pEdit->GetHorzScale();
162     if (nHorzScale != 100) {
163       sAppStream << nHorzScale << " Tz\n";
164     }
165 
166     FX_FLOAT fCharSpace = pEdit->GetCharSpace();
167     if (!FX_EDIT_IsFloatZero(fCharSpace)) {
168       sAppStream << fCharSpace << " Tc\n";
169     }
170 
171     sAppStream << sEditStream;
172   }
173 
174   return sAppStream.GetByteString();
175 }
176 
GetSelectAppearanceStream(IFX_Edit * pEdit,const CPDF_Point & ptOffset,const CPVT_WordRange * pRange)177 CFX_ByteString IFX_Edit::GetSelectAppearanceStream(
178     IFX_Edit* pEdit,
179     const CPDF_Point& ptOffset,
180     const CPVT_WordRange* pRange) {
181   CFX_ByteTextBuf sRet;
182 
183   if (pRange && pRange->IsExist()) {
184     if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
185       pIterator->SetAt(pRange->BeginPos);
186 
187       while (pIterator->NextWord()) {
188         CPVT_WordPlace place = pIterator->GetAt();
189 
190         if (pRange && place.WordCmp(pRange->EndPos) > 0)
191           break;
192 
193         CPVT_Word word;
194         CPVT_Line line;
195         if (pIterator->GetWord(word) && pIterator->GetLine(line)) {
196           sRet << word.ptWord.x + ptOffset.x << " "
197                << line.ptLine.y + line.fLineDescent << " " << word.fWidth << " "
198                << line.fLineAscent - line.fLineDescent << " re\nf\n";
199         }
200       }
201     }
202   }
203 
204   return sRet.GetByteString();
205 }
206