blob: 562f566edbff7bdd7e91de0d5bcd86a8f0bd9618 [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 Zhangc2fb35f2016-01-05 16:46:58 -08007#include "core/include/fpdfapi/fpdf_resource.h"
Lei Zhangbde53d22015-11-12 22:21:30 -08008#include "fpdfsdk/include/fxedit/fx_edit.h"
9#include "fpdfsdk/include/fxedit/fxet_edit.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) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070015 CFX_ByteString sWord;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070016 if (CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex)) {
17 if (SubWord > 0) {
18 Word = SubWord;
19 } else {
20 FX_DWORD dwCharCode = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070021
Nico Weber9d8ec5a2015-08-04 13:00:21 -070022 if (pPDFFont->IsUnicodeCompatible())
23 dwCharCode = pPDFFont->CharCodeFromUnicode(Word);
24 else
25 dwCharCode = pFontMap->CharCodeFromUnicode(nFontIndex, Word);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070026
Nico Weber9d8ec5a2015-08-04 13:00:21 -070027 if (dwCharCode > 0) {
28 pPDFFont->AppendChar(sWord, dwCharCode);
29 return sWord;
30 }
31 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070032
Nico Weber9d8ec5a2015-08-04 13:00:21 -070033 pPDFFont->AppendChar(sWord, Word);
34 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070035
Nico Weber9d8ec5a2015-08-04 13:00:21 -070036 return sWord;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070037}
38
Nico Weber9d8ec5a2015-08-04 13:00:21 -070039static CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) {
40 if (strWords.GetLength() > 0)
41 return PDF_EncodeString(strWords) + " Tj\n";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070042
Nico Weber9d8ec5a2015-08-04 13:00:21 -070043 return "";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070044}
45
Nico Weber9d8ec5a2015-08-04 13:00:21 -070046static CFX_ByteString GetFontSetString(IFX_Edit_FontMap* pFontMap,
47 int32_t nFontIndex,
48 FX_FLOAT fFontSize) {
49 CFX_ByteTextBuf sRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070050
Nico Weber9d8ec5a2015-08-04 13:00:21 -070051 if (pFontMap) {
52 CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070053
Nico Weber9d8ec5a2015-08-04 13:00:21 -070054 if (sFontAlias.GetLength() > 0 && fFontSize > 0)
55 sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n";
56 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070057
Nico Weber9d8ec5a2015-08-04 13:00:21 -070058 return sRet.GetByteString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070059}
60
Nico Weber9d8ec5a2015-08-04 13:00:21 -070061CFX_ByteString IFX_Edit::GetEditAppearanceStream(
62 IFX_Edit* pEdit,
Tom Sepez281a9ea2016-02-26 14:24:28 -080063 const CFX_FloatPoint& ptOffset,
Nico Weber9d8ec5a2015-08-04 13:00:21 -070064 const CPVT_WordRange* pRange /* = NULL*/,
65 FX_BOOL bContinuous /* = TRUE*/,
66 FX_WORD SubWord /* = 0*/) {
67 CFX_ByteTextBuf sEditStream, sWords;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070068
Tom Sepez281a9ea2016-02-26 14:24:28 -080069 CFX_FloatPoint ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070070 int32_t nCurFontIndex = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070071
Nico Weber9d8ec5a2015-08-04 13:00:21 -070072 if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
73 if (pRange)
74 pIterator->SetAt(pRange->BeginPos);
75 else
76 pIterator->SetAt(0);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070077
Nico Weber9d8ec5a2015-08-04 13:00:21 -070078 CPVT_WordPlace oldplace;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070079
Nico Weber9d8ec5a2015-08-04 13:00:21 -070080 while (pIterator->NextWord()) {
81 CPVT_WordPlace place = pIterator->GetAt();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070082
Nico Weber9d8ec5a2015-08-04 13:00:21 -070083 if (pRange && place.WordCmp(pRange->EndPos) > 0)
84 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070085
Nico Weber9d8ec5a2015-08-04 13:00:21 -070086 if (bContinuous) {
87 if (place.LineCmp(oldplace) != 0) {
88 if (sWords.GetSize() > 0) {
89 sEditStream << GetWordRenderString(sWords.GetByteString());
90 sWords.Clear();
91 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070092
Nico Weber9d8ec5a2015-08-04 13:00:21 -070093 CPVT_Word word;
94 if (pIterator->GetWord(word)) {
Tom Sepez281a9ea2016-02-26 14:24:28 -080095 ptNew = CFX_FloatPoint(word.ptWord.x + ptOffset.x,
96 word.ptWord.y + ptOffset.y);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070097 } else {
98 CPVT_Line line;
99 pIterator->GetLine(line);
Tom Sepez281a9ea2016-02-26 14:24:28 -0800100 ptNew = CFX_FloatPoint(line.ptLine.x + ptOffset.x,
101 line.ptLine.y + ptOffset.y);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700102 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700103
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700104 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
105 sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y
106 << " Td\n";
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700107
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700108 ptOld = ptNew;
109 }
110 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700111
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700112 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 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700123
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700124 sWords << GetPDFWordString(pEdit->GetFontMap(), nCurFontIndex,
125 word.Word, SubWord);
126 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700127
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700128 oldplace = place;
129 } else {
130 CPVT_Word word;
131 if (pIterator->GetWord(word)) {
Tom Sepez281a9ea2016-02-26 14:24:28 -0800132 ptNew = CFX_FloatPoint(word.ptWord.x + ptOffset.x,
133 word.ptWord.y + ptOffset.y);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700134
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700135 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 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700140
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700141 if (word.nFontIndex != nCurFontIndex) {
142 sEditStream << GetFontSetString(pEdit->GetFontMap(),
143 word.nFontIndex, word.fFontSize);
144 nCurFontIndex = word.nFontIndex;
145 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700146
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700147 sEditStream << GetWordRenderString(GetPDFWordString(
148 pEdit->GetFontMap(), nCurFontIndex, word.Word, SubWord));
149 }
150 }
151 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700152
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700153 if (sWords.GetSize() > 0) {
154 sEditStream << GetWordRenderString(sWords.GetByteString());
155 sWords.Clear();
156 }
157 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700158
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700159 CFX_ByteTextBuf sAppStream;
160 if (sEditStream.GetSize() > 0) {
161 int32_t nHorzScale = pEdit->GetHorzScale();
162 if (nHorzScale != 100) {
163 sAppStream << nHorzScale << " Tz\n";
164 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700165
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700166 FX_FLOAT fCharSpace = pEdit->GetCharSpace();
167 if (!FX_EDIT_IsFloatZero(fCharSpace)) {
168 sAppStream << fCharSpace << " Tc\n";
169 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700170
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700171 sAppStream << sEditStream;
172 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700173
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700174 return sAppStream.GetByteString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700175}
176
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700177CFX_ByteString IFX_Edit::GetSelectAppearanceStream(
178 IFX_Edit* pEdit,
Tom Sepez281a9ea2016-02-26 14:24:28 -0800179 const CFX_FloatPoint& ptOffset,
Lei Zhangc2fb35f2016-01-05 16:46:58 -0800180 const CPVT_WordRange* pRange) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700181 CFX_ByteTextBuf sRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700182
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700183 if (pRange && pRange->IsExist()) {
184 if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) {
185 pIterator->SetAt(pRange->BeginPos);
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700186
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700187 while (pIterator->NextWord()) {
188 CPVT_WordPlace place = pIterator->GetAt();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700189
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700190 if (pRange && place.WordCmp(pRange->EndPos) > 0)
191 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700192
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700193 CPVT_Word word;
194 CPVT_Line line;
195 if (pIterator->GetWord(word) && pIterator->GetLine(line)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700196 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 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700203
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700204 return sRet.GetByteString();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700205}