blob: bdce7c05db609038f7b772d7ca5cada5af50f8c9 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Lei Zhangbde53d22015-11-12 22:21:30 -08007#include "fpdfsdk/include/fxedit/fx_edit.h"
8#include "fpdfsdk/include/fxedit/fxet_edit.h"
9#include "fpdfsdk/include/fxedit/fxet_stub.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070010
Nico Weber9d8ec5a2015-08-04 13:00:21 -070011CFX_ByteString GetPDFWordString(IFX_Edit_FontMap* pFontMap,
12 int32_t nFontIndex,
13 FX_WORD Word,
14 FX_WORD SubWord) {
15 ASSERT(pFontMap != NULL);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070016
Nico Weber9d8ec5a2015-08-04 13:00:21 -070017 CFX_ByteString sWord;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070018
Nico Weber9d8ec5a2015-08-04 13:00:21 -070019 if (CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex)) {
20 if (SubWord > 0) {
21 Word = SubWord;
22 } else {
23 FX_DWORD dwCharCode = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070024
Nico Weber9d8ec5a2015-08-04 13:00:21 -070025 if (pPDFFont->IsUnicodeCompatible())
26 dwCharCode = pPDFFont->CharCodeFromUnicode(Word);
27 else
28 dwCharCode = pFontMap->CharCodeFromUnicode(nFontIndex, Word);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070029
Nico Weber9d8ec5a2015-08-04 13:00:21 -070030 if (dwCharCode > 0) {
31 pPDFFont->AppendChar(sWord, dwCharCode);
32 return sWord;
33 }
34 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070035
Nico Weber9d8ec5a2015-08-04 13:00:21 -070036 pPDFFont->AppendChar(sWord, Word);
37 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070038
Nico Weber9d8ec5a2015-08-04 13:00:21 -070039 return sWord;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070040}
41
Nico Weber9d8ec5a2015-08-04 13:00:21 -070042static CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) {
43 if (strWords.GetLength() > 0)
44 return PDF_EncodeString(strWords) + " Tj\n";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070045
Nico Weber9d8ec5a2015-08-04 13:00:21 -070046 return "";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070047}
48
Nico Weber9d8ec5a2015-08-04 13:00:21 -070049static CFX_ByteString GetFontSetString(IFX_Edit_FontMap* pFontMap,
50 int32_t nFontIndex,
51 FX_FLOAT fFontSize) {
52 CFX_ByteTextBuf sRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070053
Nico Weber9d8ec5a2015-08-04 13:00:21 -070054 if (pFontMap) {
55 CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070056
Nico Weber9d8ec5a2015-08-04 13:00:21 -070057 if (sFontAlias.GetLength() > 0 && fFontSize > 0)
58 sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n";
59 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070060
Nico Weber9d8ec5a2015-08-04 13:00:21 -070061 return sRet.GetByteString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070062}
63
Nico Weber9d8ec5a2015-08-04 13:00:21 -070064CFX_ByteString IFX_Edit::GetEditAppearanceStream(
65 IFX_Edit* pEdit,
66 const CPDF_Point& ptOffset,
67 const CPVT_WordRange* pRange /* = NULL*/,
68 FX_BOOL bContinuous /* = TRUE*/,
69 FX_WORD SubWord /* = 0*/) {
70 CFX_ByteTextBuf sEditStream, sWords;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070071
Nico Weber9d8ec5a2015-08-04 13:00:21 -070072 CPDF_Point ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f);
73 int32_t nCurFontIndex = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070074
Nico Weber9d8ec5a2015-08-04 13:00:21 -070075 if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
76 if (pRange)
77 pIterator->SetAt(pRange->BeginPos);
78 else
79 pIterator->SetAt(0);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070080
Nico Weber9d8ec5a2015-08-04 13:00:21 -070081 CPVT_WordPlace oldplace;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070082
Nico Weber9d8ec5a2015-08-04 13:00:21 -070083 while (pIterator->NextWord()) {
84 CPVT_WordPlace place = pIterator->GetAt();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070085
Nico Weber9d8ec5a2015-08-04 13:00:21 -070086 if (pRange && place.WordCmp(pRange->EndPos) > 0)
87 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070088
Nico Weber9d8ec5a2015-08-04 13:00:21 -070089 if (bContinuous) {
90 if (place.LineCmp(oldplace) != 0) {
91 if (sWords.GetSize() > 0) {
92 sEditStream << GetWordRenderString(sWords.GetByteString());
93 sWords.Clear();
94 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070095
Nico Weber9d8ec5a2015-08-04 13:00:21 -070096 CPVT_Word word;
97 if (pIterator->GetWord(word)) {
98 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x,
99 word.ptWord.y + ptOffset.y);
100 } else {
101 CPVT_Line line;
102 pIterator->GetLine(line);
103 ptNew = CPDF_Point(line.ptLine.x + ptOffset.x,
104 line.ptLine.y + ptOffset.y);
105 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700106
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700107 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
108 sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y
109 << " Td\n";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700110
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700111 ptOld = ptNew;
112 }
113 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700114
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700115 CPVT_Word word;
116 if (pIterator->GetWord(word)) {
117 if (word.nFontIndex != nCurFontIndex) {
118 if (sWords.GetSize() > 0) {
119 sEditStream << GetWordRenderString(sWords.GetByteString());
120 sWords.Clear();
121 }
122 sEditStream << GetFontSetString(pEdit->GetFontMap(),
123 word.nFontIndex, word.fFontSize);
124 nCurFontIndex = word.nFontIndex;
125 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700126
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700127 sWords << GetPDFWordString(pEdit->GetFontMap(), nCurFontIndex,
128 word.Word, SubWord);
129 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700130
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700131 oldplace = place;
132 } else {
133 CPVT_Word word;
134 if (pIterator->GetWord(word)) {
135 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x,
136 word.ptWord.y + ptOffset.y);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700137
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700138 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
139 sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y
140 << " Td\n";
141 ptOld = ptNew;
142 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700143
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700144 if (word.nFontIndex != nCurFontIndex) {
145 sEditStream << GetFontSetString(pEdit->GetFontMap(),
146 word.nFontIndex, word.fFontSize);
147 nCurFontIndex = word.nFontIndex;
148 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700149
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700150 sEditStream << GetWordRenderString(GetPDFWordString(
151 pEdit->GetFontMap(), nCurFontIndex, word.Word, SubWord));
152 }
153 }
154 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700155
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700156 if (sWords.GetSize() > 0) {
157 sEditStream << GetWordRenderString(sWords.GetByteString());
158 sWords.Clear();
159 }
160 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700161
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700162 CFX_ByteTextBuf sAppStream;
163 if (sEditStream.GetSize() > 0) {
164 int32_t nHorzScale = pEdit->GetHorzScale();
165 if (nHorzScale != 100) {
166 sAppStream << nHorzScale << " Tz\n";
167 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700168
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700169 FX_FLOAT fCharSpace = pEdit->GetCharSpace();
170 if (!FX_EDIT_IsFloatZero(fCharSpace)) {
171 sAppStream << fCharSpace << " Tc\n";
172 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700173
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700174 sAppStream << sEditStream;
175 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700176
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700177 return sAppStream.GetByteString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700178}
179
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700180CFX_ByteString IFX_Edit::GetSelectAppearanceStream(
181 IFX_Edit* pEdit,
182 const CPDF_Point& ptOffset,
183 const CPVT_WordRange* pRange /*= NULL*/) {
184 CFX_ByteTextBuf sRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700185
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700186 if (pRange && pRange->IsExist()) {
187 if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
188 pIterator->SetAt(pRange->BeginPos);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700189
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700190 while (pIterator->NextWord()) {
191 CPVT_WordPlace place = pIterator->GetAt();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700192
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700193 if (pRange && place.WordCmp(pRange->EndPos) > 0)
194 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700195
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700196 CPVT_Word word;
197 CPVT_Line line;
198 if (pIterator->GetWord(word) && pIterator->GetLine(line)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700199 sRet << word.ptWord.x + ptOffset.x << " "
200 << line.ptLine.y + line.fLineDescent << " " << word.fWidth << " "
201 << line.fLineAscent - line.fLineDescent << " re\nf\n";
202 }
203 }
204 }
205 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700206
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700207 return sRet.GetByteString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700208}