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