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
11CFX_ByteString GetPDFWordString(IFX_Edit_FontMap * pFontMap, FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord)
12{
13	ASSERT (pFontMap != NULL);
14
15	CFX_ByteString sWord;
16
17	if (CPDF_Font * pPDFFont = pFontMap->GetPDFFont(nFontIndex))
18	{
19		if (SubWord > 0)
20		{
21			Word = SubWord;
22		}
23		else
24		{
25			FX_DWORD dwCharCode = -1;
26
27			if (pPDFFont->IsUnicodeCompatible())
28				dwCharCode = pPDFFont->CharCodeFromUnicode(Word);
29			else
30				dwCharCode = pFontMap->CharCodeFromUnicode(nFontIndex, Word);
31
32			if (dwCharCode > 0 )
33			{
34				pPDFFont->AppendChar(sWord, dwCharCode);
35				return sWord;
36			}
37		}
38
39		pPDFFont->AppendChar(sWord, Word);
40	}
41
42	return sWord;
43}
44
45static CFX_ByteString GetWordRenderString(const CFX_ByteString & strWords)
46{
47	if (strWords.GetLength() > 0)
48		return PDF_EncodeString(strWords) + " Tj\n";
49
50	return "";
51}
52
53static CFX_ByteString GetFontSetString(IFX_Edit_FontMap * pFontMap, FX_INT32 nFontIndex, FX_FLOAT fFontSize)
54{
55	CFX_ByteTextBuf sRet;
56
57	if (pFontMap)
58	{
59		CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex);
60
61		if (sFontAlias.GetLength() > 0 && fFontSize > 0 )
62			sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n";
63	}
64
65	return sRet.GetByteString();
66}
67
68CFX_ByteString IFX_Edit::GetEditAppearanceStream(IFX_Edit* pEdit, const CPDF_Point & ptOffset,
69												 const CPVT_WordRange * pRange /* = NULL*/, FX_BOOL bContinuous/* = TRUE*/, FX_WORD SubWord/* = 0*/)
70{
71	CFX_ByteTextBuf sEditStream, sWords;
72
73	CPDF_Point ptOld(0.0f,0.0f),ptNew(0.0f,0.0f);
74	FX_INT32 nCurFontIndex = -1;
75
76	if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
77	{
78		if (pRange)
79			pIterator->SetAt(pRange->BeginPos);
80		else
81			pIterator->SetAt(0);
82
83		CPVT_WordPlace oldplace;
84
85		while (pIterator->NextWord())
86		{
87			CPVT_WordPlace place = pIterator->GetAt();
88
89			if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
90
91			if (bContinuous)
92			{
93				if (place.LineCmp(oldplace) != 0)
94				{
95					if (sWords.GetSize() > 0)
96					{
97						sEditStream << GetWordRenderString(sWords.GetByteString());
98						sWords.Clear();
99					}
100
101					CPVT_Word word;
102					if (pIterator->GetWord(word))
103					{
104						ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
105					}
106					else
107					{
108						CPVT_Line line;
109						pIterator->GetLine(line);
110						ptNew = CPDF_Point(line.ptLine.x + ptOffset.x, line.ptLine.y + ptOffset.y);
111					}
112
113					if (ptNew.x != ptOld.x || ptNew.y != ptOld.y)
114					{
115						sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " Td\n";
116
117						ptOld = ptNew;
118					}
119				}
120
121				CPVT_Word word;
122				if (pIterator->GetWord(word))
123				{
124					if (word.nFontIndex != nCurFontIndex)
125					{
126						if (sWords.GetSize() > 0)
127						{
128							sEditStream << GetWordRenderString(sWords.GetByteString());
129							sWords.Clear();
130						}
131						sEditStream << GetFontSetString(pEdit->GetFontMap(),word.nFontIndex,word.fFontSize);
132						nCurFontIndex = word.nFontIndex;
133					}
134
135					sWords << GetPDFWordString(pEdit->GetFontMap(),nCurFontIndex,word.Word,SubWord);
136				}
137
138				oldplace = place;
139			}
140			else
141			{
142				CPVT_Word word;
143				if (pIterator->GetWord(word))
144				{
145					ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
146
147					if (ptNew.x != ptOld.x || ptNew.y != ptOld.y)
148					{
149						sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " Td\n";
150						ptOld = ptNew;
151					}
152
153					if (word.nFontIndex != nCurFontIndex)
154					{
155						sEditStream << GetFontSetString(pEdit->GetFontMap(),word.nFontIndex,word.fFontSize);
156						nCurFontIndex = word.nFontIndex;
157					}
158
159					sEditStream << GetWordRenderString(GetPDFWordString(pEdit->GetFontMap(),nCurFontIndex,word.Word,SubWord));
160				}
161			}
162		}
163
164		if (sWords.GetSize() > 0)
165		{
166			sEditStream << GetWordRenderString(sWords.GetByteString());
167			sWords.Clear();
168		}
169	}
170
171	CFX_ByteTextBuf sAppStream;
172	if (sEditStream.GetSize() > 0)
173	{
174		FX_INT32 nHorzScale = pEdit->GetHorzScale();
175		if (nHorzScale != 100)
176		{
177			sAppStream << nHorzScale << " Tz\n";
178		}
179
180		FX_FLOAT fCharSpace = pEdit->GetCharSpace();
181		if (!FX_EDIT_IsFloatZero(fCharSpace))
182		{
183			sAppStream << fCharSpace << " Tc\n";
184		}
185
186		sAppStream << sEditStream;
187	}
188
189	return sAppStream.GetByteString();
190}
191
192CFX_ByteString IFX_Edit::GetSelectAppearanceStream(IFX_Edit* pEdit, const CPDF_Point & ptOffset,
193							const CPVT_WordRange * pRange /*= NULL*/)
194{
195	CFX_ByteTextBuf sRet;
196
197	if (pRange && pRange->IsExist())
198	{
199		if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator())
200		{
201			pIterator->SetAt(pRange->BeginPos);
202
203			while (pIterator->NextWord())
204			{
205				CPVT_WordPlace place = pIterator->GetAt();
206
207				if (pRange && place.WordCmp(pRange->EndPos) > 0) break;
208
209				CPVT_Word word;
210				CPVT_Line line;
211				if (pIterator->GetWord(word) && pIterator->GetLine(line))
212				{
213					//CPDF_Rect rcWordSel = CPDF_Rect(word.ptWord.x,line.ptLine.y + line.fLineDescent,
214					//		word.ptWord.x+word.fWidth,line.ptLine.y + line.fLineAscent);
215
216					sRet << word.ptWord.x + ptOffset.x << " " << line.ptLine.y + line.fLineDescent
217						<< " " << word.fWidth << " " << line.fLineAscent - line.fLineDescent << " re\nf\n";
218				}
219			}
220		}
221	}
222
223	return sRet.GetByteString();
224}
225
226