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/fpdfdoc/fpdf_doc.h"
8 #include "../../include/fpdfdoc/fpdf_vt.h"
9 #include "pdf_vt.h"
10 const FX_BYTE gFontSizeSteps[] = { 4, 6, 8, 9, 10, 12, 14, 18, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90, 100, 110, 120, 130, 144};
11 #define PVT_RETURN_LENGTH 1
12 #define PVT_DEFAULT_FONTSIZE 18.0f
13 #define PVTWORD_SCRIPT_NORMAL 0
14 #define PVTWORD_SCRIPT_SUPER 1
15 #define PVTWORD_SCRIPT_SUB 2
16 #define PVT_FONTSCALE 0.001f
17 #define PVT_PERCENT 0.01f
18 #define PVT_HALF 0.5f
CLine()19 CLine::CLine()
20 {
21 }
~CLine()22 CLine::~CLine()
23 {
24 }
GetBeginWordPlace() const25 CPVT_WordPlace CLine::GetBeginWordPlace() const
26 {
27 return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, -1);
28 }
GetEndWordPlace() const29 CPVT_WordPlace CLine::GetEndWordPlace() const
30 {
31 return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, m_LineInfo.nEndWordIndex);
32 }
GetPrevWordPlace(const CPVT_WordPlace & place) const33 CPVT_WordPlace CLine::GetPrevWordPlace(const CPVT_WordPlace & place) const
34 {
35 if (place.nWordIndex > m_LineInfo.nEndWordIndex) {
36 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, m_LineInfo.nEndWordIndex);
37 }
38 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, place.nWordIndex - 1);
39 }
GetNextWordPlace(const CPVT_WordPlace & place) const40 CPVT_WordPlace CLine::GetNextWordPlace(const CPVT_WordPlace & place) const
41 {
42 if (place.nWordIndex < m_LineInfo.nBeginWordIndex) {
43 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, m_LineInfo.nBeginWordIndex);
44 }
45 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, place.nWordIndex + 1);
46 }
CSection(CPDF_VariableText * pVT)47 CSection::CSection(CPDF_VariableText * pVT) : m_pVT(pVT)
48 {
49 }
~CSection()50 CSection::~CSection()
51 {
52 ResetAll();
53 }
ResetAll()54 void CSection::ResetAll()
55 {
56 ResetWordArray();
57 ResetLineArray();
58 }
ResetLineArray()59 void CSection::ResetLineArray()
60 {
61 m_LineArray.RemoveAll();
62 }
ResetWordArray()63 void CSection::ResetWordArray()
64 {
65 for (FX_INT32 i = 0, sz = m_WordArray.GetSize(); i < sz; i++) {
66 delete m_WordArray.GetAt(i);
67 }
68 m_WordArray.RemoveAll();
69 }
ResetLinePlace()70 void CSection::ResetLinePlace()
71 {
72 for (FX_INT32 i = 0, sz = m_LineArray.GetSize(); i < sz; i++) {
73 if (CLine * pLine = m_LineArray.GetAt(i)) {
74 pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1);
75 }
76 }
77 }
AddWord(const CPVT_WordPlace & place,const CPVT_WordInfo & wordinfo)78 CPVT_WordPlace CSection::AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
79 {
80 if (CPVT_WordInfo * pWord = FX_NEW CPVT_WordInfo(wordinfo)) {
81 FX_INT32 nWordIndex = FPDF_MAX(FPDF_MIN(place.nWordIndex, this->m_WordArray.GetSize()), 0);
82 if (nWordIndex == m_WordArray.GetSize()) {
83 m_WordArray.Add(pWord);
84 } else {
85 m_WordArray.InsertAt(nWordIndex, pWord);
86 }
87 }
88 return place;
89 }
AddLine(const CPVT_LineInfo & lineinfo)90 CPVT_WordPlace CSection::AddLine(const CPVT_LineInfo & lineinfo)
91 {
92 return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.Add(lineinfo), -1);
93 }
Rearrange()94 CPVT_FloatRect CSection::Rearrange()
95 {
96 ASSERT(m_pVT != NULL);
97 if (m_pVT->m_nCharArray > 0) {
98 return CTypeset(this).CharArray();
99 } else {
100 return CTypeset(this).Typeset();
101 }
102 }
GetSectionSize(FX_FLOAT fFontSize)103 CPVT_Size CSection::GetSectionSize(FX_FLOAT fFontSize)
104 {
105 return CTypeset(this).GetEditSize(fFontSize);
106 }
GetBeginWordPlace() const107 CPVT_WordPlace CSection::GetBeginWordPlace() const
108 {
109 if (CLine * pLine = m_LineArray.GetAt(0)) {
110 return pLine->GetBeginWordPlace();
111 } else {
112 return SecPlace;
113 }
114 }
GetEndWordPlace() const115 CPVT_WordPlace CSection::GetEndWordPlace() const
116 {
117 if (CLine * pLine = m_LineArray.GetAt(m_LineArray.GetSize() - 1)) {
118 return pLine->GetEndWordPlace();
119 } else {
120 return this->SecPlace;
121 }
122 }
GetPrevWordPlace(const CPVT_WordPlace & place) const123 CPVT_WordPlace CSection::GetPrevWordPlace(const CPVT_WordPlace & place) const
124 {
125 if (place.nLineIndex < 0) {
126 return GetBeginWordPlace();
127 }
128 if (place.nLineIndex >= m_LineArray.GetSize()) {
129 return GetEndWordPlace();
130 }
131 if (CLine * pLine = m_LineArray.GetAt(place.nLineIndex)) {
132 if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex) {
133 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
134 } else if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
135 if (CLine * pPrevLine = m_LineArray.GetAt(place.nLineIndex - 1)) {
136 return pPrevLine->GetEndWordPlace();
137 }
138 } else {
139 return pLine->GetPrevWordPlace(place);
140 }
141 }
142 return place;
143 }
GetNextWordPlace(const CPVT_WordPlace & place) const144 CPVT_WordPlace CSection::GetNextWordPlace(const CPVT_WordPlace & place) const
145 {
146 if (place.nLineIndex < 0) {
147 return GetBeginWordPlace();
148 }
149 if (place.nLineIndex >= m_LineArray.GetSize()) {
150 return GetEndWordPlace();
151 }
152 if (CLine * pLine = m_LineArray.GetAt(place.nLineIndex)) {
153 if (place.nWordIndex >= pLine->m_LineInfo.nEndWordIndex) {
154 if (CLine * pNextLine = m_LineArray.GetAt(place.nLineIndex + 1)) {
155 return pNextLine->GetBeginWordPlace();
156 }
157 } else {
158 return pLine->GetNextWordPlace(place);
159 }
160 }
161 return place;
162 }
UpdateWordPlace(CPVT_WordPlace & place) const163 void CSection::UpdateWordPlace(CPVT_WordPlace & place) const
164 {
165 FX_INT32 nLeft = 0;
166 FX_INT32 nRight = m_LineArray.GetSize() - 1;
167 FX_INT32 nMid = (nLeft + nRight) / 2;
168 while (nLeft <= nRight) {
169 if (CLine * pLine = m_LineArray.GetAt(nMid)) {
170 if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
171 nRight = nMid - 1;
172 nMid = (nLeft + nRight) / 2;
173 } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) {
174 nLeft = nMid + 1;
175 nMid = (nLeft + nRight) / 2;
176 } else {
177 place.nLineIndex = nMid;
178 return;
179 }
180 } else {
181 break;
182 }
183 }
184 }
SearchWordPlace(const CPDF_Point & point) const185 CPVT_WordPlace CSection::SearchWordPlace(const CPDF_Point & point) const
186 {
187 ASSERT(m_pVT != NULL);
188 CPVT_WordPlace place = GetBeginWordPlace();
189 FX_BOOL bUp = TRUE;
190 FX_BOOL bDown = TRUE;
191 FX_INT32 nLeft = 0;
192 FX_INT32 nRight = m_LineArray.GetSize() - 1;
193 FX_INT32 nMid = m_LineArray.GetSize() / 2;
194 FX_FLOAT fTop = 0;
195 FX_FLOAT fBottom = 0;
196 while (nLeft <= nRight) {
197 if (CLine * pLine = m_LineArray.GetAt(nMid)) {
198 fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent - m_pVT->GetLineLeading(m_SecInfo);
199 fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent;
200 if (IsFloatBigger(point.y, fTop)) {
201 bUp = FALSE;
202 }
203 if (IsFloatSmaller(point.y, fBottom)) {
204 bDown = FALSE;
205 }
206 if (IsFloatSmaller(point.y, fTop)) {
207 nRight = nMid - 1;
208 nMid = (nLeft + nRight) / 2;
209 continue;
210 } else if (IsFloatBigger(point.y, fBottom)) {
211 nLeft = nMid + 1;
212 nMid = (nLeft + nRight) / 2;
213 continue;
214 } else {
215 place = SearchWordPlace(point.x,
216 CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), pLine->GetEndWordPlace())
217 );
218 place.nLineIndex = nMid;
219 return place;
220 }
221 }
222 }
223 if (bUp) {
224 place = GetBeginWordPlace();
225 }
226 if (bDown) {
227 place = GetEndWordPlace();
228 }
229 return place;
230 }
SearchWordPlace(FX_FLOAT fx,const CPVT_WordPlace & lineplace) const231 CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, const CPVT_WordPlace & lineplace) const
232 {
233 if (CLine * pLine = m_LineArray.GetAt(lineplace.nLineIndex)) {
234 return SearchWordPlace(fx - m_SecInfo.rcSection.left,
235 CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), pLine->GetEndWordPlace()));
236 }
237 return GetBeginWordPlace();
238 }
SearchWordPlace(FX_FLOAT fx,const CPVT_WordRange & range) const239 CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, const CPVT_WordRange & range) const
240 {
241 CPVT_WordPlace wordplace = range.BeginPos;
242 wordplace.nWordIndex = -1;
243 if (!m_pVT) {
244 return wordplace;
245 }
246 FX_INT32 nLeft = range.BeginPos.nWordIndex;
247 FX_INT32 nRight = range.EndPos.nWordIndex + 1;
248 FX_INT32 nMid = (nLeft + nRight) / 2;
249 while (nLeft < nRight) {
250 if (nMid == nLeft) {
251 break;
252 }
253 if (nMid == nRight) {
254 nMid--;
255 break;
256 }
257 if (CPVT_WordInfo * pWord = m_WordArray.GetAt(nMid)) {
258 if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {
259 nLeft = nMid;
260 nMid = (nLeft + nRight) / 2;
261 continue;
262 } else {
263 nRight = nMid;
264 nMid = (nLeft + nRight) / 2;
265 continue;
266 }
267 } else {
268 break;
269 }
270 }
271 if (CPVT_WordInfo * pWord = m_WordArray.GetAt(nMid)) {
272 if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {
273 wordplace.nWordIndex = nMid;
274 }
275 }
276 return wordplace;
277 }
ClearLeftWords(FX_INT32 nWordIndex)278 void CSection::ClearLeftWords(FX_INT32 nWordIndex)
279 {
280 for (FX_INT32 i = nWordIndex; i >= 0; i--) {
281 delete m_WordArray.GetAt(i);
282 m_WordArray.RemoveAt(i);
283 }
284 }
ClearRightWords(FX_INT32 nWordIndex)285 void CSection::ClearRightWords(FX_INT32 nWordIndex)
286 {
287 for (FX_INT32 i = m_WordArray.GetSize() - 1; i > nWordIndex; i--) {
288 delete m_WordArray.GetAt(i);
289 m_WordArray.RemoveAt(i);
290 }
291 }
ClearMidWords(FX_INT32 nBeginIndex,FX_INT32 nEndIndex)292 void CSection::ClearMidWords(FX_INT32 nBeginIndex, FX_INT32 nEndIndex)
293 {
294 for (FX_INT32 i = nEndIndex; i > nBeginIndex; i--) {
295 delete m_WordArray.GetAt(i);
296 m_WordArray.RemoveAt(i);
297 }
298 }
ClearWords(const CPVT_WordRange & PlaceRange)299 void CSection::ClearWords(const CPVT_WordRange & PlaceRange)
300 {
301 CPVT_WordPlace SecBeginPos = GetBeginWordPlace();
302 CPVT_WordPlace SecEndPos = GetEndWordPlace();
303 if (PlaceRange.BeginPos.WordCmp(SecBeginPos) >= 0) {
304 if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
305 ClearMidWords(PlaceRange.BeginPos.nWordIndex, PlaceRange.EndPos.nWordIndex);
306 } else {
307 ClearRightWords(PlaceRange.BeginPos.nWordIndex);
308 }
309 } else if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
310 ClearLeftWords(PlaceRange.EndPos.nWordIndex);
311 } else {
312 ResetWordArray();
313 }
314 }
ClearWord(const CPVT_WordPlace & place)315 void CSection::ClearWord(const CPVT_WordPlace & place)
316 {
317 delete m_WordArray.GetAt(place.nWordIndex);
318 m_WordArray.RemoveAt(place.nWordIndex);
319 }
CTypeset(CSection * pSection)320 CTypeset::CTypeset(CSection * pSection) : m_pSection(pSection), m_pVT(pSection->m_pVT), m_rcRet(0.0f, 0.0f, 0.0f, 0.0f)
321 {
322 }
~CTypeset()323 CTypeset::~CTypeset()
324 {
325 }
CharArray()326 CPVT_FloatRect CTypeset::CharArray()
327 {
328 ASSERT(m_pSection != NULL);
329 ASSERT(m_pVT != NULL);
330 FX_FLOAT fLineAscent = m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());
331 FX_FLOAT fLineDescent = m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());
332 m_rcRet.Default();
333 FX_FLOAT x = 0.0f, y = 0.0f;
334 FX_FLOAT fNextWidth;
335 FX_INT32 nStart = 0;
336 FX_FLOAT fNodeWidth = m_pVT->GetPlateWidth() / (m_pVT->m_nCharArray <= 0 ? 1 : m_pVT->m_nCharArray);
337 if (CLine * pLine = m_pSection->m_LineArray.GetAt(0)) {
338 x = 0.0f;
339 y += m_pVT->GetLineLeading(m_pSection->m_SecInfo);
340 y += fLineAscent;
341 nStart = 0;
342 switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
343 case 0:
344 pLine->m_LineInfo.fLineX = fNodeWidth * PVT_HALF;
345 break;
346 case 1:
347 nStart = (m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize()) / 2;
348 pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;
349 break;
350 case 2:
351 nStart = m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize();
352 pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;
353 break;
354 }
355 for (FX_INT32 w = 0, sz = m_pSection->m_WordArray.GetSize(); w < sz; w++) {
356 if (w >= m_pVT->m_nCharArray) {
357 break;
358 }
359 fNextWidth = 0;
360 if (CPVT_WordInfo * pNextWord = (CPVT_WordInfo *)m_pSection->m_WordArray.GetAt(w + 1)) {
361 pNextWord->fWordTail = 0;
362 fNextWidth = m_pVT->GetWordWidth(*pNextWord);
363 }
364 if (CPVT_WordInfo * pWord = (CPVT_WordInfo *)m_pSection->m_WordArray.GetAt(w)) {
365 pWord->fWordTail = 0;
366 FX_FLOAT fWordWidth = m_pVT->GetWordWidth(*pWord);
367 FX_FLOAT fWordAscent = m_pVT->GetWordAscent(*pWord);
368 FX_FLOAT fWordDescent = m_pVT->GetWordDescent(*pWord);
369 x = (FX_FLOAT)(fNodeWidth * (w + nStart + 0.5) - fWordWidth * PVT_HALF);
370 pWord->fWordX = x;
371 pWord->fWordY = y;
372 if (w == 0) {
373 pLine->m_LineInfo.fLineX = x;
374 }
375 if (w != m_pSection->m_WordArray.GetSize() - 1)
376 pWord->fWordTail = (fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF > 0 ?
377 fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF : 0);
378 else {
379 pWord->fWordTail = 0;
380 }
381 x += fWordWidth;
382 fLineAscent = FPDF_MAX(fLineAscent, fWordAscent);
383 fLineDescent = FPDF_MIN(fLineDescent, fWordDescent);
384 }
385 }
386 pLine->m_LineInfo.nBeginWordIndex = 0;
387 pLine->m_LineInfo.nEndWordIndex = m_pSection->m_WordArray.GetSize() - 1;
388 pLine->m_LineInfo.fLineY = y;
389 pLine->m_LineInfo.fLineWidth = x - pLine->m_LineInfo.fLineX;
390 pLine->m_LineInfo.fLineAscent = fLineAscent;
391 pLine->m_LineInfo.fLineDescent = fLineDescent;
392 y += (-fLineDescent);
393 }
394 return m_rcRet = CPVT_FloatRect(0, 0, x, y);
395 }
GetEditSize(FX_FLOAT fFontSize)396 CPVT_Size CTypeset::GetEditSize(FX_FLOAT fFontSize)
397 {
398 ASSERT(m_pSection != NULL);
399 ASSERT(m_pVT != NULL);
400 SplitLines(FALSE, fFontSize);
401 return CPVT_Size(m_rcRet.Width(), m_rcRet.Height());
402 }
Typeset()403 CPVT_FloatRect CTypeset::Typeset()
404 {
405 ASSERT(m_pSection != NULL);
406 ASSERT(m_pVT != NULL);
407 m_pSection->m_LineArray.Empty();
408 SplitLines(TRUE, 0.0f);
409 m_pSection->m_LineArray.Clear();
410 OutputLines();
411 return m_rcRet;
412 }
413 static int special_chars[128] = {
414 0x0000, 0x000C, 0x0008, 0x000C, 0x0008, 0x0000, 0x0020, 0x0000,
415 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
416 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
417 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
418 0x0000, 0x0008, 0x0008, 0x0000, 0x0010, 0x0000, 0x0000, 0x0028,
419 0x000C, 0x0008, 0x0000, 0x0000, 0x0028, 0x0028, 0x0028, 0x0028,
420 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
421 0x0002, 0x0002, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0008,
422 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
423 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
424 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
425 0x0001, 0x0001, 0x0001, 0x000C, 0x0000, 0x0008, 0x0000, 0x0000,
426 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
427 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
428 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
429 0x0001, 0x0001, 0x0001, 0x000C, 0x0000, 0x0008, 0x0000, 0x0000,
430 };
IsLatin(FX_WORD word)431 static FX_BOOL IsLatin(FX_WORD word)
432 {
433 if (word <= 0x007F) {
434 if (special_chars[word] & 0x0001) {
435 return TRUE;
436 }
437 }
438 if ((word >= 0x00C0 && word <= 0x00FF) ||
439 (word >= 0x0100 && word <= 0x024F) ||
440 (word >= 0x1E00 && word <= 0x1EFF) ||
441 (word >= 0x2C60 && word <= 0x2C7F) ||
442 (word >= 0xA720 && word <= 0xA7FF) ||
443 (word >= 0xFF21 && word <= 0xFF3A) ||
444 (word >= 0xFF41 && word <= 0xFF5A)) {
445 return TRUE;
446 }
447 return FALSE;
448 }
IsDigit(FX_DWORD word)449 static FX_BOOL IsDigit(FX_DWORD word)
450 {
451 return (word >= 0x0030 && word <= 0x0039) ? TRUE : FALSE;
452 }
IsCJK(FX_DWORD word)453 static FX_BOOL IsCJK(FX_DWORD word)
454 {
455 if ((word >= 0x1100 && word <= 0x11FF) ||
456 (word >= 0x2E80 && word <= 0x2FFF) ||
457 (word >= 0x3040 && word <= 0x9FBF) ||
458 (word >= 0xAC00 && word <= 0xD7AF) ||
459 (word >= 0xF900 && word <= 0xFAFF) ||
460 (word >= 0xFE30 && word <= 0xFE4F) ||
461 (word >= 0x20000 && word <= 0x2A6DF) ||
462 (word >= 0x2F800 && word <= 0x2FA1F)) {
463 return TRUE;
464 }
465 if (word >= 0x3000 && word <= 0x303F) {
466 if (word == 0x3005 || word == 0x3006 || word == 0x3021 || word == 0x3022 ||
467 word == 0x3023 || word == 0x3024 || word == 0x3025 || word == 0x3026 ||
468 word == 0x3027 || word == 0x3028 || word == 0x3029 || word == 0x3031 ||
469 word == 0x3032 || word == 0x3033 || word == 0x3034 || word == 0x3035) {
470 return TRUE;
471 }
472 return FALSE;
473 }
474 if (word >= 0xFF66 && word <= 0xFF9D) {
475 return TRUE;
476 }
477 return FALSE;
478 }
IsPunctuation(FX_DWORD word)479 static FX_BOOL IsPunctuation(FX_DWORD word)
480 {
481 if (word <= 0x007F) {
482 if ((special_chars[word] >> 3) & 1) {
483 return TRUE;
484 }
485 } else if (word >= 0x0080 && word <= 0x00FF) {
486 if (word == 0x0082 || word == 0x0084 || word == 0x0085 || word == 0x0091 ||
487 word == 0x0092 || word == 0x0093 || word <= 0x0094 || word == 0x0096 ||
488 word == 0x00B4 || word == 0x00B8) {
489 return TRUE;
490 }
491 } else if (word >= 0x2000 && word <= 0x206F) {
492 if (word == 0x2010 || word == 0x2011 || word == 0x2012 || word == 0x2013 ||
493 word == 0x2018 || word == 0x2019 || word == 0x201A || word == 0x201B ||
494 word == 0x201C || word == 0x201D || word == 0x201E || word == 0x201F ||
495 word == 0x2032 || word == 0x2033 || word == 0x2034 || word == 0x2035 ||
496 word == 0x2036 || word == 0x2037 || word == 0x203C || word == 0x203D ||
497 word == 0x203E || word == 0x2044) {
498 return TRUE;
499 }
500 } else if (word >= 0x3000 && word <= 0x303F) {
501 if (word == 0x3001 || word == 0x3002 || word == 0x3003 || word == 0x3005 ||
502 word == 0x3009 || word == 0x300A || word == 0x300B || word == 0x300C ||
503 word == 0x300D || word == 0x300F || word == 0x300E || word == 0x3010 ||
504 word == 0x3011 || word == 0x3014 || word == 0x3015 || word == 0x3016 ||
505 word == 0x3017 || word == 0x3018 || word == 0x3019 || word == 0x301A ||
506 word == 0x301B || word == 0x301D || word == 0x301E || word == 0x301F) {
507 return TRUE;
508 }
509 } else if (word >= 0xFE50 && word <= 0xFE6F) {
510 if ((word >= 0xFE50 && word <= 0xFE5E) || word == 0xFE63) {
511 return TRUE;
512 }
513 } else if (word >= 0xFF00 && word <= 0xFFEF) {
514 if (word == 0xFF01 || word == 0xFF02 || word == 0xFF07 || word == 0xFF08 ||
515 word == 0xFF09 || word == 0xFF0C || word == 0xFF0E || word == 0xFF0F ||
516 word == 0xFF1A || word == 0xFF1B || word == 0xFF1F || word == 0xFF3B ||
517 word == 0xFF3D || word == 0xFF40 || word == 0xFF5B || word == 0xFF5C ||
518 word == 0xFF5D || word == 0xFF61 || word == 0xFF62 || word == 0xFF63 ||
519 word == 0xFF64 || word == 0xFF65 || word == 0xFF9E || word == 0xFF9F) {
520 return TRUE;
521 }
522 }
523 return FALSE;
524 }
IsConnectiveSymbol(FX_DWORD word)525 static FX_BOOL IsConnectiveSymbol(FX_DWORD word)
526 {
527 if (word <= 0x007F) {
528 if ((special_chars[word] >> 5) & 1) {
529 return TRUE;
530 }
531 }
532 return FALSE;
533 }
IsOpenStylePunctuation(FX_DWORD word)534 static FX_BOOL IsOpenStylePunctuation(FX_DWORD word)
535 {
536 if (word <= 0x007F) {
537 if ((special_chars[word] >> 2) & 1) {
538 return TRUE;
539 }
540 } else if (word == 0x300A || word == 0x300C || word == 0x300E || word == 0x3010 ||
541 word == 0x3014 || word == 0x3016 || word == 0x3018 || word == 0x301A ||
542 word == 0xFF08 || word == 0xFF3B || word == 0xFF5B || word == 0xFF62) {
543 return TRUE;
544 }
545 return FALSE;
546 }
IsCurrencySymbol(FX_WORD word)547 static FX_BOOL IsCurrencySymbol(FX_WORD word)
548 {
549 if (word == 0x0024 || word == 0x0080 || word == 0x00A2 || word == 0x00A3 ||
550 word == 0x00A4 || word == 0x00A5 || (word >= 0x20A0 && word <= 0x20CF) ||
551 word == 0xFE69 || word == 0xFF04 || word == 0xFFE0 || word == 0xFFE1 ||
552 word == 0xFFE5 || word == 0xFFE6) {
553 return TRUE;
554 }
555 return FALSE;
556 }
IsPrefixSymbol(FX_WORD word)557 static FX_BOOL IsPrefixSymbol(FX_WORD word)
558 {
559 if (IsCurrencySymbol(word)) {
560 return TRUE;
561 }
562 if (word == 0x2116) {
563 return TRUE;
564 }
565 return FALSE;
566 }
IsSpace(FX_WORD word)567 static FX_BOOL IsSpace(FX_WORD word)
568 {
569 return (word == 0x0020 || word == 0x3000) ? TRUE : FALSE;
570 }
NeedDivision(FX_WORD prevWord,FX_WORD curWord)571 static FX_BOOL NeedDivision(FX_WORD prevWord, FX_WORD curWord)
572 {
573 if ((IsLatin(prevWord) || IsDigit(prevWord)) && (IsLatin(curWord) || IsDigit(curWord))) {
574 return FALSE;
575 } else if (IsSpace(curWord) || IsPunctuation(curWord)) {
576 return FALSE;
577 } else if (IsConnectiveSymbol(prevWord) || IsConnectiveSymbol(curWord)) {
578 return FALSE;
579 } else if (IsSpace(prevWord) || IsPunctuation(prevWord)) {
580 return TRUE;
581 } else if (IsPrefixSymbol(prevWord)) {
582 return FALSE;
583 } else if (IsPrefixSymbol(curWord) || IsCJK(curWord)) {
584 return TRUE;
585 } else if (IsCJK(prevWord)) {
586 return TRUE;
587 }
588 return FALSE;
589 }
SplitLines(FX_BOOL bTypeset,FX_FLOAT fFontSize)590 void CTypeset::SplitLines(FX_BOOL bTypeset, FX_FLOAT fFontSize)
591 {
592 ASSERT(m_pVT != NULL);
593 ASSERT(m_pSection != NULL);
594 FX_INT32 nLineHead = 0;
595 FX_INT32 nLineTail = 0;
596 FX_FLOAT fMaxX = 0.0f, fMaxY = 0.0f;
597 FX_FLOAT fLineWidth = 0.0f, fBackupLineWidth = 0.0f;
598 FX_FLOAT fLineAscent = 0.0f, fBackupLineAscent = 0.0f;
599 FX_FLOAT fLineDescent = 0.0f, fBackupLineDescent = 0.0f;
600 FX_INT32 nWordStartPos = 0;
601 FX_BOOL bFullWord = FALSE;
602 FX_INT32 nLineFullWordIndex = 0;
603 FX_INT32 nCharIndex = 0;
604 CPVT_LineInfo line;
605 FX_FLOAT fWordWidth = 0;
606 FX_FLOAT fTypesetWidth = FPDF_MAX(m_pVT->GetPlateWidth() - m_pVT->GetLineIndent(m_pSection->m_SecInfo), 0.0f);
607 FX_INT32 nTotalWords = m_pSection->m_WordArray.GetSize();
608 FX_BOOL bOpened = FALSE;
609 if (nTotalWords > 0) {
610 FX_INT32 i = 0;
611 while (i < nTotalWords) {
612 CPVT_WordInfo * pWord = m_pSection->m_WordArray.GetAt(i);
613 CPVT_WordInfo* pOldWord = pWord;
614 if (i > 0) {
615 pOldWord = m_pSection->m_WordArray.GetAt(i - 1);
616 }
617 if (pWord) {
618 if (bTypeset) {
619 fLineAscent = FPDF_MAX(fLineAscent, m_pVT->GetWordAscent(*pWord, TRUE));
620 fLineDescent = FPDF_MIN(fLineDescent, m_pVT->GetWordDescent(*pWord, TRUE));
621 fWordWidth = m_pVT->GetWordWidth(*pWord);
622 } else {
623 fLineAscent = FPDF_MAX(fLineAscent, m_pVT->GetWordAscent(*pWord, fFontSize));
624 fLineDescent = FPDF_MIN(fLineDescent, m_pVT->GetWordDescent(*pWord, fFontSize));
625 fWordWidth = m_pVT->GetWordWidth(pWord->nFontIndex,
626 pWord->Word,
627 m_pVT->m_wSubWord,
628 m_pVT->m_fCharSpace,
629 m_pVT->m_nHorzScale,
630 fFontSize,
631 pWord->fWordTail,
632 0);
633 }
634 if (!bOpened) {
635 if (IsOpenStylePunctuation(pWord->Word)) {
636 bOpened = TRUE;
637 bFullWord = TRUE;
638 } else if (pOldWord != NULL) {
639 if (NeedDivision(pOldWord->Word, pWord->Word)) {
640 bFullWord = TRUE;
641 }
642 }
643 } else {
644 if (!IsSpace(pWord->Word) && !IsOpenStylePunctuation(pWord->Word)) {
645 bOpened = FALSE;
646 }
647 }
648 if (bFullWord) {
649 bFullWord = FALSE;
650 if (nCharIndex > 0) {
651 nLineFullWordIndex ++;
652 }
653 nWordStartPos = i;
654 fBackupLineWidth = fLineWidth;
655 fBackupLineAscent = fLineAscent;
656 fBackupLineDescent = fLineDescent;
657 }
658 nCharIndex++;
659 }
660 if (m_pVT->m_bLimitWidth && fTypesetWidth > 0 &&
661 fLineWidth + fWordWidth > fTypesetWidth) {
662 if (nLineFullWordIndex > 0) {
663 i = nWordStartPos;
664 fLineWidth = fBackupLineWidth;
665 fLineAscent = fBackupLineAscent;
666 fLineDescent = fBackupLineDescent;
667 }
668 if (nCharIndex == 1) {
669 fLineWidth = fWordWidth;
670 i++;
671 }
672 nLineTail = i - 1;
673 if (bTypeset) {
674 line.nBeginWordIndex = nLineHead;
675 line.nEndWordIndex = nLineTail;
676 line.nTotalWord = nLineTail - nLineHead + 1;
677 line.fLineWidth = fLineWidth;
678 line.fLineAscent = fLineAscent;
679 line.fLineDescent = fLineDescent;
680 m_pSection->AddLine(line);
681 }
682 fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo));
683 fMaxY += (-fLineDescent);
684 fMaxX = FPDF_MAX(fLineWidth, fMaxX);
685 nLineHead = i;
686 fLineWidth = 0.0f;
687 fLineAscent = 0.0f;
688 fLineDescent = 0.0f;
689 nCharIndex = 0;
690 nLineFullWordIndex = 0;
691 bFullWord = FALSE;
692 } else {
693 fLineWidth += fWordWidth;
694 i++;
695 }
696 }
697 if (nLineHead <= nTotalWords - 1) {
698 nLineTail = nTotalWords - 1;
699 if (bTypeset) {
700 line.nBeginWordIndex = nLineHead;
701 line.nEndWordIndex = nLineTail;
702 line.nTotalWord = nLineTail - nLineHead + 1;
703 line.fLineWidth = fLineWidth;
704 line.fLineAscent = fLineAscent;
705 line.fLineDescent = fLineDescent;
706 m_pSection->AddLine(line);
707 }
708 fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo));
709 fMaxY += (-fLineDescent);
710 fMaxX = FPDF_MAX(fLineWidth, fMaxX);
711 }
712 } else {
713 if (bTypeset) {
714 fLineAscent = m_pVT->GetLineAscent(m_pSection->m_SecInfo);
715 fLineDescent = m_pVT->GetLineDescent(m_pSection->m_SecInfo);
716 } else {
717 fLineAscent = m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), fFontSize);
718 fLineDescent = m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), fFontSize);
719 }
720 if (bTypeset) {
721 line.nBeginWordIndex = -1;
722 line.nEndWordIndex = -1;
723 line.nTotalWord = 0;
724 line.fLineWidth = 0;
725 line.fLineAscent = fLineAscent;
726 line.fLineDescent = fLineDescent;
727 m_pSection->AddLine(line);
728 }
729 fMaxY += (m_pVT->GetLineLeading(m_pSection->m_SecInfo) + fLineAscent + (-fLineDescent));
730 }
731 m_rcRet = CPVT_FloatRect(0, 0, fMaxX, fMaxY);
732 }
OutputLines()733 void CTypeset::OutputLines()
734 {
735 ASSERT(m_pVT != NULL);
736 ASSERT(m_pSection != NULL);
737 FX_FLOAT fMinX = 0.0f, fMinY = 0.0f, fMaxX = 0.0f, fMaxY = 0.0f;
738 FX_FLOAT fPosX = 0.0f, fPosY = 0.0f;
739 FX_FLOAT fLineIndent = m_pVT->GetLineIndent(m_pSection->m_SecInfo);
740 FX_FLOAT fTypesetWidth = FPDF_MAX(m_pVT->GetPlateWidth() - fLineIndent, 0.0f);
741 switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
742 default:
743 case 0:
744 fMinX = 0.0f;
745 break;
746 case 1:
747 fMinX = (fTypesetWidth - m_rcRet.Width()) * PVT_HALF;
748 break;
749 case 2:
750 fMinX = fTypesetWidth - m_rcRet.Width();
751 break;
752 }
753 fMaxX = fMinX + m_rcRet.Width();
754 fMinY = 0.0f;
755 fMaxY = m_rcRet.Height();
756 FX_INT32 nTotalLines = m_pSection->m_LineArray.GetSize();
757 if (nTotalLines > 0) {
758 m_pSection->m_SecInfo.nTotalLine = nTotalLines;
759 for (FX_INT32 l = 0; l < nTotalLines; l++) {
760 if (CLine * pLine = m_pSection->m_LineArray.GetAt(l)) {
761 switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
762 default:
763 case 0:
764 fPosX = 0;
765 break;
766 case 1:
767 fPosX = (fTypesetWidth - pLine->m_LineInfo.fLineWidth) * PVT_HALF;
768 break;
769 case 2:
770 fPosX = fTypesetWidth - pLine->m_LineInfo.fLineWidth;
771 break;
772 }
773 fPosX += fLineIndent;
774 fPosY += m_pVT->GetLineLeading(m_pSection->m_SecInfo);
775 fPosY += pLine->m_LineInfo.fLineAscent;
776 pLine->m_LineInfo.fLineX = fPosX - fMinX;
777 pLine->m_LineInfo.fLineY = fPosY - fMinY;
778 for (FX_INT32 w = pLine->m_LineInfo.nBeginWordIndex; w <= pLine->m_LineInfo.nEndWordIndex; w++) {
779 if (CPVT_WordInfo * pWord = m_pSection->m_WordArray.GetAt(w)) {
780 pWord->fWordX = fPosX - fMinX;
781 if (pWord->pWordProps) {
782 switch (pWord->pWordProps->nScriptType) {
783 default:
784 case PVTWORD_SCRIPT_NORMAL:
785 pWord->fWordY = fPosY - fMinY;
786 break;
787 case PVTWORD_SCRIPT_SUPER:
788 pWord->fWordY = fPosY - m_pVT->GetWordAscent(*pWord) - fMinY;
789 break;
790 case PVTWORD_SCRIPT_SUB:
791 pWord->fWordY = fPosY - m_pVT->GetWordDescent(*pWord) - fMinY;
792 break;
793 }
794 } else {
795 pWord->fWordY = fPosY - fMinY;
796 }
797 fPosX += m_pVT->GetWordWidth(*pWord);
798 }
799 }
800 fPosY += (-pLine->m_LineInfo.fLineDescent);
801 }
802 }
803 }
804 m_rcRet = CPVT_FloatRect(fMinX, fMinY, fMaxX, fMaxY);
805 }
CPDF_VariableText()806 CPDF_VariableText::CPDF_VariableText() :
807 m_pVTProvider(NULL),
808 m_pVTIterator(NULL),
809 m_bInitial(FALSE),
810 m_bRichText(FALSE),
811 m_bMultiLine(FALSE),
812 m_bLimitWidth(FALSE),
813 m_bAutoFontSize(FALSE),
814 m_nLimitChar(0),
815 m_nCharArray(0),
816 m_nAlignment(0),
817 m_fCharSpace(0.0f),
818 m_fWordSpace(0.0f),
819 m_fFontSize(0.0f),
820 m_nHorzScale(100),
821 m_wSubWord(0),
822 m_fLineLeading(0.0f)
823 {
824 }
~CPDF_VariableText()825 CPDF_VariableText::~CPDF_VariableText()
826 {
827 if (m_pVTIterator) {
828 delete m_pVTIterator;
829 m_pVTIterator = NULL;
830 }
831 ResetAll();
832 }
Initialize()833 void CPDF_VariableText::Initialize()
834 {
835 if (!m_bInitial) {
836 CPVT_SectionInfo secinfo;
837 if (m_bRichText) {
838 secinfo.pSecProps = FX_NEW CPVT_SecProps(0.0f, 0.0f, 0);
839 secinfo.pWordProps = FX_NEW CPVT_WordProps(GetDefaultFontIndex(), PVT_DEFAULT_FONTSIZE, 0, 0, 0);
840 }
841 CPVT_WordPlace place;
842 place.nSecIndex = 0;
843 AddSection(place, secinfo);
844 CPVT_LineInfo lineinfo;
845 lineinfo.fLineAscent = GetFontAscent(GetDefaultFontIndex(), GetFontSize());
846 lineinfo.fLineDescent = GetFontDescent(GetDefaultFontIndex(), GetFontSize());
847 AddLine(place, lineinfo);
848 if (CSection * pSection = m_SectionArray.GetAt(0)) {
849 pSection->ResetLinePlace();
850 }
851 m_bInitial = TRUE;
852 }
853 }
ResetAll()854 void CPDF_VariableText::ResetAll()
855 {
856 m_bInitial = FALSE;
857 ResetSectionArray();
858 }
InsertWord(const CPVT_WordPlace & place,FX_WORD word,FX_INT32 charset,const CPVT_WordProps * pWordProps)859 CPVT_WordPlace CPDF_VariableText::InsertWord(const CPVT_WordPlace & place, FX_WORD word, FX_INT32 charset,
860 const CPVT_WordProps * pWordProps)
861 {
862 FX_INT32 nTotlaWords = this->GetTotalWords();
863 if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {
864 return place;
865 }
866 if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {
867 return place;
868 }
869 CPVT_WordPlace newplace = place;
870 newplace.nWordIndex ++;
871 if (m_bRichText) {
872 CPVT_WordProps * pNewProps = pWordProps ? FX_NEW CPVT_WordProps(*pWordProps) : FX_NEW CPVT_WordProps();
873 if (pNewProps) {
874 pNewProps->nFontIndex = GetWordFontIndex(word, charset, pWordProps->nFontIndex);
875 return AddWord(newplace, CPVT_WordInfo(word, charset, -1, pNewProps));
876 }
877 } else {
878 FX_INT32 nFontIndex = GetSubWord() > 0 ? GetDefaultFontIndex() : GetWordFontIndex(word, charset, GetDefaultFontIndex());
879 return AddWord(newplace, CPVT_WordInfo(word, charset, nFontIndex, NULL));
880 }
881 return place;
882 }
InsertSection(const CPVT_WordPlace & place,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)883 CPVT_WordPlace CPDF_VariableText::InsertSection(const CPVT_WordPlace & place, const CPVT_SecProps * pSecProps,
884 const CPVT_WordProps * pWordProps)
885 {
886 FX_INT32 nTotlaWords = this->GetTotalWords();
887 if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {
888 return place;
889 }
890 if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {
891 return place;
892 }
893 if (!m_bMultiLine) {
894 return place;
895 }
896 CPVT_WordPlace wordplace = place;
897 UpdateWordPlace(wordplace);
898 CPVT_WordPlace newplace = place;
899 if (CSection * pSection = m_SectionArray.GetAt(wordplace.nSecIndex)) {
900 CPVT_WordPlace NewPlace(wordplace.nSecIndex + 1, 0, -1);
901 CPVT_SectionInfo secinfo;
902 if (m_bRichText) {
903 if (pSecProps) {
904 secinfo.pSecProps = FX_NEW CPVT_SecProps(*pSecProps);
905 }
906 if (pWordProps) {
907 secinfo.pWordProps = FX_NEW CPVT_WordProps(*pWordProps);
908 }
909 }
910 AddSection(NewPlace, secinfo);
911 newplace = NewPlace;
912 if (CSection * pNewSection = m_SectionArray.GetAt(NewPlace.nSecIndex)) {
913 for (FX_INT32 w = wordplace.nWordIndex + 1, sz = pSection->m_WordArray.GetSize(); w < sz; w++) {
914 if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(w)) {
915 NewPlace.nWordIndex++;
916 pNewSection->AddWord(NewPlace, *pWord);
917 }
918 }
919 }
920 ClearSectionRightWords(wordplace);
921 }
922 return newplace;
923 }
InsertText(const CPVT_WordPlace & place,FX_LPCWSTR text,FX_INT32 charset,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pProps)924 CPVT_WordPlace CPDF_VariableText::InsertText(const CPVT_WordPlace & place, FX_LPCWSTR text, FX_INT32 charset,
925 const CPVT_SecProps * pSecProps, const CPVT_WordProps * pProps)
926 {
927 CFX_WideString swText = text;
928 CPVT_WordPlace wp = place;
929 for (FX_INT32 i = 0, sz = swText.GetLength(); i < sz; i++) {
930 CPVT_WordPlace oldwp = wp;
931 FX_WORD word = swText.GetAt(i);
932 switch (word) {
933 case 0x0D:
934 if (m_bMultiLine) {
935 if (swText.GetAt(i + 1) == 0x0A) {
936 i += 1;
937 }
938 wp = InsertSection(wp, pSecProps, pProps);
939 }
940 break;
941 case 0x0A:
942 if (m_bMultiLine) {
943 if (swText.GetAt(i + 1) == 0x0D) {
944 i += 1;
945 }
946 wp = InsertSection(wp, pSecProps, pProps);
947 }
948 break;
949 case 0x09:
950 word = 0x20;
951 default:
952 wp = InsertWord(wp, word, charset, pProps);
953 break;
954 }
955 if (wp == oldwp) {
956 break;
957 }
958 }
959 return wp;
960 }
DeleteWords(const CPVT_WordRange & PlaceRange)961 CPVT_WordPlace CPDF_VariableText::DeleteWords(const CPVT_WordRange & PlaceRange)
962 {
963 FX_BOOL bLastSecPos = FALSE;
964 if (CSection * pSection = m_SectionArray.GetAt(PlaceRange.EndPos.nSecIndex)) {
965 bLastSecPos = (PlaceRange.EndPos == pSection->GetEndWordPlace());
966 }
967 ClearWords(PlaceRange);
968 if (PlaceRange.BeginPos.nSecIndex != PlaceRange.EndPos.nSecIndex) {
969 ClearEmptySections(PlaceRange);
970 if (!bLastSecPos) {
971 LinkLatterSection(PlaceRange.BeginPos);
972 }
973 }
974 return PlaceRange.BeginPos;
975 }
DeleteWord(const CPVT_WordPlace & place)976 CPVT_WordPlace CPDF_VariableText::DeleteWord(const CPVT_WordPlace & place)
977 {
978 return ClearRightWord(AjustLineHeader(place, TRUE));
979 }
BackSpaceWord(const CPVT_WordPlace & place)980 CPVT_WordPlace CPDF_VariableText::BackSpaceWord(const CPVT_WordPlace & place)
981 {
982 return ClearLeftWord(AjustLineHeader(place, TRUE));
983 }
SetText(FX_LPCWSTR text,FX_INT32 charset,const CPVT_SecProps * pSecProps,const CPVT_WordProps * pWordProps)984 void CPDF_VariableText::SetText(FX_LPCWSTR text, FX_INT32 charset, const CPVT_SecProps * pSecProps,
985 const CPVT_WordProps * pWordProps)
986 {
987 DeleteWords(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
988 CFX_WideString swText = text;
989 CPVT_WordPlace wp(0, 0, -1);
990 CPVT_SectionInfo secinfo;
991 if (m_bRichText) {
992 if (pSecProps) {
993 secinfo.pSecProps = FX_NEW CPVT_SecProps(*pSecProps);
994 }
995 if (pWordProps) {
996 secinfo.pWordProps = FX_NEW CPVT_WordProps(*pWordProps);
997 }
998 }
999 if (CSection * pSection = m_SectionArray.GetAt(0)) {
1000 pSection->m_SecInfo = secinfo;
1001 }
1002 FX_INT32 nCharCount = 0;
1003 for (FX_INT32 i = 0, sz = swText.GetLength(); i < sz; i++) {
1004 if (m_nLimitChar > 0 && nCharCount >= m_nLimitChar) {
1005 break;
1006 }
1007 if (m_nCharArray > 0 && nCharCount >= m_nCharArray) {
1008 break;
1009 }
1010 FX_WORD word = swText.GetAt(i);
1011 switch (word) {
1012 case 0x0D:
1013 if (m_bMultiLine) {
1014 if (swText.GetAt(i + 1) == 0x0A) {
1015 i += 1;
1016 }
1017 wp.nSecIndex ++;
1018 wp.nLineIndex = 0;
1019 wp.nWordIndex = -1;
1020 AddSection(wp, secinfo);
1021 }
1022 break;
1023 case 0x0A:
1024 if (m_bMultiLine) {
1025 if (swText.GetAt(i + 1) == 0x0D) {
1026 i += 1;
1027 }
1028 wp.nSecIndex ++;
1029 wp.nLineIndex = 0;
1030 wp.nWordIndex = -1;
1031 AddSection(wp, secinfo);
1032 }
1033 break;
1034 case 0x09:
1035 word = 0x20;
1036 default:
1037 wp = InsertWord(wp, word, charset, pWordProps);
1038 break;
1039 }
1040 nCharCount++;
1041 }
1042 }
UpdateWordPlace(CPVT_WordPlace & place) const1043 void CPDF_VariableText::UpdateWordPlace(CPVT_WordPlace & place) const
1044 {
1045 if (place.nSecIndex < 0) {
1046 place = GetBeginWordPlace();
1047 }
1048 if (place.nSecIndex >= m_SectionArray.GetSize()) {
1049 place = GetEndWordPlace();
1050 }
1051 place = AjustLineHeader(place, TRUE);
1052 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1053 pSection->UpdateWordPlace(place);
1054 }
1055 }
WordPlaceToWordIndex(const CPVT_WordPlace & place) const1056 FX_INT32 CPDF_VariableText::WordPlaceToWordIndex(const CPVT_WordPlace & place) const
1057 {
1058 CPVT_WordPlace newplace = place;
1059 UpdateWordPlace(newplace);
1060 FX_INT32 nIndex = 0;
1061 FX_INT32 i = 0;
1062 FX_INT32 sz = 0;
1063 for (i = 0, sz = m_SectionArray.GetSize(); i < sz && i < newplace.nSecIndex; i++) {
1064 if (CSection * pSection = m_SectionArray.GetAt(i)) {
1065 nIndex += pSection->m_WordArray.GetSize();
1066 if (i != m_SectionArray.GetSize() - 1) {
1067 nIndex += PVT_RETURN_LENGTH;
1068 }
1069 }
1070 }
1071 if (i >= 0 && i < m_SectionArray.GetSize()) {
1072 nIndex += newplace.nWordIndex + PVT_RETURN_LENGTH;
1073 }
1074 return nIndex;
1075 }
WordIndexToWordPlace(FX_INT32 index) const1076 CPVT_WordPlace CPDF_VariableText::WordIndexToWordPlace(FX_INT32 index) const
1077 {
1078 CPVT_WordPlace place = GetBeginWordPlace();
1079 FX_INT32 nOldIndex = 0 , nIndex = 0;
1080 FX_BOOL bFind = FALSE;
1081 for (FX_INT32 i = 0, sz = m_SectionArray.GetSize(); i < sz; i++) {
1082 if (CSection * pSection = m_SectionArray.GetAt(i)) {
1083 nIndex += pSection->m_WordArray.GetSize();
1084 if (nIndex == index) {
1085 place = pSection->GetEndWordPlace();
1086 bFind = TRUE;
1087 break;
1088 } else if (nIndex > index) {
1089 place.nSecIndex = i;
1090 place.nWordIndex = index - nOldIndex - 1;
1091 pSection->UpdateWordPlace(place);
1092 bFind = TRUE;
1093 break;
1094 }
1095 if (i != m_SectionArray.GetSize() - 1) {
1096 nIndex += PVT_RETURN_LENGTH;
1097 }
1098 nOldIndex = nIndex;
1099 }
1100 }
1101 if (!bFind) {
1102 place = GetEndWordPlace();
1103 }
1104 return place;
1105 }
GetBeginWordPlace() const1106 CPVT_WordPlace CPDF_VariableText::GetBeginWordPlace() const
1107 {
1108 return m_bInitial ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace();
1109 }
GetEndWordPlace() const1110 CPVT_WordPlace CPDF_VariableText::GetEndWordPlace() const
1111 {
1112 if (CSection * pSection = m_SectionArray.GetAt(m_SectionArray.GetSize() - 1)) {
1113 return pSection->GetEndWordPlace();
1114 }
1115 return CPVT_WordPlace();
1116 }
GetPrevWordPlace(const CPVT_WordPlace & place) const1117 CPVT_WordPlace CPDF_VariableText::GetPrevWordPlace(const CPVT_WordPlace & place) const
1118 {
1119 if( place.nSecIndex < 0) {
1120 return GetBeginWordPlace();
1121 }
1122 if (place.nSecIndex >= m_SectionArray.GetSize()) {
1123 return GetEndWordPlace();
1124 }
1125 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1126 if (place.WordCmp(pSection->GetBeginWordPlace()) <= 0) {
1127 if (CSection * pPrevSection = m_SectionArray.GetAt(place.nSecIndex - 1)) {
1128 return pPrevSection->GetEndWordPlace();
1129 } else {
1130 return GetBeginWordPlace();
1131 }
1132 } else {
1133 return pSection->GetPrevWordPlace(place);
1134 }
1135 }
1136 return place;
1137 }
GetNextWordPlace(const CPVT_WordPlace & place) const1138 CPVT_WordPlace CPDF_VariableText::GetNextWordPlace(const CPVT_WordPlace & place) const
1139 {
1140 if (place.nSecIndex < 0) {
1141 return GetBeginWordPlace();
1142 }
1143 if (place.nSecIndex >= m_SectionArray.GetSize()) {
1144 return GetEndWordPlace();
1145 }
1146 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1147 if (place.WordCmp(pSection->GetEndWordPlace()) >= 0) {
1148 if (CSection * pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
1149 return pNextSection->GetBeginWordPlace();
1150 } else {
1151 return GetEndWordPlace();
1152 }
1153 } else {
1154 return pSection->GetNextWordPlace(place);
1155 }
1156 }
1157 return place;
1158 }
SearchWordPlace(const CPDF_Point & point) const1159 CPVT_WordPlace CPDF_VariableText::SearchWordPlace(const CPDF_Point & point) const
1160 {
1161 CPDF_Point pt = OutToIn(point);
1162 CPVT_WordPlace place = GetBeginWordPlace();
1163 FX_INT32 nLeft = 0;
1164 FX_INT32 nRight = m_SectionArray.GetSize() - 1;
1165 FX_INT32 nMid = m_SectionArray.GetSize() / 2;
1166 FX_BOOL bUp = TRUE;
1167 FX_BOOL bDown = TRUE;
1168 while (nLeft <= nRight) {
1169 if (CSection * pSection = m_SectionArray.GetAt(nMid)) {
1170 if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.top)) {
1171 bUp = FALSE;
1172 }
1173 if (IsFloatBigger(pSection->m_SecInfo.rcSection.bottom, pt.y)) {
1174 bDown = FALSE;
1175 }
1176 if (IsFloatSmaller(pt.y, pSection->m_SecInfo.rcSection.top)) {
1177 nRight = nMid - 1;
1178 nMid = (nLeft + nRight) / 2;
1179 continue;
1180 } else if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.bottom)) {
1181 nLeft = nMid + 1;
1182 nMid = (nLeft + nRight) / 2;
1183 continue;
1184 } else {
1185 place = pSection->SearchWordPlace(
1186 CPDF_Point(pt.x - pSection->m_SecInfo.rcSection.left, pt.y - pSection->m_SecInfo.rcSection.top)
1187 );
1188 place.nSecIndex = nMid;
1189 return place;
1190 }
1191 } else {
1192 break;
1193 }
1194 }
1195 if (bUp) {
1196 place = GetBeginWordPlace();
1197 }
1198 if (bDown) {
1199 place = GetEndWordPlace();
1200 }
1201 return place;
1202 }
GetUpWordPlace(const CPVT_WordPlace & place,const CPDF_Point & point) const1203 CPVT_WordPlace CPDF_VariableText::GetUpWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const
1204 {
1205 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1206 CPVT_WordPlace temp = place;
1207 CPDF_Point pt = OutToIn(point);
1208 if (temp.nLineIndex-- > 0) {
1209 return pSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
1210 } else {
1211 if (temp.nSecIndex-- > 0) {
1212 if (CSection * pLastSection = m_SectionArray.GetAt(temp.nSecIndex)) {
1213 temp.nLineIndex = pLastSection->m_LineArray.GetSize() - 1;
1214 return pLastSection->SearchWordPlace(pt.x - pLastSection->m_SecInfo.rcSection.left, temp);
1215 }
1216 }
1217 }
1218 }
1219 return place;
1220 }
GetDownWordPlace(const CPVT_WordPlace & place,const CPDF_Point & point) const1221 CPVT_WordPlace CPDF_VariableText::GetDownWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const
1222 {
1223 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1224 CPVT_WordPlace temp = place;
1225 CPDF_Point pt = OutToIn(point);
1226 if (temp.nLineIndex++ < pSection->m_LineArray.GetSize() - 1) {
1227 return pSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
1228 } else {
1229 if (temp.nSecIndex++ < m_SectionArray.GetSize() - 1) {
1230 if (CSection * pNextSection = m_SectionArray.GetAt(temp.nSecIndex)) {
1231 temp.nLineIndex = 0;
1232 return pNextSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
1233 }
1234 }
1235 }
1236 }
1237 return place;
1238 }
GetLineBeginPlace(const CPVT_WordPlace & place) const1239 CPVT_WordPlace CPDF_VariableText::GetLineBeginPlace(const CPVT_WordPlace & place) const
1240 {
1241 return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
1242 }
GetLineEndPlace(const CPVT_WordPlace & place) const1243 CPVT_WordPlace CPDF_VariableText::GetLineEndPlace(const CPVT_WordPlace & place) const
1244 {
1245 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex))
1246 if (CLine * pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {
1247 return pLine->GetEndWordPlace();
1248 }
1249 return place;
1250 }
GetSectionBeginPlace(const CPVT_WordPlace & place) const1251 CPVT_WordPlace CPDF_VariableText::GetSectionBeginPlace(const CPVT_WordPlace & place) const
1252 {
1253 return CPVT_WordPlace(place.nSecIndex, 0, -1);
1254 }
GetSectionEndPlace(const CPVT_WordPlace & place) const1255 CPVT_WordPlace CPDF_VariableText::GetSectionEndPlace(const CPVT_WordPlace & place) const
1256 {
1257 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1258 return pSection->GetEndWordPlace();
1259 }
1260 return place;
1261 }
GetTotalWords() const1262 FX_INT32 CPDF_VariableText::GetTotalWords() const
1263 {
1264 FX_INT32 nTotal = 0;
1265 for (FX_INT32 i = 0, sz = m_SectionArray.GetSize(); i < sz; i++)
1266 if (CSection * pSection = m_SectionArray.GetAt(i)) {
1267 nTotal += (pSection->m_WordArray.GetSize() + PVT_RETURN_LENGTH);
1268 }
1269 return nTotal - PVT_RETURN_LENGTH;
1270 }
ResetSectionArray()1271 void CPDF_VariableText::ResetSectionArray()
1272 {
1273 for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1274 delete m_SectionArray.GetAt(s);
1275 }
1276 m_SectionArray.RemoveAll();
1277 }
AddSection(const CPVT_WordPlace & place,const CPVT_SectionInfo & secinfo)1278 CPVT_WordPlace CPDF_VariableText::AddSection(const CPVT_WordPlace & place, const CPVT_SectionInfo & secinfo)
1279 {
1280 if (IsValid() && !m_bMultiLine) {
1281 return place;
1282 }
1283 FX_INT32 nSecIndex = FPDF_MAX(FPDF_MIN(place.nSecIndex, m_SectionArray.GetSize()), 0);
1284 CSection * pSection = FX_NEW CSection(this);
1285 if (!pSection) {
1286 return place;
1287 }
1288 pSection->m_SecInfo = secinfo;
1289 pSection->SecPlace.nSecIndex = nSecIndex;
1290 if (nSecIndex == m_SectionArray.GetSize()) {
1291 m_SectionArray.Add(pSection);
1292 } else {
1293 m_SectionArray.InsertAt(nSecIndex, pSection);
1294 }
1295 return place;
1296 }
AddLine(const CPVT_WordPlace & place,const CPVT_LineInfo & lineinfo)1297 CPVT_WordPlace CPDF_VariableText::AddLine(const CPVT_WordPlace & place, const CPVT_LineInfo & lineinfo)
1298 {
1299 if (m_SectionArray.IsEmpty()) {
1300 return place;
1301 }
1302 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1303 return pSection->AddLine(lineinfo);
1304 }
1305 return place;
1306 }
AddWord(const CPVT_WordPlace & place,const CPVT_WordInfo & wordinfo)1307 CPVT_WordPlace CPDF_VariableText::AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
1308 {
1309 if (m_SectionArray.GetSize() <= 0) {
1310 return place;
1311 }
1312 CPVT_WordPlace newplace = place;
1313 newplace.nSecIndex = FPDF_MAX(FPDF_MIN(newplace.nSecIndex, m_SectionArray.GetSize() - 1), 0);
1314 if (CSection * pSection = m_SectionArray.GetAt(newplace.nSecIndex)) {
1315 return pSection->AddWord(newplace, wordinfo);
1316 }
1317 return place;
1318 }
GetWordInfo(const CPVT_WordPlace & place,CPVT_WordInfo & wordinfo)1319 FX_BOOL CPDF_VariableText::GetWordInfo(const CPVT_WordPlace & place, CPVT_WordInfo & wordinfo)
1320 {
1321 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1322 if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
1323 wordinfo = *pWord;
1324 return TRUE;
1325 }
1326 }
1327 return FALSE;
1328 }
SetWordInfo(const CPVT_WordPlace & place,const CPVT_WordInfo & wordinfo)1329 FX_BOOL CPDF_VariableText::SetWordInfo(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
1330 {
1331 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1332 if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
1333 *pWord = wordinfo;
1334 return TRUE;
1335 }
1336 }
1337 return FALSE;
1338 }
GetLineInfo(const CPVT_WordPlace & place,CPVT_LineInfo & lineinfo)1339 FX_BOOL CPDF_VariableText::GetLineInfo(const CPVT_WordPlace & place, CPVT_LineInfo & lineinfo)
1340 {
1341 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1342 if (CLine * pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {
1343 lineinfo = pLine->m_LineInfo;
1344 return TRUE;
1345 }
1346 }
1347 return FALSE;
1348 }
GetSectionInfo(const CPVT_WordPlace & place,CPVT_SectionInfo & secinfo)1349 FX_BOOL CPDF_VariableText::GetSectionInfo(const CPVT_WordPlace & place, CPVT_SectionInfo & secinfo)
1350 {
1351 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1352 secinfo = pSection->m_SecInfo;
1353 return TRUE;
1354 }
1355 return FALSE;
1356 }
GetContentRect() const1357 CPDF_Rect CPDF_VariableText::GetContentRect() const
1358 {
1359 return InToOut(CPDF_EditContainer::GetContentRect());
1360 }
GetWordFontSize(const CPVT_WordInfo & WordInfo,FX_BOOL bFactFontSize)1361 FX_FLOAT CPDF_VariableText::GetWordFontSize(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
1362 {
1363 return m_bRichText && WordInfo.pWordProps ? (WordInfo.pWordProps->nScriptType == PVTWORD_SCRIPT_NORMAL || bFactFontSize ? WordInfo.pWordProps->fFontSize : WordInfo.pWordProps->fFontSize * PVT_HALF) : GetFontSize();
1364 }
GetWordFontIndex(const CPVT_WordInfo & WordInfo)1365 FX_INT32 CPDF_VariableText::GetWordFontIndex(const CPVT_WordInfo & WordInfo)
1366 {
1367 return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nFontIndex : WordInfo.nFontIndex;
1368 }
GetWordWidth(FX_INT32 nFontIndex,FX_WORD Word,FX_WORD SubWord,FX_FLOAT fCharSpace,FX_INT32 nHorzScale,FX_FLOAT fFontSize,FX_FLOAT fWordTail,FX_INT32 nWordStyle)1369 FX_FLOAT CPDF_VariableText::GetWordWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord,
1370 FX_FLOAT fCharSpace, FX_INT32 nHorzScale,
1371 FX_FLOAT fFontSize, FX_FLOAT fWordTail, FX_INT32 nWordStyle)
1372 {
1373 return (GetCharWidth(nFontIndex, Word, SubWord, nWordStyle) * fFontSize * PVT_FONTSCALE + fCharSpace) * nHorzScale * PVT_PERCENT + fWordTail;
1374 }
GetWordWidth(const CPVT_WordInfo & WordInfo)1375 FX_FLOAT CPDF_VariableText::GetWordWidth(const CPVT_WordInfo & WordInfo)
1376 {
1377 return GetWordWidth(GetWordFontIndex(WordInfo), WordInfo.Word, GetSubWord(), GetCharSpace(WordInfo), GetHorzScale(WordInfo),
1378 GetWordFontSize(WordInfo), WordInfo.fWordTail,
1379 WordInfo.pWordProps ? WordInfo.pWordProps->nWordStyle : 0);
1380 }
GetLineAscent(const CPVT_SectionInfo & SecInfo)1381 FX_FLOAT CPDF_VariableText::GetLineAscent(const CPVT_SectionInfo & SecInfo)
1382 {
1383 return m_bRichText && SecInfo.pWordProps ? GetFontAscent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :
1384 GetFontAscent(GetDefaultFontIndex(), GetFontSize());
1385 }
GetLineDescent(const CPVT_SectionInfo & SecInfo)1386 FX_FLOAT CPDF_VariableText::GetLineDescent(const CPVT_SectionInfo & SecInfo)
1387 {
1388 return m_bRichText && SecInfo.pWordProps ? GetFontDescent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :
1389 GetFontDescent(GetDefaultFontIndex(), GetFontSize());
1390 }
GetFontAscent(FX_INT32 nFontIndex,FX_FLOAT fFontSize)1391 FX_FLOAT CPDF_VariableText::GetFontAscent(FX_INT32 nFontIndex, FX_FLOAT fFontSize)
1392 {
1393 return (FX_FLOAT)GetTypeAscent(nFontIndex) * fFontSize * PVT_FONTSCALE;
1394 }
GetFontDescent(FX_INT32 nFontIndex,FX_FLOAT fFontSize)1395 FX_FLOAT CPDF_VariableText::GetFontDescent(FX_INT32 nFontIndex, FX_FLOAT fFontSize)
1396 {
1397 return (FX_FLOAT)GetTypeDescent(nFontIndex) * fFontSize * PVT_FONTSCALE;
1398 }
GetWordAscent(const CPVT_WordInfo & WordInfo,FX_FLOAT fFontSize)1399 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)
1400 {
1401 return GetFontAscent(GetWordFontIndex(WordInfo), fFontSize);
1402 }
GetWordDescent(const CPVT_WordInfo & WordInfo,FX_FLOAT fFontSize)1403 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)
1404 {
1405 return GetFontDescent(GetWordFontIndex(WordInfo), fFontSize);
1406 }
GetWordAscent(const CPVT_WordInfo & WordInfo,FX_BOOL bFactFontSize)1407 FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
1408 {
1409 return GetFontAscent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));
1410 }
GetWordDescent(const CPVT_WordInfo & WordInfo,FX_BOOL bFactFontSize)1411 FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
1412 {
1413 return GetFontDescent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));
1414 }
GetLineLeading(const CPVT_SectionInfo & SecInfo)1415 FX_FLOAT CPDF_VariableText::GetLineLeading(const CPVT_SectionInfo & SecInfo)
1416 {
1417 return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineLeading : m_fLineLeading;
1418 }
GetLineIndent(const CPVT_SectionInfo & SecInfo)1419 FX_FLOAT CPDF_VariableText::GetLineIndent(const CPVT_SectionInfo & SecInfo)
1420 {
1421 return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineIndent : 0.0f;
1422 }
GetAlignment(const CPVT_SectionInfo & SecInfo)1423 FX_INT32 CPDF_VariableText::GetAlignment(const CPVT_SectionInfo& SecInfo)
1424 {
1425 return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->nAlignment : this->m_nAlignment;
1426 }
GetCharSpace(const CPVT_WordInfo & WordInfo)1427 FX_FLOAT CPDF_VariableText::GetCharSpace(const CPVT_WordInfo & WordInfo)
1428 {
1429 return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->fCharSpace : m_fCharSpace;
1430 }
GetHorzScale(const CPVT_WordInfo & WordInfo)1431 FX_INT32 CPDF_VariableText::GetHorzScale(const CPVT_WordInfo & WordInfo)
1432 {
1433 return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nHorzScale : m_nHorzScale;
1434 }
ClearSectionRightWords(const CPVT_WordPlace & place)1435 void CPDF_VariableText::ClearSectionRightWords(const CPVT_WordPlace & place)
1436 {
1437 CPVT_WordPlace wordplace = AjustLineHeader(place, TRUE);
1438 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1439 for (FX_INT32 w = pSection->m_WordArray.GetSize() - 1; w > wordplace.nWordIndex; w--) {
1440 delete pSection->m_WordArray.GetAt(w);
1441 pSection->m_WordArray.RemoveAt(w);
1442 }
1443 }
1444 }
AjustLineHeader(const CPVT_WordPlace & place,FX_BOOL bPrevOrNext) const1445 CPVT_WordPlace CPDF_VariableText::AjustLineHeader(const CPVT_WordPlace & place, FX_BOOL bPrevOrNext) const
1446 {
1447 if (place.nWordIndex < 0 && place.nLineIndex > 0) {
1448 if (bPrevOrNext) {
1449 return GetPrevWordPlace(place);
1450 } else {
1451 return GetNextWordPlace(place);
1452 }
1453 }
1454 return place;
1455 }
ClearEmptySection(const CPVT_WordPlace & place)1456 FX_BOOL CPDF_VariableText::ClearEmptySection(const CPVT_WordPlace & place)
1457 {
1458 if (place.nSecIndex == 0 && m_SectionArray.GetSize() == 1) {
1459 return FALSE;
1460 }
1461 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1462 if (pSection->m_WordArray.GetSize() == 0) {
1463 delete pSection;
1464 m_SectionArray.RemoveAt(place.nSecIndex);
1465 return TRUE;
1466 }
1467 }
1468 return FALSE;
1469 }
ClearEmptySections(const CPVT_WordRange & PlaceRange)1470 void CPDF_VariableText::ClearEmptySections(const CPVT_WordRange & PlaceRange)
1471 {
1472 CPVT_WordPlace wordplace;
1473 for (FX_INT32 s = PlaceRange.EndPos.nSecIndex; s > PlaceRange.BeginPos.nSecIndex; s--) {
1474 wordplace.nSecIndex = s;
1475 ClearEmptySection(wordplace);
1476 }
1477 }
LinkLatterSection(const CPVT_WordPlace & place)1478 void CPDF_VariableText::LinkLatterSection(const CPVT_WordPlace & place)
1479 {
1480 CPVT_WordPlace oldplace = AjustLineHeader(place, TRUE);
1481 if (CSection * pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
1482 if (CSection * pSection = m_SectionArray.GetAt(oldplace.nSecIndex)) {
1483 for (FX_INT32 w = 0, sz = pNextSection->m_WordArray.GetSize(); w < sz; w++) {
1484 if (CPVT_WordInfo * pWord = pNextSection->m_WordArray.GetAt(w)) {
1485 oldplace.nWordIndex ++;
1486 pSection->AddWord(oldplace, *pWord);
1487 }
1488 }
1489 }
1490 delete pNextSection;
1491 m_SectionArray.RemoveAt(place.nSecIndex + 1);
1492 }
1493 }
ClearWords(const CPVT_WordRange & PlaceRange)1494 void CPDF_VariableText::ClearWords(const CPVT_WordRange & PlaceRange)
1495 {
1496 CPVT_WordRange NewRange;
1497 NewRange.BeginPos = AjustLineHeader(PlaceRange.BeginPos, TRUE);
1498 NewRange.EndPos = AjustLineHeader(PlaceRange.EndPos, TRUE);
1499 for (FX_INT32 s = NewRange.EndPos.nSecIndex; s >= NewRange.BeginPos.nSecIndex; s--) {
1500 if (CSection * pSection = m_SectionArray.GetAt(s)) {
1501 pSection->ClearWords(NewRange);
1502 }
1503 }
1504 }
ClearLeftWord(const CPVT_WordPlace & place)1505 CPVT_WordPlace CPDF_VariableText::ClearLeftWord(const CPVT_WordPlace & place)
1506 {
1507 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1508 CPVT_WordPlace leftplace = this->GetPrevWordPlace(place);
1509 if (leftplace != place) {
1510 if (leftplace.nSecIndex != place.nSecIndex) {
1511 if (pSection->m_WordArray.GetSize() == 0) {
1512 this->ClearEmptySection(place);
1513 } else {
1514 this->LinkLatterSection(leftplace);
1515 }
1516 } else {
1517 pSection->ClearWord(place);
1518 }
1519 }
1520 return leftplace;
1521 }
1522 return place;
1523 }
ClearRightWord(const CPVT_WordPlace & place)1524 CPVT_WordPlace CPDF_VariableText::ClearRightWord(const CPVT_WordPlace & place)
1525 {
1526 if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
1527 CPVT_WordPlace rightplace = AjustLineHeader(this->GetNextWordPlace(place), FALSE);
1528 if (rightplace != place) {
1529 if(rightplace.nSecIndex != place.nSecIndex) {
1530 LinkLatterSection(place);
1531 } else {
1532 pSection->ClearWord(rightplace);
1533 }
1534 }
1535 }
1536 return place;
1537 }
RearrangeAll()1538 void CPDF_VariableText::RearrangeAll()
1539 {
1540 Rearrange(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
1541 }
RearrangePart(const CPVT_WordRange & PlaceRange)1542 void CPDF_VariableText::RearrangePart(const CPVT_WordRange & PlaceRange)
1543 {
1544 Rearrange(PlaceRange);
1545 }
Rearrange(const CPVT_WordRange & PlaceRange)1546 CPVT_FloatRect CPDF_VariableText::Rearrange(const CPVT_WordRange & PlaceRange)
1547 {
1548 CPVT_FloatRect rcRet;
1549 if (IsValid()) {
1550 if (m_bAutoFontSize) {
1551 SetFontSize(GetAutoFontSize());
1552 rcRet = RearrangeSections(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
1553 } else {
1554 rcRet = RearrangeSections(PlaceRange);
1555 }
1556 }
1557 SetContentRect(rcRet);
1558 return rcRet;
1559 }
GetAutoFontSize()1560 FX_FLOAT CPDF_VariableText::GetAutoFontSize()
1561 {
1562 FX_INT32 nTotal = sizeof(gFontSizeSteps) / sizeof(FX_BYTE);
1563 if (IsMultiLine()) {
1564 nTotal /= 4;
1565 }
1566 if (nTotal <= 0) {
1567 return 0;
1568 }
1569 if (GetPlateWidth() <= 0) {
1570 return 0;
1571 }
1572 FX_INT32 nLeft = 0;
1573 FX_INT32 nRight = nTotal - 1;
1574 FX_INT32 nMid = nTotal / 2;
1575 while (nLeft <= nRight) {
1576 if (IsBigger(gFontSizeSteps[nMid])) {
1577 nRight = nMid - 1;
1578 nMid = (nLeft + nRight) / 2;
1579 continue;
1580 } else {
1581 nLeft = nMid + 1;
1582 nMid = (nLeft + nRight) / 2;
1583 continue;
1584 }
1585 }
1586 return (FX_FLOAT)gFontSizeSteps[nMid];
1587 }
IsBigger(FX_FLOAT fFontSize)1588 FX_BOOL CPDF_VariableText::IsBigger(FX_FLOAT fFontSize)
1589 {
1590 FX_BOOL bBigger = FALSE;
1591 CPVT_Size szTotal;
1592 for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1593 if (CSection * pSection = m_SectionArray.GetAt(s)) {
1594 CPVT_Size size = pSection->GetSectionSize(fFontSize);
1595 szTotal.x = FPDF_MAX(size.x, szTotal.x);
1596 szTotal.y += size.y;
1597 if (IsFloatBigger(szTotal.x, GetPlateWidth())
1598 || IsFloatBigger(szTotal.y, GetPlateHeight())
1599 ) {
1600 bBigger = TRUE;
1601 break;
1602 }
1603 }
1604 }
1605 return bBigger;
1606 }
RearrangeSections(const CPVT_WordRange & PlaceRange)1607 CPVT_FloatRect CPDF_VariableText::RearrangeSections(const CPVT_WordRange & PlaceRange)
1608 {
1609 CPVT_WordPlace place;
1610 FX_FLOAT fPosY = 0;
1611 FX_FLOAT fOldHeight;
1612 FX_INT32 nSSecIndex = PlaceRange.BeginPos.nSecIndex;
1613 FX_INT32 nESecIndex = PlaceRange.EndPos.nSecIndex;
1614 CPVT_FloatRect rcRet;
1615 for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
1616 place.nSecIndex = s;
1617 if (CSection * pSection = m_SectionArray.GetAt(s)) {
1618 pSection->SecPlace = place;
1619 CPVT_FloatRect rcSec = pSection->m_SecInfo.rcSection;
1620 if (s >= nSSecIndex) {
1621 if (s <= nESecIndex) {
1622 rcSec = pSection->Rearrange();
1623 rcSec.top += fPosY;
1624 rcSec.bottom += fPosY;
1625 } else {
1626 fOldHeight = pSection->m_SecInfo.rcSection.bottom - pSection->m_SecInfo.rcSection.top;
1627 rcSec.top = fPosY;
1628 rcSec.bottom = fPosY + fOldHeight;
1629 }
1630 pSection->m_SecInfo.rcSection = rcSec;
1631 pSection->ResetLinePlace();
1632 }
1633 if (s == 0) {
1634 rcRet = rcSec;
1635 } else {
1636 rcRet.left = FPDF_MIN(rcSec.left, rcRet.left);
1637 rcRet.top = FPDF_MIN(rcSec.top, rcRet.top);
1638 rcRet.right = FPDF_MAX(rcSec.right, rcRet.right);
1639 rcRet.bottom = FPDF_MAX(rcSec.bottom, rcRet.bottom);
1640 }
1641 fPosY += rcSec.Height();
1642 }
1643 }
1644 return rcRet;
1645 }
GetCharWidth(FX_INT32 nFontIndex,FX_WORD Word,FX_WORD SubWord,FX_INT32 nWordStyle)1646 FX_INT32 CPDF_VariableText::GetCharWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord, FX_INT32 nWordStyle)
1647 {
1648 if (m_pVTProvider) {
1649 if (SubWord > 0) {
1650 return m_pVTProvider->GetCharWidth(nFontIndex, SubWord, nWordStyle);
1651 } else {
1652 return m_pVTProvider->GetCharWidth(nFontIndex, Word, nWordStyle);
1653 }
1654 }
1655 return 0;
1656 }
GetTypeAscent(FX_INT32 nFontIndex)1657 FX_INT32 CPDF_VariableText::GetTypeAscent(FX_INT32 nFontIndex)
1658 {
1659 return m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
1660 }
GetTypeDescent(FX_INT32 nFontIndex)1661 FX_INT32 CPDF_VariableText::GetTypeDescent(FX_INT32 nFontIndex)
1662 {
1663 return m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
1664 }
GetWordFontIndex(FX_WORD word,FX_INT32 charset,FX_INT32 nFontIndex)1665 FX_INT32 CPDF_VariableText::GetWordFontIndex(FX_WORD word, FX_INT32 charset, FX_INT32 nFontIndex)
1666 {
1667 return m_pVTProvider ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex) : -1;
1668 }
GetDefaultFontIndex()1669 FX_INT32 CPDF_VariableText::GetDefaultFontIndex()
1670 {
1671 return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
1672 }
IsLatinWord(FX_WORD word)1673 FX_BOOL CPDF_VariableText::IsLatinWord(FX_WORD word)
1674 {
1675 return m_pVTProvider ? m_pVTProvider->IsLatinWord(word) : FALSE;
1676 }
GetIterator()1677 IPDF_VariableText_Iterator * CPDF_VariableText::GetIterator()
1678 {
1679 if (!m_pVTIterator) {
1680 return m_pVTIterator = FX_NEW CPDF_VariableText_Iterator(this);
1681 }
1682 return m_pVTIterator;
1683 }
SetProvider(IPDF_VariableText_Provider * pProvider)1684 IPDF_VariableText_Provider* CPDF_VariableText::SetProvider(IPDF_VariableText_Provider * pProvider)
1685 {
1686 IPDF_VariableText_Provider* pOld = m_pVTProvider;
1687 m_pVTProvider = pProvider;
1688 return pOld;
1689 }
CPDF_VariableText_Iterator(CPDF_VariableText * pVT)1690 CPDF_VariableText_Iterator::CPDF_VariableText_Iterator(CPDF_VariableText * pVT):
1691 m_pVT(pVT),
1692 m_CurPos(-1, -1, -1)
1693 {
1694 }
~CPDF_VariableText_Iterator()1695 CPDF_VariableText_Iterator::~CPDF_VariableText_Iterator()
1696 {
1697 }
SetAt(FX_INT32 nWordIndex)1698 void CPDF_VariableText_Iterator::SetAt(FX_INT32 nWordIndex)
1699 {
1700 ASSERT(m_pVT != NULL);
1701 m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
1702 }
SetAt(const CPVT_WordPlace & place)1703 void CPDF_VariableText_Iterator::SetAt(const CPVT_WordPlace & place)
1704 {
1705 ASSERT(m_pVT != NULL);
1706 m_CurPos = place;
1707 }
NextWord()1708 FX_BOOL CPDF_VariableText_Iterator::NextWord()
1709 {
1710 ASSERT(m_pVT != NULL);
1711 if (m_CurPos == m_pVT->GetEndWordPlace()) {
1712 return FALSE;
1713 }
1714 m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);
1715 return TRUE;
1716 }
PrevWord()1717 FX_BOOL CPDF_VariableText_Iterator::PrevWord()
1718 {
1719 ASSERT(m_pVT != NULL);
1720 if (m_CurPos == m_pVT->GetBeginWordPlace()) {
1721 return FALSE;
1722 }
1723 m_CurPos = m_pVT->GetPrevWordPlace(m_CurPos);
1724 return TRUE;
1725 }
NextLine()1726 FX_BOOL CPDF_VariableText_Iterator::NextLine()
1727 {
1728 ASSERT(m_pVT != NULL);
1729 if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1730 if (m_CurPos.nLineIndex < pSection->m_LineArray.GetSize() - 1) {
1731 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1);
1732 return TRUE;
1733 } else {
1734 if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
1735 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
1736 return TRUE;
1737 }
1738 }
1739 }
1740 return FALSE;
1741 }
PrevLine()1742 FX_BOOL CPDF_VariableText_Iterator::PrevLine()
1743 {
1744 ASSERT(m_pVT != NULL);
1745 if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1746 if (m_CurPos.nLineIndex > 0) {
1747 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex - 1, -1);
1748 return TRUE;
1749 } else {
1750 if (m_CurPos.nSecIndex > 0) {
1751 if (CSection * pLastSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex - 1)) {
1752 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, pLastSection->m_LineArray.GetSize() - 1, -1);
1753 return TRUE;
1754 }
1755 }
1756 }
1757 }
1758 return FALSE;
1759 }
NextSection()1760 FX_BOOL CPDF_VariableText_Iterator::NextSection()
1761 {
1762 ASSERT(m_pVT != NULL);
1763 if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
1764 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
1765 return TRUE;
1766 }
1767 return FALSE;
1768 }
PrevSection()1769 FX_BOOL CPDF_VariableText_Iterator::PrevSection()
1770 {
1771 ASSERT(m_pVT != NULL);
1772 if (m_CurPos.nSecIndex > 0) {
1773 m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, 0, -1);
1774 return TRUE;
1775 }
1776 return FALSE;
1777 }
GetWord(CPVT_Word & word) const1778 FX_BOOL CPDF_VariableText_Iterator::GetWord(CPVT_Word & word) const
1779 {
1780 ASSERT(m_pVT != NULL);
1781 word.WordPlace = m_CurPos;
1782 if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1783 if (CLine * pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1784 if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1785 word.Word = pWord->Word;
1786 word.nCharset = pWord->nCharset;
1787 word.fWidth = m_pVT->GetWordWidth(*pWord);
1788 word.ptWord = m_pVT->InToOut(
1789 CPDF_Point(pWord->fWordX + pSection->m_SecInfo.rcSection.left,
1790 pWord->fWordY + pSection->m_SecInfo.rcSection.top) );
1791 word.fAscent = m_pVT->GetWordAscent(*pWord);
1792 word.fDescent = m_pVT->GetWordDescent(*pWord);
1793 if (pWord->pWordProps) {
1794 word.WordProps = *pWord->pWordProps;
1795 }
1796 word.nFontIndex = m_pVT->GetWordFontIndex(*pWord);
1797 word.fFontSize = m_pVT->GetWordFontSize(*pWord);
1798 return TRUE;
1799 }
1800 }
1801 }
1802 return FALSE;
1803 }
SetWord(const CPVT_Word & word)1804 FX_BOOL CPDF_VariableText_Iterator::SetWord(const CPVT_Word & word)
1805 {
1806 ASSERT(m_pVT != NULL);
1807 if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1808 if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
1809 if (pWord->pWordProps) {
1810 *pWord->pWordProps = word.WordProps;
1811 }
1812 return TRUE;
1813 }
1814 }
1815 return FALSE;
1816 }
GetLine(CPVT_Line & line) const1817 FX_BOOL CPDF_VariableText_Iterator::GetLine(CPVT_Line & line) const
1818 {
1819 ASSERT(m_pVT != NULL);
1820 line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1);
1821 if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1822 if (CLine * pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
1823 line.ptLine = m_pVT->InToOut(
1824 CPDF_Point(pLine->m_LineInfo.fLineX + pSection->m_SecInfo.rcSection.left,
1825 pLine->m_LineInfo.fLineY + pSection->m_SecInfo.rcSection.top) );
1826 line.fLineWidth = pLine->m_LineInfo.fLineWidth;
1827 line.fLineAscent = pLine->m_LineInfo.fLineAscent;
1828 line.fLineDescent = pLine->m_LineInfo.fLineDescent;
1829 line.lineEnd = pLine->GetEndWordPlace();
1830 return TRUE;
1831 }
1832 }
1833 return FALSE;
1834 }
GetSection(CPVT_Section & section) const1835 FX_BOOL CPDF_VariableText_Iterator::GetSection(CPVT_Section & section) const
1836 {
1837 ASSERT(m_pVT != NULL);
1838 section.secplace = CPVT_WordPlace(m_CurPos.nSecIndex, 0, -1);
1839 if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1840 section.rcSection = m_pVT->InToOut(pSection->m_SecInfo.rcSection);
1841 if (pSection->m_SecInfo.pSecProps) {
1842 section.SecProps = *pSection->m_SecInfo.pSecProps;
1843 }
1844 if (pSection->m_SecInfo.pWordProps) {
1845 section.WordProps = *pSection->m_SecInfo.pWordProps;
1846 }
1847 return TRUE;
1848 }
1849 return FALSE;
1850 }
SetSection(const CPVT_Section & section)1851 FX_BOOL CPDF_VariableText_Iterator::SetSection(const CPVT_Section & section)
1852 {
1853 ASSERT(m_pVT != NULL);
1854 if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
1855 if (pSection->m_SecInfo.pSecProps) {
1856 *pSection->m_SecInfo.pSecProps = section.SecProps;
1857 }
1858 if (pSection->m_SecInfo.pWordProps) {
1859 *pSection->m_SecInfo.pWordProps = section.WordProps;
1860 }
1861 return TRUE;
1862 }
1863 return FALSE;
1864 }
1865